Inductive t (A : Type) :=
| C0 : t A
| C1 : A -> t A
| C2 : A -> nat -> t A
.


(* Copyright (c) 2012-2017, Coq-std++ developers. *)
(* This file is distributed under the terms of the BSD license. *)
(** This file implements bsets as functions into Prop. *)
From stdpp Require Export prelude.
Set Default Proof Using "Type".

Record bset (A : Type) : Type := mkBSet { bset_car : A → bool }.
Arguments mkBSet {_} _ : assert.
Arguments bset_car {_} _ _ : assert.

Instance bset_top {A} : Top (bset A) := mkBSet (λ _, true).
Instance bset_empty {A} : Empty (bset A) := mkBSet (λ _, false).
Instance bset_singleton `{EqDecision A} : Singleton A (bset A) := λ x,
  mkBSet (λ y, bool_decide (y = x)).
Instance bset_elem_of {A} : ElemOf A (bset A) := λ x X, bset_car X x.
Instance bset_union {A} : Union (bset A) := λ X1 X2,
  mkBSet (λ x, bset_car X1 x || bset_car X2 x).
Instance bset_intersection {A} : Intersection (bset A) := λ X1 X2,
  mkBSet (λ x, bset_car X1 x && bset_car X2 x).
Instance bset_difference {A} : Difference (bset A) := λ X1 X2,
  mkBSet (λ x, bset_car X1 x && negb (bset_car X2 x)).
Instance bset_collection `{EqDecision A} : Collection A (bset A).
Proof.
  split; [split| |].
  - by intros x ?.
  - by intros x y; rewrite <-(bool_decide_spec (x = y)).
  - split. apply orb_prop_elim. apply orb_prop_intro.
  - split. apply andb_prop_elim. apply andb_prop_intro.
  - intros X Y x; unfold elem_of, bset_elem_of; simpl.
    destruct (bset_car X x), (bset_car Y x); simpl; tauto.
Qed.
Instance bset_elem_of_dec {A} : RelDecision (@elem_of _ (bset A) _).
Proof. refine (λ x X, cast_if (decide (bset_car X x))); done. Defined.

Typeclasses Opaque bset_elem_of.
Global Opaque bset_empty bset_singleton bset_union
  bset_intersection bset_difference.


Require Export Iron.Language.SystemF2Data.Type.
Require Export Iron.Language.SystemF2Data.Exp.Lit.
Require Export Iron.Language.SystemF2Data.Exp.Prim.

(********************************************************************)
(* Expressions *)
Inductive exp : Type :=
 (* Variables *)
 | XVar   : nat -> exp

 (* Type abstraction *)
 | XLAM   : exp -> exp

 (* Type application. *)
 | XAPP   : exp -> ty  -> exp

 (* Function abstraction. *)
 | XLam   : ty  -> exp -> exp

 (* Function application. *)
 | XApp   : exp -> exp -> exp

 (* Saturated data constructors. *)
 | XCon   : datacon  -> list ty  -> list exp -> exp

 (* Case expressions. *)
 | XCase  : exp      -> list alt -> exp

 (* Saturated primitive operators. *)
 | XPrim  : prim     -> list exp -> exp

 (* Primitive literals. *)
 | XLit   : lit      -> exp

 (* Alternatives *)
with alt     : Type :=
 | AAlt   : datacon -> exp -> alt.

Hint Constructors exp.
Hint Constructors alt.

(********************************************************************)
(* Mutual induction principle for expressions.
   As expressions are indirectly mutually recursive with lists,
   Coq's Combined scheme command won't make us a strong enough
   induction principle, so we need to write it out by hand. *)
Theorem exp_mutind
 : forall
    (PX : exp -> Prop)
    (PA : alt -> Prop)
 ,  (forall n,                                PX (XVar n))
 -> (forall x1,      PX x1                 -> PX (XLAM x1))
 -> (forall x1 t2,   PX x1                 -> PX (XAPP x1 t2))
 -> (forall t  x1,   PX x1                 -> PX (XLam t x1))
 -> (forall x1 x2,   PX x1 -> PX x2        -> PX (XApp x1 x2))
 -> (forall dc ts xs,         Forall PX xs -> PX (XCon dc ts xs))
 -> (forall x  aa,   PX x  -> Forall PA aa -> PX (XCase x aa))
 -> (forall p xs,    Forall PX xs          -> PX (XPrim p xs))
 -> (forall l,                                PX (XLit  l))
 -> (forall dc x,    PX x                  -> PA (AAlt dc x))
 ->  forall x, PX x.
Proof.
 intros PX PA.
 intros var tlam tapp lam app con case prim lit alt.
 refine (fix  IHX x : PX x := _
         with IHA a : PA a := _
         for  IHX).

 - case x; intros.
   + apply var.
   + apply tlam. apply IHX.
   + apply tapp. apply IHX.
   + apply lam.  apply IHX.
   + apply app.  apply IHX. apply IHX.
   + apply con.  induction l0; intuition.
   + apply case. apply IHX. induction l; intuition.
   + apply prim. induction l;  intuition.
   + apply lit.

 - case a; intros.
   + apply alt.  apply IHX.
Qed.


Require Import Coq.Strings.String.
Require Import Coq.Init.Datatypes.
Require Import Coq.Arith.EqNat.
Require Import List.
Import ListNotations.
Open Scope list_scope.
Require Import Core.

Definition isSingle (rule: nt * sf) :=
  match rule with
  | (_,[inr _]) => true
  | _ => false
  end.

Definition getNewText (elem: t): string :=
  match elem with
  | T s => "New_" ++ s
  end.

Definition renameElem1 (elem: nt + t) : ((nt + t)) :=
  match elem with
  | inr t => inl (NT ( getNewText t ) )
  | inl _ => elem
  end.
Definition renameElem2 (elem: nt + t) : ((list (nt *sf))) :=
  match elem with
  | inr t => (  [ ( NT ( getNewText t ), [ elem ] ) ] )
  | inl _ => ( [] )
  end.

Definition renameRule (rule: nt * sf) : ( list (nt * sf) ) :=
	match rule with
	| (l,r) => (l, map renameElem1 (snd rule)) :: flat_map renameElem2 (snd rule)
  end.

Definition normalizeRule (rule: nt * sf) : ( list (nt * sf) ) :=
  if isSingle rule then [rule] else renameRule rule.

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

Example example_1:
  forall left nt0,
  renameRule (left,[inl nt0]) = [(left,[inl nt0])].
Proof.
  intros. unfold renameRule. simpl. reflexivity. Qed.

Example example_2:
  forall left,
  renameRule (left,[]) = [(left,[])].
Proof.
  intros. unfold renameRule. simpl. reflexivity. Qed.

Example example_3:
  forall rule,
  isSingle rule = true ->
  normalizeRule rule = [rule].
Proof.
  intros. unfold normalizeRule. destruct isSingle. reflexivity. inversion H. Qed.

Example example_4:
  forall left t0,
  normalizeRule (left,[inr t0]) = [(left,[inr t0])].
Proof.  intros. reflexivity. Qed.

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

Lemma concat_in_lemma:
  forall (A: Type) (x: A) (l1: list A) (l2: list A),
  In x (l1 ++ l2) <-> In x l1 \/ In x l2.
Proof.
  intros. induction l1.
  - simpl. split.
    + intros. right. assumption.
    + intros. destruct H. inversion H. assumption.
  - simpl. split.
    + intros. destruct H.
      * left. left. assumption.
      *  apply IHl1 in H. destruct H. left. right. assumption. right. assumption.
    + intros. destruct H.
      * destruct H. left. assumption. right. apply IHl1. left. assumption.
      * right. apply IHl1. right. assumption.
Qed.

Lemma flat_map_lemma_1:
  forall (A:Type) (f: A -> list A) (x:A) (xs: list A),
    f x = [x] ->
    In x xs ->
    In x (flat_map f xs).
Proof.
  intros. induction xs.
    + inversion H0.
    + simpl. apply concat_in_lemma. assert (a :: xs = [a] ++ xs). simpl. reflexivity. rewrite H1 in H0.
      apply concat_in_lemma in H0.
      destruct H0.
      * inversion H0. subst. left. rewrite H. assumption. simpl. inversion H2.
      * right. apply IHxs. assumption.
Qed.

Lemma flat_map_lemma_2:
  forall (A:Type) (f: A -> list A) (x:A) (xs: list A),
    f x = [x] ->
    (forall x', In x (f x') -> x = x') ->
    In x (flat_map f xs) ->
    In x xs.
Proof.
  intros. induction xs.
  - inversion H1.
  - simpl in H1. apply concat_in_lemma in H1. destruct H1.
    + apply H0 in H1. subst. simpl. left. reflexivity.
    + simpl. right. apply IHxs. assumption.
Qed.

Lemma flat_map_lemma_3:
  forall (A B: Type) (f: A -> list B) (x: A) (y: B) (xs: list A),
    In x xs -> In y (f x) -> In y (flat_map f xs).
Proof.
  intros. induction xs.
  - inversion H.
  - simpl. destruct H.
    + apply concat_in_lemma. left. subst. assumption.
    + apply concat_in_lemma. right. apply IHxs. apply H.
Qed.

Lemma arrow_disj_lemma: forall (A B C: Prop),
  ((A \/ B) -> C) ->
  (A -> C) /\ (B -> C).
Proof. intros. split; auto. Qed.

Lemma destr_isSingle_lemma:
  forall x, { isSingle x = true } + { isSingle x = false}.
Proof.
  intros. destruct x. destruct s; auto. destruct s; auto. destruct s0; auto. Qed.

Lemma custom_ass_1: forall (A:Type) (c1 c2: A) (s1 s2: list A),
(s1 ++ [c1]) ++ [c2] ++ s2 = s1 ++ [c1; c2] ++ s2 .
Proof. intros. simpl. rewrite <- app_assoc with (l := s1) (m := [c1]) (n := c2 :: s2). reflexivity. Qed.

Lemma custom_ass_2: forall (A:Type) (c1 c2: A) (s1 s2: list A),
s1 ++ [c1] ++ [c2] ++ s2 = (s1 ++ [c1; c2] ++ s2) .
Proof. intros. simpl. reflexivity. Qed.

Lemma custom_ass_3: forall (A:Type) (c1 c2: A) (s1 s2: list A),
(s1 ++ [c1]) ++ c2 :: s2 = s1 ++ [c1; c2] ++ s2.
Proof. intros. simpl. apply custom_ass_1. Qed.

Lemma map_length:
  forall (A B:Type) (f: A -> B) (xs: list A) (ys: list B),
  map f xs = ys -> length xs = length ys.
Proof.
  debug auto.
  intros. generalize dependent ys.
  induction xs; intros; inversion H; simpl in *; auto. Qed.

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

Lemma invar_eps_lemma:
  forall left,
  normalizeRule (left,[]) = [(left,[])].
Proof. intros. reflexivity. Qed.

Lemma invar_single_lemma:
  forall left single,
  normalizeRule (left,[single]) = [(left,[single])].
Proof.
  intros. destruct single. reflexivity. reflexivity. Qed.

Lemma invar_2nonterm_lemma:
  forall left n0 n1,
  normalizeRule (left, [inl n0; inl n1]) = [(left, [inl n0; inl n1])].
Proof. intros. reflexivity. Qed.

Lemma h_integr_eps:
  forall left rule,
    In (left, []) (renameRule rule) -> rule = (left,[]).
Proof.
  intros. destruct rule. destruct s.
  - simpl in H. destruct H. assumption. inversion H.
  - simpl in H. destruct H.
    + inversion H.
    + apply concat_in_lemma in H. destruct H.
      * destruct s.
        -- simpl in H. inversion H.
        -- simpl in H. destruct H. inversion H. inversion H.
      * induction s0. simpl in H. inversion H. destruct a.
        -- simpl in H. apply IHs0 in H. inversion H.
        -- simpl in H. destruct H. inversion H. apply IHs0 in H. inversion H.
Qed.

Lemma integr_eps_lemma:
  forall left rule,
    In (left, []) (normalizeRule rule) -> (left, []) = rule.
Proof.
  intros.
  unfold normalizeRule in H. destruct isSingle in H.
  - inversion H. auto. inversion H0.
  - destruct rule. apply h_integr_eps in H. inversion H. reflexivity.
Qed.

Lemma hh_integr_nt_sinle:
  forall left nt0 elems,
  ~ In (left, [inl nt0]) (flat_map renameElem2 elems).
Proof.
  intros left nt0 elems contra. induction elems.
  - inversion contra.
  - simpl in contra. apply concat_in_lemma in contra. destruct contra.
    + destruct a.  inversion H. inversion H. inversion H0. inversion H0.
    + apply IHelems in H. inversion H.
Qed.

Lemma h_integr_nt_sinle:
  forall left nt0 rule,
    In (left,[inl nt0]) (renameRule rule) -> isSingle rule = false -> (left,[inl nt0]) = rule.
Proof.
  intros. destruct rule. destruct H.
  - inversion H. subst.
      destruct s. inversion H3.
      destruct s0. destruct s. simpl. reflexivity. inversion H3. inversion H0. inversion H3.
  - apply hh_integr_nt_sinle in H. inversion H.
Qed.

Lemma integr_nt_sinle_lemma :
  forall left nt0 x,
    In (left,[inl nt0]) (normalizeRule x) -> (left,[inl nt0]) = x.
Proof.
  intros. unfold normalizeRule in H. edestruct destr_isSingle_lemma; rewrite e in H.
  - inversion H. auto. inversion H0.
  - apply h_integr_nt_sinle. assumption. assumption. Qed.

Lemma hh_integr_t_sinle:
  forall name t0 elems,
  (forall s, name <> append "New_" s) ->
  ~ In (NT name, [inr t0]) (flat_map renameElem2 elems).
