Require Export euclidean__axioms.
Require Export euclidean__defs.
Require Export euclidean__tactics.
Require Export lemma__3__7b.
Require Export lemma__9__5a.
Require Export lemma__9__5b.
Require Export lemma__betweennotequal.
Require Export lemma__collinear4.
Require Export lemma__collinearorder.
Require Export lemma__inequalitysymmetric.
Require Export lemma__ray1.
Require Export lemma__rayimpliescollinear.
Require Export logic.
Definition lemma__9__5 : forall A B C P Q R, (euclidean__axioms.TS P A B C) -> ((euclidean__defs.Out R Q P) -> ((euclidean__axioms.Col A B R) -> (euclidean__axioms.TS Q A B C))).
Proof.
intro A.
intro B.
intro C.
intro P.
intro Q.
intro R.
intro H.
intro H0.
intro H1.
assert (* Cut *) ((euclidean__axioms.BetS R P Q) \/ ((Q = P) \/ (euclidean__axioms.BetS R Q P))) as H2.
- apply (@lemma__ray1.lemma__ray1 R Q P H0).
- assert (* Cut *) (euclidean__axioms.TS Q A B C) as H3.
-- assert (* Cut *) ((euclidean__axioms.nCol C P R) \/ (euclidean__axioms.Col C P R)) as H3.
--- apply (@euclidean__tactics.nCol__or__Col C P R).
--- assert ((euclidean__axioms.nCol C P R) \/ (euclidean__axioms.Col C P R)) as H4 by exact H3.
assert ((euclidean__axioms.nCol C P R) \/ (euclidean__axioms.Col C P R)) as __TmpHyp by exact H4.
destruct __TmpHyp as [H5|H5].
---- assert (* Cut *) (euclidean__axioms.TS Q A B C) as H6.
----- assert ((euclidean__axioms.BetS R P Q) \/ ((Q = P) \/ (euclidean__axioms.BetS R Q P))) as H6 by exact H2.
assert ((euclidean__axioms.BetS R P Q) \/ ((Q = P) \/ (euclidean__axioms.BetS R Q P))) as __TmpHyp0 by exact H6.
destruct __TmpHyp0 as [H7|H7].
------ assert (* Cut *) (~(euclidean__axioms.Col R Q C)) as H8.
------- intro H8.
assert (* Cut *) (euclidean__axioms.Col Q R C) as H9.
-------- assert (* Cut *) ((euclidean__axioms.Col Q R C) /\ ((euclidean__axioms.Col Q C R) /\ ((euclidean__axioms.Col C R Q) /\ ((euclidean__axioms.Col R C Q) /\ (euclidean__axioms.Col C Q R))))) as H9.
--------- apply (@lemma__collinearorder.lemma__collinearorder R Q C H8).
--------- destruct H9 as [H10 H11].
destruct H11 as [H12 H13].
destruct H13 as [H14 H15].
destruct H15 as [H16 H17].
exact H10.
-------- assert (* Cut *) (euclidean__axioms.Col R Q P) as H10.
--------- apply (@lemma__rayimpliescollinear.lemma__rayimpliescollinear R Q P H0).
--------- assert (* Cut *) (euclidean__axioms.Col Q R P) as H11.
---------- assert (* Cut *) ((euclidean__axioms.Col Q R P) /\ ((euclidean__axioms.Col Q P R) /\ ((euclidean__axioms.Col P R Q) /\ ((euclidean__axioms.Col R P Q) /\ (euclidean__axioms.Col P Q R))))) as H11.
----------- apply (@lemma__collinearorder.lemma__collinearorder R Q P H10).
----------- destruct H11 as [H12 H13].
destruct H13 as [H14 H15].
destruct H15 as [H16 H17].
destruct H17 as [H18 H19].
exact H12.
---------- assert (* Cut *) (euclidean__axioms.neq R Q) as H12.
----------- assert (* Cut *) ((euclidean__axioms.neq P Q) /\ ((euclidean__axioms.neq R P) /\ (euclidean__axioms.neq R Q))) as H12.
------------ apply (@lemma__betweennotequal.lemma__betweennotequal R P Q H7).
------------ destruct H12 as [H13 H14].
destruct H14 as [H15 H16].
exact H16.
----------- assert (* Cut *) (euclidean__axioms.neq Q R) as H13.
------------ apply (@lemma__inequalitysymmetric.lemma__inequalitysymmetric R Q H12).
------------ assert (* Cut *) (euclidean__axioms.Col R C P) as H14.
------------- apply (@euclidean__tactics.not__nCol__Col R C P).
--------------intro H14.
apply (@euclidean__tactics.Col__nCol__False R C P H14).
---------------apply (@lemma__collinear4.lemma__collinear4 Q R C P H9 H11 H13).

------------- assert (* Cut *) (euclidean__axioms.Col C P R) as H15.
-------------- assert (* Cut *) ((euclidean__axioms.Col C R P) /\ ((euclidean__axioms.Col C P R) /\ ((euclidean__axioms.Col P R C) /\ ((euclidean__axioms.Col R P C) /\ (euclidean__axioms.Col P C R))))) as H15.
--------------- apply (@lemma__collinearorder.lemma__collinearorder R C P H14).
--------------- destruct H15 as [H16 H17].
destruct H17 as [H18 H19].
destruct H19 as [H20 H21].
destruct H21 as [H22 H23].
exact H18.
-------------- apply (@euclidean__tactics.Col__nCol__False C P R H5 H15).
------- assert (* Cut *) (euclidean__axioms.TS Q A B C) as H9.
-------- apply (@lemma__9__5a.lemma__9__5a A B C P Q R H H7).
---------apply (@euclidean__tactics.nCol__notCol R Q C H8).

--------- exact H1.
-------- exact H9.
------ destruct H7 as [H8|H8].
------- assert (* Cut *) (euclidean__axioms.TS Q A B C) as H9.
-------- apply (@eq__ind__r euclidean__axioms.Point P (fun Q0 => (euclidean__defs.Out R Q0 P) -> (euclidean__axioms.TS Q0 A B C))) with (x := Q).
---------intro H9.
exact H.

--------- exact H8.
--------- exact H0.
-------- exact H9.
------- assert (* Cut *) (euclidean__axioms.TS Q A B C) as H9.
-------- apply (@lemma__9__5b.lemma__9__5b A B C P Q R H H8 H5 H1).
-------- exact H9.
----- exact H6.
---- assert (exists L, (euclidean__axioms.BetS P L C) /\ ((euclidean__axioms.Col A B L) /\ (euclidean__axioms.nCol A B P))) as H6 by exact H.
destruct H6 as [L H7].
destruct H7 as [H8 H9].
destruct H9 as [H10 H11].
assert (* Cut *) (euclidean__axioms.Col R Q P) as H12.
----- apply (@lemma__rayimpliescollinear.lemma__rayimpliescollinear R Q P H0).
----- assert (* Cut *) (euclidean__axioms.Col P C L) as H13.
------ right.
right.
right.
right.
right.
exact H8.
------ assert (* Cut *) (euclidean__axioms.Col C P L) as H14.
------- assert (* Cut *) ((euclidean__axioms.Col C P L) /\ ((euclidean__axioms.Col C L P) /\ ((euclidean__axioms.Col L P C) /\ ((euclidean__axioms.Col P L C) /\ (euclidean__axioms.Col L C P))))) as H14.
-------- apply (@lemma__collinearorder.lemma__collinearorder P C L H13).
-------- destruct H14 as [H15 H16].
destruct H16 as [H17 H18].
destruct H18 as [H19 H20].
destruct H20 as [H21 H22].
exact H15.
------- assert (* Cut *) (euclidean__axioms.neq P C) as H15.
-------- assert (* Cut *) ((euclidean__axioms.neq L C) /\ ((euclidean__axioms.neq P L) /\ (euclidean__axioms.neq P C))) as H15.
--------- apply (@lemma__betweennotequal.lemma__betweennotequal P L C H8).
--------- destruct H15 as [H16 H17].
destruct H17 as [H18 H19].
exact H19.
-------- assert (* Cut *) (euclidean__axioms.neq C P) as H16.
--------- apply (@lemma__inequalitysymmetric.lemma__inequalitysymmetric P C H15).
--------- assert (* Cut *) (euclidean__axioms.Col P L R) as H17.
---------- apply (@euclidean__tactics.not__nCol__Col P L R).
-----------intro H17.
apply (@euclidean__tactics.Col__nCol__False P L R H17).
------------apply (@lemma__collinear4.lemma__collinear4 C P L R H14 H5 H16).

---------- assert (* Cut *) (~(A = B)) as H18.
----------- intro H18.
assert (* Cut *) (euclidean__axioms.Col A B P) as H19.
------------ left.
exact H18.
------------ apply (@euclidean__tactics.Col__nCol__False A B P H11 H19).
----------- assert (* Cut *) (euclidean__axioms.Col B L R) as H19.
------------ apply (@euclidean__tactics.not__nCol__Col B L R).
-------------intro H19.
apply (@euclidean__tactics.Col__nCol__False B L R H19).
--------------apply (@lemma__collinear4.lemma__collinear4 A B L R H10 H1 H18).

------------ assert (* Cut *) (euclidean__axioms.Col L R P) as H20.
------------- assert (* Cut *) ((euclidean__axioms.Col L P R) /\ ((euclidean__axioms.Col L R P) /\ ((euclidean__axioms.Col R P L) /\ ((euclidean__axioms.Col P R L) /\ (euclidean__axioms.Col R L P))))) as H20.
-------------- apply (@lemma__collinearorder.lemma__collinearorder P L R H17).
-------------- destruct H20 as [H21 H22].
destruct H22 as [H23 H24].
destruct H24 as [H25 H26].
destruct H26 as [H27 H28].
exact H23.
------------- assert (* Cut *) (euclidean__axioms.Col L R B) as H21.
-------------- assert (* Cut *) ((euclidean__axioms.Col L B R) /\ ((euclidean__axioms.Col L R B) /\ ((euclidean__axioms.Col R B L) /\ ((euclidean__axioms.Col B R L) /\ (euclidean__axioms.Col R L B))))) as H21.
--------------- apply (@lemma__collinearorder.lemma__collinearorder B L R H19).
--------------- destruct H21 as [H22 H23].
destruct H23 as [H24 H25].
destruct H25 as [H26 H27].
destruct H27 as [H28 H29].
exact H24.
-------------- assert (* Cut *) (~(euclidean__axioms.neq L R)) as H22.
--------------- intro H22.
assert (* Cut *) (euclidean__axioms.Col R P B) as H23.
---------------- apply (@euclidean__tactics.not__nCol__Col R P B).
-----------------intro H23.
apply (@euclidean__tactics.Col__nCol__False R P B H23).
------------------apply (@lemma__collinear4.lemma__collinear4 L R P B H20 H21 H22).

---------------- assert (* Cut *) (euclidean__axioms.Col R B P) as H24.
----------------- assert (* Cut *) ((euclidean__axioms.Col P R B) /\ ((euclidean__axioms.Col P B R) /\ ((euclidean__axioms.Col B R P) /\ ((euclidean__axioms.Col R B P) /\ (euclidean__axioms.Col B P R))))) as H24.
------------------ apply (@lemma__collinearorder.lemma__collinearorder R P B H23).
------------------ destruct H24 as [H25 H26].
destruct H26 as [H27 H28].
destruct H28 as [H29 H30].
destruct H30 as [H31 H32].
exact H31.
----------------- assert (* Cut *) (euclidean__axioms.Col R B A) as H25.
------------------ assert (* Cut *) ((euclidean__axioms.Col B A R) /\ ((euclidean__axioms.Col B R A) /\ ((euclidean__axioms.Col R A B) /\ ((euclidean__axioms.Col A R B) /\ (euclidean__axioms.Col R B A))))) as H25.
------------------- apply (@lemma__collinearorder.lemma__collinearorder A B R H1).
------------------- destruct H25 as [H26 H27].
destruct H27 as [H28 H29].
destruct H29 as [H30 H31].
destruct H31 as [H32 H33].
exact H33.
------------------ assert (* Cut *) (~(euclidean__axioms.neq R B)) as H26.
------------------- intro H26.
assert (* Cut *) (euclidean__axioms.Col B P A) as H27.
-------------------- apply (@euclidean__tactics.not__nCol__Col B P A).
---------------------intro H27.
apply (@euclidean__tactics.Col__nCol__False B P A H27).
----------------------apply (@lemma__collinear4.lemma__collinear4 R B P A H24 H25 H26).

-------------------- assert (* Cut *) (euclidean__axioms.Col A B P) as H28.
--------------------- assert (* Cut *) ((euclidean__axioms.Col P B A) /\ ((euclidean__axioms.Col P A B) /\ ((euclidean__axioms.Col A B P) /\ ((euclidean__axioms.Col B A P) /\ (euclidean__axioms.Col A P B))))) as H28.
---------------------- apply (@lemma__collinearorder.lemma__collinearorder B P A H27).
---------------------- destruct H28 as [H29 H30].
destruct H30 as [H31 H32].
destruct H32 as [H33 H34].
destruct H34 as [H35 H36].
exact H33.
--------------------- apply (@euclidean__tactics.Col__nCol__False A B P H11 H28).
------------------- assert (* Cut *) (euclidean__axioms.neq B A) as H27.
-------------------- apply (@lemma__inequalitysymmetric.lemma__inequalitysymmetric A B H18).
-------------------- assert (* Cut *) (euclidean__axioms.neq R A) as H28.
--------------------- assert (* Cut *) (R = B) as H28.
---------------------- apply (@euclidean__tactics.NNPP (R = B) H26).
---------------------- intro H29.
assert (* Cut *) (A = B) as Heq.
----------------------- apply (@logic.eq__trans Point A R B).
------------------------apply (@logic.eq__sym Point R A H29).

