G4iSLt.G4iSLT_termination_measure_And

Require Import List.
Export ListNotations.
Require Import PeanoNat.
Require Import Lia.
Require Import Wellfounded.

Require Import general_export.

Require Import G4iSLT_calc.
Require Import G4iSLT_remove_list.
Require Import G4iSLT_list_lems.
Require Import G4iSLT_dec.
Require Import G4iSLT_termination_measure.
Require Import G4iSLT_termination_measure_prelims.
Require Import DLW_WO_list_nat.

(* AndR rule *)

Lemma AndR_le_counter : prem1 prem2 concl, AndRRule [; ] concl
                (less_than lt (seq_list_occ_weight ) (seq_list_occ_weight concl)) *
                (less_than lt (seq_list_occ_weight ) (seq_list_occ_weight concl)).
Proof.
intros. inversion H. subst. simpl. unfold seq_list_occ_weight ; simpl.
destruct (max_weight_list (unBoxed_list Γ [A])). simpl. destruct p.
destruct (max_weight_list (unBoxed_list Γ [A B])). simpl. destruct p.
assert (x ). apply . intros. apply InT_app_or in . destruct . apply ; apply InT_or_app ; auto.
inversion i ; subst. assert (InT ( B) (unBoxed_list Γ [ B])). apply InT_or_app ; right ; apply InT_eq.
apply in . simpl in . lia. inversion .
split.
- destruct .
  * apply less_than_eq. epose (list_occ_weight_list_swap (unBoxed_list Γ) [A] [] x).
    simpl in e. repeat rewrite app_nil_end in e. repeat rewrite app_assoc in e. rewrite e. clear e.
    epose (list_occ_weight_list_swap (unBoxed_list Γ) [A B] [] x).
    simpl in e. repeat rewrite app_nil_end in e. repeat rewrite app_assoc in e. rewrite e. clear e.
    epose (list_occ_weight_list_headlist [A] [A B] _ x). simpl in . apply . clear .
    apply list_occ_weight_list_relevant.
    destruct (max_weight_list [A]). simpl. destruct p. assert ( x).
    apply . intros. apply l. apply InT_or_app ; auto.
    destruct (max_weight_list [A B]). simpl. destruct p. assert ( x).
    apply . intros. apply . apply InT_or_app ; auto. lia.
    destruct (max_weight_list [A]). simpl. destruct p.
    destruct (max_weight_list [A B]). simpl. destruct p. assert ( ).
    apply . intros. inversion ; subst. assert (InT ( B) [ B]). apply InT_eq.
    apply in . simpl in . lia. inversion .
    apply less_than_lt. inversion ; subst.
    exfalso. assert (weight_form (A B) weight_form A).
    assert (weight_form (A B) ). apply . apply InT_eq.
    assert ( weight_form A). apply . intros. inversion ; subst ; auto. inversion .
    lia. simpl in . lia. repeat rewrite length_max ; lia.
  * apply less_than_lt. repeat rewrite length_max ; lia.
- destruct (max_weight_list (unBoxed_list Γ [B])). simpl. destruct p.
  assert ( ). apply . intros. apply InT_app_or in . destruct . apply ; apply InT_or_app ; auto.
  inversion i ; subst. assert (InT (A ) (unBoxed_list Γ [A ])). apply InT_or_app ; right ; apply InT_eq.
  apply in . simpl in ; lia. inversion .
 destruct .
  * apply less_than_eq. epose (list_occ_weight_list_swap (unBoxed_list Γ) [B] [] ).
    simpl in e. repeat rewrite app_nil_end in e. repeat rewrite app_assoc in e. rewrite e. clear e.
    epose (list_occ_weight_list_swap (unBoxed_list Γ) [A B] [] ).
    simpl in e. repeat rewrite app_nil_end in e. repeat rewrite app_assoc in e. rewrite e. clear e.
    epose (list_occ_weight_list_headlist [B] [A B] _ ). simpl in . apply . clear .
    apply list_occ_weight_list_relevant.
    destruct (max_weight_list [B]). simpl. destruct p. assert ( ).
    apply . intros. apply . apply InT_or_app ; auto.
    destruct (max_weight_list [A B]). simpl. destruct p. assert ( ).
    apply . intros. apply . apply InT_or_app ; auto. lia.
    destruct (max_weight_list [B]). simpl. destruct p.
    destruct (max_weight_list [A B]). simpl. destruct p. assert ( ).
    apply . intros. inversion ; subst. assert (InT (A ) [A ]). apply InT_eq.
    apply in . simpl in . lia. inversion .
    apply less_than_lt. inversion ; subst.
    exfalso. assert (weight_form (A B) weight_form B).
    assert (weight_form (A B) ). apply . apply InT_eq.
    assert ( weight_form B). apply . intros. inversion ; subst ; auto. inversion .
    lia. simpl in . lia. repeat rewrite length_max ; lia.
  * apply less_than_lt. repeat rewrite length_max ; lia.