Proof.
  intros t0 s0 elems KN contra.
  induction elems.
  - inversion contra.
  - simpl in contra. apply concat_in_lemma in contra. destruct contra.
    + destruct a.
      * inversion H.
      * inversion H. inversion H0. destruct t. simpl in H2. unfold not in KN. symmetry in H2.
        apply KN in H2. inversion H2. simpl in KN. inversion H0.
    + apply IHelems in H. inversion H.
Qed.

Lemma h_integr_t_sinle:
  forall (left:nt) (t0:t) (elems: list (nt + t)),
  (forall s, left <> NT ("New_" ++ s)) ->
  ~ In (left, [inr t0]) (flat_map renameElem2 elems).
Proof.
  intros.
  destruct left. apply hh_integr_t_sinle. unfold not in *. intros.
  assert (H' := H). apply H with (s0 := s0). subst. reflexivity.
Qed.

Lemma integr_t_sinle_lemma :
  forall left t0 x,
    (forall s, left <> NT ("New_" ++ s)) ->
    In (left,[inr t0]) (normalizeRule x) -> (left,[inr t0]) = x.
Proof.
  intros. unfold normalizeRule in H0. destruct isSingle.
  - inversion H0. auto. inversion H1.
  - intros. destruct x. destruct H0.
    + inversion H0. subst.
        destruct s. inversion H3.
        destruct s0. destruct s. simpl. reflexivity. inversion H3. inversion H0.
    + simpl in H0. apply h_integr_t_sinle in H0. inversion H0. assumption. Qed.

Lemma integr_sinlge_lemma :
  forall left single rule,
    (forall s, left <> NT ("New_" ++ s)) ->
    In (left, [single]) (normalizeRule rule) ->
    (left, [single]) = rule.
Proof.
  intros.
  destruct single.
    apply integr_nt_sinle_lemma. assumption.
    apply integr_t_sinle_lemma. assumption. assumption.
Qed.

Lemma h_integr_nt_nt:
  forall rule elems,
    length (snd rule) >= 2 -> ~ In rule (flat_map renameElem2 elems).
Proof.
  unfold not. intros.
  destruct rule. simpl in H.
  induction elems.
  - inversion H0.
  - simpl in H0. apply concat_in_lemma in H0. destruct H0.
    + destruct a.
      * inversion H0.
      * simpl in H0. destruct H0.
        -- inversion H0. subst. inversion H. inversion H2.
        -- inversion H0.
    + apply IHelems in H0. inversion H0. Qed.

Lemma integr_nt_nt_lemma:
  forall left n0 n1 rule,
    (forall s, left <> NT ("New_" ++ s)) ->
    (forall s, n0 <> NT ("New_" ++ s)) ->
    (forall s, n1 <> NT ("New_" ++ s)) ->
    In (left, [inl n0; inl n1]) (normalizeRule rule) ->
    (left, [inl n0; inl n1]) = rule.
Proof.
  intros left n0 n1 rule NL N0 N1 H.
  unfold normalizeRule in H. destruct isSingle.
  - destruct H. auto. inversion H.
  - destruct rule. simpl in H. destruct H.
    + inversion H.
      destruct s. inversion_clear H.
      destruct s0. inversion_clear H.
      destruct s1. inversion H2.
        destruct s; destruct s0.
        * simpl. reflexivity.
        * simpl in H4. inversion H4. symmetry in H5. destruct t. simpl in H5. apply N1 in H5. inversion H5.
        * simpl in H3. inversion H3. symmetry in H5. destruct t. simpl in H5. apply N0 in H5. inversion H5.
        * simpl in H3. inversion H3. symmetry in H5. destruct t. simpl in H5. apply N0 in H5. inversion H5.
        * inversion H2.
    + apply h_integr_nt_nt in H. inversion H. simpl. auto. Qed.

Definition renameTerms (g: cfg) := {|
  start_symbol := start_symbol g;
  rules := flat_map normalizeRule (rules g)
|}.

Definition short_rules (g: cfg) :=
  forall left right,
    In (left, right) (rules g) -> length right <= 2.

Lemma Alg_prop_1:
  forall g left,
  In (left, []) (rules g) <->
  In (left, []) (rules (renameTerms g)).
Proof.
  intros. split.
  - apply flat_map_lemma_1. reflexivity.
  - apply flat_map_lemma_2. reflexivity. apply integr_eps_lemma. Qed.

Lemma Alg_prop_2:
  forall g left r_single,
  (forall s, left <> NT ("New_" ++ s)) ->
  In (left, [r_single]) (rules g) <->
  In (left, [r_single]) (rules (renameTerms g)).
Proof.
  intros. split.
  - apply flat_map_lemma_1. apply invar_single_lemma.
  - apply flat_map_lemma_2.
    + apply invar_single_lemma.
    + intros. apply integr_sinlge_lemma. assumption. assumption. Qed.

Lemma Alg_prop_3:
  forall g left n0 n1,
    (forall s, left <> NT ("New_" ++ s)) ->
    (forall s, n0 <> NT ("New_" ++ s)) ->
    (forall s, n1 <> NT ("New_" ++ s)) ->
    In (left, [inl n0; inl n1]) (rules g) <->
    In (left, [inl n0; inl n1]) (rules (renameTerms g)).
Proof.
  intros. split.
  - apply flat_map_lemma_1. apply invar_2nonterm_lemma.
  - apply flat_map_lemma_2.
    + apply invar_2nonterm_lemma.
    + intros. apply integr_nt_nt_lemma; assumption.
  Qed.

Lemma Alg_prop_4:
  forall g left n s0,
    In (left, [inl n; inr (T s0)]) (rules g) ->
    In (left, [inl n; inl (NT ("New_" ++ s0))]) (rules (renameTerms g)) /\ In (NT ("New_" ++ s0), [inr (T s0)]) (rules (renameTerms g)).
Proof.
  intros. split.
  - apply flat_map_lemma_3 with (x := (left, [inl n; inr (T s0)])). assumption. simpl. eauto.
  - apply flat_map_lemma_3 with (x := (left, [inl n; inr (T s0)])). assumption. simpl. eauto.
Qed.

Lemma Alg_prop_5:
  forall g left n s0,
    In (left, [inr (T s0); inl n]) (rules g) ->
    In (left, [inl (NT ("New_" ++ s0)); inl n]) (rules (renameTerms g)) /\ In (NT ("New_" ++ s0), [inr (T s0)]) (rules (renameTerms g)).
Proof.
  intros. split.
  - apply flat_map_lemma_3 with (x := (left, [inr (T s0); inl n])). assumption. simpl. eauto.
  - apply flat_map_lemma_3 with (x := (left, [inr (T s0); inl n])). assumption. simpl. eauto.
Qed.

Lemma Alg_prop_6:
  forall g left s0 s1,
  In (left, [inr (T s0); inr (T s1)]) (rules g) ->
  In (left, [inl (NT ("New_" ++ s0)); inl (NT ("New_" ++ s1))]) (rules (renameTerms g))
  /\ In (NT ("New_" ++ s0), [inr (T s0)]) (rules (renameTerms g))
  /\ In (NT ("New_" ++ s1), [inr (T s1)]) (rules (renameTerms g)).
Proof.
  intros. split;[|split].
  - apply flat_map_lemma_3 with (x := (left, [inr (T s0); inr (T s1)])). assumption. simpl. eauto.
  - apply flat_map_lemma_3 with (x := (left, [inr (T s0); inr (T s1)])). assumption. simpl. eauto.
  - apply flat_map_lemma_3 with (x := (left, [inr (T s0); inr (T s1)])). assumption. simpl. eauto.
Qed.

(* -------------------------------------------------------------------------------- *)
(* -------------------- Ctrl+C Ctrl+V lemma --------------------------------------- *)
(* -------------------------------------------------------------------------------- *)

Lemma renameRule_progress_1_lemma:
  forall left n0 t0 rule,
    ~(In (left, [inl n0; inr t0]) (normalizeRule rule)).
Proof.
  intros left n0 t0 rule contr. destruct rule.
  unfold normalizeRule in contr.
  destruct destr_isSingle_lemma with (x := (n,s)); rewrite e in contr.
  + inversion contr. inversion H. subst. simpl in e. congruence. inversion H.
  + clear e. unfold renameRule in contr. destruct contr; simpl in H.
    - inversion H. clear H H1. assert (H' := H2). apply map_length in H2.
      destruct s. inversion H2. destruct s0. inversion H2. destruct s1.
      * destruct s; destruct s0; simpl in H'; inversion H'.
      * inversion H2.
    - induction s.
      * inversion H.
      * simpl in H. apply concat_in_lemma in H. destruct H.
        ++ destruct a. simpl in H. inversion H. simpl in H. destruct H. inversion H. inversion H.
        ++ auto.
Qed.

Lemma renameRule_progress_2_lemma:
  forall left t0 n0  rule,
    ~(In (left, [inr t0; inl n0]) (normalizeRule rule)).
Proof.
  intros left n0 t0 rule contr. destruct rule.
  unfold normalizeRule in contr.
  destruct destr_isSingle_lemma with (x := (n,s)); rewrite e in contr.
  + inversion contr. inversion H. subst. simpl in e. congruence. inversion H.
  + clear e. unfold renameRule in contr. destruct contr; simpl in H.
    - inversion H. clear H H1. assert (H' := H2). apply map_length in H2.
      destruct s. inversion H2. destruct s0. inversion H2. destruct s1.
      * destruct s; destruct s0; simpl in H'; inversion H'.
      * inversion H2.
    - induction s.
      * inversion H.
      * simpl in H. apply concat_in_lemma in H. destruct H.
        ++ destruct a. simpl in H. inversion H. simpl in H. destruct H. inversion H. inversion H.
        ++ auto.
Qed.

Lemma renameRule_progress_3_lemma:
  forall left t0 t1  rule,
    ~(In (left, [inr t0; inr t1]) (normalizeRule rule)).
Proof.
  intros left n0 t0 rule contr. destruct rule.
  unfold normalizeRule in contr.
  destruct destr_isSingle_lemma with (x := (n,s)); rewrite e in contr.
  + inversion contr. inversion H. subst. simpl in e. congruence. inversion H.
  + clear e. unfold renameRule in contr. destruct contr; simpl in H.
    - inversion H. clear H H1. assert (H' := H2). apply map_length in H2.
      destruct s. inversion H2. destruct s0. inversion H2. destruct s1.
      * destruct s; destruct s0; simpl in H'; inversion H'.
      * inversion H2.
    - induction s.
      * inversion H.
      * simpl in H. apply concat_in_lemma in H. destruct H.
        ++ destruct a. simpl in H. inversion H. simpl in H. destruct H. inversion H. inversion H.
        ++ auto.
Qed.

(* minimized? *)
Lemma renameRule_progress_lemma:
  forall left n0 t0 t1 right rule,
    right = [inr t0; inr t1] \/ right = [inr t0; inl n0] \/ right = [inl n0; inr t0] ->
    ~(In (left, right) (normalizeRule rule)).
Proof.
  intros left n0 t0 t1 right rule R contr. destruct rule.
  unfold normalizeRule in contr.
  destruct destr_isSingle_lemma with (x := (n,s)); rewrite e in contr.
  + inversion contr. inversion H. subst.
    destruct R; [| destruct H0]; subst; simpl in *; congruence.
    inversion H.
  + clear e. unfold renameRule in contr. destruct contr; simpl in H.
    - inversion H. clear H H1. assert (H' := H2). apply map_length in H2.
      destruct s; [|destruct s0; [|destruct s1]];
      try (destruct R as [L|R]; [|destruct R as [L|R]]; subst; destruct s; destruct s0; simpl in H'; inversion H');
      try (destruct R as [L|R]; [|destruct R as [L|R]]; subst; inversion H2).
    - induction s.
      * inversion H.
      * simpl in H. apply concat_in_lemma in H. destruct H.
        ++ destruct R as [L|R]; [|destruct R as [L|R]]; subst;
            destruct a; simpl in H; inversion H; simpl in H; destruct H; inversion H.
        ++ auto.
Qed.

(*
Lemma renameRule_progres:
  forall left t rl rr rule,
    ~(In (left, rl ++ [inr t] ++ rr) (renameRule rule)).
Proof.
  intros left t rl rr rule contr. destruct rule.
  unfold renameRule in contr. destruct contr; simpl in H.
    - (* inversion H. clear H H1. assert (H' := H2). apply map_length in H2. *)
      induction rl.
      + induction s.
        * simpl in *. inversion H.
        * destruct a. simpl in H. inversion H.
     admit.
      destruct s; [|destruct s0; [|destruct s1]];
      try (destruct R as [L|R]; [|destruct R as [L|R]]; subst; destruct s; destruct s0; simpl in H'; inversion H');
      try (destruct R as [L|R]; [|destruct R as [L|R]]; subst; inversion H2).
    - induction s.
      * inversion H.
      * simpl in H. apply concat_in_lemma in H. destruct H.
        ++ destruct R as [L|R]; [|destruct R as [L|R]]; subst;
            destruct a; simpl in H; inversion H; simpl in H; destruct H; inversion H.
        ++ auto.
Qed.
*)

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

Lemma lemma_9:
  forall left n0 t0 rules,
    ~ In (left, [inl n0; inr t0]) (flat_map normalizeRule rules).
Proof.
  intros left n0 t0 rules contr. induction rules.
  - simpl in contr. assumption.
  - destruct a. simpl in contr. apply concat_in_lemma in contr. destruct contr.
    + apply renameRule_progress_1_lemma in H. inversion H.
    + apply IHrules. assumption.
Qed.

Lemma lemma_12:
  forall left t0 n0 rules,
    ~ In (left, [inr t0; inl n0]) (flat_map normalizeRule rules).
Proof.
  intros left n0 t0 rules contr. induction rules.
  - simpl in contr. assumption.
  - destruct a. simpl in contr. apply concat_in_lemma in contr. destruct contr.
    + apply renameRule_progress_2_lemma in H. inversion H.
    + apply IHrules. assumption.
Qed.

Lemma lemma_13:
  forall left t0 t1 rules,
    ~ In (left, [inr t0; inr t1]) (flat_map normalizeRule rules).
Proof.
  intros left n0 t0 rules contr. induction rules.
  - simpl in contr. assumption.
  - destruct a. simpl in contr. apply concat_in_lemma in contr. destruct contr.
    + apply renameRule_progress_3_lemma in H. inversion H.
    + apply IHrules. assumption.
Qed.

Lemma Alg_prop_7:
forall g left n0 t0,
  ~ In (left, [inl n0; inr t0]) (rules (renameTerms g)).
Proof. intros. apply lemma_9. Qed.

Lemma Alg_prop_8:
forall g left t0 n0,
 ~ In (left, [inr t0; inl n0]) (rules (renameTerms g)).
Proof. intros. apply lemma_12. Qed.

Lemma Alg_prop_9:
forall g left t0 t1,
  ~ In (left, [inr t0; inr t1]) (rules (renameTerms g)).
Proof. intros. apply lemma_13. Qed.

(* TODO:  form. *)
Theorem eq_rename:
  forall g,
    short_rules g /\ short_rules (renameTerms g) ->
      g_equiv g (renameTerms g).
Proof.
unfold g_equiv. unfold produces. unfold generates. unfold short_rules. simpl. split.
- intros.
  induction H0.
  + apply derives_refl.
  + assert (H' := H1).
    apply H in H1.
    inversion H1.

    destruct right. inversion H3. destruct right. inversion H3. destruct right.
    destruct s0; destruct s4.

    * inversion H3. eapply derives_step. apply IHderives.

    apply -> Alg_prop_3. assumption. admit. admit. admit.

    * destruct t0.
    apply Alg_prop_4 in H'. destruct H'.

    apply derives_trans with (s2 := s2 ++ [inl n; inl (NT ("New_" ++ s0))] ++ s3).
    eapply derives_step. apply IHderives. assumption.

    rewrite <- custom_ass_1 with (s1 := s2) (c1 := inl n) (c2 := inr (T s0)) (s2 := s3).

    apply derives_step with
    (g := (renameTerms g))
    (s1 := (s2 ++ [inl n; inl (NT ("New_" ++ s0))] ++ s3))
    (s2 := s2 ++ [inl n]) (s3 := s3) (left := (NT ("New_" ++ s0))) (right := [inr (T s0)]).

    rewrite <- custom_ass_1.

    apply derives_refl.
    assumption.

    * destruct t0.
      apply Alg_prop_5 in H'. destruct H'.
      apply derives_trans with (s2 := s2 ++ [inl (NT ("New_" ++ s0)); inl n] ++ s3).
      eapply derives_step. apply IHderives. assumption.

      apply derives_step with
      (g := (renameTerms g))
      (s1 := (s2 ++ [inl (NT ("New_" ++ s0))] ++ [inl n] ++ s3))
      (s2 := s2) (s3 := [inl n] ++ s3) (left := (NT ("New_" ++ s0))) (right := [inr (T s0)]).

      apply derives_refl.
      assumption.

    * destruct t0. destruct t1.

      apply Alg_prop_6 in H'. destruct H'. destruct H4.

      apply derives_trans with (s2 := s2 ++ [inl (NT ("New_" ++ s0)); inl (NT ("New_" ++ s4))] ++ s3).
      apply derives_step with (left := left). assumption. assumption.

      apply derives_trans with (s2 := s2 ++ [inr (T s0); inl (NT ("New_" ++ s4))] ++ s3).
      apply derives_step with
      (g := (renameTerms g))
      ( s1:= (s2 ++ [inl (NT ("New_" ++ s0)); inl (NT ("New_" ++ s4))] ++ s3))
      (s2:=s2)
      (s3:= [inl (NT ("New_" ++ s4))] ++ s3)
      (left := NT ("New_" ++ s0)) (right := [inr (T s0)]).

      apply derives_refl.
      assumption.

      rewrite <- custom_ass_1 with (s1 := s2) (c1 := inr (T s0)) (c2 := inr (T s4)) (s2 := s3).

      apply derives_step with
      (g := (renameTerms g))
      (s1:= (s2 ++ [inr (T s0); inl (NT ("New_" ++ s4))] ++ s3))
      (s2:= s2 ++ [inr (T s0)])
      (s3:= s3)
      (left := NT ("New_" ++ s4)) (right := [inr (T s4)]).
      rewrite <- custom_ass_3.
      apply derives_refl. assumption.

    * inversion H3.
    * inversion H3. destruct right. inversion H5. destruct right. destruct s0.
      eapply derives_step. apply IHderives. apply -> Alg_prop_2. assumption.
        admit. (* forall s0 : string, left <> NT ("New_" ++ s0) *)

      eapply derives_step. apply IHderives.  apply -> Alg_prop_2. assumption.
        admit. (* forall s0 : string, left <> NT ("New_" ++ s0) *)
      inversion H5.

      inversion H5. destruct right.
      eapply derives_step. apply IHderives. apply -> Alg_prop_1. assumption.
      inversion H7.

- intros. induction H0.
  + apply derives_refl.
  + assert (H' := H1). apply H in H1. inversion H1.

  destruct right. inversion H3. destruct right. inversion H3. destruct right.
  destruct s0; destruct s4.
  * apply derives_step with (left := left). assumption. apply Alg_prop_3. admit. admit. admit.  assumption.
  * apply Alg_prop_7 in H'. inversion H'.
  * apply Alg_prop_8 in H'. inversion H'.

  * apply Alg_prop_9 in H'. inversion H'.
  * inversion H3.
  * inversion H3. destruct right. inversion H5.
  destruct right.
  apply derives_step with (left := left). assumption.

  apply <- Alg_prop_2. assumption.
    admit. (* forall s0 : string, left <> NT ("New_" ++ s0) *)
  inversion H5.
  inversion H5. destruct right. apply derives_step with (left := left). assumption.

  apply <- Alg_prop_1. assumption.
  inversion H7.
Admitted.


(************************************************************************)
(*  v      *   The Coq Proof Assistant  /  The Coq Development Team     *)
(* <O___,, *   INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2011     *)
(*   \VV/  **************************************************************)
(*    //   *      This file is distributed under the terms of the       *)
(*         *       GNU Lesser General Public License Version 2.1        *)
(************************************************************************)

(*i $Id: Sorting.v 14641 2011-11-06 11:59:10Z herbelin $ i*)

Require Export Sorted.
Require Export Mergesort.


Require Import Coq.Logic.Classical_Prop.
Require Import Logic.lib.Ensembles_ext.
Require Import Logic.lib.EnsemblesProperties.
Require Import Logic.lib.Bijection.
Require Import Logic.lib.Countable.
Require Import Logic.GeneralLogic.Base.
Require Import Logic.GeneralLogic.ProofTheory.BasicSequentCalculus.
Require Import Logic.GeneralLogic.KripkeModel.
Require Import Logic.GeneralLogic.Semantics.Kripke.
Require Import Logic.GeneralLogic.Complete.ContextProperty.
Require Import Logic.GeneralLogic.Complete.ContextProperty_Kripke.
Require Import Logic.GeneralLogic.Complete.Lindenbaum.
Require Import Logic.GeneralLogic.Complete.Canonical_Kripke.
Require Import Logic.GeneralLogic.Complete.Complete_Kripke.
Require Import Logic.MinimumLogic.Syntax.
Require Import Logic.MinimumLogic.ProofTheory.Minimum.
Require Import Logic.MinimumLogic.Semantics.Kripke.
Require Import Logic.MinimumLogic.Complete.ContextProperty_Kripke.
Require Import Logic.MinimumLogic.Complete.Truth_Kripke.
Require Import Logic.MinimumLogic.Complete.Lindenbaum_Kripke.
Require Logic.MinimumLogic.DeepEmbedded.MinimumLanguage.
Require Logic.MinimumLogic.DeepEmbedded.MinimumLogic.
Require Logic.MinimumLogic.DeepEmbedded.KripkeSemantics.

Local Open Scope logic_base.
Local Open Scope syntax.
Local Open Scope kripke_model.
Local Open Scope kripke_model_class.
Import KripkeModelFamilyNotation.
Import KripkeModelNotation_Intuitionistic.
Import KripkeModelClass.

Section Complete.

Context (Var: Type) (CV: Countable Var).

Instance L: Language := MinimumLanguage.L Var.
Instance minL: MinimumLanguage L := MinimumLanguage.minL Var.

Instance GP: Provable L := MinimumLogic.GP Var.
Instance GD: Derivable L := MinimumLogic.GD Var.
Instance GDP: DerivableProvable L GP GD := MinimumLogic.GDP Var.
Instance minAX: MinimumAxiomatization L GP := MinimumLogic.minAX Var.
Instance SC: ProvableDerivable L GP GD := MinimumLogic.GPD Var.
Instance bSC: BasicSequentCalculus L GD := MinimumLogic.bSC Var.
Instance fwSC: FiniteWitnessedSequentCalculus L GD := MinimumLogic.fwSC Var.
Instance minSC: MinimumSequentCalculus L GD := MinimumLogic.minSC Var.
Instance Kripke_MD: Model := KripkeSemantics.MD Var.
Instance Kripke_kMD: KripkeModel Kripke_MD := KripkeSemantics.kMD Var.
Instance Kripke_R (M: Kmodel): Relation (Kworlds M) := KripkeSemantics.R Var M.
Instance Kripke_SM: Semantics L Kripke_MD := KripkeSemantics.SM Var.
Instance Kripke_kminSM (M: Kmodel): KripkeMinimumSemantics L Kripke_MD M Kripke_SM := KripkeSemantics.kminSM Var M.

Definition cP: context -> Prop := derivable_closed.

Lemma AL_DC: at_least derivable_closed cP.
Proof. solve_at_least. Qed.

Lemma LIN_CD: forall x: expr, Lindenbaum_constructable (cannot_derive x) cP.
Proof.
  intros.
  apply Lindenbaum_constructable_suffice; auto.
  + apply MinimumLanguage.formula_countable; auto.
  + apply Lindenbaum_preserves_cannot_derive.
  + unfold cP.
    apply Lindenbaum_cannot_derive_ensures_derivable_closed.
Qed.

Definition canonical_frame: KripkeSemantics.frame :=
  KripkeSemantics.Build_frame (sig cP) (fun a b => Included _ (proj1_sig a) (proj1_sig b)).

Definition canonical_eval: Var -> KripkeSemantics.sem canonical_frame :=
  fun p a => proj1_sig a (MinimumLanguage.varp p).

Definition canonical_Kmodel: @Kmodel (KripkeSemantics.MD Var) (KripkeSemantics.kMD Var) :=
  KripkeSemantics.Build_Kmodel Var canonical_frame canonical_eval.

Definition rel: bijection (Kworlds canonical_Kmodel) (sig cP) := bijection_refl.

Definition H_R:
  forall m n Phi Psi, rel m Phi -> rel n Psi ->
    (m <= n <-> Included _ (proj1_sig Phi) (proj1_sig Psi)).
Proof.
  intros.
  change (m = Phi) in H.
  change (n = Psi) in H0.
  subst; reflexivity.
Qed.

Lemma TRUTH:
  forall x: expr, forall m Phi, rel m Phi ->
    (KRIPKE: canonical_Kmodel, m |= x <-> proj1_sig Phi x).
Proof.
  induction x.
  + exact (truth_lemma_impp cP rel H_R AL_DC LIN_CD x1 x2 IHx1 IHx2).
  + intros; change (m = Phi) in H; subst; reflexivity.
Qed.

Import Logic.MinimumLogic.DeepEmbedded.KripkeSemantics.

Theorem complete_MinimumLogic_Kripke_all:
  strongly_complete GD Kripke_SM
    (KripkeModelClass _ (Kmodel_Monotonic + Kmodel_PreOrder)).
Proof.
  apply (general_completeness cP rel LIN_CD TRUTH).
  constructor; hnf.
  + intros.
    exact (denote_monotonic cP rel H_R
             (MinimumLanguage.varp v)
             (TRUTH (MinimumLanguage.varp v))).
  + exact (po_R cP rel H_R).
Qed.

End Complete.


Require Import sorted_listupto_spec.

Definition type_LF_159 :=  nat -> (Prop * (List.list term)).

Definition F_159 : type_LF_159:= (fun    u1 => ((plus u1 0) = u1, (Term id_plus ((model_nat u1):: (Term id_0 nil)::nil))::(model_nat u1)::nil)).
Definition F_169 : type_LF_159:= (fun     _ => (0 = 0, (Term id_0 nil)::(Term id_0 nil)::nil)).
Definition F_175 : type_LF_159:= (fun    u2 => ((S (plus u2 0)) = (S u2), (Term id_S ((Term id_plus ((model_nat u2):: (Term id_0 nil)::nil))::nil))::(Term id_S ((model_nat u2)::nil))::nil)).
Definition F_180 : type_LF_159:= (fun    u2 => (u2 = u2, (model_nat u2)::(model_nat u2)::nil)).

Definition LF_159 := [F_159, F_169, F_175, F_180].

Function f_159 (u1: nat) {struct u1} : nat :=
 match u1 with
| 0 => 0
| (S u2) => 0
end.

Lemma main_159 : forall F, In F LF_159 -> forall u1, (forall F', In F' LF_159 -> forall e1, less (snd (F' e1)) (snd (F u1)) -> fst (F' e1)) -> fst (F u1).
Proof.
intros F HF u1; case_In HF; intro Hind.

	(* GENERATE on [ 159 ] *)

rename u1 into _u1.
rename _u1 into u1.

revert Hind.

pattern u1, (f_159 u1). apply f_159_ind.

(* case [ 169 ] *)

intros _u1.  intro eq_1.  intro HFabs0.
assert (Hind := HFabs0 F_169). clear HFabs0.
assert (HFabs0 : fst (F_169 0)).
apply Hind. trivial_in 1. unfold snd. unfold F_169. unfold F_159. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_159. unfold F_169.
auto.

(* case [ 175 ] *)

intros _u1. intro u2.  intro eq_1.  intro HFabs0.
assert (Hind := HFabs0 F_175). clear HFabs0.
assert (HFabs0 : fst (F_175 u2)).
apply Hind. trivial_in 2. unfold snd. unfold F_175. unfold F_159. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_159. unfold F_175.
auto.

	(* TAUTOLOGY on [ 169 ] *)

unfold fst. unfold F_169.
auto.

	(* POSITIVE DECOMPOSITION on [ 175 ] *)

rename u1 into _u2.
rename _u2 into u2.
assert (H1 := Hind F_159).
assert (HFabs1 : fst (F_159 u2)).
apply H1. trivial_in 0. unfold snd. unfold F_159. unfold F_175. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_175. unfold F_159.

unfold fst in HFabs1. unfold F_159 in HFabs1.

repeat (auto || (rewrite HFabs1||  auto)).

	(* TAUTOLOGY on [ 180 ] *)

unfold fst. unfold F_180.
auto.

Qed.

(* the set of all formula instances from the proof *)
Definition S_159 := fun f => exists F, In F LF_159 /\ exists e1, f = F e1.

Theorem all_true_159: forall F, In F LF_159 -> forall u1: nat, fst (F u1).
Proof.
let n := constr:(1) in
let p := constr:(S(S(n))) in
intros;
let G := fresh "G" in
let x := fresh "x" in
apply wf_subset with (R:=@snd_rpo_mul P Prop max_size) (S:=S_159);
[(* 1 *) apply wf_snd_rpo_mul, prec_wf
|(* 2 *) idtac
|(* 3 *) eexists; split; [ eassumption | idtac]; do_nat n ltac:(eexists); reflexivity
];

intros x G;
do_nat p ltac:(elim G; intro; clear G; intro G);
rewrite G in * |- *; clear G; clear x;
intro G;
apply main_159;
 [assumption | idtac];
intros;
apply G;
 [ idtac | assumption ];
eexists; split;
 [idtac | do_nat n ltac:(eexists); reflexivity];
assumption.
Qed.

Theorem true_159: forall (u1: nat), (plus u1 0) = u1.
Proof.
do 1 intro.
apply (all_true_159 F_159);
 (trivial_in 0) ||
 (repeat constructor).
Qed.

Definition type_LF_182 :=  nat ->  nat -> (Prop * (List.list term)).

Definition F_182 : type_LF_182:= (fun    u1 u2 => ((le u1 u2) = false -> (le u1 u2) = true -> False, (Term id_le ((model_nat u1):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_le ((model_nat u1):: (model_nat u2)::nil))::(Term id_true nil)::nil)).
Definition F_198 : type_LF_182:= (fun    u2 _ => (true = false -> (le 0 u2) = true -> False, (Term id_true nil)::(Term id_false nil)::(Term id_le ((Term id_0 nil):: (model_nat u2)::nil))::(Term id_true nil)::nil)).
Definition F_204 : type_LF_182:= (fun    u3 _ => (false = false -> (le (S u3) 0) = true -> False, (Term id_false nil)::(Term id_false nil)::(Term id_le ((Term id_S ((model_nat u3)::nil)):: (Term id_0 nil)::nil))::(Term id_true nil)::nil)).
Definition F_210 : type_LF_182:= (fun    u3 u4 => ((le u3 u4) = false -> (le (S u3) (S u4)) = true -> False, (Term id_le ((model_nat u3):: (model_nat u4)::nil))::(Term id_false nil)::(Term id_le ((Term id_S ((model_nat u3)::nil)):: (Term id_S ((model_nat u4)::nil))::nil))::(Term id_true nil)::nil)).
Definition F_211 : type_LF_182:= (fun    u3 _ => ((le (S u3) 0) = true -> False, (Term id_le ((Term id_S ((model_nat u3)::nil)):: (Term id_0 nil)::nil))::(Term id_true nil)::nil)).
Definition F_217 : type_LF_182:= (fun     _ _ => (false = true -> False, (Term id_false nil)::(Term id_true nil)::nil)).

Definition LF_182 := [F_182, F_198, F_204, F_210, F_211, F_217].

Function f_182 (u1: nat) (u2: nat) {struct u1} : bool :=
 match u1, u2 with
| 0, _ => true
| (S u3), 0 => true
| (S u3), (S u4) => true
end.

Lemma main_182 : forall F, In F LF_182 -> forall u1, forall u2, (forall F', In F' LF_182 -> forall e1, forall e2, less (snd (F' e1 e2)) (snd (F u1 u2)) -> fst (F' e1 e2)) -> fst (F u1 u2).
Proof.
intros F HF u1 u2; case_In HF; intro Hind.

	(* GENERATE on [ 182 ] *)

rename u1 into _u1. rename u2 into _u2.
rename _u1 into u1. rename _u2 into u2.

revert Hind.

pattern u1, u2, (f_182 u1 u2). apply f_182_ind.

(* case [ 198 ] *)

intros _u1 _u2.  intro eq_1. intro. intro Heq2. rewrite <- Heq2.  intro HFabs0.
assert (Hind := HFabs0 F_198). clear HFabs0.
assert (HFabs0 : fst (F_198 _u2 0)).
apply Hind. trivial_in 1. unfold snd. unfold F_198. unfold F_182. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_182. unfold F_198.
auto.

(* case [ 204 ] *)

intros _u1 _u2. intro u3.  intro eq_1.  intro eq_2.  intro HFabs0.
assert (Hind := HFabs0 F_204). clear HFabs0.
assert (HFabs0 : fst (F_204 u3 0)).
apply Hind. trivial_in 2. unfold snd. unfold F_204. unfold F_182. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_182. unfold F_204.
auto.

(* case [ 210 ] *)

intros _u1 _u2. intro u3.  intro eq_1. intro u4.  intro eq_2.  intro HFabs0.
assert (Hind := HFabs0 F_210). clear HFabs0.
assert (HFabs0 : fst (F_210 u3 u4)).
apply Hind. trivial_in 3. unfold snd. unfold F_210. unfold F_182. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_182. unfold F_210.
auto.

	(* NEGATIVE CLASH on [ 198 ] *)

unfold fst. unfold F_198. intros. try discriminate.

	(* NEGATIVE DECOMPOSITION on [ 204 ] *)

rename u1 into _u3. rename u2 into d_u2.
rename _u3 into u3.
assert (H := Hind F_211).
assert (HFabs0 : fst (F_211 u3 0)).
apply H. trivial_in 4. unfold snd. unfold F_211. unfold F_204. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_204. unfold F_211.

unfold fst in HFabs0. unfold F_211 in HFabs0.
auto.

	(* REWRITING on [ 210 ] *)

rename u1 into _u3. rename u2 into _u4.
rename _u3 into u3. rename _u4 into u4.
assert (Res := Hind F_182). clear Hind.
assert (HFabs1 : fst (F_182 u3 u4)).
apply Res. trivial_in 0. unfold snd. unfold F_182. unfold F_210. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_210. unfold fst in HFabs1. unfold F_182 in HFabs1.
pattern u3, u4. simpl (le _ _). cbv beta.
 simpl. auto.

	(* REWRITING on [ 211 ] *)

rename u1 into _u3. rename u2 into d_u2.
rename _u3 into u3.
assert (Res := Hind F_217). clear Hind.
assert (HFabs1 : fst (F_217 0 0)).
apply Res. trivial_in 5. unfold snd. unfold F_217. unfold F_211. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_211. unfold fst in HFabs1. unfold F_217 in HFabs1.
pattern u3. simpl (le _ _). cbv beta.
 simpl. auto.

	(* NEGATIVE CLASH on [ 217 ] *)

unfold fst. unfold F_217. intros. try discriminate.

Qed.

(* the set of all formula instances from the proof *)
Definition S_182 := fun f => exists F, In F LF_182 /\ exists e1, exists e2, f = F e1 e2.

Theorem all_true_182: forall F, In F LF_182 -> forall u1: nat, forall u2: nat, fst (F u1  u2).
Proof.
let n := constr:(2) in
let p := constr:(S(S(n))) in
intros;
let G := fresh "G" in
let x := fresh "x" in
apply wf_subset with (R:=@snd_rpo_mul P Prop max_size) (S:=S_182);
[(* 1 *) apply wf_snd_rpo_mul, prec_wf
|(* 2 *) idtac
|(* 3 *) eexists; split; [ eassumption | idtac]; do_nat n ltac:(eexists); reflexivity
];

intros x G;
do_nat p ltac:(elim G; intro; clear G; intro G);
rewrite G in * |- *; clear G; clear x;
intro G;
apply main_182;
 [assumption | idtac];
intros;
apply G;
 [ idtac | assumption ];
eexists; split;
 [idtac | do_nat n ltac:(eexists); reflexivity];
assumption.
Qed.

Theorem true_182: forall (u1: nat) (u2: nat), (le u1 u2) = false -> (le u1 u2) = true -> False.
Proof.
do 2 intro.
apply (all_true_182 F_182);
 (trivial_in 0) ||
 (repeat constructor).
Qed.

Definition type_LF_222 :=  PLAN ->  OBJ ->  nat ->  nat ->  nat -> (Prop * (List.list term)).

Definition F_222 : type_LF_222:= (fun  u2 u1  _ _ _ => ((sortedT (Cons u1 u2)) = true -> (sortedT u2) = true, (Term id_sortedT ((Term id_Cons ((model_OBJ u1):: (model_PLAN u2)::nil))::nil))::(Term id_true nil)::(Term id_sortedT ((model_PLAN u2)::nil))::(Term id_true nil)::nil)).
Definition F_243 : type_LF_222:= (fun  u7  _ u3 u4 u6 => ((sortedT (Cons (C u3 u6) u7)) = true -> (le u3 u4) = true -> (sortedT (Cons (C u3 u6) u7)) = true, (Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u6)::nil)):: (model_PLAN u7)::nil))::nil))::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u4)::nil))::(Term id_true nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u6)::nil)):: (model_PLAN u7)::nil))::nil))::(Term id_true nil)::nil)).
Definition F_249 : type_LF_222:= (fun  u7  _ u3 u4 u6 => (false = true -> (le u3 u4) = false -> (sortedT (Cons (C u3 u6) u7)) = true, (Term id_false nil)::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u4)::nil))::(Term id_false nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u6)::nil)):: (model_PLAN u7)::nil))::nil))::(Term id_true nil)::nil)).
Definition F_237 : type_LF_222:= (fun   _  _  _ _ _ => (true = true -> (sortedT Nil) = true, (Term id_true nil)::(Term id_true nil)::(Term id_sortedT ((Term id_Nil nil)::nil))::(Term id_true nil)::nil)).
Definition F_250 : type_LF_222:= (fun   _  _  _ _ _ => ((sortedT Nil) = true, (Term id_sortedT ((Term id_Nil nil)::nil))::(Term id_true nil)::nil)).
Definition F_253 : type_LF_222:= (fun   _  _  _ _ _ => (true = true, (Term id_true nil)::(Term id_true nil)::nil)).

