(*Tests from testcases folder. 3 SAT (7,8,9) and 1 IMPL (11) fail to run
because Coq runs out of memory*)
Add LoadPath "..".
Require Import msl.msl_standard.
Require Import share_dec_base.
Require Import share_equation_system.
Require Import share_simplifier.
Require Import share_solver.
Require Import fbool_solver.
Require Import share_solver_with_partition.

Module Tester.

 Module es := Equation_system sv_nat Share_Domain.
 Module esf := System_Features sv_nat es.
 Module bf := Bool_formula sv_nat.
 Module bsf := BF_solver sv_nat bf.
 Import es.
 Module solver := Solver_with_partition sv_nat es bf bsf.
 Import solver.

 Definition a1 : var := 0.
 Definition a2 : var := 1.
 Definition a3 : var := 2.
 Definition a4 : var := 3.
 Definition a5 : var := 4.
 Definition a6 : var := 5.
 Definition a7 : var := 6.
 Definition a8 : var := 7.
 Definition a9 : var := 8.
 Definition a10 : var := 9.
 Definition a11 : var := 10.
 Definition a12 : var := 11.
 Definition a13 : var := 12.
 Definition a14 : var := 13.
 Definition a15 : var := 14.
 Definition a16 : var := 15.
 Definition a17 : var := 16.
 Definition a18 : var := 17.
 Definition a19 : var := 18.
 Definition a20 : var := 19.
 Definition a21 : var := 20.
 Definition a : var := 21.
 Definition b : var := 22.
 Definition c : var := 23.
 Definition d : var := 24.
 Definition ses1 :=Sat_equation_system (nil) (nil) ((Vobject a1,Vobject a2,Vobject a3)::(Vobject a2,Vobject a3,Vobject a4)::(Vobject a3,Vobject a4,Vobject a5)::(Vobject a4,Vobject a5,Vobject a6)::(Vobject a5,Vobject a6,Vobject a7)::(Vobject a6,Vobject a7,Vobject a8)::(Vobject a7,Vobject a8,Vobject a9)::(Vobject a8,Vobject a9,Vobject a10)::(Vobject a9,Vobject a10,Vobject a11)::(Vobject a10,Vobject a11,Vobject a12)::(Vobject a11,Vobject a12,Vobject a13)::(Vobject a12,Vobject a13,Vobject a14)::(Vobject a13,Vobject a14,Vobject a15)::(Vobject a14,Vobject a15,Vobject a16)::(Vobject a15,Vobject a16,Vobject a17)::(Vobject a16,Vobject a17,Vobject a18)::(Vobject a17,Vobject a18,Vobject a19)::(Vobject a18,Vobject a19,Vobject a20)::nil).
 Definition ses2 :=Sat_equation_system (nil) (nil) ((Vobject a1,Vobject a2,Vobject a3)::(Vobject a2,Vobject a3,Vobject a4)::(Vobject a3,Vobject a4,Vobject a5)::(Vobject a4,Vobject a5,Vobject a6)::(Vobject a5,Vobject a6,Vobject a7)::(Vobject a6,Vobject a7,Vobject a8)::(Vobject a7,Vobject a8,Vobject a9)::(Vobject a8,Vobject a9,Vobject a10)::(Vobject a9,Vobject a10,Vobject a11)::(Vobject a10,Vobject a11,Vobject a12)::(Vobject a11,Vobject a12,Vobject a13)::(Vobject a12,Vobject a13,Vobject a14)::(Vobject a13,Vobject a14,Vobject a15)::(Vobject a14,Vobject a15,Vobject a16)::(Vobject a15,Vobject a16,Vobject a17)::(Vobject a16,Vobject a17,Vobject a18)::(Vobject a17,Vobject a18,Vobject a19)::(Vobject a18,Vobject a19,Vobject a20)::(Vobject a19,Vobject a20,Cobject (Share.top))::nil).
 Definition ses3 :=Sat_equation_system (nil) (nil) ((Vobject a1,Vobject a2,Vobject a3)::(Vobject a2,Vobject a3,Vobject a4)::(Vobject a3,Vobject a4,Vobject a5)::(Vobject a4,Vobject a5,Vobject a6)::(Vobject a5,Vobject a6,Vobject a7)::(Vobject a6,Vobject a7,Vobject a8)::(Vobject a7,Vobject a8,Vobject a9)::(Vobject a8,Vobject a9,Vobject a10)::(Vobject a9,Vobject a10,Vobject a11)::(Vobject a10,Vobject a11,Vobject a12)::(Vobject a11,Vobject a12,Vobject a13)::(Vobject a12,Vobject a13,Vobject a14)::(Vobject a13,Vobject a14,Vobject a15)::(Vobject a14,Vobject a15,Vobject a16)::(Vobject a15,Vobject a16,Vobject a17)::(Vobject a16,Vobject a17,Vobject a18)::(Vobject a17,Vobject a18,Vobject a19)::(Vobject a18,Vobject a19,Vobject a20)::(Vobject a19,Vobject a20,Cobject (Share.recompose (Share.top,Share.bot)))::nil).
 Definition ses4 :=Sat_equation_system (nil) (nil) ((Vobject a1,Vobject a2,Vobject a3)::(Vobject a3,Vobject a4,Vobject a5)::(Vobject a5,Vobject a6,Vobject a7)::(Vobject a7,Vobject a8,Vobject a9)::(Vobject a9,Vobject a10,Vobject a11)::(Vobject a11,Vobject a12,Vobject a13)::(Vobject a13,Vobject a14,Vobject a15)::(Vobject a15,Vobject a16,Vobject a17)::(Vobject a17,Vobject a18,Vobject a19)::(Vobject a19,Vobject a20,Vobject a21)::nil).
 Definition ses5 :=Sat_equation_system (nil) (nil) ((Vobject a1,Vobject a2,Vobject a3)::(Vobject a3,Vobject a4,Vobject a5)::(Vobject a5,Vobject a6,Vobject a7)::(Vobject a7,Vobject a8,Vobject a9)::(Vobject a9,Vobject a10,Vobject a11)::(Vobject a11,Vobject a12,Vobject a13)::(Vobject a13,Vobject a14,Vobject a15)::(Vobject a15,Vobject a16,Vobject a17)::(Vobject a17,Vobject a18,Vobject a19)::(Vobject a19,Vobject a20,Cobject (Share.top))::nil).
 Definition ses6 :=Sat_equation_system (nil) (nil) ((Vobject a1,Vobject a2,Vobject a3)::(Vobject a3,Vobject a4,Vobject a5)::(Vobject a5,Vobject a6,Vobject a7)::(Vobject a7,Vobject a8,Vobject a9)::(Vobject a9,Vobject a10,Vobject a11)::(Vobject a11,Vobject a12,Vobject a13)::(Vobject a13,Vobject a14,Vobject a15)::(Vobject a15,Vobject a16,Vobject a17)::(Vobject a17,Vobject a18,Vobject a19)::(Vobject a19,Vobject a20,Cobject (Share.recompose (Share.bot,Share.top)))::nil).
 (*
 Definition ses7 :=Sat_equation_system (nil) (nil) ((Vobject a1,Vobject a2,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))))))))))))))))::nil).
 Definition ses8 :=Sat_equation_system (nil) (nil) ((Vobject a1,Vobject a2,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))))))))))))))))::(Vobject a2,Vobject a3,Cobject (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.top,Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot)))::nil).
 Definition ses9 :=Sat_equation_system (nil) (nil) ((Vobject a1,Vobject a2,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))))))))))))))))::(Vobject a2,Vobject a3,Cobject (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.top,Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot)))::(Vobject a1,Cobject (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.top,Share.bot),Share.recompose (Share.bot,Share.top)),Share.recompose (Share.recompose (Share.top,Share.bot),Share.recompose (Share.top,Share.bot))),Share.recompose (Share.recompose (Share.recompose (Share.top,Share.bot),Share.recompose (Share.top,Share.bot)),Share.recompose (Share.recompose (Share.bot,Share.top),Share.recompose (Share.bot,Share.top))))),Vobject a3)::nil).
 *)
 Definition ses10 :=Sat_equation_system (nil) ((Vobject a1,Vobject a4)::(Vobject a2,Vobject a5)::(Vobject a3,Vobject a6)::(Vobject a7,Cobject (Share.top))::(Vobject a8,Cobject (Share.recompose (Share.recompose (Share.top,Share.bot),Share.bot)))::(Vobject a9,Cobject (Share.recompose (Share.recompose (Share.bot,Share.top),Share.top)))::nil) ((Vobject a1,Vobject a2,Vobject a7)::(Vobject a2,Vobject a3,Vobject a8)::(Vobject a3,Vobject a1,Vobject a9)::(Vobject a4,Vobject a5,Cobject (Share.top))::(Cobject (Share.top),Vobject a3,Vobject a7)::(Cobject (Share.recompose (Share.recompose (Share.recompose (Share.top,Share.bot),Share.bot),Share.bot)),Cobject (Share.recompose (Share.bot,Share.top)),Vobject a10)::(Vobject a11,Cobject (Share.recompose (Share.top,Share.bot)),Cobject (Share.top))::(Cobject (Share.top),Vobject a12,Vobject a7)::(Cobject (Share.recompose (Share.top,Share.bot)),Cobject (Share.recompose (Share.bot,Share.top)),Cobject (Share.top))::nil).
 Definition ses11 :=Sat_equation_system (nil) ((Vobject a1,Vobject a4)::(Vobject a2,Vobject a5)::(Vobject a3,Vobject a6)::(Vobject a7,Cobject (Share.top))::(Vobject a8,Cobject (Share.recompose (Share.recompose (Share.top,Share.bot),Share.bot)))::(Vobject a9,Cobject (Share.recompose (Share.recompose (Share.bot,Share.top),Share.top)))::nil) ((Vobject a1,Vobject a2,Vobject a7)::(Vobject a2,Vobject a3,Vobject a8)::(Vobject a3,Vobject a1,Vobject a9)::(Vobject a4,Vobject a5,Cobject (Share.top))::(Cobject (Share.top),Vobject a3,Vobject a7)::(Cobject (Share.recompose (Share.recompose (Share.recompose (Share.top,Share.bot),Share.bot),Share.bot)),Cobject (Share.recompose (Share.bot,Share.top)),Vobject a10)::(Vobject a11,Cobject (Share.recompose (Share.top,Share.bot)),Cobject (Share.top))::(Cobject (Share.top),Vobject a12,Vobject a7)::(Cobject (Share.recompose (Share.top,Share.bot)),Cobject (Share.recompose (Share.bot,Share.top)),Cobject (Share.top))::(Vobject a5,Vobject a6,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))::nil).
 Definition ses12 :=Sat_equation_system (nil) ((Vobject a1,Vobject a2)::(Vobject a2,Vobject a3)::(Vobject a3,Vobject a4)::(Vobject a4,Vobject a5)::(Vobject a5,Vobject a6)::(Vobject a6,Vobject a7)::(Vobject a7,Vobject a8)::(Vobject a8,Vobject a9)::(Vobject a9,Vobject a10)::(Vobject a10,Vobject a11)::(Vobject a11,Vobject a12)::(Vobject a12,Vobject a13)::(Vobject a13,Vobject a14)::(Vobject a14,Vobject a15)::(Vobject a15,Vobject a16)::(Vobject a16,Vobject a17)::(Vobject a17,Vobject a18)::(Vobject a18,Vobject a19)::(Vobject a19,Vobject a20)::nil) (nil).

 Definition ses13 :=Sat_equation_system (nil) ((Vobject a1,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))))))))::(Vobject a2,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.top,Share.bot)))))))))))::(Vobject a3,Cobject (Share.top))::(Vobject a6,Cobject (Share.recompose (Share.recompose (Share.recompose (Share.top,Share.bot),Share.recompose (Share.top,Share.bot)),Share.recompose (Share.recompose (Share.bot,Share.top),Share.recompose (Share.bot,Share.top)))))::(Vobject a7,Cobject (Share.recompose (Share.top,Share.bot)))::(Vobject a8,Cobject (Share.top))::(Vobject a9,Cobject (Share.top))::(Vobject a10,Cobject (Share.top))::(Vobject a11,Cobject (Share.top))::(Vobject a12,Cobject (Share.top))::(Vobject a13,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))))))))::(Vobject a14,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))))))))::(Vobject a15,Cobject (Share.top))::(Vobject a17,Cobject (Share.top))::(Vobject a18,Cobject (Share.top))::(Vobject a19,Cobject (Share.top))::(Vobject a20,Cobject (Share.top))::nil) (nil).
 Definition ses14 :=Sat_equation_system (nil) ((Vobject a4,Vobject a5)::(Vobject a8,Vobject a9)::(Vobject a10,Vobject a11)::(Vobject a11,Vobject a12)::(Vobject a13,Vobject a14)::(Vobject a1,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))))))))::(Vobject a2,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.top,Share.bot)))))))))))::(Vobject a3,Cobject (Share.top))::(Vobject a6,Cobject (Share.recompose (Share.recompose (Share.recompose (Share.top,Share.bot),Share.recompose (Share.top,Share.bot)),Share.recompose (Share.recompose (Share.bot,Share.top),Share.recompose (Share.bot,Share.top)))))::(Vobject a7,Cobject (Share.recompose (Share.top,Share.bot)))::(Vobject a8,Cobject (Share.top))::(Vobject a9,Cobject (Share.top))::(Vobject a10,Cobject (Share.top))::(Vobject a11,Cobject (Share.top))::(Vobject a12,Cobject (Share.top))::(Vobject a13,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))))))))::(Vobject a14,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))))))))::(Vobject a15,Cobject (Share.top))::(Vobject a17,Cobject (Share.top))::(Vobject a18,Cobject (Share.top))::(Vobject a19,Cobject (Share.top))::(Vobject a20,Cobject (Share.top))::nil) (nil).
 Definition ses15 :=Sat_equation_system (nil) ((Vobject a1,Vobject a2)::(Vobject a4,Vobject a5)::(Vobject a8,Vobject a9)::(Vobject a10,Vobject a11)::(Vobject a11,Vobject a12)::(Vobject a13,Vobject a14)::(Vobject a1,Vobject a20)::(Vobject a1,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))))))))::(Vobject a2,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.top,Share.bot)))))))))))::(Vobject a3,Cobject (Share.top))::(Vobject a6,Cobject (Share.recompose (Share.recompose (Share.recompose (Share.top,Share.bot),Share.recompose (Share.top,Share.bot)),Share.recompose (Share.recompose (Share.bot,Share.top),Share.recompose (Share.bot,Share.top)))))::(Vobject a7,Cobject (Share.recompose (Share.top,Share.bot)))::(Vobject a8,Cobject (Share.top))::(Vobject a9,Cobject (Share.top))::(Vobject a10,Cobject (Share.top))::(Vobject a11,Cobject (Share.top))::(Vobject a12,Cobject (Share.top))::(Vobject a13,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))))))))::(Vobject a14,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))))))))::(Vobject a15,Cobject (Share.top))::(Vobject a17,Cobject (Share.top))::(Vobject a18,Cobject (Share.top))::(Vobject a19,Cobject (Share.top))::(Vobject a20,Cobject (Share.top))::nil) (nil).
 Definition ses16 :=Sat_equation_system (nil) ((Vobject a1,Cobject (Share.top))::(Vobject a2,Cobject (Share.top))::(Vobject a3,Cobject (Share.top))::(Vobject a4,Cobject (Share.top))::(Vobject a5,Cobject (Share.top))::(Vobject a6,Cobject (Share.top))::(Vobject a7,Cobject (Share.top))::(Vobject a8,Cobject (Share.top))::(Vobject a9,Cobject (Share.top))::(Vobject a1,Cobject (Share.recompose (Share.bot,Share.top)))::nil) (nil).
 Definition ses17 :=Sat_equation_system (nil) (nil) (nil).
 Definition is1 :=(Impl_equation_system (nil) (nil) (nil) ((Vobject a1,Vobject a2,Vobject a3)::nil),Impl_equation_system (nil) (nil) (nil) ((Vobject a1,Vobject a2,Vobject a3)::nil)).
 Definition is2 :=(Impl_equation_system (nil) (nil) ((Vobject a1,Vobject a2)::nil) ((Vobject a1,Vobject a2,Vobject a3)::nil),Impl_equation_system (nil) (nil) (nil) (nil)).
 Definition is3 :=(Impl_equation_system (nil) (nil) ((Vobject a1,Vobject a2)::nil) ((Vobject a1,Vobject a2,Vobject a3)::nil),Impl_equation_system (nil) (nil) ((Vobject a3,Cobject (Share.top))::nil) (nil)).
 Definition is4 :=(Impl_equation_system (nil) (nil) (nil) ((Vobject a1,Vobject a2,Cobject (Share.top))::(Vobject a2,Vobject a3,Cobject (Share.recompose (Share.top,Share.bot)))::(Vobject a1,Vobject a3,Cobject (Share.recompose (Share.bot,Share.top)))::nil),Impl_equation_system (nil) (nil) ((Vobject a1,Cobject (Share.recompose (Share.bot,Share.top)))::(Vobject a2,Cobject (Share.recompose (Share.top,Share.bot)))::nil) (nil)).
 Definition is5 :=(Impl_equation_system (nil) (nil) (nil) (nil),Impl_equation_system (nil) (nil) ((Vobject a1,Vobject a1)::(Vobject a2,Vobject a2)::(Vobject a3,Vobject a3)::(Vobject a4,Vobject a4)::(Vobject a5,Vobject a5)::(Vobject a6,Vobject a6)::(Vobject a7,Vobject a7)::(Vobject a8,Vobject a8)::(Vobject a9,Vobject a9)::(Vobject a10,Vobject a10)::nil) ((Cobject (Share.recompose (Share.top,Share.bot)),Cobject (Share.recompose (Share.bot,Share.top)),Cobject (Share.top))::nil)).
 Definition is6 :=(Impl_equation_system (nil) (nil) (nil) (nil),Impl_equation_system (a11::nil) (nil) ((Vobject a1,Vobject a1)::(Vobject a2,Vobject a2)::(Vobject a3,Vobject a3)::(Vobject a4,Vobject a4)::(Vobject a5,Vobject a5)::(Vobject a6,Vobject a6)::(Vobject a7,Vobject a7)::(Vobject a8,Vobject a8)::(Vobject a9,Vobject a9)::(Vobject a10,Vobject a10)::(Vobject a11,Cobject (Share.top))::nil) ((Cobject (Share.recompose (Share.top,Share.bot)),Cobject (Share.recompose (Share.bot,Share.top)),Cobject (Share.top))::nil)).
 Definition is7 :=(Impl_equation_system (nil) (nil) ((Vobject a1,Vobject a2)::(Vobject a3,Vobject a4)::(Vobject a5,Vobject a6)::(Vobject a1,Cobject (Share.recompose (Share.bot,Share.top)))::(Vobject a3,Cobject (Share.recompose (Share.top,Share.bot)))::nil) ((Vobject a1,Vobject a3,Cobject (Share.top))::(Vobject a5,Vobject a6,Vobject a7)::nil),Impl_equation_system (nil) (nil) (nil) (nil)).
 Definition is8 :=(Impl_equation_system (nil) (nil) ((Vobject a1,Vobject a2)::(Vobject a3,Vobject a4)::(Vobject a5,Vobject a6)::(Vobject a1,Cobject (Share.recompose (Share.bot,Share.top)))::(Vobject a3,Cobject (Share.recompose (Share.top,Share.bot)))::nil) ((Vobject a1,Vobject a3,Cobject (Share.top))::(Vobject a5,Vobject a6,Vobject a7)::(Vobject a1,Vobject a1,Vobject a2)::nil),Impl_equation_system (nil) (nil) (nil) ((Vobject a8,Vobject a9,Vobject a10)::nil)).
 Definition is9 :=(Impl_equation_system (nil) (nil) ((Vobject a1,Vobject a2)::(Vobject a3,Vobject a4)::(Vobject a5,Vobject a6)::(Vobject a1,Cobject (Share.recompose (Share.bot,Share.top)))::(Vobject a3,Cobject (Share.recompose (Share.top,Share.bot)))::nil) ((Vobject a1,Vobject a3,Cobject (Share.top))::(Vobject a5,Vobject a6,Vobject a7)::nil),Impl_equation_system (nil) (nil) ((Vobject a3,Cobject (Share.recompose (Share.top,Share.bot)))::nil) ((Vobject a4,Vobject a5,Vobject a3)::nil)).
 Definition is10 :=(Impl_equation_system (nil) (nil) ((Vobject a1,Vobject a2)::(Vobject a3,Vobject a4)::(Vobject a5,Vobject a6)::(Vobject a1,Cobject (Share.recompose (Share.bot,Share.top)))::(Vobject a3,Cobject (Share.recompose (Share.top,Share.bot)))::nil) ((Vobject a1,Vobject a3,Cobject (Share.top))::(Vobject a3,Vobject a4,Vobject a5)::(Vobject a5,Vobject a6,Vobject a7)::nil),Impl_equation_system (nil) (nil) ((Vobject a10,Vobject a11)::(Vobject a8,Cobject (Share.recompose (Share.top,Share.bot)))::nil) ((Vobject a8,Vobject a9,Vobject a10)::nil)).
 (*
 Definition is11 :=(Impl_equation_system (nil) (nil) (nil) ((Vobject a1,Vobject a2,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))))))))))))))))::nil),Impl_equation_system (nil) (nil) ((Vobject a2,Cobject (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.top,Share.bot),Share.top),Share.top),Share.top),Share.top),Share.top),Share.top),Share.top),Share.top),Share.top),Share.top),Share.top),Share.top),Share.top),Share.top),Share.top),Share.top)))::nil) (nil)).
 *)
 Definition is12 :=(Impl_equation_system (nil) (nil) ((Vobject a1,Vobject a3)::(Vobject a2,Vobject a3)::nil) ((Vobject a1,Vobject a2,Cobject (Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.bot,Share.top))))))))))))))))))::nil),Impl_equation_system (nil) (nil) ((Vobject a2,Cobject (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.top,Share.bot),Share.top),Share.top),Share.top),Share.top),Share.top),Share.top),Share.top),Share.top),Share.top),Share.top),Share.top),Share.top),Share.top),Share.top),Share.top),Share.top)))::nil) (nil)).
 Definition is13 :=(Impl_equation_system (nil) (nil) ((Vobject a1,Vobject a3)::nil) ((Vobject a1,Vobject a2,Cobject (Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.bot,Share.top))))))))))))))))))::(Vobject a3,Vobject a3,Vobject a3)::nil),Impl_equation_system (nil) (nil) ((Vobject a2,Cobject (Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.top,Share.recompose (Share.bot,Share.top))))))))))))))))))::nil) (nil)).
 Definition is14 :=(Impl_equation_system (nil) (nil) (nil) (nil),Impl_equation_system (nil) (nil) (nil) (nil)).
 Definition ses18 :=Sat_equation_system (nil) (nil) ((Vobject a,Vobject b,Cobject (Share.top))::(Vobject c,Vobject b,Cobject (Share.recompose (Share.top,Share.bot)))::(Vobject c,Vobject a,Cobject (Share.top))::nil).
 Definition ses19 :=Sat_equation_system (a::nil) ((Vobject a,Vobject a)::(Vobject a,Cobject (Share.top))::nil) ((Vobject a,Vobject a,Vobject a)::nil).
 Definition ses20 :=Sat_equation_system (a::nil) ((Vobject a,Vobject a)::(Vobject a,Cobject (Share.bot))::nil) ((Vobject a,Vobject a,Vobject a)::nil).
 Definition ses21 :=Sat_equation_system (a ::nil) (nil) ((Vobject a,Vobject b,Cobject (Share.top))::nil).
 Definition ses22 :=Sat_equation_system (a ::nil) (nil) ((Vobject a,Vobject b,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))))::nil).
 Definition ses23 :=Sat_equation_system (a ::nil) (nil) ((Vobject a,Vobject b,Cobject (Share.top))::(Vobject a,Vobject c,Cobject (Share.top))::(Vobject b,Vobject c,Cobject (Share.top))::nil).
 Definition ses24 :=Sat_equation_system (a ::nil) (nil) ((Vobject a,Vobject b,Cobject (Share.top))::(Vobject a,Vobject c,Cobject (Share.top))::(Vobject b,Vobject c,Cobject (Share.top))::(Vobject a,Vobject a,Vobject a)::nil).
 Definition ses25 :=Sat_equation_system (a ::nil) (nil) ((Vobject a,Vobject b,Cobject (Share.top))::(Vobject a,Vobject c,Cobject (Share.top))::(Vobject b,Vobject c,Cobject (Share.top))::(Vobject a,Vobject b,Vobject c)::nil).
 Definition ses26 :=Sat_equation_system (a1 ::nil) (nil) ((Vobject a1,Vobject a2,Cobject (Share.top))::(Vobject a3,Vobject a4,Vobject a1)::(Vobject a5,Vobject a6,Vobject a3)::(Vobject a7,Vobject a8,Vobject a5)::(Vobject a9,Vobject a10,Vobject a7)::(Vobject a11,Vobject a12,Vobject a9)::(Vobject a13,Vobject a14,Vobject a11)::(Vobject a15,Vobject a16,Vobject a13)::nil).
 Definition ses27 :=Sat_equation_system (a1 ::nil) ((Vobject a1,Vobject a16)::nil) ((Vobject a1,Vobject a2,Cobject (Share.top))::(Vobject a3,Vobject a4,Vobject a1)::(Vobject a5,Vobject a6,Vobject a3)::(Vobject a7,Vobject a8,Vobject a5)::(Vobject a9,Vobject a10,Vobject a7)::(Vobject a11,Vobject a12,Vobject a9)::(Vobject a13,Vobject a14,Vobject a11)::(Vobject a15,Vobject a16,Vobject a13)::nil).
 Definition ses28 :=Sat_equation_system (a1 ::nil) ((Vobject a1,Vobject a3)::(Vobject a2,Vobject a4)::(Vobject a5,Cobject (Share.top))::nil) ((Vobject a1,Vobject a4,Vobject a5)::(Vobject a2,Vobject a3,Vobject a6)::nil).
 Definition ses29 :=Sat_equation_system (a1 ::nil) ((Vobject a1,Vobject a2)::(Vobject a3,Cobject (Share.bot))::(Vobject a4,Cobject (Share.top))::(Vobject a5,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))::nil) ((Vobject a1,Vobject a5,Vobject a6)::(Vobject a2,Vobject a7,Vobject a3)::nil).
 Definition ses30 :=Sat_equation_system (a1::nil) ((Vobject a1,Vobject a2)::(Vobject a3,Cobject (Share.bot))::(Vobject a4,Cobject (Share.top))::(Vobject a5,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))::nil) ((Vobject a1,Vobject a5,Vobject a6)::(Vobject a2,Vobject a7,Vobject a3)::nil).
 Definition ses31 :=Sat_equation_system (nil) ((Vobject a1,Vobject a2)::(Vobject a3,Cobject (Share.bot))::(Vobject a4,Cobject (Share.top))::(Vobject a5,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))::nil) ((Vobject a1,Vobject a5,Vobject a6)::(Vobject a2,Vobject a7,Vobject a3)::nil).
 Definition ses32 :=Sat_equation_system (a1::nil) (nil) ((Vobject a1,Vobject a2,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))))))))::(Vobject a1,Vobject a3,Cobject (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.top,Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot)))::nil).
 Definition ses33 :=Sat_equation_system (nil) (nil) ((Vobject a1,Vobject a2,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))))))))::(Vobject a1,Vobject a3,Cobject (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.top,Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot)))::nil).
 Definition ses34 :=Sat_equation_system (a1::nil) ((Vobject a1,Vobject a2)::(Vobject a2,Vobject a3)::(Vobject a3,Vobject a4)::(Vobject a4,Vobject a5)::(Vobject a5,Vobject a6)::(Vobject a6,Vobject a7)::(Vobject a7,Vobject a8)::nil) (nil).
 Definition ses35 :=Sat_equation_system (a1::nil) ((Vobject a1,Vobject a2)::(Vobject a2,Vobject a3)::(Vobject a3,Vobject a4)::(Vobject a4,Vobject a5)::(Vobject a5,Vobject a6)::(Vobject a6,Vobject a7)::(Vobject a7,Vobject a8)::nil) ((Vobject a1,Vobject a4,Vobject a8)::nil).
 Definition ses36 :=Sat_equation_system (nil) (nil) ((Vobject a1,Vobject a2,Cobject (Share.top))::(Vobject a2,Vobject a3,Cobject (Share.recompose (Share.bot,Share.top)))::(Vobject a3,Vobject a4,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))::(Vobject a4,Vobject a5,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))::(Vobject a5,Vobject a6,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))))::(Vobject a6,Vobject a7,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))))::(Vobject a7,Vobject a8,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))))))::nil).
 Definition ses37 :=Sat_equation_system (a1 ::nil) (nil) ((Vobject a1,Vobject a2,Cobject (Share.top))::(Vobject a2,Vobject a3,Cobject (Share.recompose (Share.bot,Share.top)))::(Vobject a3,Vobject a4,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))::(Vobject a4,Vobject a5,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))::(Vobject a5,Vobject a6,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))))::(Vobject a6,Vobject a7,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))))::(Vobject a7,Vobject a8,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))))))::nil).
 Definition ses38 :=Sat_equation_system (a1 ::nil) ((Vobject a1,Vobject a8)::nil) ((Vobject a1,Vobject a2,Cobject (Share.top))::(Vobject a2,Vobject a3,Cobject (Share.recompose (Share.bot,Share.top)))::(Vobject a3,Vobject a4,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))::(Vobject a4,Vobject a5,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))::(Vobject a5,Vobject a6,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))))::(Vobject a6,Vobject a7,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))))::(Vobject a7,Vobject a8,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))))))::nil).
 Definition ses39 :=Sat_equation_system (nil) (nil) ((Vobject a1,Vobject a2,Cobject (Share.top))::(Vobject a2,Vobject a3,Cobject (Share.recompose (Share.top,Share.bot)))::(Vobject a3,Vobject a4,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))::nil).
 Definition ses40 :=Sat_equation_system (a1 ::nil) (nil) ((Vobject a1,Vobject a2,Cobject (Share.top))::(Vobject a2,Vobject a3,Cobject (Share.recompose (Share.top,Share.bot)))::(Vobject a3,Vobject a4,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))::nil).
 Definition ses41 :=Sat_equation_system (a1 ::nil) (nil) ((Vobject a1,Vobject a2,Cobject (Share.top))::(Vobject a2,Vobject a3,Cobject (Share.recompose (Share.top,Share.bot)))::(Vobject a3,Vobject a4,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))::nil).
 Definition ses42 :=Sat_equation_system (nil) (nil) ((Vobject a1,Vobject a1,Vobject a1)::(Vobject a2,Vobject a2,Vobject a2)::(Vobject a1,Vobject a2,Vobject a3)::nil).
 Definition ses43 :=Sat_equation_system (a1 ::nil) (nil) ((Vobject a1,Vobject a1,Vobject a1)::(Vobject a2,Vobject a2,Vobject a2)::(Vobject a1,Vobject a2,Vobject a3)::nil).
 Definition ses44 :=Sat_equation_system (a ::nil) ((Vobject a,Vobject d)::(Vobject b,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))::nil) ((Vobject b,Vobject d,Vobject c)::(Vobject a,Vobject b,Vobject c)::nil).
 Definition ses45 :=Sat_equation_system (a ::nil) ((Vobject a,Vobject d)::(Vobject b,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))::nil) ((Vobject b,Vobject d,Vobject c)::(Vobject a,Vobject b,Vobject c)::(Vobject a,Vobject c,Vobject b)::nil).
 Definition ses46 :=Sat_equation_system (nil) ((Vobject a,Vobject b)::(Vobject c,Vobject a)::(Vobject d,Vobject b)::(Vobject c,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))))::(Vobject d,Cobject (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.top,Share.bot),Share.bot),Share.bot),Share.bot)))::nil) ((Vobject a,Vobject a,Vobject b)::(Vobject c,Vobject d,Vobject a)::nil).
 Definition ses47 :=Sat_equation_system (a ::nil) ((Vobject a,Vobject b)::(Vobject c,Vobject a)::(Vobject d,Vobject b)::(Vobject c,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))))::(Vobject d,Cobject (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.top,Share.bot),Share.bot),Share.bot),Share.bot)))::nil) ((Vobject a,Vobject a,Vobject b)::(Vobject c,Vobject d,Vobject a)::nil).
 Definition ses48 :=Sat_equation_system (a ::nil) ((Vobject a,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))))))::(Vobject b,Cobject (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.top,Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot)))::(Vobject c,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))))))::(Vobject d,Cobject (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.top,Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot)))::nil) (nil).
 Definition ses49 :=Sat_equation_system (a ::nil) ((Vobject a,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))))))::(Vobject b,Cobject (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.top,Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot)))::(Vobject c,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))))))::(Vobject d,Cobject (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.top,Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot),Share.bot)))::nil) ((Vobject a,Vobject b,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))))))))::(Vobject c,Vobject d,Cobject (Share.top))::nil).
 Definition ses50 :=Sat_equation_system (a1 ::nil) ((Vobject a1,Vobject a2)::(Vobject a3,Vobject a4)::(Vobject a5,Vobject a6)::(Vobject a7,Vobject a8)::nil) ((Vobject a1,Vobject a3,Vobject a5)::(Vobject a2,Vobject a4,Vobject a6)::nil).
 Definition ses51 :=Sat_equation_system (a1 ::nil) ((Vobject a1,Vobject a2)::(Vobject a3,Vobject a4)::(Vobject a5,Vobject a6)::(Vobject a7,Vobject a8)::nil) ((Vobject a1,Vobject a3,Vobject a5)::(Vobject a2,Vobject a4,Vobject a6)::(Vobject a7,Vobject a8,Vobject a1)::nil).
 Definition ses52 :=Sat_equation_system (a1 ::nil) ((Vobject a1,Vobject a2)::(Vobject a3,Vobject a4)::(Vobject a5,Vobject a6)::(Vobject a7,Vobject a8)::nil) ((Vobject a1,Vobject a3,Vobject a5)::(Vobject a2,Vobject a4,Vobject a6)::(Vobject a7,Vobject a8,Vobject a8)::nil).
 Definition ses53 :=Sat_equation_system (a1 ::nil) ((Vobject a1,Vobject a2)::(Vobject a3,Vobject a4)::(Vobject a5,Vobject a6)::(Vobject a7,Vobject a8)::nil) ((Vobject a1,Vobject a3,Vobject a5)::(Vobject a2,Vobject a4,Vobject a6)::(Vobject a7,Vobject a8,Vobject a8)::nil).
 Definition is15 :=(Impl_equation_system (nil) (a::nil) (nil) ((Vobject a,Vobject a,Vobject a)::nil),Impl_equation_system (nil) (nil) (nil) ((Vobject a1,Vobject a2,Vobject a3)::nil)).
 Definition is16 :=(Impl_equation_system (nil) (a1 ::nil) ((Vobject a9,Cobject (Share.recompose (Share.bot,Share.top)))::nil) ((Vobject a1,Vobject a2,Vobject a9)::(Vobject a3,Vobject a4,Vobject a1)::(Vobject a5,Vobject a6,Vobject a3)::(Vobject a7,Vobject a8,Vobject a5)::nil),Impl_equation_system (nil) (a9::nil) (nil) ((Vobject a1,Vobject a2,Cobject (Share.recompose (Share.bot,Share.top)))::nil)).
 Definition is17 :=(Impl_equation_system (nil) (a1::nil) (nil) (nil),Impl_equation_system (nil) (a1::nil) (nil) (nil)).
 Definition is18 :=(Impl_equation_system (nil) (a1::nil) (nil) (nil),Impl_equation_system (nil) (a2::nil) (nil) (nil)).
 Definition is19 :=(Impl_equation_system (nil) (a1::nil) (nil) ((Vobject a1,Vobject a2,Vobject a3)::nil),Impl_equation_system (nil) (a3::nil) (nil) (nil)).
 Definition is20 :=(Impl_equation_system (nil) (a1::nil) (nil) ((Vobject a1,Vobject a2,Vobject a3)::nil),Impl_equation_system (nil) (a2::nil) (nil) (nil)).
 Definition is21 :=(Impl_equation_system (nil) (a1::nil) (nil) ((Vobject a1,Vobject a2,Vobject a3)::(Vobject a3,Vobject a4,Vobject a5)::(Vobject a5,Vobject a6,Vobject a7)::(Vobject a7,Vobject a8,Vobject a9)::(Vobject a9,Vobject a10,Vobject a11)::(Vobject a11,Vobject a12,Vobject a13)::(Vobject a13,Vobject a14,Vobject a15)::nil),Impl_equation_system (nil) (a15::nil) (nil) (nil)).
 Definition is22 :=(Impl_equation_system (nil) (a1::nil) (nil) ((Vobject a1,Vobject a2,Vobject a3)::(Vobject a3,Vobject a4,Vobject a5)::(Vobject a5,Vobject a6,Vobject a7)::(Vobject a7,Vobject a8,Vobject a9)::(Vobject a9,Vobject a10,Vobject a11)::(Vobject a11,Vobject a12,Vobject a13)::(Vobject a13,Vobject a14,Vobject a15)::nil),Impl_equation_system (nil) (a14::nil) (nil) (nil)).
 Definition is23 :=(Impl_equation_system (nil) (nil) (nil) ((Vobject a1,Vobject a1,Vobject a1)::(Vobject a2,Vobject a2,Vobject a2)::(Vobject a1,Vobject a2,Vobject a3)::nil),Impl_equation_system (nil) (nil) ((Vobject a3,Cobject (Share.bot))::nil) (nil)).
 Definition is24 :=(Impl_equation_system (nil) (nil) (nil) ((Vobject a1,Vobject a1,Vobject a1)::(Vobject a2,Vobject a2,Vobject a2)::(Vobject a1,Vobject a2,Vobject a3)::nil),Impl_equation_system (nil) (a3::nil) (nil) (nil)).
 Definition is25 :=(Impl_equation_system (nil) (nil) ((Vobject a,Cobject (Share.bot))::nil) (nil),Impl_equation_system (nil) (a::nil) (nil) (nil)).
 Definition is26 :=(Impl_equation_system (nil) (a::nil) ((Vobject a,Cobject (Share.bot))::nil) (nil),Impl_equation_system (nil) (a::nil) (nil) (nil)).
 Definition is27 :=(Impl_equation_system (nil) (nil) (nil) ((Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))),Vobject a,Vobject b)::nil),Impl_equation_system (nil) (a::nil) (nil) (nil)).
 Definition is28 :=(Impl_equation_system (nil) (nil) (nil) ((Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))),Vobject a,Vobject b)::nil),Impl_equation_system (nil) (b::nil) (nil) (nil)).
 Definition is29 :=(Impl_equation_system (nil) (a9::nil) (nil) ((Vobject a1,Vobject a2,Vobject a3)::(Vobject a3,Vobject a4,Vobject a5)::(Vobject a5,Vobject a6,Vobject a7)::(Vobject a7,Vobject a8,Vobject a9)::nil),Impl_equation_system (nil) (a1::nil) (nil) (nil)).
 Definition is30 :=(Impl_equation_system (nil) (a1::nil) (nil) ((Vobject a1,Vobject a2,Vobject a3)::(Vobject a3,Vobject a4,Vobject a5)::(Vobject a5,Vobject a6,Vobject a7)::(Vobject a7,Vobject a8,Vobject a9)::nil),Impl_equation_system (nil) (a9::nil) (nil) (nil)).
 Definition is31 :=(Impl_equation_system (nil) (a9::nil) (nil) ((Vobject a1,Vobject a2,Vobject a3)::(Vobject a3,Vobject a4,Vobject a5)::(Vobject a5,Vobject a6,Vobject a7)::(Vobject a7,Vobject a8,Vobject a9)::(Vobject a8,Vobject a8,Vobject a8)::(Vobject a6,Vobject a6,Vobject a6)::(Vobject a4,Vobject a4,Vobject a4)::(Vobject a2,Vobject a2,Vobject a2)::nil),Impl_equation_system (nil) (a1::nil) (nil) (nil)).
 Definition is32 :=(Impl_equation_system (nil) (a::nil) (nil) ((Vobject a,Vobject a,Vobject a)::nil),Impl_equation_system (nil) (a1 ::nil) ((Vobject a5,Vobject a6)::(Vobject a2,Vobject a4)::(Vobject a4,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top)))))::nil) ((Vobject a1,Vobject a3,Vobject a8)::(Vobject a2,Vobject a8,Vobject a4)::nil)).
 Definition is33 :=(Impl_equation_system (nil) (nil) (nil) ((Vobject a,Vobject a,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))))))))::nil),Impl_equation_system (nil) (a::nil) (nil) (nil)).
 Definition is34 :=(Impl_equation_system (nil) (nil) (nil) ((Vobject a,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))))))),Vobject a)::nil),Impl_equation_system (nil) (a::nil) (nil) (nil)).
 Definition is35 :=(Impl_equation_system (nil) (nil) (nil) ((Cobject (Share.recompose (Share.bot,Share.top)),Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.top,Share.bot))))),Vobject a)::nil),Impl_equation_system (nil) (a::nil) (nil) (nil)).
 Definition is36 :=(Impl_equation_system (nil) (nil) (nil) (nil),Impl_equation_system (nil) (a ::nil) ((Vobject a,Vobject c)::(Vobject a,Cobject (Share.top))::(Vobject b,Cobject (Share.top))::nil) ((Vobject a,Vobject b,Vobject c)::nil)).
 Definition is37 :=(Impl_equation_system (nil) (a ::nil) ((Vobject a,Cobject (Share.recompose (Share.top,Share.bot)))::(Vobject b,Cobject (Share.recompose (Share.bot,Share.top)))::nil) ((Vobject a,Vobject b,Vobject c)::nil),Impl_equation_system (nil) (c::nil) ((Vobject c,Cobject (Share.top))::nil) (nil)).
 Definition is38 :=(Impl_equation_system (nil) (a ::nil) ((Vobject a,Cobject (Share.recompose (Share.top,Share.bot)))::(Vobject b,Cobject (Share.recompose (Share.bot,Share.top)))::nil) ((Vobject a,Vobject b,Vobject c)::nil),Impl_equation_system (nil) (c::nil) ((Vobject c,Cobject (Share.top))::nil) ((Vobject a,Vobject b,Vobject a)::nil)).
 Definition is39 :=(Impl_equation_system (nil) (a ::nil) ((Vobject a,Cobject (Share.recompose (Share.top,Share.bot)))::(Vobject b,Cobject (Share.recompose (Share.bot,Share.top)))::nil) ((Vobject a,Vobject b,Vobject c)::nil),Impl_equation_system (nil) (c::nil) ((Vobject c,Cobject (Share.top))::nil) ((Vobject a,Vobject b,Vobject c)::nil)).
 Definition is40 :=(Impl_equation_system (nil) (a1::nil) ((Vobject a1,Vobject a2)::nil) (nil),Impl_equation_system (nil) (a2::nil) (nil) (nil)).
 Definition is41 :=(Impl_equation_system (nil) (nil) (nil) ((Vobject a1,Vobject a2,Cobject (Share.top))::(Vobject a3,Vobject a4,Vobject a1)::(Vobject a5,Vobject a6,Vobject a3)::(Vobject a7,Vobject a8,Vobject a5)::nil),Impl_equation_system (nil) (a1 ::nil) (nil) (nil)).
 Definition is42 :=(Impl_equation_system (nil) (a8::nil) (nil) ((Vobject a1,Vobject a2,Cobject (Share.top))::(Vobject a3,Vobject a4,Vobject a1)::(Vobject a5,Vobject a6,Vobject a3)::(Vobject a7,Vobject a8,Vobject a5)::nil),Impl_equation_system (nil) (a5 ::nil) (nil) (nil)).
 Definition is43 :=(Impl_equation_system (nil) (a8::nil) (nil) ((Vobject a1,Vobject a2,Cobject (Share.top))::(Vobject a3,Vobject a4,Vobject a1)::(Vobject a5,Vobject a6,Vobject a3)::(Vobject a7,Vobject a8,Vobject a5)::nil),Impl_equation_system (nil) (a2::nil) (nil) (nil)).
 Definition is44 :=(Impl_equation_system (nil) (a1 ::nil) (nil) ((Vobject a2,Vobject a2,Vobject a1)::nil),Impl_equation_system (nil) (a2 ::nil) (nil) (nil)).
 Definition is45 :=(Impl_equation_system (nil) (a1::nil) (nil) ((Vobject a2,Vobject a3,Vobject a1)::nil),Impl_equation_system (nil) (a2::nil) (nil) (nil)).
 Definition is46 :=(Impl_equation_system (nil) (nil) (nil) ((Vobject a1,Vobject a2,Vobject a3)::(Vobject a3,Vobject a2,Vobject a5)::(Vobject a3,Vobject a5,Vobject a2)::(Vobject a1,Vobject a4,Vobject a6)::(Vobject a5,Vobject a3,Vobject a8)::nil),Impl_equation_system (nil) (a1::nil) (nil) (nil)).
 Definition is47 :=(Impl_equation_system (nil) (nil) (nil) ((Cobject (Share.top),Cobject (Share.top),Cobject (Share.top))::nil),Impl_equation_system (nil) (a1 ::nil) ((Vobject a1,Vobject a8)::(Vobject a1,Cobject (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.top,Share.bot),Share.bot),Share.bot),Share.bot)))::(Vobject a8,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))))::nil) ((Vobject a3,Vobject a4,Vobject a5)::nil)).
 Definition is48 :=(Impl_equation_system (nil) (nil) (nil) ((Cobject (Share.recompose (Share.bot,Share.top)),Cobject (Share.recompose (Share.top,Share.bot)),Cobject (Share.top))::nil),Impl_equation_system (nil) (a1 ::nil) ((Vobject a1,Vobject a8)::(Vobject a1,Cobject (Share.recompose (Share.recompose (Share.recompose (Share.recompose (Share.top,Share.bot),Share.bot),Share.bot),Share.bot)))::(Vobject a8,Cobject (Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.recompose (Share.bot,Share.top))))))::nil) ((Vobject a3,Vobject a4,Vobject a5)::nil)).
 Definition is49 :=(Impl_equation_system (nil) (nil) (nil) ((Cobject (Share.recompose (Share.bot,Share.top)),Cobject (Share.recompose (Share.top,Share.bot)),Cobject (Share.top))::nil),Impl_equation_system (nil) (nil) (nil) ((Cobject (Share.recompose (Share.recompose (Share.bot,Share.top),Share.recompose (Share.bot,Share.top))),Cobject (Share.recompose (Share.recompose (Share.top,Share.bot),Share.recompose (Share.top,Share.bot))),Cobject (Share.top))::nil)).

 Definition l :=
 (ses1::ses2::ses3::ses4::ses5::ses6::(*ses7::ses8::ses9::*)ses10::
  ses11::ses12::ses13::ses14::ses15::ses16::ses17::ses18::ses19::ses20::
  ses21::ses22::ses23::ses24::ses25::ses26::ses27::ses28::ses29::ses30::
  ses31::ses32::ses33::ses34::ses35::ses36::ses37::ses38::ses39::ses40::
  ses41::ses42::ses43::ses44::ses45::ses46::ses47::ses48::ses49::ses50::
  ses51::ses52::ses53::nil).
 (*
 Time Eval compute in (map SATsolver l).
 *)
 (*16.1s*)

 Definition l' :=
 (
 is1::is2::is3::is4::is5::is6::is7::is8::is9::is10::
 (*is11::*)is12::is13::is14::is15::is16::is17::is18::is19::is20::
 is21::is22::is23::is24::is25::is26::is27::is28::is29::is30::
 is31::is32::is33::is34::is35::is36::is37::is38::is39::is40::
 is41::is42::is43::is44::is45::is46::is47::is48::is49::nil
 ).
 (*
 Time Eval compute in (map IMPLsolver l').
 *)
 (*8.9s*)

End Tester.


(*
Copyright © 2009 Valentin Blot

Permission is hereby granted, free of charge, to any person obtaining a copy of
this proof and associated documentation files (the "Proof"), to deal in
the Proof without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Proof, and to permit persons to whom the Proof is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Proof.

THE PROOF IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE PROOF OR THE USE OR OTHER DEALINGS IN THE PROOF.
*)
Require Import CPoly_Degree.
Require Import CRing_Homomorphisms.
Require Import CoRN.model.ordfields.Qordfield.
Require Import CauchySeq.
Require Import Q_in_CReals.

Require Import CPoly_Euclid RingClass CRingClass.
Require Import Q_can nat_Q_lists RX_deg RX_div QX_root_loc.

Section Z_Q.

Let QX := cpoly_cring Q_as_CRing.
Add Ring q_r : (r_rt (Ring:=CRing_is_Ring Q_as_CRing)).
Add Ring qx_r : (r_rt (Ring:=CRing_is_Ring (cpoly_cring Q_as_CRing))).

Let QX_dec := RX_dec Q_as_CRing Q_dec.
Let QX_deg := RX_deg Q_as_CRing Q_dec.

Fixpoint QX_test_list (P : QX) (l : list Q_as_CRing) : option Q_as_CRing :=
  match l with
    | nil => None
    | cons q l => match Q_dec (P ! q) [0] with inl _ => Some q | inr _ => QX_test_list P l end
  end.

Lemma QX_test_list_spec_none : forall P l, QX_test_list P l = None ->
        forall q : Q_as_CRing, In q l -> P ! q [#] [0].
Proof.
 induction l.
  intros; contradiction.
 unfold QX_test_list.
 case (Q_dec P ! a [0]).
  intros; discriminate.
 fold (QX_test_list P l).
 intros Hap Hnone q.
 simpl (In q (a::l)).
 case (Q_dec a q).
  intros Haq Hin Hval.
  destruct Hap.
  rewrite -> Haq; assumption.
 intros.
 apply IHl.
  assumption.
 destruct H.
  destruct c; rewrite H; reflexivity.
 assumption.
Qed.

Lemma QX_test_list_spec_some : forall P l x, QX_test_list P l = Some x ->
        P ! x [=] [0].
Proof.
 induction l.
  intros; discriminate.
 unfold QX_test_list.
 fold (QX_test_list P l).
 case (Q_dec P ! a [0]); [|intro; assumption].
 intros.
 injection H; intro.
 rewrite <- H0; assumption.
Qed.

Let P0 (P : QX) := nth_coeff 0 (QX_ZX.qx2zx P).
Let Pn (P : QX) := nth_coeff (QX_deg P) (QX_ZX.qx2zx P).

Definition QX_find_root (P : QX) : option Q_as_CRing :=
    match Q_dec (P ! [0]) [0] with inl _ => Some [0] | inr _ => QX_test_list P (list_Q (P0 P) (Pn P)) end.

Lemma QX_find_root_spec_none : forall P, QX_find_root P = None -> forall q : Q_as_CRing, P ! q [#] [0].
Proof.
 intro P; unfold QX_find_root.
 case (Q_dec P ! [0] [0]).
  intros; discriminate.
 intros Hap Hnone q.
 assert (forall x y : Q_as_CRing, {x = y} + {x <> y}).
  clear; intros x y.
  destruct x; destruct y; simpl.
  case (Z.eq_dec Qnum Qnum0); case (Z.eq_dec Qden Qden0); intros H1 H2.
     left; f_equal; [assumption|injection H1; tauto].
    right; intro H3; injection H3; intros; destruct H1; f_equal; assumption.
   right; intro H3; injection H3; intros; destruct H2; assumption.
  right; intro H3; injection H3; intros; destruct H2; assumption.
 destruct (In_dec X (Q_can q) (list_Q (P0 P) (Pn P))).
  intro H; rewrite -> (Q_can_spec q) in H; revert H.
  apply (QX_test_list_spec_none _ _ Hnone _ i).
 intro Hval; apply n.
 apply QX_root_loc; assumption.
Qed.

Lemma QX_find_root_spec_some : forall P x, QX_find_root P = Some x -> P ! x [=] [0].
Proof.
 intros P x; unfold QX_find_root.
 case (Q_dec P ! [0] [0]).
  intros H1 H2; injection H2; intro H3; rewrite <- H3; assumption.
 intro Hap; apply QX_test_list_spec_some.
Qed.

Lemma QX_integral : forall p q : QX, p [#] [0] -> q [#] [0] -> p[*]q [#] [0].
Proof.
 intros p q Hp Hq.
 apply (nth_coeff_strext _ (QX_deg p + QX_deg q)).
 simpl (nth_coeff (QX_deg p + QX_deg q) ([0]:QX)).
 cut (degree (QX_deg p + QX_deg q) (p[*]q)).
  intro H; apply H.
 apply (degree_mult Q_as_CField).
  apply RX_deg_spec; assumption.
 apply RX_deg_spec; assumption.
Qed.

Lemma QX_deg_mult : forall p q, p [#] [0] -> q [#] [0] ->
           QX_deg (p[*]q) = QX_deg p + QX_deg q.
Proof.
 intros p q Hp Hq.
 set (RX_deg_spec _ Q_dec _ Hp).
 set (RX_deg_spec _ Q_dec _ Hq).
 set (degree_mult Q_as_CField _ _ _ _ d d0).
 fold QX_deg in d1.
 apply (degree_inj _ (p[*]q)); [|assumption].
 apply RX_deg_spec.
 apply QX_integral; assumption.
Qed.

Lemma QX_div_deg0 : forall (p : QX) (a : Q_as_CRing),
              QX_deg p <> 0 -> RX_div _ p a [#] [0].
Proof.
 intros p a Hdeg.
 case (QX_dec (RX_div _ p a) [0]); [|tauto].
 intro Heq; destruct Hdeg; revert Heq.
 unfold RX_div.
 destruct (cpoly_div p (_X_monic _ a)) as [[q r] _ [s [d s0]]].
 unfold fst, snd in *.
 intro Hq.
 rewrite -> Hq in s.
 assert (H : p [=] r); [rewrite -> s; unfold cg_minus; unfold QX; ring|].
 unfold QX_deg; rewrite (RX_deg_wd _ Q_dec _ _ H); fold QX_deg.
 destruct (_X_monic _ a).
 destruct (degree_le_zero _ _ (d _ H1)).
 unfold QX_deg; rewrite (RX_deg_wd _ Q_dec _ _ s1).
 rewrite RX_deg_c_; reflexivity.
Qed.

Lemma QX_div_deg : forall (p : QX) (a : Q_as_CRing),
          QX_deg p <> 0 -> QX_deg p = S (QX_deg (RX_div _ p a)).
Proof.
 intros p a Hdeg.
 case_eq (QX_deg p).
  intro; destruct Hdeg; assumption.
 intros n Heq.
 f_equal.
 revert Heq.
 unfold QX_deg; rewrite (RX_deg_wd _ Q_dec _ _ (RX_div_spec _ p a)).
 rewrite RX_deg_sum.
  rewrite max_comm.
  rewrite -> QX_deg_mult.
    unfold QX_deg; rewrite RX_deg_minus.
     rewrite RX_deg_c_, RX_deg_x_, RX_deg_c_; fold QX_deg.
     simpl; rewrite plus_comm; simpl.
     intro H; injection H; symmetry; assumption.
    rewrite RX_deg_x_, RX_deg_c_; discriminate.
   apply QX_div_deg0; assumption.
  right; left; discriminate.
 rewrite RX_deg_c_.
 rewrite -> QX_deg_mult.
   unfold QX_deg; rewrite RX_deg_minus.
    rewrite RX_deg_x_, RX_deg_c_.
    rewrite plus_comm; discriminate.
   rewrite RX_deg_x_, RX_deg_c_; discriminate.
  apply QX_div_deg0; assumption.
 right; left; discriminate.
Qed.

Fixpoint QX_extract_roots_rec (n : nat) (P : QX) :=
  match n with
    | O => P
    | S n =>
      match QX_find_root P with
        | None => P
        | Some x => QX_extract_roots_rec n (RX_div _ P x)
      end
  end.

Definition QX_extract_roots (P : QX) := QX_extract_roots_rec (QX_deg P) P.

Lemma QX_extract_roots_spec_rat : forall P a,
       P [#] [0] -> (QX_extract_roots P) ! a [#] [0].
Proof.
 unfold QX_extract_roots.
 intros P a; remember (QX_deg P) as n; revert P Heqn.
 induction n.
  intros P Hdeg Hap; unfold QX_extract_roots_rec.
  destruct (RX_deg_spec _ Q_dec _ Hap).
  fold QX_deg in d; rewrite <- Hdeg in d.
  destruct (degree_le_zero _ _ d).
  case (Q_dec P ! a [0]); [|tauto].
  intro Heq; destruct (ap_imp_neq _ _ _ Hap); clear Hap; revert Heq.
  rewrite -> s, c_apply; intro H; rewrite -> H; split; [reflexivity|apply I].
 unfold QX_extract_roots_rec.
 intros P Hdeg Hap.
 case_eq (QX_find_root P).
  intros x Hsome; fold (QX_extract_roots_rec n (RX_div _ P x)).
  apply IHn.
   apply eq_add_S.
   rewrite <- QX_div_deg; [assumption|].
   rewrite <- Hdeg; discriminate.
  case (QX_dec (RX_div _ P x) [0]); [|tauto].
  intro Heq; apply QX_div_deg0.
  rewrite <- Hdeg; discriminate.
 intro; apply QX_find_root_spec_none; assumption.
Qed.

Definition inj_Q_fun := Build_CSetoid_fun _ _ _ (inj_Q_strext IR).
Lemma inj_Q_pres_plus : fun_pres_plus _ _ inj_Q_fun.
Proof. intros x y; apply inj_Q_plus. Qed.
Lemma inj_Q_pres_unit : fun_pres_unit _ _ inj_Q_fun.
Proof. apply inj_Q_One. Qed.
Lemma inj_Q_pres_mult : fun_pres_mult _ _ inj_Q_fun.
Proof. intros x y; apply inj_Q_mult. Qed.
Definition inj_Q_rh := Build_RingHom _ _ inj_Q_fun inj_Q_pres_plus inj_Q_pres_mult inj_Q_pres_unit.
Definition inj_QX_rh := cpoly_map inj_Q_rh.

Lemma QX_extract_roots_spec_nrat : forall (P : QX) (x : IR),
      (forall y : Q_as_CRing, x [~=] (inj_Q_rh y)) ->
         (inj_QX_rh P) ! x [=] [0] -> (inj_QX_rh (QX_extract_roots P)) ! x [=] [0].
Proof.
 intros P x Hx; unfold QX_extract_roots.
 remember (QX_deg P) as n; revert P Heqn; induction n.
  intros; unfold QX_extract_roots_rec; assumption.
 intros P Hdeg Hval; unfold QX_extract_roots_rec; fold (QX_extract_roots_rec).
 case_eq (QX_find_root P); [|intro; assumption].
 intros y Hsome.
 apply IHn.
  apply eq_add_S.
  rewrite Hdeg; apply QX_div_deg.
  rewrite <- Hdeg; discriminate.
 clear IHn; revert Hval.
 rewrite -> (RX_div_spec _ P y) at 1.
 rewrite -> rh_pres_plus.
 rewrite -> rh_pres_mult.
 rewrite -> rh_pres_minus.
 rewrite -> (cpoly_map_X _ _ inj_Q_rh).
 rewrite -> (cpoly_map_C _ _ inj_Q_rh).
 rewrite -> (cpoly_map_C _ _ inj_Q_rh).
 rewrite -> plus_apply.
 rewrite -> mult_apply.
 rewrite -> minus_apply.
 rewrite -> x_apply.
 rewrite -> c_apply.
 rewrite -> c_apply.
 rewrite -> (QX_find_root_spec_some _ _ Hsome).
 rewrite -> rh_pres_zero.
 rewrite -> cm_rht_unit.
 rewrite -> mult_commutes.
 set (H := Hx y); revert H; generalize (RX_div Q_as_CRing P y).
 clear; intros P Hap Heq.
 apply (mult_eq_zero IR (x[-]inj_Q_rh y)); [|assumption].
 intro; apply Hap.
 apply cg_inv_unique_2; assumption.
Qed.

End Z_Q.


(** * Lan and Colimit **)
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.

Generalizable All Variables.

Set Primitive Projections.
Set Universe Polymorphism.

Require Import COC.Base.Main COC.Cons.Terminal COC.Limit.Colimit COC.KanExt.Lan.

Program Definition colimit_from_lan
        (C D: Category)
        (F: C --> D)
        (lan: Lan F (ToOne C))
  : Colimit F :=
  [Colimit [Cocone by (lanN lan) to (lanF lan tt)]
    by `(lanU lan (S:=constant_functor One D (c: Cocone F)) [i :=> c i] tt) ].
Next Obligation.
  rewrite (natrans_naturality (IsNatrans:=lanN lan)); simpl.
  now rewrite (fmap_id (F:=lanF lan) tt), cat_comp_id_cod.
Qed.
Next Obligation.
  now rewrite cocone_commute, cat_comp_id_cod.
Qed.
Next Obligation.
  generalize (lan_universality (IsLan:=lan)(S:=[* in One |-> c in D])); simpl.
  intros H; apply H.

  generalize (lan_uniqueness (IsLan:=lan)(S:=[* in One |-> c in D])); simpl.
  intros Huniq; eapply (Huniq _ [x :=> match x with
                                       | tt => u
                                       end
                                   from (lanF lan) to [* in One |-> c in D]]); simpl.
  now apply H.
  Grab Existential Variables.
  split.
  intros [] [] []; simpl.
  now rewrite (fmap_id (F:=lanF lan)), cat_comp_id_dom, cat_comp_id_cod.
Qed.

Program Definition lan_from_colimit
        (C D: Category)
        (F: C --> D)
        (colim: Colimit F)
  : Lan F (ToOne C) :=
  [Lan by (fun S (e: F ==> (S \o ToOne C)) =>
           [ x :=> match x with
                   | tt => colimit_univ colim [Cocone by e to S tt]
                   end])
   with [Functor by f :-> Id colim], [ c in C :=> colim c]].
Next Obligation.
  now rewrite cat_comp_id_dom.
Qed.
Next Obligation.
  now rewrite cocone_commute, cat_comp_id_cod.
Qed.
Next Obligation.
  rewrite (natrans_naturality (IsNatrans:=e)); simpl.
  now rewrite (fmap_id (F:=S) tt), cat_comp_id_cod.
Qed.
Next Obligation.
  destruct X, Y, f.
  now rewrite cat_comp_id_dom, (fmap_id (F:=S) tt), cat_comp_id_cod.
Qed.
Next Obligation.
  generalize (colimit_universality (IsColimit:=colim)); simpl.
  intros H; apply (H [Cocone by e to S tt] X).
  destruct X.
  generalize (colimit_uniqueness (IsColimit:=colim)); intros Huniq.
  now apply (Huniq [Cocone by e to S tt]), H.
Qed.


Load Integers.
Load AS_State.
Load AS_Int_Impl.
Load AS_Int.

(* The execution of single instruction *)
Definition exec :instruction -> state -> state :=
  fun inst state => match state with
  | createState stack pc reg_0 reg_1 reg_2 reg_3 =>
      match inst with
      |inst_pushbyte n => exec_pushbyte (data n false false) state
      |inst_pop => exec_pop state
      |inst_getlocal_0 => exec_getLocal state 0
      |inst_getlocal_1 => exec_getLocal state 1
      |inst_getlocal_2 => exec_getLocal state 2
      |inst_getlocal_3 => exec_getLocal state 3
      |inst_setlocal_0 => exec_setLocal state 0
      |inst_setlocal_1 => exec_setLocal state 1
      |inst_setlocal_2 => exec_setLocal state 2
      |inst_setlocal_3 => exec_setLocal state 3
      |inst_add        => exec_add state
      |inst_convert_i  => convertIFromState state
      |_ => state
      end
  end.

(* The execution of list of instructions *)
Fixpoint startExec (inst_seq:list instruction) (s:state) : state :=
  match inst_seq with
 | nil => s
 | cons x t' => startExec t' (exec x s)
  end.


Require Import
        Coq.Structures.OrderedTypeEx
        Coq.Structures.OrderedType
        Coq.FSets.FMapAVL
        Coq.Strings.Ascii.

Require Import
        Fiat.BinEncoders.Env.Common.Specs
        Fiat.BinEncoders.Env.Common.Sig
        Fiat.BinEncoders.Env.Common.Compose.

Require Import
        Fiat.BinEncoders.Env.BinLib.Core
        Fiat.BinEncoders.Env.BinLib.FixInt
        Fiat.BinEncoders.Env.BinLib.Char
        Fiat.BinEncoders.Env.BinLib.Bool
        Fiat.BinEncoders.Env.BinLib.Enum
        Fiat.BinEncoders.Env.Lib.FixList
        Fiat.BinEncoders.Env.Lib.IList
        Fiat.BinEncoders.Env.Lib.SteppingCacheList.

Set Implicit Arguments.

Module list_as_OT (O : OrderedType) <: OrderedType.
  (* http://www.ensiie.fr/~robillard/Graph_Library/ *)
  Import O.
  Module Import OP := OrderedTypeFacts O.

  Definition t := list O.t.
  Definition eq := eqlistA O.eq.

  Inductive lt_ : t -> t -> Prop :=
  | ltnil : forall a l, lt_ nil (a :: l)
  | ltcons : forall a l a' l', O.lt a a' -> lt_ (a :: l) (a' :: l')
  | lt_tail : forall a a' l l', O.eq a a' -> lt_ l l' -> lt_ (a :: l) (a' :: l').

  Definition lt := lt_.

  Lemma eq_dec : forall l l', {eq l l'} + {~eq l l'}.
  Proof.
    unfold eq; induction l; intros.
    destruct l'. left. abstract intuition.
    right. abstract (intro; inversion H).
    destruct l'. right. abstract (intro; inversion H).
    destruct (IHl l').
    destruct (O.eq_dec a t0). left. abstract (constructor; auto).
    right. abstract (intro; elim n; inversion H; auto).
    right. abstract (intro; elim n; inversion H; auto).
  Defined.

  Lemma eq_refl : forall x, eq x x.
  Proof.
    unfold eq; induction x; intros. auto.
    constructor; auto.
  Qed.

  Lemma eq_sym : forall x y, eq x y -> eq y x.
  Proof.
    unfold eq; induction x; intros.
    inversion H; auto.
    destruct y. inversion H.
    inversion H. subst.
    constructor. auto. auto.
  Qed.

  Lemma eq_trans : forall x y z, eq x y -> eq y z -> eq x z.
  Proof.
    induction x; unfold eq; intros.
    inversion H. subst. inversion H0. subst. auto.
    destruct y. inversion H.
    destruct z. inversion H0.
    constructor. inversion H; inversion H0; subst.
    eapply O.eq_trans; eauto.
    eapply IHx; inversion H; inversion H0; subst; eauto.
  Qed.

  Lemma lt_trans : forall x y z, lt x y -> lt y z -> lt x z.
  Proof.
    induction x; unfold lt; intros.
    inversion H; subst.
    inversion H0; subst.
    constructor.
    constructor.
    inversion H; subst.
    inversion H0; subst.
    constructor. eapply O.lt_trans; eauto.
    inversion H0; subst.
    constructor.
    rewrite <-H3. auto.
    constructor.
    rewrite <-H3. auto.
    inversion H0; subst.
    constructor.
    rewrite H3. auto.
    apply lt_tail. rewrite H3. auto. eapply IHx; eauto.
  Qed.

  Lemma lt_not_eq : forall x y, lt x y -> ~eq x y.
  Proof.
    induction x; unfold lt, eq; intros; intro.
    inversion H; subst.
    inversion H0.
    destruct y. inversion H0.
    inversion H0; subst.
    inversion H; subst.
    elim (O.lt_not_eq H2 H4).
    eapply IHx; eauto.
  Qed.

  Lemma compare : forall x y, Compare lt eq x y.
  Proof.
    induction x; intros.
    destruct y.
    apply EQ. apply eq_refl.
    apply LT. constructor.
    destruct y. apply GT. constructor.
    destruct (O.compare a t0).
    apply LT. constructor. auto.
    destruct (IHx y).
    apply LT. apply lt_tail; auto.
    apply EQ. constructor; auto.
    apply GT. apply lt_tail; auto.
    apply GT. constructor. auto.
  Defined.
End list_as_OT.

Module Type OrderedTypeWithP (O : OrderedType).
  Parameter P : O.t -> Prop.
End OrderedTypeWithP.

Module sig_as_OT (O : OrderedType) (O' : OrderedTypeWithP O) <: OrderedType.
  Import O.
  Module Import OP := OrderedTypeFacts O.

  Definition t := sig O'.P.
  Definition eq (t1 t2 : t) := O.eq (proj1_sig t1) (proj1_sig t2).
  Definition lt (t1 t2 : t) := O.lt (proj1_sig t1) (proj1_sig t2).

  Lemma eq_dec : forall l l', {eq l l'} + {~eq l l'}.
  Proof. intros; destruct l; destruct l'; apply O.eq_dec. Defined.

  Lemma eq_refl : forall x, eq x x.
  Proof. intros; destruct x; apply O.eq_refl. Qed.

  Lemma eq_sym : forall x y, eq x y -> eq y x.
  Proof. intros; destruct x; destruct y; unfold eq in *; apply O.eq_sym; eauto. Qed.

  Lemma eq_trans : forall x y z, eq x y -> eq y z -> eq x z.
  Proof. intros; destruct x; destruct y; destruct z; unfold eq in *; eapply eq_trans; eauto. Qed.

  Lemma lt_trans : forall x y z, lt x y -> lt y z -> lt x z.
  Proof. intros; destruct x; destruct y; destruct z; unfold lt in *; eapply lt_trans; eauto. Qed.

  Lemma lt_not_eq : forall x y, lt x y -> ~eq x y.
  Proof. intros; destruct x; destruct y; apply O.lt_not_eq; eauto. Qed.

  Lemma compare : forall x y, Compare lt eq x y.
  Proof.
    intros; destruct x; destruct y.
    unfold lt, eq.
    destruct (O.compare x x0) eqn: eq; [ eapply LT | eapply EQ | eapply GT ]; eauto.
  Defined.
End sig_as_OT.

Module ascii_as_OT <: OrderedType.
  Definition t := ascii.
  Definition eq (c1 c2 : t) := N_of_ascii c1 = N_of_ascii c2.
  Definition lt (c1 c2 : t) := N.lt (N_of_ascii c1) (N_of_ascii c2).

  Lemma eq_dec : forall l l', {eq l l'} + {~eq l l'}.
  Proof. unfold eq. intros.
         destruct (N.eqb (N_of_ascii l) (N_of_ascii l')) eqn: eq.
         - left. abstract (rewrite <- N.eqb_eq; eauto).
         - right. abstract (rewrite <- N.eqb_neq; eauto).  Defined.

  Lemma eq_refl : forall x, eq x x.
  Proof. reflexivity. Qed.

  Lemma eq_sym : forall x y, eq x y -> eq y x.
  Proof. intros. symmetry. eauto. Qed.

  Lemma eq_trans : forall x y z, eq x y -> eq y z -> eq x z.
  Proof. intros. unfold eq in *. rewrite H. rewrite H0. eauto. Qed.

  Lemma lt_trans : forall x y z, lt x y -> lt y z -> lt x z.
  Proof. intros. unfold lt in *. eapply N.lt_trans; eauto. Qed.

  Lemma lt_not_eq : forall x y, lt x y -> ~eq x y.
  Proof. intros. unfold eq, lt in *. intro.
         rewrite <- N.compare_lt_iff in H.
         rewrite <- N.compare_eq_iff in H0.
         congruence. Qed.

  Lemma compare : forall x y, Compare lt eq x y.
  Proof.
    intros. unfold lt, eq.
    destruct (N.compare (N_of_ascii x) (N_of_ascii y)) eqn: eq.
    - eapply EQ. abstract (rewrite <- N.compare_eq_iff; eauto).
    - eapply LT. abstract (rewrite <- N.compare_lt_iff; eauto).
    - eapply GT. abstract (rewrite <- N.compare_gt_iff; eauto).
  Defined.
End ascii_as_OT.

Record word_t :=
  { word : { l : list ascii | length l < exp2_nat 6 } }.
Definition position_t := uint 14.

Module list_ascii_as_OT := list_as_OT ascii_as_OT.
Module list_ascii_as_OT_with_P <: OrderedTypeWithP list_ascii_as_OT.
  Definition P (l : list ascii) := length l < exp2_nat 6.
End list_ascii_as_OT_with_P.

Module word_as_OT := sig_as_OT list_ascii_as_OT list_ascii_as_OT_with_P.

Module N_as_OT_with_P <: OrderedTypeWithP N_as_OT.
  Definition P (n : N) := (n < exp2 14)%N.
End N_as_OT_with_P.

Module position_as_OT := sig_as_OT N_as_OT N_as_OT_with_P.

Module word_t_as_OT <: OrderedType.
  Import word_as_OT.

  Definition t := word_t.
  Definition eq (a b : word_t) := eq a.(word) b.(word).
  Definition lt (a b : word_t) := lt a.(word) b.(word).

  Lemma eq_dec : forall l l', {eq l l'} + {~eq l l'}.
  Proof.
    destruct l; destruct l'; apply eq_dec.  Defined.

  Lemma eq_refl : forall x, eq x x.
  Proof.
    destruct x; apply eq_refl.  Qed.

  Lemma eq_sym : forall x y, eq x y -> eq y x.
  Proof.
    destruct x; destruct y; apply eq_sym.  Qed.

  Lemma eq_trans : forall x y z, eq x y -> eq y z -> eq x z.
  Proof.
    destruct x; destruct y; destruct z; apply eq_trans.  Qed.

  Lemma lt_trans : forall x y z, lt x y -> lt y z -> lt x z.
  Proof.
    destruct x; destruct y; destruct z; apply lt_trans.  Qed.

  Lemma lt_not_eq : forall x y, lt x y -> ~eq x y.
  Proof.
    destruct x; destruct y; apply lt_not_eq.  Qed.

  Lemma compare : forall x y, Compare lt eq x y.
  Proof.
    destruct x; destruct y.
    refine (match compare word0 word1 with
            | LT _ => LT _
            | EQ _ => EQ _
            | GT _ => GT _
            end); unfold lt, eq; eauto.  Defined.
End word_t_as_OT.

Module list_word_t_as_OT := list_as_OT word_t_as_OT.

Module EMap := FMapAVL.Make(list_word_t_as_OT).
Module DMap := FMapAVL.Make(position_as_OT).

Definition EMapT := EMap.t position_t.
Definition DMapT := DMap.t (list word_t).

Record CacheT :=
  { eMap : EMapT;
    dMap : DMapT;
    offs : N }.

Instance cache : Cache :=
  {| CacheEncode := CacheT;
     CacheDecode := CacheT;
     Equiv := fun x y => x = y /\
                         forall p q, EMap.MapsTo p q x.(eMap) <-> DMap.MapsTo q p x.(dMap) |}.

Instance cacheAddN : CacheAdd cache N :=
  {| addE := fun c n => {| eMap := c.(eMap);
                           dMap := c.(dMap);
                           offs := c.(offs) + n |};
     addD := fun c n => {| eMap := c.(eMap);
                           dMap := c.(dMap);
                           offs := c.(offs) + n |} |}.
Proof. abstract (simpl; intuition; subst; eauto).  Defined.

Require Import Coq.FSets.FMapFacts.
Module EMapFacts := WFacts_fun (list_word_t_as_OT) (EMap).
Module DMapFacts := WFacts_fun (position_as_OT) (DMap).

Lemma cacheAddPair' :
  forall (ce : CacheEncode) (cd : CacheDecode) (t : EMap.key * DMap.key),
   Equiv ce cd ->
   Equiv
     (let (l, p) := t in
      if EMap.mem (elt:=position_t) l (eMap ce) || DMap.mem (elt:=list word_t) p (dMap ce)
      then ce
      else {| eMap := EMap.add l p (eMap ce); dMap := DMap.add p l (dMap ce); offs := offs ce |})
     (let (l, p) := t in
      if EMap.mem (elt:=position_t) l (eMap cd) || DMap.mem (elt:=list word_t) p (dMap cd)
      then cd
      else {| eMap := EMap.add l p (eMap cd); dMap := DMap.add p l (dMap cd); offs := offs cd |}).
Proof.
  Local Hint Resolve EMap.E.eq_refl.
  simpl; intuition; simpl in *; subst; eauto.
  - destruct (EMap.mem a (eMap cd)) eqn: eq1; destruct (DMap.mem b (dMap cd)) eqn: eq2;
      simpl in *; try apply H1; eauto.
    rewrite EMapFacts.add_mapsto_iff in H.
    rewrite DMapFacts.add_mapsto_iff.
    inversion H. clear H. intuition.
    left. subst. assert (a = p).
    { clear -H; generalize dependent p; induction a; intuition.
      inversion H; eauto.
      destruct p; inversion H; subst; clear H.
      erewrite IHa; eauto; f_equal.
      clear -H3. destruct a. destruct w. simpl in *.
      destruct word0 eqn: ?. simpl in *. destruct word1 eqn: ?. simpl in *.
      f_equal. erewrite <- sig_equivalence.
      clear -H3; generalize dependent x0; induction x; intuition.
      inversion H3; eauto.
      destruct x0; inversion H3; subst; clear H3.
      erewrite IHx; eauto; f_equal.
      apply f_equal with (f:=ascii_of_N) in H2. rewrite !ascii_N_embedding in H2. eauto. }
    intuition eauto.
    right. intuition. apply H1 in H4. clear - eq2 H4 H0.
    destruct b eqn: ?. destruct q eqn: ?. erewrite sig_equivalence with (P:=N_as_OT_with_P.P) (n_pf:=p0) (m_pf:=l) in H0.
    simpl in H0. erewrite <- Heqk in H0. unfold N_as_OT_with_P.P in *. rewrite <- Heqp1 in H0.
    subst. inversion H0. subst. clear H0. rewrite DMapFacts.mem_find_b in eq2.
    rewrite DMapFacts.find_mapsto_iff in H4.
    erewrite (proj1 (sig_equivalence _ ((fun n : N => (n < exp2 14)%N)) x0 x0 p0 l) eq_refl) in eq2.
    unfold EMap.key, list_ascii_as_OT_with_P.P in *. erewrite H4 in eq2. congruence.
    apply H1. eauto.
  - destruct (EMap.mem a (eMap cd)) eqn: eq1; destruct (DMap.mem b (dMap cd)) eqn: eq2;
      simpl in *; try apply H1; eauto.
    rewrite DMapFacts.add_mapsto_iff in H.
    rewrite EMapFacts.add_mapsto_iff.
    inversion H.
    { clear H. intuition.
      left. subst. assert (b = q).
      { clear -H. destruct b eqn: ?. destruct q eqn: ?.
        simpl in H. unfold N_as_OT_with_P.P. apply sig_equivalence. eauto. }
      intuition eauto. }
    { right. intuition. apply H1 in H4. clear - eq1 H4 H0.
      rewrite EMapFacts.mem_find_b in eq1.
      assert (a = p).
      { clear -H0; generalize dependent p; induction a; intuition.
        inversion H0; eauto.
        destruct p; inversion H0; subst; clear H0.
        erewrite IHa; eauto; f_equal.
        clear -H3. destruct a. destruct w.
        destruct word0 eqn: ?. destruct word1 eqn: ?. simpl in *.
        f_equal. erewrite <- sig_equivalence.
        clear -H3; generalize dependent x0; induction x; intuition.
        inversion H3; eauto.
        destruct x0; inversion H3; subst; clear H3.
        erewrite IHx; eauto; f_equal.
        apply f_equal with (f:=ascii_of_N) in H2. rewrite !ascii_N_embedding in H2. eauto. }
      subst. rewrite EMapFacts.find_mapsto_iff in H4.
      rewrite H4 in eq1. congruence.
      apply H1. eauto. }
  Grab Existential Variables.
  simpl in *. omega.
  simpl in *. omega.
  simpl in *. omega.
  simpl in *. omega.  Qed.

Instance cacheAddPair : CacheAdd cache (list word_t * position_t) :=
  {| addE := fun c (b : _ * _) => let (l, p) := b
                                  in if EMap.mem l c.(eMap) || DMap.mem p c.(dMap)
                                     then c
                                     else {| eMap := EMap.add l p c.(eMap);
                                             dMap := DMap.add p l c.(dMap);
                                             offs := c.(offs) |};
     addD := fun c (b : _ * _) => let (l, p) := b
                                  in if EMap.mem l c.(eMap) || DMap.mem p c.(dMap)
                                     then c
                                     else {| eMap := EMap.add l p c.(eMap);
                                             dMap := DMap.add p l c.(dMap);
                                             offs := c.(offs) |} |}.
Proof. eapply cacheAddPair'.  Qed.

Definition get_position (n : N) : position_t.
  refine (if position_as_OT.OP.lt_dec n (exp2 14)
          then exist _ n _
          else exist _ 0%N _).
  abstract eauto.
  abstract (rewrite <- N.compare_lt_iff; eauto).
Defined.

Instance cachePeek : CachePeek cache position_t :=
  {| peekE := fun c => get_position (N.div c.(offs) 8);
     peekD := fun c => get_position (N.div c.(offs) 8) |}.
Proof.
  abstract (unfold Equiv;
  intuition;
  destruct ce; destruct cd; simpl in *;
  inversion H; inversion H0; eauto).
Defined.

Instance cacheGet : CacheGet cache (list word_t) position_t :=
  {| getE := fun c l => EMap.find l c.(eMap);
     getD := fun c p => DMap.find p c.(dMap) |}.
Proof.
  abstract (
  simpl; intuition; subst; [
  apply DMap.find_1; apply EMap.find_2 in H; apply H1; eauto |
  apply EMap.find_1; apply DMap.find_2 in H; apply H1; eauto ]).
Defined.


(********************************************************************)
(*                                                                  *)
(*  The Why3 Verification Platform   /   The Why3 Development Team  *)
(*  Copyright 2010-2018   --   Inria - CNRS - Paris-Sud University  *)
(*                                                                  *)
(*  This software is distributed under the terms of the GNU Lesser  *)
(*  General Public License version 2.1, with the special exception  *)
(*  on linking described in file LICENSE.                           *)
(*                                                                  *)
(********************************************************************)

(* This file is generated by Why3's Coq-realize driver *)
(* Beware! Only edit allowed sections below    *)
Require Import BuiltIn.
Require BuiltIn.
Require list.List.
Require option.Option.

(* Why3 assumption *)
Definition hd {a:Type} {a_WT:WhyType a} (l:(list a)): (option a) :=
  match l with
  | Init.Datatypes.nil => Init.Datatypes.None
  | (Init.Datatypes.cons h _) => (Init.Datatypes.Some h)
  end.

(* Why3 assumption *)
Definition tl {a:Type} {a_WT:WhyType a} (l:(list a)): (option (list a)) :=
  match l with
  | Init.Datatypes.nil => Init.Datatypes.None
  | (Init.Datatypes.cons _ t) => (Init.Datatypes.Some t)
  end.


Add LoadPath "PLC".
Add LoadPath "../metatheory".
Require PLC_ott.
Require PLC_inf.
Require Export STLC_other.

Ltac gather_atoms ::=
  let A := gather_atoms_with (fun x : vars => x) in
  let B := gather_atoms_with (fun x : var => {{ x }}) in
  let C := gather_atoms_with (fun x : typing_env => dom x) in
  let D1 := gather_atoms_with (fun x => fv_term x) in
  let D2 := gather_atoms_with (fun x => PLC_ott.fv_term x) in
  constr:(A \u B \u C \u D1 \u D2).

Inductive erase : term -> PLC_ott.term -> Prop :=
| erase_var : forall (x: termvar),
  erase (term_var_f x) (PLC_ott.term_var_f x)
| erase_abs : forall L τ e e',
  (forall (x: termvar), x ∉ L ->
  erase (open_term_wrt_term e (term_var_f x)) (PLC_ott.open_term_wrt_term e' (PLC_ott.term_var_f x))) ->
  erase (term_abs τ e) (PLC_ott.term_abs e')
| erase_app : forall e₁ e₁' e₂ e₂',
  erase e₁ e₁' ->
  erase e₂ e₂' ->
  erase (term_app e₁ e₂) (PLC_ott.term_app e₁' e₂')
.
Hint Constructors erase.

Lemma erase_regular1 : forall e e',
  erase e e' → lc_term e.
Proof.
intros e e' H.
induction H; auto.
Qed.

Lemma erase_regular2 : forall e e',
  erase e e' → PLC_ott.lc_term e'.
Proof.
intros e e' H.
induction H; auto.
Qed.
Hint Resolve erase_regular1 erase_regular2.

Lemma erase_subst : forall e₁ e₂ e₁' e₂' x,
  erase e₁ e₁' → erase e₂ e₂' →
  erase (subst_term e₂ x e₁) (PLC_ott.subst_term e₂' x e₁').
Proof.
intros e₁ e₂ e₁' e₂' x H1 H2.
induction H1; simpl in *; auto.
Case "var".
unfold termvar in *; unfold PLC_ott.termvar in *.
destruct (x0 == x); auto.
Case "abs".
pick fresh y. apply erase_abs with (L := L ∪ {{x}}); intros; auto.
replace (term_var_f x0) with (subst_term e₂ x (term_var_f x0)).
rewrite <- subst_term_open_term_wrt_term; eauto.
replace (PLC_ott.term_var_f x0) with (PLC_ott.subst_term e₂' x (PLC_ott.term_var_f x0)).
rewrite <- PLC_inf.subst_term_open_term_wrt_term; eauto.
autorewrite with lngen; reflexivity.
autorewrite with lngen; reflexivity.
Qed.
Hint Resolve erase_subst.

Lemma erase_uniqueness : forall e e₁ e₂,
  erase e e₁ → erase e e₂ → e₁ = e₂.
Proof.
intros e e1 e2 H1 H2.
generalize dependent e2.
induction H1; intros e2 H2; inversion H2; subst; f_equal; auto.
Case "abs". pick fresh x.
apply PLC_inf.open_term_wrt_term_inj with (x1 := x); auto.
Qed.

Lemma erase_exists : forall e, lc_term e → exists e', erase e e'.
Proof.
intros e H.
induction H; eauto.
Case "abs". pick fresh x.
destruct (H0 x) as [e' H2].
exists (PLC_ott.term_abs (PLC_inf.close_term_wrt_term x e')).
apply erase_abs with (L := PLC_ott.fv_term e' ∪ {{x}}); intros; auto.
rewrite <- PLC_inf.subst_term_spec.
rewrite (subst_term_intro x); auto.
Case "app".
destruct IHlc_term1 as [e1' H1].
destruct IHlc_term2 as [e2' H2].
eauto.
Qed.

Lemma erase_red0 : forall e₁ e₂ e₁' e₂',
  red0 e₁ e₂ → erase e₁ e₁' →
  erase e₂ e₂' → PLC_ott.red0 e₁' e₂'.
Proof.
intros e₁ e₂ e₁' e₂' Hred H1 H2.
inversion Hred; subst; inversion H1; subst.
Case "beta".
inversion H5; subst. assert (e₂' = PLC_ott.open_term_wrt_term e' e₂'0).
eapply erase_uniqueness; eauto.
pick fresh x. rewrite (subst_term_intro x); auto.
rewrite (PLC_inf.subst_term_intro x); auto.
subst; eauto.
Qed.

Lemma erase_red1 : forall e₁ e₂ e₁' e₂',
  e₁ ⇝ e₂ → erase e₁ e₁' →
  erase e₂ e₂' → PLC_ott.red1 e₁' e₂'.
Proof.
intros e₁ e₂ e₁' e₂' Hred Herase1 Herase2.
generalize dependent e₁'. generalize dependent e₂'.
induction Hred; intros.
Case "empty". eauto using erase_red0.
Case "appL". inversion Herase1; subst; inversion Herase2; subst.
replace e₂'1 with e₂'0 by eauto using erase_uniqueness; eauto.
Case "appR". inversion Herase1; subst; inversion Herase2; subst.
replace e₁' with e₁'0 by eauto using erase_uniqueness; eauto.
Case "abs". inversion Herase1; subst; inversion Herase2; subst.
pick fresh x.
apply PLC_ott.red1_abs with (L := L ∪ L0 ∪ L1 ∪ {{x}}); intros; eauto.
Qed.

Lemma erase_red0_inv : forall Γ τ e₁' e₂' e₁,
  PLC_ott.red0 e₁' e₂' →
  erase e₁ e₁' →
  wfterm Γ e₁ τ →
  exists e₂, red0 e₁ e₂.
Proof.
intros Γ τ e₁' e₂' e₁ Hred Herase Hwfterm.
inversion Hred; subst.
inversion Herase; subst.
Case "app". inversion H4; subst.
SCase "abs". eauto.
Qed.

Lemma erase_red1_inv : forall Γ τ e₁' e₂' e₁,
  PLC_ott.red1 e₁' e₂' →
  erase e₁ e₁' →
  wfterm Γ e₁ τ →
  exists e₂, e₁ ⇝ e₂.
Proof.
intros Γ τ e₁' e₂' e₁ Hred Herase Hwfterm.
generalize dependent e₁. generalize dependent τ. generalize dependent Γ.
induction Hred; intros.
Case "empty". edestruct erase_red0_inv; eauto.
Case "appL". inversion Herase; subst; inversion Hwfterm; subst; edestruct IHHred; eauto.
Case "appR". inversion Herase; subst; inversion Hwfterm; subst.
SCase "app". edestruct IHHred; eauto.
Case "abs". inversion Herase; subst; inversion Hwfterm; subst.
SCase "abs". pick fresh x. edestruct (H0 x); eauto.
exists (term_abs τ0 (close_term_wrt_term x x0)).
apply red1_abs with (L := {{x}}); intros; auto.
rewrite <- subst_term_spec.
rewrite (subst_term_intro x); auto.
Qed.

Lemma simulation : forall Γ τ e₁ e₁',
  wfterm Γ e₁ τ →
  erase e₁ e₁' →
  ((exists e₂, e₁ ⇝ e₂) ↔ (exists e₂', PLC_ott.red1 e₁' e₂')).
Proof.
intros Γ τ e₁ e₁' Hwfterm Herase; split; intros [e H].
destruct (erase_exists e); eauto using erase_red1.
edestruct erase_red1_inv; eauto.
Qed.


Require Import Coq.ZArith.ZArith Coq.micromega.Lia.
Require Import QArith.QArith_base QArith.Qround Crypto.Util.QUtil.
Require Import Crypto.ArithmeticCPS.BaseConversion.
Require Import Crypto.ArithmeticCPS.Core.
Require Import Crypto.ArithmeticCPS.ModOps.
Require Import Crypto.Arithmetic.Partition.
Require Import Crypto.ArithmeticCPS.Saturated.
Require Import Crypto.Util.CPSUtil.
Require Import Crypto.Util.CPSNotations.
Require Import Crypto.Util.Decidable.
Require Import Crypto.Util.ListUtil.
Require Import Crypto.Util.Prod.
Require Import Crypto.Util.Tactics.BreakMatch.
Require Import Crypto.Util.Tactics.DestructHead.
Require Import Crypto.Util.ZUtil.EquivModulo.
Require Import Crypto.Util.ZUtil.Opp.
Require Import Crypto.Util.ZUtil.Tactics.DivModToQuotRem.
Require Import Crypto.Util.ZUtil.Tactics.PeelLe.
Require Import Crypto.Util.ZUtil.Tactics.RewriteModSmall.
Require Import Crypto.Util.ZUtil.Tactics.PullPush.Modulo.

Require Import Crypto.Util.Notations.
Local Open Scope Z_scope.

Import CPSBindNotations.
Local Open Scope cps_scope.

(* TODO: rename this module? (Should it be, e.g., [Rows.freeze]?) *)
Module Freeze (Import RT : Runtime).
  Module Import Deps.
    Module Rows := Rows RT.
  End Deps.
  Section Freeze.
    Context (weight : nat -> Z).

    Definition freeze_cps n mask (m p:list Z) : ~> list Z :=
      (p_carry <- Rows.sub_cps weight n p m;
         let '(p, carry) := p_carry in
         r_carry <- Rows.conditional_add_cps weight n mask (-carry)%RT p m;
           let '(r, carry) := r_carry in
           return r).
  End Freeze.
End Freeze.

Module FreezeModOps (Import RT : Runtime).
  Module Import Deps.
    Module Export Positional := Positional RT.
    Module Export Freeze := Freeze RT.
    Module BaseConversion := BaseConversion RT.
    Module Export Core.
      Module Associational := ArithmeticCPS.Core.Associational RT.
    End Core.
  End Deps.
  Section mod_ops.
  Local Coercion Z.of_nat : nat >-> Z.
  Local Coercion QArith_base.inject_Z : Z >-> Q.
  (* Design constraints:
     - inputs must be [Z] (b/c reification does not support Q)
     - internal structure must not match on the arguments (b/c reification does not support [positive]) *)
  Context (limbwidth_num limbwidth_den : Z)
          (limbwidth_good : 0 < limbwidth_den <= limbwidth_num)
          (s : Z)
          (c : list (Z*Z))
          (n : nat)
          (bitwidth : Z)
          (m_enc : list Z)
          (Hn_nz : n <> 0%nat).
  Local Notation bytes_weight := (@weight 8 1).
  Local Notation weight := (@weight limbwidth_num limbwidth_den).
  Let m := (s - Associational.eval c).

  Context (Hs : s = weight n).
  Context (c_small : 0 < Associational.eval c < weight n)
          (m_enc_bounded : List.map (BinInt.Z.land (Z.ones bitwidth)) m_enc = m_enc)
          (m_enc_correct : Positional.eval weight n m_enc = m)
          (Hm_enc_len : length m_enc = n).

  Definition bytes_n
    := Eval cbv [Qceiling Qdiv inject_Z Qfloor Qmult Qopp Qnum Qden Qinv Pos.mul]
      in Z.to_nat (Qceiling (Z.log2_up (weight n) / 8)).

  Definition to_bytes_cps (v : list Z) : ~> _
    := BaseConversion.convert_bases_cps weight bytes_weight n bytes_n v.

  Definition from_bytes_cps (v : list Z) : ~> _
    := BaseConversion.convert_bases_cps bytes_weight weight bytes_n n v.

  Definition freeze_to_bytesmod_cps (f : list Z) : ~> list Z
    := (f <- freeze_cps weight n (Z.ones bitwidth) m_enc f; to_bytes_cps f).

  Definition to_bytesmod_cps (f : list Z) : ~> list Z
    := to_bytes_cps f.
  Definition to_bytesmod (f : list Z) : list Z := to_bytesmod_cps f _ id.

  Definition from_bytesmod_cps (f : list Z) : ~> list Z
    := from_bytes_cps f.
  Definition from_bytesmod (f : list Z) : list Z := from_bytesmod_cps f _ id.
  End mod_ops.
End FreezeModOps.


From Test Require Import tactic.

Section FOFProblem.

Variable Universe : Set.
Variable UniverseElement : Universe.

Variable wd_ : Universe -> Universe -> Prop.
Variable col_ : Universe -> Universe -> Universe -> Prop.

Variable col_swap1_1 : (forall A B C : Universe, (col_ A B C -> col_ B A C)).
Variable col_swap2_2 : (forall A B C : Universe, (col_ A B C -> col_ B C A)).
Variable col_triv_3 : (forall A B : Universe, col_ A B B).
Variable wd_swap_4 : (forall A B : Universe, (wd_ A B -> wd_ B A)).
Variable col_trans_5 : (forall P Q A B C : Universe, ((wd_ P Q /\ (col_ P Q A /\ (col_ P Q B /\ col_ P Q C))) -> col_ A B C)).

Theorem pipo_6 : (forall P Q A B C Dprime Pprime Cprime Dprimeprime Pprimeprime Z T : Universe, ((wd_ P Q /\ (wd_ T Z /\ (wd_ B Cprime /\ (wd_ Cprime Dprimeprime /\ (wd_ B Dprimeprime /\ (wd_ A B /\ (wd_ B C /\ (wd_ A C /\ (wd_ Cprime Pprimeprime /\ (wd_ B Pprime /\ (wd_ Dprime B /\ (wd_ T B /\ (wd_ B Pprimeprime /\ (wd_ B Z /\ (wd_ Cprime C /\ (wd_ A Dprime /\ (wd_ Pprime Cprime /\ (col_ A B T /\ (col_ B T Pprimeprime /\ (col_ B C Z /\ (col_ Cprime Dprimeprime Pprimeprime /\ (col_ B Cprime A /\ col_ B Dprime Pprime)))))))))))))))))))))) -> col_ B Cprime Dprimeprime)).
Proof.
  time tac.
Qed.

End FOFProblem.