------------------------ exact H28.
----------------------- assert False.
------------------------apply (@H18 Heq).
------------------------ contradiction.
--------------------- assert (* Cut *) (euclidean__axioms.Col B A R) as H29.
---------------------- assert (* Cut *) ((euclidean__axioms.Col B R A) /\ ((euclidean__axioms.Col B A R) /\ ((euclidean__axioms.Col A R B) /\ ((euclidean__axioms.Col R A B) /\ (euclidean__axioms.Col A B R))))) as H29.
----------------------- apply (@lemma__collinearorder.lemma__collinearorder R B A H25).
----------------------- destruct H29 as [H30 H31].
destruct H31 as [H32 H33].
destruct H33 as [H34 H35].
destruct H35 as [H36 H37].
exact H32.
---------------------- assert (* Cut *) (euclidean__axioms.Col B A L) as H30.
----------------------- assert (* Cut *) ((euclidean__axioms.Col B A L) /\ ((euclidean__axioms.Col B L A) /\ ((euclidean__axioms.Col L A B) /\ ((euclidean__axioms.Col A L B) /\ (euclidean__axioms.Col L B A))))) as H30.
------------------------ apply (@lemma__collinearorder.lemma__collinearorder A B L H10).
------------------------ destruct H30 as [H31 H32].
destruct H32 as [H33 H34].
destruct H34 as [H35 H36].
destruct H36 as [H37 H38].
exact H31.
----------------------- assert (* Cut *) (euclidean__axioms.Col A L R) as H31.
------------------------ apply (@euclidean__tactics.not__nCol__Col A L R).
-------------------------intro H31.
apply (@euclidean__tactics.Col__nCol__False A L R H31).
--------------------------apply (@lemma__collinear4.lemma__collinear4 B A L R H30 H29 H27).

------------------------ assert (* Cut *) (euclidean__axioms.Col L R A) as H32.
------------------------- assert (* Cut *) ((euclidean__axioms.Col L A R) /\ ((euclidean__axioms.Col L R A) /\ ((euclidean__axioms.Col R A L) /\ ((euclidean__axioms.Col A R L) /\ (euclidean__axioms.Col R L A))))) as H32.
-------------------------- apply (@lemma__collinearorder.lemma__collinearorder A L R H31).
-------------------------- destruct H32 as [H33 H34].
destruct H34 as [H35 H36].
destruct H36 as [H37 H38].
destruct H38 as [H39 H40].
exact H35.
------------------------- assert (* Cut *) (euclidean__axioms.Col R P A) as H33.
-------------------------- apply (@euclidean__tactics.not__nCol__Col R P A).
---------------------------intro H33.
apply (@euclidean__tactics.Col__nCol__False R P A H33).
----------------------------apply (@lemma__collinear4.lemma__collinear4 L R P A H20 H32 H22).

-------------------------- assert (* Cut *) (euclidean__axioms.Col R A P) as H34.
--------------------------- assert (* Cut *) ((euclidean__axioms.Col P R A) /\ ((euclidean__axioms.Col P A R) /\ ((euclidean__axioms.Col A R P) /\ ((euclidean__axioms.Col R A P) /\ (euclidean__axioms.Col A P R))))) as H34.
---------------------------- apply (@lemma__collinearorder.lemma__collinearorder R P A H33).
---------------------------- destruct H34 as [H35 H36].
destruct H36 as [H37 H38].
destruct H38 as [H39 H40].
destruct H40 as [H41 H42].
exact H41.
--------------------------- assert (* Cut *) (euclidean__axioms.Col R A B) as H35.
---------------------------- assert (* Cut *) ((euclidean__axioms.Col A B R) /\ ((euclidean__axioms.Col A R B) /\ ((euclidean__axioms.Col R B A) /\ ((euclidean__axioms.Col B R A) /\ (euclidean__axioms.Col R A B))))) as H35.
----------------------------- apply (@lemma__collinearorder.lemma__collinearorder B A R H29).
----------------------------- destruct H35 as [H36 H37].
destruct H37 as [H38 H39].
destruct H39 as [H40 H41].
destruct H41 as [H42 H43].
exact H43.
---------------------------- assert (* Cut *) (euclidean__axioms.Col A P B) as H36.
----------------------------- apply (@euclidean__tactics.not__nCol__Col A P B).
------------------------------intro H36.
apply (@euclidean__tactics.Col__nCol__False A P B H36).
-------------------------------apply (@lemma__collinear4.lemma__collinear4 R A P B H34 H35 H28).

----------------------------- assert (* Cut *) (euclidean__axioms.Col A B P) as H37.
------------------------------ assert (* Cut *) ((euclidean__axioms.Col P A B) /\ ((euclidean__axioms.Col P B A) /\ ((euclidean__axioms.Col B A P) /\ ((euclidean__axioms.Col A B P) /\ (euclidean__axioms.Col B P A))))) as H37.
------------------------------- apply (@lemma__collinearorder.lemma__collinearorder A P B H36).
------------------------------- destruct H37 as [H38 H39].
destruct H39 as [H40 H41].
destruct H41 as [H42 H43].
destruct H43 as [H44 H45].
exact H44.
------------------------------ apply (@euclidean__tactics.Col__nCol__False A B P H11 H37).
--------------- assert (* Cut *) (euclidean__axioms.BetS P R C) as H23.
---------------- apply (@eq__ind euclidean__axioms.Point L (fun X => euclidean__axioms.BetS P X C)) with (y := R).
----------------- exact H8.
-----------------apply (@euclidean__tactics.NNPP (L = R) H22).

---------------- assert (* Cut *) (euclidean__axioms.BetS C R P) as H24.
----------------- apply (@euclidean__axioms.axiom__betweennesssymmetry P R C H23).
----------------- assert (* Cut *) (euclidean__axioms.BetS C R Q) as H25.
------------------ assert ((euclidean__axioms.BetS R P Q) \/ ((Q = P) \/ (euclidean__axioms.BetS R Q P))) as H25 by exact H2.
assert ((euclidean__axioms.BetS R P Q) \/ ((Q = P) \/ (euclidean__axioms.BetS R Q P))) as __TmpHyp0 by exact H25.
destruct __TmpHyp0 as [H26|H26].
------------------- assert (* Cut *) (euclidean__axioms.BetS C R Q) as H27.
-------------------- apply (@lemma__3__7b.lemma__3__7b C R P Q H24 H26).
-------------------- exact H27.
------------------- destruct H26 as [H27|H27].
-------------------- assert (* Cut *) (euclidean__axioms.BetS C R Q) as H28.
--------------------- apply (@eq__ind__r euclidean__axioms.Point P (fun Q0 => (euclidean__defs.Out R Q0 P) -> ((euclidean__axioms.Col R Q0 P) -> (euclidean__axioms.BetS C R Q0)))) with (x := Q).
----------------------intro H28.
intro H29.
exact H24.

---------------------- exact H27.
---------------------- exact H0.
---------------------- exact H12.
--------------------- exact H28.
-------------------- assert (* Cut *) (euclidean__axioms.BetS C R Q) as H28.
--------------------- apply (@euclidean__axioms.axiom__innertransitivity C R Q P H24 H27).
--------------------- exact H28.
------------------ assert (* Cut *) (euclidean__axioms.BetS Q R C) as H26.
------------------- apply (@euclidean__axioms.axiom__betweennesssymmetry C R Q H25).
------------------- assert (* Cut *) (~(euclidean__axioms.Col A B Q)) as H27.
-------------------- intro H27.
assert (* Cut *) (euclidean__axioms.Col Q R C) as H28.
--------------------- right.
right.
right.
right.
left.
exact H26.
--------------------- assert (* Cut *) (euclidean__axioms.Col B Q R) as H29.
---------------------- apply (@euclidean__tactics.not__nCol__Col B Q R).
-----------------------intro H29.
apply (@euclidean__tactics.Col__nCol__False B Q R H29).
------------------------apply (@lemma__collinear4.lemma__collinear4 A B Q R H27 H1 H18).

---------------------- assert (* Cut *) (euclidean__axioms.Col R B Q) as H30.
----------------------- assert (* Cut *) ((euclidean__axioms.Col Q B R) /\ ((euclidean__axioms.Col Q R B) /\ ((euclidean__axioms.Col R B Q) /\ ((euclidean__axioms.Col B R Q) /\ (euclidean__axioms.Col R Q B))))) as H30.
------------------------ apply (@lemma__collinearorder.lemma__collinearorder B Q R H29).
------------------------ destruct H30 as [H31 H32].
destruct H32 as [H33 H34].
destruct H34 as [H35 H36].
destruct H36 as [H37 H38].
exact H35.
----------------------- assert (euclidean__axioms.Col R Q P) as H31 by exact H12.
assert (* Cut *) (euclidean__axioms.Col Q R B) as H32.
------------------------ assert (* Cut *) ((euclidean__axioms.Col B R Q) /\ ((euclidean__axioms.Col B Q R) /\ ((euclidean__axioms.Col Q R B) /\ ((euclidean__axioms.Col R Q B) /\ (euclidean__axioms.Col Q B R))))) as H32.
------------------------- apply (@lemma__collinearorder.lemma__collinearorder R B Q H30).
------------------------- destruct H32 as [H33 H34].
destruct H34 as [H35 H36].
destruct H36 as [H37 H38].
destruct H38 as [H39 H40].
exact H37.
------------------------ assert (* Cut *) (euclidean__axioms.Col Q R P) as H33.
------------------------- assert (* Cut *) ((euclidean__axioms.Col Q R P) /\ ((euclidean__axioms.Col Q P R) /\ ((euclidean__axioms.Col P R Q) /\ ((euclidean__axioms.Col R P Q) /\ (euclidean__axioms.Col P Q R))))) as H33.
-------------------------- apply (@lemma__collinearorder.lemma__collinearorder R Q P H31).
-------------------------- destruct H33 as [H34 H35].
destruct H35 as [H36 H37].
destruct H37 as [H38 H39].
destruct H39 as [H40 H41].
exact H34.
------------------------- assert (* Cut *) (euclidean__axioms.neq Q R) as H34.
-------------------------- assert (* Cut *) ((euclidean__axioms.neq R C) /\ ((euclidean__axioms.neq Q R) /\ (euclidean__axioms.neq Q C))) as H34.
--------------------------- apply (@lemma__betweennotequal.lemma__betweennotequal Q R C H26).
--------------------------- destruct H34 as [H35 H36].
destruct H36 as [H37 H38].
exact H37.
-------------------------- assert (* Cut *) (euclidean__axioms.Col R B P) as H35.
--------------------------- apply (@euclidean__tactics.not__nCol__Col R B P).
----------------------------intro H35.
apply (@euclidean__tactics.Col__nCol__False R B P H35).
-----------------------------apply (@lemma__collinear4.lemma__collinear4 Q R B P H32 H33 H34).

--------------------------- assert (* Cut *) (euclidean__axioms.Col R B A) as H36.
---------------------------- assert (* Cut *) ((euclidean__axioms.Col B A R) /\ ((euclidean__axioms.Col B R A) /\ ((euclidean__axioms.Col R A B) /\ ((euclidean__axioms.Col A R B) /\ (euclidean__axioms.Col R B A))))) as H36.
----------------------------- apply (@lemma__collinearorder.lemma__collinearorder A B R H1).
----------------------------- destruct H36 as [H37 H38].
destruct H38 as [H39 H40].
destruct H40 as [H41 H42].
destruct H42 as [H43 H44].
exact H44.
---------------------------- assert (* Cut *) (~(euclidean__axioms.neq R B)) as H37.
----------------------------- intro H37.
assert (* Cut *) (euclidean__axioms.Col B P A) as H38.
------------------------------ apply (@euclidean__tactics.not__nCol__Col B P A).
-------------------------------intro H38.
apply (@euclidean__tactics.Col__nCol__False B P A H38).
--------------------------------apply (@lemma__collinear4.lemma__collinear4 R B P A H35 H36 H37).

------------------------------ assert (* Cut *) (euclidean__axioms.Col A B P) as H39.
------------------------------- assert (* Cut *) ((euclidean__axioms.Col P B A) /\ ((euclidean__axioms.Col P A B) /\ ((euclidean__axioms.Col A B P) /\ ((euclidean__axioms.Col B A P) /\ (euclidean__axioms.Col A P B))))) as H39.
-------------------------------- apply (@lemma__collinearorder.lemma__collinearorder B P A H38).
-------------------------------- destruct H39 as [H40 H41].
destruct H41 as [H42 H43].
destruct H43 as [H44 H45].
destruct H45 as [H46 H47].
exact H44.
------------------------------- apply (@euclidean__tactics.Col__nCol__False A B P H11 H39).
----------------------------- assert (* Cut *) (euclidean__axioms.neq B A) as H38.
------------------------------ apply (@lemma__inequalitysymmetric.lemma__inequalitysymmetric A B H18).
------------------------------ assert (* Cut *) (euclidean__axioms.neq R A) as H39.
------------------------------- assert (* Cut *) (R = B) as H39.
-------------------------------- apply (@euclidean__tactics.NNPP (R = B) H37).
-------------------------------- assert (* Cut *) (L = R) as H40.
--------------------------------- apply (@euclidean__tactics.NNPP (L = R) H22).
--------------------------------- intro H41.
assert (* Cut *) (A = B) as Heq.
---------------------------------- apply (@logic.eq__trans Point A R B).
-----------------------------------apply (@logic.eq__sym Point R A H41).