Definition LF_222 := [F_222, F_243, F_249, F_237, F_250, F_253].

Function f_222 (u2: PLAN) (u1: OBJ) {struct u2} : bool :=
 match u2, u1 with
| Nil, _ => true
| (Cons (C u3 u6) u7), (C u4 u5) => true
end.

Lemma main_222 : forall F, In F LF_222 -> forall u1, forall u2, forall u3, forall u4, forall u5, (forall F', In F' LF_222 -> forall e1, forall e2, forall e3, forall e4, forall e5, less (snd (F' e1 e2 e3 e4 e5)) (snd (F u1 u2 u3 u4 u5)) -> fst (F' e1 e2 e3 e4 e5)) -> fst (F u1 u2 u3 u4 u5).
Proof.
intros F HF u1 u2 u3 u4 u5; case_In HF; intro Hind.

	(* GENERATE on [ 222 ] *)

rename u1 into _u2. rename u2 into _u1. rename u3 into d_u3. rename u4 into d_u4. rename u5 into d_u5.
rename _u2 into u2. rename _u1 into u1.

revert Hind.

pattern u2, u1, (f_222 u2 u1). apply f_222_ind.

(* case [ 237 ] *)

intros _u2 _u1.  intro eq_1. intro. intro Heq1. rewrite <- Heq1.  intro HFabs0.
assert (Hind := HFabs0 F_237). clear HFabs0.
assert (HFabs0 : fst (F_237 Nil (C 0 0 ) 0 0 0)).
apply Hind. trivial_in 3. unfold snd. unfold F_237. unfold F_222. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_222. unfold F_237.
auto.

intros _u2 _u1. intro u3. intro u6. intro u7.  intro eq_1. intro u4. intro u5.  intro eq_2.  intro HFabs0.
case_eq (le u3 u4); [intro H | intro H].

(* case [ 243 ] *)

assert (Hind := HFabs0 F_243). clear HFabs0.
assert (HFabs0 : fst (F_243 u7 (C 0 0 ) u3 u4 u6)).
apply Hind. trivial_in 1. unfold snd. unfold F_243. unfold F_222. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_222. unfold F_243. simpl in H. repeat(simpl; rewrite H). repeat(simpl in HFabs0; rewrite H in HFabs0). try (auto || (intro H0; contradict H0)).
auto.

(* case [ 249 ] *)

assert (Hind := HFabs0 F_249). clear HFabs0.
assert (HFabs0 : fst (F_249 u7 (C 0 0 ) u3 u4 u6)).
apply Hind. trivial_in 2. unfold snd. unfold F_249. unfold F_222. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_222. unfold F_249. simpl in H. repeat(simpl; rewrite H). repeat(simpl in HFabs0; rewrite H in HFabs0). try (auto || (intro H0; contradict H0)).
auto.

	(* TAUTOLOGY on [ 243 ] *)

unfold fst. unfold F_243.
auto.

	(* NEGATIVE CLASH on [ 249 ] *)

unfold fst. unfold F_249. intros. try discriminate.

	(* NEGATIVE DECOMPOSITION on [ 237 ] *)

rename u1 into d_u1. rename u2 into d_u2. rename u3 into d_u3. rename u4 into d_u4. rename u5 into d_u5.

assert (H := Hind F_250).
assert (HFabs0 : fst (F_250 Nil (C 0 0 ) 0 0 0)).
apply H. trivial_in 4. unfold snd. unfold F_250. unfold F_237. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_237. unfold F_250.

unfold fst in HFabs0. unfold F_250 in HFabs0.
auto.

	(* REWRITING on [ 250 ] *)

rename u1 into d_u1. rename u2 into d_u2. rename u3 into d_u3. rename u4 into d_u4. rename u5 into d_u5.

assert (Res := Hind F_253). clear Hind.
assert (HFabs1 : fst (F_253 Nil (C 0 0 ) 0 0 0)).
apply Res. trivial_in 5. unfold snd. unfold F_253. unfold F_250. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_250. unfold fst in HFabs1. unfold F_253 in HFabs1.    simpl. auto.

	(* TAUTOLOGY on [ 253 ] *)

unfold fst. unfold F_253.
auto.

Qed.

(* the set of all formula instances from the proof *)
Definition S_222 := fun f => exists F, In F LF_222 /\ exists e1, exists e2, exists e3, exists e4, exists e5, f = F e1 e2 e3 e4 e5.

Theorem all_true_222: forall F, In F LF_222 -> forall u1: PLAN, forall u2: OBJ, forall u3: nat, forall u4: nat, forall u5: nat, fst (F u1 u2 u3  u4  u5).
Proof.
let n := constr:(5) in
let p := constr:(S(S(n))) in
intros;
let G := fresh "G" in
let x := fresh "x" in
apply wf_subset with (R:=@snd_rpo_mul P Prop max_size) (S:=S_222);
[(* 1 *) apply wf_snd_rpo_mul, prec_wf
|(* 2 *) idtac
|(* 3 *) eexists; split; [ eassumption | idtac]; do_nat n ltac:(eexists); reflexivity
];

intros x G;
do_nat p ltac:(elim G; intro; clear G; intro G);
rewrite G in * |- *; clear G; clear x;
intro G;
apply main_222;
 [assumption | idtac];
intros;
apply G;
 [ idtac | assumption ];
eexists; split;
 [idtac | do_nat n ltac:(eexists); reflexivity];
assumption.
Qed.

Theorem true_222: forall (u2: PLAN) (u1: OBJ), (sortedT (Cons u1 u2)) = true -> (sortedT u2) = true.
Proof.
do 2 intro.
apply (all_true_222 F_222);
 (trivial_in 0) ||
 (repeat constructor).
Qed.

Definition type_LF_254 :=  PLAN ->  OBJ ->  nat ->  nat ->  nat ->  nat -> (Prop * (List.list term)).

Definition F_254 : type_LF_254:= (fun  u2 u1  _ _ _ _ => ((sortedT (Cons u1 u2)) = true -> (le (timel u2) (time u1)) = true, (Term id_sortedT ((Term id_Cons ((model_OBJ u1):: (model_PLAN u2)::nil))::nil))::(Term id_true nil)::(Term id_le ((Term id_timel ((model_PLAN u2)::nil)):: (Term id_time ((model_OBJ u1)::nil))::nil))::(Term id_true nil)::nil)).
Definition F_282 : type_LF_254:= (fun  u7  _ u3 u4 u5 u6 => (false = true -> (le u3 u4) = false -> (le (timel (Cons (C u3 u6) u7)) (time (C u4 u5))) = true, (Term id_false nil)::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u4)::nil))::(Term id_false nil)::(Term id_le ((Term id_timel ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u6)::nil)):: (model_PLAN u7)::nil))::nil)):: (Term id_time ((Term id_C ((model_nat u4):: (model_nat u5)::nil))::nil))::nil))::(Term id_true nil)::nil)).
Definition F_270 : type_LF_254:= (fun   _ u1  _ _ _ _ => (true = true -> (le (timel Nil) (time u1)) = true, (Term id_true nil)::(Term id_true nil)::(Term id_le ((Term id_timel ((Term id_Nil nil)::nil)):: (Term id_time ((model_OBJ u1)::nil))::nil))::(Term id_true nil)::nil)).
Definition F_276 : type_LF_254:= (fun  u7  _ u3 u4 u5 u6 => ((sortedT (Cons (C u3 u6) u7)) = true -> (le u3 u4) = true -> (le (timel (Cons (C u3 u6) u7)) (time (C u4 u5))) = true, (Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u6)::nil)):: (model_PLAN u7)::nil))::nil))::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u4)::nil))::(Term id_true nil)::(Term id_le ((Term id_timel ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u6)::nil)):: (model_PLAN u7)::nil))::nil)):: (Term id_time ((Term id_C ((model_nat u4):: (model_nat u5)::nil))::nil))::nil))::(Term id_true nil)::nil)).
Definition F_283 : type_LF_254:= (fun   _ u1  _ _ _ _ => ((le (timel Nil) (time u1)) = true, (Term id_le ((Term id_timel ((Term id_Nil nil)::nil)):: (Term id_time ((model_OBJ u1)::nil))::nil))::(Term id_true nil)::nil)).
Definition F_286 : type_LF_254:= (fun  u7  _ u3 u4 u6 _ => ((sortedT (Cons (C u3 u6) u7)) = true -> (le u3 u4) = true -> (le (timel (Cons (C u3 u6) u7)) u4) = true, (Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u6)::nil)):: (model_PLAN u7)::nil))::nil))::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u4)::nil))::(Term id_true nil)::(Term id_le ((Term id_timel ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u6)::nil)):: (model_PLAN u7)::nil))::nil)):: (model_nat u4)::nil))::(Term id_true nil)::nil)).
Definition F_289 : type_LF_254:= (fun   _ u1  _ _ _ _ => ((le 0 (time u1)) = true, (Term id_le ((Term id_0 nil):: (Term id_time ((model_OBJ u1)::nil))::nil))::(Term id_true nil)::nil)).
Definition F_295 : type_LF_254:= (fun   _  _  _ _ _ _ => (true = true, (Term id_true nil)::(Term id_true nil)::nil)).
Definition F_292 : type_LF_254:= (fun  u7  _ u3 u4 u6 _ => ((sortedT (Cons (C u3 u6) u7)) = true -> (le u3 u4) = true -> (le (time (C u3 u6)) u4) = true, (Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u6)::nil)):: (model_PLAN u7)::nil))::nil))::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u4)::nil))::(Term id_true nil)::(Term id_le ((Term id_time ((Term id_C ((model_nat u3):: (model_nat u6)::nil))::nil)):: (model_nat u4)::nil))::(Term id_true nil)::nil)).
Definition F_298 : type_LF_254:= (fun  u7  _ u3 u4 u6 _ => ((sortedT (Cons (C u3 u6) u7)) = true -> (le u3 u4) = true -> (le u3 u4) = true, (Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u6)::nil)):: (model_PLAN u7)::nil))::nil))::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u4)::nil))::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u4)::nil))::(Term id_true nil)::nil)).