Qed.


Theorem AndR_less_thanS : prem1 prem2 concl, AndRRule [;] concl
                                                          ( << concl) * ( << concl).
Proof.
intros. split.
- unfold less_thanS. pose (AndR_le_counter _ _ _ H). destruct p ; auto.
- unfold less_thanS. pose (AndR_le_counter _ _ _ H). destruct p ; auto.
Qed.


(*------------------------------------------------------------------------------------------------------------------------------------------*)

(* AndL rule *)

Lemma AndL_le_counter : prem concl, AndLRule [prem] concl less_than lt (seq_list_occ_weight prem) (seq_list_occ_weight concl).
Proof.
intros. inversion H. subst. simpl. unfold seq_list_occ_weight ; simpl. repeat rewrite unBox_app_distrib ; simpl.
repeat rewrite app_assoc ; simpl.
destruct (max_weight_list (unBoxed_list Γ0 unBox_formula A :: unBox_formula B :: unBoxed_list Γ1 [C])). simpl. destruct p.
destruct (max_weight_list (unBoxed_list Γ0 A B :: unBoxed_list Γ1 [C])). simpl. destruct p.
assert (x ). apply . intros. apply InT_app_or in ; destruct . apply ; apply InT_or_app ; auto.
inversion i ; subst. assert (weight_form (A B) ). apply . apply InT_or_app ; right ; apply InT_eq.
simpl in . destruct A ; simpl ; simpl in ; lia. inversion ; subst. assert (weight_form (A B) ).
apply . apply InT_or_app ; right ; apply InT_eq. simpl in . destruct B ; simpl ; simpl in ; lia.
apply . apply InT_or_app ; right ; apply InT_cons ; auto.
inversion ; subst. 2: apply less_than_lt ; repeat rewrite length_max ; lia.
epose (list_occ_weight_list_swap (unBoxed_list Γ0) (unBox_formula A :: [unBox_formula B]) _ ).
simpl in e. rewrite e. clear e.
epose (list_occ_weight_list_swap (unBoxed_list Γ0) [A B] _ ).
simpl in e. rewrite e. clear e. apply less_than_eq.
epose (list_occ_weight_list_headlist (unBox_formula A :: [unBox_formula B]) [A B] _ ). simpl in .
repeat rewrite app_assoc in . apply . clear . apply list_occ_weight_list_relevant.
destruct (max_weight_list [unBox_formula A; unBox_formula B]). simpl. destruct p. assert (x ).
apply . intros. apply l. apply InT_or_app ; right. inversion ; subst. apply InT_eq. apply InT_cons.
inversion ; subst. apply InT_eq. inversion .
destruct (max_weight_list [A B]). simpl. destruct p. assert ( ).
apply . intros. apply . apply InT_or_app ; right. inversion ; subst. apply InT_eq. inversion . lia.
destruct (max_weight_list [unBox_formula A; unBox_formula B]). simpl. destruct p.
destruct (max_weight_list [A B]). simpl. destruct p. assert (x ).
apply . intros. assert (InT (A B) [A B]). apply InT_eq. apply in . simpl in .
inversion ; subst. destruct A ; simpl in ; simpl ; lia.
inversion ; subst. destruct B ; simpl in ; simpl ; lia. inversion .
apply less_than_lt. inversion ; subst. 2: repeat rewrite length_max ; lia.
exfalso. assert (weight_form (A B) Nat.max (weight_form B) (weight_form A)).
assert (weight_form (A B) ). apply . apply InT_eq.
assert ( Nat.max (weight_form B) (weight_form A)). apply . intros.
inversion ; subst ; try lia. destruct A ; simpl ; lia. inversion ; subst.
rewrite Nat.max_comm. destruct B ; simpl ; lia. inversion . lia. simpl in ; lia.
Qed.


Theorem AndL_less_thanS : prem concl, AndLRule [prem] concl
                                                          (prem << concl).
Proof.
intros. unfold less_thanS. pose (AndL_le_counter _ _ H) ; auto.
Qed.