----------------------------------- exact H39.
---------------------------------- assert False.
-----------------------------------apply (@H18 Heq).
----------------------------------- contradiction.
------------------------------- assert (* Cut *) (euclidean__axioms.Col B A R) as H40.
-------------------------------- assert (* Cut *) ((euclidean__axioms.Col B R A) /\ ((euclidean__axioms.Col B A R) /\ ((euclidean__axioms.Col A R B) /\ ((euclidean__axioms.Col R A B) /\ (euclidean__axioms.Col A B R))))) as H40.
--------------------------------- apply (@lemma__collinearorder.lemma__collinearorder R B A H36).
--------------------------------- destruct H40 as [H41 H42].
destruct H42 as [H43 H44].
destruct H44 as [H45 H46].
destruct H46 as [H47 H48].
exact H43.
-------------------------------- assert (* Cut *) (euclidean__axioms.Col B A Q) as H41.
--------------------------------- assert (* Cut *) ((euclidean__axioms.Col B A Q) /\ ((euclidean__axioms.Col B Q A) /\ ((euclidean__axioms.Col Q A B) /\ ((euclidean__axioms.Col A Q B) /\ (euclidean__axioms.Col Q B A))))) as H41.
---------------------------------- apply (@lemma__collinearorder.lemma__collinearorder A B Q H27).
---------------------------------- destruct H41 as [H42 H43].
destruct H43 as [H44 H45].
destruct H45 as [H46 H47].
destruct H47 as [H48 H49].
exact H42.
--------------------------------- assert (euclidean__axioms.neq B A) as H42 by exact H38.
assert (* Cut *) (euclidean__axioms.Col A Q R) as H43.
---------------------------------- apply (@euclidean__tactics.not__nCol__Col A Q R).
-----------------------------------intro H43.
apply (@euclidean__tactics.Col__nCol__False A Q R H43).
------------------------------------apply (@lemma__collinear4.lemma__collinear4 B A Q R H41 H40 H42).

---------------------------------- assert (* Cut *) (euclidean__axioms.Col R A Q) as H44.
----------------------------------- assert (* Cut *) ((euclidean__axioms.Col Q A R) /\ ((euclidean__axioms.Col Q R A) /\ ((euclidean__axioms.Col R A Q) /\ ((euclidean__axioms.Col A R Q) /\ (euclidean__axioms.Col R Q A))))) as H44.
------------------------------------ apply (@lemma__collinearorder.lemma__collinearorder A Q R H43).
------------------------------------ destruct H44 as [H45 H46].
destruct H46 as [H47 H48].
destruct H48 as [H49 H50].
destruct H50 as [H51 H52].
exact H49.
----------------------------------- assert (* Cut *) (euclidean__axioms.Col Q R A) as H45.
------------------------------------ assert (* Cut *) ((euclidean__axioms.Col A R Q) /\ ((euclidean__axioms.Col A Q R) /\ ((euclidean__axioms.Col Q R A) /\ ((euclidean__axioms.Col R Q A) /\ (euclidean__axioms.Col Q A R))))) as H45.
------------------------------------- apply (@lemma__collinearorder.lemma__collinearorder R A Q H44).
------------------------------------- destruct H45 as [H46 H47].
destruct H47 as [H48 H49].
destruct H49 as [H50 H51].
destruct H51 as [H52 H53].
exact H50.
------------------------------------ assert (* Cut *) (euclidean__axioms.Col R A P) as H46.
------------------------------------- apply (@euclidean__tactics.not__nCol__Col R A P).
--------------------------------------intro H46.
apply (@euclidean__tactics.Col__nCol__False R A P H46).
---------------------------------------apply (@lemma__collinear4.lemma__collinear4 Q R A P H45 H33 H34).

------------------------------------- assert (* Cut *) (euclidean__axioms.Col R A B) as H47.
-------------------------------------- assert (* Cut *) ((euclidean__axioms.Col A B R) /\ ((euclidean__axioms.Col A R B) /\ ((euclidean__axioms.Col R B A) /\ ((euclidean__axioms.Col B R A) /\ (euclidean__axioms.Col R A B))))) as H47.
--------------------------------------- apply (@lemma__collinearorder.lemma__collinearorder B A R H40).
--------------------------------------- destruct H47 as [H48 H49].
destruct H49 as [H50 H51].
destruct H51 as [H52 H53].
destruct H53 as [H54 H55].
exact H55.
-------------------------------------- assert (* Cut *) (euclidean__axioms.Col A P B) as H48.
--------------------------------------- apply (@euclidean__tactics.not__nCol__Col A P B).
----------------------------------------intro H48.
apply (@euclidean__tactics.Col__nCol__False A P B H48).
-----------------------------------------apply (@lemma__collinear4.lemma__collinear4 R A P B H46 H47 H39).

--------------------------------------- assert (* Cut *) (euclidean__axioms.Col A B P) as H49.
---------------------------------------- assert (* Cut *) ((euclidean__axioms.Col P A B) /\ ((euclidean__axioms.Col P B A) /\ ((euclidean__axioms.Col B A P) /\ ((euclidean__axioms.Col A B P) /\ (euclidean__axioms.Col B P A))))) as H49.
----------------------------------------- apply (@lemma__collinearorder.lemma__collinearorder A P B H48).
----------------------------------------- destruct H49 as [H50 H51].
destruct H51 as [H52 H53].
destruct H53 as [H54 H55].
destruct H55 as [H56 H57].
exact H56.
---------------------------------------- apply (@euclidean__tactics.Col__nCol__False A B P H11 H49).
-------------------- assert (* Cut *) (euclidean__axioms.TS Q A B C) as H28.
--------------------- exists R.
split.
---------------------- exact H26.
---------------------- split.
----------------------- exact H1.
----------------------- apply (@euclidean__tactics.nCol__notCol A B Q H27).
--------------------- exact H28.
-- exact H3.
Qed.


From Coq Require Import ssreflect ssrfun ssrbool.

Require Import Setoid.
From Coq Require Import Unicode.Utf8.
From Coq.Logic Require Import Classical_Prop FunctionalExtensionality.
From Coq.Classes Require Import Morphisms_Prop.

From stdpp Require Import base sets.

From MatchingLogic Require Import
    Logic
    Utils.extralibrary
    Theories.Definedness_Syntax
    Theories.Definedness_Semantics
    Theories.Sorts_Syntax.

Import MatchingLogic.Logic.Notations.
Import MatchingLogic.DerivedOperators_Syntax.Notations.
Import MatchingLogic.Semantics.Notations.