Definition LF_254 := [F_254, F_282, F_270, F_276, F_283, F_286, F_289, F_295, F_292, F_298].

Function f_254 (u2: PLAN) (u1: OBJ) {struct u2} : bool :=
 match u2, u1 with
| Nil, _ => true
| (Cons (C u3 u6) u7), (C u4 u5) => true
end.

Lemma main_254 : forall F, In F LF_254 -> forall u1, forall u2, forall u3, forall u4, forall u5, forall u6, (forall F', In F' LF_254 -> forall e1, forall e2, forall e3, forall e4, forall e5, forall e6, less (snd (F' e1 e2 e3 e4 e5 e6)) (snd (F u1 u2 u3 u4 u5 u6)) -> fst (F' e1 e2 e3 e4 e5 e6)) -> fst (F u1 u2 u3 u4 u5 u6).
Proof.
intros F HF u1 u2 u3 u4 u5 u6; case_In HF; intro Hind.

	(* GENERATE on [ 254 ] *)

rename u1 into _u2. rename u2 into _u1. rename u3 into d_u3. rename u4 into d_u4. rename u5 into d_u5. rename u6 into d_u6.
rename _u2 into u2. rename _u1 into u1.

revert Hind.

pattern u2, u1, (f_254 u2 u1). apply f_254_ind.

(* case [ 270 ] *)

intros _u2 _u1.  intro eq_1. intro. intro Heq1. rewrite <- Heq1.  intro HFabs0.
assert (Hind := HFabs0 F_270). clear HFabs0.
assert (HFabs0 : fst (F_270 Nil _u1 0 0 0 0)).
apply Hind. trivial_in 2. unfold snd. unfold F_270. unfold F_254. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_254. unfold F_270.
auto.

intros _u2 _u1. intro u3. intro u6. intro u7.  intro eq_1. intro u4. intro u5.  intro eq_2.  intro HFabs0.
case_eq (le u3 u4); [intro H | intro H].

(* case [ 276 ] *)

assert (Hind := HFabs0 F_276). clear HFabs0.
assert (HFabs0 : fst (F_276 u7 (C 0 0 ) u3 u4 u5 u6)).
apply Hind. trivial_in 3. unfold snd. unfold F_276. unfold F_254. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_254. unfold F_276. simpl in H. repeat(simpl; rewrite H). repeat(simpl in HFabs0; rewrite H in HFabs0). try (auto || (intro H0; contradict H0)).
auto.

(* case [ 282 ] *)

assert (Hind := HFabs0 F_282). clear HFabs0.
assert (HFabs0 : fst (F_282 u7 (C 0 0 ) u3 u4 u5 u6)).
apply Hind. trivial_in 1. unfold snd. unfold F_282. unfold F_254. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_254. unfold F_282. simpl in H. repeat(simpl; rewrite H). repeat(simpl in HFabs0; rewrite H in HFabs0). try (auto || (intro H0; contradict H0)).
auto.

	(* NEGATIVE CLASH on [ 282 ] *)

unfold fst. unfold F_282. intros. try discriminate.

	(* NEGATIVE DECOMPOSITION on [ 270 ] *)

rename u1 into d_u1. rename u2 into _u1. rename u3 into d_u3. rename u4 into d_u4. rename u5 into d_u5. rename u6 into d_u6.
rename _u1 into u1.
assert (H := Hind F_283).
assert (HFabs0 : fst (F_283 Nil u1 0 0 0 0)).
apply H. trivial_in 4. unfold snd. unfold F_283. unfold F_270. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_270. unfold F_283.

unfold fst in HFabs0. unfold F_283 in HFabs0.
auto.

	(* REWRITING on [ 276 ] *)

rename u1 into _u7. rename u2 into d_u2. rename u3 into _u3. rename u4 into _u4. rename u5 into _u5. rename u6 into _u6.
rename _u7 into u7. rename _u3 into u3. rename _u4 into u4. rename _u5 into u5. rename _u6 into u6.
assert (Res := Hind F_286). clear Hind.
assert (HFabs1 : fst (F_286 u7 (C 0 0 ) u3 u4 u6 0)).
apply Res. trivial_in 5. unfold snd. unfold F_286. unfold F_276. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_276. unfold fst in HFabs1. unfold F_286 in HFabs1.
pattern u4, u5. simpl (time _). cbv beta.
 simpl. auto.

	(* REWRITING on [ 283 ] *)

rename u1 into d_u1. rename u2 into _u1. rename u3 into d_u3. rename u4 into d_u4. rename u5 into d_u5. rename u6 into d_u6.
rename _u1 into u1.
assert (Res := Hind F_289). clear Hind.
assert (HFabs1 : fst (F_289 Nil u1 0 0 0 0)).
apply Res. trivial_in 6. unfold snd. unfold F_289. unfold F_283. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_283. unfold fst in HFabs1. unfold F_289 in HFabs1.    simpl. auto.

	(* REWRITING on [ 286 ] *)

rename u1 into _u7. rename u2 into d_u2. rename u3 into _u3. rename u4 into _u4. rename u5 into _u6. rename u6 into d_u6.
rename _u7 into u7. rename _u3 into u3. rename _u4 into u4. rename _u6 into u6.
assert (Res := Hind F_292). clear Hind.
assert (HFabs1 : fst (F_292 u7 (C 0 0 ) u3 u4 u6 0)).
apply Res. trivial_in 8. unfold snd. unfold F_292. unfold F_286. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_286. unfold fst in HFabs1. unfold F_292 in HFabs1.
pattern (C u3 u6), u7. simpl (timel _). cbv beta.
 simpl. auto.

	(* REWRITING on [ 289 ] *)

rename u1 into d_u1. rename u2 into _u1. rename u3 into d_u3. rename u4 into d_u4. rename u5 into d_u5. rename u6 into d_u6.
rename _u1 into u1.
assert (Res := Hind F_295). clear Hind.
assert (HFabs1 : fst (F_295 Nil (C 0 0 ) 0 0 0 0)).
apply Res. trivial_in 7. unfold snd. unfold F_295. unfold F_289. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_289. unfold fst in HFabs1. unfold F_295 in HFabs1.
pattern (time u1). simpl (le _ _). cbv beta.
 simpl. auto.

	(* TAUTOLOGY on [ 295 ] *)

unfold fst. unfold F_295.
auto.

	(* REWRITING on [ 292 ] *)

rename u1 into _u7. rename u2 into d_u2. rename u3 into _u3. rename u4 into _u4. rename u5 into _u6. rename u6 into d_u6.
rename _u7 into u7. rename _u3 into u3. rename _u4 into u4. rename _u6 into u6.
assert (Res := Hind F_298). clear Hind.
assert (HFabs1 : fst (F_298 u7 (C 0 0 ) u3 u4 u6 0)).
apply Res. trivial_in 9. unfold snd. unfold F_298. unfold F_292. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_292. unfold fst in HFabs1. unfold F_298 in HFabs1.
pattern u3, u6. simpl (time _). cbv beta.
 simpl. auto.

	(* TAUTOLOGY on [ 298 ] *)

unfold fst. unfold F_298.
auto.

Qed.

(* the set of all formula instances from the proof *)
Definition S_254 := fun f => exists F, In F LF_254 /\ exists e1, exists e2, exists e3, exists e4, exists e5, exists e6, f = F e1 e2 e3 e4 e5 e6.

Theorem all_true_254: forall F, In F LF_254 -> forall u1: PLAN, forall u2: OBJ, forall u3: nat, forall u4: nat, forall u5: nat, forall u6: nat, fst (F u1 u2 u3  u4  u5  u6).
Proof.
let n := constr:(6) in
let p := constr:(S(S(n))) in
intros;
let G := fresh "G" in
let x := fresh "x" in
apply wf_subset with (R:=@snd_rpo_mul P Prop max_size) (S:=S_254);
[(* 1 *) apply wf_snd_rpo_mul, prec_wf
|(* 2 *) idtac
|(* 3 *) eexists; split; [ eassumption | idtac]; do_nat n ltac:(eexists); reflexivity
];

intros x G;
do_nat p ltac:(elim G; intro; clear G; intro G);
rewrite G in * |- *; clear G; clear x;
intro G;
apply main_254;
 [assumption | idtac];
intros;
apply G;
 [ idtac | assumption ];
eexists; split;
 [idtac | do_nat n ltac:(eexists); reflexivity];
assumption.
Qed.

Theorem true_254: forall (u2: PLAN) (u1: OBJ), (sortedT (Cons u1 u2)) = true -> (le (timel u2) (time u1)) = true.
Proof.
do 2 intro.
apply (all_true_254 F_254);
 (trivial_in 0) ||
 (repeat constructor).
Qed.

Definition type_LF_299 :=  PLAN ->  nat ->  nat ->  nat ->  nat ->  nat -> (Prop * (List.list term)).

Definition F_299 : type_LF_299:= (fun   u1 u2 _ _ _ _ => ((sortedT u1) = true -> (sortedT (listUpTo u1 u2)) = true, (Term id_sortedT ((model_PLAN u1)::nil))::(Term id_true nil)::(Term id_sortedT ((Term id_listUpTo ((model_PLAN u1):: (model_nat u2)::nil))::nil))::(Term id_true nil)::nil)).
Definition F_330 : type_LF_299:= (fun    _  _ _ _ _ _ => ((sortedT Nil) = true -> (sortedT Nil) = true, (Term id_sortedT ((Term id_Nil nil)::nil))::(Term id_true nil)::(Term id_sortedT ((Term id_Nil nil)::nil))::(Term id_true nil)::nil)).
Definition F_336 : type_LF_299:= (fun   u6 u2 u3 u5 _ _ => ((sortedT (Cons (C u3 u5) u6)) = true -> (le u3 u2) = true -> (sortedT (Cons (C u3 u5) Nil)) = true, (Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u5)::nil)):: (model_PLAN u6)::nil))::nil))::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u2)::nil))::(Term id_true nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u5)::nil)):: (Term id_Nil nil)::nil))::nil))::(Term id_true nil)::nil)).
Definition F_345 : type_LF_299:= (fun   u6 u2 u3 u5 _ _ => ((sortedT (Cons (C u3 u5) u6)) = true -> (le u3 u2) = true -> true = true, (Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u5)::nil)):: (model_PLAN u6)::nil))::nil))::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u2)::nil))::(Term id_true nil)::(Term id_true nil)::(Term id_true nil)::nil)).
Definition F_342 : type_LF_299:= (fun   u6 u2 u3 u5 _ _ => ((sortedT (Cons (C u3 u5) u6)) = true -> (le u3 u2) = false -> (sortedT (Cons (C u3 u5) (listUpTo u6 u2))) = true, (Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u5)::nil)):: (model_PLAN u6)::nil))::nil))::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u5)::nil)):: (Term id_listUpTo ((model_PLAN u6):: (model_nat u2)::nil))::nil))::nil))::(Term id_true nil)::nil)).
Definition F_367 : type_LF_299:= (fun   u6 u2 u3 u5 _ _ => ((le u3 u2) = false -> (sortedT u6) = true -> (le (timel u6) (time (C u3 u5))) = true -> (sortedT (Cons (C u3 u5) (listUpTo u6 u2))) = true, (Term id_le ((model_nat u3):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_sortedT ((model_PLAN u6)::nil))::(Term id_true nil)::(Term id_le ((Term id_timel ((model_PLAN u6)::nil)):: (Term id_time ((Term id_C ((model_nat u3):: (model_nat u5)::nil))::nil))::nil))::(Term id_true nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u5)::nil)):: (Term id_listUpTo ((model_PLAN u6):: (model_nat u2)::nil))::nil))::nil))::(Term id_true nil)::nil)).
Definition F_370 : type_LF_299:= (fun   u6 u2 u3 u5 _ _ => ((le u3 u2) = false -> (sortedT u6) = true -> (le (timel u6) u3) = true -> (sortedT (Cons (C u3 u5) (listUpTo u6 u2))) = true, (Term id_le ((model_nat u3):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_sortedT ((model_PLAN u6)::nil))::(Term id_true nil)::(Term id_le ((Term id_timel ((model_PLAN u6)::nil)):: (model_nat u3)::nil))::(Term id_true nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u5)::nil)):: (Term id_listUpTo ((model_PLAN u6):: (model_nat u2)::nil))::nil))::nil))::(Term id_true nil)::nil)).
Definition F_402 : type_LF_299:= (fun    _ u2 u3 u5 _ _ => ((le u3 u2) = false -> (sortedT Nil) = true -> (le (timel Nil) u3) = true -> (sortedT (Cons (C u3 u5) Nil)) = true, (Term id_le ((model_nat u3):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_sortedT ((Term id_Nil nil)::nil))::(Term id_true nil)::(Term id_le ((Term id_timel ((Term id_Nil nil)::nil)):: (model_nat u3)::nil))::(Term id_true nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u5)::nil)):: (Term id_Nil nil)::nil))::nil))::(Term id_true nil)::nil)).
Definition F_417 : type_LF_299:= (fun    _ u2 u3 _ _ _ => ((le u3 u2) = false -> (sortedT Nil) = true -> (le (timel Nil) u3) = true -> true = true, (Term id_le ((model_nat u3):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_sortedT ((Term id_Nil nil)::nil))::(Term id_true nil)::(Term id_le ((Term id_timel ((Term id_Nil nil)::nil)):: (model_nat u3)::nil))::(Term id_true nil)::(Term id_true nil)::(Term id_true nil)::nil)).
Definition F_408 : type_LF_299:= (fun   u10 u2 u3 u5 u7 u9 => ((le u3 u2) = false -> (sortedT (Cons (C u7 u9) u10)) = true -> (le (timel (Cons (C u7 u9) u10)) u3) = true -> (le u7 u2) = true -> (sortedT (Cons (C u3 u5) (Cons (C u7 u9) Nil))) = true, (Term id_le ((model_nat u3):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u7):: (model_nat u9)::nil)):: (model_PLAN u10)::nil))::nil))::(Term id_true nil)::(Term id_le ((Term id_timel ((Term id_Cons ((Term id_C ((model_nat u7):: (model_nat u9)::nil)):: (model_PLAN u10)::nil))::nil)):: (model_nat u3)::nil))::(Term id_true nil)::(Term id_le ((model_nat u7):: (model_nat u2)::nil))::(Term id_true nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u5)::nil)):: (Term id_Cons ((Term id_C ((model_nat u7):: (model_nat u9)::nil)):: (Term id_Nil nil)::nil))::nil))::nil))::(Term id_true nil)::nil)).
Definition F_414 : type_LF_299:= (fun   u10 u2 u3 u5 u7 u9 => ((le u3 u2) = false -> (sortedT (Cons (C u7 u9) u10)) = true -> (le (timel (Cons (C u7 u9) u10)) u3) = true -> (le u7 u2) = false -> (sortedT (Cons (C u3 u5) (Cons (C u7 u9) (listUpTo u10 u2)))) = true, (Term id_le ((model_nat u3):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u7):: (model_nat u9)::nil)):: (model_PLAN u10)::nil))::nil))::(Term id_true nil)::(Term id_le ((Term id_timel ((Term id_Cons ((Term id_C ((model_nat u7):: (model_nat u9)::nil)):: (model_PLAN u10)::nil))::nil)):: (model_nat u3)::nil))::(Term id_true nil)::(Term id_le ((model_nat u7):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u5)::nil)):: (Term id_Cons ((Term id_C ((model_nat u7):: (model_nat u9)::nil)):: (Term id_listUpTo ((model_PLAN u10):: (model_nat u2)::nil))::nil))::nil))::nil))::(Term id_true nil)::nil)).
Definition F_420 : type_LF_299:= (fun   u10 u2 u3 u5 u7 u9 => ((le u3 u2) = false -> (sortedT (Cons (C u7 u9) u10)) = true -> (le (time (C u7 u9)) u3) = true -> (le u7 u2) = true -> (sortedT (Cons (C u3 u5) (Cons (C u7 u9) Nil))) = true, (Term id_le ((model_nat u3):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u7):: (model_nat u9)::nil)):: (model_PLAN u10)::nil))::nil))::(Term id_true nil)::(Term id_le ((Term id_time ((Term id_C ((model_nat u7):: (model_nat u9)::nil))::nil)):: (model_nat u3)::nil))::(Term id_true nil)::(Term id_le ((model_nat u7):: (model_nat u2)::nil))::(Term id_true nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u5)::nil)):: (Term id_Cons ((Term id_C ((model_nat u7):: (model_nat u9)::nil)):: (Term id_Nil nil)::nil))::nil))::nil))::(Term id_true nil)::nil)).
Definition F_423 : type_LF_299:= (fun   u10 u2 u3 u5 u7 u9 => ((le u3 u2) = false -> (sortedT (Cons (C u7 u9) u10)) = true -> (le (time (C u7 u9)) u3) = true -> (le u7 u2) = false -> (sortedT (Cons (C u3 u5) (Cons (C u7 u9) (listUpTo u10 u2)))) = true, (Term id_le ((model_nat u3):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u7):: (model_nat u9)::nil)):: (model_PLAN u10)::nil))::nil))::(Term id_true nil)::(Term id_le ((Term id_time ((Term id_C ((model_nat u7):: (model_nat u9)::nil))::nil)):: (model_nat u3)::nil))::(Term id_true nil)::(Term id_le ((model_nat u7):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u5)::nil)):: (Term id_Cons ((Term id_C ((model_nat u7):: (model_nat u9)::nil)):: (Term id_listUpTo ((model_PLAN u10):: (model_nat u2)::nil))::nil))::nil))::nil))::(Term id_true nil)::nil)).
Definition F_426 : type_LF_299:= (fun   u10 u2 u3 u5 u7 u9 => ((le u3 u2) = false -> (sortedT (Cons (C u7 u9) u10)) = true -> (le u7 u3) = true -> (le u7 u2) = true -> (sortedT (Cons (C u3 u5) (Cons (C u7 u9) Nil))) = true, (Term id_le ((model_nat u3):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u7):: (model_nat u9)::nil)):: (model_PLAN u10)::nil))::nil))::(Term id_true nil)::(Term id_le ((model_nat u7):: (model_nat u3)::nil))::(Term id_true nil)::(Term id_le ((model_nat u7):: (model_nat u2)::nil))::(Term id_true nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u5)::nil)):: (Term id_Cons ((Term id_C ((model_nat u7):: (model_nat u9)::nil)):: (Term id_Nil nil)::nil))::nil))::nil))::(Term id_true nil)::nil)).
Definition F_451 : type_LF_299:= (fun   u10 u2 u3 u5 u7 u9 => ((le u3 u2) = false -> (le u7 u3) = true -> (le u7 u2) = true -> (sortedT u10) = true -> (le (timel u10) (time (C u7 u9))) = true -> (sortedT (Cons (C u3 u5) (Cons (C u7 u9) Nil))) = true, (Term id_le ((model_nat u3):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_le ((model_nat u7):: (model_nat u3)::nil))::(Term id_true nil)::(Term id_le ((model_nat u7):: (model_nat u2)::nil))::(Term id_true nil)::(Term id_sortedT ((model_PLAN u10)::nil))::(Term id_true nil)::(Term id_le ((Term id_timel ((model_PLAN u10)::nil)):: (Term id_time ((Term id_C ((model_nat u7):: (model_nat u9)::nil))::nil))::nil))::(Term id_true nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u5)::nil)):: (Term id_Cons ((Term id_C ((model_nat u7):: (model_nat u9)::nil)):: (Term id_Nil nil)::nil))::nil))::nil))::(Term id_true nil)::nil)).
Definition F_429 : type_LF_299:= (fun   u10 u2 u3 u5 u7 u9 => ((le u3 u2) = false -> (sortedT (Cons (C u7 u9) u10)) = true -> (le u7 u3) = true -> (le u7 u2) = false -> (sortedT (Cons (C u3 u5) (Cons (C u7 u9) (listUpTo u10 u2)))) = true, (Term id_le ((model_nat u3):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u7):: (model_nat u9)::nil)):: (model_PLAN u10)::nil))::nil))::(Term id_true nil)::(Term id_le ((model_nat u7):: (model_nat u3)::nil))::(Term id_true nil)::(Term id_le ((model_nat u7):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u5)::nil)):: (Term id_Cons ((Term id_C ((model_nat u7):: (model_nat u9)::nil)):: (Term id_listUpTo ((model_PLAN u10):: (model_nat u2)::nil))::nil))::nil))::nil))::(Term id_true nil)::nil)).
Definition F_476 : type_LF_299:= (fun   u10 u2 u3 u5 u7 u9 => ((le u3 u2) = false -> (le u7 u3) = true -> (le u7 u2) = false -> (sortedT u10) = true -> (le (timel u10) (time (C u7 u9))) = true -> (sortedT (Cons (C u3 u5) (Cons (C u7 u9) (listUpTo u10 u2)))) = true, (Term id_le ((model_nat u3):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_le ((model_nat u7):: (model_nat u3)::nil))::(Term id_true nil)::(Term id_le ((model_nat u7):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_sortedT ((model_PLAN u10)::nil))::(Term id_true nil)::(Term id_le ((Term id_timel ((model_PLAN u10)::nil)):: (Term id_time ((Term id_C ((model_nat u7):: (model_nat u9)::nil))::nil))::nil))::(Term id_true nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u5)::nil)):: (Term id_Cons ((Term id_C ((model_nat u7):: (model_nat u9)::nil)):: (Term id_listUpTo ((model_PLAN u10):: (model_nat u2)::nil))::nil))::nil))::nil))::(Term id_true nil)::nil)).
Definition F_454 : type_LF_299:= (fun   u10 u2 u3 u5 u7 u9 => ((le u3 u2) = false -> (le u7 u3) = true -> (le u7 u2) = true -> (sortedT u10) = true -> (le (timel u10) u7) = true -> (sortedT (Cons (C u3 u5) (Cons (C u7 u9) Nil))) = true, (Term id_le ((model_nat u3):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_le ((model_nat u7):: (model_nat u3)::nil))::(Term id_true nil)::(Term id_le ((model_nat u7):: (model_nat u2)::nil))::(Term id_true nil)::(Term id_sortedT ((model_PLAN u10)::nil))::(Term id_true nil)::(Term id_le ((Term id_timel ((model_PLAN u10)::nil)):: (model_nat u7)::nil))::(Term id_true nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u5)::nil)):: (Term id_Cons ((Term id_C ((model_nat u7):: (model_nat u9)::nil)):: (Term id_Nil nil)::nil))::nil))::nil))::(Term id_true nil)::nil)).
Definition F_532 : type_LF_299:= (fun   u10 u2 u3 u7 u9 _ => ((le u3 u2) = false -> (le u7 u3) = true -> (le u7 u2) = true -> (sortedT u10) = true -> (le (timel u10) u7) = true -> (le u7 u3) = true -> (sortedT (Cons (C u7 u9) Nil)) = true, (Term id_le ((model_nat u3):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_le ((model_nat u7):: (model_nat u3)::nil))::(Term id_true nil)::(Term id_le ((model_nat u7):: (model_nat u2)::nil))::(Term id_true nil)::(Term id_sortedT ((model_PLAN u10)::nil))::(Term id_true nil)::(Term id_le ((Term id_timel ((model_PLAN u10)::nil)):: (model_nat u7)::nil))::(Term id_true nil)::(Term id_le ((model_nat u7):: (model_nat u3)::nil))::(Term id_true nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u7):: (model_nat u9)::nil)):: (Term id_Nil nil)::nil))::nil))::(Term id_true nil)::nil)).
Definition F_539 : type_LF_299:= (fun   u10 u2 u3 u7 _ _ => ((le u3 u2) = false -> (le u7 u3) = true -> (le u7 u2) = true -> (sortedT u10) = true -> (le (timel u10) u7) = true -> (le u7 u3) = true -> true = true, (Term id_le ((model_nat u3):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_le ((model_nat u7):: (model_nat u3)::nil))::(Term id_true nil)::(Term id_le ((model_nat u7):: (model_nat u2)::nil))::(Term id_true nil)::(Term id_sortedT ((model_PLAN u10)::nil))::(Term id_true nil)::(Term id_le ((Term id_timel ((model_PLAN u10)::nil)):: (model_nat u7)::nil))::(Term id_true nil)::(Term id_le ((model_nat u7):: (model_nat u3)::nil))::(Term id_true nil)::(Term id_true nil)::(Term id_true nil)::nil)).
Definition F_536 : type_LF_299:= (fun   u10 u2 u3 u7 _ _ => ((le u3 u2) = false -> (le u7 u3) = true -> (le u7 u2) = true -> (sortedT u10) = true -> (le (timel u10) u7) = true -> (le u7 u3) = false -> false = true, (Term id_le ((model_nat u3):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_le ((model_nat u7):: (model_nat u3)::nil))::(Term id_true nil)::(Term id_le ((model_nat u7):: (model_nat u2)::nil))::(Term id_true nil)::(Term id_sortedT ((model_PLAN u10)::nil))::(Term id_true nil)::(Term id_le ((Term id_timel ((model_PLAN u10)::nil)):: (model_nat u7)::nil))::(Term id_true nil)::(Term id_le ((model_nat u7):: (model_nat u3)::nil))::(Term id_false nil)::(Term id_false nil)::(Term id_true nil)::nil)).
Definition F_479 : type_LF_299:= (fun   u10 u2 u3 u5 u7 u9 => ((le u3 u2) = false -> (le u7 u3) = true -> (le u7 u2) = false -> (sortedT u10) = true -> (le (timel u10) u7) = true -> (sortedT (Cons (C u3 u5) (Cons (C u7 u9) (listUpTo u10 u2)))) = true, (Term id_le ((model_nat u3):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_le ((model_nat u7):: (model_nat u3)::nil))::(Term id_true nil)::(Term id_le ((model_nat u7):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_sortedT ((model_PLAN u10)::nil))::(Term id_true nil)::(Term id_le ((Term id_timel ((model_PLAN u10)::nil)):: (model_nat u7)::nil))::(Term id_true nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u5)::nil)):: (Term id_Cons ((Term id_C ((model_nat u7):: (model_nat u9)::nil)):: (Term id_listUpTo ((model_PLAN u10):: (model_nat u2)::nil))::nil))::nil))::nil))::(Term id_true nil)::nil)).
Definition F_578 : type_LF_299:= (fun   u10 u2 u3 u7 _ _ => ((le u3 u2) = false -> (le u7 u3) = true -> (le u7 u2) = false -> (sortedT u10) = true -> (le (timel u10) u7) = true -> (le u7 u3) = false -> false = true, (Term id_le ((model_nat u3):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_le ((model_nat u7):: (model_nat u3)::nil))::(Term id_true nil)::(Term id_le ((model_nat u7):: (model_nat u2)::nil))::(Term id_false nil)::(Term id_sortedT ((model_PLAN u10)::nil))::(Term id_true nil)::(Term id_le ((Term id_timel ((model_PLAN u10)::nil)):: (model_nat u7)::nil))::(Term id_true nil)::(Term id_le ((model_nat u7):: (model_nat u3)::nil))::(Term id_false nil)::(Term id_false nil)::(Term id_true nil)::nil)).

Definition LF_299 := [F_299, F_330, F_336, F_345, F_342, F_367, F_370, F_402, F_417, F_408, F_414, F_420, F_423, F_426, F_451, F_429, F_476, F_454, F_532, F_539, F_536, F_479, F_578].

Function f_299 (u1: PLAN) (u2: nat) {struct u1} : PLAN :=
 match u1, u2 with
| Nil, _ => Nil
| (Cons (C u3 u5) u6), _ => Nil
end.

Function f_370 (u6: PLAN) (u2: nat) {struct u6} : PLAN :=
 match u6, u2 with
| Nil, _ => Nil
| (Cons (C u7 u9) u10), _ => Nil
end.

Lemma main_299 : forall F, In F LF_299 -> forall u1, forall u2, forall u3, forall u4, forall u5, forall u6, (forall F', In F' LF_299 -> forall e1, forall e2, forall e3, forall e4, forall e5, forall e6, less (snd (F' e1 e2 e3 e4 e5 e6)) (snd (F u1 u2 u3 u4 u5 u6)) -> fst (F' e1 e2 e3 e4 e5 e6)) -> fst (F u1 u2 u3 u4 u5 u6).
Proof.
intros F HF u1 u2 u3 u4 u5 u6; case_In HF; intro Hind.

	(* GENERATE on [ 299 ] *)

rename u1 into _u1. rename u2 into _u2. rename u3 into d_u3. rename u4 into d_u4. rename u5 into d_u5. rename u6 into d_u6.
rename _u1 into u1. rename _u2 into u2.

revert Hind.

pattern u1, u2, (f_299 u1 u2). apply f_299_ind.

(* case [ 330 ] *)

intros _u1 _u2.  intro eq_1. intro. intro Heq2. rewrite <- Heq2.  intro HFabs0.
assert (Hind := HFabs0 F_330). clear HFabs0.
assert (HFabs0 : fst (F_330 Nil 0 0 0 0 0)).
apply Hind. trivial_in 1. unfold snd. unfold F_330. unfold F_299. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_299. unfold F_330.
auto.

intros _u1 _u2. intro u3. intro u5. intro u6.  intro eq_1. intro. intro Heq2. rewrite <- Heq2.  intro HFabs0.
case_eq (le u3 _u2); [intro H | intro H].

(* case [ 336 ] *)

assert (Hind := HFabs0 F_336). clear HFabs0.
assert (HFabs0 : fst (F_336 u6 _u2 u3 u5 0 0)).
apply Hind. trivial_in 2. unfold snd. unfold F_336. unfold F_299. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_299. unfold F_336. simpl in H. repeat(simpl; rewrite H). repeat(simpl in HFabs0; rewrite H in HFabs0). try (auto || (intro H0; contradict H0)).
auto.

(* case [ 342 ] *)

assert (Hind := HFabs0 F_342). clear HFabs0.
assert (HFabs0 : fst (F_342 u6 _u2 u3 u5 0 0)).
apply Hind. trivial_in 4. unfold snd. unfold F_342. unfold F_299. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_299. unfold F_342. simpl in H. repeat(simpl; rewrite H). repeat(simpl in HFabs0; rewrite H in HFabs0). try (auto || (intro H0; contradict H0)).
auto.

	(* TAUTOLOGY on [ 330 ] *)

unfold fst. unfold F_330.
auto.

	(* REWRITING on [ 336 ] *)

rename u1 into _u6. rename u2 into _u2. rename u3 into _u3. rename u4 into _u5. rename u5 into d_u5. rename u6 into d_u6.
rename _u6 into u6. rename _u2 into u2. rename _u3 into u3. rename _u5 into u5.
assert (Res := Hind F_345). clear Hind.
assert (HFabs1 : fst (F_345 u6 u2 u3 u5 0 0)).
apply Res. trivial_in 3. unfold snd. unfold F_345. unfold F_336. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_336. unfold fst in HFabs1. unfold F_345 in HFabs1.
pattern (C u3 u5). simpl (sortedT _). cbv beta.
 simpl. auto.

	(* TAUTOLOGY on [ 345 ] *)

unfold fst. unfold F_345.
auto.

	(* AUGMENTATION on [ 342 ] *)

rename u1 into _u6. rename u2 into _u2. rename u3 into _u3. rename u4 into _u5. rename u5 into d_u5. rename u6 into d_u6.
rename _u6 into u6. rename _u2 into u2. rename _u3 into u3. rename _u5 into u5.
assert (H := Hind F_367). clear Hind.
assert (HFabs0: fst (F_367 u6 u2 u3 u5 0 0)).
apply H. trivial_in 5. unfold snd. unfold F_342. unfold F_367. rewrite_model. abstract solve_rpo_mul.

unfold fst. unfold F_342.

specialize true_254 with (u1 := (C u3 u5)) (u2 := u6).
specialize true_222 with (u1 := (C u3 u5)) (u2 := u6). auto.

	(* REWRITING on [ 367 ] *)

rename u1 into _u6. rename u2 into _u2. rename u3 into _u3. rename u4 into _u5. rename u5 into d_u5. rename u6 into d_u6.
rename _u6 into u6. rename _u2 into u2. rename _u3 into u3. rename _u5 into u5.
assert (Res := Hind F_370). clear Hind.
assert (HFabs1 : fst (F_370 u6 u2 u3 u5 0 0)).
apply Res. trivial_in 6. unfold snd. unfold F_370. unfold F_367. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_367. unfold fst in HFabs1. unfold F_370 in HFabs1.
pattern u3, u5. simpl (time _). cbv beta.
 simpl. auto.

	(* GENERATE on [ 370 ] *)

rename u1 into _u6. rename u2 into _u2. rename u3 into _u3. rename u4 into _u5. rename u5 into d_u5. rename u6 into d_u6.
rename _u6 into u6. rename _u2 into u2. rename _u3 into u3. rename _u5 into u5.

revert Hind.

pattern u6, u2, (f_370 u6 u2). apply f_370_ind.

(* case [ 402 ] *)

intros _u6 _u2.  intro eq_1. intro. intro Heq2. rewrite <- Heq2.  intro HFabs0.
assert (Hind := HFabs0 F_402). clear HFabs0.
assert (HFabs0 : fst (F_402 Nil _u2 u3 u5 0 0)).
apply Hind. trivial_in 7. unfold snd. unfold F_402. unfold F_370. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_370. unfold F_402.
auto.

intros _u6 _u2. intro u7. intro u9. intro u10.  intro eq_1. intro. intro Heq2. rewrite <- Heq2.  intro HFabs0.
case_eq (le u7 _u2); [intro H | intro H].

(* case [ 408 ] *)

assert (Hind := HFabs0 F_408). clear HFabs0.
assert (HFabs0 : fst (F_408 u10 _u2 u3 u5 u7 u9)).
apply Hind. trivial_in 9. unfold snd. unfold F_408. unfold F_370. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_370. unfold F_408. simpl in H. repeat(simpl; rewrite H). repeat(simpl in HFabs0; rewrite H in HFabs0). try (auto || (intro H0; contradict H0)).
auto.

(* case [ 414 ] *)

assert (Hind := HFabs0 F_414). clear HFabs0.
assert (HFabs0 : fst (F_414 u10 _u2 u3 u5 u7 u9)).
apply Hind. trivial_in 10. unfold snd. unfold F_414. unfold F_370. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_370. unfold F_414. simpl in H. repeat(simpl; rewrite H). repeat(simpl in HFabs0; rewrite H in HFabs0). try (auto || (intro H0; contradict H0)).
auto.

	(* REWRITING on [ 402 ] *)

rename u1 into d_u1. rename u2 into _u2. rename u3 into _u3. rename u4 into _u5. rename u5 into d_u5. rename u6 into d_u6.
rename _u2 into u2. rename _u3 into u3. rename _u5 into u5.
assert (Res := Hind F_417). clear Hind.
assert (HFabs1 : fst (F_417 Nil u2 u3 0 0 0)).
apply Res. trivial_in 8. unfold snd. unfold F_417. unfold F_402. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_402. unfold fst in HFabs1. unfold F_417 in HFabs1.
pattern (C u3 u5). simpl (sortedT _). cbv beta.
 simpl. auto.

	(* TAUTOLOGY on [ 417 ] *)

unfold fst. unfold F_417.
auto.

	(* REWRITING on [ 408 ] *)

rename u1 into _u10. rename u2 into _u2. rename u3 into _u3. rename u4 into _u5. rename u5 into _u7. rename u6 into _u9.
rename _u10 into u10. rename _u2 into u2. rename _u3 into u3. rename _u5 into u5. rename _u7 into u7. rename _u9 into u9.
assert (Res := Hind F_420). clear Hind.
assert (HFabs1 : fst (F_420 u10 u2 u3 u5 u7 u9)).
apply Res. trivial_in 11. unfold snd. unfold F_420. unfold F_408. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_408. unfold fst in HFabs1. unfold F_420 in HFabs1.
pattern (C u7 u9), u10. simpl (timel _). cbv beta.
 simpl. auto.

	(* REWRITING on [ 414 ] *)

rename u1 into _u10. rename u2 into _u2. rename u3 into _u3. rename u4 into _u5. rename u5 into _u7. rename u6 into _u9.
rename _u10 into u10. rename _u2 into u2. rename _u3 into u3. rename _u5 into u5. rename _u7 into u7. rename _u9 into u9.
assert (Res := Hind F_423). clear Hind.
assert (HFabs1 : fst (F_423 u10 u2 u3 u5 u7 u9)).
apply Res. trivial_in 12. unfold snd. unfold F_423. unfold F_414. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_414. unfold fst in HFabs1. unfold F_423 in HFabs1.
pattern (C u7 u9), u10. simpl (timel _). cbv beta.
 simpl. auto.

	(* REWRITING on [ 420 ] *)

rename u1 into _u10. rename u2 into _u2. rename u3 into _u3. rename u4 into _u5. rename u5 into _u7. rename u6 into _u9.
rename _u10 into u10. rename _u2 into u2. rename _u3 into u3. rename _u5 into u5. rename _u7 into u7. rename _u9 into u9.
assert (Res := Hind F_426). clear Hind.
assert (HFabs1 : fst (F_426 u10 u2 u3 u5 u7 u9)).
apply Res. trivial_in 13. unfold snd. unfold F_426. unfold F_420. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_420. unfold fst in HFabs1. unfold F_426 in HFabs1.
pattern u7, u9. simpl (time _). cbv beta.
 simpl. auto.

	(* REWRITING on [ 423 ] *)

rename u1 into _u10. rename u2 into _u2. rename u3 into _u3. rename u4 into _u5. rename u5 into _u7. rename u6 into _u9.
rename _u10 into u10. rename _u2 into u2. rename _u3 into u3. rename _u5 into u5. rename _u7 into u7. rename _u9 into u9.
assert (Res := Hind F_429). clear Hind.
assert (HFabs1 : fst (F_429 u10 u2 u3 u5 u7 u9)).
apply Res. trivial_in 15. unfold snd. unfold F_429. unfold F_423. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_423. unfold fst in HFabs1. unfold F_429 in HFabs1.
pattern u7, u9. simpl (time _). cbv beta.
 simpl. auto.

	(* AUGMENTATION on [ 426 ] *)

rename u1 into _u10. rename u2 into _u2. rename u3 into _u3. rename u4 into _u5. rename u5 into _u7. rename u6 into _u9.
rename _u10 into u10. rename _u2 into u2. rename _u3 into u3. rename _u5 into u5. rename _u7 into u7. rename _u9 into u9.
assert (H := Hind F_451). clear Hind.
assert (HFabs0: fst (F_451 u10 u2 u3 u5 u7 u9)).
apply H. trivial_in 14. unfold snd. unfold F_426. unfold F_451. rewrite_model. abstract solve_rpo_mul.

unfold fst. unfold F_426.

specialize true_254 with (u1 := (C u7 u9)) (u2 := u10).
specialize true_222 with (u1 := (C u7 u9)) (u2 := u10). auto.

	(* REWRITING on [ 451 ] *)

rename u1 into _u10. rename u2 into _u2. rename u3 into _u3. rename u4 into _u5. rename u5 into _u7. rename u6 into _u9.
rename _u10 into u10. rename _u2 into u2. rename _u3 into u3. rename _u5 into u5. rename _u7 into u7. rename _u9 into u9.
assert (Res := Hind F_454). clear Hind.
assert (HFabs1 : fst (F_454 u10 u2 u3 u5 u7 u9)).
apply Res. trivial_in 17. unfold snd. unfold F_454. unfold F_451. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_451. unfold fst in HFabs1. unfold F_454 in HFabs1.
pattern u7, u9. simpl (time _). cbv beta.
 simpl. auto.

	(* AUGMENTATION on [ 429 ] *)

rename u1 into _u10. rename u2 into _u2. rename u3 into _u3. rename u4 into _u5. rename u5 into _u7. rename u6 into _u9.
rename _u10 into u10. rename _u2 into u2. rename _u3 into u3. rename _u5 into u5. rename _u7 into u7. rename _u9 into u9.
assert (H := Hind F_476). clear Hind.
assert (HFabs0: fst (F_476 u10 u2 u3 u5 u7 u9)).
apply H. trivial_in 16. unfold snd. unfold F_429. unfold F_476. rewrite_model. abstract solve_rpo_mul.

unfold fst. unfold F_429.

specialize true_254 with (u1 := (C u7 u9)) (u2 := u10).
specialize true_222 with (u1 := (C u7 u9)) (u2 := u10). auto.

	(* REWRITING on [ 476 ] *)

rename u1 into _u10. rename u2 into _u2. rename u3 into _u3. rename u4 into _u5. rename u5 into _u7. rename u6 into _u9.
rename _u10 into u10. rename _u2 into u2. rename _u3 into u3. rename _u5 into u5. rename _u7 into u7. rename _u9 into u9.
assert (Res := Hind F_479). clear Hind.
assert (HFabs1 : fst (F_479 u10 u2 u3 u5 u7 u9)).
apply Res. trivial_in 21. unfold snd. unfold F_479. unfold F_476. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_476. unfold fst in HFabs1. unfold F_479 in HFabs1.
pattern u7, u9. simpl (time _). cbv beta.
 simpl. auto.

	(* TOTAL CASE REWRITING on [ 454 ] *)

rename u1 into _u10. rename u2 into _u2. rename u3 into _u3. rename u4 into _u5. rename u5 into _u7. rename u6 into _u9.
rename _u10 into u10. rename _u2 into u2. rename _u3 into u3. rename _u5 into u5. rename _u7 into u7. rename _u9 into u9.
assert (H: ((le u7 u3) = true) \/ ((le u7 u3) = false)).

destruct ((le u7 u3)); auto.

destruct H as [H|H].

(* rewriting with the axiom [ 109 ] *)

assert (H1 := Hind F_532). clear Hind.
assert (HFabs0 : fst (F_532 u10 u2 u3 u7 u9 0)).
apply H1. trivial_in 18. unfold snd. unfold F_532. unfold F_454. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_454. unfold F_532. unfold fst in HFabs0. unfold F_532 in HFabs0. simpl in HFabs0.
pattern u7.
pattern u3.
pattern u5.
pattern u9.
pattern Nil.
simpl (sortedT _). cbv beta. try unfold sortedT. try rewrite H. try rewrite H0. try unfold sortedT in HFabs0. try rewrite H in HFabs0. try rewrite H0 in HFabs0. auto.

(* rewriting with the axiom [ 110 ] *)

assert (H1 := Hind F_536). clear Hind.
assert (HFabs0 : fst (F_536 u10 u2 u3 u7 0 0)).
apply H1. trivial_in 20. unfold snd. unfold F_536. unfold F_454. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_454. unfold F_536. unfold fst in HFabs0. unfold F_536 in HFabs0. simpl in HFabs0.
pattern u7.
pattern u3.
pattern u5.
pattern u9.
pattern Nil.
simpl (sortedT _). cbv beta. try unfold sortedT. try rewrite H. try rewrite H0. try unfold sortedT in HFabs0. try rewrite H in HFabs0. try rewrite H0 in HFabs0. auto.

	(* REWRITING on [ 532 ] *)

rename u1 into _u10. rename u2 into _u2. rename u3 into _u3. rename u4 into _u7. rename u5 into _u9. rename u6 into d_u6.
rename _u10 into u10. rename _u2 into u2. rename _u3 into u3. rename _u7 into u7. rename _u9 into u9.
assert (Res := Hind F_539). clear Hind.
assert (HFabs1 : fst (F_539 u10 u2 u3 u7 0 0)).
apply Res. trivial_in 19. unfold snd. unfold F_539. unfold F_532. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_532. unfold fst in HFabs1. unfold F_539 in HFabs1.
pattern (C u7 u9). simpl (sortedT _). cbv beta.
 simpl. auto.

	(* TAUTOLOGY on [ 539 ] *)

unfold fst. unfold F_539.
auto.

	(* SUBSUMPTION on [ 536 ] *)

rename u1 into _u10. rename u2 into _u2. rename u3 into _u3. rename u4 into _u7. rename u5 into d_u5. rename u6 into d_u6.
rename _u10 into u10. rename _u2 into u2. rename _u3 into u3. rename _u7 into u7.
unfold fst. unfold F_536. specialize true_182 with (u1 := u7) (u2 := u3). intro L. intros. contradict L. (auto || symmetry; auto).

	(* TOTAL CASE REWRITING on [ 479 ] *)

rename u1 into _u10. rename u2 into _u2. rename u3 into _u3. rename u4 into _u5. rename u5 into _u7. rename u6 into _u9.
rename _u10 into u10. rename _u2 into u2. rename _u3 into u3. rename _u5 into u5. rename _u7 into u7. rename _u9 into u9.
assert (H: ((le u7 u3) = true) \/ ((le u7 u3) = false)).

destruct ((le u7 u3)); auto.

destruct H as [H|H].

(* rewriting with the axiom [ 109 ] *)

assert (H1 := Hind F_370). clear Hind.
assert (HFabs0 : fst (F_370 u10 u2 u7 u9 0 0)).
apply H1. trivial_in 6. unfold snd. unfold F_370. unfold F_479. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_479. unfold F_370. unfold fst in HFabs0. unfold F_370 in HFabs0. simpl in HFabs0.
pattern u7.
pattern u3.
pattern u5.
pattern u9.
pattern (listUpTo u10 u2).
simpl (sortedT _). cbv beta. try unfold sortedT. try rewrite H. try rewrite H0. try unfold sortedT in HFabs0. try rewrite H in HFabs0. try rewrite H0 in HFabs0. auto.

(* rewriting with the axiom [ 110 ] *)

assert (H1 := Hind F_578). clear Hind.
assert (HFabs0 : fst (F_578 u10 u2 u3 u7 0 0)).
apply H1. trivial_in 22. unfold snd. unfold F_578. unfold F_479. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_479. unfold F_578. unfold fst in HFabs0. unfold F_578 in HFabs0. simpl in HFabs0.
pattern u7.
pattern u3.
pattern u5.
pattern u9.
pattern (listUpTo u10 u2).
simpl (sortedT _). cbv beta. try unfold sortedT. try rewrite H. try rewrite H0. try unfold sortedT in HFabs0. try rewrite H in HFabs0. try rewrite H0 in HFabs0. auto.

	(* SUBSUMPTION on [ 578 ] *)

rename u1 into _u10. rename u2 into _u2. rename u3 into _u3. rename u4 into _u7. rename u5 into d_u5. rename u6 into d_u6.
rename _u10 into u10. rename _u2 into u2. rename _u3 into u3. rename _u7 into u7.
unfold fst. unfold F_578. specialize true_182 with (u1 := u7) (u2 := u3). intro L. intros. contradict L. (auto || symmetry; auto).

Qed.

(* the set of all formula instances from the proof *)
Definition S_299 := fun f => exists F, In F LF_299 /\ exists e1, exists e2, exists e3, exists e4, exists e5, exists e6, f = F e1 e2 e3 e4 e5 e6.

Theorem all_true_299: forall F, In F LF_299 -> forall u1: PLAN, forall u2: nat, forall u3: nat, forall u4: nat, forall u5: nat, forall u6: nat, fst (F u1 u2  u3  u4  u5  u6).
Proof.
let n := constr:(6) in
let p := constr:(S(S(n))) in
intros;
let G := fresh "G" in
let x := fresh "x" in
apply wf_subset with (R:=@snd_rpo_mul P Prop max_size) (S:=S_299);
[(* 1 *) apply wf_snd_rpo_mul, prec_wf
|(* 2 *) idtac
|(* 3 *) eexists; split; [ eassumption | idtac]; do_nat n ltac:(eexists); reflexivity
];

intros x G;
do_nat p ltac:(elim G; intro; clear G; intro G);
rewrite G in * |- *; clear G; clear x;
intro G;
apply main_299;
 [assumption | idtac];
intros;
apply G;
 [ idtac | assumption ];
eexists; split;
 [idtac | do_nat n ltac:(eexists); reflexivity];
assumption.
Qed.

Theorem true_299: forall (u1: PLAN) (u2: nat), (sortedT u1) = true -> (sortedT (listUpTo u1 u2)) = true.
Proof.
do 2 intro.
apply (all_true_299 F_299);
 (trivial_in 0) ||
 (repeat constructor).
Qed.