Section with_model.
    Context
      {Σ : Signature}
      {syntax : Sorts_Syntax.Syntax}
      {M : Model}.
    Open Scope ml_scope.
    Hypothesis M_satisfies_theory : M ⊨ᵀ Definedness_Syntax.theory.

    Local Definition sym (s : Symbols) : Pattern :=
      patt_sym (inj s).

    Definition Mpatt_inhabitant_set m := app_ext (sym_interp M (inj inhabitant)) {[m]}.

    (* ϕ is expected to be a sort pattern *)
    Definition Minterp_inhabitant (ϕ : Pattern) (ρ : Valuation)
      := @eval Σ M ρ (patt_app (sym inhabitant) ϕ).

    Lemma eval_forall_of_sort_predicate s ϕ ρ:
      let x := fresh_evar ϕ in
      M_predicate M (ϕ^{evar: 0 ↦ x}) ->
      eval ρ (patt_forall_of_sort s ϕ) = ⊤
      <-> (∀ m : Domain M, m ∈ Minterp_inhabitant s ρ ->
                           eval (update_evar_val x m ρ) (ϕ^{evar: 0 ↦ x}) = ⊤).
    Proof.
      intros x Hpred.
      unfold patt_forall_of_sort.
      assert (Hsub: is_subformula_of_ind ϕ (patt_in b0 (patt_inhabitant_set (nest_ex s)) ---> ϕ)).
      { apply sub_imp_r. apply sub_eq. reflexivity.  }
      rewrite eval_forall_predicate.
      {
        mlSimpl. simpl.
        apply M_predicate_impl.
        - apply T_predicate_in.
          apply M_satisfies_theory.
        - subst x.
          apply M_predicate_evar_open_fresh_evar_2.
          2: apply Hpred.
          eapply evar_fresh_in_subformula. apply Hsub. apply set_evar_fresh_is_fresh.
      }
      subst x.
      remember (patt_in b0 (patt_inhabitant_set (nest_ex s)) ---> ϕ) as Bigϕ.
      assert (Hfresh: fresh_evar Bigϕ ∉ free_evars (patt_sym (inj inhabitant) $ (nest_ex s))).
      { rewrite HeqBigϕ.
        unfold patt_inhabitant_set.
        fold (evar_is_fresh_in (fresh_evar (patt_in b0 (sym inhabitant $ s) ---> ϕ)) (patt_sym (inj inhabitant) $ s)).
        unfold sym.
        eapply evar_fresh_in_subformula.
        2: apply set_evar_fresh_is_fresh.
        (* TODO automation *)
        apply sub_imp_l. unfold patt_in. unfold patt_defined.
        apply sub_app_r. unfold patt_and.
        unfold patt_not. unfold patt_or.
        apply sub_imp_l. apply sub_imp_r.
        apply sub_imp_l. apply sub_eq. reflexivity.
      }

      remember (patt_in b0 (patt_inhabitant_set s) ---> ϕ) as Bigϕ'.
      assert (HfreeBigϕ: free_evars Bigϕ = free_evars Bigϕ').
      { subst. simpl. unfold nest_ex. rewrite free_evars_nest_ex_aux. reflexivity. }
      assert (HfreshBigϕ: fresh_evar Bigϕ = fresh_evar Bigϕ').
      { unfold fresh_evar. rewrite HfreeBigϕ. reflexivity. }
      clear HfreeBigϕ.

      assert (Hfrs: evar_is_fresh_in (fresh_evar Bigϕ) s).
      { unfold evar_is_fresh_in.
        rewrite HfreshBigϕ. fold (evar_is_fresh_in (fresh_evar Bigϕ') s).
        eapply evar_fresh_in_subformula'. 2: apply set_evar_fresh_is_fresh.
        rewrite HeqBigϕ'. simpl. rewrite is_subformula_of_refl. simpl.
        rewrite !orb_true_r. auto.
      }

      split.
      - intros H m H'.
        specialize (H m).
        (*rewrite -eval_fresh_evar_subterm.*)
        rewrite -(eval_fresh_evar_subterm _ Bigϕ).
        rewrite HeqBigϕ in H.
        mlSimpl in H.
        rewrite -HeqBigϕ in H.
        assumption.
        rewrite {3}HeqBigϕ in H.
        eapply eval_impl_MP.
        apply H.
        simpl. fold evar_open.

        unfold Minterp_inhabitant in H'.
        pose proof (Hfeip := free_evar_in_patt M M_satisfies_theory (fresh_evar Bigϕ) (patt_sym (inj inhabitant) $ (nest_ex s)^{evar: 0 ↦ (fresh_evar Bigϕ)}) (update_evar_val (fresh_evar Bigϕ) m ρ)).
        destruct Hfeip as [Hfeip1 _]. apply Hfeip1. clear Hfeip1.
        rewrite update_evar_val_same.
        clear H. unfold sym in H'.
        unfold Ensembles.In.

        rewrite eval_app_simpl.
        unfold evar_open. rewrite nest_ex_same.
        rewrite eval_sym_simpl.

        rewrite eval_app_simpl in H'.
        rewrite eval_sym_simpl in H'.
        rewrite eval_free_evar_independent.
        {
          solve_free_evars_inclusion 5.
        }
        apply H'.

      - intros H m.
        pose proof (Hfeip := free_evar_in_patt  M M_satisfies_theory (fresh_evar Bigϕ) (patt_sym (inj inhabitant) $ (nest_ex s)^{evar: 0 ↦ (fresh_evar Bigϕ)}) (update_evar_val (fresh_evar Bigϕ) m ρ)).
        destruct Hfeip as [_ Hfeip2].
        rewrite {3}HeqBigϕ.
        unfold evar_open. mlSimpl. simpl.
        apply eval_predicate_impl.
        apply T_predicate_in. apply M_satisfies_theory.
        intros H1.
        specialize (Hfeip2 H1). clear H1.
        specialize (H m).
        rewrite -(eval_fresh_evar_subterm _ Bigϕ) in H.
        apply Hsub. apply H. clear H.

        unfold Minterp_inhabitant.
        unfold Ensembles.In in Hfeip2. unfold sym.

        rewrite eval_app_simpl in Hfeip2.
        unfold evar_open in Hfeip2. rewrite nest_ex_same in Hfeip2.
        rewrite eval_sym_simpl in Hfeip2.

        rewrite eval_app_simpl.
        rewrite eval_sym_simpl.
        rewrite update_evar_val_same in Hfeip2.
        rewrite eval_free_evar_independent in Hfeip2.
        {
          solve_free_evars_inclusion 5.
        }
        apply Hfeip2.
    Qed.

    Lemma eval_exists_of_sort_predicate s ϕ ρ:
      let x := fresh_evar ϕ in
      M_predicate M (ϕ^{evar: 0 ↦ x}) ->
      eval ρ (patt_exists_of_sort s ϕ) = ⊤
      <-> (∃ m : Domain M, m ∈ Minterp_inhabitant s ρ /\
                           eval (update_evar_val x m ρ) (ϕ^{evar: 0 ↦ x}) = ⊤).
    Proof.
      intros x Hpred.
      unfold patt_exists_of_sort.
      assert (Hsub: is_subformula_of_ind ϕ (patt_in b0 (patt_inhabitant_set (nest_ex s)) and ϕ)).
      { unfold patt_and. unfold patt_or.  apply sub_imp_l. apply sub_imp_r. apply sub_imp_l. apply sub_eq. reflexivity. }
      rewrite eval_exists_predicate_full.
      {
        unfold evar_open. mlSimpl. simpl.
        apply M_predicate_and.
        - apply T_predicate_in.
          apply M_satisfies_theory.
        - subst x.
          apply M_predicate_evar_open_fresh_evar_2.
          2: apply Hpred.
          eapply evar_fresh_in_subformula. apply Hsub. apply set_evar_fresh_is_fresh.
      }
      subst x.
      remember (patt_in b0 (patt_inhabitant_set (nest_ex s)) and ϕ) as Bigϕ.
      assert (Hfresh: fresh_evar Bigϕ ∉ free_evars (patt_sym (inj inhabitant) $ (nest_ex s))).
      { rewrite HeqBigϕ.
        unfold patt_inhabitant_set.
        fold (evar_is_fresh_in (fresh_evar (patt_in b0 (sym inhabitant $ s) and ϕ)) (patt_sym (inj inhabitant) $ s)).
        unfold sym.
        eapply evar_fresh_in_subformula.
        2: apply set_evar_fresh_is_fresh.
        (* TODO automation *)
        unfold patt_and. unfold patt_not. unfold patt_or.
        apply sub_imp_l. apply sub_imp_l. apply sub_imp_l.
        apply sub_imp_l. unfold patt_in. unfold patt_defined.
        apply sub_app_r. unfold patt_and.
        unfold patt_not. unfold patt_or.
        apply sub_imp_l. apply sub_imp_r.
        apply sub_imp_l. apply sub_eq. reflexivity.
      }

      remember (patt_in b0 (patt_inhabitant_set s) and ϕ) as Bigϕ'.
      assert (HfreeBigϕ: free_evars Bigϕ = free_evars Bigϕ').
      { subst. simpl. unfold nest_ex. rewrite free_evars_nest_ex_aux. reflexivity. }
      assert (HfreshBigϕ: fresh_evar Bigϕ = fresh_evar Bigϕ').
      { unfold fresh_evar. rewrite HfreeBigϕ. reflexivity. }
      clear HfreeBigϕ.

      assert (Hfrs: evar_is_fresh_in (fresh_evar Bigϕ) s).
      { unfold evar_is_fresh_in.
        rewrite HfreshBigϕ. fold (evar_is_fresh_in (fresh_evar Bigϕ') s).
        eapply evar_fresh_in_subformula'. 2: apply set_evar_fresh_is_fresh.
        rewrite HeqBigϕ'. simpl. rewrite is_subformula_of_refl. simpl.
        rewrite !orb_true_r. auto.
      }

      split.
      - intros [m H].
        exists m.
        rewrite -(eval_fresh_evar_subterm _ Bigϕ).
        assumption.
        rewrite {3}HeqBigϕ in H.

        apply eval_and_full in H.
        fold evar_open in H.
        destruct H as [H1 H2].
        split. 2: apply H2. clear H2.
        unfold Minterp_inhabitant.
        pose proof (Hfeip := free_evar_in_patt M M_satisfies_theory (fresh_evar Bigϕ) (patt_sym (inj inhabitant) $ (nest_ex s)^{evar: 0 ↦ (fresh_evar Bigϕ)}) (update_evar_val (fresh_evar Bigϕ) m ρ)).
        destruct Hfeip as [_ Hfeip2].

        apply Hfeip2 in H1. clear Hfeip2.
        rewrite update_evar_val_same in H1.
        unfold sym.
        unfold Ensembles.In in H1.

        rewrite eval_app_simpl in H1.
        unfold evar_open in H1.
        rewrite nest_ex_same in H1.
        rewrite eval_sym_simpl in H1.

        rewrite eval_app_simpl.
        rewrite eval_sym_simpl.
        rewrite eval_free_evar_independent in H1.
        {
          solve_free_evars_inclusion 5.
        }
        apply H1.

      - intros [m [H1 H2] ]. exists m.
        pose proof (Hfeip := free_evar_in_patt M M_satisfies_theory (fresh_evar Bigϕ) (patt_sym (inj inhabitant) $ (nest_ex s)^{evar: 0 ↦ (fresh_evar Bigϕ)}) (update_evar_val (fresh_evar Bigϕ) m ρ)).
        destruct Hfeip as [Hfeip1 _].
        rewrite {3}HeqBigϕ.
        apply eval_and_full. fold evar_open.
        split.
        + apply Hfeip1. clear Hfeip1.
          unfold Ensembles.In.
          rewrite -> update_evar_val_same.
          unfold Minterp_inhabitant in H1. unfold sym in H1.

          rewrite eval_app_simpl in H1.
          rewrite eval_sym_simpl in H1.

          rewrite eval_app_simpl.
          unfold evar_open. rewrite nest_ex_same.
          rewrite eval_sym_simpl.
          rewrite eval_free_evar_independent.
          {
            solve_free_evars_inclusion 5.
          }
          apply H1.
        + rewrite -(eval_fresh_evar_subterm _ Bigϕ) in H2.
          apply Hsub.
          apply H2.
    Qed.

    Lemma M_predicate_exists_of_sort s ϕ :
      let x := fresh_evar ϕ in
      M_predicate M (ϕ^{evar: 0 ↦ x}) -> M_predicate M (patt_exists_of_sort s ϕ).
    Proof.
      intros x Hpred.
      unfold patt_exists_of_sort.
      apply M_predicate_exists.
      unfold evar_open. mlSimpl.
      rewrite {1}[bevar_subst _ _ _]/=.
      apply M_predicate_and.
      - apply T_predicate_in.
        apply M_satisfies_theory.
      - subst x.
        apply M_predicate_evar_open_fresh_evar_2.
        2: apply Hpred.
        eapply evar_fresh_in_subformula.
        2: apply set_evar_fresh_is_fresh.
        apply sub_imp_l.
        apply sub_imp_r. apply sub_imp_l. apply sub_eq. reflexivity.
    Qed.

    Hint Resolve M_predicate_exists_of_sort : core.

    Lemma M_predicate_forall_of_sort s ϕ :
      let x := fresh_evar ϕ in
      M_predicate M (ϕ^{evar: 0 ↦ x}) -> M_predicate M (patt_forall_of_sort s ϕ).
    Proof.
      intros x Hpred.
      unfold patt_forall_of_sort.
      apply M_predicate_forall.
      unfold evar_open. mlSimpl.
      apply M_predicate_impl.
      - apply T_predicate_in.
        apply M_satisfies_theory.
      - subst x.
        apply M_predicate_evar_open_fresh_evar_2.
        2: apply Hpred.
        eapply evar_fresh_in_subformula. 2: apply set_evar_fresh_is_fresh.
        apply sub_imp_r. apply sub_eq. reflexivity.
    Qed.

    Hint Resolve M_predicate_forall_of_sort : core.

    Lemma interp_total_function f s₁ s₂ ρ :
      @eval Σ M ρ (patt_total_function f s₁ s₂) = ⊤ <->
      is_total_function f (Minterp_inhabitant s₁ ρ) (Minterp_inhabitant s₂ ρ) ρ.
    Proof.
      unfold is_total_function.
      rewrite eval_forall_of_sort_predicate.
      1: { mlSortedSimpl. eapply M_predicate_exists_of_sort. eauto. }

      remember (fresh_evar (patt_exists_of_sort (nest_ex s₂) (patt_equal ((nest_ex (nest_ex f)) $ b1) b0))) as x'.
      rewrite [nest_ex s₂]/nest_ex.
      mlSortedSimpl.
      unfold nest_ex. repeat rewrite nest_ex_same.
      rewrite fuse_nest_ex_same.
      unfold evar_open.
      rewrite nest_ex_same_general. 1-2: lia. mlSimpl.
      simpl. rewrite nest_ex_same_general. 1-2: lia. mlSimpl.
      simpl.

      apply all_iff_morphism.
      unfold pointwise_relation. intros m₁.
      apply all_iff_morphism. unfold pointwise_relation. intros Hinh1.

      rewrite eval_exists_of_sort_predicate.
      1: {
        unfold evar_open. mlSimpl.
        apply T_predicate_equals; apply M_satisfies_theory.
      }
      apply ex_iff_morphism. unfold pointwise_relation. intros m₂.

      unfold Minterp_inhabitant.
      rewrite 2!eval_app_simpl.
      rewrite 2!eval_sym_simpl.
      rewrite eval_free_evar_independent.
      (* two subgoals *)
      fold (evar_is_fresh_in x' (nest_ex s₂)).

      assert (Hfreq: x' = fresh_evar (patt_imp s₂ (nest_ex (nest_ex f)))).
      { rewrite Heqx'. unfold fresh_evar. apply f_equal. simpl.
        rewrite 2!free_evars_nest_ex_aux.
        rewrite !(left_id_L ∅ union). rewrite !(right_id_L ∅ union).
        rewrite (idemp_L union). reflexivity.
      }
      {
        rewrite Hfreq.
        unfold evar_is_fresh_in.
        eapply evar_is_fresh_in_richer'.
        2: apply set_evar_fresh_is_fresh'. solve_free_evars_inclusion 5.
      }

      apply and_iff_morphism.
      1: { now rewrite nest_ex_aux_0. }

      unfold evar_open. mlSimpl. simpl.
      repeat rewrite nest_ex_same.

      remember (fresh_evar (patt_equal (nest_ex_aux 0 1 f $ patt_free_evar x') b0)) as x''.

      rewrite equal_iff_interpr_same. 1: apply M_satisfies_theory.
      simpl. rewrite eval_free_evar_simpl.
      rewrite update_evar_val_same.
      rewrite eval_app_simpl.
      rewrite eval_free_evar_simpl.

      (*  Hx''neqx' : x'' ≠ x'
          Hx''freeinf : x'' ∉ free_evars f
       *)
      rewrite {2}update_evar_val_comm.
      {
        solve_fresh_neq.
      }
      rewrite update_evar_val_same.
      rewrite eval_free_evar_independent.
      {
         rewrite Heqx''. unfold evar_is_fresh_in.
         eapply evar_is_fresh_in_richer'.
         2: apply set_evar_fresh_is_fresh'. cbn.
         solve_free_evars_inclusion 5.
      }
      rewrite eval_free_evar_independent.
      {
         rewrite Heqx'. unfold evar_is_fresh_in.
         eapply evar_is_fresh_in_richer'.
         2: apply set_evar_fresh_is_fresh'. cbn.
         solve_free_evars_inclusion 5.
      }
      auto.
    Qed.

    Lemma interp_partial_function f s₁ s₂ ρ :
      @eval Σ M ρ (patt_partial_function f s₁ s₂) = ⊤ <->
      ∀ (m₁ : Domain M),
        m₁ ∈ Minterp_inhabitant s₁ ρ ->
        ∃ (m₂ : Domain M),
          m₂ ∈ Minterp_inhabitant s₂ ρ /\
          (app_ext (@eval Σ M ρ f) {[m₁]})
            ⊆ {[m₂]}.
    Proof.
      rewrite eval_forall_of_sort_predicate.
      1: { mlSortedSimpl. eauto. }

      unfold evar_open. mlSimpl.
      remember (fresh_evar (patt_exists_of_sort (nest_ex s₂) (patt_subseteq ((nest_ex (nest_ex f)) $ b1) b0))) as x'.
      rewrite [nest_ex s₂]/nest_ex.
      mlSortedSimpl.
      rewrite nest_ex_same.
      unfold nest_ex.
      rewrite fuse_nest_ex_same.
      mlSimpl. rewrite nest_ex_same_general. 1-2: lia. simpl.

      apply all_iff_morphism.
      unfold pointwise_relation. intros m₁.
      apply all_iff_morphism. unfold pointwise_relation. intros Hinh1.

      rewrite eval_exists_of_sort_predicate.
      1: {
        unfold evar_open. mlSimpl.
        apply T_predicate_subseteq; apply M_satisfies_theory.
      }

      apply ex_iff_morphism. unfold pointwise_relation. intros m₂.

      unfold Minterp_inhabitant.
      rewrite 2!eval_app_simpl.
      rewrite 2!eval_sym_simpl.
      rewrite eval_free_evar_independent.
      {
        fold (evar_is_fresh_in x' (nest_ex s₂)).

        assert (Hfreq: x' = fresh_evar (patt_imp s₂ (nest_ex (nest_ex f)))).
        { rewrite Heqx'. unfold fresh_evar. apply f_equal. simpl.
          rewrite 2!free_evars_nest_ex_aux.
          rewrite !(left_id_L ∅ union). rewrite !(right_id_L ∅ union).
          reflexivity.
        }

        rewrite Hfreq.
        unfold nest_ex.
        unfold evar_is_fresh_in.
        eapply evar_is_fresh_in_richer'.
         2: apply set_evar_fresh_is_fresh'. cbn.
         solve_free_evars_inclusion 5.
      }

      apply and_iff_morphism; auto.

      unfold evar_open. mlSimpl.
      rewrite nest_ex_same.
      simpl.
      remember (fresh_evar (patt_subseteq (nest_ex_aux 0 1 f $ patt_free_evar x') b0)) as x''.

      rewrite subseteq_iff_interpr_subseteq. 1: apply M_satisfies_theory.
      simpl. rewrite eval_free_evar_simpl.
      rewrite update_evar_val_same.
      rewrite eval_app_simpl.
      rewrite eval_free_evar_simpl.

      (*  Hx''neqx' : x'' ≠ x'
          Hx''freeinf : x'' ∉ free_evars f
       *)

      rewrite {2}update_evar_val_comm.
      {
        solve_fresh_neq.
      }
      rewrite update_evar_val_same.
      unfold nest_ex.

      rewrite eval_free_evar_independent.
      {
         rewrite Heqx''. unfold evar_is_fresh_in.
         eapply evar_is_fresh_in_richer'.
         2: apply set_evar_fresh_is_fresh'. cbn.
         solve_free_evars_inclusion 5.
      }
      rewrite eval_free_evar_independent.
      {
         rewrite Heqx'. unfold evar_is_fresh_in.
         eapply evar_is_fresh_in_richer'.
         2: apply set_evar_fresh_is_fresh'. cbn.
         solve_free_evars_inclusion 5.
      }
      tauto.
    Qed.

    Lemma Minterp_inhabitant_evar_open_update_evar_val ρ x e s m:
      evar_is_fresh_in x s ->
      m ∈ Minterp_inhabitant ((nest_ex s)^{evar: 0 ↦ x}) (update_evar_val x e ρ)
      <-> m ∈ Minterp_inhabitant s ρ.
    Proof.
      intros Hfr.
      unfold Minterp_inhabitant.
      rewrite 2!eval_app_simpl.
      rewrite 2!eval_sym_simpl.
      unfold nest_ex, evar_open. rewrite nest_ex_same.
      rewrite eval_free_evar_independent; auto.
   Qed.

    Lemma interp_partial_function_injective f s ρ :
      @eval Σ M ρ (patt_partial_function_injective f s) = ⊤ <->
      ∀ (m₁ : Domain M),
        m₁ ∈ Minterp_inhabitant s ρ ->
        ∀ (m₂ : Domain M),
          m₂ ∈ Minterp_inhabitant s ρ ->
          (rel_of ρ f) m₁ ≠ ∅ ->
          (rel_of ρ f) m₁ = (rel_of ρ f) m₂ ->
          m₁ = m₂.
    Proof.
      unfold patt_partial_function_injective.
      rewrite eval_forall_of_sort_predicate.
      1: {
        match goal with
        | [ |- M_predicate _ (evar_open _ ?x _) ] => remember x
        end.
        unfold evar_open. mlSortedSimpl. mlSimpl. simpl.
        case_match; try lia.
        case_match; try lia.
        apply M_predicate_forall_of_sort.
        match goal with
        | [ |- M_predicate _ (evar_open _ ?x _) ] => remember x
        end.
        unfold evar_open. mlSimpl. simpl.
        eauto.
      }
      remember
      (fresh_evar
             (patt_forall_of_sort (nest_ex s)
                (! patt_equal (nest_ex (nest_ex f) $ b1) ⊥ --->
                 patt_equal (nest_ex (nest_ex f) $ b1) (nest_ex (nest_ex f) $ b0) --->
                 patt_equal b1 b0)))
      as x₁.
      apply all_iff_morphism. intros m₁.
      apply all_iff_morphism. intros Hm₁s.

      unfold evar_open. mlSortedSimpl.
      rewrite eval_forall_of_sort_predicate.
      1: { eauto 8. (* TODO be more explicit. Have a tactic for this kind of goals. *) }
      remember
      (fresh_evar
             (! patt_equal
                  ((nest_ex (nest_ex f))^[evar:1↦patt_free_evar x₁] $ b1^[evar:1↦patt_free_evar x₁])
                  ⊥ --->
              patt_equal
                ((nest_ex (nest_ex f))^[evar:1↦patt_free_evar x₁] $ b1^[evar:1↦patt_free_evar x₁])
                ((nest_ex (nest_ex f))^[evar:1↦patt_free_evar x₁] $ b0^[evar:1↦patt_free_evar x₁]) --->
              patt_equal b1^[evar:1↦patt_free_evar x₁] b0^[evar:1↦patt_free_evar x₁]))
      as x₂.

      apply all_iff_morphism. intros m₂.
      rewrite Minterp_inhabitant_evar_open_update_evar_val.
      1: {
        eapply evar_is_fresh_in_richer.
        2: { subst x₁.
             apply set_evar_fresh_is_fresh.
        }
        solve_free_evars_inclusion 5.
      }
      apply all_iff_morphism. intros Hm₂s.
      unfold evar_open. mlSimpl.
      unfold nest_ex in *.
      rewrite fuse_nest_ex_same in Heqx₂, Heqx₁. rewrite nest_ex_same_general in Heqx₁, Heqx₂.
      1-2: lia.
      rewrite fuse_nest_ex_same. rewrite nest_ex_same_general. 1-2: lia. simpl.
      rewrite nest_ex_same.
      simpl in Heqx₁, Heqx₂.

      rewrite eval_predicate_impl. 1: { eauto. }
      simpl.
      rewrite eval_predicate_not. 1: { eauto. }
      rewrite equal_iff_interpr_same.
      1: apply M_satisfies_theory.
      rewrite eval_bott_simpl.
      rewrite eval_app_simpl.
      rewrite eval_free_evar_simpl.
      rewrite update_evar_val_neq.
      { solve_fresh_neq. }
      rewrite update_evar_val_same.
      rewrite eval_free_evar_independent.
      {
         unfold evar_is_fresh_in.
         eapply evar_is_fresh_in_richer'.
         2: apply set_evar_fresh_is_fresh'. cbn.
         solve_free_evars_inclusion 5.
      }
      rewrite eval_free_evar_independent.
      {
         rewrite Heqx₁. unfold evar_is_fresh_in.
         eapply evar_is_fresh_in_richer'.
         2: apply set_evar_fresh_is_fresh'. cbn.
         solve_free_evars_inclusion 5.
      }
      fold (rel_of ρ f m₁).
      apply all_iff_morphism. unfold pointwise_relation. intros Hnonempty.

      rewrite eval_predicate_impl. 1: { eauto. }
      (*rewrite simpl_evar_open.*)
      rewrite equal_iff_interpr_same. 1: apply M_satisfies_theory.
      rewrite 2!eval_app_simpl.
      rewrite equal_iff_interpr_same. 1: { apply M_satisfies_theory. }
      rewrite !eval_free_evar_simpl.
      rewrite update_evar_val_same.
      rewrite update_evar_val_neq.
      { solve_fresh_neq. }
      rewrite update_evar_val_same.
      unfold rel_of.
      rewrite eval_free_evar_independent.
      {
         (* rewrite Heqx₂. *) unfold evar_is_fresh_in.
         eapply evar_is_fresh_in_richer'.
         2: apply set_evar_fresh_is_fresh'. cbn.
         solve_free_evars_inclusion 5.
      }
      rewrite eval_free_evar_independent.
      {
         rewrite Heqx₁. unfold evar_is_fresh_in.
         eapply evar_is_fresh_in_richer'.
         2: apply set_evar_fresh_is_fresh'. cbn.
         solve_free_evars_inclusion 5.
      }
      apply all_iff_morphism. intros Hfm1eqfm2.
      clear.
      set_solver.
    Qed.

    Lemma interp_total_function_injective f s ρ :
      @eval Σ M ρ (patt_total_function_injective f s) = ⊤ <->
      total_function_is_injective f (Minterp_inhabitant s ρ) ρ.
    Proof.
      unfold total_function_is_injective.
      unfold patt_partial_function_injective.
      rewrite eval_forall_of_sort_predicate.
      1: {
        match goal with
        | [ |- M_predicate _ (evar_open _ ?x _) ] => remember x
        end.
        unfold evar_open. mlSortedSimpl. mlSimpl. simpl.
        apply M_predicate_forall_of_sort.
        match goal with
        | [ |- M_predicate _ (evar_open _ ?x _) ] => remember x
        end.
        case_match; try lia.
        case_match; try lia.
        unfold evar_open. mlSimpl. simpl.
        eauto 8.
      }
      remember
      (fresh_evar
               (patt_forall_of_sort (nest_ex s)
                  (patt_equal (nest_ex (nest_ex f) $ b1) (nest_ex (nest_ex f) $ b0) ---> patt_equal b1 b0)))
      as x₁.
      apply all_iff_morphism. intros m₁.
      apply all_iff_morphism. intros Hm₁s.

      unfold evar_open. mlSortedSimpl. mlSimpl.
      rewrite eval_forall_of_sort_predicate.
      1: {
                match goal with
        | [ |- M_predicate _ (evar_open _ ?x _) ] => remember x
        end.
        unfold evar_open. mlSimpl. simpl.
        eauto.
      }
      remember
      (fresh_evar
             (patt_equal
                ((nest_ex (nest_ex f))^[evar:1↦patt_free_evar x₁] $ b1^[evar:1↦patt_free_evar x₁])
                ((nest_ex (nest_ex f))^[evar:1↦patt_free_evar x₁] $ b0^[evar:1↦patt_free_evar x₁]) --->
              patt_equal b1^[evar:1↦patt_free_evar x₁] b0^[evar:1↦patt_free_evar x₁]))
      as x₂.

      apply all_iff_morphism. intros m₂.
      rewrite Minterp_inhabitant_evar_open_update_evar_val.
      1: {
        eapply evar_is_fresh_in_richer.
        2: { subst. apply set_evar_fresh_is_fresh. }
        solve_free_evars_inclusion 5.
      }
      apply all_iff_morphism. intros Hm₂s.
      unfold nest_ex, evar_open in *.
      rewrite fuse_nest_ex_same in Heqx₂, Heqx₁. rewrite nest_ex_same_general in Heqx₁, Heqx₂.
      1-2: lia.
      rewrite fuse_nest_ex_same. rewrite nest_ex_same_general. 1-2: lia. simpl pred.
      mlSimpl.

      rewrite eval_predicate_impl.
      1: { eauto. }
      simpl.

      rewrite equal_iff_interpr_same.
      1: { apply M_satisfies_theory. }
      rewrite 2!eval_app_simpl.
      rewrite eval_free_evar_simpl.
      rewrite update_evar_val_neq.
      { solve_fresh_neq. }
      rewrite update_evar_val_same.

      rewrite eval_free_evar_simpl.
      rewrite update_evar_val_same.
      rewrite nest_ex_same.
      rewrite eval_free_evar_independent.
      {
         rewrite Heqx₂. unfold evar_is_fresh_in.
         eapply evar_is_fresh_in_richer'.
         2: apply set_evar_fresh_is_fresh'. cbn.
         solve_free_evars_inclusion 5.
      }
      rewrite eval_free_evar_independent.
      {
         rewrite Heqx₁. unfold evar_is_fresh_in.
         eapply evar_is_fresh_in_richer'.
         2: apply set_evar_fresh_is_fresh'. cbn.
         solve_free_evars_inclusion 5.
      }
      fold (rel_of ρ f m₁). fold (rel_of ρ f m₂).
      apply all_iff_morphism. intros Hfm1eqfm2.

      rewrite equal_iff_interpr_same.
      1: apply M_satisfies_theory.
      rewrite 2!eval_free_evar_simpl.
      rewrite update_evar_val_same.
      rewrite update_evar_val_neq.
      { solve_fresh_neq. }
      rewrite update_evar_val_same.
      clear. set_solver.
    Qed.

    Lemma eval_exists_of_sort
      (s : Pattern)
      (ρ : Valuation)
      (indec : forall (m : Domain M), Decision (m ∈ Minterp_inhabitant s ρ))
      (ϕ : Pattern):
    eval ρ (patt_exists_of_sort s ϕ)
    = stdpp_ext.propset_fa_union (λ (m : Domain M),
      match (indec m) with
      | left _ => eval (update_evar_val (fresh_evar ϕ) m ρ) (ϕ^{evar: 0 ↦ (fresh_evar ϕ)})
      | right _ => ∅
      end
    ).
    Proof.
      unfold patt_exists_of_sort.
      rewrite eval_ex_simpl. simpl.
      f_equal. apply functional_extensionality.
      intros m.
      remember (fresh_evar (patt_in b0 (patt_inhabitant_set (nest_ex s)) and ϕ)) as x.
      destruct (indec m) eqn:Hm.
      {
        clear Hm.
        rename e into Hinh.
        unfold evar_open. mlSimpl. simpl.
        unfold nest_ex. rewrite nest_ex_same.
        rewrite eval_and_simpl.
        unfold Minterp_inhabitant in Hinh.
        replace m with (evar_valuation (update_evar_val x m ρ) x) in Hinh.
        2: { apply update_evar_val_same. }
        rewrite -(eval_free_evar_independent ρ x m) in Hinh.
        {
          eapply evar_is_fresh_in_richer.
          2: { subst. apply set_evar_fresh_is_fresh. }
          simpl. clear. unfold nest_ex. rewrite free_evars_nest_ex_aux. set_solver.
        }
        rewrite free_evar_in_patt  in Hinh.
        1: { apply M_satisfies_theory. }
        rewrite Hinh.
        remember (fresh_evar ϕ) as x'.
        assert (Htmp: eval (update_evar_val x m ρ)
          ϕ^[evar:0↦patt_free_evar x] =
          eval (update_evar_val x' m ρ)
          ϕ^[evar:0↦patt_free_evar x']).
        {
          apply eval_fresh_evar_open.
          { subst x.
            eapply evar_is_fresh_in_richer.
            2: { apply set_evar_fresh_is_fresh. }
            simpl. clear. set_solver.
          }
          {
            subst. apply set_evar_fresh_is_fresh.
          }
        }
        rewrite Htmp. clear. unfold_leibniz. set_solver.
      }
      {
        clear Hm.
        rename n into Hinh.
        unfold evar_open. mlSimpl.
        rewrite eval_and_simpl. simpl.
        replace m with (evar_valuation (update_evar_val x m ρ) x) in Hinh.
        2: { apply update_evar_val_same. }
        unfold nest_ex. rewrite nest_ex_same.
        unfold Minterp_inhabitant in Hinh.
        rewrite -(eval_free_evar_independent ρ x m) in Hinh.
        {
          eapply evar_is_fresh_in_richer.
          2: { subst. apply set_evar_fresh_is_fresh. }
          simpl. clear. unfold nest_ex. rewrite free_evars_nest_ex_aux. set_solver.
        }
        rewrite free_evar_in_patt  in Hinh.
        1:{ apply M_satisfies_theory. }
        rewrite predicate_not_full_iff_empty in Hinh.
        1: { apply T_predicate_in. apply M_satisfies_theory. }
        rewrite Hinh. clear. set_solver.
      }
    Qed.

    Lemma eval_forall_of_sort
      (s : Pattern)
      (ρ : Valuation)
      (indec : forall (m : Domain M), Decision (m ∈ Minterp_inhabitant s ρ))
      (ϕ : Pattern):
    eval ρ (patt_forall_of_sort s ϕ)
    = stdpp_ext.propset_fa_intersection (λ (m : Domain M),
      match (indec m) with
      | left _ => eval (update_evar_val (fresh_evar ϕ) m ρ) (ϕ^{evar: 0 ↦ (fresh_evar ϕ)})
      | right _ => ⊤
      end
    ).
    Proof.
      unfold patt_forall_of_sort.
      rewrite eval_all_simpl.
      simpl.
      f_equal. apply functional_extensionality.
      intros m.
      remember (fresh_evar
      (patt_in b0 (patt_inhabitant_set (nest_ex s)) ---> ϕ)) as x.
      destruct (indec m) eqn:Hm.
      {
        clear Hm.
        rename e into Hinh.
        unfold evar_open. mlSimpl. simpl.
        unfold nest_ex. rewrite nest_ex_same.
        unfold Minterp_inhabitant in Hinh.
        replace m with (evar_valuation (update_evar_val x m ρ) x) in Hinh.
        2: { apply update_evar_val_same. }
        rewrite -(eval_free_evar_independent ρ x m) in Hinh.
        {
          eapply evar_is_fresh_in_richer.
          2: { subst. apply set_evar_fresh_is_fresh. }
          simpl. clear. unfold nest_ex. rewrite free_evars_nest_ex_aux. set_solver.
        }
        rewrite free_evar_in_patt in Hinh.
        1: { apply M_satisfies_theory. }
        unfold patt_inhabitant_set.
        unfold Sorts_Syntax.sym.
        unfold sym in Hinh.
        rewrite eval_imp_simpl.
        rewrite Hinh.
        remember (fresh_evar ϕ) as x'.
        assert (Htmp: eval (update_evar_val x m ρ)
          ϕ^[evar:0↦patt_free_evar x] =
          eval (update_evar_val x' m ρ)
          ϕ^[evar:0↦patt_free_evar x']).
        {
          apply eval_fresh_evar_open.
          { subst x.
            eapply evar_is_fresh_in_richer.
            2: { apply set_evar_fresh_is_fresh. }
            simpl. clear. set_solver.
          }
          {
            subst. apply set_evar_fresh_is_fresh.
          }
        }
        rewrite Htmp. clear. unfold_leibniz. set_solver.
      }
      {
        clear Hm.
        rename n into Hinh.
        unfold evar_open. mlSimpl.
        rewrite eval_imp_simpl. simpl.
        replace m with (evar_valuation (update_evar_val x m ρ) x) in Hinh.
        2: { apply update_evar_val_same. }
        unfold nest_ex. rewrite nest_ex_same.
        unfold Minterp_inhabitant in Hinh.
        rewrite -(eval_free_evar_independent ρ x m) in Hinh.
        {
          eapply evar_is_fresh_in_richer.
          2: { subst. apply set_evar_fresh_is_fresh. }
          simpl. clear. unfold nest_ex. rewrite free_evars_nest_ex_aux. set_solver.
        }
        rewrite free_evar_in_patt  in Hinh.
        1:{ apply M_satisfies_theory. }
        rewrite predicate_not_full_iff_empty in Hinh.
        1: { apply T_predicate_in. apply M_satisfies_theory. }
        rewrite Hinh. clear. set_solver.
      }
    Qed.

  End with_model.

  #[export]
  Hint Resolve M_predicate_exists_of_sort : core.

  #[export]
  Hint Resolve M_predicate_forall_of_sort : core.


Require Import final_spec.

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

Definition F_158 : type_LF_158:= (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_173 : type_LF_158:= (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_179 : type_LF_158:= (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_185 : type_LF_158:= (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_186 : type_LF_158:= (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_192 : type_LF_158:= (fun     _ _ => (false = true -> False, (Term id_false nil)::(Term id_true nil)::nil)).

Definition LF_158 := [F_158, F_173, F_179, F_185, F_186, F_192].

Function f_158 (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_158 : forall F, In F LF_158 -> forall u1, forall u2, (forall F', In F' LF_158 -> 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 [ 158 ] *)

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

revert Hind.

pattern u1, u2, (f_158 u1 u2). apply f_158_ind.

(* case [ 173 ] *)

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

(* case [ 179 ] *)

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

(* case [ 185 ] *)

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

	(* NEGATIVE CLASH on [ 173 ] *)

unfold fst. unfold F_173. intros. try discriminate.

	(* NEGATIVE DECOMPOSITION on [ 179 ] *)

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

unfold fst in HFabs0. unfold F_186 in HFabs0.
auto.

	(* REWRITING on [ 185 ] *)

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

	(* REWRITING on [ 186 ] *)

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

	(* NEGATIVE CLASH on [ 192 ] *)

unfold fst. unfold F_192. intros. try discriminate.

Qed.

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

Theorem all_true_158: forall F, In F LF_158 -> 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_158);
[(* 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_158;
 [assumption | idtac];
intros;
apply G;
 [ idtac | assumption ];
eexists; split;
 [idtac | do_nat n ltac:(eexists); reflexivity];
assumption.
Qed.

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

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

Definition F_196 : type_LF_196:= (fun   u1  _ _ _ _ => ((sortedT u1) = true -> (sortedT u1) = false -> False, (Term id_sortedT ((model_PLAN u1)::nil))::(Term id_true nil)::(Term id_sortedT ((model_PLAN u1)::nil))::(Term id_false nil)::nil)).
Definition F_229 : type_LF_196:= (fun   u6 u2 u3 u4 u5 => (false = true -> (sortedT (Cons (C u3 u4) (Cons (C u2 u5) u6))) = false -> (le u2 u3) = false -> False, (Term id_false nil)::(Term id_true nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u4)::nil)):: (Term id_Cons ((Term id_C ((model_nat u2):: (model_nat u5)::nil)):: (model_PLAN u6)::nil))::nil))::nil))::(Term id_false nil)::(Term id_le ((model_nat u2):: (model_nat u3)::nil))::(Term id_false nil)::nil)).
Definition F_211 : type_LF_196:= (fun    _  _ _ _ _ => (true = true -> (sortedT Nil) = false -> False, (Term id_true nil)::(Term id_true nil)::(Term id_sortedT ((Term id_Nil nil)::nil))::(Term id_false nil)::nil)).
Definition F_217 : type_LF_196:= (fun    _ u3 u4 _ _ => (true = true -> (sortedT (Cons (C u3 u4) Nil)) = false -> False, (Term id_true nil)::(Term id_true nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u4)::nil)):: (Term id_Nil nil)::nil))::nil))::(Term id_false nil)::nil)).
Definition F_230 : type_LF_196:= (fun    _  _ _ _ _ => ((sortedT Nil) = false -> False, (Term id_sortedT ((Term id_Nil nil)::nil))::(Term id_false nil)::nil)).
Definition F_234 : type_LF_196:= (fun    _  _ _ _ _ => (true = false -> False, (Term id_true nil)::(Term id_false nil)::nil)).
Definition F_231 : type_LF_196:= (fun    _ u3 u4 _ _ => ((sortedT (Cons (C u3 u4) Nil)) = false -> False, (Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u4)::nil)):: (Term id_Nil nil)::nil))::nil))::(Term id_false nil)::nil)).
Definition F_237 : type_LF_196:= (fun    _  _ _ _ _ => (true = false -> False, (Term id_true nil)::(Term id_false nil)::nil)).
Definition F_223 : type_LF_196:= (fun   u6 u2 u3 u4 u5 => ((sortedT (Cons (C u2 u5) u6)) = true -> (sortedT (Cons (C u3 u4) (Cons (C u2 u5) u6))) = false -> (le u2 u3) = true -> False, (Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u2):: (model_nat u5)::nil)):: (model_PLAN u6)::nil))::nil))::(Term id_true nil)::(Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u3):: (model_nat u4)::nil)):: (Term id_Cons ((Term id_C ((model_nat u2):: (model_nat u5)::nil)):: (model_PLAN u6)::nil))::nil))::nil))::(Term id_false nil)::(Term id_le ((model_nat u2):: (model_nat u3)::nil))::(Term id_true nil)::nil)).
Definition F_249 : type_LF_196:= (fun   u6 u2 u3 u5 _ => ((sortedT (Cons (C u2 u5) u6)) = true -> false = false -> (le u2 u3) = true -> (le u2 u3) = false -> False, (Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u2):: (model_nat u5)::nil)):: (model_PLAN u6)::nil))::nil))::(Term id_true nil)::(Term id_false nil)::(Term id_false nil)::(Term id_le ((model_nat u2):: (model_nat u3)::nil))::(Term id_true nil)::(Term id_le ((model_nat u2):: (model_nat u3)::nil))::(Term id_false nil)::nil)).
Definition F_250 : type_LF_196:= (fun   u6 u2 u3 u5 _ => ((sortedT (Cons (C u2 u5) u6)) = true -> (le u2 u3) = true -> (le u2 u3) = false -> False, (Term id_sortedT ((Term id_Cons ((Term id_C ((model_nat u2):: (model_nat u5)::nil)):: (model_PLAN u6)::nil))::nil))::(Term id_true nil)::(Term id_le ((model_nat u2):: (model_nat u3)::nil))::(Term id_true nil)::(Term id_le ((model_nat u2):: (model_nat u3)::nil))::(Term id_false nil)::nil)).

Definition LF_196 := [F_196, F_229, F_211, F_217, F_230, F_234, F_231, F_237, F_223, F_249, F_250].

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

Lemma main_196 : forall F, In F LF_196 -> forall u1, forall u2, forall u3, forall u4, forall u5, (forall F', In F' LF_196 -> 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 [ 196 ] *)

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

revert Hind.

pattern u1, (f_196 u1). apply f_196_ind.

(* case [ 211 ] *)

intros _u1.  intro eq_1.  intro HFabs0.
assert (Hind := HFabs0 F_211). clear HFabs0.
assert (HFabs0 : fst (F_211 Nil 0 0 0 0)).
apply Hind. trivial_in 2. unfold snd. unfold F_211. unfold F_196. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_196. unfold F_211.
auto.

(* case [ 217 ] *)

intros _u1. intro u3. intro u4.  intro eq_1.  intro HFabs0.
assert (Hind := HFabs0 F_217). clear HFabs0.
assert (HFabs0 : fst (F_217 Nil u3 u4 0 0)).
apply Hind. trivial_in 3. unfold snd. unfold F_217. unfold F_196. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_196. unfold F_217.
auto.

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

(* case [ 223 ] *)

assert (Hind := HFabs0 F_223). clear HFabs0.
assert (HFabs0 : fst (F_223 u6 u2 u3 u4 u5)).
apply Hind. trivial_in 8. unfold snd. unfold F_223. unfold F_196. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_196. unfold F_223. simpl in H. repeat(simpl; rewrite H). repeat(simpl in HFabs0; rewrite H in HFabs0). try (auto || (intro H0; contradict H0)).
auto.

(* case [ 229 ] *)

assert (Hind := HFabs0 F_229). clear HFabs0.
assert (HFabs0 : fst (F_229 u6 u2 u3 u4 u5)).
apply Hind. trivial_in 1. unfold snd. unfold F_229. unfold F_196. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_196. unfold F_229. 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 [ 229 ] *)

unfold fst. unfold F_229. intros. try discriminate.

	(* NEGATIVE DECOMPOSITION on [ 211 ] *)

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_230).
assert (HFabs0 : fst (F_230 Nil 0 0 0 0)).
apply H. trivial_in 4. unfold snd. unfold F_230. unfold F_211. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_211. unfold F_230.

unfold fst in HFabs0. unfold F_230 in HFabs0.
auto.

	(* NEGATIVE DECOMPOSITION on [ 217 ] *)

rename u1 into d_u1. rename u2 into _u3. rename u3 into _u4. rename u4 into d_u4. rename u5 into d_u5.
rename _u3 into u3. rename _u4 into u4.
assert (H := Hind F_231).
assert (HFabs0 : fst (F_231 Nil u3 u4 0 0)).
apply H. trivial_in 6. unfold snd. unfold F_231. unfold F_217. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_217. unfold F_231.

unfold fst in HFabs0. unfold F_231 in HFabs0.
auto.

	(* REWRITING on [ 230 ] *)

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_234). clear Hind.
assert (HFabs1 : fst (F_234 Nil 0 0 0 0)).
apply Res. trivial_in 5. unfold snd. unfold F_234. unfold F_230. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_230. unfold fst in HFabs1. unfold F_234 in HFabs1.    simpl. auto.

	(* NEGATIVE CLASH on [ 234 ] *)

unfold fst. unfold F_234. intros. try discriminate.

	(* REWRITING on [ 231 ] *)

rename u1 into d_u1. rename u2 into _u3. rename u3 into _u4. rename u4 into d_u4. rename u5 into d_u5.
rename _u3 into u3. rename _u4 into u4.
assert (Res := Hind F_237). clear Hind.
assert (HFabs1 : fst (F_237 Nil 0 0 0 0)).
apply Res. trivial_in 5. unfold snd. unfold F_237. unfold F_231. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_231. unfold fst in HFabs1. unfold F_237 in HFabs1.
pattern (C u3 u4). simpl (sortedT _). cbv beta.
 simpl. auto.

	(* NEGATIVE CLASH on [ 237 ] *)

unfold fst. unfold F_237. intros. try discriminate.

	(* TOTAL CASE REWRITING on [ 223 ] *)

rename u1 into _u6. rename u2 into _u2. rename u3 into _u3. rename u4 into _u4. rename u5 into _u5.
rename _u6 into u6. rename _u2 into u2. rename _u3 into u3. rename _u4 into u4. rename _u5 into u5.
assert (H: ((le u2 u3) = true) \/ ((le u2 u3) = false)).

destruct ((le u2 u3)); auto.

destruct H as [H|H].

(* rewriting with the axiom [ 109 ] *)

assert (H1 := Hind F_196). clear Hind.
assert (HFabs0 : fst (F_196 (Cons (C u2 u5) u6) 0 0 0 0)).
apply H1. trivial_in 0. unfold snd. unfold F_196. unfold F_223. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_223. unfold F_196. unfold fst in HFabs0. unfold F_196 in HFabs0. simpl in HFabs0.
pattern u2.
pattern u3.
pattern u4.
pattern u5.
pattern u6.
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_249). clear Hind.
assert (HFabs0 : fst (F_249 u6 u2 u3 u5 0)).
apply H1. trivial_in 9. unfold snd. unfold F_249. unfold F_223. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_223. unfold F_249. unfold fst in HFabs0. unfold F_249 in HFabs0. simpl in HFabs0.
pattern u2.
pattern u3.
pattern u4.
pattern u5.
pattern u6.
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.

	(* NEGATIVE DECOMPOSITION on [ 249 ] *)

rename u1 into _u6. rename u2 into _u2. rename u3 into _u3. rename u4 into _u5. rename u5 into d_u5.
rename _u6 into u6. rename _u2 into u2. rename _u3 into u3. rename _u5 into u5.
assert (H := Hind F_250).
assert (HFabs0 : fst (F_250 u6 u2 u3 u5 0)).
apply H. trivial_in 10. unfold snd. unfold F_250. unfold F_249. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_249. unfold F_250.

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

	(* SUBSUMPTION on [ 250 ] *)

rename u1 into _u6. rename u2 into _u2. rename u3 into _u3. rename u4 into _u5. rename u5 into d_u5.
rename _u6 into u6. rename _u2 into u2. rename _u3 into u3. rename _u5 into u5.
unfold fst. unfold F_250. specialize true_158 with (u1 := u2) (u2 := u3). intro L. intros. contradict L. (auto || symmetry; auto).

Qed.

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

Theorem all_true_196: forall F, In F LF_196 -> forall u1: PLAN, forall u2: nat, 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_196);
[(* 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_196;
 [assumption | idtac];
intros;
apply G;
 [ idtac | assumption ];
eexists; split;
 [idtac | do_nat n ltac:(eexists); reflexivity];
assumption.
Qed.

Theorem true_196: forall (u1: PLAN), (sortedT u1) = true -> (sortedT u1) = false -> False.
Proof.
do 1 intro.
apply (all_true_196 F_196);
 (trivial_in 0) ||
 (repeat constructor).
Qed.

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

Definition F_257 : type_LF_257:= (fun   u2 u3 u4 u1 => ((acr u1 u2 u3 u4) = (acr1 u1 u2 u3 u4), (Term id_acr ((model_PLAN u1):: (model_nat u2):: (model_nat u3):: (model_nat u4)::nil))::(Term id_acr1 ((model_PLAN u1):: (model_nat u2):: (model_nat u3):: (model_nat u4)::nil))::nil)).
Definition F_267 : type_LF_257:= (fun   u2 u3 u4 u1 => ((sortedT u1) = true -> (le u3 u4) = false -> (acr u1 u2 u3 u4) = (progAt (prog u1 u3 u4) u2), (Term id_sortedT ((model_PLAN u1)::nil))::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u4)::nil))::(Term id_false nil)::(Term id_acr ((model_PLAN u1):: (model_nat u2):: (model_nat u3):: (model_nat u4)::nil))::(Term id_progAt ((Term id_prog ((model_PLAN u1):: (model_nat u3):: (model_nat u4)::nil)):: (model_nat u2)::nil))::nil)).
Definition F_294 : type_LF_257:= (fun   u2 u3 u4 u1 => ((sortedT u1) = true -> (le u3 u4) = false -> (sortedT u1) = true -> (le u3 u4) = false -> (maxEr (wind u1 u2 u3 u4)) = (progAt (prog u1 u3 u4) u2), (Term id_sortedT ((model_PLAN u1)::nil))::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u4)::nil))::(Term id_false nil)::(Term id_sortedT ((model_PLAN u1)::nil))::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u4)::nil))::(Term id_false nil)::(Term id_maxEr ((Term id_wind ((model_PLAN u1):: (model_nat u2):: (model_nat u3):: (model_nat u4)::nil))::nil))::(Term id_progAt ((Term id_prog ((model_PLAN u1):: (model_nat u3):: (model_nat u4)::nil)):: (model_nat u2)::nil))::nil)).
Definition F_298 : type_LF_257:= (fun   u2 u3 u4 u1 => ((sortedT u1) = true -> (le u3 u4) = false -> (sortedT u1) = false -> 0 = (progAt (prog u1 u3 u4) u2), (Term id_sortedT ((model_PLAN u1)::nil))::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u4)::nil))::(Term id_false nil)::(Term id_sortedT ((model_PLAN u1)::nil))::(Term id_false nil)::(Term id_0 nil)::(Term id_progAt ((Term id_prog ((model_PLAN u1):: (model_nat u3):: (model_nat u4)::nil)):: (model_nat u2)::nil))::nil)).
Definition F_302 : type_LF_257:= (fun   u2 u3 u4 u1 => ((sortedT u1) = true -> (le u3 u4) = false -> (sortedT u1) = true -> (le u3 u4) = true -> 0 = (progAt (prog u1 u3 u4) u2), (Term id_sortedT ((model_PLAN u1)::nil))::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u4)::nil))::(Term id_false nil)::(Term id_sortedT ((model_PLAN u1)::nil))::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u4)::nil))::(Term id_true nil)::(Term id_0 nil)::(Term id_progAt ((Term id_prog ((model_PLAN u1):: (model_nat u3):: (model_nat u4)::nil)):: (model_nat u2)::nil))::nil)).
Definition F_271 : type_LF_257:= (fun   u2 u3 u4 u1 => ((sortedT u1) = false -> (acr u1 u2 u3 u4) = 0, (Term id_sortedT ((model_PLAN u1)::nil))::(Term id_false nil)::(Term id_acr ((model_PLAN u1):: (model_nat u2):: (model_nat u3):: (model_nat u4)::nil))::(Term id_0 nil)::nil)).
Definition F_322 : type_LF_257:= (fun    _ _ _ u1 => ((sortedT u1) = false -> (sortedT u1) = false -> 0 = 0, (Term id_sortedT ((model_PLAN u1)::nil))::(Term id_false nil)::(Term id_sortedT ((model_PLAN u1)::nil))::(Term id_false nil)::(Term id_0 nil)::(Term id_0 nil)::nil)).
Definition F_326 : type_LF_257:= (fun   u3 u4 _ u1 => ((sortedT u1) = false -> (sortedT u1) = true -> (le u3 u4) = true -> 0 = 0, (Term id_sortedT ((model_PLAN u1)::nil))::(Term id_false nil)::(Term id_sortedT ((model_PLAN u1)::nil))::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u4)::nil))::(Term id_true nil)::(Term id_0 nil)::(Term id_0 nil)::nil)).
Definition F_318 : type_LF_257:= (fun   u2 u3 u4 u1 => ((sortedT u1) = false -> (sortedT u1) = true -> (le u3 u4) = false -> (maxEr (wind u1 u2 u3 u4)) = 0, (Term id_sortedT ((model_PLAN u1)::nil))::(Term id_false nil)::(Term id_sortedT ((model_PLAN u1)::nil))::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u4)::nil))::(Term id_false nil)::(Term id_maxEr ((Term id_wind ((model_PLAN u1):: (model_nat u2):: (model_nat u3):: (model_nat u4)::nil))::nil))::(Term id_0 nil)::nil)).
Definition F_275 : type_LF_257:= (fun   u2 u3 u4 u1 => ((sortedT u1) = true -> (le u3 u4) = true -> (acr u1 u2 u3 u4) = 0, (Term id_sortedT ((model_PLAN u1)::nil))::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u4)::nil))::(Term id_true nil)::(Term id_acr ((model_PLAN u1):: (model_nat u2):: (model_nat u3):: (model_nat u4)::nil))::(Term id_0 nil)::nil)).
Definition F_340 : type_LF_257:= (fun   u3 u4 _ u1 => ((sortedT u1) = true -> (le u3 u4) = true -> (sortedT u1) = false -> 0 = 0, (Term id_sortedT ((model_PLAN u1)::nil))::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u4)::nil))::(Term id_true nil)::(Term id_sortedT ((model_PLAN u1)::nil))::(Term id_false nil)::(Term id_0 nil)::(Term id_0 nil)::nil)).
Definition F_344 : type_LF_257:= (fun   u3 u4 _ u1 => ((sortedT u1) = true -> (le u3 u4) = true -> (sortedT u1) = true -> (le u3 u4) = true -> 0 = 0, (Term id_sortedT ((model_PLAN u1)::nil))::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u4)::nil))::(Term id_true nil)::(Term id_sortedT ((model_PLAN u1)::nil))::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u4)::nil))::(Term id_true nil)::(Term id_0 nil)::(Term id_0 nil)::nil)).
Definition F_336 : type_LF_257:= (fun   u2 u3 u4 u1 => ((sortedT u1) = true -> (le u3 u4) = true -> (sortedT u1) = true -> (le u3 u4) = false -> (maxEr (wind u1 u2 u3 u4)) = 0, (Term id_sortedT ((model_PLAN u1)::nil))::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u4)::nil))::(Term id_true nil)::(Term id_sortedT ((model_PLAN u1)::nil))::(Term id_true nil)::(Term id_le ((model_nat u3):: (model_nat u4)::nil))::(Term id_false nil)::(Term id_maxEr ((Term id_wind ((model_PLAN u1):: (model_nat u2):: (model_nat u3):: (model_nat u4)::nil))::nil))::(Term id_0 nil)::nil)).

Definition LF_257 := [F_257, F_267, F_294, F_298, F_302, F_271, F_322, F_326, F_318, F_275, F_340, F_344, F_336].

Hypothesis true_156: forall u1 u2 u3 u4, (sortedT u1) = true -> (le u2 u3) = false -> (progAt (prog u1 u2 u3) u4) = (maxEr (wind u1 u4 u2 u3)).

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

	(* TOTAL CASE REWRITING on [ 257 ] *)

rename u1 into _u2. rename u2 into _u3. rename u3 into _u4. rename u4 into _u1.
rename _u2 into u2. rename _u3 into u3. rename _u4 into u4. rename _u1 into u1.
assert (H: ((sortedT u1) = true) /\ ((le u3 u4) = false) \/ ((sortedT u1) = false) \/ ((sortedT u1) = true) /\ ((le u3 u4) = true)).

destruct ((le u3 u4)); destruct ((sortedT u1)); auto.

destruct H as [[H H0]|[H|[H H0]]].

(* rewriting with the axiom [ 151 ] *)

assert (H1 := Hind F_267). clear Hind.
assert (HFabs0 : fst (F_267 u2 u3 u4 u1)).
apply H1. trivial_in 1. unfold snd. unfold F_267. unfold F_257. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_257. unfold F_267. unfold fst in HFabs0. unfold F_267 in HFabs0. simpl in HFabs0.
pattern u1.
pattern u3.
pattern u4.
pattern u2.
simpl (acr1 _ _ _ _). cbv beta. try unfold acr1. try rewrite H. try rewrite H0. try unfold acr1 in HFabs0. try rewrite H in HFabs0. try rewrite H0 in HFabs0. auto.

(* rewriting with the axiom [ 152 ] *)

assert (H1 := Hind F_271). clear Hind.
assert (HFabs0 : fst (F_271 u2 u3 u4 u1)).
apply H1. trivial_in 5. unfold snd. unfold F_271. unfold F_257. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_257. unfold F_271. unfold fst in HFabs0. unfold F_271 in HFabs0. simpl in HFabs0.
pattern u1.
pattern u2.
pattern u3.
pattern u4.
simpl (acr1 _ _ _ _). cbv beta. try unfold acr1. try rewrite H. try rewrite H0. try unfold acr1 in HFabs0. try rewrite H in HFabs0. try rewrite H0 in HFabs0. auto.

(* rewriting with the axiom [ 153 ] *)

assert (H1 := Hind F_275). clear Hind.
assert (HFabs0 : fst (F_275 u2 u3 u4 u1)).
apply H1. trivial_in 9. unfold snd. unfold F_275. unfold F_257. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_257. unfold F_275. unfold fst in HFabs0. unfold F_275 in HFabs0. simpl in HFabs0.
pattern u1.
pattern u3.
pattern u4.
pattern u2.
simpl (acr1 _ _ _ _). cbv beta. try unfold acr1. try rewrite H. try rewrite H0. try unfold acr1 in HFabs0. try rewrite H in HFabs0. try rewrite H0 in HFabs0. auto.

	(* TOTAL CASE REWRITING on [ 267 ] *)

rename u1 into _u2. rename u2 into _u3. rename u3 into _u4. rename u4 into _u1.
rename _u2 into u2. rename _u3 into u3. rename _u4 into u4. rename _u1 into u1.
assert (H: ((sortedT u1) = true) /\ ((le u3 u4) = false) \/ ((sortedT u1) = false) \/ ((sortedT u1) = true) /\ ((le u3 u4) = true)).

destruct ((le u3 u4)); destruct ((sortedT u1)); auto.

destruct H as [[H H0]|[H|[H H0]]].

(* rewriting with the axiom [ 125 ] *)

assert (H1 := Hind F_294). clear Hind.
assert (HFabs0 : fst (F_294 u2 u3 u4 u1)).
apply H1. trivial_in 2. unfold snd. unfold F_294. unfold F_267. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_267. unfold F_294. unfold fst in HFabs0. unfold F_294 in HFabs0. simpl in HFabs0.
pattern u1.
pattern u3.
pattern u4.
pattern u2.
simpl (acr _ _ _ _). cbv beta. try unfold acr. try rewrite H. try rewrite H0. try unfold acr in HFabs0. try rewrite H in HFabs0. try rewrite H0 in HFabs0. auto.

(* rewriting with the axiom [ 126 ] *)

assert (H1 := Hind F_298). clear Hind.
assert (HFabs0 : fst (F_298 u2 u3 u4 u1)).
apply H1. trivial_in 3. unfold snd. unfold F_298. unfold F_267. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_267. unfold F_298. unfold fst in HFabs0. unfold F_298 in HFabs0. simpl in HFabs0.
pattern u1.
pattern u2.
pattern u3.
pattern u4.
simpl (acr _ _ _ _). cbv beta. try unfold acr. try rewrite H. try rewrite H0. try unfold acr in HFabs0. try rewrite H in HFabs0. try rewrite H0 in HFabs0. auto.

(* rewriting with the axiom [ 127 ] *)

assert (H1 := Hind F_302). clear Hind.
assert (HFabs0 : fst (F_302 u2 u3 u4 u1)).
apply H1. trivial_in 4. unfold snd. unfold F_302. unfold F_267. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_267. unfold F_302. unfold fst in HFabs0. unfold F_302 in HFabs0. simpl in HFabs0.
pattern u1.
pattern u3.
pattern u4.
pattern u2.
simpl (acr _ _ _ _). cbv beta. try unfold acr. try rewrite H. try rewrite H0. try unfold acr in HFabs0. try rewrite H in HFabs0. try rewrite H0 in HFabs0. auto.

	(* SUBSUMPTION on [ 294 ] *)

rename u1 into _u2. rename u2 into _u3. rename u3 into _u4. rename u4 into _u1.
rename _u2 into u2. rename _u3 into u3. rename _u4 into u4. rename _u1 into u1.
unfold fst. unfold F_294. specialize true_156 with (u1 := u1) (u2 := u3) (u3 := u4) (u4 := u2).
(auto || symmetry; auto).

	(* SUBSUMPTION on [ 298 ] *)

rename u1 into _u2. rename u2 into _u3. rename u3 into _u4. rename u4 into _u1.
rename _u2 into u2. rename _u3 into u3. rename _u4 into u4. rename _u1 into u1.
unfold fst. unfold F_298. specialize true_196 with (u1 := u1). intro L. intros. contradict L. (auto || symmetry; auto).

	(* SUBSUMPTION on [ 302 ] *)

rename u1 into _u2. rename u2 into _u3. rename u3 into _u4. rename u4 into _u1.
rename _u2 into u2. rename _u3 into u3. rename _u4 into u4. rename _u1 into u1.
unfold fst. unfold F_302. specialize true_158 with (u1 := u3) (u2 := u4). intro L. intros. contradict L. (auto || symmetry; auto).

	(* TOTAL CASE REWRITING on [ 271 ] *)

rename u1 into _u2. rename u2 into _u3. rename u3 into _u4. rename u4 into _u1.
rename _u2 into u2. rename _u3 into u3. rename _u4 into u4. rename _u1 into u1.
assert (H: ((sortedT u1) = true) /\ ((le u3 u4) = false) \/ ((sortedT u1) = false) \/ ((sortedT u1) = true) /\ ((le u3 u4) = true)).

destruct ((le u3 u4)); destruct ((sortedT u1)); auto.

destruct H as [[H H0]|[H|[H H0]]].

(* rewriting with the axiom [ 125 ] *)

assert (H1 := Hind F_318). clear Hind.
assert (HFabs0 : fst (F_318 u2 u3 u4 u1)).
apply H1. trivial_in 8. unfold snd. unfold F_318. unfold F_271. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_271. unfold F_318. unfold fst in HFabs0. unfold F_318 in HFabs0. simpl in HFabs0.
pattern u1.
pattern u3.
pattern u4.
pattern u2.
simpl (acr _ _ _ _). cbv beta. try unfold acr. try rewrite H. try rewrite H0. try unfold acr in HFabs0. try rewrite H in HFabs0. try rewrite H0 in HFabs0. auto.

(* rewriting with the axiom [ 126 ] *)

assert (H1 := Hind F_322). clear Hind.
assert (HFabs0 : fst (F_322 0 0 0 u1)).
apply H1. trivial_in 6. unfold snd. unfold F_322. unfold F_271. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_271. unfold F_322. unfold fst in HFabs0. unfold F_322 in HFabs0. simpl in HFabs0.
pattern u1.
pattern u2.
pattern u3.
pattern u4.
simpl (acr _ _ _ _). cbv beta. try unfold acr. try rewrite H. try rewrite H0. try unfold acr in HFabs0. try rewrite H in HFabs0. try rewrite H0 in HFabs0. auto.

(* rewriting with the axiom [ 127 ] *)

assert (H1 := Hind F_326). clear Hind.
assert (HFabs0 : fst (F_326 u3 u4 0 u1)).
apply H1. trivial_in 7. unfold snd. unfold F_326. unfold F_271. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_271. unfold F_326. unfold fst in HFabs0. unfold F_326 in HFabs0. simpl in HFabs0.
pattern u1.
pattern u3.
pattern u4.
pattern u2.
simpl (acr _ _ _ _). cbv beta. try unfold acr. try rewrite H. try rewrite H0. try unfold acr in HFabs0. try rewrite H in HFabs0. try rewrite H0 in HFabs0. auto.

	(* TAUTOLOGY on [ 322 ] *)

unfold fst. unfold F_322.
auto.

	(* TAUTOLOGY on [ 326 ] *)

unfold fst. unfold F_326.
auto.

	(* SUBSUMPTION on [ 318 ] *)

rename u1 into _u2. rename u2 into _u3. rename u3 into _u4. rename u4 into _u1.
rename _u2 into u2. rename _u3 into u3. rename _u4 into u4. rename _u1 into u1.
unfold fst. unfold F_318. specialize true_196 with (u1 := u1). intro L. intros. contradict L. (auto || symmetry; auto).

	(* TOTAL CASE REWRITING on [ 275 ] *)

rename u1 into _u2. rename u2 into _u3. rename u3 into _u4. rename u4 into _u1.
rename _u2 into u2. rename _u3 into u3. rename _u4 into u4. rename _u1 into u1.
assert (H: ((sortedT u1) = true) /\ ((le u3 u4) = false) \/ ((sortedT u1) = false) \/ ((sortedT u1) = true) /\ ((le u3 u4) = true)).

destruct ((le u3 u4)); destruct ((sortedT u1)); auto.

destruct H as [[H H0]|[H|[H H0]]].

(* rewriting with the axiom [ 125 ] *)

assert (H1 := Hind F_336). clear Hind.
assert (HFabs0 : fst (F_336 u2 u3 u4 u1)).
apply H1. trivial_in 12. unfold snd. unfold F_336. unfold F_275. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_275. unfold F_336. unfold fst in HFabs0. unfold F_336 in HFabs0. simpl in HFabs0.
pattern u1.
pattern u3.
pattern u4.
pattern u2.
simpl (acr _ _ _ _). cbv beta. try unfold acr. try rewrite H. try rewrite H0. try unfold acr in HFabs0. try rewrite H in HFabs0. try rewrite H0 in HFabs0. auto.

(* rewriting with the axiom [ 126 ] *)

assert (H1 := Hind F_340). clear Hind.
assert (HFabs0 : fst (F_340 u3 u4 0 u1)).
apply H1. trivial_in 10. unfold snd. unfold F_340. unfold F_275. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_275. unfold F_340. unfold fst in HFabs0. unfold F_340 in HFabs0. simpl in HFabs0.
pattern u1.
pattern u2.
pattern u3.
pattern u4.
simpl (acr _ _ _ _). cbv beta. try unfold acr. try rewrite H. try rewrite H0. try unfold acr in HFabs0. try rewrite H in HFabs0. try rewrite H0 in HFabs0. auto.

(* rewriting with the axiom [ 127 ] *)

assert (H1 := Hind F_344). clear Hind.
assert (HFabs0 : fst (F_344 u3 u4 0 u1)).
apply H1. trivial_in 11. unfold snd. unfold F_344. unfold F_275. rewrite_model. abstract solve_rpo_mul.
unfold fst. unfold F_275. unfold F_344. unfold fst in HFabs0. unfold F_344 in HFabs0. simpl in HFabs0.
pattern u1.
pattern u3.
pattern u4.
pattern u2.
simpl (acr _ _ _ _). cbv beta. try unfold acr. try rewrite H. try rewrite H0. try unfold acr in HFabs0. try rewrite H in HFabs0. try rewrite H0 in HFabs0. auto.

	(* TAUTOLOGY on [ 340 ] *)

unfold fst. unfold F_340.
auto.

	(* TAUTOLOGY on [ 344 ] *)

unfold fst. unfold F_344.
auto.

	(* SUBSUMPTION on [ 336 ] *)

rename u1 into _u2. rename u2 into _u3. rename u3 into _u4. rename u4 into _u1.
rename _u2 into u2. rename _u3 into u3. rename _u4 into u4. rename _u1 into u1.
unfold fst. unfold F_336. specialize true_158 with (u1 := u3) (u2 := u4). intro L. intros. contradict L. (auto || symmetry; auto).

Qed.

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

Theorem all_true_257: forall F, In F LF_257 -> forall u1: nat, forall u2: nat, forall u3: nat, forall u4: PLAN, fst (F u1  u2  u3 u4).
Proof.
let n := constr:(4) 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_257);
[(* 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_257;
 [assumption | idtac];
intros;
apply G;
 [ idtac | assumption ];
eexists; split;
 [idtac | do_nat n ltac:(eexists); reflexivity];
assumption.
Qed.

Theorem true_257: forall (u2: nat) (u3: nat) (u4: nat) (u1: PLAN), (acr u1 u2 u3 u4) = (acr1 u1 u2 u3 u4).
Proof.
do 4 intro.
apply (all_true_257 F_257);
 (trivial_in 0) ||
 (repeat constructor).
Qed.