aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChantal Keller <Chantal.Keller@inria.fr>2015-01-12 16:28:10 +0100
committerChantal Keller <Chantal.Keller@inria.fr>2015-01-12 16:28:10 +0100
commitcfb4587e26623318f432c7e3e21711afc2b966e7 (patch)
treea90c6f372633458aa0766510bcfdc4682eaa8f6a
parent1e10dcc783b82269cc3fe3bb7419b9c1cc9e0fa7 (diff)
downloadsmtcoq-cfb4587e26623318f432c7e3e21711afc2b966e7.tar.gz
smtcoq-cfb4587e26623318f432c7e3e21711afc2b966e7.zip
Initial import of SMTCoq v1.2
-rw-r--r--examples/Example.v67
-rw-r--r--examples/euf.log8
-rw-r--r--examples/euf.smt211
-rw-r--r--examples/example.ml7
-rw-r--r--examples/hole4.cnf76
-rw-r--r--examples/hole4.log49
-rw-r--r--examples/sat.cnf6
-rw-r--r--examples/sat.log5
-rw-r--r--src/Make91
-rw-r--r--src/Makefile416
-rw-r--r--src/Misc.v1004
-rw-r--r--src/SMTCoq.v20
-rw-r--r--src/SMT_terms.v1308
-rw-r--r--src/State.v572
-rw-r--r--src/Trace.v567
-rw-r--r--src/cnf/Cnf.v419
-rw-r--r--src/euf/Euf.v538
-rw-r--r--src/extraction/Extract.v26
-rw-r--r--src/extraction/Makefile47
-rw-r--r--src/extraction/extrNative.ml332
-rw-r--r--src/extraction/extrNative.mli67
-rw-r--r--src/extraction/sat_checker.ml431
-rw-r--r--src/extraction/sat_checker.mli169
-rw-r--r--src/extraction/smt_checker.ml6849
-rw-r--r--src/extraction/smt_checker.mli1889
-rw-r--r--src/extraction/test.ml42
-rw-r--r--src/extraction/verit_checker.ml324
-rw-r--r--src/extraction/zchaff_checker.ml103
-rw-r--r--src/lia/Lia.v1611
-rw-r--r--src/lia/lia.ml208
-rw-r--r--src/spl/Arithmetic.v94
-rw-r--r--src/spl/Operators.v549
-rw-r--r--src/spl/Syntactic.v531
-rw-r--r--src/trace/coqTerms.ml187
-rw-r--r--src/trace/satAtom.ml65
-rw-r--r--src/trace/smtAtom.ml748
-rw-r--r--src/trace/smtAtom.mli175
-rw-r--r--src/trace/smtCertif.ml140
-rw-r--r--src/trace/smtCnf.ml264
-rw-r--r--src/trace/smtForm.ml510
-rw-r--r--src/trace/smtForm.mli99
-rw-r--r--src/trace/smtMisc.ml47
-rw-r--r--src/trace/smtTrace.ml465
-rw-r--r--src/trace/smt_tactic.ml455
-rw-r--r--src/verit/smtlib2_ast.ml189
-rw-r--r--src/verit/smtlib2_genConstr.ml226
-rw-r--r--src/verit/smtlib2_lex.mll88
-rw-r--r--src/verit/smtlib2_parse.mly299
-rw-r--r--src/verit/smtlib2_util.ml29
-rw-r--r--src/verit/verit.ml542
-rw-r--r--src/verit/veritLexer.mll148
-rw-r--r--src/verit/veritParser.mly204
-rw-r--r--src/verit/veritSyntax.ml355
-rw-r--r--src/verit/veritSyntax.mli44
-rw-r--r--src/zchaff/cnfParser.ml57
-rw-r--r--src/zchaff/satParser.ml178
-rw-r--r--src/zchaff/zchaff.ml532
-rw-r--r--src/zchaff/zchaffParser.ml161
-rw-r--r--unit-tests/Makefile32
-rw-r--r--unit-tests/Tests.v1273
-rw-r--r--unit-tests/cmu-bmc-barrel6.cnf8932
-rw-r--r--unit-tests/hole4.cnf76
-rw-r--r--unit-tests/hole4.smt299
-rw-r--r--unit-tests/let1.smt25
-rw-r--r--unit-tests/let2.smt26
-rw-r--r--unit-tests/lia1.smt27
-rw-r--r--unit-tests/lia2.smt25
-rw-r--r--unit-tests/lia3.smt26
-rw-r--r--unit-tests/lia4.smt26
-rw-r--r--unit-tests/lia5.smt26
-rw-r--r--unit-tests/lia6.smt25
-rw-r--r--unit-tests/lia7.smt25
-rwxr-xr-xunit-tests/runverit.sh7
-rwxr-xr-xunit-tests/runzchaff.sh8
-rw-r--r--unit-tests/sat1.cnf3
-rw-r--r--unit-tests/sat1.smt25
-rw-r--r--unit-tests/sat10.smt27
-rw-r--r--unit-tests/sat11.smt28
-rw-r--r--unit-tests/sat12.smt211
-rw-r--r--unit-tests/sat13.smt27
-rw-r--r--unit-tests/sat2.cnf6
-rw-r--r--unit-tests/sat2.smt27
-rw-r--r--unit-tests/sat3.cnf3
-rw-r--r--unit-tests/sat3.smt25
-rw-r--r--unit-tests/sat4.smt25
-rw-r--r--unit-tests/sat5.cnf6
-rw-r--r--unit-tests/sat5.smt27
-rw-r--r--unit-tests/sat6.cnf6
-rw-r--r--unit-tests/sat6.smt210
-rw-r--r--unit-tests/sat7.cnf6
-rw-r--r--unit-tests/sat7.smt28
-rw-r--r--unit-tests/sat8.smt25
-rw-r--r--unit-tests/sat9.smt28
-rw-r--r--unit-tests/uf1.smt210
-rw-r--r--unit-tests/uf2.smt29
-rw-r--r--unit-tests/uf3.smt29
-rw-r--r--unit-tests/uf4.smt29
-rw-r--r--unit-tests/uf5.smt211
-rw-r--r--unit-tests/uf6.smt210
-rw-r--r--unit-tests/uf7.smt211
-rw-r--r--unit-tests/velev-sss-1.0-05.cnf12813
101 files changed, 47726 insertions, 0 deletions
diff --git a/examples/Example.v b/examples/Example.v
new file mode 100644
index 0000000..9dacc6a
--- /dev/null
+++ b/examples/Example.v
@@ -0,0 +1,67 @@
+(* "Require Import SMTCoq." is needed to use the SMTCoq program *)
+
+Require Import SMTCoq.
+Require Import Bool.
+Local Open Scope int63_scope.
+
+(* Examples that check ZChaff certificates *)
+
+Zchaff_Checker "sat.cnf" "sat.log".
+Zchaff_Theorem sat "sat.cnf" "sat.log".
+Check sat.
+
+Zchaff_Checker "hole4.cnf" "hole4.log".
+
+(* Example that checks a VeriT certificate, for logic QF_UF *)
+
+Section Verit.
+ Verit_Checker "euf.smt2" "euf.log".
+End Verit.
+
+(* Examples of the zchaff tactic (requires zchaff in your PATH
+ environment variable):
+ - with booleans
+ - with concrete terms *)
+
+Goal forall a b c,
+ (a || b || c) && ((negb a) || (negb b) || (negb c)) && ((negb a) || b) && ((negb b) || c) && ((negb c) || a) = false.
+Proof.
+ zchaff.
+Qed.
+
+Goal forall i j k,
+ let a := i == j in
+ let b := j == k in
+ let c := k == i in
+ (a || b || c) && ((negb a) || (negb b) || (negb c)) && ((negb a) || b) && ((negb b) || c) && ((negb c) || a) = false.
+Proof.
+ zchaff.
+Qed.
+
+(* Examples of the verit tactic (requires verit in your PATH environment
+ variable):
+ - with booleans
+ - in logics QF_UF and QF_LIA *)
+
+Goal forall a b c, ((a || b || c) && ((negb a) || (negb b) || (negb c)) && ((negb a) || b) && ((negb b) || c) && ((negb c) || a)) = false.
+Proof.
+ verit.
+Qed.
+
+
+Goal forall (a b : Z) (P : Z -> bool) (f : Z -> Z),
+ (negb (Zeq_bool (f a) b)) || (negb (P (f a))) || (P b).
+Proof.
+ verit.
+Qed.
+
+
+Goal forall b1 b2 x1 x2,
+ implb
+ (ifb b1
+ (ifb b2 (Zeq_bool (2*x1+1) (2*x2+1)) (Zeq_bool (2*x1+1) (2*x2)))
+ (ifb b2 (Zeq_bool (2*x1) (2*x2+1)) (Zeq_bool (2*x1) (2*x2))))
+ ((implb b1 b2) && (implb b2 b1) && (Zeq_bool x1 x2)).
+Proof.
+ verit.
+Qed.
diff --git a/examples/euf.log b/examples/euf.log
new file mode 100644
index 0000000..3bccc6a
--- /dev/null
+++ b/examples/euf.log
@@ -0,0 +1,8 @@
+1:(input (#1:(and #2:(= b a) #3:(= b c) #4:(= c d) #5:(= e c) #6:(= e f) (not #7:(= a f)))))
+2:(and (#2) 1 0)
+3:(and (#3) 1 1)
+4:(and (#5) 1 3)
+5:(and (#6) 1 4)
+6:(and ((not #7)) 1 5)
+7:(eq_transitive ((not #2) (not #3) (not #5) (not #6) #7))
+8:(resolution () 7 2 3 4 5 6)
diff --git a/examples/euf.smt2 b/examples/euf.smt2
new file mode 100644
index 0000000..c151654
--- /dev/null
+++ b/examples/euf.smt2
@@ -0,0 +1,11 @@
+(set-logic QF_UF)
+(declare-sort U 0)
+(declare-fun a () U)
+(declare-fun b () U)
+(declare-fun c () U)
+(declare-fun d () U)
+(declare-fun e () U)
+(declare-fun f () U)
+(assert (and (= a b) (= b c) (= c d) (= c e) (= e f) (not (= a f))))
+(check-sat)
+(exit)
diff --git a/examples/example.ml b/examples/example.ml
new file mode 100644
index 0000000..0bb7178
--- /dev/null
+++ b/examples/example.ml
@@ -0,0 +1,7 @@
+let _ = Printf.printf "Zchaff_checker.checker \"sat.cnf\" \"sat.log\" = %b\n" (Zchaff_checker.checker "sat.cnf" "sat.log")
+let _ = Printf.printf "Zchaff_checker.checker \"hole4.cnf\" \"hole4.log\" = %b\n" (Zchaff_checker.checker "hole4.cnf" "hole4.log")
+
+
+
+
+let _ = Printf.printf "Verit_checker.checker \"euf.smt2\" \"euf.log\" = %b\n" (Verit_checker.checker "euf.smt2" "euf.log")
diff --git a/examples/hole4.cnf b/examples/hole4.cnf
new file mode 100644
index 0000000..9dd148c
--- /dev/null
+++ b/examples/hole4.cnf
@@ -0,0 +1,76 @@
+p cnf 20 75
+1 2 3 4 0
+5 6 7 8 0
+9 10 11 12 0
+13 14 15 16 0
+17 18 19 20 0
+-1 -2 0
+-1 -3 0
+-1 -4 0
+-2 -3 0
+-2 -4 0
+-3 -4 0
+-5 -6 0
+-5 -7 0
+-5 -8 0
+-6 -7 0
+-6 -8 0
+-7 -8 0
+-9 -10 0
+-9 -11 0
+-9 -12 0
+-10 -11 0
+-10 -12 0
+-11 -12 0
+-13 -14 0
+-13 -15 0
+-13 -16 0
+-14 -15 0
+-14 -16 0
+-15 -16 0
+-17 -18 0
+-17 -19 0
+-17 -20 0
+-18 -19 0
+-18 -20 0
+-19 -20 0
+-1 -5 0
+-1 -9 0
+-1 -13 0
+-1 -17 0
+-5 -9 0
+-5 -13 0
+-5 -17 0
+-9 -13 0
+-9 -17 0
+-13 -17 0
+-2 -6 0
+-2 -10 0
+-2 -14 0
+-2 -18 0
+-6 -10 0
+-6 -14 0
+-6 -18 0
+-10 -14 0
+-10 -18 0
+-14 -18 0
+-3 -7 0
+-3 -11 0
+-3 -15 0
+-3 -19 0
+-7 -11 0
+-7 -15 0
+-7 -19 0
+-11 -15 0
+-11 -19 0
+-15 -19 0
+-4 -8 0
+-4 -12 0
+-4 -16 0
+-4 -20 0
+-8 -12 0
+-8 -16 0
+-8 -20 0
+-12 -16 0
+-12 -20 0
+-16 -20 0
diff --git a/examples/hole4.log b/examples/hole4.log
new file mode 100644
index 0000000..ab23cdd
--- /dev/null
+++ b/examples/hole4.log
@@ -0,0 +1,49 @@
+CL: 75 <= 65 1 0 59 56
+CL: 76 <= 55 1 0 69 66 2 75 52 50 47
+CL: 77 <= 60 3 1 72 69 2 46 45
+CL: 78 <= 57 3 0 70 65
+CL: 79 <= 57 3 0 72 66
+CL: 80 <= 67 3 0 60 55 1 49 2 79 78 77
+CL: 81 <= 45 1 0 70 67 3 62 59 56 80 76 44 43 41 38
+CL: 82 <= 61 4 1 74 70
+CL: 83 <= 71 4 1 64 60 3 82 53 49
+CL: 84 <= 51 4 1 64 60 3 73 72 69 2 83 36 35
+CL: 85 <= 48 4 0 73 66
+CL: 86 <= 4 51 68 1 0 78
+CL: 87 <= 71 4 1 48 45 86 39 2 85 64 60 57
+CL: 88 <= 51 4 1 58 55
+CL: 89 <= 82 48 45 0 88 39 2 74 72 70 67 3 87
+CL: 90 <= 58 4 0 74 67
+CL: 91 <= 68 4 0 64 57 3 90 53 46 89 84
+CL: 92 <= 61 4 1 68 65 0 53 49 46
+CL: 93 <= 1 45 61 0 85 69 66 2 92
+CL: 94 <= 53 4 2 71 69
+CL: 95 <= 2 49 73 1 88 94 58 55 93 42 40 37
+CL: 96 <= 58 4 0 73 66 2 39 35
+CL: 97 <= 36 2 0 73 68 4 61 55
+CL: 98 <= 0 58 36 4 2 71 69 65 1 97 96 54 52 50 47 91 95
+CL: 99 <= 71 4 1 54 50
+CL: 100 <= 51 4 1 74 70 3 99 37 35
+CL: 101 <= 68 4 0 54 47
+CL: 102 <= 40 3 1 74 71 4 48 45
+VAR: 1 L: 9 V: 0 A: 100 Lits: 34 38 14 30 3
+VAR: 2 L: 11 V: 0 A: 102 Lits: 28 30 14 34 38 5
+VAR: 3 L: 5 V: 0 A: 56 Lits: 7 23
+VAR: 4 L: 12 V: 1 A: 0 Lits: 2 4 6 8
+VAR: 5 L: 18 V: 0 A: 40 Lits: 11 27
+VAR: 6 L: 19 V: 0 A: 51 Lits: 13 37
+VAR: 7 L: 6 V: 0 A: 59 Lits: 15 23
+VAR: 8 L: 13 V: 0 A: 65 Lits: 9 17
+VAR: 9 L: 2 V: 0 A: 18 Lits: 19 23
+VAR: 10 L: 3 V: 0 A: 20 Lits: 21 23
+VAR: 11 L: 1 V: 1 A: 98 Lits: 34 22
+VAR: 12 L: 4 V: 0 A: 22 Lits: 23 25
+VAR: 13 L: 16 V: 1 A: 3 Lits: 26 28 30 32
+VAR: 14 L: 10 V: 0 A: 101 Lits: 34 38 2 6 29
+VAR: 15 L: 7 V: 0 A: 62 Lits: 23 31
+VAR: 16 L: 14 V: 0 A: 67 Lits: 9 33
+VAR: 17 L: 0 V: 0 A: 81 Lits: 35
+VAR: 18 L: 17 V: 1 A: 4 Lits: 34 36 38 40
+VAR: 19 L: 8 V: 0 A: 63 Lits: 23 39
+VAR: 20 L: 15 V: 0 A: 68 Lits: 9 41
+CONF: 1 == 10 12 14 16
diff --git a/examples/sat.cnf b/examples/sat.cnf
new file mode 100644
index 0000000..508791a
--- /dev/null
+++ b/examples/sat.cnf
@@ -0,0 +1,6 @@
+p cnf 3 5
+1 2 3 0
+-1 -2 -3 0
+-1 2 0
+-2 3 0
+-3 1 0
diff --git a/examples/sat.log b/examples/sat.log
new file mode 100644
index 0000000..af89d7c
--- /dev/null
+++ b/examples/sat.log
@@ -0,0 +1,5 @@
+CL: 5 <= 2 1 4
+VAR: 1 L: 2 V: 0 A: 2 Lits: 3 4
+VAR: 2 L: 1 V: 0 A: 3 Lits: 5 6
+VAR: 3 L: 0 V: 0 A: 5 Lits: 7
+CONF: 0 == 2 4 6
diff --git a/src/Make b/src/Make
new file mode 100644
index 0000000..d1c9342
--- /dev/null
+++ b/src/Make
@@ -0,0 +1,91 @@
+########################################################################
+## This file is intended to developers, please do not use it to ##
+## generate a Makefile, rather use the provided Makefile. ##
+########################################################################
+
+
+
+
+########################################################################
+## To generate the Makefile: ##
+## coq_makefile -f Make -o Makefile ##
+## Change the "all" target into: ##
+## all: ml $(CMXFILES) $(CMXA) $(CMXS) $(VOFILES) ##
+## Change the "install-natdynlink" target: change CMXSFILES into CMXS and add the same thing for CMXA and VCMXS. ##
+## Change the "install" target: change CMO into CMX. ##
+## Finally, suppress the "Makefile" target and add to the "clean" target: ##
+## - rm -f NSMTCoq* cnf/NSMTCoq* euf/NSMTCoq* lia/NSMTCoq* spl/NSMTCoq* ../unit-tests/NSMTCoq* ../unit-tests/*.zlog ../unit-tests/*.vtlog verit/veritParser.mli verit/veritParser.ml verit/veritLexer.ml verit/smtlib2_parse.mli verit/smtlib2_parse.ml verit/smtlib2_lex.ml ##
+########################################################################
+
+
+-R . SMTCoq
+
+-I cnf
+-I euf
+-I lia
+-I trace
+-I verit
+-I zchaff
+
+# -custom "cd ../unit-tests; make" "" "logs"
+-custom "cd ../unit-tests; make" "" "test"
+
+-custom "$(CAMLLEX) $<" "%.mll" "%.ml"
+-custom "$(CAMLYACC) $<" "%.mly" "%.ml %.mli"
+-custom "" "verit/veritParser.ml verit/veritLexer.ml verit/smtlib2_parse.ml verit/smtlib2_lex.ml" "ml"
+
+-custom "$(CAMLOPTLINK) $(ZFLAGS) -a -o $@ $^" "trace/smtMisc.cmx trace/coqTerms.cmx trace/smtForm.cmx trace/smtCertif.cmx trace/smtTrace.cmx trace/smtCnf.cmx trace/satAtom.cmx trace/smtAtom.cmx zchaff/satParser.cmx zchaff/zchaffParser.cmx zchaff/cnfParser.cmx zchaff/zchaff.cmx verit/smtlib2_util.cmx verit/smtlib2_ast.cmx verit/smtlib2_parse.cmx verit/smtlib2_lex.cmx lia/lia.cmx verit/veritSyntax.cmx verit/veritParser.cmx verit/veritLexer.cmx verit/smtlib2_genConstr.cmx verit/verit.cmx trace/smt_tactic.cmx" "$(CMXA)"
+-custom "$(CAMLOPTLINK) $(ZFLAGS) -o $@ -linkall -shared $^" "$(CMXA)" "$(CMXS)"
+
+CMXA = trace/smtcoq.cmxa
+CMXS = trace/smt_tactic.cmxs
+VCMXS = "NSMTCoq_State.cmxs NSMTCoq_Misc.cmxs NSMTCoq_SMT_terms.cmxs cnf/NSMTCoq_cnf_Cnf.cmxs euf/NSMTCoq_euf_Euf.cmxs lia/NSMTCoq_lia_Lia.cmxs spl/NSMTCoq_spl_Syntactic.cmxs spl/NSMTCoq_spl_Arithmetic.cmxs spl/NSMTCoq_spl_Operators.cmxs NSMTCoq_Trace.cmxs NSMTCoq_SMTCoq.cmxs NSMTCoq_State.cmi NSMTCoq_Misc.cmi NSMTCoq_SMT_terms.cmi cnf/NSMTCoq_cnf_Cnf.cmi euf/NSMTCoq_euf_Euf.cmi lia/NSMTCoq_lia_Lia.cmi spl/NSMTCoq_spl_Syntactic.cmxs spl/NSMTCoq_spl_Arithmetic.cmi spl/NSMTCoq_spl_Operators.cmi NSMTCoq_Trace.cmi NSMTCoq_Trace.cmi NSMTCoq_SMTCoq.cmi"
+CAMLLEX = $(CAMLBIN)ocamllex
+CAMLYACC = $(CAMLBIN)ocamlyacc
+
+trace/coqTerms.ml
+trace/satAtom.ml
+trace/smtAtom.ml
+trace/smtAtom.mli
+trace/smtCertif.ml
+trace/smtCnf.ml
+trace/smtForm.ml
+trace/smtForm.mli
+trace/smtMisc.ml
+trace/smt_tactic.ml4
+trace/smtTrace.ml
+
+verit/smtlib2_ast.ml
+verit/smtlib2_genConstr.ml
+verit/smtlib2_lex.ml
+verit/smtlib2_parse.ml
+verit/smtlib2_util.ml
+verit/veritParser.ml
+verit/veritLexer.ml
+verit/verit.ml
+verit/veritSyntax.ml
+verit/veritSyntax.mli
+
+zchaff/cnfParser.ml
+zchaff/satParser.ml
+zchaff/zchaff.ml
+zchaff/zchaffParser.ml
+
+cnf/Cnf.v
+
+euf/Euf.v
+
+lia/lia.ml
+lia/Lia.v
+
+spl/Syntactic.v
+spl/Arithmetic.v
+spl/Operators.v
+
+Misc.v
+SMTCoq.v
+SMT_terms.v
+State.v
+Trace.v
+
+# tests/Tests.v
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..8919e7f
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,416 @@
+#############################################################################
+## v # The Coq Proof Assistant ##
+## <O___,, # INRIA - CNRS - LIX - LRI - PPS ##
+## \VV/ # ##
+## // # Makefile automagically generated by coq_makefile Vtrunk ##
+#############################################################################
+
+# WARNING
+#
+# This Makefile has been automagically generated
+# Edit at your own risks !
+#
+# END OF WARNING
+
+#
+# This Makefile was generated by the command line :
+# coq_makefile -f Make -o Makefile
+#
+
+.DEFAULT_GOAL := all
+
+#
+# This Makefile may take arguments passed as environment variables:
+# COQBIN to specify the directory where Coq binaries resides;
+# ZDEBUG/COQDEBUG to specify debug flags for ocamlc&ocamlopt/coqc;
+# DSTROOT to specify a prefix to install path.
+
+# Here is a hack to make $(eval $(shell works:
+define donewline
+
+
+endef
+includecmdwithout@ = $(eval $(subst @,$(donewline),$(shell { $(1) | tr '\n' '@'; })))
+$(call includecmdwithout@,$(COQBIN)coqtop -config)
+
+##########################
+# #
+# Libraries definitions. #
+# #
+##########################
+
+OCAMLLIBS?=-I zchaff\
+ -I verit\
+ -I trace\
+ -I lia\
+ -I euf\
+ -I cnf
+COQLIBS?= -R . SMTCoq
+COQDOCLIBS?=-R . SMTCoq
+
+##########################
+# #
+# Variables definitions. #
+# #
+##########################
+
+CAMLYACC=$(CAMLBIN)ocamlyacc
+CAMLLEX=$(CAMLBIN)ocamllex
+VCMXS=NSMTCoq_State.cmxs NSMTCoq_Misc.cmxs NSMTCoq_SMT_terms.cmxs cnf/NSMTCoq_cnf_Cnf.cmxs euf/NSMTCoq_euf_Euf.cmxs lia/NSMTCoq_lia_Lia.cmxs spl/NSMTCoq_spl_Syntactic.cmxs spl/NSMTCoq_spl_Arithmetic.cmxs spl/NSMTCoq_spl_Operators.cmxs NSMTCoq_Trace.cmxs NSMTCoq_SMTCoq.cmxs NSMTCoq_State.cmi NSMTCoq_Misc.cmi NSMTCoq_SMT_terms.cmi cnf/NSMTCoq_cnf_Cnf.cmi euf/NSMTCoq_euf_Euf.cmi lia/NSMTCoq_lia_Lia.cmi spl/NSMTCoq_spl_Syntactic.cmxs spl/NSMTCoq_spl_Arithmetic.cmi spl/NSMTCoq_spl_Operators.cmi NSMTCoq_Trace.cmi NSMTCoq_Trace.cmi NSMTCoq_SMTCoq.cmi
+CMXS=trace/smt_tactic.cmxs
+CMXA=trace/smtcoq.cmxa
+
+OPT?=
+COQDEP?=$(COQBIN)coqdep -c
+COQFLAGS?=-q $(OPT) $(COQLIBS) $(OTHERFLAGS) $(COQ_XML)
+COQCHKFLAGS?=-silent -o
+COQDOCFLAGS?=-interpolate -utf8
+COQC?=$(COQBIN)coqc
+GALLINA?=$(COQBIN)gallina
+COQDOC?=$(COQBIN)coqdoc
+COQCHK?=$(COQBIN)coqchk
+
+COQSRCLIBS?=-I $(COQLIB)kernel -I $(COQLIB)lib \
+ -I $(COQLIB)library -I $(COQLIB)parsing \
+ -I $(COQLIB)pretyping -I $(COQLIB)interp \
+ -I $(COQLIB)proofs -I $(COQLIB)tactics \
+ -I $(COQLIB)toplevel \
+ -I $(COQLIB)plugins/btauto \
+ -I $(COQLIB)plugins/cc \
+ -I $(COQLIB)plugins/decl_mode \
+ -I $(COQLIB)plugins/extraction \
+ -I $(COQLIB)plugins/field \
+ -I $(COQLIB)plugins/firstorder \
+ -I $(COQLIB)plugins/fourier \
+ -I $(COQLIB)plugins/funind \
+ -I $(COQLIB)plugins/micromega \
+ -I $(COQLIB)plugins/nsatz \
+ -I $(COQLIB)plugins/omega \
+ -I $(COQLIB)plugins/quote \
+ -I $(COQLIB)plugins/ring \
+ -I $(COQLIB)plugins/romega \
+ -I $(COQLIB)plugins/rtauto \
+ -I $(COQLIB)plugins/setoid_ring \
+ -I $(COQLIB)plugins/syntax \
+ -I $(COQLIB)plugins/xml
+ZFLAGS=$(OCAMLLIBS) $(COQSRCLIBS) -I $(CAMLP4LIB)
+
+CAMLC?=$(OCAMLC) -c -rectypes
+CAMLOPTC?=$(OCAMLOPT) -c -rectypes
+CAMLLINK?=$(OCAMLC) -rectypes
+CAMLOPTLINK?=$(OCAMLOPT) -rectypes
+GRAMMARS?=grammar.cma
+CAMLP4EXTEND?=pa_extend.cmo pa_macro.cmo q_MLast.cmo
+CAMLP4OPTIONS?=-loc loc
+PP?=-pp "$(CAMLP4BIN)$(CAMLP4)o -I $(CAMLLIB) -I . $(COQSRCLIBS) $(CAMLP4EXTEND) $(GRAMMARS) $(CAMLP4OPTIONS) -impl"
+
+##################
+# #
+# Install Paths. #
+# #
+##################
+
+ifdef USERINSTALL
+XDG_DATA_HOME?=$(HOME)/.local/share
+COQLIBINSTALL=$(XDG_DATA_HOME)/coq
+COQDOCINSTALL=$(XDG_DATA_HOME)/doc/coq
+else
+COQLIBINSTALL=${COQLIB}user-contrib
+COQDOCINSTALL=${DOCDIR}user-contrib
+endif
+
+######################
+# #
+# Files dispatching. #
+# #
+######################
+
+VFILES:=Trace.v\
+ State.v\
+ SMT_terms.v\
+ SMTCoq.v\
+ Misc.v\
+ spl/Operators.v\
+ spl/Arithmetic.v\
+ spl/Syntactic.v\
+ lia/Lia.v\
+ euf/Euf.v\
+ cnf/Cnf.v
+
+-include $(addsuffix .d,$(VFILES))
+.SECONDARY: $(addsuffix .d,$(VFILES))
+
+vo_to_obj = $(addsuffix .o,$(foreach vo,$(1),$(addprefix $(dir $(vo)),$(filter-out Warning: Error:,$(firstword $(shell $(COQBIN)coqtop -batch -quiet -print-mod-uid $(vo:.vo=)))))))
+VOFILES:=$(foreach vo,$(VFILES:.v=.vo),$(dir $(vo))$(notdir $(vo)))
+GLOBFILES:=$(VFILES:.v=.glob)
+VIFILES:=$(VFILES:.v=.vi)
+GFILES:=$(VFILES:.v=.g)
+HTMLFILES:=$(VFILES:.v=.html)
+GHTMLFILES:=$(VFILES:.v=.g.html)
+OBJFILES:=$(call vo_to_obj,$(VOFILES))
+ML4FILES:=trace/smt_tactic.ml4
+
+-include $(addsuffix .d,$(ML4FILES))
+.SECONDARY: $(addsuffix .d,$(ML4FILES))
+
+MLFILES:=lia/lia.ml\
+ zchaff/zchaffParser.ml\
+ zchaff/zchaff.ml\
+ zchaff/satParser.ml\
+ zchaff/cnfParser.ml\
+ verit/veritSyntax.ml\
+ verit/verit.ml\
+ verit/veritLexer.ml\
+ verit/veritParser.ml\
+ verit/smtlib2_util.ml\
+ verit/smtlib2_parse.ml\
+ verit/smtlib2_lex.ml\
+ verit/smtlib2_genConstr.ml\
+ verit/smtlib2_ast.ml\
+ trace/smtTrace.ml\
+ trace/smtMisc.ml\
+ trace/smtForm.ml\
+ trace/smtCnf.ml\
+ trace/smtCertif.ml\
+ trace/smtAtom.ml\
+ trace/satAtom.ml\
+ trace/coqTerms.ml
+
+-include $(addsuffix .d,$(MLFILES))
+.SECONDARY: $(addsuffix .d,$(MLFILES))
+
+MLIFILES:=verit/veritSyntax.mli\
+ trace/smtForm.mli\
+ trace/smtAtom.mli
+
+-include $(addsuffix .d,$(MLIFILES))
+.SECONDARY: $(addsuffix .d,$(MLIFILES))
+
+ALLCMOFILES:=$(ML4FILES:.ml4=.cmo) $(MLFILES:.ml=.cmo)
+CMOFILES=$(filter-out $(addsuffix .cmo,$(foreach lib,$(MLLIBFILES:.mllib=_MLLIB_DEPENDENCIES) $(MLPACKFILES:.mlpack=_MLPACK_DEPENDENCIES),$($(lib)))),$(ALLCMOFILES))
+CMXFILES=$(CMOFILES:.cmo=.cmx)
+CMIFILES=$(sort $(ALLCMOFILES:.cmo=.cmi) $(MLIFILES:.mli=.cmi))
+CMXSFILES=$(CMXFILES:.cmx=.cmxs)
+
+#######################################
+# #
+# Definition of the toplevel targets. #
+# #
+#######################################
+
+all: ml $(CMXFILES) $(CMXA) $(CMXS) $(VOFILES)
+
+mlihtml: $(MLIFILES:.mli=.cmi)
+ mkdir $@ || rm -rf $@/*
+ $(OCAMLDOC) -html -rectypes -d $@ -m A $(ZDEBUG) $(ZFLAGS) $(^:.cmi=.mli)
+
+all-mli.tex: $(MLIFILES:.mli=.cmi)
+ $(OCAMLDOC) -latex -rectypes -o $@ -m A $(ZDEBUG) $(ZFLAGS) $(^:.cmi=.mli)
+
+spec: $(VIFILES)
+
+gallina: $(GFILES)
+
+html: $(GLOBFILES) $(VFILES)
+ - mkdir -p html
+ $(COQDOC) -toc $(COQDOCFLAGS) -html $(COQDOCLIBS) -d html $(VFILES)
+
+gallinahtml: $(GLOBFILES) $(VFILES)
+ - mkdir -p html
+ $(COQDOC) -toc $(COQDOCFLAGS) -html -g $(COQDOCLIBS) -d html $(VFILES)
+
+all.ps: $(VFILES)
+ $(COQDOC) -toc $(COQDOCFLAGS) -ps $(COQDOCLIBS) -o $@ `$(COQDEP) -sort -suffix .v $^`
+
+all-gal.ps: $(VFILES)
+ $(COQDOC) -toc $(COQDOCFLAGS) -ps -g $(COQDOCLIBS) -o $@ `$(COQDEP) -sort -suffix .v $^`
+
+all.pdf: $(VFILES)
+ $(COQDOC) -toc $(COQDOCFLAGS) -pdf $(COQDOCLIBS) -o $@ `$(COQDEP) -sort -suffix .v $^`
+
+all-gal.pdf: $(VFILES)
+ $(COQDOC) -toc $(COQDOCFLAGS) -pdf -g $(COQDOCLIBS) -o $@ `$(COQDEP) -sort -suffix .v $^`
+
+validate: $(VOFILES)
+ $(COQCHK) $(COQCHKFLAGS) $(COQLIBS) $(notdir $(^:.vo=))
+
+beautify: $(VFILES:=.beautified)
+ for file in $^; do mv $${file%.beautified} $${file%beautified}old && mv $${file} $${file%.beautified}; done
+ @echo 'Do not do "make clean" until you are sure that everything went well!'
+ @echo 'If there were a problem, execute "for file in $$(find . -name \*.v.old -print); do mv $${file} $${file%.old}; done" in your shell/'
+
+.PHONY: all opt byte archclean clean install userinstall depend html validate
+
+###################
+# #
+# Custom targets. #
+# #
+###################
+
+$(CMXS): $(CMXA)
+ $(CAMLOPTLINK) $(ZFLAGS) -o $@ -linkall -shared $^
+
+$(CMXA): trace/smtMisc.cmx trace/coqTerms.cmx trace/smtForm.cmx trace/smtCertif.cmx trace/smtTrace.cmx trace/smtCnf.cmx trace/satAtom.cmx trace/smtAtom.cmx zchaff/satParser.cmx zchaff/zchaffParser.cmx zchaff/cnfParser.cmx zchaff/zchaff.cmx verit/smtlib2_util.cmx verit/smtlib2_ast.cmx verit/smtlib2_parse.cmx verit/smtlib2_lex.cmx lia/lia.cmx verit/veritSyntax.cmx verit/veritParser.cmx verit/veritLexer.cmx verit/smtlib2_genConstr.cmx verit/verit.cmx trace/smt_tactic.cmx
+ $(CAMLOPTLINK) $(ZFLAGS) -a -o $@ $^
+
+ml: verit/veritParser.ml verit/veritLexer.ml verit/smtlib2_parse.ml verit/smtlib2_lex.ml
+
+
+%.ml %.mli: %.mly
+ $(CAMLYACC) $<
+
+%.ml: %.mll
+ $(CAMLLEX) $<
+
+test:
+ cd ../unit-tests; make
+
+####################
+# #
+# Special targets. #
+# #
+####################
+
+byte:
+ $(MAKE) all "OPT:=-byte"
+
+opt:
+ $(MAKE) all "OPT:=-opt"
+
+userinstall:
+ +$(MAKE) USERINSTALL=true install
+
+install-natdynlink:
+ for i in $(CMXS); do \
+ install -d `dirname $(DSTROOT)$(COQLIBINSTALL)/SMTCoq/$$i`; \
+ install -m 0644 $$i $(DSTROOT)$(COQLIBINSTALL)/SMTCoq/$$i; \
+ done
+ for i in $(CMXA); do \
+ install -d `dirname $(DSTROOT)$(COQLIBINSTALL)/SMTCoq/$$i`; \
+ install -m 0644 $$i $(DSTROOT)$(COQLIBINSTALL)/SMTCoq/$$i; \
+ done
+ for i in $(VCMXS); do \
+ install -d `dirname $(DSTROOT)$(COQLIBINSTALL)/SMTCoq/$$i`; \
+ install -m 0644 $$i $(DSTROOT)$(COQLIBINSTALL)/SMTCoq/$$i; \
+ done
+
+install:$(if ifeq '$(HASNATDYNLINK)' 'true',install-natdynlink)
+ for i in $(VOFILES) $(OBJFILES) $(OBJFILES:.o=.cm*); do \
+ install -d `dirname $(DSTROOT)$(COQLIBINSTALL)/SMTCoq/$$i`; \
+ install -m 0644 $$i $(DSTROOT)$(COQLIBINSTALL)/SMTCoq/$$i; \
+ done
+ for i in $(CMXFILES); do \
+ install -d `dirname $(DSTROOT)$(COQLIBINSTALL)/SMTCoq/$$i`; \
+ install -m 0644 $$i $(DSTROOT)$(COQLIBINSTALL)/SMTCoq/$$i; \
+ done
+ for i in $(CMIFILES); do \
+ install -d `dirname $(DSTROOT)$(COQLIBINSTALL)/SMTCoq/$$i`; \
+ install -m 0644 $$i $(DSTROOT)$(COQLIBINSTALL)/SMTCoq/$$i; \
+ done
+
+install-doc:
+ install -d $(DSTROOT)$(COQDOCINSTALL)/SMTCoq/html
+ for i in html/*; do \
+ install -m 0644 $$i $(DSTROOT)$(COQDOCINSTALL)/SMTCoq/$$i;\
+ done
+ install -d $(DSTROOT)$(COQDOCINSTALL)/SMTCoq/mlihtml
+ for i in mlihtml/*; do \
+ install -m 0644 $$i $(DSTROOT)$(COQDOCINSTALL)/SMTCoq/$$i;\
+ done
+
+clean:
+ rm -f $(ALLCMOFILES) $(CMIFILES) $(CMAFILES)
+ rm -f $(ALLCMOFILES:.cmo=.cmx) $(CMXAFILES) $(CMXSFILES) $(ALLCMOFILES:.cmo=.o) $(CMXAFILES:.cmxa=.a)
+ rm -f $(addsuffix .d,$(MLFILES) $(MLIFILES) $(ML4FILES) $(MLLIBFILES) $(MLPACKFILES))
+ rm -f $(OBJFILES) $(OBJFILES:.o=.native)
+ rm -f $(OBJFILES:.o=.cmi) $(OBJFILES:.o=.cmo)
+ rm -f $(OBJFILES:.o=.cmx) $(OBJFILES:.o=.cmxs)
+ rm -f $(VOFILES) $(VIFILES) $(GFILES) $(VFILES:.v=.v.d) $(VFILES:=.beautified) $(VFILES:=.old)
+ rm -f all.ps all-gal.ps all.pdf all-gal.pdf all.glob $(VFILES:.v=.glob) $(VFILES:.v=.tex) $(VFILES:.v=.g.tex) all-mli.tex
+ - rm -rf html mlihtml
+ - rm -rf $(CMXS)
+ - rm -rf $(CMXA)
+ - rm -rf ml
+ - rm -rf test
+ - rm -f NSMTCoq* cnf/NSMTCoq* euf/NSMTCoq* lia/NSMTCoq* spl/NSMTCoq* ../unit-tests/NSMTCoq* ../unit-tests/*.zlog ../unit-tests/*.vtlog verit/veritParser.mli verit/veritParser.ml verit/veritLexer.ml verit/smtlib2_parse.mli verit/smtlib2_parse.ml verit/smtlib2_lex.ml
+
+archclean:
+ rm -f *.cmx *.o
+
+printenv:
+ @$(COQBIN)coqtop -config
+ @echo CAMLC = $(CAMLC)
+ @echo CAMLOPTC = $(CAMLOPTC)
+ @echo PP = $(PP)
+ @echo COQFLAGS = $(COQFLAGS)
+ @echo COQLIBINSTALL = $(COQLIBINSTALL)
+ @echo COQDOCINSTALL = $(COQDOCINSTALL)
+
+
+###################
+# #
+# Implicit rules. #
+# #
+###################
+
+%.cmi: %.mli
+ $(CAMLC) $(ZDEBUG) $(ZFLAGS) $<
+
+%.mli.d: %.mli
+ $(OCAMLDEP) -slash $(OCAMLLIBS) "$<" > "$@" || ( RV=$$?; rm -f "$@"; exit $${RV} )
+
+%.cmo: %.ml4
+ $(CAMLC) $(ZDEBUG) $(ZFLAGS) $(PP) -impl $<
+
+%.cmx: %.ml4
+ $(CAMLOPTC) $(ZDEBUG) $(ZFLAGS) $(PP) -impl $<
+
+%.ml4.d: %.ml4
+ $(OCAMLDEP) -slash $(OCAMLLIBS) $(PP) -impl "$<" > "$@" || ( RV=$$?; rm -f "$@"; exit $${RV} )
+
+%.cmo: %.ml
+ $(CAMLC) $(ZDEBUG) $(ZFLAGS) $<
+
+%.cmx: %.ml
+ $(CAMLOPTC) $(ZDEBUG) $(ZFLAGS) $<
+
+%.ml.d: %.ml
+ $(OCAMLDEP) -slash $(OCAMLLIBS) "$<" > "$@" || ( RV=$$?; rm -f "$@"; exit $${RV} )
+
+%.cmxs: %.cmx
+ $(CAMLOPTLINK) $(ZDEBUG) $(ZFLAGS) -shared -o $@ $<
+
+%.vo %.glob: %.v
+ $(COQC) $(COQDEBUG) $(COQFLAGS) $*
+
+%.vi: %.v
+ $(COQC) -i $(COQDEBUG) $(COQFLAGS) $*
+
+%.g: %.v
+ $(GALLINA) $<
+
+%.tex: %.v
+ $(COQDOC) $(COQDOCFLAGS) -latex $< -o $@
+
+%.html: %.v %.glob
+ $(COQDOC) $(COQDOCFLAGS) -html $< -o $@
+
+%.g.tex: %.v
+ $(COQDOC) $(COQDOCFLAGS) -latex -g $< -o $@
+
+%.g.html: %.v %.glob
+ $(COQDOC)$(COQDOCFLAGS) -html -g $< -o $@
+
+%.v.d: %.v
+ $(COQDEP) -slash $(COQLIBS) "$<" > "$@" || ( RV=$$?; rm -f "$@"; exit $${RV} )
+
+%.v.beautified:
+ $(COQC) $(COQDEBUG) $(COQFLAGS) -beautify $*
+
+# WARNING
+#
+# This Makefile has been automagically generated
+# Edit at your own risks !
+#
+# END OF WARNING
+
diff --git a/src/Misc.v b/src/Misc.v
new file mode 100644
index 0000000..c3e5de7
--- /dev/null
+++ b/src/Misc.v
@@ -0,0 +1,1004 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+
+Require Import Bool List PArray Int63.
+Local Open Scope int63_scope.
+Local Open Scope array_scope.
+
+
+(** Lemmas about Bool *)
+
+Lemma implb_true_r : forall a, implb a true = true.
+Proof. intros [ | ]; reflexivity. Qed.
+
+
+(** Lemmas about Int63 *)
+
+Lemma le_eq : forall i j,
+ (j <= i) = true -> (j + 1 <= i) = false -> i = j.
+Proof.
+ intros i j; rewrite leb_spec; destruct (dec_Zle [|j+1|] [|i|]) as [H|H].
+ rewrite <- leb_spec in H; rewrite H; discriminate.
+ intros H1 _; apply to_Z_inj; rewrite add_spec, to_Z_1 in H.
+ assert (H2: (([|j|] + 1)%Z < wB)%Z \/ ([|j|] + 1)%Z = wB).
+ pose (H3 := to_Z_bounded j); omega.
+ destruct H2 as [H2|H2].
+ rewrite Zmod_small in H.
+ omega.
+ split.
+ pose (H3 := to_Z_bounded j); omega.
+ assumption.
+ rewrite H2, Z_mod_same_full in H; elim H; destruct (to_Z_bounded i) as [H3 _]; assumption.
+Qed.
+
+
+Lemma lt_eq : forall i j,
+ (i < j + 1) = true -> (i < j) = false -> i = j.
+Proof.
+ intros i j. rewrite ltb_spec. destruct (dec_Zlt [|i|] [|j|]) as [H|H].
+ rewrite <- ltb_spec in H; rewrite H; discriminate.
+ intros H1 _; apply to_Z_inj. rewrite add_spec in H1. rewrite to_Z_1 in H1.
+ assert (H2: (([|j|] + 1)%Z < wB)%Z \/ ([|j|] + 1)%Z = wB).
+ pose (H3 := to_Z_bounded j); omega.
+ destruct H2 as [H2|H2].
+ rewrite Zmod_small in H1.
+ omega.
+ split.
+ pose (H3 := to_Z_bounded j); omega.
+ assumption.
+ rewrite H2, Z_mod_same_full in H1; elimtype False. destruct (to_Z_bounded i) as [H3 _]. omega.
+Qed.
+
+
+Lemma foldi_down_ZInd2 :
+ forall A (P: Z -> A -> Prop) (f:int -> A -> A) max min a,
+ (max < min = true -> P ([|min|])%Z a) ->
+ (P ([|max|]+1)%Z a) ->
+ (forall i a, min <= i = true -> i <= max = true -> P ([|i|]+1)%Z a -> P [|i|] (f i a)) ->
+ P [|min|] (foldi_down f max min a).
+Proof.
+ unfold foldi_down;intros A P f max min a Hlt;intros.
+ set (P' z cont :=
+ if Zlt_bool z ([|min|]+1)%Z then cont = (fun a0 : A => a0)
+ else forall a, P z a -> P [|min|] (cont a)).
+ assert (H1: P' ([|max|]+1)%Z (foldi_down_cont (fun (i : int) (cont : A -> A) (a0 : A) => cont (f i a0)) max
+ min (fun a0 : A => a0))).
+ apply foldi_down_cont_ZInd;intros;red.
+ assert (H20: (z+1 < [|min|]+1)%Z).
+ omega.
+ rewrite Zlt_is_lt_bool in H20; rewrite H20;trivial.
+ case_eq (Zlt_bool ([|i|]+1) ([|min|]+1));intros.
+ rewrite <- Zlt_is_lt_bool in H4;rewrite leb_spec in H1;elimtype False;omega.
+ clear H4;revert H3;unfold P'.
+ case_eq (Zlt_bool ([|i|] - 1 + 1) ([|min|]+1));intros;auto.
+ rewrite <- Zlt_is_lt_bool in H3; assert ([|i|] = [|min|]) by (rewrite leb_spec in H1;omega).
+ rewrite H4, <- H6. apply H0;trivial.
+ apply H4. replace ([|i|] - 1 + 1)%Z with [|i|] by omega. auto.
+ revert H1;unfold P'.
+ case_eq (Zlt_bool ([|max|]+1)%Z ([|min|]+1)%Z);auto.
+ rewrite <- Zlt_is_lt_bool.
+ intro H22; assert (H21: ([|max|] < [|min|])%Z). omega.
+ rewrite <- ltb_spec in H21. intros;rewrite foldi_down_cont_lt;auto.
+Qed.
+
+
+Lemma foldi_down_Ind2 : forall A (P : int -> A -> Prop) f max min a,
+ (max < max_int = true) ->
+ (max < min = true -> P min a) ->
+ P (max+1) a ->
+ (forall i a, min <= i = true -> i <= max = true ->
+ P (i+1) a -> P i (f i a)) ->
+ P min (foldi_down f max min a).
+Proof.
+ intros A P f max min a H H0 H1 H2.
+ set (P' z a := (0 <= z < wB)%Z -> P (of_Z z) a).
+ assert (W:= to_Z_add_1 _ _ H).
+ assert (P' ([|min|])%Z (foldi_down f max min a)).
+ apply foldi_down_ZInd2;unfold P';intros.
+ rewrite of_to_Z;auto.
+ rewrite <- W, of_to_Z;auto.
+ rewrite of_to_Z. apply H2; trivial.
+ assert (i < max_int = true).
+ apply leb_ltb_trans with max; trivial.
+ rewrite <- (to_Z_add_1 _ _ H7) in H5. rewrite of_to_Z in H5. apply H5. apply to_Z_bounded.
+ unfold P' in H3; rewrite of_to_Z in H3;apply H3;apply to_Z_bounded.
+Qed.
+
+
+(** Lemmas about PArray.to_list *)
+
+Lemma to_list_In : forall {A} (t: array A) i,
+ i < length t = true -> In (t.[i]) (to_list t).
+Proof.
+ intros A t i H; unfold to_list; case_eq (0 == length t); intro Heq.
+ unfold is_true in H; rewrite ltb_spec in H; rewrite eqb_spec in Heq; rewrite <- Heq in H; rewrite to_Z_0 in H; pose (H1 := to_Z_bounded i); elimtype False; omega.
+ pose (P := fun j a => i < j = true \/ In (t .[ i]) a).
+ pose (H1:= foldi_down_Ind2 _ P); unfold P in H1.
+ assert (H2: i < 0 = true \/ In (t .[ i]) (foldi_down (fun (i0 : int) (l : list A) => t .[ i0] :: l) (length t - 1) 0 nil)).
+ apply H1.
+ rewrite ltb_spec; erewrite to_Z_sub_1; try eassumption.
+ pose (H2 := to_Z_bounded (length t)); change [|max_int|] with (wB-1)%Z; omega.
+ intro H2; elimtype False; rewrite ltb_spec, to_Z_0 in H2; pose (H3 := to_Z_bounded (length t - 1)); omega.
+ left; unfold is_true; rewrite ltb_spec; rewrite (to_Z_add_1 _ max_int).
+ erewrite to_Z_sub_1; try eassumption.
+ unfold is_true in H; rewrite ltb_spec in H; omega.
+ rewrite ltb_spec; erewrite to_Z_sub_1; try eassumption.
+ pose (H2 := to_Z_bounded (length t)); change [|max_int|] with (wB-1)%Z; omega.
+ intros j a H2 H3 [H4|H4].
+ case_eq (i < j); intro Heq2.
+ left; reflexivity.
+ right; rewrite (lt_eq _ _ H4 Heq2); constructor; reflexivity.
+ right; constructor 2; assumption.
+ destruct H2 as [H2|H2]; try assumption.
+ unfold is_true in H2; rewrite ltb_spec, to_Z_0 in H2; pose (H3 := to_Z_bounded i); elimtype False; omega.
+Qed.
+
+Lemma In_to_list : forall {A} (t: array A) x,
+ In x (to_list t) -> exists i, i < length t = true /\ x = t.[i].
+Proof.
+ intros A t x; unfold to_list; case_eq (0 == length t); intro Heq.
+ intro H; inversion H.
+ rewrite eqb_false_spec in Heq.
+ pose (P (_:int) l := In x l ->
+ exists i : int, (i < length t) = true /\ x = t .[ i]).
+ pose (H1 := foldi_down_Ind2 _ P (fun (i : int) (l : list A) => t .[ i] :: l) (length t - 1) 0); unfold P in H1; apply H1.
+ rewrite ltb_spec, to_Z_sub_1_diff; auto; change [|max_int|] with (wB-1)%Z; pose (H2 := to_Z_bounded (length t)); omega.
+ intros _ H; inversion H.
+ intro H; inversion H.
+ simpl; intros i a _ H2 IH [H3|H3].
+ exists i; split; auto; rewrite ltb_spec; rewrite leb_spec, to_Z_sub_1_diff in H2; auto; omega.
+ destruct (IH H3) as [j [H4 H5]]; exists j; auto.
+Qed.
+
+
+(** Lemmas about PArray.mapi *)
+
+Lemma length_mapi : forall {A B} (f:int -> A -> B) t,
+ length (mapi f t) = length t.
+Proof.
+ unfold mapi; intros A B f t; case_eq (length t == 0).
+ rewrite Int63Properties.eqb_spec; intro Heq; rewrite Heq, length_make; auto.
+ rewrite eqb_false_spec; intro Heq; apply foldi_ind.
+ rewrite length_make, ltb_length; auto.
+ intros i a _ H1 H2; rewrite length_set; auto.
+Qed.
+
+
+Lemma default_mapi : forall {A B} (f:int -> A -> B) t,
+ default (mapi f t) = f (length t) (default t).
+Proof.
+ unfold mapi; intros A B f t; case (length t == 0).
+ rewrite default_make; auto.
+ apply foldi_ind.
+ rewrite default_make; auto.
+ intros; rewrite default_set; auto.
+Qed.
+
+Lemma get_mapi : forall {A B} (f:int -> A -> B) t i,
+ i < length t = true -> (mapi f t).[i] = f i (t.[i]).
+Proof.
+ intros A B f t i Hi; generalize (length_mapi f t); unfold mapi; case_eq (length t == 0).
+ rewrite Int63Properties.eqb_spec; intro Heq; rewrite Heq in Hi; eelim ltb_0; eassumption.
+ rewrite eqb_false_spec; intro Heq; pose (Hi':=Hi); replace (length t) with ((length t - 1) + 1) in Hi'.
+ generalize Hi'; apply (foldi_Ind _ (fun j a => (i < j) = true -> length a = length t -> a.[i] = f i (t.[i]))).
+ rewrite ltb_spec, (to_Z_sub_1 _ i); auto; destruct (to_Z_bounded (length t)) as [_ H]; change [|max_int|] with (wB-1)%Z; omega.
+ intros H _; eelim ltb_0; eassumption.
+ intros H; eelim ltb_0; eassumption.
+ intros j a _ H1 IH H2 H3; rewrite length_set in H3; case_eq (j == i).
+ rewrite Int63Properties.eqb_spec; intro Heq2; subst i; rewrite get_set_same; auto; rewrite H3; auto.
+ rewrite eqb_false_spec; intro Heq2; rewrite get_set_other; auto; apply IH; auto; rewrite ltb_spec; rewrite ltb_spec, (to_Z_add_1 _ (length t)) in H2.
+ assert (H4: [|i|] <> [|j|]) by (intro H4; apply Heq2, to_Z_inj; auto); omega.
+ rewrite ltb_spec; rewrite leb_spec, (to_Z_sub_1 _ _ Hi) in H1; omega.
+ apply to_Z_inj; rewrite (to_Z_add_1 _ max_int).
+ rewrite to_Z_sub_1_diff; auto; omega.
+ rewrite ltb_spec, to_Z_sub_1_diff; auto; destruct (to_Z_bounded (length t)) as [_ H]; change [|max_int|] with (wB-1)%Z; omega.
+Qed.
+
+
+Lemma get_mapi_outofbound : forall {A B} (f:int -> A -> B) t i,
+ i < length t = false -> (mapi f t).[i] = f (length t) (default t).
+Proof.
+ intros A B f t i H1; rewrite get_outofbound.
+ apply default_mapi.
+ rewrite length_mapi; auto.
+Qed.
+
+
+(** Custom fold_left and fold_right *)
+
+Definition afold_left A B default (OP : A -> A -> A) (F : B -> A) (V : array B) :=
+ let n := PArray.length V in
+ if n == 0 then default
+ else foldi (fun i a => OP a (F (V.[i]))) 1 (n-1) (F (V.[0])).
+
+
+Definition afold_right A B default (OP : A -> A -> A) (F : B -> A) (V : array B) :=
+ let n := PArray.length V in
+ if n == 0 then default else
+ if n <= 1 then F (V.[0])
+ else foldi_down (fun i b => OP (F (V.[i])) b) (n-2) 0 (F (V.[n-1])).
+
+
+(** Some properties about afold_left *)
+
+Lemma afold_left_eq :
+ forall A B OP def (F1 F2 : A -> B) V1 V2,
+ length V1 = length V2 ->
+ (forall i, i < length V1 = true -> F1 (V1.[i]) = F2 (V2.[i])) ->
+ afold_left _ _ def OP F1 V1 = afold_left _ _ def OP F2 V2.
+Proof.
+ unfold afold_left;intros. rewrite <- H.
+ destruct (Int63Properties.reflect_eqb (length V1) 0);trivial.
+ rewrite (H0 0); [ | unfold is_true;rewrite <- not_0_ltb;trivial].
+ apply foldi_eq_compat;intros;rewrite H0;trivial.
+ unfold is_true;rewrite ltb_leb_sub1;trivial.
+Qed.
+
+
+Definition afoldi_left {A B:Type} default (OP : int -> A -> A -> A) (F : B -> A) (V : array B) :=
+ let n := PArray.length V in
+ if n == 0 then default
+ else foldi (fun i a => OP i a (F (V.[i]))) 1 (n-1) (F (V.[0])).
+
+
+Lemma afoldi_left_Ind :
+ forall {A B: Type} (P : int -> A -> Prop) default (OP : int -> A -> A -> A) (F : B -> A) (t:array B),
+ if length t == 0 then
+ True
+ else
+ (forall a i, i < length t = true -> P i a -> P (i+1) (OP i a (F (t.[i])))) ->
+ P 1 (F (t.[0])) ->
+ P (length t) (afoldi_left default OP F t).
+Proof.
+ intros A B P default OP F t; case_eq (length t == 0).
+ intros; exact I.
+ intros Heq H1 H2; unfold afoldi_left; rewrite Heq;
+ assert (H: (length t - 1) + 1 = length t) by ring.
+ rewrite <- H at 1; apply foldi_Ind; auto.
+ assert (W:= leb_max_int (length t)); rewrite leb_spec in W.
+ rewrite ltb_spec, to_Z_sub_1_diff; auto with zarith.
+ intro H3; rewrite H3 in Heq; discriminate.
+ intro Hlt; assert (H3: length t - 1 = 0).
+ rewrite ltb_spec, to_Z_1 in Hlt; apply to_Z_inj; rewrite to_Z_0; pose (H3 := to_Z_bounded (length t - 1)); omega.
+ rewrite H3; assumption.
+ intros i a H3 H4; apply H1; trivial.
+ rewrite ltb_leb_sub1; auto.
+ intro H5; rewrite H5 in Heq; discriminate.
+Qed.
+
+
+Lemma afold_left_Ind :
+ forall A B (P : int -> A -> Prop) default (OP : A -> A -> A) (F : B -> A) (t:array B),
+ if length t == 0 then
+ True
+ else
+ (forall a i, i < length t = true -> P i a -> P (i+1) (OP a (F (t.[i])))) ->
+ P 1 (F (t.[0])) ->
+ P (length t) (afold_left A B default OP F t).
+Proof.
+ intros A B P default OP F t;
+ apply (afoldi_left_Ind P default (fun _ => OP)); trivial.
+Qed.
+
+
+Lemma afold_left_ind :
+ forall A B (P : A -> Prop) default (OP : A -> A -> A) (F : B -> A) (t:array B),
+ (forall a i, i < length t = true -> P a -> P (OP a (F (t.[i])))) ->
+ P default -> P (F (t.[0])) ->
+ P (afold_left _ _ default OP F t).
+Proof.
+ intros A B P default OP F t H1 H2 H4.
+ pose (H3 := afold_left_Ind A B (fun _ => P) default OP F t).
+ case_eq (length t == 0); intro Heq.
+ unfold afold_left; rewrite Heq; assumption.
+ rewrite Heq in H3; apply H3; trivial.
+Qed.
+
+
+Lemma afold_left_spec : forall A B (f:B -> A) args op e,
+ (forall a, op e a = a) ->
+ afold_left _ _ e op f args =
+ fold_left (fun a v => op a (f v)) e args.
+ Proof.
+ unfold afold_left, fold_left;intros A B f args op neu H10.
+ destruct (reflect_eqb (length args) 0) as [e|n].
+ rewrite e, eqb_refl;trivial.
+ apply not_eq_sym in n;rewrite (eqb_false_complete _ _ n).
+ case_eq (0 < (length args - 1));intros H.
+ rewrite foldi_lt with (from := 0);trivial.
+ rewrite H10; auto.
+ assert (H0: (0 <> [|length args|])%Z).
+ intros Heq;apply n;apply to_Z_inj;trivial.
+ assert (H1: length args = 1).
+ generalize (to_Z_bounded (length args)).
+ rewrite <- not_true_iff_false, ltb_spec, to_Z_0, to_Z_sub_1_diff in H;auto.
+ intros;apply to_Z_inj;rewrite to_Z_1;omega.
+ rewrite H1; change (1 - 1) with 0; rewrite (foldi_eq _ _ 0 0); auto.
+ Qed.
+
+
+(** Some properties about afold_right *)
+
+Lemma afold_right_eq :
+ forall A B OP def (F1 F2 : A -> B) V1 V2,
+ length V1 = length V2 ->
+ (forall i, i < length V1 = true -> F1 (V1.[i]) = F2 (V2.[i])) ->
+ afold_right _ _ def OP F1 V1 = afold_right _ _ def OP F2 V2.
+Proof.
+ unfold afold_right;intros.
+ rewrite <- H.
+ destruct (Int63Properties.reflect_eqb (length V1) 0);trivial.
+ destruct (reflect_leb (length V1) 1);intros.
+ apply H0;unfold is_true;rewrite ltb_leb_sub1;trivial. apply leb_0.
+ assert (length V1 - 1 < length V1 = true).
+ rewrite ltb_leb_sub1;auto using leb_refl.
+ rewrite (H0 (length V1 - 1));trivial.
+ apply foldi_down_eq_compat;intros;rewrite H0;trivial.
+ unfold is_true;rewrite ltb_leb_sub1;[ | trivial].
+ apply ltb_leb_sub1;trivial.
+ revert n0 H3;rewrite ltb_spec, leb_spec, to_Z_1, sub_spec.
+ change [|2|] with 2%Z.
+ intros HH;assert (W:= to_Z_bounded (length V1));rewrite Zmod_small;omega.
+Qed.
+
+
+Definition afoldi_right {A B:Type} default (OP : int -> A -> A -> A) (F : B -> A) (V : array B) :=
+ let n := PArray.length V in
+ if n == 0 then default
+ else if n <= 1 then F (V .[ 0])
+ else foldi_down (fun i a => OP i (F (V.[i])) a) (n-2) 0 (F (V.[n-1])).
+
+
+Lemma afoldi_right_Ind :
+ forall {A B: Type} (P : int -> A -> Prop) default (OP : int -> A -> A -> A) (F : B -> A) (t:array B),
+ if length t <= 1 then
+ True
+ else
+ (forall a i, i < length t - 1 = true -> P (i+1) a -> P i (OP i (F (t.[i])) a)) ->
+ P ((length t)-1) (F (t.[(length t)-1])) ->
+ P 0 (afoldi_right default OP F t).
+Proof.
+ intros A B P default OP F t; case_eq (length t <= 1).
+ intros; exact I.
+ intros Heq H1 H2; unfold afoldi_right. replace (length t == 0) with false.
+ rewrite Heq.
+ set (P' z a := P (of_Z (z + 1)) a).
+ change (P' ([|0|] - 1)%Z (foldi_down (fun (i : int) (a : A) => OP i (F (t .[ i])) a) (length t - 2) 0 (F (t .[ length t - 1])))).
+ apply foldi_down_ZInd;unfold P'.
+ intros Hlt;elim (ltb_0 _ Hlt).
+ replace (length t - 2) with (length t - 1 - 1) by ring.
+ rewrite to_Z_sub_1_diff.
+ ring_simplify ([|length t - 1|] - 1 + 1)%Z;rewrite of_to_Z;trivial.
+ assert (H10: (1 < length t) = true) by (rewrite ltb_negb_geb, Heq; auto).
+ intro H11. rewrite ltb_spec in H10. assert (H12: [|length t - 1|] = 0%Z) by (rewrite H11; auto). change [|1|] with (1%Z) in H10. rewrite to_Z_sub_1_diff in H12; [omega| ]. intro H13. assert (H14: [|length t|] = 0%Z) by (rewrite H13; auto). omega.
+ intros;ring_simplify ([|i|] - 1 + 1)%Z;rewrite of_to_Z;auto.
+ assert (i < length t - 1 = true).
+ rewrite ltb_spec. rewrite leb_spec in H0. replace (length t - 2) with (length t - 1 - 1) in H0 by ring. rewrite to_Z_sub_1_diff in H0; [omega| ]. intro H4. assert (H5: [|length t - 1|] = 0%Z) by (rewrite H4; auto). assert (H6: 1 < length t = true) by (rewrite ltb_negb_geb, Heq; auto). rewrite ltb_spec in H6. change ([|1|]) with (1%Z) in H6. rewrite to_Z_sub_1_diff in H5; [omega| ]. intro H7. assert (H8: [|length t|] = 0%Z) by (rewrite H7; auto). omega.
+ apply H1;trivial.
+ rewrite <-(to_Z_add_1 _ _ H4), of_to_Z in H3;auto.
+ symmetry. rewrite eqb_false_spec. intro H. rewrite H in Heq. discriminate.
+Qed.
+
+
+Lemma afold_right_Ind :
+ forall A B (P : int -> A -> Prop) default (OP : A -> A -> A) (F : B -> A) (t:array B),
+ if length t <= 1 then
+ True
+ else
+ (forall a i, i < length t - 1 = true -> P (i+1) a -> P i (OP (F (t.[i])) a)) ->
+ P ((length t)-1) (F (t.[(length t)-1])) ->
+ P 0 (afold_right A B default OP F t).
+Proof.
+ intros A B P default OP F t;
+ apply (afoldi_right_Ind P default (fun _ => OP)); trivial.
+Qed.
+
+
+Lemma afold_right_ind :
+ forall A B (P : A -> Prop) default (OP : A -> A -> A) (F : B -> A) (t:array B),
+ (forall a i, i < length t - 1 = true -> P a -> P (OP (F (t.[i])) a)) ->
+ P default -> P (F (t.[length t - 1])) ->
+ P (afold_right _ _ default OP F t).
+Proof.
+ intros A B P default OP F t H1 H2 H4.
+ pose (H3 := afold_right_Ind A B (fun _ => P) default OP F t).
+ unfold afold_right. case_eq (length t == 0); auto. intro H10. assert (H := H10). rewrite eqb_false_spec in H. case_eq (length t <= 1); intro Heq.
+ replace 0 with (length t - 1); auto. apply to_Z_inj. rewrite to_Z_sub_1_diff; auto. rewrite leb_spec in Heq. assert (H5 := leb_0 (length t)). rewrite leb_spec in H5. change [|0|] with 0%Z in *. change [|1|] with 1%Z in Heq. assert (H6 : [|length t|] <> 0%Z) by (intro H6; elim H; apply to_Z_inj; auto). omega. rewrite Heq in H3. unfold afold_right in H3. rewrite H10, Heq in H3. apply H3; auto.
+Qed.
+
+
+Lemma afold_right_ind_nonempty :
+ forall A B (P : A -> Prop) default (OP : A -> A -> A) (F : B -> A) (t:array B),
+ (forall a i, i < length t - 1 = true -> P a -> P (OP (F (t.[i])) a)) ->
+ 0 < length t = true -> P (F (t.[length t - 1])) ->
+ P (afold_right _ _ default OP F t).
+Proof.
+ intros A B P default OP F t H1 H2 H4.
+ pose (H3 := afold_right_Ind A B (fun _ => P) default OP F t).
+ unfold afold_right. assert (H10 : length t == 0 = false) by (rewrite eqb_false_spec; intro H; rewrite H in H2; discriminate). rewrite H10. assert (H := H10). rewrite eqb_false_spec in H. case_eq (length t <= 1); intro Heq.
+ replace 0 with (length t - 1); auto. apply to_Z_inj. rewrite to_Z_sub_1_diff; auto. rewrite leb_spec in Heq. assert (H5 := leb_0 (length t)). rewrite leb_spec in H5. change [|0|] with 0%Z in *. change [|1|] with 1%Z in Heq. assert (H6 : [|length t|] <> 0%Z) by (intro H6; elim H; apply to_Z_inj; auto). omega. rewrite Heq in H3. unfold afold_right in H3. rewrite H10, Heq in H3. apply H3; auto.
+Qed.
+
+
+Lemma afold_right_spec : forall A B (f:B -> A) args op e,
+ (forall a, op a e = a) ->
+ afold_right _ _ e op f args =
+ fold_right (fun v a => op (f v) a) args e.
+ Proof.
+ unfold afold_right, fold_right;intros A B f args op neu H10.
+ destruct (reflect_eqb (length args) 0) as [e|n].
+ rewrite e, eqb_refl;trivial.
+ apply not_eq_sym in n;rewrite (eqb_false_complete _ _ n).
+ case_eq (length args <= 1); intro Heq.
+ assert (H11: length args = 1).
+ apply to_Z_inj. rewrite leb_spec in Heq. assert (H11: 0%Z <> [|length args|]) by (intro H; elim n; apply to_Z_inj; auto). change [|1|] with (1%Z) in *. assert (H12 := leb_0 (length args)). rewrite leb_spec in H12. change [|0|] with 0%Z in H12. omega.
+ rewrite H11, foldi_down_eq; auto.
+ assert (H11: 1 < length args = true) by (rewrite ltb_negb_geb, Heq; auto). replace (foldi_down (fun (i : int) (b : A) => op (f (args .[ i])) b) (length args - 1) 0 neu) with (foldi_down (fun (i : int) (b : A) => op (f (args .[ i])) b) (length args - 1 - 1) 0 (op (f (args .[ length args - 1])) neu)).
+ replace (length args - 1 - 1) with (length args - 2) by ring. rewrite H10. auto.
+ symmetry. apply foldi_down_gt. rewrite ltb_spec. change [|0|] with 0%Z. rewrite to_Z_sub_1_diff; auto. rewrite ltb_spec in H11. change [|1|] with 1%Z in H11. omega.
+ Qed.
+
+
+(** Application to our uses of afold_left and afold_right *)
+(* Case andb *)
+
+Lemma afold_left_andb_false : forall A i a f,
+ i < length a = true ->
+ f (a .[ i]) = false ->
+ afold_left bool A true andb f a = false.
+Proof.
+ intros A i a f; rewrite afold_left_spec; auto; apply (fold_left_Ind _ _ (fun j t => (i < j) = true -> f (a .[ i]) = false -> t = false)).
+ intros b j H1 H2 H3 H4; case_eq (i == j).
+ rewrite Int63Properties.eqb_spec; intro; subst i; rewrite H4, andb_false_r; auto.
+ rewrite eqb_false_spec; intro Heq; rewrite H2; auto; rewrite ltb_spec; rewrite ltb_spec in H3; rewrite (to_Z_add_1 _ (length a)) in H3; auto; assert (H5: [|i|] <> [|j|]) by (intro H5; apply Heq, to_Z_inj; auto); omega.
+ intro H; eelim ltb_0; eassumption.
+Qed.
+
+
+Lemma afold_left_andb_false_inv : forall A a f,
+ afold_left bool A true andb f a = false ->
+ exists i, (i < length a = true) /\ (f (a .[ i]) = false).
+Proof.
+ intros A a f; rewrite afold_left_spec; auto; apply fold_left_ind; try discriminate.
+ intros b i H1; case b; simpl.
+ intros _ H2; exists i; auto.
+ intros H2 _; destruct (H2 (refl_equal false)) as [j [H3 H4]]; exists j; auto.
+Qed.
+
+
+Lemma afold_left_andb_true : forall A a f,
+ (forall i, i < length a = true -> f (a.[i]) = true) ->
+ afold_left bool A true andb f a = true.
+Proof.
+ intros A a f H; rewrite afold_left_spec; auto; apply fold_left_ind; trivial; intros b j H1 H2; rewrite H2; simpl; rewrite H; trivial.
+Qed.
+
+
+Lemma afold_left_andb_true_inv : forall A a f,
+ afold_left bool A true andb f a = true ->
+ forall i, i < length a = true -> f (a.[i]) = true.
+Proof.
+ intros A a f; rewrite afold_left_spec; auto; apply (fold_left_Ind _ _ (fun j t => t = true -> forall i, (i < j) = true -> f (a .[ i]) = true)).
+ intros b i H1; case b; simpl; try discriminate; intros H2 H3 j Hj; case_eq (j == i); intro Heq.
+ rewrite Int63Properties.eqb_spec in Heq; subst j; auto.
+ apply H2; auto; rewrite eqb_false_spec in Heq; rewrite ltb_spec; rewrite ltb_spec in Hj; assert (H4: [|j|] <> [|i|]) by (intro H; apply Heq, to_Z_inj; auto); rewrite (to_Z_add_1 _ (length a)) in Hj; auto; omega.
+ intros _ i H; eelim ltb_0; eassumption.
+Qed.
+
+
+(* Case orb *)
+
+Lemma afold_left_orb_true : forall A i a f,
+ i < length a = true ->
+ f (a .[ i]) = true ->
+ afold_left bool A false orb f a = true.
+Proof.
+ intros A i a f; rewrite afold_left_spec; auto; apply (fold_left_Ind _ _ (fun j t => (i < j) = true -> f (a .[ i]) = true -> t = true)).
+ intros b j H1 H2 H3 H4; case_eq (i == j).
+ rewrite Int63Properties.eqb_spec; intro; subst i; rewrite H4, orb_true_r; auto.
+ rewrite eqb_false_spec; intro Heq; rewrite H2; auto; rewrite ltb_spec; rewrite ltb_spec in H3; rewrite (to_Z_add_1 _ (length a)) in H3; auto; assert (H5: [|i|] <> [|j|]) by (intro H5; apply Heq, to_Z_inj; auto); omega.
+ intro H; eelim ltb_0; eassumption.
+Qed.
+
+
+Lemma afold_left_orb_true_inv : forall A a f,
+ afold_left bool A false orb f a = true ->
+ exists i, (i < length a = true) /\ (f (a .[ i]) = true).
+Proof.
+ intros A a f; rewrite afold_left_spec; auto; apply fold_left_ind; try discriminate.
+ intros b i H1; case b; simpl.
+ intros H2 _; destruct (H2 (refl_equal true)) as [j [H3 H4]]; exists j; auto.
+ intros _ H2; exists i; auto.
+Qed.
+
+
+Lemma afold_left_orb_false : forall A a f,
+ (forall i, i < length a = true -> f (a.[i]) = false) ->
+ afold_left bool A false orb f a = false.
+Proof.
+ intros A a f H; rewrite afold_left_spec; auto; apply fold_left_ind; trivial; intros b j H1 H2; rewrite H2; simpl; rewrite H; trivial.
+Qed.
+
+
+Lemma afold_left_orb_false_inv : forall A a f,
+ afold_left bool A false orb f a = false ->
+ forall i, i < length a = true -> f (a.[i]) = false.
+Proof.
+ intros A a f; rewrite afold_left_spec; auto; apply (fold_left_Ind _ _ (fun j t => t = false -> forall i, (i < j) = true -> f (a .[ i]) = false)).
+ intros b i H1; case b; simpl; try discriminate; intros H2 H3 j Hj; case_eq (j == i); intro Heq.
+ rewrite Int63Properties.eqb_spec in Heq; subst j; auto.
+ apply H2; auto; rewrite eqb_false_spec in Heq; rewrite ltb_spec; rewrite ltb_spec in Hj; assert (H4: [|j|] <> [|i|]) by (intro H; apply Heq, to_Z_inj; auto); rewrite (to_Z_add_1 _ (length a)) in Hj; auto; omega.
+ intros _ i H; eelim ltb_0; eassumption.
+Qed.
+
+
+(* Case implb *)
+
+Lemma afold_right_implb_false : forall A a f,
+ 0 < length a = true /\
+ (forall i, i < length a - 1 = true -> f (a .[ i]) = true) /\
+ f (a.[length a - 1]) = false ->
+ afold_right bool A true implb f a = false.
+Proof.
+ intros A a f; intros [H1 [H2 H3]]; apply afold_right_ind_nonempty; auto; intros b i H4 H5; rewrite H5, H2; auto.
+Qed.
+
+
+Lemma afold_right_implb_false_inv : forall A a f,
+ afold_right bool A true implb f a = false ->
+ 0 < length a = true /\
+ (forall i, i < length a - 1 = true -> f (a .[ i]) = true) /\
+ f (a.[length a - 1]) = false.
+Proof.
+ intros A a f; case_eq (length a == 0); intro Heq1.
+ unfold afold_right; rewrite Heq1; discriminate.
+ intro H; split.
+ rewrite eqb_false_spec in Heq1; rewrite <- not_0_ltb; auto.
+ generalize H; clear H; case_eq (length a <= 1); intro Heq2.
+ unfold afold_right; rewrite Heq1, Heq2; intro H; replace (length a - 1) with 0.
+ split; auto; intros i Hi; elim (ltb_0 i); auto.
+ rewrite eqb_false_spec in Heq1; apply to_Z_inj; rewrite to_Z_sub_1_diff; auto; rewrite leb_spec in Heq2; change [|1|] with 1%Z in Heq2; assert ([|length a|] <> 0%Z) by (intro H1; apply Heq1, to_Z_inj; auto); generalize (leb_0 (length a)); rewrite leb_spec; change [|0|] with 0%Z; omega.
+ pose (P j k := k = false -> (forall i : int, (j <= i) = true -> (i < length a - 1) = true -> f (a .[ i]) = true) /\ f (a .[ length a - 1]) = false); assert (H: P 0 (afold_right bool A true implb f a)).
+ generalize (afold_right_Ind _ _ P true implb f a); rewrite Heq2; intro IH; apply IH; clear IH; unfold P.
+ intros b i H1 H2 H3; case_eq b; intro Heq3.
+ rewrite Heq3 in H3; generalize H3; case (f (a .[ i])); discriminate.
+ destruct (H2 Heq3) as [H4 H5]; split; auto; intros j H6 H7; case_eq (i == j); intro Heq4.
+ rewrite eqb_spec in Heq4; subst j b; generalize H3; case (f (a .[ i])); auto; discriminate.
+ apply H4; auto; rewrite leb_spec in *; rewrite (to_Z_add_1 _ _ H1); rewrite eqb_false_spec in Heq4; assert ([|i|] <> [|j|]) by (intro H; apply Heq4, to_Z_inj; auto); omega.
+ intro H; split; auto; intros i H1 H2; elimtype False; rewrite leb_spec in H1; rewrite ltb_spec in H2; omega.
+ unfold P in H; intro H1; destruct (H H1) as [H2 H3]; split; auto; intro i; apply H2, leb_0.
+Qed.
+
+
+Lemma afold_right_implb_true_aux : forall A a f,
+ (exists i, i < length a - 1 = true /\ f (a.[i]) = false) ->
+ afold_right bool A true implb f a = true.
+Proof.
+ intros A a f; case_eq (length a == 0); intro Heq1.
+ intros _; unfold afold_right; rewrite Heq1; auto.
+ case_eq (length a <= 1); intro Heq2.
+ intros [i [Hi _]]; elim (ltb_0 i); replace 0 with (length a - 1); auto; rewrite eqb_false_spec in Heq1; apply to_Z_inj; rewrite to_Z_sub_1_diff; auto; assert (H1: [|length a|] <> 0%Z) by (intro H; apply Heq1, to_Z_inj; auto); rewrite leb_spec in Heq2; generalize (leb_0 (length a)); rewrite leb_spec; change [|0|] with 0%Z; change [|1|] with 1%Z in Heq2; omega.
+ pose (P j k := (exists i : int, (j <= i) = true /\ (i < length a - 1) = true /\ f (a .[ i]) = false) -> k = true); assert (H: P 0 (afold_right bool A true implb f a)).
+ generalize (afold_right_Ind _ _ P true implb f a); rewrite Heq2; intro IH; apply IH; clear IH; unfold P.
+ intros b i H1 H2 [j [H3 [H4 H5]]]; case_eq (i == j); intro Heq3.
+ rewrite eqb_spec in Heq3; subst i; rewrite H5; case b; auto.
+ rewrite H2.
+ case (f (a .[ i])); auto.
+ exists j; repeat split; auto; assert (H: i < j = true).
+ rewrite ltb_spec; rewrite leb_spec in H3; rewrite eqb_false_spec in Heq3; assert (H: [|i|] <> [|j|]) by (intro H; apply Heq3, to_Z_inj; auto); omega.
+ rewrite leb_spec, (to_Z_add_1 _ _ H); rewrite ltb_spec in H; omega.
+ intros [i [H1 [H2 _]]]; elimtype False; rewrite leb_spec in H1; rewrite ltb_spec in H2; omega.
+ unfold P in H; intros [i Hi]; apply H; exists i; split; auto; apply leb_0.
+Qed.
+
+
+Lemma afold_right_implb_true : forall A a f,
+ length a = 0 \/ (exists i, i < length a - 1 = true /\ f (a.[i]) = false) \/
+ (forall i, i < length a = true -> f (a.[i]) = true) ->
+ afold_right bool A true implb f a = true.
+Proof.
+ intros A a f; case_eq (length a == 0).
+ intros H _; unfold afold_right; rewrite H; auto.
+ intros Heq [H1|[H1|H1]].
+ rewrite H1 in Heq; discriminate.
+ apply afold_right_implb_true_aux; auto.
+ apply afold_right_ind_nonempty.
+ intros b i H2 H3; subst b; case (f (a .[ i])); auto.
+ apply not_0_ltb; intro H; rewrite H in Heq; discriminate.
+ apply H1; rewrite ltb_spec, to_Z_sub_1_diff; [omega| ]; intro H; rewrite H in Heq; discriminate.
+Qed.
+
+
+Lemma afold_right_implb_true_inv : forall A a f,
+ afold_right bool A true implb f a = true ->
+ length a = 0 \/ (exists i, i < length a - 1 = true /\ f (a.[i]) = false) \/
+ (forall i, i < length a = true -> f (a.[i]) = true).
+Proof.
+ intros A a f; case_eq (length a == 0); intro Heq1.
+ intros _; left; rewrite eqb_spec in Heq1; auto.
+ case_eq (length a <= 1); intro Heq2.
+ unfold afold_right; rewrite Heq1, Heq2; intro H; right; right; intros i Hi; replace i with 0; auto; apply to_Z_inj; rewrite ltb_spec in Hi; rewrite eqb_false_spec in Heq1; assert (H1: [|length a|] <> 0%Z) by (intro H1; apply Heq1, to_Z_inj; auto); rewrite leb_spec in Heq2; change [|1|] with 1%Z in Heq2; generalize (leb_0 (length a)) (leb_0 i); rewrite !leb_spec; change [|0|] with 0%Z; omega.
+ pose (P j k := k = true -> (exists i : int, (j <= i) = true /\ (i < length a - 1) = true /\ f (a .[ i]) = false) \/ (forall i : int, (j <= i) = true -> (i < length a) = true -> f (a .[ i]) = true)); assert (H: P 0 (afold_right bool A true implb f a)).
+ generalize (afold_right_Ind _ _ P true implb f a); rewrite Heq2; intro IH; apply IH; clear IH; unfold P.
+ intros b i H1 H2 H3; case_eq b; intro Heq3.
+ destruct (H2 Heq3) as [[j [H4 [H5 H6]]]|H4].
+ left; exists j; repeat split; auto; rewrite leb_spec in *; rewrite (to_Z_add_1 _ _ H1) in H4; omega.
+ case_eq (f (a.[i])); intro Heq4.
+ right; intros j H5 H6; case_eq (i == j); intro Heq5.
+ rewrite eqb_spec in Heq5; subst j; auto.
+ apply H4; auto; rewrite leb_spec in *; rewrite (to_Z_add_1 _ _ H1); rewrite eqb_false_spec in Heq5; assert ([|i|] <> [|j|]) by (intro H; apply Heq5, to_Z_inj; auto); omega.
+ left; exists i; repeat split; auto; apply leb_refl.
+ rewrite Heq3 in H3; case_eq (f (a .[ i])); intro Heq4; rewrite Heq4 in H3; try discriminate; left; exists i; repeat split; auto; apply leb_refl.
+ intros H1; right; intros i H2 H3; replace i with (length a - 1); auto; apply to_Z_inj; rewrite leb_spec in H2; rewrite (to_Z_sub_1 _ _ H3) in *; rewrite ltb_spec in H3; omega.
+ unfold P in H; intro H1; right; destruct (H H1) as [[i [_ H2]]|H2].
+ left; exists i; auto.
+ right; intro i; apply H2, leb_0.
+Qed.
+
+
+(* Other cases *)
+
+Lemma afold_left_length_2 : forall A B default OP F t,
+ (length t == 2) = true ->
+ afold_left A B default OP F t = OP (F (t.[0])) (F (t.[1])).
+Proof.
+ intros A B default OP F t H; unfold afold_left; rewrite eqb_spec in H; rewrite H; change (2 == 0) with false; simpl; change (2-1) with 1; rewrite foldi_eq; trivial.
+Qed.
+
+
+Lemma afold_right_length_2 : forall A B default OP F t,
+ (length t == 2) = true ->
+ afold_right A B default OP F t = OP (F (t.[0])) (F (t.[1])).
+Proof.
+ intros A B default OP F t H; unfold afold_right; rewrite eqb_spec in H; rewrite H; change (2 == 0) with false; simpl; change (2<=1) with false; simpl; change (2-2) with 0; rewrite foldi_down_eq; trivial.
+Qed.
+
+
+Ltac tac_left :=
+ intros t f H H1 H2; rewrite afold_left_length_2;
+ [rewrite H1, H2| ]; trivial.
+
+
+Ltac tac_right :=
+ try (intros t f H H1 H2; rewrite afold_right_length_2;
+ [rewrite H1, H2| ]; trivial);
+ try (intros t f H H1; rewrite afold_right_length_2;
+ [rewrite H1| ]; trivial);
+ try (rewrite implb_true_r; trivial).
+
+
+Lemma afold_left_xorb_false1 : forall t f,
+ (PArray.length t == 2) = true ->
+ f (t .[ 0]) = false -> f (t .[ 1]) = false ->
+ afold_left bool int false xorb f t = false.
+Proof. tac_left. Qed.
+
+
+Lemma afold_left_xorb_false2 : forall t f,
+ (PArray.length t == 2) = true ->
+ f (t .[ 0]) = true -> f (t .[ 1]) = true ->
+ afold_left bool int false xorb f t = false.
+Proof. tac_left. Qed.
+
+
+Lemma afold_left_xorb_true1 : forall t f,
+ (PArray.length t == 2) = true ->
+ f (t .[ 0]) = false -> f (t .[ 1]) = true ->
+ afold_left bool int false xorb f t = true.
+Proof. tac_left. Qed.
+
+
+Lemma afold_left_xorb_true2 : forall t f,
+ (PArray.length t == 2) = true ->
+ f (t .[ 0]) = true -> f (t .[ 1]) = false ->
+ afold_left bool int false xorb f t = true.
+Proof. tac_left. Qed.
+
+
+(* Lemma afold_right_implb_false : forall t f, *)
+(* (PArray.length t == 2) = true -> *)
+(* f (t .[ 0]) = true -> f (t .[ 1]) = false -> *)
+(* afold_right bool int true implb f t = false. *)
+(* Proof. tac_right. Qed. *)
+
+
+(* Lemma afold_right_implb_true1 : forall t f, *)
+(* (PArray.length t == 2) = true -> *)
+(* f (t .[ 0]) = false -> *)
+(* afold_right bool int true implb f t = true. *)
+(* Proof. tac_right. Qed. *)
+
+
+(* Lemma afold_right_implb_true2 : forall t f, *)
+(* (PArray.length t == 2) = true -> *)
+(* f (t.[1]) = true -> *)
+(* afold_right bool int true implb f t = true. *)
+(* Proof. tac_right. Qed. *)
+
+
+Lemma afold_left_eqb_false1 : forall t f,
+ (PArray.length t == 2) = true ->
+ f (t .[ 0]) = false -> f (t .[ 1]) = true ->
+ afold_left bool int true eqb f t = false.
+Proof. tac_left. Qed.
+
+
+Lemma afold_left_eqb_false2 : forall t f,
+ (PArray.length t == 2) = true ->
+ f (t .[ 0]) = true -> f (t .[ 1]) = false ->
+ afold_left bool int true eqb f t = false.
+Proof. tac_left. Qed.
+
+
+Lemma afold_left_eqb_true1 : forall t f,
+ (PArray.length t == 2) = true ->
+ f (t .[ 0]) = true -> f (t .[ 1]) = true ->
+ afold_left bool int true eqb f t = true.
+Proof. tac_left. Qed.
+
+
+Lemma afold_left_eqb_true2 : forall t f,
+ (PArray.length t == 2) = true ->
+ f (t .[ 0]) = false -> f (t .[ 1]) = false ->
+ afold_left bool int true eqb f t = true.
+Proof. tac_left. Qed.
+
+
+(** Two elements in a list *)
+
+Section List2.
+
+ Variable A : Type.
+
+ Inductive In2 (i j : A) : list A -> Prop :=
+ | In2_hd : forall l, In j l -> In2 i j (i::l)
+ | In2_tl : forall k l, In2 i j l -> In2 i j (k::l).
+
+ Local Hint Constructors In2.
+
+
+ Lemma In2_app : forall i j l m, In2 i j (l ++ m) <->
+ In2 i j l \/ (In i l /\ In j m) \/ In2 i j m.
+ Proof.
+ intros i j; induction l as [ |t l IHl]; simpl; intro m; split; auto.
+ intros [H|[[H _]|H]]; auto.
+ inversion H.
+ elim H.
+ intro H; inversion H; clear H.
+ subst i l0; rewrite in_app_iff in H1; destruct H1 as [H1|H1]; auto.
+ subst k l0; rewrite IHl in H1; destruct H1 as [H1|[[H1 H2]|H1]]; auto.
+ intros [H|[[[H|H] H1]|H]].
+ inversion H; clear H.
+ subst i l0; constructor 1; rewrite in_app_iff; auto.
+ subst k l0; constructor 2; rewrite IHl; left; auto.
+ subst t; constructor 1; rewrite in_app_iff; auto.
+ constructor 2; rewrite IHl; right; left; auto.
+ constructor 2; rewrite IHl; right; right; auto.
+ Qed.
+
+
+ Fixpoint rev_aux acc (l:list A) :=
+ match l with
+ | nil => acc
+ | t::q => rev_aux (t::acc) q
+ end.
+
+
+ Lemma In2_rev_aux : forall i j l acc, In2 i j (rev_aux acc l) <->
+ In2 i j acc \/ (In i l /\ In j acc) \/ In2 j i l.
+ Proof.
+ intros i j; induction l as [ |t q IHq]; simpl; intro acc; split; auto.
+ intros [H|[[H _]|H]]; auto.
+ elim H.
+ inversion H.
+ rewrite IHq; clear IHq; intros [H|[[H1 H2]|H]]; auto.
+ inversion H; auto.
+ inversion H2; auto; clear H2; subst t; right; right; auto.
+ intros [H|[[[H1|H1] H2]|H]]; rewrite IHq; clear IHq; auto.
+ subst t; auto.
+ right; left; split; auto; constructor 2; auto.
+ inversion H; clear H; auto; subst j l; right; left; split; auto; constructor 1; auto.
+ Qed.
+
+
+ Definition rev := rev_aux nil.
+
+
+ Lemma In2_rev : forall i j l, In2 i j (rev l) <-> In2 j i l.
+ Proof.
+ intros i j l; unfold rev; rewrite In2_rev_aux; split; auto; intros [H|[[_ H]|H]]; auto; inversion H.
+ Qed.
+
+
+ Lemma In2_In : forall i j, i <> j -> forall l, (In i l /\ In j l) <-> (In2 i j l \/ In2 j i l).
+ Proof.
+ intros i j H l; split.
+ intros [H1 H2]; generalize H1 H2; clear H1 H2; induction l as [ |t q IHq].
+ intro H1; inversion H1.
+ intros H1 H2; inversion H1; clear H1.
+ subst t; inversion H2; auto; elim H; auto.
+ inversion H2; clear H2.
+ subst t; auto.
+ destruct (IHq H0 H1) as [H2|H2]; auto.
+ intros [H1|H1]; induction H1 as [H1|t q H1 [IH1 IH2]].
+ split; [constructor 1|constructor 2]; auto.
+ split; constructor 2; auto.
+ split; [constructor 2|constructor 1]; auto.
+ split; constructor 2; auto.
+ Qed.
+
+End List2.
+
+Arguments In2 [A] i j _.
+Arguments rev [A] l.
+Arguments In2_In [A i j] _ l.
+
+
+(** List of distinct elements *)
+
+Section Distinct.
+
+ Variable A : Type.
+ Variable eq : A -> A -> bool.
+
+ Fixpoint distinct_aux2 acc ref l :=
+ match l with
+ | nil => acc
+ | t::q => distinct_aux2 (acc && (negb (eq ref t))) ref q
+ end.
+
+ Lemma distinct_aux2_spec : forall ref l acc, distinct_aux2 acc ref l = true
+ <->
+ acc = true /\ (forall i, In i l -> eq ref i = false).
+ Proof.
+ intro ref; induction l as [ |t q IHq]; simpl.
+ intro acc; split.
+ intro H; split; auto; intros i H1; elim H1.
+ intros [H _]; auto.
+ intro acc; rewrite (IHq (acc && negb (eq ref t))); split.
+ rewrite andb_true_iff; intros [[H1 H2] H3]; split; auto; intros i [Hi|Hi]; auto; subst i; generalize H2; case (eq ref t); auto; discriminate.
+ intros [H1 H2]; rewrite andb_true_iff; repeat split; auto; rewrite (H2 t); auto.
+ Qed.
+
+ Lemma distinct_aux2_spec_neg : forall ref l acc,
+ distinct_aux2 acc ref l = false <->
+ acc = false \/ (exists i, In i l /\ eq ref i = true).
+ Proof.
+ intro ref; induction l as [ |t q IHq]; simpl.
+ intro acc; split; auto; intros [H|[i [H _]]]; auto; elim H.
+ intro acc; rewrite (IHq (acc && negb (eq ref t))); rewrite andb_false_iff;split.
+ intros [[H|H]|[i [H1 H2]]]; auto.
+ right; exists t; split; auto; generalize H; case (eq ref t); auto.
+ right; exists i; split; auto.
+ intros [H|[i [[H1|H1] H2]]]; auto.
+ subst t; left; right; generalize H2; case (eq ref i); auto.
+ right; exists i; auto.
+ Qed.
+
+ Fixpoint distinct_aux acc l :=
+ match l with
+ | nil => acc
+ | t::q =>
+ let acc' := distinct_aux2 acc t q in
+ distinct_aux acc' q
+ end.
+
+ Local Hint Constructors In2.
+
+ Lemma distinct_aux_spec : forall l acc, distinct_aux acc l = true <->
+ acc = true /\ (forall i j, In2 i j l -> eq i j = false).
+ Proof.
+ induction l as [ |t q IHq]; simpl.
+ intro acc; split.
+ intro H; split; auto; intros i j H1; inversion H1.
+ intros [H _]; auto.
+ intro acc; rewrite (IHq (distinct_aux2 acc t q)), distinct_aux2_spec; split.
+ intros [[H1 H2] H3]; split; auto; intros i j H; inversion H; auto.
+ intros [H1 H2]; repeat split; auto.
+ Qed.
+
+ Lemma distinct_aux_spec_neg : forall l acc, distinct_aux acc l = false <->
+ acc = false \/ (exists i j, In2 i j l /\ eq i j = true).
+ Proof.
+ induction l as [ |t q IHq]; simpl.
+ intro acc; split; auto; intros [H|[i [j [H _]]]]; auto; inversion H.
+ intro acc; rewrite (IHq (distinct_aux2 acc t q)), distinct_aux2_spec_neg; split.
+ intros [[H|[i [H1 H2]]]|[i [j [H1 H2]]]]; auto.
+ right; exists t; exists i; auto.
+ right; exists i; exists j; auto.
+ intros [H|[i [j [H1 H2]]]]; auto; inversion H1; clear H1.
+ subst i l; left; right; exists j; auto.
+ subst k l; right; exists i; exists j; auto.
+ Qed.
+
+ Definition distinct := distinct_aux true.
+
+ Lemma distinct_spec : forall l, distinct l = true <->
+ (forall i j, In2 i j l -> eq i j = false).
+ Proof.
+ unfold distinct; intro l; rewrite distinct_aux_spec; split; auto; intros [_ H]; auto.
+ Qed.
+
+ Lemma distinct_false_spec : forall l, distinct l = false <->
+ (exists i j, In2 i j l /\ eq i j = true).
+ Proof.
+ unfold distinct; intro l; rewrite distinct_aux_spec_neg; split; auto; intros [H|H]; auto; discriminate.
+ Qed.
+
+End Distinct.
+
+Arguments distinct [A] eq l.
+
+
+(** Specification of existsb *)
+
+Lemma existsb_false_spec : forall f from to,
+ existsb f from to = false <->
+ forall i, ((from <= i) = true /\ (i <= to) = true) -> f i = false.
+Proof.
+ unfold existsb;intros; setoid_rewrite leb_spec; apply foldi_cont_ZInd.
+ intros z Hz; split; auto; intros _ i [H1 H2]; assert (H3 := Z.le_trans _ _ _ H1 H2); elimtype False; omega.
+ intros i cont H1 H2 H3; case_eq (f i); intro Heq.
+ split; try discriminate; intro H; rewrite <- Heq; apply H; split; try omega; rewrite leb_spec in H2; auto.
+ rewrite H3; split; intros H j [Hj1 Hj2].
+ case_eq (i == j); intro Heq2.
+ rewrite eqb_spec in Heq2; subst j; auto.
+ apply H; split; auto; rewrite eqb_false_spec in Heq2; assert ([|i|] <> [|j|]) by (intro; apply Heq2, to_Z_inj; auto); omega.
+ apply H; omega.
+Qed.
+
+
+Lemma array_existsbi_false_spec : forall A (f : int -> A -> bool) t,
+ existsbi f t = false <->
+ forall i, i < length t = true -> f i (t.[i]) = false.
+Proof.
+ unfold existsbi;intros A f t; destruct (reflect_eqb 0 (length t)).
+ split; auto. intros _ i Hi. elim (ltb_0 i). rewrite e. auto.
+ rewrite existsb_false_spec. split.
+ intros H i Hi. apply H. split; [apply leb_0| ]. rewrite leb_spec. rewrite (to_Z_sub_1 _ _ Hi). rewrite ltb_spec in Hi. omega.
+ intros H i [_ Hi]. apply H. rewrite ltb_spec. rewrite leb_spec in Hi. rewrite to_Z_sub_1_diff in Hi; auto; omega.
+Qed.
+
+
+Lemma array_existsb_false_spec : forall A (f : A -> bool) t,
+ PArray.existsb f t = false <->
+ forall i, i < length t = true -> f (t.[i]) = false.
+Proof.
+ intros A f t; unfold PArray.existsb; case_eq (0 == length t).
+ rewrite eqb_spec; intro H; split; auto; intros _ i Hi; elim (ltb_0 i); rewrite H; auto.
+ intro H; rewrite existsb_false_spec; split.
+ intros H1 i Hi; apply H1; split; [apply leb_0| ]; rewrite leb_spec, (to_Z_sub_1 _ _ Hi); rewrite ltb_spec in Hi; omega.
+ intros H1 i [_ H2]; apply H1; rewrite ltb_spec; rewrite leb_spec in H2; rewrite to_Z_sub_1_diff in H2; [omega| ]; intro H3; rewrite H3 in H; discriminate.
+Qed.
+
+
+(** Forall of two lists at the same time *)
+
+Section Forall2.
+
+ Variables (A B:Type) (f:A->B->bool).
+
+ Fixpoint forallb2 l1 l2 :=
+ match l1, l2 with
+ | nil, nil => true
+ | a::l1, b::l2 => f a b && forallb2 l1 l2
+ | _, _ => false
+ end.
+
+End Forall2.
+
+Implicit Arguments forallb2 [A B].
+
diff --git a/src/SMTCoq.v b/src/SMTCoq.v
new file mode 100644
index 0000000..e318cc0
--- /dev/null
+++ b/src/SMTCoq.v
@@ -0,0 +1,20 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+Require Export Int63 List PArray.
+Require Export State SMT_terms Trace.
+Export Atom Form Sat_Checker Cnf_Checker Euf_Checker.
+
+Declare ML Module "trace/smt_tactic".
diff --git a/src/SMT_terms.v b/src/SMT_terms.v
new file mode 100644
index 0000000..5f6120e
--- /dev/null
+++ b/src/SMT_terms.v
@@ -0,0 +1,1308 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+
+Add LoadPath "." as SMTCoq.
+Require Import Bool List Int63 PArray.
+Require Import Misc State.
+
+Local Open Scope array_scope.
+Local Open Scope int63_scope.
+
+Hint Unfold is_true.
+
+
+(* Remark: I use Notation instead of Definition du eliminate conversion check during the type checking *)
+Notation atom := int (only parsing).
+
+Module Form.
+
+ Notation fargs := (array _lit) (only parsing).
+
+ Inductive form : Type :=
+ | Fatom (_:atom)
+ | Ftrue
+ | Ffalse
+ | Fnot2 (_:int) (_:_lit)
+ | Fand (_:fargs)
+ | For (_:fargs)
+ | Fimp (_:fargs)
+ | Fxor (_:_lit) (_:_lit)
+ | Fiff (_:_lit) (_:_lit)
+ | Fite (_:_lit) (_:_lit) (_:_lit).
+
+ Definition is_Ftrue h :=
+ match h with Ftrue => true | _ => false end.
+
+ Definition is_Ffalse h :=
+ match h with Ffalse => true | _ => false end.
+
+ Lemma is_Ftrue_correct : forall h, is_Ftrue h -> h = Ftrue.
+ Proof. destruct h;trivial;discriminate. Qed.
+
+ Lemma is_Ffalse_correct : forall h, is_Ffalse h -> h = Ffalse.
+ Proof. destruct h;trivial;discriminate. Qed.
+
+ Section Interp.
+ Variable interp_atom : atom -> bool.
+
+ Section Interp_form.
+
+ (* On suppose qu'on a l'interprétation des litéraux *)
+ Variable interp_var : var -> bool.
+
+ (* Interprétation d'une formule en supposant l'interprétation
+ des litéraux *)
+ (* (les litéraux font office d'index de hachage) *)
+ Definition interp_aux (h:form) : bool :=
+ match h with
+ | Fatom a => interp_atom a
+ | Ftrue => true
+ | Ffalse => false
+ | Fnot2 i l => fold (fun b => negb (negb b)) 1 i (Lit.interp interp_var l)
+ | Fand args => afold_left _ _ true andb (Lit.interp interp_var) args
+ | For args => afold_left _ _ false orb (Lit.interp interp_var) args
+ | Fimp args => afold_right _ _ true implb (Lit.interp interp_var) args
+ | Fxor a b => xorb (Lit.interp interp_var a) (Lit.interp interp_var b)
+ | Fiff a b => Bool.eqb (Lit.interp interp_var a) (Lit.interp interp_var b)
+ | Fite a b c =>
+ if Lit.interp interp_var a then Lit.interp interp_var b
+ else Lit.interp interp_var c
+ end.
+
+ End Interp_form.
+
+ Section Interp_get.
+
+ Variable t_form : PArray.array form.
+
+ Definition t_interp : PArray.array bool :=
+ PArray.foldi_left (fun i t_b hf =>
+ t_b.[i <- interp_aux (PArray.get t_b) hf])
+ (PArray.make (PArray.length t_form) true) t_form.
+
+ Fixpoint lt_form i h:=
+ match h with
+ | Fatom _ | Ftrue | Ffalse => true
+ | Fnot2 _ l => Lit.blit l < i
+ | Fand args | For args | Fimp args =>
+ PArray.forallb (fun l => Lit.blit l < i) args
+ | Fxor a b | Fiff a b => (Lit.blit a < i) && (Lit.blit b < i)
+ | Fite a b c => (Lit.blit a < i) && (Lit.blit b < i) && (Lit.blit c < i)
+ end.
+
+ Lemma lt_form_interp_form_aux :
+ forall f1 f2 i h,
+ (forall j, j < i -> f1 j = f2 j) ->
+ lt_form i h ->
+ interp_aux f1 h = interp_aux f2 h.
+ Proof.
+ destruct h;simpl;intros;trivial;
+ try (apply afold_left_eq;unfold is_true in H0;
+ rewrite PArray.forallb_spec in H0;intros;
+ auto using Lit.interp_eq_compat).
+ f_equal;auto using Lit.interp_eq_compat.
+ apply afold_right_eq;unfold is_true in H0;
+ rewrite PArray.forallb_spec in H0;intros;
+ auto using Lit.interp_eq_compat.
+ unfold is_true in H0;rewrite !andb_true_iff in H0;decompose [and] H0;
+ rewrite !(Lit.interp_eq_compat f1 f2);auto.
+ unfold is_true in H0;rewrite !andb_true_iff in H0;decompose [and] H0;
+ rewrite !(Lit.interp_eq_compat f1 f2);auto.
+ unfold is_true in H0;rewrite !andb_true_iff in H0;decompose [and] H0;
+ rewrite !(Lit.interp_eq_compat f1 f2);auto.
+ Qed.
+
+ Definition wf := PArray.forallbi lt_form t_form.
+
+ Hypothesis wf_t_i : wf.
+
+ Lemma length_t_interp : length t_interp = length t_form.
+ Proof.
+ unfold t_interp;apply PArray.foldi_left_Ind with (P := fun i a => length a = length t_form).
+ intros;rewrite length_set;trivial.
+ rewrite length_make, ltb_length;trivial.
+ Qed.
+
+ Lemma default_t_interp : default t_interp = true.
+ Proof.
+ unfold t_interp;apply PArray.foldi_left_Ind with
+ (P := fun i a => default a = true).
+ intros;rewrite default_set;trivial.
+ apply default_make.
+ Qed.
+
+ Lemma t_interp_wf : forall i, i < PArray.length t_form ->
+ t_interp.[i] = interp_aux (PArray.get t_interp) (t_form.[i]).
+ Proof.
+ set (P' i t := length t = length t_form ->
+ forall j, j < i ->
+ t.[j] = interp_aux (PArray.get t) (t_form.[j])).
+ assert (P' (length t_form) t_interp).
+ unfold is_true, wf in wf_t_i;rewrite PArray.forallbi_spec in wf_t_i.
+ unfold t_interp;apply foldi_left_Ind;unfold P';intros.
+ rewrite length_set in H1.
+ destruct (Int63Properties.reflect_eqb j i).
+ rewrite e, PArray.get_set_same.
+ apply lt_form_interp_form_aux with (2:= wf_t_i i H).
+ intros;rewrite get_set_other;trivial.
+ intros Heq;elim (not_ltb_refl i);rewrite Heq at 1;trivial.
+ rewrite H1;trivial.
+ assert (j < i).
+ assert ([|j|] <> [|i|]) by (intros Heq1;elim n;apply to_Z_inj;trivial).
+ generalize H2;unfold is_true;rewrite !ltb_spec, (to_Z_add_1 _ _ H);
+ auto with zarith.
+ rewrite get_set_other, H0;auto.
+ apply lt_form_interp_form_aux with
+ (2:= wf_t_i j (ltb_trans _ _ _ H3 H)).
+ intros;rewrite get_set_other;trivial.
+ intros Heq;elim (not_ltb_refl i);apply ltb_trans with j;
+ [ rewrite Heq| ];trivial.
+ elim (ltb_0 _ H0).
+ apply H;apply length_t_interp.
+ Qed.
+
+ End Interp_get.
+
+ Definition interp_state_var t_form :=
+ let t_interp := t_interp t_form in
+ PArray.get t_interp.
+
+ Register interp_aux as PrimInline.
+ Definition interp t_form := interp_aux (interp_state_var t_form).
+
+ Lemma wf_interp_form_lt :
+ forall t_form, wf t_form ->
+ forall x, x < PArray.length t_form ->
+ interp_state_var t_form x = interp t_form (t_form.[x]).
+ Proof.
+ unfold interp_state_var;intros.
+ apply t_interp_wf;trivial.
+ Qed.
+
+ Lemma wf_interp_form :
+ forall t_form, PArray.default t_form = Ftrue -> wf t_form ->
+ forall x, interp_state_var t_form x = interp t_form (t_form.[x]).
+ Proof.
+ intros t Hd Hwf x;case_eq (x < PArray.length t);intros.
+ apply wf_interp_form_lt;trivial.
+ unfold interp_state_var;rewrite !PArray.get_outofbound;trivial.
+ rewrite default_t_interp, Hd;trivial.
+ rewrite length_t_interp;trivial.
+ Qed.
+
+ Definition check_form t_form :=
+ is_Ftrue (PArray.default t_form) &&
+ is_Ftrue (t_form.[0]) &&
+ is_Ffalse (t_form.[1]) &&
+ wf t_form.
+
+ Lemma check_form_correct : forall t_form,
+ check_form t_form ->
+ ((PArray.default t_form = Ftrue /\ wf t_form) /\
+ Valuation.wf (interp_state_var t_form)).
+ Proof.
+ unfold is_true, check_form;intros t;rewrite !andb_true_iff.
+ intros H;decompose [and] H;clear H;
+ assert (PArray.default t = Ftrue) by (apply is_Ftrue_correct;trivial).
+ repeat split;trivial.
+ rewrite wf_interp_form;trivial.
+ apply is_Ftrue_correct in H4;trivial;rewrite H4;reflexivity.
+ rewrite wf_interp_form;trivial.
+ apply is_Ffalse_correct in H3;trivial;rewrite H3;discriminate.
+ Qed.
+
+ End Interp.
+
+End Form.
+
+(* TODO Move this *)
+Record typ_eqb : Type := Typ_eqb {
+ te_carrier : Type;
+ te_eqb : te_carrier -> te_carrier -> bool;
+ te_reflect : forall x y, reflect (x = y) (te_eqb x y)
+}.
+
+(* Common used types into which we interpret *)
+
+(* Unit *)
+
+Section Unit_typ_eqb.
+
+ Let carrier : Type := unit.
+
+ Let eqb : carrier -> carrier -> bool :=
+ fun _ _ => true.
+
+ Lemma unit_reflect :
+ forall x y, reflect (x = y) (eqb x y).
+ Proof.
+ unfold eqb; intros x y; case x; case y; simpl;
+ constructor; reflexivity.
+ Qed.
+
+ Definition unit_typ_eqb :=
+ Typ_eqb carrier eqb unit_reflect.
+
+End Unit_typ_eqb.
+(* End TODO *)
+
+Module Typ.
+
+ Notation index := int (only parsing).
+
+ Inductive type :=
+ | Tindex : index -> type
+ | TZ : type
+ | Tbool : type
+ | Tpositive : type.
+
+ Definition ftype := (list type * type)%type.
+
+ Section Interp.
+
+ Variable t_i : PArray.array typ_eqb.
+
+ Definition interp t :=
+ match t with
+ | Tindex i => (t_i.[i]).(te_carrier)
+ | TZ => Z
+ | Tbool => bool
+ | Tpositive => positive
+ end.
+
+ Definition interp_ftype (t:ftype) :=
+ List.fold_right (fun dom codom =>interp dom -> codom)
+ (interp (snd t)) (fst t).
+
+ (* Boolean equality over interpretation of a btype *)
+ Section Interp_Equality.
+
+ Definition i_eqb (t:type) : interp t -> interp t -> bool :=
+ match t with
+ | Tindex i => (t_i.[i]).(te_eqb)
+ | TZ => Zeq_bool
+ | Tbool => Bool.eqb
+ | Tpositive => Peqb
+ end.
+
+ Lemma i_eqb_spec : forall t x y, i_eqb t x y <-> x = y.
+ Proof.
+ destruct t;simpl;intros.
+ symmetry;apply reflect_iff;apply te_reflect.
+ symmetry;apply Zeq_is_eq_bool.
+ apply Bool.eqb_true_iff.
+ apply Peqb_eq.
+ Qed.
+
+ Lemma reflect_i_eqb : forall t x y, reflect (x = y) (i_eqb t x y).
+ Proof.
+ intros;apply iff_reflect;symmetry;apply i_eqb_spec.
+ Qed.
+
+ Lemma i_eqb_sym : forall t x y, i_eqb t x y = i_eqb t y x.
+ Proof.
+ intros t x y; case_eq (i_eqb t x y); case_eq (i_eqb t y x); auto.
+ change (i_eqb t x y = true) with (is_true (i_eqb t x y)); rewrite i_eqb_spec; intros H1 H2; subst y; pose (H:=reflect_i_eqb t x x); inversion H; [rewrite <- H0 in H1; discriminate|elim H2; auto].
+ change (i_eqb t y x = true) with (is_true (i_eqb t y x)); rewrite i_eqb_spec; intros H1 H2; subst y; pose (H:=reflect_i_eqb t x x); inversion H; [rewrite <- H0 in H2; discriminate|elim H1; auto].
+ Qed.
+
+ End Interp_Equality.
+
+ End Interp.
+
+ (* Plutôt que de tester l'égalité entre deux btypes dans Prop, on
+ écrit une fonction calculant:
+ - si deux btype A et B sont égaux
+ - si oui, une fonction permettant de passer les objets de type A en
+ objets de type B
+ On montre que cette fonction réfléchit l'égalité de Coq. *)
+
+ Section Cast.
+
+ (* L'inductif cast_result spécifie si deux btype sont égaux (Cast) ou
+ non (NoCast). Dans le cas où ils sont égaux, une fonction permet de
+ passer de l'un à l'autre. *)
+
+ Inductive cast_result (A B: type) : Type :=
+ | Cast (k: forall P, P A -> P B)
+ | NoCast.
+
+ Implicit Arguments Cast [A B].
+ Implicit Arguments NoCast [A B].
+
+ Notation idcast := (Cast (fun P x => x)).
+ (* La fonction cast calcule cast_result *)
+
+ Definition cast (A B: type) : cast_result A B :=
+ match A as C, B as D return cast_result C D with
+ | Tindex i, Tindex j =>
+ match cast i j with
+ | Some k => Cast (fun P => k (fun y => P (Tindex y)))
+ | None => NoCast
+ end
+ | TZ, TZ => idcast
+ | Tbool, Tbool => idcast
+ | Tpositive, Tpositive => idcast
+ | _, _ => NoCast
+ end.
+
+ Lemma cast_refl:
+ forall A, cast A A = Cast (fun P (H : P A) => H).
+ Proof.
+ intros A0;destruct A0;simpl;trivial.
+ rewrite cast_refl;trivial.
+ Qed.
+
+ (* Remark : I use this definition because eqb will not be used only in the interpretation *)
+ Definition eqb (A B: type) : bool :=
+ match A, B with
+ | Tindex i, Tindex j => i == j
+ | TZ, TZ => true
+ | Tbool, Tbool => true
+ | Tpositive, Tpositive => true
+ | _, _ => false
+ end.
+
+
+ (* TODO : Move this *)
+ Lemma not_false : ~ false.
+ Proof. intro;discriminate. Qed.
+ Hint Resolve not_false.
+
+ Lemma is_true_true : true.
+ Proof. reflexivity. Qed.
+ Hint Resolve is_true_true.
+
+ Lemma not_is_true_eq_false : forall b:bool, ~ b <-> b = false.
+ Proof. exact not_true_iff_false. Qed.
+
+ Lemma cast_diff: forall A B, eqb A B = false -> cast A B = NoCast.
+ Proof.
+ intros A0 B0;destruct A0; destruct B0;simpl;trivial;try discriminate.
+ intros Heq;rewrite (cast_diff _ _ Heq);trivial.
+ Qed.
+
+ Lemma neq_cast : forall A B,
+ cast A B = (if eqb A B then cast A B else NoCast).
+ Proof.
+ intros C D;case_eq (eqb C D);trivial;apply cast_diff.
+ Qed.
+
+ Lemma reflect_eqb : forall x y, reflect (x = y) (eqb x y).
+ Proof.
+ intros x y;destruct x;destruct y;simpl;try constructor;trivial;try discriminate.
+ apply iff_reflect;rewrite eqb_spec;split;intros H;[inversion H | subst];trivial.
+ Qed.
+
+ Lemma eqb_spec : forall x y, eqb x y <-> x = y.
+ Proof.
+ intros;symmetry;apply reflect_iff;apply reflect_eqb.
+ Qed.
+
+ Lemma eqb_refl : forall x, eqb x x.
+ Proof. intros; rewrite eqb_spec; auto. Qed.
+
+ End Cast.
+
+End Typ.
+
+(* TODO move this *)
+Inductive dlist (A:Type) (P:A->Type) : list A -> Type :=
+| Dnil : dlist A P nil
+| Dcons : forall a l, P a -> dlist A P l -> dlist A P (cons a l).
+
+Set Implicit Arguments.
+Definition list_beq := fun (A : Type) (eq_A : A -> A -> bool) =>
+fix list_eqrec (X Y : list A) : bool :=
+ match X with
+ | nil => match Y with
+ | nil => true
+ | (_ :: _)%list => false
+ end
+ | (x :: x0)%list =>
+ match Y with
+ | nil => false
+ | (x1 :: x2)%list => (eq_A x x1 && list_eqrec x0 x2)%bool
+ end
+ end.
+Unset Implicit Arguments.
+
+Lemma reflect_list_beq : forall (A:Type) (beq:A -> A -> bool),
+ (forall x y, reflect (x = y) (beq x y)) ->
+ forall x y, reflect (x = y) (list_beq beq x y).
+Proof.
+ intros A beq Hbeq;induction x;destruct y;simpl;try (constructor;trivial;discriminate).
+ destruct (Hbeq a a0) as [Heq | Hd];simpl;[ | constructor;intros Heq;elim Hd;inversion Heq;trivial].
+ destruct (IHx y) as [Heq0 | Hd];simpl;[ | constructor;intros Heq0;elim Hd;inversion Heq0;trivial].
+ constructor;subst;trivial.
+Qed.
+
+Lemma list_beq_spec : forall (A:Type) (beq:A -> A -> bool),
+ (forall x y, beq x y <-> x = y) ->
+ forall x y, list_beq beq x y <-> x = y.
+Proof.
+ intros A beq HA x y;symmetry;apply reflect_iff;apply reflect_list_beq.
+ intros;apply iff_reflect;symmetry;apply HA.
+Qed.
+(* End move *)
+
+Module Atom.
+
+ Notation func := int (only parsing).
+
+ Inductive cop : Type :=
+ | CO_xH
+ | CO_Z0.
+
+ Inductive unop : Type :=
+ | UO_xO
+ | UO_xI
+ | UO_Zpos
+ | UO_Zneg
+ | UO_Zopp.
+
+ Inductive binop : Type :=
+ | BO_Zplus
+ | BO_Zminus
+ | BO_Zmult
+ | BO_Zlt
+ | BO_Zle
+ | BO_Zge
+ | BO_Zgt
+ | BO_eq (_ : Typ.type).
+
+ Inductive nop : Type :=
+ | NO_distinct (_ : Typ.type).
+
+ Notation hatom := int (only parsing).
+
+ Inductive atom : Type :=
+ | Acop (_: cop)
+ | Auop (_ : unop) (_:hatom)
+ | Abop (_ : binop) (_:hatom) (_:hatom)
+ | Anop (_ : nop) (_: list hatom)
+ | Aapp (_:func) (_: list hatom).
+
+
+ (* Generic predicates and operations *)
+
+ (** Equality *)
+ Definition cop_eqb o o' :=
+ match o, o' with
+ | CO_xH, CO_xH
+ | CO_Z0, CO_Z0 => true
+ | _,_ => false
+ end.
+
+ Definition uop_eqb o o' :=
+ match o, o' with
+ | UO_xO, UO_xO
+ | UO_xI, UO_xI
+ | UO_Zpos, UO_Zpos
+ | UO_Zneg, UO_Zneg
+ | UO_Zopp, UO_Zopp => true
+ | _,_ => false
+ end.
+
+ Definition bop_eqb o o' :=
+ match o, o' with
+ | BO_Zplus, BO_Zplus
+ | BO_Zminus, BO_Zminus
+ | BO_Zmult, BO_Zmult
+ | BO_Zlt, BO_Zlt
+ | BO_Zle, BO_Zle
+ | BO_Zge, BO_Zge
+ | BO_Zgt, BO_Zgt => true
+ | BO_eq t, BO_eq t' => Typ.eqb t t'
+ | _,_ => false
+ end.
+
+ Definition nop_eqb o o' :=
+ match o, o' with
+ | NO_distinct t, NO_distinct t' => Typ.eqb t t'
+ end.
+
+ Definition eqb (t t':atom) :=
+ match t,t' with
+ | Acop o, Acop o' => cop_eqb o o'
+ | Auop o t, Auop o' t' => uop_eqb o o' && (t == t')
+ | Abop o t1 t2, Abop o' t1' t2' => bop_eqb o o' && (t1 == t1') && (t2 == t2')
+ | Anop o t, Anop o' t' => nop_eqb o o' && list_beq Int63Native.eqb t t'
+ | Aapp a la, Aapp b lb => (a == b) && list_beq Int63Native.eqb la lb
+ | _, _ => false
+ end.
+
+ Ltac preflect t :=
+ let Heq := fresh "Heq" in
+ let Hd := fresh "Hd" in
+ destruct t as [Heq | Hd];simpl;
+ [ | constructor;intros Heq;elim Hd;inversion Heq;trivial].
+
+ Lemma reflect_cop_eqb : forall o1 o2, reflect (o1 = o2) (cop_eqb o1 o2).
+ Proof.
+ destruct o1;destruct o2;simpl;constructor;trivial;discriminate.
+ Qed.
+
+ Lemma reflect_uop_eqb : forall o1 o2, reflect (o1 = o2) (uop_eqb o1 o2).
+ Proof.
+ destruct o1;destruct o2;simpl;constructor;trivial;discriminate.
+ Qed.
+
+ Lemma reflect_bop_eqb : forall o1 o2, reflect (o1 = o2) (bop_eqb o1 o2).
+ Proof.
+ destruct o1;destruct o2;simpl;try (constructor;trivial;discriminate).
+ preflect (Typ.reflect_eqb t t0).
+ constructor;subst;trivial.
+ Qed.
+
+ Lemma reflect_nop_eqb : forall o1 o2, reflect (o1 = o2) (nop_eqb o1 o2).
+ Proof.
+ intros [t1] [t2]; simpl; preflect (Typ.reflect_eqb t1 t2); constructor; subst; reflexivity.
+ Qed.
+
+ Lemma reflect_eqb : forall t1 t2, reflect (t1 = t2) (eqb t1 t2).
+ Proof.
+ destruct t1;destruct t2;simpl; try (constructor;trivial;discriminate).
+ (* Constants *)
+ preflect (reflect_cop_eqb c c0);constructor;subst;trivial.
+ (* Unary operators *)
+ preflect (reflect_uop_eqb u u0); preflect (Int63Properties.reflect_eqb i i0);
+ constructor;subst;trivial.
+ (* Binary operators *)
+ preflect (reflect_bop_eqb b b0);
+ preflect (Int63Properties.reflect_eqb i i1);
+ preflect (Int63Properties.reflect_eqb i0 i2);
+ constructor;subst;trivial.
+ (* N-ary operators *)
+ preflect (reflect_nop_eqb n n0); preflect (reflect_list_beq _ _ Int63Properties.reflect_eqb l l0); constructor; subst; reflexivity.
+ (* Application *)
+ preflect (Int63Properties.reflect_eqb i i0);
+ preflect (reflect_list_beq _ _ Int63Properties.reflect_eqb l l0);
+ constructor;subst;trivial.
+ Qed.
+
+ Lemma eqb_spec : forall t1 t2, eqb t1 t2 <-> t1 = t2.
+ Proof.
+ intros;symmetry;apply reflect_iff;apply reflect_eqb.
+ Qed.
+
+ (** Typing and interpretation *)
+
+ Record val (t:Type) (I:t -> Type) := Val {
+ v_type : t;
+ v_val : I v_type
+ }.
+
+ Section Typing_Interp.
+ Variable t_i : PArray.array typ_eqb.
+
+ Local Notation interp_t := (Typ.interp t_i).
+ Local Notation interp_ft := (Typ.interp_ftype t_i).
+
+ Definition bval := val Typ.type interp_t.
+ Definition Bval := Val Typ.type interp_t.
+ Definition tval := val Typ.ftype interp_ft.
+ Definition Tval := Val Typ.ftype interp_ft.
+
+ Definition bvtrue : bval := Bval Typ.Tbool true.
+ Definition bvfalse : bval := Bval Typ.Tbool false.
+
+ Lemma Bval_inj1 : forall T U t u, Bval T t = Bval U u -> T = U.
+ Proof. intros T U t u H; inversion H; auto. Qed.
+
+ Lemma Bval_inj2 : forall T t u, Bval T t = Bval T u -> t = u.
+ Proof.
+ intros T t u H; assert (H1: (fun (x:bval) =>
+ match Typ.cast (v_type _ _ x) T with
+ | Typ.Cast k => k _ (v_val _ _ x) = v_val _ _ (Bval T u)
+ | Typ.NoCast => True
+ end) (Bval T t)).
+ rewrite H, Typ.cast_refl; reflexivity.
+ simpl in H1; rewrite Typ.cast_refl in H1; auto.
+ Qed.
+
+ (* Interprétation d'une fonction*)
+ Variable t_func : PArray.array tval.
+
+ (** Type checking of atom assuming an type for hatom *)
+ Section Typ_Aux.
+ Variable get_type : hatom -> Typ.type.
+
+ Definition typ_cop o :=
+ match o with
+ | CO_xH => Typ.Tpositive
+ | CO_Z0 => Typ.TZ
+ end.
+
+ Definition typ_uop o :=
+ match o with
+ | UO_xO => (Typ.Tpositive,Typ.Tpositive)
+ | UO_xI => (Typ.Tpositive,Typ.Tpositive)
+ | UO_Zpos => (Typ.Tpositive, Typ.TZ)
+ | UO_Zneg => (Typ.Tpositive, Typ.TZ)
+ | UO_Zopp => (Typ.TZ, Typ.TZ)
+ end.
+
+ Definition typ_bop o :=
+ match o with
+ | BO_Zplus => ((Typ.TZ,Typ.TZ), Typ.TZ)
+ | BO_Zminus => ((Typ.TZ,Typ.TZ), Typ.TZ)
+ | BO_Zmult => ((Typ.TZ,Typ.TZ), Typ.TZ)
+ | BO_Zlt => ((Typ.TZ,Typ.TZ), Typ.Tbool)
+ | BO_Zle => ((Typ.TZ,Typ.TZ), Typ.Tbool)
+ | BO_Zge => ((Typ.TZ,Typ.TZ), Typ.Tbool)
+ | BO_Zgt => ((Typ.TZ,Typ.TZ), Typ.Tbool)
+ | BO_eq t => ((t,t),Typ.Tbool)
+ end.
+
+ Definition typ_nop o :=
+ match o with
+ | NO_distinct t => (t,Typ.Tbool)
+ end.
+
+ Fixpoint check_args (args:list hatom) (targs:list Typ.type) :=
+ match args, targs with
+ | nil, nil => true
+ | a::args, t::targs => Typ.eqb (get_type a) t && check_args args targs
+ | _, _ => false
+ end.
+
+ Definition check_aux (a:atom) (t:Typ.type) : bool :=
+ match a with
+ | Acop o => Typ.eqb (typ_cop o) t
+ | Auop o a =>
+ let (ta,t') := typ_uop o in
+ Typ.eqb t' t && Typ.eqb (get_type a) ta
+ | Abop o a1 a2 =>
+ let (ta,t') := typ_bop o in
+ let (ta1,ta2) := ta in
+ Typ.eqb t' t && Typ.eqb (get_type a1) ta1 && Typ.eqb (get_type a2) ta2
+ | Anop o a =>
+ let (ta,t') := typ_nop o in
+ (Typ.eqb t' t) && (List.forallb (fun t1 => Typ.eqb (get_type t1) ta) a)
+ | Aapp f args =>
+ let (targs,tr) := v_type _ _ (t_func.[f]) in
+ check_args args targs && Typ.eqb tr t
+ end.
+
+ (* Typing is unique *)
+
+ Lemma unicity : forall a t1 t2,
+ check_aux a t1 -> check_aux a t2 -> t1 = t2.
+ Proof.
+ destruct a;simpl.
+ (* Constants *)
+ intros t1 t2;rewrite !Typ.eqb_spec;intros;subst;trivial.
+ (* Unary operators *)
+ unfold is_true; intros t1 t2;rewrite (surjective_pairing (typ_uop u)),!andb_true_iff.
+ intros [H1 _] [H2 _]; change (is_true (Typ.eqb (snd (typ_uop u)) t1)) in H1.
+ change (is_true (Typ.eqb (snd (typ_uop u)) t2)) in H2.
+ rewrite Typ.eqb_spec in H1, H2;subst;trivial.
+ (* Binary operators *)
+ unfold is_true; intros t1 t2;rewrite (surjective_pairing (typ_bop b)),
+ (surjective_pairing (fst (typ_bop b))) ,!andb_true_iff.
+ intros [[H1 _] _] [[H2 _] _]; change (is_true (Typ.eqb (snd (typ_bop b)) t1)) in H1.
+ change (is_true (Typ.eqb (snd (typ_bop b)) t2)) in H2.
+ rewrite Typ.eqb_spec in H1, H2;subst;trivial.
+ (* N-ary operators *)
+ intros t1 t2; destruct (typ_nop n) as [ta t']; unfold is_true; rewrite !andb_true_iff; change (is_true (Typ.eqb t' t1) /\ is_true (List.forallb (fun t3 : int => Typ.eqb (get_type t3) ta) l) -> is_true (Typ.eqb t' t2) /\ is_true (List.forallb (fun t3 : int => Typ.eqb (get_type t3) ta) l) -> t1 = t2); rewrite !Typ.eqb_spec; intros [H1 _] [H2 _]; subst; auto.
+ (* Application *)
+ intros t1 t2;destruct (v_type Typ.ftype interp_ft (t_func.[ i])).
+ unfold is_true;rewrite !andb_true_iff;intros [_ H1] [_ H2].
+ transitivity t;[ symmetry| ];rewrite <-Typ.eqb_spec;trivial.
+ Qed.
+
+ (* Typing is decidable *)
+
+ Lemma check_args_dec : forall tr args targs,
+ {exists T : Typ.type,
+ check_args args targs && Typ.eqb tr T} +
+ {forall T : Typ.type,
+ check_args args targs && Typ.eqb tr T = false}.
+ Proof.
+ intro A; induction args as [ |h l IHl]; simpl.
+ (* Base case *)
+ intros [ | ]; simpl.
+ left; exists A; apply Typ.eqb_refl.
+ intros; right; reflexivity.
+ (* Inductive case *)
+ intros [ |B targs]; simpl.
+ right; reflexivity.
+ case (Typ.eqb (get_type h) B); simpl; auto.
+ Qed.
+
+ Lemma check_aux_dec : forall a,
+ {exists T, check_aux a T} + {forall T, check_aux a T = false}.
+ Proof.
+ intros [op|op h|op h1 h2|op ha|f args]; simpl.
+ (* Constants *)
+ left; destruct op; simpl.
+ exists Typ.Tpositive; auto.
+ exists Typ.TZ; auto.
+ (* Unary operators *)
+ destruct op; simpl; try (case (Typ.eqb (get_type h) Typ.Tpositive); [left; exists Typ.Tpositive|right; intro; rewrite andb_false_r]; reflexivity); try (case (Typ.eqb (get_type h) Typ.Tpositive); [left; exists Typ.TZ|right; intro; rewrite andb_false_r]; reflexivity); case (Typ.eqb (get_type h) Typ.TZ); [left; exists Typ.TZ|right; intro; rewrite andb_false_r]; reflexivity.
+ (* Binary operators *)
+ destruct op; simpl; try (case (Typ.eqb (get_type h1) Typ.TZ); [case (Typ.eqb (get_type h2) Typ.TZ); [left; exists Typ.TZ|right; intro; rewrite andb_false_r]|right; intro; rewrite andb_false_r]; reflexivity); try (case (Typ.eqb (get_type h1) Typ.TZ); [case (Typ.eqb (get_type h2) Typ.TZ); [left; exists Typ.Tbool|right; intro; rewrite andb_false_r]|right; intro; rewrite andb_false_r]; reflexivity); case (Typ.eqb (get_type h1) t); [case (Typ.eqb (get_type h2) t); [left; exists Typ.Tbool|right; intro; rewrite andb_false_r]|right; intro; rewrite andb_false_r]; reflexivity.
+ (* N-ary operators *)
+ destruct op as [ty]; simpl; case (List.forallb (fun t1 : int => Typ.eqb (get_type t1) ty) ha).
+ left; exists Typ.Tbool; auto.
+ right; intro T; rewrite andb_false_r; auto.
+ (* Application *)
+ case (v_type Typ.ftype interp_ft (t_func .[ f])); intros; apply check_args_dec.
+ Qed.
+
+ End Typ_Aux.
+ (** Interpretation of hatom assuming an interpretation for atom *)
+ Section Interp_Aux.
+
+ Variable interp_hatom : hatom -> bval.
+
+ Definition apply_unop (t r : Typ.type)
+ (op : interp_t t -> interp_t r) (tv:bval) :=
+ let (t', v) := tv in
+ match Typ.cast t' t with
+ | Typ.Cast k => Bval r (op (k _ v))
+ | _ => bvtrue
+ end.
+
+ Definition apply_binop (t1 t2 r : Typ.type)
+ (op : interp_t t1 -> interp_t t2 -> interp_t r) (tv1 tv2:bval) :=
+ let (t1', v1) := tv1 in
+ let (t2', v2) := tv2 in
+ match Typ.cast t1' t1, Typ.cast t2' t2 with
+ | Typ.Cast k1, Typ.Cast k2 => Bval r (op (k1 _ v1) (k2 _ v2))
+ | _, _ => bvtrue
+ end.
+
+ Fixpoint apply_func
+ targs tr (f:interp_ft (targs,tr)) (lv:list bval) : bval :=
+ match targs as targs0 return interp_ft (targs0,tr) -> bval with
+ | nil => fun v =>
+ match lv with
+ | nil => Bval tr v
+ | _ => bvtrue
+ end
+ | t::targs => fun f =>
+ match lv with
+ | v::lv =>
+ let (tv,v) := v in
+ match Typ.cast tv t with
+ | Typ.Cast k =>
+ let f := f (k _ v) in apply_func targs tr f lv
+ | _ => bvtrue
+ end
+ | _ => bvtrue
+ end
+ end f.
+
+ Definition interp_cop o :=
+ match o with
+ | CO_xH => Bval Typ.Tpositive xH
+ | CO_Z0 => Bval Typ.TZ Z0
+ end.
+
+ Definition interp_uop o :=
+ match o with
+ | UO_xO => apply_unop Typ.Tpositive Typ.Tpositive xO
+ | UO_xI => apply_unop Typ.Tpositive Typ.Tpositive xI
+ | UO_Zpos => apply_unop Typ.Tpositive Typ.TZ Zpos
+ | UO_Zneg => apply_unop Typ.Tpositive Typ.TZ Zneg
+ | UO_Zopp => apply_unop Typ.TZ Typ.TZ Zopp
+ end.
+
+ Definition interp_bop o :=
+ match o with
+ | BO_Zplus => apply_binop Typ.TZ Typ.TZ Typ.TZ Zplus
+ | BO_Zminus => apply_binop Typ.TZ Typ.TZ Typ.TZ Zminus
+ | BO_Zmult => apply_binop Typ.TZ Typ.TZ Typ.TZ Zmult
+ | BO_Zlt => apply_binop Typ.TZ Typ.TZ Typ.Tbool Zlt_bool
+ | BO_Zle => apply_binop Typ.TZ Typ.TZ Typ.Tbool Zle_bool
+ | BO_Zge => apply_binop Typ.TZ Typ.TZ Typ.Tbool Zge_bool
+ | BO_Zgt => apply_binop Typ.TZ Typ.TZ Typ.Tbool Zgt_bool
+ | BO_eq t => apply_binop t t Typ.Tbool (Typ.i_eqb t_i t)
+ end.
+
+ Fixpoint compute_interp ty acc l :=
+ match l with
+ | nil => Some acc
+ | a::q =>
+ let (ta,va) := interp_hatom a in
+ match Typ.cast ta ty with
+ | Typ.Cast ka => compute_interp ty ((ka _ va)::acc) q
+ | _ => None
+ end
+ end.
+
+ (* Lemma compute_interp_spec : forall ty l acc, *)
+ (* match compute_interp ty acc l with *)
+ (* | Some l' => forall i, In i l' <-> (In i acc \/ (exists a, In a l /\ interp_hatom a = Bval ty i)) *)
+ (* | None => exists a, In a l /\ let (ta,_) := interp_hatom a in ta <> ty *)
+ (* end. *)
+ (* Proof. *)
+ (* intro ty; induction l as [ |a q IHq]; simpl. *)
+ (* intros acc i; split. *)
+ (* intro H; left; auto. *)
+ (* intros [H|[a [H _]]]; auto; elim H. *)
+ (* intro acc; case_eq (interp_hatom a); intros ta va Heq; rewrite Typ.neq_cast; case_eq (Typ.eqb ta ty). *)
+ (* change (Typ.eqb ta ty = true) with (is_true (Typ.eqb ta ty)); rewrite Typ.eqb_spec; intro; subst ta; rewrite Typ.cast_refl; generalize (IHq (va :: acc)); clear IHq; case (compute_interp ty (va :: acc) q). *)
+ (* intros l IH i; rewrite (IH i); clear IH; split; intros [H|[a1 [H1 H2]]]. *)
+ (* inversion H; auto. *)
+ (* subst va; clear H; right; exists a; split; auto. *)
+ (* right; exists a1; split; auto. *)
+ (* left; constructor 2; auto. *)
+ (* destruct H1 as [H1|H1]. *)
+ (* subst a1; left; constructor 1; rewrite Heq in H2; apply (Bval_inj2 ty); auto. *)
+ (* right; exists a1; auto. *)
+ (* intros [a1 [H1 H2]]; exists a1; split; auto. *)
+ (* intro H; exists a; split; auto; rewrite Heq; intro H1; subst ta; rewrite Typ.eqb_refl in H; discriminate. *)
+ (* Qed. *)
+
+ Lemma compute_interp_spec : forall ty l acc,
+ match compute_interp ty acc l with
+ | Some l' => forall i j, In2 i j l' <-> (In2 i j acc \/ (In j acc /\ exists a, In a l /\ interp_hatom a = Bval ty i) \/ (exists a b, In2 b a l /\ interp_hatom a = Bval ty i /\ interp_hatom b = Bval ty j))
+ | None => exists a, In a l /\ let (ta,_) := interp_hatom a in ta <> ty
+ end.
+ Proof.
+ intro ty; induction l as [ |a q IHq]; simpl.
+ intros acc i; split.
+ intro H; left; auto.
+ intros [H|[[_ [a [H _]]]|[a [b [H _]]]]]; auto.
+ elim H.
+ inversion H.
+ intro acc; case_eq (interp_hatom a); intros ta va Heq; rewrite Typ.neq_cast; case_eq (Typ.eqb ta ty).
+ change (Typ.eqb ta ty = true) with (is_true (Typ.eqb ta ty)); rewrite Typ.eqb_spec; intro; subst ta; rewrite Typ.cast_refl; generalize (IHq (va :: acc)); clear IHq; case (compute_interp ty (va :: acc) q).
+ intros l IH i j; rewrite (IH i j); clear IH; split.
+ intros [H|[[H [b [H1 H2]]]|[b [c [H [H1 H2]]]]]].
+ inversion H; clear H.
+ subst i l0; right; left; split; auto; exists a; split; auto.
+ subst k l0; left; auto.
+ inversion H; clear H.
+ subst va; right; right; exists b; exists a; repeat split; auto; constructor 1; auto.
+ right; left; split; auto; exists b; auto.
+ right; right; exists b; exists c; repeat split; auto; constructor 2; auto.
+ intros [H|[[H [b [[H1|H1] H2]]]|[b [c [H [H1 H2]]]]]].
+ left; constructor 2; auto.
+ subst b; rewrite Heq in H2; generalize (Bval_inj2 _ _ _ H2); intro; subst va; left; constructor; auto.
+ right; left; split.
+ constructor 2; auto.
+ exists b; auto.
+ inversion H; clear H.
+ subst c l0; rewrite Heq in H2; generalize (Bval_inj2 _ _ _ H2); intro; subst va; right; left; split.
+ constructor 1; auto.
+ exists b; auto.
+ subst k l0; right; right; exists b; exists c; auto.
+ intros [a1 [H1 H2]]; exists a1; split; auto.
+ intro H; exists a; split; auto; rewrite Heq; intro H1; subst ta; rewrite Typ.eqb_refl in H; discriminate.
+ Qed.
+
+ (* Lemma compute_interp_spec_rev : forall ty l, *)
+ (* match compute_interp ty nil l with *)
+ (* | Some l' => forall i, In i (rev l') <-> (exists a, In a l /\ interp_hatom a = Bval ty i) *)
+ (* | None => exists a, In a l /\ let (ta,_) := interp_hatom a in ta <> ty *)
+ (* end. *)
+ (* Proof. (* ICI *) *)
+ (* intros ty l; generalize (compute_interp_spec ty l nil); case (compute_interp ty nil l); auto; intros l' H i; rewrite <- In_rev, (H i); split; auto; intros [H1|H1]; auto; inversion H1. *)
+ (* Qed. *)
+
+ Lemma compute_interp_spec_rev : forall ty l,
+ match compute_interp ty nil l with
+ | Some l' => forall i j, In2 j i (rev l') <-> (exists a b, In2 b a l /\ interp_hatom a = Bval ty i /\ interp_hatom b = Bval ty j)
+ | None => exists a, In a l /\ let (ta,_) := interp_hatom a in ta <> ty
+ end.
+ Proof.
+ intros ty l; generalize (compute_interp_spec ty l nil); case (compute_interp ty nil l); auto; intros l' H i j; rewrite In2_rev, (H i j); split; auto; intros [H1|[[H1 _]|H1]]; auto; inversion H1.
+ Qed.
+
+ Definition interp_aux (a:atom) : bval :=
+ match a with
+ | Acop o => interp_cop o
+ | Auop o a => interp_uop o (interp_hatom a)
+ | Abop o a1 a2 => interp_bop o (interp_hatom a1) (interp_hatom a2)
+ | Anop (NO_distinct t) a =>
+ match compute_interp t nil a with
+ | Some l => Bval Typ.Tbool (distinct (Typ.i_eqb t_i t) (rev l))
+ | None => bvtrue
+ end
+ | Aapp f args =>
+ let (tf,f) := t_func.[f] in
+ let lv := List.map interp_hatom args in
+ apply_func (fst tf) (snd tf) f lv
+ end.
+
+ Definition interp_bool (v:bval) : bool :=
+ let (t,v) := v in
+ match Typ.cast t Typ.Tbool with
+ | Typ.Cast k => k _ v
+ | _ => true
+ end.
+
+
+ (* If an atom is well-typed, it has an interpretation *)
+
+ Variable get_type : hatom -> Typ.type.
+ Hypothesis check_aux_interp_hatom : forall h,
+ exists v, interp_hatom h = (Bval (get_type h) v).
+
+ Lemma check_args_interp_aux : forall t l f,
+ (let (targs, tr) := v_type Typ.ftype interp_ft f in
+ check_args get_type l targs && Typ.eqb tr t) ->
+ exists v : interp_t t,
+ (let (tf, f0) := f in
+ apply_func (fst tf) (snd tf) f0 (List.map interp_hatom l)) =
+ Bval t v.
+ Proof.
+ intro A; induction l as [ |h l IHl]; simpl; intros [tf f]; simpl.
+ (* Base case *)
+ destruct tf as [[ | ] tr]; try discriminate; simpl; rewrite Typ.eqb_spec; intro; subst tr; exists f; auto.
+ (* Inductive case *)
+ destruct tf as [[ |B targs] tr]; try discriminate; simpl; rewrite <- andb_assoc; unfold is_true; rewrite andb_true_iff; change (Typ.eqb (get_type h) B = true /\ check_args get_type l targs && Typ.eqb tr A = true) with (is_true (Typ.eqb (get_type h) B) /\ is_true (check_args get_type l targs && Typ.eqb tr A)); rewrite Typ.eqb_spec; intros [H1 H2]; destruct (check_aux_interp_hatom h) as [v0 Heq0]; rewrite Heq0; generalize v0 Heq0; rewrite H1; intros v1 Heq1; simpl; generalize (IHl (Tval (targs,tr) (f v1))); simpl; intro IH; destruct (IH H2) as [v2 Heq2]; exists v2; rewrite Typ.cast_refl; auto.
+ Qed.
+
+ Lemma check_aux_interp_aux_aux : forall a t,
+ check_aux get_type a t ->
+ exists v, interp_aux a = (Bval t v).
+ Proof.
+ intros [op|op h|op h1 h2|op ha|f l]; simpl.
+ (* Constants *)
+ destruct op; intros [i| | | ]; simpl; try discriminate; intros _.
+ exists 1%positive; auto.
+ exists 0%Z; auto.
+ (* Unary operators *)
+ destruct op; intros [i| | | ]; simpl; try discriminate; rewrite Typ.eqb_spec; intro H1; destruct (check_aux_interp_hatom h) as [x Hx]; rewrite Hx; simpl; generalize x Hx; rewrite H1; intros y Hy; rewrite Typ.cast_refl.
+ exists (y~0)%positive; auto.
+ exists (y~1)%positive; auto.
+ exists (Zpos y); auto.
+ exists (Zneg y); auto.
+ exists (- y)%Z; auto.
+ (* Binary operators *)
+ destruct op as [ | | | | | | |A]; intros [i| | | ]; simpl; try discriminate; unfold is_true; rewrite andb_true_iff; try (change (Typ.eqb (get_type h1) Typ.TZ = true /\ Typ.eqb (get_type h2) Typ.TZ = true) with (is_true (Typ.eqb (get_type h1) Typ.TZ) /\ is_true (Typ.eqb (get_type h2) Typ.TZ)); rewrite !Typ.eqb_spec; intros [H1 H2]; destruct (check_aux_interp_hatom h1) as [x1 Hx1]; rewrite Hx1; destruct (check_aux_interp_hatom h2) as [x2 Hx2]; rewrite Hx2; simpl; generalize x1 Hx1 x2 Hx2; rewrite H1, H2; intros y1 Hy1 y2 Hy2; rewrite !Typ.cast_refl).
+ exists (y1 + y2)%Z; auto.
+ exists (y1 - y2)%Z; auto.
+ exists (y1 * y2)%Z; auto.
+ exists (y1 <? y2)%Z; auto.
+ exists (y1 <=? y2)%Z; auto.
+ exists (y1 >=? y2)%Z; auto.
+ exists (y1 >? y2)%Z; auto.
+ change (Typ.eqb (get_type h1) A = true /\ Typ.eqb (get_type h2) A = true) with (is_true (Typ.eqb (get_type h1) A) /\ is_true (Typ.eqb (get_type h2) A)); rewrite !Typ.eqb_spec; intros [H1 H2]; destruct (check_aux_interp_hatom h1) as [x1 Hx1]; rewrite Hx1; destruct (check_aux_interp_hatom h2) as [x2 Hx2]; rewrite Hx2; simpl; generalize x1 Hx1 x2 Hx2; rewrite H1, H2; intros y1 Hy1 y2 Hy2; rewrite !Typ.cast_refl; exists (Typ.i_eqb t_i A y1 y2); auto.
+ (* N-ary operators *)
+ destruct op as [A]; simpl; intros [ | | | ]; try discriminate; simpl; intros _; case (compute_interp A nil ha).
+ intro l; exists (distinct (Typ.i_eqb t_i A) (rev l)); auto.
+ exists true; auto.
+ (* Application *)
+ intro t; apply check_args_interp_aux.
+ Qed.
+
+
+ (* If an atom is not well-typed, its interpretation is bvtrue *)
+
+ Lemma check_args_interp_aux_contr : forall l f,
+ (forall T : Typ.type,
+ (let (targs, tr) := v_type Typ.ftype interp_ft f in
+ check_args get_type l targs && Typ.eqb tr T) = false) ->
+ (let (tf, f0) := f in
+ apply_func (fst tf) (snd tf) f0 (List.map interp_hatom l)) = bvtrue.
+ induction l as [ |h l IHl]; simpl; intros [tf f]; simpl.
+ (* Base case *)
+ destruct tf as [[ | ] tr]; simpl; auto; intro H; generalize (H tr); rewrite Typ.eqb_refl; discriminate.
+ (* Inductive case *)
+ destruct tf as [[ |B targs] tr]; simpl; auto. intro H. destruct (check_aux_interp_hatom h) as [v Hv]. rewrite Hv. simpl. assert (H2: (Typ.eqb (get_type h) B = false) \/ (forall T : Typ.type, check_args get_type l targs && Typ.eqb tr T = false)) by (case_eq (Typ.eqb (get_type h) B); try (intros; left; reflexivity); intro Heq; right; intro T; generalize (H T); rewrite Heq; auto). destruct H2 as [H2|H2]; rewrite Typ.neq_cast.
+ rewrite H2. auto.
+ case_eq (Typ.eqb (get_type h) B); auto. change (Typ.eqb (get_type h) B = true) with (is_true (Typ.eqb (get_type h) B)). rewrite Typ.eqb_spec. intro; subst B. rewrite Typ.cast_refl. apply (IHl (Tval (targs,tr) (f v))). auto.
+ Qed.
+
+ Lemma check_aux_interp_aux_contr_aux : forall a,
+ (forall T, check_aux get_type a T = false) ->
+ interp_aux a = bvtrue.
+ Proof.
+ intros [op|op h|op h1 h2|op ha|f l]; simpl.
+ (* Constants *)
+ destruct op; simpl; intro H.
+ discriminate (H Typ.Tpositive).
+ discriminate (H Typ.TZ).
+ (* Unary operators *)
+ destruct op; simpl; intro H; destruct (check_aux_interp_hatom h) as [v Hv]; rewrite Hv; simpl; rewrite Typ.neq_cast; try (pose (H2 := H Typ.Tpositive); simpl in H2; rewrite H2; auto); pose (H2 := H Typ.TZ); simpl in H2; rewrite H2; auto.
+ (* Binary operators *)
+ destruct op; simpl; intro H; destruct (check_aux_interp_hatom h1) as [v1 Hv1]; destruct (check_aux_interp_hatom h2) as [v2 Hv2]; rewrite Hv1, Hv2; simpl; try (pose (H2 := H Typ.TZ); simpl in H2; rewrite andb_false_iff in H2; destruct H2 as [H2|H2]; [rewrite (Typ.neq_cast (get_type h1)), H2|rewrite (Typ.neq_cast (get_type h2)), H2; case (Typ.cast (get_type h1) Typ.TZ)]; auto); try (pose (H2 := H Typ.Tbool); simpl in H2; rewrite andb_false_iff in H2; destruct H2 as [H2|H2]; [rewrite (Typ.neq_cast (get_type h1)), H2|rewrite (Typ.neq_cast (get_type h2)), H2; case (Typ.cast (get_type h1) Typ.TZ)]; auto); case (Typ.cast (get_type h1) t); auto.
+ (* N-ary operators *)
+ destruct op as [A]; simpl; intro H; generalize (H Typ.Tbool); simpl; clear H; assert (H: forall l1, List.forallb (fun t1 : int => Typ.eqb (get_type t1) A) ha = false -> match compute_interp A l1 ha with | Some l => Bval Typ.Tbool (distinct (Typ.i_eqb t_i A) (rev l)) | None => bvtrue end = bvtrue).
+ induction ha as [ |h ha Iha]; simpl.
+ intros; discriminate.
+ intro l1; destruct (check_aux_interp_hatom h) as [vh Hh]; case_eq (Typ.eqb (get_type h) A); simpl.
+ change (Typ.eqb (get_type h) A = true) with (is_true (Typ.eqb (get_type h) A)); rewrite Typ.eqb_spec; intro; subst A; intro H; rewrite Hh; simpl; rewrite Typ.cast_refl; apply Iha; auto.
+ intros H _; rewrite Hh; simpl; rewrite (Typ.cast_diff _ _ H); auto.
+ apply H.
+ (* Application *)
+ apply check_args_interp_aux_contr.
+ Qed.
+
+ End Interp_Aux.
+
+ Section Interp_get.
+
+ Variable t_atom : PArray.array atom.
+
+ Definition t_interp : PArray.array bval :=
+ PArray.foldi_left (fun i t_a a => t_a.[i <- interp_aux (PArray.get t_a) a])
+ (PArray.make (PArray.length t_atom) (interp_cop CO_xH)) t_atom.
+
+ Definition lt_atom i a :=
+ match a with
+ | Acop _ => true
+ | Auop _ h => h < i
+ | Abop _ h1 h2 => (h1 < i) && (h2 < i)
+ | Anop _ ha => List.forallb (fun h => h < i) ha
+ | Aapp f args => List.forallb (fun h => h < i) args
+ end.
+
+ Lemma lt_interp_aux :
+ forall f1 f2 i, (forall j, j < i -> f1 j = f2 j) ->
+ forall a, lt_atom i a ->
+ interp_aux f1 a = interp_aux f2 a.
+ Proof.
+ intros f1 f2 i Hf; destruct a;simpl;intros;auto.
+ (* Unary operators *)
+ rewrite Hf;trivial.
+ (* Binary operators *)
+ unfold is_true in H;rewrite andb_true_iff in H;destruct H;rewrite !Hf;trivial.
+ (* N-ary operators *)
+ destruct n as [A]; replace (compute_interp f1 A nil l) with (compute_interp f2 A nil l); trivial; assert (H1: forall acc, compute_interp f2 A acc l = compute_interp f1 A acc l); auto; induction l as [ |k l IHl]; simpl; auto; intro acc; simpl in H; unfold is_true in H; rewrite andb_true_iff in H; destruct H as [H1 H2]; rewrite (Hf _ H1); destruct (f2 k) as [ta va]; destruct (Typ.cast ta A) as [ka| ]; auto.
+ (* Application *)
+ replace (List.map f1 l) with (List.map f2 l); trivial.
+ induction l;simpl in H |- *;trivial.
+ unfold is_true in H;rewrite andb_true_iff in H;destruct H;rewrite Hf, IHl;trivial.
+ Qed.
+
+ Definition wf := PArray.forallbi lt_atom t_atom.
+
+ Hypothesis wf_t_i : wf.
+
+ Lemma length_t_interp : length t_interp = length t_atom.
+ Proof.
+ unfold t_interp;apply PArray.foldi_left_Ind with
+ (P := fun i a => length a = length t_atom).
+ intros;rewrite length_set;trivial.
+ rewrite length_make, ltb_length;trivial.
+ Qed.
+
+ Lemma default_t_interp : default t_interp = interp_cop CO_xH.
+ Proof.
+ unfold t_interp;apply PArray.foldi_left_Ind with
+ (P := fun i a => default a = interp_cop CO_xH).
+ intros;rewrite default_set;trivial.
+ apply default_make.
+ Qed.
+
+ Lemma t_interp_wf_lt : forall i, i < PArray.length t_atom ->
+ t_interp.[i] = interp_aux (PArray.get t_interp) (t_atom.[i]).
+ Proof.
+ set (P' i t := length t = length t_atom ->
+ forall j, j < i ->
+ t.[j] = interp_aux (PArray.get t) (t_atom.[j])).
+ assert (P' (length t_atom) t_interp).
+ unfold is_true, wf in wf_t_i;rewrite PArray.forallbi_spec in wf_t_i.
+ unfold t_interp;apply foldi_left_Ind;unfold P';intros.
+ rewrite length_set in H1.
+ destruct (Int63Properties.reflect_eqb j i).
+ rewrite e, PArray.get_set_same.
+ apply lt_interp_aux with (2:= wf_t_i i H).
+ intros;rewrite get_set_other;trivial.
+ intros Heq;elim (not_ltb_refl i);rewrite Heq at 1;trivial.
+ rewrite H1;trivial.
+ assert (j < i).
+ assert ([|j|] <> [|i|]) by(intros Heq1;elim n;apply to_Z_inj;trivial).
+ generalize H2;unfold is_true;rewrite !ltb_spec,
+ (to_Z_add_1 _ _ H);auto with zarith.
+ rewrite get_set_other, H0;auto.
+ apply lt_interp_aux with (2:= wf_t_i j (ltb_trans _ _ _ H3 H)).
+ intros;rewrite get_set_other;trivial.
+ intros Heq;elim (not_ltb_refl i);apply ltb_trans with j;
+ [ rewrite Heq| ];trivial.
+ elim (ltb_0 _ H0).
+ apply H;apply length_t_interp.
+ Qed.
+
+ Hypothesis default_t_atom : default t_atom = Acop CO_xH.
+
+ Lemma t_interp_wf : forall i,
+ t_interp.[i] = interp_aux (PArray.get t_interp) (t_atom.[i]).
+ Proof.
+ intros i;case_eq (i< PArray.length t_atom);intros.
+ apply t_interp_wf_lt;trivial.
+ rewrite !PArray.get_outofbound;trivial.
+ rewrite default_t_atom, default_t_interp;trivial.
+ rewrite length_t_interp;trivial.
+ Qed.
+
+ Definition get_type' (t_interp':array bval) i := v_type _ _ (t_interp'.[i]).
+
+ Local Notation get_type := (get_type' t_interp).
+
+ (* If an atom is well-typed, it has an interpretation *)
+
+ Lemma check_aux_interp_aux_lt_aux : forall a h,
+ (forall j : int,
+ j < h ->
+ exists v : interp_t (v_type Typ.type interp_t (a .[ j])),
+ a .[ j] = Bval (v_type Typ.type interp_t (a .[ j])) v) ->
+ forall l, List.forallb (fun h0 : int => h0 < h) l = true ->
+ forall (f0: tval),
+ exists
+ v : interp_t
+ (v_type Typ.type interp_t
+ (let (tf, f) := f0 in
+ apply_func (fst tf) (snd tf) f (List.map (get a) l))),
+ (let (tf, f) := f0 in
+ apply_func (fst tf) (snd tf) f (List.map (get a) l)) =
+ Bval
+ (v_type Typ.type interp_t
+ (let (tf, f) := f0 in
+ apply_func (fst tf) (snd tf) f (List.map (get a) l))) v.
+ Proof.
+ intros a h IH; induction l as [ |j l IHl]; simpl.
+ intros _ [[[ | ] tr] f]; simpl.
+ exists f; auto.
+ exists true; auto.
+ rewrite andb_true_iff; intros [H1 H2] [[[ |A targs] tr] f]; simpl.
+ exists true; auto.
+ destruct (IH j H1) as [x Hx]; rewrite Hx; simpl; case (Typ.cast (v_type Typ.type interp_t (a .[ j])) A); simpl.
+ intro k; destruct (IHl H2 (Tval (targs,tr) (f (k interp_t x)))) as [y Hy]; simpl in Hy; rewrite Hy; simpl; exists y; auto.
+ exists true; auto.
+ Qed.
+
+ Lemma check_aux_interp_aux_lt : forall h, h < length t_atom ->
+ forall a,
+ (forall j, j < h ->
+ exists v, a.[j] = Bval (v_type _ _ (a.[j])) v) ->
+ exists v, interp_aux (get a) (t_atom.[h]) =
+ Bval (v_type _ _ (interp_aux (get a) (t_atom.[h]))) v.
+ Proof.
+ unfold wf, is_true in wf_t_i; rewrite forallbi_spec in wf_t_i.
+ intros h Hh a IH; generalize (wf_t_i h Hh).
+ case (t_atom.[h]); simpl.
+ (* Constants *)
+ intros [ | ] _; simpl.
+ exists 1%positive; auto.
+ exists 0%Z; auto.
+ (* Unary operators *)
+ intros [ | | | | ] i H; simpl; destruct (IH i H) as [x Hx]; rewrite Hx; simpl.
+ case (Typ.cast (v_type Typ.type interp_t (a .[ i])) Typ.Tpositive); simpl; try (exists true; auto); intro k; exists ((k interp_t x)~0)%positive; auto.
+ case (Typ.cast (v_type Typ.type interp_t (a .[ i])) Typ.Tpositive); simpl; try (exists true; auto); intro k; exists ((k interp_t x)~1)%positive; auto.
+ case (Typ.cast (v_type Typ.type interp_t (a .[ i])) Typ.Tpositive); simpl; try (exists true; auto); intro k; exists (Zpos (k interp_t x)); auto.
+ case (Typ.cast (v_type Typ.type interp_t (a .[ i])) Typ.Tpositive); simpl; try (exists true; auto); intro k; exists (Zneg (k interp_t x)); auto.
+ case (Typ.cast (v_type Typ.type interp_t (a .[ i])) Typ.TZ); simpl; try (exists true; auto); intro k; exists (- k interp_t x)%Z; auto.
+ (* Binary operators *)
+ intros [ | | | | | | |A] h1 h2; simpl; rewrite andb_true_iff; intros [H1 H2]; destruct (IH h1 H1) as [x Hx]; destruct (IH h2 H2) as [y Hy]; rewrite Hx, Hy; simpl.
+ case (Typ.cast (v_type Typ.type interp_t (a .[ h1])) Typ.TZ); simpl; try (exists true; auto); intro k1; case (Typ.cast (v_type Typ.type interp_t (a .[ h2])) Typ.TZ); simpl; try (exists true; auto); intro k2; exists (k1 interp_t x + k2 interp_t y)%Z; auto.
+ case (Typ.cast (v_type Typ.type interp_t (a .[ h1])) Typ.TZ); simpl; try (exists true; auto); intro k1; case (Typ.cast (v_type Typ.type interp_t (a .[ h2])) Typ.TZ); simpl; try (exists true; auto); intro k2; exists (k1 interp_t x - k2 interp_t y)%Z; auto.
+ case (Typ.cast (v_type Typ.type interp_t (a .[ h1])) Typ.TZ); simpl; try (exists true; auto); intro k1; case (Typ.cast (v_type Typ.type interp_t (a .[ h2])) Typ.TZ); simpl; try (exists true; auto); intro k2; exists (k1 interp_t x * k2 interp_t y)%Z; auto.
+ case (Typ.cast (v_type Typ.type interp_t (a .[ h1])) Typ.TZ); simpl; try (exists true; auto); intro k1; case (Typ.cast (v_type Typ.type interp_t (a .[ h2])) Typ.TZ) as [k2| ]; simpl; try (exists true; reflexivity); exists (k1 interp_t x <? k2 interp_t y); auto.
+ case (Typ.cast (v_type Typ.type interp_t (a .[ h1])) Typ.TZ); simpl; try (exists true; auto); intro k1; case (Typ.cast (v_type Typ.type interp_t (a .[ h2])) Typ.TZ) as [k2| ]; simpl; try (exists true; reflexivity); exists (k1 interp_t x <=? k2 interp_t y); auto.
+ case (Typ.cast (v_type Typ.type interp_t (a .[ h1])) Typ.TZ); simpl; try (exists true; auto); intro k1; case (Typ.cast (v_type Typ.type interp_t (a .[ h2])) Typ.TZ) as [k2| ]; simpl; try (exists true; reflexivity); exists (k1 interp_t x >=? k2 interp_t y); auto.
+ case (Typ.cast (v_type Typ.type interp_t (a .[ h1])) Typ.TZ); simpl; try (exists true; auto); intro k1; case (Typ.cast (v_type Typ.type interp_t (a .[ h2])) Typ.TZ) as [k2| ]; simpl; try (exists true; reflexivity); exists (k1 interp_t x >? k2 interp_t y); auto.
+ case (Typ.cast (v_type Typ.type interp_t (a .[ h1])) A); simpl; try (exists true; auto); intro k1; case (Typ.cast (v_type Typ.type interp_t (a .[ h2])) A) as [k2| ]; simpl; try (exists true; reflexivity); exists (Typ.i_eqb t_i A (k1 interp_t x) (k2 interp_t y)); auto.
+ (* N-ary operators *)
+ intros [A] l; assert (forall acc, List.forallb (fun h0 : int => h0 < h) l = true -> exists v, match compute_interp (get a) A acc l with | Some l0 => Bval Typ.Tbool (distinct (Typ.i_eqb t_i A) (rev l0)) | None => bvtrue end = Bval (v_type Typ.type interp_t match compute_interp (get a) A acc l with | Some l0 => Bval Typ.Tbool (distinct (Typ.i_eqb t_i A) (rev l0)) | None => bvtrue end) v); auto; induction l as [ |i l IHl]; simpl.
+ intros acc _; exists (distinct (Typ.i_eqb t_i A) (rev acc)); auto.
+ intro acc; rewrite andb_true_iff; intros [H1 H2]; destruct (IH _ H1) as [va Hva]; rewrite Hva; simpl; case (Typ.cast (v_type Typ.type interp_t (a .[ i])) A); simpl; try (exists true; auto); intro k; destruct (IHl (k interp_t va :: acc) H2) as [vb Hvb]; exists vb; auto.
+ (* Application *)
+ intros i l H; apply (check_aux_interp_aux_lt_aux a h IH l H (t_func.[i])).
+ Qed.
+
+ Lemma check_aux_interp_hatom_lt : forall h, h < length t_atom ->
+ exists v, t_interp.[h] = Bval (get_type h) v.
+ Proof.
+ set (P' i t := length t = length t_atom ->
+ forall j, j < i ->
+ exists v, t.[j] = Bval (v_type Typ.type interp_t (t.[j])) v).
+ assert (P' (length t_atom) t_interp).
+ unfold t_interp;apply foldi_left_Ind;unfold P';intros.
+ rewrite length_set in H1.
+ destruct (Int63Properties.reflect_eqb j i).
+ rewrite e, PArray.get_set_same.
+ apply check_aux_interp_aux_lt; auto.
+ rewrite H1; auto.
+ assert (j < i).
+ assert ([|j|] <> [|i|]) by(intros Heq1;elim n;apply to_Z_inj;trivial).
+ generalize H2;unfold is_true;rewrite !ltb_spec,
+ (to_Z_add_1 _ _ H);auto with zarith.
+ rewrite get_set_other;auto.
+ elim (ltb_0 _ H0).
+ apply H;apply length_t_interp.
+ Qed.
+
+ Lemma check_aux_interp_hatom : forall h,
+ exists v, t_interp.[h] = Bval (get_type h) v.
+ Proof.
+ intros i;case_eq (i< PArray.length t_atom);intros.
+ apply check_aux_interp_hatom_lt;trivial.
+ unfold get_type'; rewrite !PArray.get_outofbound;trivial.
+ rewrite default_t_interp; simpl; exists (1%positive); auto.
+ rewrite length_t_interp;trivial.
+ Qed.
+
+ Lemma check_aux_interp_aux : forall a t,
+ check_aux get_type a t ->
+ exists v, interp_aux (get t_interp) a = (Bval t v).
+ Proof.
+ intros a t; apply check_aux_interp_aux_aux; apply check_aux_interp_hatom.
+ Qed.
+
+ (* If an atom is not well-typed, its interpretation if bvtrue *)
+
+ Lemma check_aux_interp_aux_contr : forall a,
+ (forall T, check_aux get_type a T = false) ->
+ interp_aux (get t_interp) a = bvtrue.
+ Proof.
+ intros; eapply check_aux_interp_aux_contr_aux; eauto; apply check_aux_interp_hatom.
+ Qed.
+
+ End Interp_get.
+
+
+ Definition get_type t_atom :=
+ get_type' (t_interp t_atom).
+
+ Definition wt t_atom :=
+ let t_interp := t_interp t_atom in
+ let get_type := get_type' t_interp in
+ PArray.forallbi (fun i h => check_aux get_type h (get_type i)) t_atom.
+
+
+ Definition interp_hatom (t_atom : PArray.array atom) :=
+ let t_a := t_interp t_atom in
+ PArray.get t_a.
+
+ Definition interp t_atom := interp_aux (interp_hatom t_atom).
+
+ Definition interp_form_hatom t_atom : hatom -> bool :=
+ let interp := interp_hatom t_atom in
+ fun a => interp_bool (interp a).
+
+ End Typing_Interp.
+
+ Definition check_atom t_atom :=
+ match default t_atom with
+ | Acop CO_xH => wf t_atom
+ | _ => false
+ end.
+
+ Lemma check_atom_correct : forall t_atom, check_atom t_atom ->
+ wf t_atom /\ default t_atom = Acop CO_xH.
+ Proof.
+ intro t_atom; unfold check_atom; case (default t_atom); try discriminate; intro c; case c; auto; discriminate.
+ Qed.
+
+End Atom.
diff --git a/src/State.v b/src/State.v
new file mode 100644
index 0000000..d793410
--- /dev/null
+++ b/src/State.v
@@ -0,0 +1,572 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+Require Import List.
+Require Import Bool.
+Require Import Int63.
+Require Import PArray.
+
+(* Require Import AxiomesInt. *)
+
+Local Open Scope int63_scope.
+Local Open Scope array_scope.
+
+Coercion is_true (x: bool) := x = true.
+
+Set Vm Optimize.
+
+Notation var := int (only parsing).
+
+(* Variables interpretation *)
+Module Valuation.
+(* TODO : Should be var -> Prop *)
+ Definition t := var -> bool.
+ Definition wf (rho : t) : Prop := rho 0 /\ ~ rho 1.
+
+End Valuation.
+
+
+Module Var.
+
+ Definition _true : var := 0. (* true *)
+ Register _true as PrimInline.
+
+ Definition _false : var := 1. (* false *)
+
+ Definition interp (rho:Valuation.t) (x:var) : bool := rho x.
+
+ Lemma interp_true : forall rho, Valuation.wf rho -> interp rho _true.
+ Proof. intros rho [H _];exact H. Qed.
+
+ Lemma interp_false : forall rho, Valuation.wf rho -> ~ interp rho _false.
+ Proof. intros rho [_ H];exact H. Qed.
+
+End Var.
+
+Notation _lit := int (only parsing).
+
+Module Lit.
+
+ Definition is_pos (l:_lit) := is_even l.
+ Register is_pos as PrimInline.
+
+ Definition blit (l:_lit) : var := l >> 1.
+ Register blit as PrimInline.
+
+ Definition lit (x:var) : _lit := x << 1.
+ Register lit as PrimInline.
+
+ Definition neg (l:_lit) : _lit := l lxor 1.
+ Register neg as PrimInline.
+
+ Definition nlit (x:var) : _lit := neg (lit x).
+ Register nlit as PrimInline.
+
+ Definition _true : _lit := Eval compute in lit Var._true.
+ Register _true as PrimInline.
+
+ Lemma lit_true : _true = lit Var._true.
+ Proof. reflexivity. Qed.
+
+ Definition _false : _lit := Eval compute in lit Var._false.
+ Register _false as PrimInline.
+
+ Lemma lit_false : _false = lit Var._false.
+ Proof. reflexivity. Qed.
+
+ Definition eqb (l l' : _lit) := l == l'.
+ Register eqb as PrimInline.
+
+ Lemma eqb_spec : forall l l', eqb l l' = true <-> l = l'.
+ Proof eqb_spec.
+
+ Lemma neg_involutive : forall l, neg (neg l) = l.
+ Proof.
+ unfold neg;intros; rewrite <- lxor_assoc;change (1 lxor 1) with 0;rewrite lxor_0_r;trivial.
+ Qed.
+
+ Lemma blit_neg : forall l, blit (neg l) = blit l.
+ Proof.
+ unfold blit, neg;intros l.
+ rewrite lxor_lsr, lxor_0_r;trivial.
+ Qed.
+
+ Lemma lit_blit: forall l,
+ is_pos l = true -> lit (blit l) = l.
+ Proof.
+ unfold is_pos, lit, blit;intros.
+ rewrite (bit_xor_split l) at 2.
+ rewrite is_even_bit, negb_true_iff in H;rewrite H.
+ symmetry;apply lxor_0_r.
+ Qed.
+
+ Lemma lit_blit_neg: forall l,
+ is_pos l = false -> lit (blit l) = neg l.
+ Proof.
+ unfold is_pos, lit, blit;intros.
+ rewrite (bit_xor_split l) at 2.
+ rewrite is_even_bit, negb_false_iff in H;rewrite H.
+ rewrite <- (neg_involutive ((l >> 1) << 1)) at 1;trivial.
+ Qed.
+
+ Lemma nlit_blit: forall l,
+ is_pos l = false -> nlit (blit l) = l.
+ Proof.
+ unfold nlit;intros;rewrite lit_blit_neg;auto using neg_involutive.
+ Qed.
+
+ Lemma nlit_blit_neg: forall l,
+ is_pos l = true -> nlit (blit l) = neg l.
+ Proof.
+ unfold nlit;intros;rewrite lit_blit;auto using neg_involutive.
+ Qed.
+
+ Lemma is_pos_lit : forall l,
+ is_pos (lit l) = true.
+ Proof.
+ unfold is_pos, lit;apply is_even_lsl_1.
+ Qed.
+
+ Lemma is_pos_neg : forall l,
+ is_pos (neg l) = negb (is_pos l).
+ Proof.
+ unfold neg, is_pos;intros l.
+ rewrite is_even_xor, xorb_false_r;trivial.
+ Qed.
+
+ Lemma is_pos_nlit : forall l,
+ is_pos (nlit l) = false.
+ Proof.
+ unfold nlit;intros l;rewrite is_pos_neg, is_pos_lit;trivial.
+ Qed.
+
+ Lemma is_pos_true : is_pos _true.
+ Proof. reflexivity. Qed.
+
+ Lemma is_pos_false : is_pos _false.
+ Proof. reflexivity. Qed.
+
+ Lemma blit_pos :forall a b,
+ Lit.blit a = Lit.blit b -> Lit.is_pos a = Lit.is_pos b ->
+ a = b.
+ Proof lsr_is_even_eq.
+
+ Lemma blit_lit : forall l, blit (lit (blit l)) = blit l.
+ Proof.
+ intros l;case_eq (is_pos l);intros.
+ rewrite lit_blit;trivial.
+ rewrite lit_blit_neg, blit_neg;trivial.
+ Qed.
+
+ Lemma blit_nlit : forall l, blit (nlit (blit l)) = blit l.
+ Proof.
+ intros l;case_eq (is_pos l);intros.
+ rewrite nlit_blit_neg, blit_neg;trivial.
+ rewrite nlit_blit;trivial.
+ Qed.
+
+ Lemma blit_true : blit _true = Var._true.
+ Proof. reflexivity. Qed.
+
+ Lemma blit_false : blit _false = Var._false.
+ Proof. reflexivity. Qed.
+
+ (* Interpretation of a literal *)
+ Definition interp rho (l:_lit) :=
+ if is_pos l then Var.interp rho (blit l)
+ else negb (Var.interp rho (blit l)).
+
+ Lemma interp_true : forall rho, Valuation.wf rho -> interp rho _true.
+ Proof.
+ intros rho Hwf;unfold interp;rewrite is_pos_true, blit_true.
+ apply Var.interp_true;trivial.
+ Qed.
+
+ Lemma interp_false : forall rho, Valuation.wf rho -> ~interp rho _false.
+ Proof.
+ intros rho Hwf;unfold interp;rewrite is_pos_false, blit_false.
+ apply Var.interp_false;trivial.
+ Qed.
+
+ Lemma interp_neg : forall rho l, interp rho (neg l) = negb (interp rho l).
+ Proof.
+ intros rho l;unfold interp;rewrite is_pos_neg, blit_neg.
+ destruct (is_pos l);simpl;auto using negb_involutive.
+ Qed.
+
+ Lemma interp_lit : forall rho l, interp rho (lit (blit l)) = Var.interp rho (blit l).
+ Proof.
+ intros;unfold interp;rewrite is_pos_lit, blit_lit;trivial.
+ Qed.
+
+ Lemma interp_nlit : forall rho l, interp rho (nlit (blit l)) = negb (Var.interp rho (blit l)).
+ Proof.
+ unfold nlit;intros rho l;rewrite interp_neg, interp_lit;trivial.
+ Qed.
+
+ Lemma interp_eq_compat : forall rho1 rho2 l,
+ rho1 (blit l) = rho2 (blit l) ->
+ interp rho1 l = interp rho2 l.
+ Proof.
+ unfold interp, Var.interp;intros rho1 rho2 l Heq;rewrite Heq;trivial.
+ Qed.
+
+ Lemma lxor_neg : forall l1 l2, (l1 lxor l2 == 1) = true -> l1 = Lit.neg l2.
+ Proof.
+ unfold Lit.neg; intros l1 l2;rewrite eqb_spec;intros Heq;rewrite <- Heq.
+ rewrite lxor_comm, <- lxor_assoc, lxor_nilpotent, lxor_0_r;trivial.
+ Qed.
+
+End Lit.
+
+
+Lemma compare_spec' : forall x y,
+ match x ?= y with
+ | Lt => x < y
+ | Eq => x = y
+ | Gt => y < x
+ end.
+Proof.
+ intros x y;rewrite compare_def_spec;unfold compare_def.
+ case_eq (x < y);intros;[reflexivity | ].
+ case_eq (x == y);intros.
+ rewrite <- eqb_spec;trivial.
+ rewrite <- not_true_iff_false in H, H0.
+ unfold is_true in *;rewrite ltb_spec in H |- *;rewrite eqb_spec in H0.
+ assert ([|x|] <> [|y|]) by (intros Heq;apply H0, to_Z_inj;trivial);omega.
+Qed.
+
+
+Module C.
+
+ Definition t := list _lit.
+
+ Definition interp (rho:Valuation.t) (l:t) :=
+ List.existsb (Lit.interp rho) l.
+
+ Definition valid rho c :=
+ interp rho c = true.
+
+ Definition _true : t := Lit._true :: nil.
+
+ Definition is_false (c:t) :=
+ match c with
+ | nil => true
+ | _ => false
+ end.
+
+ Section OR.
+
+ Variable or : t -> t -> t.
+ Variable l1 : _lit.
+ Variable c1 : t.
+
+ Fixpoint or_aux (c2:t) :=
+ match c2 with
+ | nil => l1 :: c1
+ | l2::c2' =>
+ match l1 ?= l2 with
+ | Eq => l1 :: or c1 c2'
+ | Lt => l1 :: or c1 c2
+ | Gt => l2 :: or_aux c2'
+ end
+ end.
+
+ Variable rho : Valuation.t.
+ Hypothesis or_correct : forall c2,
+ interp rho (or c1 c2) = interp rho c1 || interp rho c2.
+
+ Lemma or_aux_correct : forall c2,
+ interp rho (or_aux c2) = interp rho (l1::c1) || interp rho c2.
+ Proof.
+ induction c2;simpl.
+ rewrite orb_false_r;trivial.
+ generalize (compare_spec' l1 a);destruct (l1 ?= a);intros H;simpl.
+ rewrite H;destruct (Lit.interp rho a);trivial.
+ rewrite !orb_false_l, or_correct;trivial.
+ rewrite or_correct;simpl;rewrite orb_assoc;trivial.
+ rewrite IHc2;simpl.
+ destruct (Lit.interp rho a);simpl;trivial.
+ rewrite orb_true_r;trivial.
+ Qed.
+
+ End OR.
+
+ Fixpoint or (c1 c2:t) {struct c1} : t :=
+ match c1, c2 with
+ | nil, _ => c2
+ | _, nil => c1
+ | l1::c1, l2::c2' =>
+ match compare l1 l2 with
+ | Eq => l1 :: or c1 c2'
+ | Lt => l1 :: or c1 c2
+ | Gt => l2 :: or_aux or l1 c1 c2'
+ end
+ end.
+
+ Lemma or_correct : forall rho c1 c2,
+ interp rho (or c1 c2) = interp rho c1 || interp rho c2.
+ Proof.
+ induction c1;simpl;trivial.
+ destruct c2;simpl.
+ rewrite orb_false_r;trivial.
+ generalize (compare_spec' a i);destruct (a ?= i);intros H;simpl.
+ rewrite H, IHc1;simpl;destruct (Lit.interp rho i);simpl;trivial.
+ rewrite IHc1, orb_assoc;trivial.
+ rewrite or_aux_correct;simpl;trivial.
+ destruct (Lit.interp rho i);trivial.
+ simpl;rewrite !orb_true_r;trivial.
+ Qed.
+
+ Section RESOLVE.
+
+ Variable resolve : t -> t -> t.
+ Variable l1 : _lit.
+ Variable c1 : t.
+
+ Fixpoint resolve_aux (c2:t) : t :=
+ match c2 with
+ | nil => _true
+ | l2::c2' =>
+ match compare l1 l2 with
+ | Eq => l1 :: resolve c1 c2'
+ | Lt => if l1 lxor l2 == 1 then or c1 c2' else l1 :: resolve c1 c2
+ | Gt =>
+ if l1 lxor l2 == 1 then or c1 c2' else l2 :: resolve_aux c2'
+ end
+ end.
+
+ Lemma resolve_aux_correct : forall rho,
+ (forall c2, interp rho c1 -> interp rho c2 -> interp rho (resolve c1 c2)) ->
+ interp rho (l1 :: c1) ->
+ forall c2, interp rho c2 ->
+ interp rho (resolve_aux c2).
+ Proof.
+ intros rho resolve_correct Hc1;simpl in Hc1.
+ induction c2;simpl;try discriminate.
+ generalize (compare_spec' l1 a);destruct (l1 ?= a);intros;subst;simpl.
+ simpl in Hc1;destruct (Lit.interp rho a);simpl in *;auto.
+ generalize (Lit.lxor_neg l1 a);destruct (l1 lxor a == 1);intros.
+ rewrite or_correct.
+ rewrite H1, Lit.interp_neg in Hc1;trivial;destruct (Lit.interp rho a).
+ simpl in Hc1;rewrite Hc1;trivial.
+ simpl in H0;rewrite H0, orb_true_r;trivial.
+ simpl;destruct (Lit.interp rho l1);simpl;auto.
+ generalize (Lit.lxor_neg l1 a);destruct (l1 lxor a == 1);intros.
+ rewrite or_correct.
+ rewrite H1, Lit.interp_neg in Hc1;trivial;destruct (Lit.interp rho a).
+ simpl in Hc1;rewrite Hc1;trivial.
+ simpl in H0;rewrite H0, orb_true_r;trivial.
+ simpl;destruct (Lit.interp rho a);simpl;auto.
+ Qed.
+
+ End RESOLVE.
+
+ Fixpoint resolve (c1 c2:t) {struct c1} : t :=
+ match c1, c2 with
+ | nil, _ => _true
+ | _, nil => _true
+ | l1::c1, l2::c2' =>
+ match compare l1 l2 with
+ | Eq => l1 :: resolve c1 c2'
+ | Lt => if l1 lxor l2 == 1 then or c1 c2' else l1 :: resolve c1 c2
+ | Gt =>
+ if l1 lxor l2 == 1 then or c1 c2' else l2 :: resolve_aux resolve l1 c1 c2'
+ end
+ end.
+
+ Lemma resolve_correct : forall rho c1 c2,
+ interp rho c1 -> interp rho c2 ->
+ interp rho (resolve c1 c2).
+ Proof.
+ induction c1;simpl;try discriminate.
+ destruct c2;simpl;try discriminate.
+ intros Hc1 Hc2.
+ generalize (compare_spec' a i);destruct (a ?= i);intros;subst;simpl.
+ destruct (Lit.interp rho i);simpl in *;auto.
+ generalize (Lit.lxor_neg a i);destruct (a lxor i == 1);intros.
+ rewrite or_correct.
+ rewrite H0, Lit.interp_neg in Hc1;trivial;destruct (Lit.interp rho i).
+ simpl in Hc1;rewrite Hc1;trivial.
+ simpl in Hc2;rewrite Hc2, orb_true_r;trivial.
+ simpl;destruct (Lit.interp rho a);simpl;auto.
+ generalize (Lit.lxor_neg a i);destruct (a lxor i == 1);intros.
+ rewrite or_correct.
+ rewrite H0, Lit.interp_neg in Hc1;trivial;destruct (Lit.interp rho i).
+ simpl in Hc1;rewrite Hc1;trivial.
+ simpl in Hc2;rewrite Hc2, orb_true_r;trivial.
+ simpl;destruct (Lit.interp rho i);simpl;auto using resolve_aux_correct.
+ Qed.
+
+ Lemma interp_true : forall rho, Valuation.wf rho -> interp rho _true = true.
+ Proof.
+ unfold _true, interp;intros rho Hwf;simpl.
+ rewrite Lit.interp_true;trivial.
+ Qed.
+
+ Lemma is_false_correct :
+ forall c, is_false c = true ->
+ forall rho, ~valid rho c.
+ Proof.
+ unfold valid, interp;destruct c;simpl; auto;discriminate.
+ Qed.
+
+End C.
+
+
+Notation clause_id := int (only parsing).
+
+Notation resolution := (array clause_id) (only parsing).
+
+Module S.
+
+ Definition t := array C.t.
+
+ Definition get (s:t) (cid:clause_id) := s.[cid].
+ Register get as PrimInline.
+
+ (* Do not use this function outside this module *)
+ (* expect if you are sure that [c = sort_uniq c] *)
+ Definition internal_set (s:t) (cid:clause_id) (c:C.t) : t := s.[cid <- c].
+ Register internal_set as PrimInline.
+
+ Definition make (nclauses : int) : t :=
+ PArray.make nclauses C._true.
+
+ Definition valid rho s :=
+ forall id, C.valid rho (get s id).
+
+
+ (* Specification of make *)
+
+ Lemma valid_make : forall rho nclauses,
+ Valuation.wf rho ->
+ valid rho (make nclauses).
+ Proof.
+ unfold valid, make, get;intros.
+ rewrite PArray.get_make; apply C.interp_true;trivial.
+ Qed.
+
+
+ (* Specification of get *)
+
+ Lemma valid_get : forall rho s, valid rho s ->
+ forall id, C.valid rho (get s id).
+ Proof. auto. Qed.
+
+
+ (* Specification of internal_set *)
+
+ Lemma valid_internal_set :
+ forall rho s, valid rho s ->
+ forall c, C.valid rho c ->
+ forall id, valid rho (set s id c).
+ Proof.
+ unfold valid, get, set;simpl;intros.
+ destruct (Int63Properties.reflect_eqb id id0);subst.
+ case_eq (id0 < length s);intros.
+ rewrite PArray.get_set_same;trivial.
+ rewrite PArray.get_outofbound.
+ rewrite PArray.default_set.
+ rewrite <- (PArray.get_outofbound _ _ (length s)); trivial.
+ rewrite <- not_true_iff_false, ltb_spec;auto with zarith.
+ rewrite PArray.length_set;trivial.
+ rewrite get_set_other;trivial.
+ Qed.
+
+ (* Building clause *)
+ (* Same as set but without precondition *)
+
+ (* TODO: It can be a good idea to change the insertion sort algorithm *)
+
+ Fixpoint insert l1 c :=
+ match c with
+ | nil => l1:: nil
+ | l2 :: c' =>
+ match l1 ?= l2 with
+ | Lt => if l1 lxor l2 == 1 then C._true else l1 :: c
+ | Eq => c
+ | Gt => if l1 lxor l2 == 1 then C._true else l2 :: insert l1 c'
+ end
+ end.
+
+ Fixpoint sort_uniq c :=
+ match c with
+ | nil => nil
+ | l1 :: c => insert l1 (sort_uniq c)
+ end.
+
+ Lemma insert_correct : forall rho (Hwf:Valuation.wf rho) l1 c,
+ C.interp rho (insert l1 c) = C.interp rho (l1 :: c).
+ Proof.
+ intros rho Hwf l1;induction c;simpl;trivial.
+ generalize (compare_spec' l1 a);destruct (l1 ?= a);intros;subst;simpl.
+ destruct (Lit.interp rho a);simpl in *;auto.
+ generalize (Lit.lxor_neg l1 a);destruct (l1 lxor a == 1);intros;trivial.
+ rewrite C.interp_true;trivial.
+ rewrite H0, Lit.interp_neg;trivial;destruct (Lit.interp rho a);trivial.
+ generalize (Lit.lxor_neg l1 a);destruct (l1 lxor a == 1);intros.
+ rewrite C.interp_true;trivial.
+ rewrite H0, Lit.interp_neg;trivial;destruct (Lit.interp rho a);trivial.
+ simpl;rewrite orb_assoc,(orb_comm (Lit.interp rho l1)),<-orb_assoc,IHc;trivial.
+ Qed.
+
+ Lemma sort_uniq_correct : forall rho (Hwf:Valuation.wf rho) c,
+ C.interp rho (sort_uniq c) = C.interp rho c.
+ Proof.
+ intros rho Hwf;induction c;simpl;trivial.
+ rewrite insert_correct;trivial;simpl;rewrite IHc;trivial.
+ Qed.
+
+ Definition set_clause (s:t) pos (c:C.t) : t :=
+ set s pos (sort_uniq c).
+
+ Lemma valid_set_clause :
+ forall rho s, Valuation.wf rho -> valid rho s -> forall pos c,
+ C.valid rho c -> valid rho (set_clause s pos c).
+ Proof.
+ unfold valid, get, set_clause. intros rho s Hrho Hs pos c Hc id.
+ destruct (Int63Properties.reflect_eqb pos id);subst.
+ case_eq (id < length s); intro H.
+ unfold get;rewrite PArray.get_set_same; trivial.
+ unfold C.valid;rewrite sort_uniq_correct;trivial.
+ generalize (Hs id);rewrite !PArray.get_outofbound, PArray.default_set;trivial.
+ rewrite length_set;trivial.
+ rewrite get_set_other;trivial.
+ Qed.
+
+
+ (* Resolution *)
+
+ Definition set_resolve (s:t) pos (r:resolution) : t :=
+ let len := PArray.length r in
+ if len == 0 then s
+ else
+ let c := foldi (fun i c => C.resolve (get s (r.[i])) c) 1 (len - 1)
+ (get s (r.[0])) in
+ internal_set s pos c.
+
+ Lemma valid_set_resolve :
+ forall rho s, Valuation.wf rho -> valid rho s ->
+ forall pos r, valid rho (set_resolve s pos r).
+ Proof.
+ unfold set_resolve; intros rho s Hrho Hv pos r.
+ destruct (Int63Properties.reflect_eqb (length r) 0);[trivial | ].
+ apply valid_internal_set;trivial.
+ apply foldi_ind;auto.
+ intros i c _ _ Hc;apply C.resolve_correct;auto;apply Hv.
+ Qed.
+
+End S.
diff --git a/src/Trace.v b/src/Trace.v
new file mode 100644
index 0000000..d369958
--- /dev/null
+++ b/src/Trace.v
@@ -0,0 +1,567 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+Add LoadPath "." as SMTCoq.
+Add LoadPath "cnf" as SMTCoq.cnf.
+Add LoadPath "euf" as SMTCoq.euf.
+Add LoadPath "lia" as SMTCoq.lia.
+Add LoadPath "spl" as SMTCoq.spl.
+
+Require Import Bool Int63 PArray.
+Require Import Misc State SMT_terms Cnf Euf Lia Syntactic Arithmetic Operators.
+
+Local Open Scope array_scope.
+Local Open Scope int63_scope.
+
+Set Implicit Arguments.
+Unset Strict Implicit.
+Set Vm Optimize.
+Section trace.
+
+ (* We are given a certificate, a checker for it (that modifies a
+ state), and a proof that the checker is correct: the state it
+ returns must be valid and well-formed. *)
+
+ Variable step : Type.
+
+ Variable check_step : S.t -> step -> S.t.
+
+ Variable rho : Valuation.t.
+
+ (* We use [array array step] to allow bigger trace *)
+ Definition _trace_ := array (array step).
+
+ (* A checker for such a trace *)
+
+ Variable is_false : C.t -> bool.
+ Hypothesis is_false_correct : forall c, is_false c -> ~ C.interp rho c.
+
+ Definition _checker_ (s: S.t) (t: _trace_) (confl:clause_id) : bool :=
+ let s' := PArray.fold_left (fun s a => PArray.fold_left check_step s a) s t in
+ is_false (S.get s' confl).
+ Register _checker_ as PrimInline.
+
+ (* For debugging *)
+ (*
+
+ Variable check_step_debug : S.t -> step -> option S.t.
+
+ Definition _checker_debug_ (s: S.t) (t: _trace_) : sum S.t ((int*int)*S.t) :=
+ let s' := PArray.foldi_left (fun i s a => PArray.foldi_left (fun j s' a' =>
+ match s' with
+ | inl s'' =>
+ match check_step_debug s'' a' with
+ | Some s''' => inl s'''
+ | None => inr ((i,j),s'')
+ end
+ | u => u
+ end) s a) (inl s) t in
+ s'.
+
+ Definition _checker_partial_ (s: S.t) (t: _trace_) (max:int) : S.t :=
+ PArray.fold_left (fun s a => PArray.foldi_left (fun i s' a' => if i < max then check_step s' a' else s') s a) s t.
+ *)
+
+ (* Proof of its partial correction: if it returns true, then the
+ initial state is not valid *)
+
+ Hypothesis valid_check_step :
+ forall s, S.valid rho s -> forall c, S.valid rho (check_step s c).
+
+ Lemma _checker__correct :
+ forall s, forall t confl, _checker_ s t confl-> ~ (S.valid rho s).
+ Proof.
+ unfold _checker_.
+ intros s t' cid Hf Hv.
+ apply (is_false_correct Hf).
+ apply S.valid_get.
+ apply PArray.fold_left_ind; auto.
+ intros a i _ Ha;apply PArray.fold_left_ind;trivial.
+ intros a0 i0 _ H1;auto.
+ Qed.
+
+End trace.
+
+
+(* Application to resolution *)
+
+Module Sat_Checker.
+
+ Inductive step :=
+ | Res (_:int) (_:resolution).
+
+ Definition resolution_checker s t :=
+ _checker_ (fun s (st:step) => let (pos, r) := st in S.set_resolve s pos r) s t.
+
+ Lemma resolution_checker_correct :
+ forall rho, Valuation.wf rho ->
+ forall s t cid, resolution_checker C.is_false s t cid->
+ ~S.valid rho s.
+ Proof.
+ intros rho Hwr;apply _checker__correct.
+ intros; apply C.is_false_correct; trivial.
+ intros s Hv (pos, r);apply S.valid_set_resolve;trivial.
+ Qed.
+
+ (** Application to Zchaff *)
+ Definition dimacs := PArray.array (PArray.array _lit).
+
+ Definition C_interp_or rho c :=
+ afold_left _ _ false orb (Lit.interp rho) c.
+
+ Lemma C_interp_or_spec : forall rho c,
+ C_interp_or rho c = C.interp rho (to_list c).
+ Proof.
+ intros rho c; unfold C_interp_or; case_eq (C.interp rho (to_list c)).
+ unfold C.interp; rewrite List.existsb_exists; intros [x [H1 H2]]; destruct (In_to_list _ _ H1) as [i [H3 H4]]; subst x; apply (afold_left_orb_true _ i); auto.
+ unfold C.interp; intro H; apply afold_left_orb_false; intros i H1; case_eq (Lit.interp rho (c .[ i])); auto; intro Heq; assert (H2: exists x, List.In x (to_list c) /\ Lit.interp rho x = true).
+ exists (c.[i]); split; auto; apply to_list_In; auto.
+ rewrite <- List.existsb_exists in H2; rewrite H2 in H; auto.
+Qed.
+
+ Definition valid rho (d:dimacs) :=
+ afold_left _ _ true andb (C_interp_or rho) d.
+
+ Lemma valid_spec : forall rho d,
+ valid rho d <->
+ (forall i : int, i < length d -> C.interp rho (PArray.to_list (d.[i]))).
+ Proof.
+ unfold valid; intros rho d; split; intro H.
+ intros i Hi; case_eq (C.interp rho (to_list (d .[ i]))); try reflexivity.
+ intro Heq; erewrite afold_left_andb_false in H; try eassumption.
+ rewrite C_interp_or_spec; auto.
+ apply afold_left_andb_true; try assumption; intros i Hi; rewrite C_interp_or_spec; apply H; auto.
+ Qed.
+
+ Inductive certif :=
+ | Certif : int -> _trace_ step -> clause_id -> certif.
+
+ Definition add_roots s (d:dimacs) :=
+ PArray.foldi_right (fun i c s => S.set_clause s i (PArray.to_list c)) d s.
+
+ Definition checker (d:dimacs) (c:certif) :=
+ let (nclauses, t, confl_id) := c in
+ resolution_checker C.is_false (add_roots (S.make nclauses) d) t confl_id.
+
+ Lemma valid_add_roots : forall rho, Valuation.wf rho ->
+ forall d s, valid rho d -> S.valid rho s ->
+ S.valid rho (add_roots s d).
+ Proof.
+ intros rho Hwr d s Hd Hs; unfold add_roots; apply (PArray.foldi_right_Ind _ _ (fun _ a => S.valid rho a)); auto; intros a i Hlt Hv; apply S.valid_set_clause; auto; rewrite valid_spec in Hd; apply Hd; auto.
+ Qed.
+
+ Lemma checker_correct : forall d c,
+ checker d c = true ->
+ forall rho, Valuation.wf rho -> ~valid rho d.
+ Proof.
+ unfold checker; intros d (nclauses, t, confl_id) Hc rho Hwf Hv.
+ apply (resolution_checker_correct Hwf Hc).
+ apply valid_add_roots; auto.
+ apply S.valid_make; auto.
+ Qed.
+
+ Definition interp_var rho x :=
+ match compare x 1 with
+ | Lt => true
+ | Eq => false
+ | Gt => rho (x - 1)
+ (* This allows to have variable starting at 1 in the interpretation as in dimacs files *)
+ end.
+
+ Lemma theorem_checker :
+ forall d c,
+ checker d c = true ->
+ forall rho, ~valid (interp_var rho) d.
+ Proof.
+ intros d c H rho;apply checker_correct with c;trivial.
+ split;compute;trivial;discriminate.
+ Qed.
+
+End Sat_Checker.
+
+Module Cnf_Checker.
+
+ Inductive step :=
+ | Res (pos:int) (res:resolution)
+ | ImmFlatten (pos:int) (cid:clause_id) (lf:_lit)
+ | CTrue (pos:int)
+ | CFalse (pos:int)
+ | BuildDef (pos:int) (l:_lit)
+ | BuildDef2 (pos:int) (l:_lit)
+ | BuildProj (pos:int) (l:_lit) (i:int)
+ | ImmBuildDef (pos:int) (cid:clause_id)
+ | ImmBuildDef2 (pos:int) (cid:clause_id)
+ | ImmBuildProj (pos:int) (cid:clause_id) (i:int).
+
+ Local Open Scope list_scope.
+
+ Local Notation check_flatten t_form := (check_flatten t_form (fun i1 i2 => i1 == i2) (fun _ _ => false)) (only parsing).
+
+ Definition step_checker t_form s (st:step) :=
+ match st with
+ | Res pos res => S.set_resolve s pos res
+ | ImmFlatten pos cid lf => S.set_clause s pos (check_flatten t_form s cid lf)
+ | CTrue pos => S.set_clause s pos Cnf.check_True
+ | CFalse pos => S.set_clause s pos Cnf.check_False
+ | BuildDef pos l => S.set_clause s pos (check_BuildDef t_form l)
+ | BuildDef2 pos l => S.set_clause s pos (check_BuildDef2 t_form l)
+ | BuildProj pos l i => S.set_clause s pos (check_BuildProj t_form l i)
+ | ImmBuildDef pos cid => S.set_clause s pos (check_ImmBuildDef t_form s cid)
+ | ImmBuildDef2 pos cid => S.set_clause s pos (check_ImmBuildDef2 t_form s cid)
+ | ImmBuildProj pos cid i => S.set_clause s pos (check_ImmBuildProj t_form s cid i)
+ end.
+
+ Lemma step_checker_correct : forall rho t_form,
+ Form.check_form t_form ->
+ forall s, S.valid (Form.interp_state_var rho t_form) s ->
+ forall st : step, S.valid (Form.interp_state_var rho t_form)
+ (step_checker t_form s st).
+ Proof.
+ intros rho t_form Ht s H; destruct (Form.check_form_correct rho _ Ht) as [[Ht1 Ht2] Ht3]; intros [pos res|pos cid lf|pos|pos|pos l|pos l|pos l i|pos cid|pos cid|pos cid i]; simpl; try apply S.valid_set_clause; auto.
+ apply S.valid_set_resolve; auto.
+ apply valid_check_flatten; auto; try discriminate; intros a1 a2; unfold is_true; rewrite Int63Properties.eqb_spec; intro; subst a1; auto.
+ apply valid_check_True; auto.
+ apply valid_check_False; auto.
+ apply valid_check_BuildDef; auto.
+ apply valid_check_BuildDef2; auto.
+ apply valid_check_BuildProj; auto.
+ apply valid_check_ImmBuildDef; auto.
+ apply valid_check_ImmBuildDef2; auto.
+ apply valid_check_ImmBuildProj; auto.
+ Qed.
+
+ Definition cnf_checker t_form s t :=
+ _checker_ (step_checker t_form) s t.
+
+ Lemma cnf_checker_correct : forall rho t_form,
+ Form.check_form t_form -> forall s t confl,
+ cnf_checker t_form C.is_false s t confl ->
+ ~ (S.valid (Form.interp_state_var rho t_form) s).
+ Proof.
+ unfold cnf_checker; intros rho t_form Ht; apply _checker__correct.
+ intros c H; apply C.is_false_correct; auto.
+ apply step_checker_correct; auto.
+ Qed.
+
+
+ Inductive certif :=
+ | Certif : int -> _trace_ step -> int -> certif.
+
+ Definition checker t_form l (c:certif) :=
+ let (nclauses, t, confl) := c in
+ Form.check_form t_form &&
+ cnf_checker t_form C.is_false (S.set_clause (S.make nclauses) 0 (l::nil)) t confl.
+
+ Lemma checker_correct : forall t_form l c,
+ checker t_form l c = true ->
+ forall rho, ~ (Lit.interp (Form.interp_state_var rho t_form) l).
+ Proof.
+ unfold checker; intros t_form l (nclauses, t, confl); unfold is_true; rewrite andb_true_iff; intros [H1 H2] rho H; apply (cnf_checker_correct (rho:=rho) H1 H2); destruct (Form.check_form_correct rho _ H1) as [[Ht1 Ht2] Ht3]; apply S.valid_set_clause; auto.
+ apply S.valid_make; auto.
+ unfold C.valid; simpl; rewrite H; auto.
+ Qed.
+
+ Definition checker_b t_form l (b:bool) (c:certif) :=
+ let l := if b then Lit.neg l else l in
+ checker t_form l c.
+
+ Lemma checker_b_correct : forall t_var t_form l b c,
+ checker_b t_form l b c = true ->
+ Lit.interp (Form.interp_state_var (PArray.get t_var) t_form) l = b.
+ Proof.
+ unfold checker_b; intros t_var t_form l b c; case b; case_eq (Lit.interp (Form.interp_state_var (get t_var) t_form) l); auto; intros H1 H2; elim (checker_correct H2 (rho:=get t_var)); auto; rewrite Lit.interp_neg, H1; auto.
+ Qed.
+
+ Definition checker_eq t_form l1 l2 l (c:certif) :=
+ negb (Lit.is_pos l) &&
+ match t_form.[Lit.blit l] with
+ | Form.Fiff l1' l2' => (l1 == l1') && (l2 == l2')
+ | _ => false
+ end &&
+ checker t_form l c.
+
+ Lemma checker_eq_correct : forall t_var t_form l1 l2 l c,
+ checker_eq t_form l1 l2 l c = true ->
+ Lit.interp (Form.interp_state_var (PArray.get t_var) t_form) l1 =
+ Lit.interp (Form.interp_state_var (PArray.get t_var) t_form) l2.
+ Proof.
+ unfold checker_eq; intros t_var t_form l1 l2 l c; rewrite !andb_true_iff; case_eq (t_form .[ Lit.blit l]); [intros _ _|intros _|intros _|intros _ _ _|intros _ _|intros _ _|intros _ _|intros _ _ _|intros l1' l2' Heq|intros _ _ _ _]; intros [[H1 H2] H3]; try discriminate; rewrite andb_true_iff in H2; rewrite !Int63Properties.eqb_spec in H2; destruct H2 as [H2 H4]; subst l1' l2'; case_eq (Lit.is_pos l); intro Heq'; rewrite Heq' in H1; try discriminate; clear H1; assert (H:PArray.default t_form = Form.Ftrue /\ Form.wf t_form).
+ unfold checker in H3; destruct c as (nclauses, t, confl); rewrite andb_true_iff in H3; destruct H3 as [H3 _]; destruct (Form.check_form_correct (get t_var) _ H3) as [[Ht1 Ht2] Ht3]; split; auto.
+ destruct H as [H1 H2]; case_eq (Lit.interp (Form.interp_state_var (get t_var) t_form) l1); intro Heq1; case_eq (Lit.interp (Form.interp_state_var (get t_var) t_form) l2); intro Heq2; auto; elim (checker_correct H3 (rho:=get t_var)); unfold Lit.interp; rewrite Heq'; unfold Var.interp; rewrite Form.wf_interp_form; auto; rewrite Heq; simpl; rewrite Heq1, Heq2; auto.
+ Qed.
+
+End Cnf_Checker.
+
+
+(* Application to resolution + cnf justification + euf + lia *)
+
+(* Require Cnf.Cnf. *)
+(* Require Euf.Euf. *)
+(* Require Lia.Lia. *)
+
+Module Euf_Checker.
+
+ Inductive step :=
+ | Res (pos:int) (res:resolution)
+ | ImmFlatten (pos:int) (cid:clause_id) (lf:_lit)
+ | CTrue (pos:int)
+ | CFalse (pos:int)
+ | BuildDef (pos:int) (l:_lit)
+ | BuildDef2 (pos:int) (l:_lit)
+ | BuildProj (pos:int) (l:_lit) (i:int)
+ | ImmBuildDef (pos:int) (cid:clause_id)
+ | ImmBuildDef2 (pos:int) (cid:clause_id)
+ | ImmBuildProj (pos:int) (cid:clause_id) (i:int)
+ | EqTr (pos:int) (l:_lit) (fl: list _lit)
+ | EqCgr (pos:int) (l:_lit) (fl: list (option _lit))
+ | EqCgrP (pos:int) (l1:_lit) (l2:_lit) (fl: list (option _lit))
+ | LiaMicromega (pos:int) (cl:list _lit) (c:list ZMicromega.ZArithProof)
+ | LiaDiseq (pos:int) (l:_lit)
+ | SplArith (pos:int) (orig:clause_id) (res:_lit) (l:list ZMicromega.ZArithProof)
+ | SplDistinctElim (pos:int) (orig:clause_id) (res:_lit).
+
+ Local Open Scope list_scope.
+
+ Local Notation check_flatten t_atom t_form := (check_flatten t_form (check_hatom t_atom) (check_neg_hatom t_atom)) (only parsing).
+
+ Definition step_checker t_atom t_form s (st:step) :=
+ match st with
+ | Res pos res => S.set_resolve s pos res
+ | ImmFlatten pos cid lf => S.set_clause s pos (check_flatten t_atom t_form s cid lf)
+ | CTrue pos => S.set_clause s pos Cnf.check_True
+ | CFalse pos => S.set_clause s pos Cnf.check_False
+ | BuildDef pos l => S.set_clause s pos (check_BuildDef t_form l)
+ | BuildDef2 pos l => S.set_clause s pos (check_BuildDef2 t_form l)
+ | BuildProj pos l i => S.set_clause s pos (check_BuildProj t_form l i)
+ | ImmBuildDef pos cid => S.set_clause s pos (check_ImmBuildDef t_form s cid)
+ | ImmBuildDef2 pos cid => S.set_clause s pos (check_ImmBuildDef2 t_form s cid)
+ | ImmBuildProj pos cid i => S.set_clause s pos (check_ImmBuildProj t_form s cid i)
+ | EqTr pos l fl => S.set_clause s pos (check_trans t_form t_atom l fl)
+ | EqCgr pos l fl => S.set_clause s pos (check_congr t_form t_atom l fl)
+ | EqCgrP pos l1 l2 fl => S.set_clause s pos (check_congr_pred t_form t_atom l1 l2 fl)
+ | LiaMicromega pos cl c => S.set_clause s pos (check_micromega t_form t_atom cl c)
+ | LiaDiseq pos l => S.set_clause s pos (check_diseq t_form t_atom l)
+ | SplArith pos orig res l => S.set_clause s pos (check_spl_arith t_form t_atom (S.get s orig) res l)
+ | SplDistinctElim pos orig res => S.set_clause s pos (check_distinct_elim t_form t_atom (S.get s orig) res)
+ end.
+
+ Lemma step_checker_correct : forall t_i t_func t_atom t_form,
+ let rho := Form.interp_state_var (Atom.interp_form_hatom t_i t_func t_atom) t_form in
+ Form.check_form t_form -> Atom.check_atom t_atom ->
+ Atom.wt t_i t_func t_atom ->
+ forall s, S.valid rho s ->
+ forall st : step, S.valid rho (step_checker t_atom t_form s st).
+ Proof.
+ intros t_i t_func t_atom t_form rho H1 H2 H10 s Hs. destruct (Form.check_form_correct (Atom.interp_form_hatom t_i t_func t_atom) _ H1) as [[Ht1 Ht2] Ht3]. destruct (Atom.check_atom_correct _ H2) as [Ha1 Ha2]. intros [pos res|pos cid lf|pos|pos|pos l|pos l|pos l i|pos cid|pos cid|pos cid i|pos l fl|pos l fl|pos l1 l2 fl|pos cl c|pos l|pos orig res l|pos orig res]; simpl; try apply S.valid_set_clause; auto.
+ apply S.valid_set_resolve; auto.
+ apply valid_check_flatten; auto; intros h1 h2 H.
+ rewrite (Syntactic.check_hatom_correct_bool _ _ _ Ha1 Ha2 _ _ H); auto.
+ rewrite (Syntactic.check_neg_hatom_correct_bool _ _ _ H10 Ha1 Ha2 _ _ H); auto.
+ apply valid_check_True; auto.
+ apply valid_check_False; auto.
+ apply valid_check_BuildDef; auto.
+ apply valid_check_BuildDef2; auto.
+ apply valid_check_BuildProj; auto.
+ apply valid_check_ImmBuildDef; auto.
+ apply valid_check_ImmBuildDef2; auto.
+ apply valid_check_ImmBuildProj; auto.
+ apply valid_check_trans; auto.
+ apply valid_check_congr; auto.
+ apply valid_check_congr_pred; auto.
+ apply valid_check_micromega; auto.
+ apply valid_check_diseq; auto.
+ apply valid_check_spl_arith; auto.
+ apply valid_check_distinct_elim; auto.
+ Qed.
+
+ Definition euf_checker t_atom t_form s t :=
+ _checker_ (step_checker t_atom t_form) s t.
+
+ Lemma euf_checker_correct : forall t_i t_func t_atom t_form,
+ let rho := Form.interp_state_var (Atom.interp_form_hatom t_i t_func t_atom) t_form in
+ Form.check_form t_form -> Atom.check_atom t_atom ->
+ Atom.wt t_i t_func t_atom ->
+ forall s t confl,
+ euf_checker t_atom t_form C.is_false s t confl ->
+ ~ (S.valid rho s).
+ Proof.
+ unfold euf_checker; intros t_i t_func t_atom t_form rho H1 H2 H10; apply _checker__correct.
+ intros c H; apply C.is_false_correct; auto.
+ apply step_checker_correct; auto.
+ Qed.
+
+ Inductive certif :=
+ | Certif : int -> _trace_ step -> int -> certif.
+
+ Definition add_roots s d used_roots :=
+ match used_roots with
+ | Some ur => PArray.foldi_right (fun i c_index s =>
+ let c := if c_index < length d then (d.[c_index])::nil else C._true in
+ S.set_clause s i c) ur s
+ | None => PArray.foldi_right (fun i c s => S.set_clause s i (c::nil)) d s
+ end.
+
+ Definition valid t_i t_func t_atom t_form d :=
+ let rho := Form.interp_state_var (Atom.interp_form_hatom t_i t_func t_atom) t_form in
+ afold_left _ _ true andb (Lit.interp rho) d.
+
+ Lemma add_roots_correct : forall t_i t_func t_atom t_form,
+ let rho := Form.interp_state_var (Atom.interp_form_hatom t_i t_func t_atom) t_form in
+ Form.check_form t_form -> Atom.check_atom t_atom ->
+ Atom.wt t_i t_func t_atom ->
+ forall s d used_roots, S.valid rho s -> valid t_func t_atom t_form d ->
+ S.valid rho (add_roots s d used_roots).
+ Proof.
+ intros t_i t_func t_atom t_form rho H1 H2 H10 s d used_roots H3; unfold valid; intro H4; pose (H5 := (afold_left_andb_true_inv _ _ _ H4)); unfold add_roots; assert (Valuation.wf rho) by (destruct (Form.check_form_correct (Atom.interp_form_hatom t_i t_func t_atom) _ H1) as [_ H]; auto); case used_roots.
+ intro ur; apply (foldi_right_Ind _ _ (fun _ a => S.valid rho a)); auto; intros a i H6 Ha; apply S.valid_set_clause; auto; case_eq (ur .[ i] < length d).
+ intro; unfold C.valid; simpl; rewrite H5; auto.
+ intros; apply C.interp_true; auto.
+ apply (foldi_right_Ind _ _ (fun _ a => S.valid rho a)); auto; intros a i H6 Ha; apply S.valid_set_clause; auto; unfold C.valid; simpl; rewrite H5; auto.
+ Qed.
+
+ Definition checker t_i t_func t_atom t_form d used_roots (c:certif) :=
+ let (nclauses, t, confl) := c in
+ Form.check_form t_form && Atom.check_atom t_atom &&
+ Atom.wt t_i t_func t_atom &&
+ euf_checker t_atom t_form C.is_false (add_roots (S.make nclauses) d used_roots) t confl.
+ Implicit Arguments checker [].
+
+ Lemma checker_correct : forall t_i t_func t_atom t_form d used_roots c,
+ checker t_i t_func t_atom t_form d used_roots c = true ->
+ ~ valid t_func t_atom t_form d.
+ Proof.
+ unfold checker; intros t_i t_func t_atom t_form d used_roots (nclauses, t, confl); rewrite !andb_true_iff; intros [[[H1 H2] H10] H3] H; eelim euf_checker_correct; try eassumption; apply add_roots_correct; try eassumption; apply S.valid_make; destruct (Form.check_form_correct (Atom.interp_form_hatom t_i t_func t_atom) _ H1) as [_ H4]; auto.
+ Qed.
+
+ Definition checker_b t_i t_func t_atom t_form l (b:bool) (c:certif) :=
+ let l := if b then Lit.neg l else l in
+ let (nclauses,_,_) := c in
+ checker t_i t_func t_atom t_form (PArray.make nclauses l) None c.
+
+ Lemma checker_b_correct : forall t_i t_func t_atom t_form l b c,
+ checker_b t_func t_atom t_form l b c = true ->
+ Lit.interp (Form.interp_state_var (Atom.interp_form_hatom t_i t_func t_atom) t_form) l = b.
+ Proof.
+ unfold checker_b; intros t_i t_func t_atom t_form l b (nclauses, t, confl); case b; intros H2; case_eq (Lit.interp (Form.interp_state_var (Atom.interp_form_hatom t_i t_func t_atom) t_form) l); auto; intros H1; elim (checker_correct H2 (t_func:=t_func)); auto; unfold valid; apply afold_left_andb_true; intros i Hi; rewrite get_make; auto; rewrite Lit.interp_neg, H1; auto.
+ Qed.
+
+ Definition checker_eq t_i t_func t_atom t_form l1 l2 l (c:certif) :=
+ negb (Lit.is_pos l) &&
+ match t_form.[Lit.blit l] with
+ | Form.Fiff l1' l2' => (l1 == l1') && (l2 == l2')
+ | _ => false
+ end &&
+ let (nclauses,_,_) := c in
+ checker t_i t_func t_atom t_form (PArray.make nclauses l) None c.
+
+ Lemma checker_eq_correct : forall t_i t_func t_atom t_form l1 l2 l c,
+ checker_eq t_func t_atom t_form l1 l2 l c = true ->
+ Lit.interp (Form.interp_state_var (Atom.interp_form_hatom t_i t_func t_atom) t_form) l1 =
+ Lit.interp (Form.interp_state_var (Atom.interp_form_hatom t_i t_func t_atom) t_form) l2.
+ Proof.
+ unfold checker_eq; intros t_i t_func t_atom t_form l1 l2 l (nclauses, t, confl); rewrite !andb_true_iff; case_eq (t_form .[ Lit.blit l]); [intros _ _|intros _|intros _|intros _ _ _|intros _ _|intros _ _|intros _ _|intros _ _ _|intros l1' l2' Heq|intros _ _ _ _]; intros [[H1 H2] H3]; try discriminate; rewrite andb_true_iff in H2; rewrite !Int63Properties.eqb_spec in H2; destruct H2 as [H2 H4]; subst l1' l2'; case_eq (Lit.is_pos l); intro Heq'; rewrite Heq' in H1; try discriminate; clear H1; assert (H:PArray.default t_form = Form.Ftrue /\ Form.wf t_form).
+ unfold checker in H3; rewrite !andb_true_iff in H3; destruct H3 as [[[H3 _] _] _]; destruct (Form.check_form_correct (Atom.interp_form_hatom t_i t_func t_atom) _ H3) as [[Ht1 Ht2] Ht3]; split; auto.
+ destruct H as [H1 H2]; case_eq (Lit.interp (Form.interp_state_var (Atom.interp_form_hatom t_i t_func t_atom) t_form) l1); intro Heq1; case_eq (Lit.interp (Form.interp_state_var (Atom.interp_form_hatom t_i t_func t_atom) t_form) l2); intro Heq2; auto; elim (checker_correct H3 (t_func:=t_func)); unfold valid; apply afold_left_andb_true; intros i Hi; rewrite get_make; unfold Lit.interp; rewrite Heq'; unfold Var.interp; rewrite Form.wf_interp_form; auto; rewrite Heq; simpl; rewrite Heq1, Heq2; auto.
+ Qed.
+
+
+ (* Checker for extraction, that does not know the evaluation contexts.
+ TODO: show that there always exists a well-typed evaluation
+ context. *)
+
+ Definition checker_ext t_atom t_form d used_roots (c:certif) :=
+ let (nclauses, t, confl) := c in
+ Form.check_form t_form && Atom.check_atom t_atom &&
+ euf_checker t_atom t_form C.is_false (add_roots (S.make nclauses) d used_roots) t confl.
+ Implicit Arguments checker_ext [].
+
+ Lemma checker_ext_correct : forall t_atom t_form d used_roots c,
+ checker_ext t_atom t_form d used_roots c = true ->
+ forall t_i t_func, Atom.wt t_i t_func t_atom ->
+ ~ valid t_func t_atom t_form d.
+ Proof.
+ unfold checker_ext; intros t_atom t_form d used_roots (nclauses, t, confl); rewrite !andb_true_iff; intros [[H1 H2] H3]; intros t_i t_func H10 H; eelim euf_checker_correct; try eassumption; apply add_roots_correct; try eassumption; apply S.valid_make; destruct (Form.check_form_correct (Atom.interp_form_hatom t_i t_func t_atom) _ H1) as [_ H4]; auto.
+ Qed.
+
+ (* For debugging *)
+ (*
+ Fixpoint is__true (c:C.t) :=
+ match c with
+ | cons l q => if (l == 0) then true else is__true q
+ | _ => false
+ end.
+
+ Definition step_checker_debug t_atom t_form s (st:step) :=
+ match st with
+ | Res pos res =>
+ let s' := S.set_resolve s pos res in
+ if is__true (s'.[pos]) then None else Some s'
+ | ImmFlatten pos cid lf =>
+ let c := check_flatten t_atom t_form s cid lf in
+ if is__true c then None else Some (S.set_clause s pos c)
+ | CTrue pos => Some (S.set_clause s pos Cnf.check_True)
+ | CFalse pos => Some (S.set_clause s pos Cnf.check_False)
+ | BuildDef pos l =>
+ let c := check_BuildDef t_form l in
+ if is__true c then None else Some (S.set_clause s pos c)
+ | BuildDef2 pos l =>
+ let c := check_BuildDef2 t_form l in
+ if is__true c then None else Some (S.set_clause s pos c)
+ | BuildProj pos l i =>
+ let c := check_BuildProj t_form l i in
+ if is__true c then None else Some (S.set_clause s pos c)
+ | ImmBuildDef pos cid =>
+ let c := check_ImmBuildDef t_form s cid in
+ if is__true c then None else Some (S.set_clause s pos c)
+ | ImmBuildDef2 pos cid =>
+ let c := check_ImmBuildDef2 t_form s cid in
+ if is__true c then None else Some (S.set_clause s pos c)
+ | ImmBuildProj pos cid i =>
+ let c := check_ImmBuildProj t_form s cid i in
+ if is__true c then None else Some (S.set_clause s pos c)
+ | EqTr pos l fl =>
+ let c := check_trans t_form t_atom l fl in
+ if is__true c then None else Some (S.set_clause s pos c)
+ | EqCgr pos l fl =>
+ let c := check_congr t_form t_atom l fl in
+ if is__true c then None else Some (S.set_clause s pos c)
+ | EqCgrP pos l1 l2 fl =>
+ let c := check_congr_pred t_form t_atom l1 l2 fl in
+ if is__true c then None else Some (S.set_clause s pos c)
+ | LiaMicromega pos cl c =>
+ let c := check_micromega t_form t_atom cl c in
+ if is__true c then None else Some (S.set_clause s pos c)
+ | LiaDiseq pos l =>
+ let c := check_diseq t_form t_atom l in
+ if is__true c then None else Some (S.set_clause s pos c)
+ | SplArith pos orig res l =>
+ let c := check_spl_arith t_form t_atom (S.get s orig) res l in
+ if is__true c then None else Some (S.set_clause s pos c)
+ | SplDistinctElim pos input res =>
+ let c := check_distinct_elim t_form t_atom (S.get s input) res in
+ if is__true c then None else Some (S.set_clause s pos c)
+ end.
+
+ Definition euf_checker_debug t_atom t_form s t :=
+ _checker_debug_ (step_checker_debug t_atom t_form) s t.
+
+ Definition euf_checker_partial t_atom t_form s t :=
+ _checker_partial_ (step_checker t_atom t_form) s t.
+ *)
+
+End Euf_Checker.
+
+
+Unset Implicit Arguments.
diff --git a/src/cnf/Cnf.v b/src/cnf/Cnf.v
new file mode 100644
index 0000000..d918dab
--- /dev/null
+++ b/src/cnf/Cnf.v
@@ -0,0 +1,419 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+Require Import PArray List Bool.
+(* Add LoadPath ".." as SMTCoq. *)
+Require Import Misc State SMT_terms.
+
+Import Form.
+
+Local Open Scope array_scope.
+Local Open Scope int63_scope.
+
+Set Implicit Arguments.
+Unset Strict Implicit.
+
+Definition or_of_imp args :=
+ let last := PArray.length args - 1 in
+ PArray.mapi (fun i l => if i == last then l else Lit.neg l) args.
+Register or_of_imp as PrimInline.
+
+Lemma length_or_of_imp : forall args,
+ PArray.length (or_of_imp args) = PArray.length args.
+Proof. intro; apply length_mapi. Qed.
+
+Lemma get_or_of_imp : forall args i,
+ i < (PArray.length args) - 1 -> (or_of_imp args).[i] = Lit.neg (args.[i]).
+Proof.
+ unfold or_of_imp; intros args i H; case_eq (0 < PArray.length args).
+ intro Heq; rewrite get_mapi.
+ replace (i == PArray.length args - 1) with false; auto; symmetry; rewrite eqb_false_spec; intro; subst i; unfold is_true in H; rewrite ltb_spec, (to_Z_sub_1 _ _ Heq) in H; omega.
+ rewrite ltb_spec; unfold is_true in H; rewrite ltb_spec, (to_Z_sub_1 _ _ Heq) in H; omega.
+ rewrite ltb_negb_geb; case_eq (PArray.length args <= 0); try discriminate; intros Heq _; assert (H1: PArray.length args = 0).
+ apply to_Z_inj; rewrite leb_spec in Heq; destruct (to_Z_bounded (PArray.length args)) as [H1 _]; change [|0|] with 0%Z in *; omega.
+ rewrite !get_outofbound.
+ rewrite default_mapi, H1; auto.
+ rewrite H1; case_eq (i < 0); auto; intro H2; eelim ltb_0; eassumption.
+ rewrite length_mapi, H1; case_eq (i < 0); auto; intro H2; eelim ltb_0; eassumption.
+Qed.
+
+Lemma get_or_of_imp2 : forall args i, 0 < PArray.length args ->
+ i = (PArray.length args) - 1 -> (or_of_imp args).[i] = args.[i].
+Proof.
+ unfold or_of_imp; intros args i Heq Hi; rewrite get_mapi; subst i.
+ rewrite Int63Axioms.eqb_refl; auto.
+ rewrite ltb_spec, (to_Z_sub_1 _ _ Heq); omega.
+Qed.
+
+
+Section CHECKER.
+
+ Variable t_form : PArray.array form.
+ Local Notation get_hash := (PArray.get t_form) (only parsing).
+ Variable s : S.t.
+
+
+ (* * true : {true} *)
+
+ Definition check_True := C._true.
+
+
+ (* * false : {(not false)} *)
+
+ Definition check_False := Lit.neg (Lit._false)::nil.
+
+
+ (* * and_neg : {(and a_1 ... a_n) (not a_1) ... (not a_n)}
+ * or_pos : {(not (or a_1 ... a_n)) a_1 ... a_n}
+ * implies_pos : {(not (implies a b)) (not a) b}
+ * xor_pos1 : {(not (xor a b)) a b}
+ * xor_neg1 : {(xor a b) a (not b)}
+ * equiv_pos1 : {(not (iff a b)) a (not b)}
+ * equiv_neg1 : {(iff a b) (not a) (not b)}
+ * ite_pos1 : {(not (if_then_else a b c)) a c}
+ * ite_neg1 : {(if_then_else a b c) a (not c)} *)
+
+ Definition check_BuildDef l :=
+ match get_hash (Lit.blit l) with
+ | Fand args =>
+ if Lit.is_pos l then l :: List.map Lit.neg (PArray.to_list args)
+ else C._true
+ | For args =>
+ if Lit.is_pos l then C._true
+ else l :: PArray.to_list args
+ | Fimp args =>
+ if Lit.is_pos l then C._true
+ else
+ let args := or_of_imp args in
+ l :: PArray.to_list args
+ | Fxor a b =>
+ if Lit.is_pos l then l::a::Lit.neg b::nil
+ else l::a::b::nil
+ | Fiff a b =>
+ if Lit.is_pos l then l::Lit.neg a::Lit.neg b::nil
+ else l::a::Lit.neg b::nil
+ | Fite a b c =>
+ if Lit.is_pos l then l::a::Lit.neg c::nil
+ else l::a::c::nil
+ | _ => C._true
+ end.
+
+
+ (* * not_and : {(not (and a_1 ... a_n))} --> {(not a_1) ... (not a_n)}
+ * or : {(or a_1 ... a_n)} --> {a_1 ... a_n}
+ * implies : {(implies a b)} --> {(not a) b}
+ * xor1 : {(xor a b)} --> {a b}
+ * not_xor1 : {(not (xor a b))} --> {a (not b)}
+ * equiv2 : {(iff a b)} --> {a (not b)}
+ * not_equiv2 : {(not (iff a b))} --> {(not a) (not b)}
+ * ite1 : {(if_then_else a b c)} --> {a c}
+ * not_ite1 : {(not (if_then_else a b c))} --> {a (not c)} *)
+
+ Definition check_ImmBuildDef pos :=
+ match S.get s pos with
+ | l::nil =>
+ match get_hash (Lit.blit l) with
+ | Fand args =>
+ if Lit.is_pos l then C._true
+ else List.map Lit.neg (PArray.to_list args)
+ | For args =>
+ if Lit.is_pos l then PArray.to_list args
+ else C._true
+ | Fimp args =>
+ if Lit.is_pos l then
+ let args := or_of_imp args in
+ PArray.to_list args
+ else C._true
+ | Fxor a b =>
+ if Lit.is_pos l then a::b::nil
+ else a::Lit.neg b::nil
+ | Fiff a b =>
+ if Lit.is_pos l then a::Lit.neg b::nil
+ else Lit.neg a::Lit.neg b::nil
+ | Fite a b c =>
+ if Lit.is_pos l then a::c::nil
+ else a::Lit.neg c::nil
+ | _ => C._true
+ end
+ | _ => C._true
+ end.
+
+
+ (* * xor_pos2 : {(not (xor a b)) (not a) (not b)}
+ * xor_neg2 : {(xor a b) (not a) b}
+ * equiv_pos2 : {(not (iff a b)) (not a) b}
+ * equiv_neg2 : {(iff a b) a b}
+ * ite_pos2 : {(not (if_then_else a b c)) (not a) b}
+ * ite_neg2 : {(if_then_else a b c) (not a) (not b)} *)
+
+ Definition check_BuildDef2 l :=
+ match get_hash (Lit.blit l) with
+ | Fxor a b =>
+ if Lit.is_pos l then l::Lit.neg a::b::nil
+ else l::Lit.neg a::Lit.neg b::nil
+ | Fiff a b =>
+ if Lit.is_pos l then l::a::b::nil
+ else l::Lit.neg a::b::nil
+ | Fite a b c =>
+ if Lit.is_pos l then l::Lit.neg a::Lit.neg b::nil
+ else l::Lit.neg a::b::nil
+ | _ => C._true
+ end.
+
+
+ (* * xor2 : {(xor a b)} --> {(not a) (not b)}
+ * not_xor2 : {(not (xor a b))} --> {(not a) b}
+ * equiv1 : {(iff a b)} --> {(not a) b}
+ * not_equiv1 : {(not (iff a b))} --> {a b}
+ * ite2 : {(if_then_else a b c)} --> {(not a) b}
+ * not_ite2 : {(not (if_then_else a b c))} --> {(not a) (not b)}
+ *)
+
+ Definition check_ImmBuildDef2 pos :=
+ match S.get s pos with
+ | l::nil =>
+ match get_hash (Lit.blit l) with
+ | Fxor a b =>
+ if Lit.is_pos l then Lit.neg a::Lit.neg b::nil
+ else Lit.neg a::b::nil
+ | Fiff a b =>
+ if Lit.is_pos l then Lit.neg a::b::nil
+ else a::b::nil
+ | Fite a b c =>
+ if Lit.is_pos l then Lit.neg a::b::nil
+ else Lit.neg a::Lit.neg b::nil
+ | _ => C._true
+ end
+ | _ => C._true
+ end.
+
+
+ (* * or_neg : {(or a_1 ... a_n) (not a_i)}
+ * and_pos : {(not (and a_1 ... a_n)) a_i}
+ * implies_neg1 : {(implies a b) a}
+ * implies_neg2 : {(implies a b) (not b)} *)
+
+ Definition check_BuildProj l i :=
+ let x := Lit.blit l in
+ match get_hash x with
+ | For args =>
+ if i < PArray.length args then Lit.lit x::Lit.neg (args.[i])::nil
+ else C._true
+ | Fand args =>
+ if i < PArray.length args then Lit.nlit x::(args.[i])::nil
+ else C._true
+ | Fimp args =>
+ let len := PArray.length args in
+ if i < len then
+ if i == len - 1 then Lit.lit x::Lit.neg (args.[i])::nil
+ else Lit.lit x::(args.[i])::nil
+ else C._true
+ | _ => C._true
+ end.
+
+
+ (* * and : {(and a_1 ... a_n)} --> {a_i}
+ * not_or : {(not (or a_1 ... a_n))} --> {(not a_i)}
+ * not_implies1 : {(not (implies a b))} --> {a}
+ * not_implies2 : {(not (implies a b))} --> {(not b)} *)
+
+ Definition check_ImmBuildProj pos i :=
+ match S.get s pos with
+ | l::nil =>
+ let x := Lit.blit l in
+ match get_hash x with
+ | For args =>
+ if (i < PArray.length args) && negb (Lit.is_pos l) then Lit.neg (args.[i])::nil
+ else C._true
+ | Fand args =>
+ if (i < PArray.length args) && (Lit.is_pos l) then (args.[i])::nil
+ else C._true
+ | Fimp args =>
+ let len := PArray.length args in
+ if (i < len) && negb (Lit.is_pos l) then
+ if i == len - 1 then Lit.neg (args.[i])::nil
+ else (args.[i])::nil
+ else C._true
+ | _ => C._true
+ end
+ | _ => C._true
+ end.
+
+ (** The correctness proofs *)
+
+ Variable interp_atom : atom -> bool.
+
+ Hypothesis Hch_f : check_form t_form.
+
+ Local Notation rho := (Form.interp_state_var interp_atom t_form).
+
+ Let Hwfrho : Valuation.wf rho.
+ Proof.
+ destruct (check_form_correct interp_atom _ Hch_f) as (_, H);exact H.
+ Qed.
+
+ Lemma valid_check_True : C.valid rho check_True.
+ Proof.
+ apply C.interp_true;trivial.
+ Qed.
+
+ Lemma valid_check_False : C.valid rho check_False.
+ Proof.
+ unfold check_False, C.valid;simpl.
+ rewrite Lit.interp_neg.
+ assert (W:= Lit.interp_false _ Hwfrho).
+ destruct (Lit.interp rho Lit._false);trivial;elim W;red;trivial.
+ Qed.
+
+ Let rho_interp : forall x : int,
+ rho x = interp interp_atom t_form (t_form.[ x]).
+ Proof.
+ destruct (check_form_correct interp_atom _ Hch_f) as ((H,H0), _).
+ intros x;apply wf_interp_form;trivial.
+ Qed.
+
+ Ltac tauto_check :=
+ try (rewrite !Lit.interp_neg);
+ repeat
+ match goal with |- context [Lit.interp rho ?x] =>
+ destruct (Lit.interp rho x);trivial end.
+
+ Axiom afold_left_and : forall a,
+ afold_left bool int true andb (Lit.interp rho) a =
+ List.forallb (Lit.interp rho) (to_list a).
+
+ Axiom afold_left_or : forall a,
+ afold_left bool int false orb (Lit.interp rho) a =
+ C.interp rho (to_list a).
+
+ Axiom afold_right_impb : forall a,
+ (afold_right bool int true implb (Lit.interp rho) a) =
+ C.interp rho (to_list (or_of_imp a)).
+
+ Axiom Cinterp_neg : forall cl,
+ C.interp rho (map Lit.neg cl) = negb (forallb (Lit.interp rho) cl).
+
+ Lemma valid_check_BuildDef : forall l, C.valid rho (check_BuildDef l).
+ Proof.
+ unfold check_BuildDef,C.valid;intros l.
+ case_eq (t_form.[Lit.blit l]);intros;auto using C.interp_true;
+ case_eq (Lit.is_pos l);intros Heq;auto using C.interp_true;simpl;
+ unfold Lit.interp at 1;rewrite Heq;unfold Var.interp; rewrite rho_interp, H;simpl;
+ tauto_check.
+ rewrite afold_left_and, Cinterp_neg;apply orb_negb_r.
+ rewrite afold_left_or, orb_comm;apply orb_negb_r.
+ rewrite afold_right_impb, orb_comm;apply orb_negb_r.
+ Qed.
+
+ Lemma valid_check_BuildDef2 : forall l, C.valid rho (check_BuildDef2 l).
+ Proof.
+ unfold check_BuildDef2,C.valid;intros l.
+ case_eq (t_form.[Lit.blit l]);intros;auto using C.interp_true;
+ case_eq (Lit.is_pos l);intros Heq;auto using C.interp_true;simpl;
+ unfold Lit.interp at 1;rewrite Heq;unfold Var.interp; rewrite rho_interp, H;simpl;
+ tauto_check.
+ Qed.
+
+ Lemma valid_check_BuildProj : forall l i, C.valid rho (check_BuildProj l i).
+ Proof.
+ unfold check_BuildProj,C.valid;intros l i.
+ case_eq (t_form.[Lit.blit l]);intros;auto using C.interp_true;
+ case_eq (i < PArray.length a);intros Hlt;auto using C.interp_true;simpl.
+
+ rewrite Lit.interp_nlit;unfold Var.interp;rewrite rho_interp, orb_false_r, H.
+ simpl;rewrite afold_left_and.
+ case_eq (forallb (Lit.interp rho) (to_list a));trivial.
+ rewrite forallb_forall;intros Heq;rewrite Heq;trivial.
+ apply to_list_In; auto.
+ rewrite Lit.interp_lit;unfold Var.interp;rewrite rho_interp, orb_false_r, H.
+ simpl;rewrite afold_left_or.
+
+ unfold C.interp;case_eq (existsb (Lit.interp rho) (to_list a));trivial.
+ rewrite <-not_true_iff_false, existsb_exists, Lit.interp_neg.
+ case_eq (Lit.interp rho (a .[ i]));trivial.
+ intros Heq Hex;elim Hex;exists (a.[i]);split;trivial.
+ apply to_list_In; auto.
+ case_eq (i == PArray.length a - 1);intros Heq;simpl;
+ rewrite Lit.interp_lit;unfold Var.interp;rewrite rho_interp, H;simpl;
+ rewrite afold_right_impb; case_eq (C.interp rho (to_list (or_of_imp a)));trivial;
+ unfold C.interp;rewrite <-not_true_iff_false, existsb_exists;
+ try rewrite Lit.interp_neg; case_eq (Lit.interp rho (a .[ i]));trivial;
+ intros Heq' Hex;elim Hex.
+ exists (a.[i]);split;trivial.
+ assert (H1: 0 < PArray.length a) by (apply (leb_ltb_trans _ i _); auto; apply leb_0); rewrite Int63Properties.eqb_spec in Heq; rewrite <- (get_or_of_imp2 H1 Heq); apply to_list_In; rewrite length_or_of_imp; auto.
+ exists (Lit.neg (a.[i]));rewrite Lit.interp_neg, Heq';split;trivial.
+ assert (H1: i < PArray.length a - 1 = true) by (rewrite ltb_spec, (to_Z_sub_1 _ _ Hlt); rewrite eqb_false_spec in Heq; assert (H1: [|i|] <> ([|PArray.length a|] - 1)%Z) by (intro H1; apply Heq, to_Z_inj; rewrite (to_Z_sub_1 _ _ Hlt); auto); rewrite ltb_spec in Hlt; omega); rewrite <- (get_or_of_imp H1); apply to_list_In; rewrite length_or_of_imp; auto.
+ Qed.
+
+ Hypothesis Hs : S.valid rho s.
+
+ Lemma valid_check_ImmBuildDef : forall cid,
+ C.valid rho (check_ImmBuildDef cid).
+ Proof.
+ unfold check_ImmBuildDef,C.valid;intros cid.
+ generalize (Hs cid);unfold C.valid.
+ destruct (S.get s cid) as [ | l [ | _l _c]];auto using C.interp_true.
+ simpl;unfold Lit.interp, Var.interp; rewrite !rho_interp;
+ destruct (t_form.[Lit.blit l]);auto using C.interp_true;
+ case_eq (Lit.is_pos l);intros Heq;auto using C.interp_true;simpl;
+ tauto_check.
+ rewrite afold_left_and, Cinterp_neg, orb_false_r;trivial.
+ rewrite afold_left_or, orb_false_r;trivial.
+ rewrite afold_right_impb, orb_false_r;trivial.
+ Qed.
+
+ Lemma valid_check_ImmBuildDef2 : forall cid, C.valid rho (check_ImmBuildDef2 cid).
+ Proof.
+ unfold check_ImmBuildDef2,C.valid;intros cid.
+ generalize (Hs cid);unfold C.valid.
+ destruct (S.get s cid) as [ | l [ | _l _c]];auto using C.interp_true.
+ simpl;unfold Lit.interp, Var.interp; rewrite !rho_interp;
+ destruct (t_form.[Lit.blit l]);auto using C.interp_true;
+ case_eq (Lit.is_pos l);intros Heq;auto using C.interp_true;simpl;
+ tauto_check.
+ Qed.
+
+ Lemma valid_check_ImmBuildProj : forall cid i, C.valid rho (check_ImmBuildProj cid i).
+ Proof.
+ unfold check_ImmBuildProj,C.valid;intros cid i.
+ generalize (Hs cid);unfold C.valid.
+ destruct (S.get s cid) as [ | l [ | _l _c]];auto using C.interp_true.
+ simpl;unfold Lit.interp, Var.interp; rewrite !rho_interp;
+ destruct (t_form.[Lit.blit l]);auto using C.interp_true;
+ case_eq (i < PArray.length a); intros Hlt;auto using C.interp_true;
+ case_eq (Lit.is_pos l);intros Heq;auto using C.interp_true;simpl;
+ rewrite !orb_false_r.
+ rewrite afold_left_and.
+ rewrite forallb_forall;intros H;apply H;auto.
+ apply to_list_In; auto.
+ rewrite negb_true_iff, <-not_true_iff_false, afold_left_or.
+ unfold C.interp;rewrite existsb_exists, Lit.interp_neg.
+ case_eq (Lit.interp rho (a .[ i]));trivial.
+ intros Heq' Hex;elim Hex;exists (a.[i]);split;trivial.
+ apply to_list_In; auto.
+ rewrite negb_true_iff, <-not_true_iff_false, afold_right_impb.
+ case_eq (i == PArray.length a - 1);intros Heq';simpl;
+ unfold C.interp;simpl;try rewrite Lit.interp_neg;rewrite orb_false_r,
+ existsb_exists;case_eq (Lit.interp rho (a .[ i]));trivial;
+ intros Heq2 Hex;elim Hex.
+ exists (a.[i]);split;trivial.
+ assert (H1: 0 < PArray.length a) by (apply (leb_ltb_trans _ i _); auto; apply leb_0); rewrite Int63Properties.eqb_spec in Heq'; rewrite <- (get_or_of_imp2 H1 Heq'); apply to_list_In; rewrite length_or_of_imp; auto.
+ exists (Lit.neg (a.[i]));rewrite Lit.interp_neg, Heq2;split;trivial.
+ assert (H1: i < PArray.length a - 1 = true) by (rewrite ltb_spec, (to_Z_sub_1 _ _ Hlt); rewrite eqb_false_spec in Heq'; assert (H1: [|i|] <> ([|PArray.length a|] - 1)%Z) by (intro H1; apply Heq', to_Z_inj; rewrite (to_Z_sub_1 _ _ Hlt); auto); rewrite ltb_spec in Hlt; omega); rewrite <- (get_or_of_imp H1); apply to_list_In; rewrite length_or_of_imp; auto.
+ Qed.
+
+End CHECKER.
+
+Unset Implicit Arguments.
diff --git a/src/euf/Euf.v b/src/euf/Euf.v
new file mode 100644
index 0000000..9b86bf3
--- /dev/null
+++ b/src/euf/Euf.v
@@ -0,0 +1,538 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+(* Add LoadPath ".." as SMTCoq. *)
+Require Import Bool List Int63 PArray.
+Require Import State SMT_terms.
+
+Local Open Scope array_scope.
+Local Open Scope int63_scope.
+
+Section certif.
+
+ Variable t_form : PArray.array Form.form.
+ Variable t_atom : PArray.array Atom.atom.
+
+ Local Notation get_atom := (PArray.get t_atom) (only parsing).
+ Local Notation get_form := (PArray.get t_form) (only parsing).
+
+ Definition get_eq (x:var) (f : int -> int -> C.t) :=
+ match get_form x with
+ | Form.Fatom xa =>
+ match get_atom xa with
+ | Atom.Abop (Atom.BO_eq _) a b => f a b
+ | _ => C._true
+ end
+ | _ => C._true
+ end.
+ Register get_eq as PrimInline.
+
+ Fixpoint check_trans_aux (t1 t2:int)
+ (eqs:list _lit) (res:_lit) (clause:C.t) : C.t :=
+ match eqs with
+ | nil =>
+ let xres := Lit.blit res in
+ get_eq xres (fun t1' t2' =>
+ if ((t1 == t1') && (t2 == t2')) ||
+ ((t1 == t2') && (t2 == t1')) then
+ Lit.lit xres :: clause
+ else C._true)
+ | leq::eqs =>
+ let xeq := Lit.blit leq in
+ get_eq xeq (fun t t' =>
+ if t2 == t' then
+ check_trans_aux t1 t eqs res (Lit.nlit xeq :: clause)
+ else
+ if t2 == t then
+ check_trans_aux t1 t' eqs res (Lit.nlit xeq :: clause)
+ else
+ if t1 == t' then
+ check_trans_aux t t2 eqs res (Lit.nlit xeq :: clause)
+ else
+ if t1 == t then
+ check_trans_aux t' t2 eqs res (Lit.nlit xeq :: clause)
+ else C._true)
+ end.
+
+ Definition check_trans (res:_lit) (eqs:list _lit) : C.t :=
+ match eqs with
+ | nil =>
+ let xres := Lit.blit res in
+ get_eq xres (fun t1 t2 =>
+ if t1 == t2 then Lit.lit xres :: nil else C._true)
+ | leq :: eqs =>
+ let xeq := Lit.blit leq in
+ get_eq xeq
+ (fun t1 t2 => check_trans_aux t1 t2 eqs res (Lit.nlit xeq :: nil))
+ end.
+
+ Fixpoint build_congr (eqs:list (option _lit))
+ (l r:list int) (c:C.t) {struct eqs} :=
+ match eqs, l, r with
+ | nil, nil, nil => c
+ | eq::eqs, t1::l, t2::r =>
+ match eq with
+ | None => if t1 == t2 then build_congr eqs l r c else C._true
+ | Some leq =>
+ let xeq := Lit.blit leq in
+ get_eq xeq (fun t1' t2' =>
+ if ((t1 == t1') && (t2 == t2')) ||
+ ((t1 == t2') && (t2 == t1')) then
+ build_congr eqs l r (Lit.nlit xeq :: c)
+ else C._true)
+ end
+ | _, _, _ => C._true
+ end.
+
+ Definition check_congr (leq:_lit) (eqs:list (option _lit)) :=
+ let xeq := Lit.blit leq in
+ get_eq xeq (fun t1 t2 =>
+ match get_atom t1, get_atom t2 with
+ | Atom.Abop o1 a1 a2, Atom.Abop o2 b1 b2 =>
+ if Atom.bop_eqb o1 o2 then
+ build_congr eqs (a1::a2::nil) (b1::b2::nil) (Lit.lit xeq :: nil)
+ else C._true
+ | Atom.Auop o1 a, Atom.Auop o2 b =>
+ if Atom.uop_eqb o1 o2 then
+ build_congr eqs (a::nil) (b::nil) (Lit.lit xeq :: nil)
+ else C._true
+ | Atom.Aapp f1 args1, Atom.Aapp f2 args2 =>
+ if f1 == f2 then build_congr eqs args1 args2 (Lit.lit xeq :: nil)
+ else C._true
+ | _, _ => C._true
+ end).
+
+ Definition check_congr_pred (PA:_lit) (PB:_lit) (eqs:list (option _lit)) :=
+ let xPA := Lit.blit PA in
+ let xPB := Lit.blit PB in
+ match get_form xPA, get_form xPB with
+ | Form.Fatom pa, Form.Fatom pb =>
+ match get_atom pa, get_atom pb with
+ | Atom.Abop o1 a1 a2, Atom.Abop o2 b1 b2 =>
+ if Atom.bop_eqb o1 o2 then
+ build_congr eqs
+ (a1::a2::nil) (b1::b2::nil) (Lit.nlit xPA :: Lit.lit xPB :: nil)
+ else C._true
+ | Atom.Auop o1 a, Atom.Auop o2 b =>
+ if Atom.uop_eqb o1 o2 then
+ build_congr eqs
+ (a::nil) (b::nil) (Lit.nlit xPA :: Lit.lit xPB :: nil)
+ else C._true
+ | Atom.Aapp p a, Atom.Aapp p' b =>
+ if p == p' then
+ build_congr eqs a b (Lit.nlit xPA :: Lit.lit xPB :: nil)
+ else C._true
+ | _, _ => C._true
+ end
+ | _, _ => C._true
+ end.
+
+ Section Proof.
+
+ Variables (t_i : array typ_eqb)
+ (t_func : array (Atom.tval t_i))
+ (ch_atom : Atom.check_atom t_atom)
+ (ch_form : Form.check_form t_form)
+ (wt_t_atom : Atom.wt t_i t_func t_atom).
+
+ Local Notation interp_hatom :=
+ (Atom.interp_hatom t_i t_func t_atom).
+
+ Local Notation interp_form_hatom :=
+ (Atom.interp_form_hatom t_i t_func t_atom).
+
+ Local Notation rho :=
+ (Form.interp_state_var interp_form_hatom t_form).
+
+ Let wf_t_atom : Atom.wf t_atom.
+ Proof. destruct (Atom.check_atom_correct _ ch_atom); auto. Qed.
+
+ Let def_t_atom : default t_atom = Atom.Acop Atom.CO_xH.
+ Proof. destruct (Atom.check_atom_correct _ ch_atom); auto. Qed.
+
+ Let def_t_form : default t_form = Form.Ftrue.
+ Proof.
+ destruct (Form.check_form_correct interp_form_hatom _ ch_form) as [H _]; destruct H; auto.
+ Qed.
+
+ Let wf_t_form : Form.wf t_form.
+ Proof.
+ destruct (Form.check_form_correct interp_form_hatom _ ch_form) as [H _]; destruct H; auto.
+ Qed.
+
+ Let wf_rho : Valuation.wf rho.
+ Proof.
+ destruct (Form.check_form_correct interp_form_hatom _ ch_form); auto.
+ Qed.
+
+ Lemma valid_C_true : C.interp rho C._true.
+ Proof.
+ apply C.interp_true.
+ destruct (Form.check_form_correct interp_form_hatom _ ch_form);trivial.
+ Qed.
+ Hint Resolve valid_C_true.
+
+ Local Notation interp := (Atom.interp t_i t_func t_atom).
+
+ Lemma wf_interp_form : forall x,
+ rho x = Form.interp interp_form_hatom t_form (t_form.[x]).
+ Proof.
+ destruct (Form.check_form_correct interp_form_hatom _ ch_form).
+ destruct H; intros x;rewrite Form.wf_interp_form;trivial.
+ Qed.
+
+ Local Notation get_type :=
+ (Atom.get_type t_i t_func t_atom).
+
+ Local Notation check_type :=
+ (Atom.check_aux t_i t_func get_type).
+
+ Lemma get_eq_interp :
+ forall (l:_lit) (f:Atom.hatom -> Atom.hatom -> C.t),
+ (forall xa, t_form.[Lit.blit l] = Form.Fatom xa ->
+ forall t a b, t_atom.[xa] = Atom.Abop (Atom.BO_eq t) a b ->
+ rho (Lit.blit l) =
+ Atom.interp_bool t_i
+ (Atom.apply_binop t_i t t Typ.Tbool (Typ.i_eqb t_i t)
+ (interp_hatom a) (interp_hatom b)) ->
+ Typ.eqb (get_type a) t -> Typ.eqb (get_type b) t ->
+ C.interp rho (f a b)) ->
+ C.interp rho (get_eq (Lit.blit l) f).
+ Proof.
+ intros l f Hf;unfold get_eq.
+ case_eq (t_form.[Lit.blit l]);trivial;intros.
+ case_eq (t_atom.[i]);trivial;intros.
+ destruct b;trivial.
+ generalize wt_t_atom;unfold Atom.wt;unfold is_true;
+ rewrite PArray.forallbi_spec;intros.
+ assert (i < length t_atom).
+ apply PArray.get_not_default_lt.
+ rewrite H0, def_t_atom;discriminate.
+ apply H1 in H2;clear H1;rewrite H0 in H2;simpl in H2.
+ rewrite !andb_true_iff in H2;decompose [and] H2;clear H2.
+ apply Hf with (2:= H0);trivial.
+ rewrite wf_interp_form, H;simpl.
+ unfold Atom.interp_form_hatom, Atom.interp_hatom at 1;simpl.
+ rewrite Atom.t_interp_wf, H0;simpl;trivial.
+ Qed.
+
+ Let tunicity : forall A T U, Typ.eqb A T -> Typ.eqb A U -> T = U.
+ Proof. intros A T U; rewrite !Typ.eqb_spec; intros; subst T U; auto. Qed.
+
+ Ltac tunicity :=
+ match goal with
+ | [ H1 : is_true (Typ.eqb ?a ?t1),
+ H2 : is_true (Typ.eqb ?a ?t2) |- _ ] =>
+ assert (W:= tunicity _ _ _ H1 H2);try subst
+ | _ => idtac
+ end.
+
+ Lemma interp_binop_eqb_sym :
+ forall u a b,
+ Atom.apply_binop t_i u u Typ.Tbool (Typ.i_eqb t_i u) a b =
+ Atom.apply_binop t_i u u Typ.Tbool (Typ.i_eqb t_i u) b a.
+ Proof.
+ unfold Atom.apply_binop;simpl;intros u (ta,va) (tb,vb).
+ destruct (Typ.cast ta u);destruct (Typ.cast tb u);trivial.
+ apply f_equal; apply eq_true_iff_eq.
+ match goal with |- ?x = _ <-> ?y = _ =>
+ change (is_true x <-> is_true y) end.
+ rewrite !Typ.i_eqb_spec;split;auto.
+ Qed.
+
+ Lemma interp_binop_eqb_trans:
+ forall u a b c,
+ Typ.eqb (get_type a) u -> Typ.eqb (get_type b) u -> Typ.eqb (get_type c) u ->
+ Atom.interp_bool t_i
+ (Atom.apply_binop t_i u u Typ.Tbool (Typ.i_eqb t_i u)
+ (interp_hatom a) (interp_hatom b)) ->
+ Atom.interp_bool t_i
+ (Atom.apply_binop t_i u u Typ.Tbool (Typ.i_eqb t_i u)
+ (interp_hatom b) (interp_hatom c)) ->
+ Atom.interp_bool t_i
+ (Atom.apply_binop t_i u u Typ.Tbool (Typ.i_eqb t_i u)
+ (interp_hatom a) (interp_hatom c)).
+ Proof.
+ intros u a b c Ha Hb Hc.
+ generalize (Atom.check_aux_interp_hatom _ t_func _ wf_t_atom a), (Atom.check_aux_interp_hatom _ t_func _ wf_t_atom b), (Atom.check_aux_interp_hatom _ t_func _ wf_t_atom c). rewrite Typ.eqb_spec in Ha. rewrite Typ.eqb_spec in Hb. rewrite Typ.eqb_spec in Hc. unfold Atom.get_type in Ha, Hb, Hc. rewrite Ha, Hb, Hc. intros [va HHa] [vb HHb] [vc HHc].
+ unfold Atom.interp_hatom.
+ rewrite HHa, HHb, HHc;simpl;rewrite Typ.cast_refl.
+ unfold Atom.interp_bool;simpl.
+ rewrite !Typ.i_eqb_spec;intros HH;rewrite HH;trivial.
+ Qed.
+
+ Lemma check_trans_aux_correct :
+ forall eqs u t1 t2 res c,
+ Typ.eqb (get_type t1) u -> Typ.eqb (get_type t2) u ->
+ Atom.interp_bool t_i (interp (Atom.Abop (Atom.BO_eq u) t1 t2)) \/
+ C.interp rho c ->
+ C.interp rho (check_trans_aux t1 t2 eqs res c).
+ Proof.
+ induction eqs;simpl;intros.
+ apply get_eq_interp;intros.
+ match goal with |- context [if ?b then _ else _] => case_eq b end;
+ intros;trivial.
+ simpl;rewrite Lit.interp_lit;unfold Var.interp.
+ destruct H1;[ | rewrite H1,orb_true_r;auto].
+ rewrite orb_true_iff, !andb_true_iff in H7;destruct H7 as
+ [[H7 H8] | [H7 H8]].
+ rewrite eqb_spec in H7. rewrite eqb_spec in H8. subst.
+ tunicity. rewrite H4, H1;auto.
+ rewrite eqb_spec in H7. rewrite eqb_spec in H8. subst.
+ tunicity;rewrite interp_binop_eqb_sym in H1;rewrite H4, H1;auto.
+ apply get_eq_interp;intros.
+ destruct (Int63Properties.reflect_eqb t2 b);subst;tunicity.
+ apply (IHeqs u);trivial.
+ simpl;unfold is_true;rewrite orb_true_iff.
+ rewrite Lit.interp_nlit;unfold Var.interp.
+ (* Attention ici on utilise la decidabilit'e de l'egalit'e sur u *)
+ case_eq (rho (Lit.blit a));[rewrite H4; intros | simpl;auto].
+ destruct H1;[left | auto].
+ apply interp_binop_eqb_trans with (4:= H1);trivial.
+ rewrite interp_binop_eqb_sym;trivial.
+ destruct (Int63Properties.reflect_eqb t2 a0); subst;tunicity.
+ apply (IHeqs u);trivial.
+ simpl;unfold is_true;rewrite orb_true_iff.
+ rewrite Lit.interp_nlit;unfold Var.interp.
+ (* Attention ici on utilise la decidabilit'e de l'egalit'e sur u *)
+ case_eq (rho (Lit.blit a));[rewrite H4; intros | simpl;auto].
+ destruct H1;[left | auto].
+ apply interp_binop_eqb_trans with (4:= H1);trivial.
+ destruct (Int63Properties.reflect_eqb t1 b);subst;tunicity.
+ apply (IHeqs u);trivial.
+ simpl;unfold is_true;rewrite orb_true_iff.
+ rewrite Lit.interp_nlit;unfold Var.interp.
+ (* Attention ici on utilise la decidabilit'e de l'egalit'e sur u *)
+ case_eq (rho (Lit.blit a));[rewrite H4; intros | simpl;auto].
+ destruct H1;[left | auto].
+ apply interp_binop_eqb_trans with (5:= H1);trivial.
+ destruct (Int63Properties.reflect_eqb t1 a0);[subst;tunicity|auto].
+ apply (IHeqs u);trivial.
+ simpl;unfold is_true;rewrite orb_true_iff.
+ rewrite Lit.interp_nlit;unfold Var.interp.
+ (* Attention ici on utilise la decidabilit'e de l'egalit'e sur u *)
+ case_eq (rho (Lit.blit a));[rewrite H4; intros | simpl;auto].
+ destruct H1;[left | auto].
+ apply interp_binop_eqb_trans with (5:= H1);trivial.
+ rewrite interp_binop_eqb_sym;trivial.
+ Qed.
+
+ Lemma valid_check_trans :
+ forall res eqs,
+ C.interp rho (check_trans res eqs).
+ Proof.
+ unfold check_trans;intros res [ | leq eqs].
+ apply get_eq_interp;intros.
+ destruct (Int63Properties.reflect_eqb a b).
+ unfold C.interp; simpl; rewrite orb_false_r.
+ unfold Lit.interp; simpl; rewrite Lit.is_pos_lit.
+ unfold Var.interp; simpl; rewrite Lit.blit_lit.
+ rewrite H1.
+ unfold Atom.interp_bool; simpl.
+ rewrite e; simpl.
+ generalize (Atom.check_aux_interp_hatom _ t_func _ wf_t_atom b). rewrite Typ.eqb_spec in H3. unfold Atom.get_type in H3. rewrite H3. intros [vb HHb].
+ unfold Atom.interp_hatom.
+ rewrite HHb;simpl;rewrite Typ.cast_refl;simpl.
+ rewrite !Typ.i_eqb_spec;trivial.
+ auto.
+ apply get_eq_interp;intros.
+ apply check_trans_aux_correct with t;trivial.
+ simpl;rewrite Lit.interp_nlit;unfold Var.interp. rewrite <- H1.
+ (* Attention ici on utilise la decidabilit'e de l'egalit'e sur t *)
+ destruct (rho (Lit.blit leq));auto.
+ Qed.
+
+ Inductive Forall2 A B (P:A->B->Prop) : list A -> list B -> Prop :=
+ | Forall2_nil : Forall2 A B P nil nil
+ | Forall2_cons :
+ forall a b la lb, P a b -> Forall2 A B P la lb ->
+ Forall2 A B P (a::la) (b::lb).
+
+ Lemma build_congr_correct : forall lp l r c,
+ (Forall2 _ _ (fun a b => interp_hatom a = interp_hatom b) l r -> C.interp rho c) ->
+ C.interp rho (build_congr lp l r c).
+ Proof.
+ induction lp;destruct l;destruct r;simpl;trivial;intros.
+ apply H;constructor.
+ destruct a.
+ apply get_eq_interp;intros.
+ match goal with |- context [if ?x then _ else _] =>
+ case_eq x;intros;auto end.
+ apply IHlp;simpl;intros.
+ rewrite Lit.interp_nlit;unfold Var.interp.
+ case_eq (rho (Lit.blit i1));intros;simpl;[ | auto].
+ apply H;constructor;trivial.
+ generalize (Atom.check_aux_interp_hatom _ t_func _ wf_t_atom a), (Atom.check_aux_interp_hatom _ t_func _ wf_t_atom b). rewrite Typ.eqb_spec in H3. rewrite Typ.eqb_spec in H4. unfold Atom.get_type in H3, H4. rewrite H3,H4. intros [va HHa] [vb HHb].
+ revert H7;rewrite H2;unfold Atom.apply_binop; simpl.
+ unfold Atom.interp_hatom.
+ rewrite HHa, HHb;simpl;rewrite Typ.cast_refl;simpl.
+ intros W;change (is_true (Typ.i_eqb t_i t va vb)) in W.
+ rewrite Typ.i_eqb_spec in W.
+ rewrite orb_true_iff, !andb_true_iff in H5;destruct H5 as
+ [ [H5 H7] | [H5 H7]].
+ rewrite eqb_spec in H5. rewrite eqb_spec in H7. subst.
+ rewrite HHa, HHb;trivial.
+ rewrite eqb_spec in H5. rewrite eqb_spec in H7. subst.
+ rewrite HHa, HHb;trivial.
+ destruct (Int63Properties.reflect_eqb i i0);[subst | auto].
+ apply IHlp;intros;apply H;constructor;auto.
+ Qed.
+
+ Lemma valid_check_congr :
+ forall leq eqs,
+ C.interp rho (check_congr leq eqs).
+ Proof.
+ unfold check_congr;intros leq eqs;apply get_eq_interp;intros.
+ case_eq (t_atom .[ a]);intros;auto;
+ case_eq (t_atom .[ b]);intros;auto.
+ (* uop *)
+ destruct (Atom.reflect_uop_eqb u u0);[subst | auto].
+ apply build_congr_correct;intros.
+ simpl;rewrite Lit.interp_lit, orb_false_r;unfold Var.interp.
+ rewrite H1.
+ generalize (Atom.check_aux_interp_hatom _ t_func _ wf_t_atom a), (Atom.check_aux_interp_hatom _ t_func _ wf_t_atom b). rewrite Typ.eqb_spec in H2. rewrite Typ.eqb_spec in H3. unfold Atom.get_type in H2, H3. rewrite H2,H3. intros [va HHa] [vb HHb].
+ unfold Atom.apply_binop;unfold Atom.interp_hatom;simpl.
+ rewrite HHb, HHa. simpl.
+ rewrite Atom.t_interp_wf in HHa; auto. rewrite H4 in HHa. simpl in HHa.
+ rewrite Atom.t_interp_wf in HHb; auto. rewrite H5 in HHb. simpl in HHb.
+ rewrite Typ.cast_refl;simpl.
+ assert (Atom.Bval t_i t va = Atom.Bval t_i t vb).
+ inversion H6;subst.
+ unfold Atom.interp_hatom in H10.
+ rewrite <- HHa; rewrite <- HHb, H10;trivial.
+ rewrite Typ.i_eqb_spec.
+ inversion H7.
+ apply Eqdep_dec.inj_pair2_eq_dec in H9;trivial.
+ intros x y;destruct (Typ.reflect_eqb x y);auto.
+ (* bop *)
+ destruct (Atom.reflect_bop_eqb b0 b1);[subst | auto].
+ apply build_congr_correct;intros.
+ simpl;rewrite Lit.interp_lit, orb_false_r;unfold Var.interp.
+ rewrite H1.
+ generalize (Atom.check_aux_interp_hatom _ t_func _ wf_t_atom a), (Atom.check_aux_interp_hatom _ t_func _ wf_t_atom b). rewrite Typ.eqb_spec in H2. rewrite Typ.eqb_spec in H3. unfold Atom.get_type in H2, H3. rewrite H2,H3. intros [va HHa] [vb HHb].
+ unfold Atom.apply_binop. unfold Atom.interp_hatom;simpl.
+ rewrite HHb, HHa;simpl.
+ rewrite Atom.t_interp_wf in HHa; auto. rewrite H4 in HHa. simpl in HHa.
+ rewrite Atom.t_interp_wf in HHb; auto. rewrite H5 in HHb. simpl in HHb.
+ rewrite Typ.cast_refl;simpl.
+ assert (Atom.Bval t_i t va = Atom.Bval t_i t vb).
+ inversion H6;clear H6;subst.
+ inversion H12;clear H12;subst.
+ unfold Atom.interp_hatom in H10, H8.
+ rewrite <- HHa. rewrite <- HHb, H10, H8;trivial.
+ rewrite Typ.i_eqb_spec.
+ inversion H7.
+ apply Eqdep_dec.inj_pair2_eq_dec in H9;trivial.
+ intros x y;destruct (Typ.reflect_eqb x y);auto.
+ (* op *)
+ destruct (Int63Properties.reflect_eqb i i0);[subst | auto].
+ apply build_congr_correct;intros.
+ simpl;rewrite Lit.interp_lit, orb_false_r;unfold Var.interp.
+ rewrite H1.
+ generalize (Atom.check_aux_interp_hatom _ t_func _ wf_t_atom a), (Atom.check_aux_interp_hatom _ t_func _ wf_t_atom b). rewrite Typ.eqb_spec in H2. rewrite Typ.eqb_spec in H3. unfold Atom.get_type in H2, H3. rewrite H2,H3. intros [va HHa] [vb HHb].
+ unfold Atom.apply_binop;unfold Atom.interp_hatom;simpl.
+ rewrite HHb, HHa;simpl.
+ rewrite Atom.t_interp_wf in HHa; auto. rewrite H4 in HHa. simpl in HHa.
+ rewrite Atom.t_interp_wf in HHb; auto. rewrite H5 in HHb. simpl in HHb.
+ rewrite Typ.cast_refl;simpl.
+ assert (Atom.Bval t_i t va = Atom.Bval t_i t vb).
+ rewrite <- HHa;rewrite <- HHb;destruct (t_func.[i0]).
+ apply f_equal;clear HHa HHb va vb H5 H4.
+ induction H6;simpl;trivial.
+ unfold Atom.interp_hatom in H4.
+ rewrite IHForall2, H4;trivial.
+ rewrite Typ.i_eqb_spec.
+ inversion H7.
+ apply Eqdep_dec.inj_pair2_eq_dec in H9;trivial.
+ intros x y;destruct (Typ.reflect_eqb x y);auto.
+ Qed.
+
+ Lemma valid_check_congr_pred :
+ forall lpa lpb eqs,
+ C.interp rho (check_congr_pred lpa lpb eqs).
+ Proof.
+ unfold check_congr_pred;intros.
+ case_eq (t_form.[Lit.blit lpa]);auto.
+ case_eq (t_form.[Lit.blit lpb]);auto;intros.
+ case_eq (t_atom.[i0]);auto; case_eq (t_atom.[i]);auto;intros.
+ (* uop *)
+ destruct (Atom.reflect_uop_eqb u0 u);[subst | auto].
+ apply build_congr_correct;simpl;intros.
+ rewrite orb_false_r, Lit.interp_lit, Lit.interp_nlit;unfold Var.interp.
+ replace (rho (Lit.blit lpb)) with (rho (Lit.blit lpa)).
+ destruct (rho (Lit.blit lpa));reflexivity.
+ rewrite !wf_interp_form, H, H0;simpl.
+ generalize wt_t_atom;unfold Atom.wt;unfold is_true;
+ rewrite PArray.forallbi_spec;intros.
+ assert (i < length t_atom).
+ apply PArray.get_not_default_lt.
+ rewrite H1, def_t_atom;discriminate.
+ assert (i0 < length t_atom).
+ apply PArray.get_not_default_lt.
+ rewrite H2, def_t_atom;discriminate.
+ apply H4 in H5;apply H4 in H6;clear H4.
+ unfold Atom.interp_form_hatom, Atom.interp_hatom;simpl.
+ rewrite !Atom.t_interp_wf, H1, H2;simpl;trivial.
+ apply f_equal;apply f_equal.
+ inversion H3;clear H3;subst;trivial.
+
+ (* bop *)
+ destruct (Atom.reflect_bop_eqb b0 b);[subst | auto].
+ apply build_congr_correct;simpl;intros.
+ rewrite orb_false_r, Lit.interp_lit, Lit.interp_nlit;unfold Var.interp.
+ replace (rho (Lit.blit lpb)) with (rho (Lit.blit lpa)).
+ destruct (rho (Lit.blit lpa));reflexivity.
+ rewrite !wf_interp_form, H, H0;simpl.
+ generalize wt_t_atom;unfold Atom.wt;unfold is_true;
+ rewrite PArray.forallbi_spec;intros.
+ assert (i < length t_atom).
+ apply PArray.get_not_default_lt.
+ rewrite H1, def_t_atom. discriminate.
+ assert (i0 < length t_atom).
+ apply PArray.get_not_default_lt.
+ rewrite H2, def_t_atom;discriminate.
+ apply H4 in H5;apply H4 in H6;clear H4.
+ unfold Atom.interp_form_hatom, Atom.interp_hatom;simpl.
+ rewrite !Atom.t_interp_wf, H1, H2;simpl;trivial.
+ inversion H3;clear H3;subst.
+ inversion H11;clear H11;subst.
+ apply f_equal; apply f_equal2;trivial.
+
+ (* op *)
+ destruct (Int63Properties.reflect_eqb i2 i1);[subst | auto].
+ apply build_congr_correct;simpl;intros.
+ rewrite orb_false_r, Lit.interp_lit, Lit.interp_nlit;unfold Var.interp.
+ replace (rho (Lit.blit lpb)) with (rho (Lit.blit lpa)).
+ destruct (rho (Lit.blit lpa));reflexivity.
+ rewrite !wf_interp_form, H, H0;simpl.
+ generalize wt_t_atom;unfold Atom.wt;unfold is_true;
+ rewrite PArray.forallbi_spec;intros.
+ assert (i < length t_atom).
+ apply PArray.get_not_default_lt.
+ rewrite H1, def_t_atom;discriminate.
+ assert (i0 < length t_atom).
+ apply PArray.get_not_default_lt.
+ rewrite H2, def_t_atom;discriminate.
+ apply H4 in H5;apply H4 in H6;clear H4.
+ unfold Atom.interp_form_hatom, Atom.interp_hatom;simpl.
+ rewrite !Atom.t_interp_wf, H1, H2;simpl;trivial.
+ apply f_equal;destruct (t_func.[i1]);apply f_equal.
+ clear H H0 H1 H2 H5 H6.
+ induction H3;simpl;trivial.
+ unfold Atom.interp_hatom in H;rewrite H, IHForall2;trivial.
+ Qed.
+
+ End Proof.
+
+End certif.
diff --git a/src/extraction/Extract.v b/src/extraction/Extract.v
new file mode 100644
index 0000000..1161f48
--- /dev/null
+++ b/src/extraction/Extract.v
@@ -0,0 +1,26 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+
+Require Int63Native.
+Require Import ExtractNative.
+Require Import SMTCoq.
+
+Extract Constant Int63Native.eqb => "fun i j -> ExtrNative.compare i j = ExtrNative.Eq".
+
+Set Extraction AccessOpaque.
+
+Extraction "extraction/sat_checker.ml" Sat_Checker.checker.
+Extraction "extraction/smt_checker.ml" Euf_Checker.checker_ext.
diff --git a/src/extraction/Makefile b/src/extraction/Makefile
new file mode 100644
index 0000000..07a30dd
--- /dev/null
+++ b/src/extraction/Makefile
@@ -0,0 +1,47 @@
+# List of user's files and name of the final program (edit this part)
+
+USERFILES=test.ml
+PROGRAM=test
+# USERFILES=../../../../examples/example.ml
+# PROGRAM=../../../../examples/example
+
+
+# Compilation
+
+COQTOP=$(COQBIN)../
+
+FLAGS=-rectypes
+COMPILEFLAGS=-cclib -lunix
+
+SMTLIB=-I .. -I ../zchaff -I ../verit -I ../trace -I ../lia -I ../euf -I ../cnf
+COQLIB=-I ${COQTOP}kernel -I ${COQTOP}lib -I ${COQTOP}library -I ${COQTOP}parsing -I ${COQTOP}pretyping -I ${COQTOP}interp -I ${COQTOP}proofs -I ${COQTOP}tactics -I ${COQTOP}toplevel -I ${COQTOP}plugins/btauto -I ${COQTOP}plugins/cc -I ${COQTOP}plugins/decl_mode -I ${COQTOP}plugins/extraction -I ${COQTOP}plugins/field -I ${COQTOP}plugins/firstorder -I ${COQTOP}plugins/fourier -I ${COQTOP}plugins/funind -I ${COQTOP}plugins/micromega -I ${COQTOP}plugins/nsatz -I ${COQTOP}plugins/omega -I ${COQTOP}plugins/quote -I ${COQTOP}plugins/ring -I ${COQTOP}plugins/romega -I ${COQTOP}plugins/rtauto -I ${COQTOP}plugins/setoid_ring -I ${COQTOP}plugins/syntax -I ${COQTOP}plugins/xml -I /usr/lib/ocaml/camlp5
+
+CMXA=nums.cmxa str.cmxa unix.cmxa gramlib.cmxa dynlink.cmxa ${COQTOP}kernel/byterun/coq_fix_code.o ${COQTOP}kernel/byterun/coq_interp.o ${COQTOP}kernel/byterun/coq_memory.o ${COQTOP}kernel/byterun/coq_values.o clib.cmxa lib.cmxa kernel.cmxa library.cmxa pretyping.cmxa interp.cmxa proofs.cmxa parsing.cmxa tactics.cmxa toplevel.cmxa micromega_plugin.cmxa smtcoq.cmxa
+CMI=extrNative.cmi sat_checker.cmi smt_checker.cmi
+CMX=extrNative.cmx sat_checker.cmx zchaff_checker.cmx smt_checker.cmx verit_checker.cmx
+USERCMX=$(USERFILES:.ml=.cmx)
+
+OCAMLC=ocamlc
+OCAMLOPT=ocamlopt
+
+
+all: $(PROGRAM)
+
+%.cmi: %.mli
+ $(OCAMLC) -c $(FLAGS) $(SMTLIB) $(COQLIB) $<
+
+%.cmx: %.ml
+ $(OCAMLOPT) -c $(FLAGS) $(SMTLIB) $(COQLIB) $<
+
+$(PROGRAM): $(CMI) $(CMX) $(USERCMX)
+ $(OCAMLOPT) $(FLAGS) $(SMTLIB) $(COQLIB) -o $@ $(COMPILEFLAGS) $(CMXA) $(CMX) $(USERCMX)
+
+
+.PHONY: clean mrproper
+
+
+clean:
+ rm -f *.cmi *.cmx *.o
+
+mrproper: clean
+ rm -rf $(PROGRAM)
diff --git a/src/extraction/extrNative.ml b/src/extraction/extrNative.ml
new file mode 100644
index 0000000..4d56287
--- /dev/null
+++ b/src/extraction/extrNative.ml
@@ -0,0 +1,332 @@
+type comparison = Eq | Lt | Gt
+
+type 'a carry = C0 of 'a | C1 of 'a
+
+type uint = int
+
+ (* to be used only on 32 bits achitectures *)
+let maxuint31 = Int32.of_string "0x7FFFFFFF"
+let uint_32 i = Int32.logand (Int32.of_int i) maxuint31
+
+let select f32 f64 = if Sys.word_size = 64 then f64 else f32
+
+ (* conversion to an int *)
+let to_int i = i
+
+let of_int_32 i = i
+let of_int_64 i = i land 0x7FFFFFFF
+
+let of_int = select of_int_32 of_int_64
+let of_uint i = i
+
+ (* convertion of an uint31 to a string *)
+let to_string_32 i = Int32.to_string (uint_32 i)
+let to_string_64 = string_of_int
+
+let to_string = select to_string_32 to_string_64
+let of_string s =
+ let i32 = Int32.of_string s in
+ if Int32.compare Int32.zero i32 <= 0
+ && Int32.compare i32 maxuint31 <= 0
+ then Int32.to_int i32
+ else raise (Failure "int_of_string")
+
+
+
+ (* logical shift *)
+let l_sl x y =
+ of_int (if 0 <= y && y < 31 then x lsl y else 0)
+
+let l_sr x y =
+ if 0 <= y && y < 31 then x lsr y else 0
+
+let l_and x y = x land y
+let l_or x y = x lor y
+let l_xor x y = x lxor y
+
+ (* addition of int31 *)
+let add x y = of_int (x + y)
+
+ (* subtraction *)
+let sub x y = of_int (x - y)
+
+ (* multiplication *)
+let mul x y = of_int (x * y)
+
+ (* exact multiplication *)
+let mulc_32 x y =
+ let x = Int64.of_int32 (uint_32 x) in
+ let y = Int64.of_int32 (uint_32 y) in
+ let m = Int64.mul x y in
+ let l = Int64.to_int m in
+ let h = Int64.to_int (Int64.shift_right_logical m 31) in
+ h,l
+
+let mulc_64 x y =
+ let m = x * y in
+ let l = of_int_64 m in
+ let h = of_int_64 (m lsr 31) in
+ h, l
+let mulc = select mulc_32 mulc_64
+
+ (* division *)
+let div_32 x y =
+ if y = 0 then 0 else
+ Int32.to_int (Int32.div (uint_32 x) (uint_32 y))
+let div_64 x y = if y = 0 then 0 else x / y
+let div = select div_32 div_64
+
+ (* modulo *)
+let rem_32 x y =
+ if y = 0 then 0
+ else Int32.to_int (Int32.rem (uint_32 x) (uint_32 y))
+let rem_64 x y = if y = 0 then 0 else x mod y
+let rem = select rem_32 rem_64
+
+ (* division of two numbers by one *)
+let div21_32 xh xl y =
+ if y = 0 then (0,0)
+ else
+ let x =
+ Int64.logor
+ (Int64.shift_left (Int64.of_int32 (uint_32 xh)) 31)
+ (Int64.of_int32 (uint_32 xl)) in
+ let y = Int64.of_int32 (uint_32 y) in
+ let q = Int64.div x y in
+ let r = Int64.rem x y in
+ Int64.to_int q, Int64.to_int r
+let div21_64 xh xl y =
+ if y = 0 then (0,0)
+ else
+ let x = (xh lsl 31) lor xl in
+ let q = x / y in
+ let r = x mod y in
+ q, r
+let div21 = select div21_32 div21_64
+
+ (* comparison *)
+let lt_32 x y = (x lxor 0x40000000) < (y lxor 0x40000000)
+(* if 0 <= x then
+ if 0 <= y then x < y
+ else true
+ else if 0 <= y then false
+ else x < y *)
+(* Int32.compare (uint_32 x) (uint_32 y) < 0 *)
+
+let lt_64 x y = x < y
+let lt = select lt_32 lt_64
+
+let le_32 x y =
+ (x lxor 0x40000000) <= (y lxor 0x40000000)
+(*
+ if 0 <= x then
+ if 0 <= y then x <= y
+ else true
+ else if 0 <= y then false
+ else x <= y
+*)
+(*Int32.compare (uint_32 x) (uint_32 y) <= 0*)
+let le_64 x y = x <= y
+let le = select le_32 le_64
+
+let eq x y = x == y
+
+let cmp_32 x y = Int32.compare (uint_32 x) (uint_32 y)
+let cmp_64 x y = compare x y
+let compare = select cmp_32 cmp_64
+
+let compare x y =
+ match compare x y with
+ | x when x < 0 -> Lt
+ | 0 -> Eq
+ | _ -> Gt
+
+ (* head tail *)
+
+let head0 x =
+ let r = ref 0 in
+ let x = ref x in
+ if !x land 0x7FFF0000 = 0 then r := !r + 15
+ else x := !x lsr 15;
+ if !x land 0xFF00 = 0 then (x := !x lsl 8; r := !r + 8);
+ if !x land 0xF000 = 0 then (x := !x lsl 4; r := !r + 4);
+ if !x land 0xC000 = 0 then (x := !x lsl 2; r := !r + 2);
+ if !x land 0x8000 = 0 then (x := !x lsl 1; r := !r + 1);
+ if !x land 0x8000 = 0 then ( r := !r + 1);
+ !r;;
+
+let tail0 x =
+ let r = ref 0 in
+ let x = ref x in
+ if !x land 0xFFFF = 0 then (x := !x lsr 16; r := !r + 16);
+ if !x land 0xFF = 0 then (x := !x lsr 8; r := !r + 8);
+ if !x land 0xF = 0 then (x := !x lsr 4; r := !r + 4);
+ if !x land 0x3 = 0 then (x := !x lsr 2; r := !r + 2);
+ if !x land 0x1 = 0 then ( r := !r + 1);
+ !r
+
+let addc x y =
+ let s = add x y in
+ if lt s x then C1 s else C0 s
+
+let addcarryc x y =
+ let s = add (x+1) y in
+ if le s x then C1 s else C0 s
+
+let subc x y =
+ let s = sub x y in
+ if lt x y then C1 s else C0 s
+
+let subcarryc x y =
+ let s = sub (x-1) y in
+ if le x y then C1 s else C0 s
+
+let diveucl x y = div x y, rem x y
+
+let diveucl_21 = div21
+
+let addmuldiv p i j =
+ let p' = to_int p in
+ of_uint (l_or
+ (l_sl i p)
+ (l_sr j (of_int (31 - p'))))
+
+let rec foldi_cont f min max cont a =
+ if lt min max then f min (foldi_cont f (add min 1) max cont) a
+ else if min = max then f min cont a
+ else cont a
+
+let rec foldi_down_cont f max min cont a =
+ if lt min max then
+ f max (foldi_down_cont f (sub max 1) min cont) a
+ else if min = max then f min cont a
+ else cont a
+
+let print_uint x =
+ Printf.fprintf stderr "%s" (to_string x);
+ flush stderr;
+ x
+
+(* Les Tableaux maintenant *)
+
+let max_array_length32 = 4194303 (* Sys.max_array_length on arch32 *)
+
+type 'a parray = ('a kind) ref
+and 'a kind =
+ | Array of 'a array
+ (* | Matrix of 'a array array *)
+ | Updated of int * 'a * 'a parray
+
+let of_array t = ref (Array t)
+
+let parray_make n def =
+ let n = to_int n in
+ let n =
+ if 0 <= n && n < max_array_length32 then n + 1
+ else max_array_length32 in
+ ref (Array (Array.make n def))
+
+let rec get_updated p n =
+ match !p with
+ | Array t ->
+ let l = Array.length t in
+ if 0 <= n && n < l then Array.unsafe_get t n
+ else (Array.unsafe_get t (l-1))
+ | Updated (k,e,p) -> if n = k then e else get_updated p n
+
+let parray_get p n =
+ let n = to_int n in
+ match !p with
+ | Array t ->
+ let l = Array.length t in
+ if 0 <= n && n < l then Array.unsafe_get t n
+ else (Array.unsafe_get t (l-1))
+ | Updated _ -> get_updated p n
+
+
+let rec default_updated p =
+ match !p with
+ | Array t -> Array.unsafe_get t (Array.length t - 1)
+ | Updated (_,_,p) -> default_updated p
+
+let parray_default p =
+ match !p with
+ | Array t -> Array.unsafe_get t (Array.length t - 1)
+ | Updated (_,_,p) -> default_updated p
+
+let rec length p =
+ match !p with
+ | Array t -> of_int (Array.length t - 1) (* The default value *)
+ | Updated (_, _, p) -> length p
+
+let parray_length p =
+ match !p with
+ | Array t -> of_int (Array.length t - 1)
+ | Updated (_, _, p) -> length p
+
+let parray_set p n e =
+ let kind = !p in
+ let n = to_int n in
+ match kind with
+ | Array t ->
+ if 0 <= n && n < Array.length t - 1 then
+ let res = ref kind in
+ p := Updated (n, Array.unsafe_get t n, res);
+ Array.unsafe_set t n e;
+ res
+ else p
+ | Updated _ ->
+ if 0 <= n && n < to_int (parray_length p) then
+ ref (Updated(n, e, p))
+ else p
+
+
+let rec copy_updated p =
+ match !p with
+ | Array t -> Array.copy t
+ | Updated (n,e,p) ->
+ let t = copy_updated p in
+ Array.unsafe_set t n e; t
+
+let parray_copy p =
+ let t =
+ match !p with
+ | Array t -> Array.copy t
+ | Updated _ -> copy_updated p in
+ ref (Array t)
+
+let rec rerootk t k =
+ match !t with
+ | Array _ -> k ()
+ | Updated (i, v, t') ->
+ let k' () =
+ begin match !t' with
+ | Array a as n ->
+ let v' = a.(i) in
+ a.(i) <- v;
+ t := n;
+ t' := Updated (i, v', t)
+ | Updated _ -> assert false
+ end; k() in
+ rerootk t' k'
+
+let parray_reroot t = rerootk t (fun () -> t)
+
+let parray_init n f def =
+ let n = to_int n in
+ let n =
+ if 0 <= n && n < max_array_length32 then n + 1
+ else max_array_length32 in
+ let t = Array.make n def in
+ for i = 0 to n - 2 do Array.unsafe_set t i (f i) done;
+ ref (Array t)
+
+let parray_map f p =
+ match !p with
+ | Array t -> ref (Array (Array.map f t))
+ | _ ->
+ let len = to_int (length p) in
+ ref (Array
+ (Array.init (len + 1)
+ (fun i -> f (parray_get p (of_int i)))))
+
diff --git a/src/extraction/extrNative.mli b/src/extraction/extrNative.mli
new file mode 100644
index 0000000..14eff5f
--- /dev/null
+++ b/src/extraction/extrNative.mli
@@ -0,0 +1,67 @@
+type comparison = Eq | Lt | Gt
+type 'a carry = C0 of 'a | C1 of 'a
+
+(*s Unsigned Int *)
+type uint
+
+(* Conversion with int *)
+val to_int : uint -> int
+val of_int : int -> uint
+val of_uint : int -> uint
+
+(* Conversion with string *)
+val to_string : uint -> string
+val of_string : string -> uint
+
+(* logical operations *)
+val l_sl : uint -> uint -> uint
+val l_sr : uint -> uint -> uint
+val l_and : uint -> uint -> uint
+val l_or : uint -> uint -> uint
+val l_xor : uint -> uint -> uint
+
+(* arithmetic operations *)
+val add : uint -> uint -> uint
+val sub : uint -> uint -> uint
+val mul : uint -> uint -> uint
+val mulc : uint -> uint -> uint * uint
+val div : uint -> uint -> uint
+val rem : uint -> uint -> uint
+
+val lt : uint -> uint -> bool
+val le : uint -> uint -> bool
+val eq : uint -> uint -> bool
+val compare : uint -> uint -> comparison
+
+val head0 : uint -> uint
+val tail0 : uint -> uint
+
+val addc : uint -> uint -> uint carry
+val addcarryc : uint -> uint -> uint carry
+val subc : uint -> uint -> uint carry
+val subcarryc : uint -> uint -> uint carry
+val diveucl : uint -> uint -> uint * uint
+val diveucl_21 : uint -> uint -> uint -> uint * uint
+val addmuldiv : uint -> uint -> uint -> uint
+
+val foldi_cont :
+ (uint -> ('a -> 'b) -> 'a -> 'b) -> uint -> uint -> ('a -> 'b) -> 'a -> 'b
+val foldi_down_cont :
+ (uint -> ('a -> 'b) -> 'a -> 'b) -> uint -> uint -> ('a -> 'b) -> 'a -> 'b
+val print_uint : uint -> uint
+
+
+(*s Persistant array *)
+
+type 'a parray
+
+val of_array : 'a array -> 'a parray
+
+val parray_make : uint -> 'a -> 'a parray
+val parray_get : 'a parray -> uint -> 'a
+val parray_default : 'a parray -> 'a
+val parray_length : 'a parray -> uint
+val parray_set : 'a parray -> uint -> 'a -> 'a parray
+val parray_copy : 'a parray -> 'a parray
+val parray_reroot : 'a parray -> 'a parray
+
diff --git a/src/extraction/sat_checker.ml b/src/extraction/sat_checker.ml
new file mode 100644
index 0000000..59635e0
--- /dev/null
+++ b/src/extraction/sat_checker.ml
@@ -0,0 +1,431 @@
+(** val negb : bool -> bool **)
+
+let negb = function
+| true -> false
+| false -> true
+
+type 'a list =
+| Nil
+| Cons of 'a * 'a list
+
+(** val existsb : ('a1 -> bool) -> 'a1 list -> bool **)
+
+let rec existsb f = function
+| Nil -> false
+| Cons (a, l0) -> if f a then true else existsb f l0
+
+type int = ExtrNative.uint
+
+(** val lsl0 : int -> int -> int **)
+
+let lsl0 = ExtrNative.l_sl
+
+(** val lsr0 : int -> int -> int **)
+
+let lsr0 = ExtrNative.l_sr
+
+(** val land0 : int -> int -> int **)
+
+let land0 = ExtrNative.l_and
+
+(** val lxor0 : int -> int -> int **)
+
+let lxor0 = ExtrNative.l_xor
+
+(** val sub : int -> int -> int **)
+
+let sub = ExtrNative.sub
+
+(** val eqb : int -> int -> bool **)
+
+let eqb = fun i j -> ExtrNative.compare i j = ExtrNative.Eq
+
+(** val foldi_cont :
+ (int -> ('a1 -> 'a2) -> 'a1 -> 'a2) -> int -> int -> ('a1 -> 'a2) -> 'a1
+ -> 'a2 **)
+
+let foldi_cont = ExtrNative.foldi_cont
+
+(** val foldi_down_cont :
+ (int -> ('a1 -> 'a2) -> 'a1 -> 'a2) -> int -> int -> ('a1 -> 'a2) -> 'a1
+ -> 'a2 **)
+
+let foldi_down_cont = ExtrNative.foldi_down_cont
+
+(** val is_zero : int -> bool **)
+
+let is_zero i =
+ eqb i (ExtrNative.of_uint(0))
+
+(** val is_even : int -> bool **)
+
+let is_even i =
+ is_zero (land0 i (ExtrNative.of_uint(1)))
+
+(** val compare : int -> int -> ExtrNative.comparison **)
+
+let compare = ExtrNative.compare
+
+(** val foldi : (int -> 'a1 -> 'a1) -> int -> int -> 'a1 -> 'a1 **)
+
+let foldi f from to0 =
+ foldi_cont (fun i cont a -> cont (f i a)) from to0 (fun a -> a)
+
+(** val foldi_down : (int -> 'a1 -> 'a1) -> int -> int -> 'a1 -> 'a1 **)
+
+let foldi_down f from downto0 =
+ foldi_down_cont (fun i cont a -> cont (f i a)) from downto0 (fun a -> a)
+
+type 'a array = 'a ExtrNative.parray
+
+(** val make : int -> 'a1 -> 'a1 array **)
+
+let make = ExtrNative.parray_make
+
+module Coq__1 = struct
+ (** val get : 'a1 array -> int -> 'a1 **)
+
+ let get = ExtrNative.parray_get
+end
+let get = Coq__1.get
+
+(** val set : 'a1 array -> int -> 'a1 -> 'a1 array **)
+
+let set = ExtrNative.parray_set
+
+(** val length : 'a1 array -> int **)
+
+let length = ExtrNative.parray_length
+
+(** val to_list : 'a1 array -> 'a1 list **)
+
+let to_list t0 =
+ let len = length t0 in
+ if eqb (ExtrNative.of_uint(0)) len
+ then Nil
+ else foldi_down (fun i l -> Cons ((get t0 i), l))
+ (sub len (ExtrNative.of_uint(1))) (ExtrNative.of_uint(0)) Nil
+
+(** val fold_left : ('a1 -> 'a2 -> 'a1) -> 'a1 -> 'a2 array -> 'a1 **)
+
+let fold_left f a t0 =
+ let len = length t0 in
+ if eqb (ExtrNative.of_uint(0)) len
+ then a
+ else foldi (fun i a0 -> f a0 (get t0 i)) (ExtrNative.of_uint(0))
+ (sub (length t0) (ExtrNative.of_uint(1))) a
+
+(** val foldi_right :
+ (int -> 'a1 -> 'a2 -> 'a2) -> 'a1 array -> 'a2 -> 'a2 **)
+
+let foldi_right f t0 b =
+ let len = length t0 in
+ if eqb (ExtrNative.of_uint(0)) len
+ then b
+ else foldi_down (fun i b0 -> f i (get t0 i) b0)
+ (sub len (ExtrNative.of_uint(1))) (ExtrNative.of_uint(0)) b
+
+module Valuation =
+ struct
+ type t = int -> bool
+ end
+
+module Var =
+ struct
+ (** val _true : int **)
+
+ let _true =
+ (ExtrNative.of_uint(0))
+
+ (** val _false : int **)
+
+ let _false =
+ (ExtrNative.of_uint(1))
+
+ (** val interp : Valuation.t -> int -> bool **)
+
+ let interp rho x =
+ rho x
+ end
+
+module Lit =
+ struct
+ (** val is_pos : int -> bool **)
+
+ let is_pos l =
+ is_even l
+
+ (** val blit : int -> int **)
+
+ let blit l =
+ lsr0 l (ExtrNative.of_uint(1))
+
+ (** val lit : int -> int **)
+
+ let lit x =
+ lsl0 x (ExtrNative.of_uint(1))
+
+ (** val neg : int -> int **)
+
+ let neg l =
+ lxor0 l (ExtrNative.of_uint(1))
+
+ (** val nlit : int -> int **)
+
+ let nlit x =
+ neg (lit x)
+
+ (** val _true : int **)
+
+ let _true =
+ (ExtrNative.of_uint(0))
+
+ (** val _false : int **)
+
+ let _false =
+ (ExtrNative.of_uint(2))
+
+ (** val eqb : int -> int -> bool **)
+
+ let eqb l l' =
+ eqb l l'
+
+ (** val interp : Valuation.t -> int -> bool **)
+
+ let interp rho l =
+ if is_pos l
+ then Var.interp rho (blit l)
+ else negb (Var.interp rho (blit l))
+ end
+
+module C =
+ struct
+ type t = int list
+
+ (** val interp : Valuation.t -> t -> bool **)
+
+ let interp rho l =
+ existsb (Lit.interp rho) l
+
+ (** val _true : t **)
+
+ let _true =
+ Cons (Lit._true, Nil)
+
+ (** val is_false : t -> bool **)
+
+ let is_false = function
+ | Nil -> true
+ | Cons (i, l) -> false
+
+ (** val or_aux : (t -> t -> t) -> int -> t -> t -> int list **)
+
+ let rec or_aux or0 l1 c1 c2 = match c2 with
+ | Nil -> Cons (l1, c1)
+ | Cons (l2, c2') ->
+ (match compare l1 l2 with
+ | ExtrNative.Eq -> Cons (l1, (or0 c1 c2'))
+ | ExtrNative.Lt -> Cons (l1, (or0 c1 c2))
+ | ExtrNative.Gt -> Cons (l2, (or_aux or0 l1 c1 c2')))
+
+ (** val coq_or : t -> t -> t **)
+
+ let rec coq_or c1 c2 =
+ match c1 with
+ | Nil -> c2
+ | Cons (l1, c3) ->
+ (match c2 with
+ | Nil -> c1
+ | Cons (l2, c2') ->
+ (match compare l1 l2 with
+ | ExtrNative.Eq -> Cons (l1, (coq_or c3 c2'))
+ | ExtrNative.Lt -> Cons (l1, (coq_or c3 c2))
+ | ExtrNative.Gt -> Cons (l2, (or_aux coq_or l1 c3 c2'))))
+
+ (** val resolve_aux : (t -> t -> t) -> int -> t -> t -> t **)
+
+ let rec resolve_aux resolve0 l1 c1 c2 = match c2 with
+ | Nil -> _true
+ | Cons (l2, c2') ->
+ (match compare l1 l2 with
+ | ExtrNative.Eq -> Cons (l1, (resolve0 c1 c2'))
+ | ExtrNative.Lt ->
+ if eqb (lxor0 l1 l2) (ExtrNative.of_uint(1))
+ then coq_or c1 c2'
+ else Cons (l1, (resolve0 c1 c2))
+ | ExtrNative.Gt ->
+ if eqb (lxor0 l1 l2) (ExtrNative.of_uint(1))
+ then coq_or c1 c2'
+ else Cons (l2, (resolve_aux resolve0 l1 c1 c2')))
+
+ (** val resolve : t -> t -> t **)
+
+ let rec resolve c1 c2 =
+ match c1 with
+ | Nil -> _true
+ | Cons (l1, c3) ->
+ (match c2 with
+ | Nil -> _true
+ | Cons (l2, c2') ->
+ (match compare l1 l2 with
+ | ExtrNative.Eq -> Cons (l1, (resolve c3 c2'))
+ | ExtrNative.Lt ->
+ if eqb (lxor0 l1 l2) (ExtrNative.of_uint(1))
+ then coq_or c3 c2'
+ else Cons (l1, (resolve c3 c2))
+ | ExtrNative.Gt ->
+ if eqb (lxor0 l1 l2) (ExtrNative.of_uint(1))
+ then coq_or c3 c2'
+ else Cons (l2, (resolve_aux resolve l1 c3 c2'))))
+ end
+
+module S =
+ struct
+ type t = C.t array
+
+ (** val get : t -> int -> C.t **)
+
+ let get s cid =
+ get s cid
+
+ (** val internal_set : t -> int -> C.t -> t **)
+
+ let internal_set s cid c =
+ set s cid c
+
+ (** val make : int -> t **)
+
+ let make nclauses =
+ make nclauses C._true
+
+ (** val insert : int -> int list -> int list **)
+
+ let rec insert l1 c = match c with
+ | Nil -> Cons (l1, Nil)
+ | Cons (l2, c') ->
+ (match compare l1 l2 with
+ | ExtrNative.Eq -> c
+ | ExtrNative.Lt ->
+ if eqb (lxor0 l1 l2) (ExtrNative.of_uint(1))
+ then C._true
+ else Cons (l1, c)
+ | ExtrNative.Gt ->
+ if eqb (lxor0 l1 l2) (ExtrNative.of_uint(1))
+ then C._true
+ else Cons (l2, (insert l1 c')))
+
+ (** val sort_uniq : int list -> int list **)
+
+ let rec sort_uniq = function
+ | Nil -> Nil
+ | Cons (l1, c0) -> insert l1 (sort_uniq c0)
+
+ (** val set_clause : t -> int -> C.t -> t **)
+
+ let set_clause s pos c =
+ set s pos (sort_uniq c)
+
+ (** val set_resolve : t -> int -> int array -> t **)
+
+ let set_resolve s pos r =
+ let len = length r in
+ if eqb len (ExtrNative.of_uint(0))
+ then s
+ else let c =
+ foldi (fun i c -> C.resolve (get s (Coq__1.get r i)) c)
+ (ExtrNative.of_uint(1)) (sub len (ExtrNative.of_uint(1)))
+ (get s (Coq__1.get r (ExtrNative.of_uint(0))))
+ in
+ internal_set s pos c
+ end
+
+(** val afold_left :
+ 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a2 -> 'a1) -> 'a2 array -> 'a1 **)
+
+let afold_left default oP f v =
+ let n = length v in
+ if eqb n (ExtrNative.of_uint(0))
+ then default
+ else foldi (fun i a -> oP a (f (get v i))) (ExtrNative.of_uint(1))
+ (sub n (ExtrNative.of_uint(1))) (f (get v (ExtrNative.of_uint(0))))
+
+type 'step _trace_ = 'step array array
+
+(** val _checker_ :
+ (S.t -> 'a1 -> S.t) -> (C.t -> bool) -> S.t -> 'a1 _trace_ -> int -> bool **)
+
+let _checker_ check_step is_false0 s t0 confl =
+ let s' = fold_left (fun s0 a -> fold_left check_step s0 a) s t0 in
+ is_false0 (S.get s' confl)
+
+module Sat_Checker =
+ struct
+ type step =
+ | Res of int * int array
+
+ (** val step_rect : (int -> int array -> 'a1) -> step -> 'a1 **)
+
+ let step_rect f = function
+ | Res (x, x0) -> f x x0
+
+ (** val step_rec : (int -> int array -> 'a1) -> step -> 'a1 **)
+
+ let step_rec f = function
+ | Res (x, x0) -> f x x0
+
+ (** val resolution_checker :
+ (C.t -> bool) -> S.t -> step _trace_ -> int -> bool **)
+
+ let resolution_checker s t0 =
+ _checker_ (fun s0 st -> let Res (pos, r) = st in S.set_resolve s0 pos r)
+ s t0
+
+ type dimacs = int array array
+
+ (** val coq_C_interp_or : Valuation.t -> int array -> bool **)
+
+ let coq_C_interp_or rho c =
+ afold_left false (fun b1 b2 -> if b1 then true else b2) (Lit.interp rho)
+ c
+
+ (** val valid : Valuation.t -> dimacs -> bool **)
+
+ let valid rho d =
+ afold_left true (fun b1 b2 -> if b1 then b2 else false)
+ (coq_C_interp_or rho) d
+
+ type certif =
+ | Certif of int * step _trace_ * int
+
+ (** val certif_rect :
+ (int -> step _trace_ -> int -> 'a1) -> certif -> 'a1 **)
+
+ let certif_rect f = function
+ | Certif (x, x0, x1) -> f x x0 x1
+
+ (** val certif_rec :
+ (int -> step _trace_ -> int -> 'a1) -> certif -> 'a1 **)
+
+ let certif_rec f = function
+ | Certif (x, x0, x1) -> f x x0 x1
+
+ (** val add_roots : S.t -> dimacs -> S.t **)
+
+ let add_roots s d =
+ foldi_right (fun i c s0 -> S.set_clause s0 i (to_list c)) d s
+
+ (** val checker : dimacs -> certif -> bool **)
+
+ let checker d = function
+ | Certif (nclauses, t0, confl_id) ->
+ resolution_checker C.is_false (add_roots (S.make nclauses) d) t0 confl_id
+
+ (** val interp_var : (int -> bool) -> int -> bool **)
+
+ let interp_var rho x =
+ match compare x (ExtrNative.of_uint(1)) with
+ | ExtrNative.Eq -> false
+ | ExtrNative.Lt -> true
+ | ExtrNative.Gt -> rho (sub x (ExtrNative.of_uint(1)))
+ end
+
diff --git a/src/extraction/sat_checker.mli b/src/extraction/sat_checker.mli
new file mode 100644
index 0000000..5fa2757
--- /dev/null
+++ b/src/extraction/sat_checker.mli
@@ -0,0 +1,169 @@
+val negb : bool -> bool
+
+type 'a list =
+| Nil
+| Cons of 'a * 'a list
+
+val existsb : ('a1 -> bool) -> 'a1 list -> bool
+
+type int = ExtrNative.uint
+
+val lsl0 : int -> int -> int
+
+val lsr0 : int -> int -> int
+
+val land0 : int -> int -> int
+
+val lxor0 : int -> int -> int
+
+val sub : int -> int -> int
+
+val eqb : int -> int -> bool
+
+val foldi_cont :
+ (int -> ('a1 -> 'a2) -> 'a1 -> 'a2) -> int -> int -> ('a1 -> 'a2) -> 'a1 ->
+ 'a2
+
+val foldi_down_cont :
+ (int -> ('a1 -> 'a2) -> 'a1 -> 'a2) -> int -> int -> ('a1 -> 'a2) -> 'a1 ->
+ 'a2
+
+val is_zero : int -> bool
+
+val is_even : int -> bool
+
+val compare : int -> int -> ExtrNative.comparison
+
+val foldi : (int -> 'a1 -> 'a1) -> int -> int -> 'a1 -> 'a1
+
+val foldi_down : (int -> 'a1 -> 'a1) -> int -> int -> 'a1 -> 'a1
+
+type 'a array = 'a ExtrNative.parray
+
+val make : int -> 'a1 -> 'a1 array
+
+val get : 'a1 array -> int -> 'a1
+
+val set : 'a1 array -> int -> 'a1 -> 'a1 array
+
+val length : 'a1 array -> int
+
+val to_list : 'a1 array -> 'a1 list
+
+val fold_left : ('a1 -> 'a2 -> 'a1) -> 'a1 -> 'a2 array -> 'a1
+
+val foldi_right : (int -> 'a1 -> 'a2 -> 'a2) -> 'a1 array -> 'a2 -> 'a2
+
+module Valuation :
+ sig
+ type t = int -> bool
+ end
+
+module Var :
+ sig
+ val _true : int
+
+ val _false : int
+
+ val interp : Valuation.t -> int -> bool
+ end
+
+module Lit :
+ sig
+ val is_pos : int -> bool
+
+ val blit : int -> int
+
+ val lit : int -> int
+
+ val neg : int -> int
+
+ val nlit : int -> int
+
+ val _true : int
+
+ val _false : int
+
+ val eqb : int -> int -> bool
+
+ val interp : Valuation.t -> int -> bool
+ end
+
+module C :
+ sig
+ type t = int list
+
+ val interp : Valuation.t -> t -> bool
+
+ val _true : t
+
+ val is_false : t -> bool
+
+ val or_aux : (t -> t -> t) -> int -> t -> t -> int list
+
+ val coq_or : t -> t -> t
+
+ val resolve_aux : (t -> t -> t) -> int -> t -> t -> t
+
+ val resolve : t -> t -> t
+ end
+
+module S :
+ sig
+ type t = C.t array
+
+ val get : t -> int -> C.t
+
+ val internal_set : t -> int -> C.t -> t
+
+ val make : int -> t
+
+ val insert : int -> int list -> int list
+
+ val sort_uniq : int list -> int list
+
+ val set_clause : t -> int -> C.t -> t
+
+ val set_resolve : t -> int -> int array -> t
+ end
+
+val afold_left :
+ 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a2 -> 'a1) -> 'a2 array -> 'a1
+
+type 'step _trace_ = 'step array array
+
+val _checker_ :
+ (S.t -> 'a1 -> S.t) -> (C.t -> bool) -> S.t -> 'a1 _trace_ -> int -> bool
+
+module Sat_Checker :
+ sig
+ type step =
+ | Res of int * int array
+
+ val step_rect : (int -> int array -> 'a1) -> step -> 'a1
+
+ val step_rec : (int -> int array -> 'a1) -> step -> 'a1
+
+ val resolution_checker :
+ (C.t -> bool) -> S.t -> step _trace_ -> int -> bool
+
+ type dimacs = int array array
+
+ val coq_C_interp_or : Valuation.t -> int array -> bool
+
+ val valid : Valuation.t -> dimacs -> bool
+
+ type certif =
+ | Certif of int * step _trace_ * int
+
+ val certif_rect : (int -> step _trace_ -> int -> 'a1) -> certif -> 'a1
+
+ val certif_rec : (int -> step _trace_ -> int -> 'a1) -> certif -> 'a1
+
+ val add_roots : S.t -> dimacs -> S.t
+
+ val checker : dimacs -> certif -> bool
+
+ val interp_var : (int -> bool) -> int -> bool
+ end
+
diff --git a/src/extraction/smt_checker.ml b/src/extraction/smt_checker.ml
new file mode 100644
index 0000000..53aa130
--- /dev/null
+++ b/src/extraction/smt_checker.ml
@@ -0,0 +1,6849 @@
+type __ = Obj.t
+let __ = let rec f _ = Obj.repr f in Obj.repr f
+
+type unit0 =
+| Tt
+
+(** val implb : bool -> bool -> bool **)
+
+let implb b1 b2 =
+ if b1 then b2 else true
+
+(** val xorb : bool -> bool -> bool **)
+
+let xorb b1 b2 =
+ if b1 then if b2 then false else true else b2
+
+(** val negb : bool -> bool **)
+
+let negb = function
+| true -> false
+| false -> true
+
+type nat =
+| O
+| S of nat
+
+type 'a option =
+| Some of 'a
+| None
+
+(** val option_map : ('a1 -> 'a2) -> 'a1 option -> 'a2 option **)
+
+let option_map f = function
+| Some a -> Some (f a)
+| None -> None
+
+(** val fst : ('a1*'a2) -> 'a1 **)
+
+let fst = function
+| x,y -> x
+
+(** val snd : ('a1*'a2) -> 'a2 **)
+
+let snd = function
+| x,y -> y
+
+type 'a list =
+| Nil
+| Cons of 'a * 'a list
+
+(** val app : 'a1 list -> 'a1 list -> 'a1 list **)
+
+let rec app l m =
+ match l with
+ | Nil -> m
+ | Cons (a, l1) -> Cons (a, (app l1 m))
+
+(** val compOpp : ExtrNative.comparison -> ExtrNative.comparison **)
+
+let compOpp = function
+| ExtrNative.Eq -> ExtrNative.Eq
+| ExtrNative.Lt -> ExtrNative.Gt
+| ExtrNative.Gt -> ExtrNative.Lt
+
+type compareSpecT =
+| CompEqT
+| CompLtT
+| CompGtT
+
+(** val compareSpec2Type : ExtrNative.comparison -> compareSpecT **)
+
+let compareSpec2Type = function
+| ExtrNative.Eq -> CompEqT
+| ExtrNative.Lt -> CompLtT
+| ExtrNative.Gt -> CompGtT
+
+type 'a compSpecT = compareSpecT
+
+(** val compSpec2Type :
+ 'a1 -> 'a1 -> ExtrNative.comparison -> 'a1 compSpecT **)
+
+let compSpec2Type x y c =
+ compareSpec2Type c
+
+type 'a sig0 =
+ 'a
+ (* singleton inductive, whose constructor was exist *)
+
+type sumbool =
+| Left
+| Right
+
+type 'a sumor =
+| Inleft of 'a
+| Inright
+
+(** val plus : nat -> nat -> nat **)
+
+let rec plus n0 m =
+ match n0 with
+ | O -> m
+ | S p -> S (plus p m)
+
+(** val nat_iter : nat -> ('a1 -> 'a1) -> 'a1 -> 'a1 **)
+
+let rec nat_iter n0 f x =
+ match n0 with
+ | O -> x
+ | S n' -> f (nat_iter n' f x)
+
+type positive =
+| XI of positive
+| XO of positive
+| XH
+
+type n =
+| N0
+| Npos of positive
+
+type z =
+| Z0
+| Zpos of positive
+| Zneg of positive
+
+(** val eqb : bool -> bool -> bool **)
+
+let eqb b1 b2 =
+ if b1 then b2 else if b2 then false else true
+
+type reflect =
+| ReflectT
+| ReflectF
+
+(** val iff_reflect : bool -> reflect **)
+
+let iff_reflect = function
+| true -> ReflectT
+| false -> ReflectF
+
+module type TotalOrder' =
+ sig
+ type t
+ end
+
+module MakeOrderTac =
+ functor (O:TotalOrder') ->
+ struct
+
+ end
+
+module MaxLogicalProperties =
+ functor (O:TotalOrder') ->
+ functor (M:sig
+ val max : O.t -> O.t -> O.t
+ end) ->
+ struct
+ module Private_Tac = MakeOrderTac(O)
+ end
+
+module Pos =
+ struct
+ type t = positive
+
+ (** val succ : positive -> positive **)
+
+ let rec succ = function
+ | XI p -> XO (succ p)
+ | XO p -> XI p
+ | XH -> XO XH
+
+ (** val add : positive -> positive -> positive **)
+
+ let rec add x y =
+ match x with
+ | XI p ->
+ (match y with
+ | XI q -> XO (add_carry p q)
+ | XO q -> XI (add p q)
+ | XH -> XO (succ p))
+ | XO p ->
+ (match y with
+ | XI q -> XI (add p q)
+ | XO q -> XO (add p q)
+ | XH -> XI p)
+ | XH ->
+ (match y with
+ | XI q -> XO (succ q)
+ | XO q -> XI q
+ | XH -> XO XH)
+
+ (** val add_carry : positive -> positive -> positive **)
+
+ and add_carry x y =
+ match x with
+ | XI p ->
+ (match y with
+ | XI q -> XI (add_carry p q)
+ | XO q -> XO (add_carry p q)
+ | XH -> XI (succ p))
+ | XO p ->
+ (match y with
+ | XI q -> XO (add_carry p q)
+ | XO q -> XI (add p q)
+ | XH -> XO (succ p))
+ | XH ->
+ (match y with
+ | XI q -> XI (succ q)
+ | XO q -> XO (succ q)
+ | XH -> XI XH)
+
+ (** val pred_double : positive -> positive **)
+
+ let rec pred_double = function
+ | XI p -> XI (XO p)
+ | XO p -> XI (pred_double p)
+ | XH -> XH
+
+ (** val pred : positive -> positive **)
+
+ let pred = function
+ | XI p -> XO p
+ | XO p -> pred_double p
+ | XH -> XH
+
+ (** val pred_N : positive -> n **)
+
+ let pred_N = function
+ | XI p -> Npos (XO p)
+ | XO p -> Npos (pred_double p)
+ | XH -> N0
+
+ type mask =
+ | IsNul
+ | IsPos of positive
+ | IsNeg
+
+ (** val mask_rect : 'a1 -> (positive -> 'a1) -> 'a1 -> mask -> 'a1 **)
+
+ let mask_rect f f0 f1 = function
+ | IsNul -> f
+ | IsPos x -> f0 x
+ | IsNeg -> f1
+
+ (** val mask_rec : 'a1 -> (positive -> 'a1) -> 'a1 -> mask -> 'a1 **)
+
+ let mask_rec f f0 f1 = function
+ | IsNul -> f
+ | IsPos x -> f0 x
+ | IsNeg -> f1
+
+ (** val succ_double_mask : mask -> mask **)
+
+ let succ_double_mask = function
+ | IsNul -> IsPos XH
+ | IsPos p -> IsPos (XI p)
+ | IsNeg -> IsNeg
+
+ (** val double_mask : mask -> mask **)
+
+ let double_mask = function
+ | IsPos p -> IsPos (XO p)
+ | x0 -> x0
+
+ (** val double_pred_mask : positive -> mask **)
+
+ let double_pred_mask = function
+ | XI p -> IsPos (XO (XO p))
+ | XO p -> IsPos (XO (pred_double p))
+ | XH -> IsNul
+
+ (** val pred_mask : mask -> mask **)
+
+ let pred_mask = function
+ | IsPos q ->
+ (match q with
+ | XH -> IsNul
+ | _ -> IsPos (pred q))
+ | _ -> IsNeg
+
+ (** val sub_mask : positive -> positive -> mask **)
+
+ let rec sub_mask x y =
+ match x with
+ | XI p ->
+ (match y with
+ | XI q -> double_mask (sub_mask p q)
+ | XO q -> succ_double_mask (sub_mask p q)
+ | XH -> IsPos (XO p))
+ | XO p ->
+ (match y with
+ | XI q -> succ_double_mask (sub_mask_carry p q)
+ | XO q -> double_mask (sub_mask p q)
+ | XH -> IsPos (pred_double p))
+ | XH ->
+ (match y with
+ | XH -> IsNul
+ | _ -> IsNeg)
+
+ (** val sub_mask_carry : positive -> positive -> mask **)
+
+ and sub_mask_carry x y =
+ match x with
+ | XI p ->
+ (match y with
+ | XI q -> succ_double_mask (sub_mask_carry p q)
+ | XO q -> double_mask (sub_mask p q)
+ | XH -> IsPos (pred_double p))
+ | XO p ->
+ (match y with
+ | XI q -> double_mask (sub_mask_carry p q)
+ | XO q -> succ_double_mask (sub_mask_carry p q)
+ | XH -> double_pred_mask p)
+ | XH -> IsNeg
+
+ (** val sub : positive -> positive -> positive **)
+
+ let sub x y =
+ match sub_mask x y with
+ | IsPos z0 -> z0
+ | _ -> XH
+
+ (** val mul : positive -> positive -> positive **)
+
+ let rec mul x y =
+ match x with
+ | XI p -> add y (XO (mul p y))
+ | XO p -> XO (mul p y)
+ | XH -> y
+
+ (** val iter : positive -> ('a1 -> 'a1) -> 'a1 -> 'a1 **)
+
+ let rec iter n0 f x =
+ match n0 with
+ | XI n' -> f (iter n' f (iter n' f x))
+ | XO n' -> iter n' f (iter n' f x)
+ | XH -> f x
+
+ (** val pow : positive -> positive -> positive **)
+
+ let pow x y =
+ iter y (mul x) XH
+
+ (** val square : positive -> positive **)
+
+ let rec square = function
+ | XI p2 -> XI (XO (add (square p2) p2))
+ | XO p2 -> XO (XO (square p2))
+ | XH -> XH
+
+ (** val div2 : positive -> positive **)
+
+ let div2 = function
+ | XI p2 -> p2
+ | XO p2 -> p2
+ | XH -> XH
+
+ (** val div2_up : positive -> positive **)
+
+ let div2_up = function
+ | XI p2 -> succ p2
+ | XO p2 -> p2
+ | XH -> XH
+
+ (** val size_nat : positive -> nat **)
+
+ let rec size_nat = function
+ | XI p2 -> S (size_nat p2)
+ | XO p2 -> S (size_nat p2)
+ | XH -> S O
+
+ (** val size : positive -> positive **)
+
+ let rec size = function
+ | XI p2 -> succ (size p2)
+ | XO p2 -> succ (size p2)
+ | XH -> XH
+
+ (** val compare_cont :
+ positive -> positive -> ExtrNative.comparison -> ExtrNative.comparison **)
+
+ let rec compare_cont x y r =
+ match x with
+ | XI p ->
+ (match y with
+ | XI q -> compare_cont p q r
+ | XO q -> compare_cont p q ExtrNative.Gt
+ | XH -> ExtrNative.Gt)
+ | XO p ->
+ (match y with
+ | XI q -> compare_cont p q ExtrNative.Lt
+ | XO q -> compare_cont p q r
+ | XH -> ExtrNative.Gt)
+ | XH ->
+ (match y with
+ | XH -> r
+ | _ -> ExtrNative.Lt)
+
+ (** val compare : positive -> positive -> ExtrNative.comparison **)
+
+ let compare x y =
+ compare_cont x y ExtrNative.Eq
+
+ (** val min : positive -> positive -> positive **)
+
+ let min p p' =
+ match compare p p' with
+ | ExtrNative.Gt -> p'
+ | _ -> p
+
+ (** val max : positive -> positive -> positive **)
+
+ let max p p' =
+ match compare p p' with
+ | ExtrNative.Gt -> p
+ | _ -> p'
+
+ (** val eqb : positive -> positive -> bool **)
+
+ let rec eqb p q =
+ match p with
+ | XI p2 ->
+ (match q with
+ | XI q0 -> eqb p2 q0
+ | _ -> false)
+ | XO p2 ->
+ (match q with
+ | XO q0 -> eqb p2 q0
+ | _ -> false)
+ | XH ->
+ (match q with
+ | XH -> true
+ | _ -> false)
+
+ (** val leb : positive -> positive -> bool **)
+
+ let leb x y =
+ match compare x y with
+ | ExtrNative.Gt -> false
+ | _ -> true
+
+ (** val ltb : positive -> positive -> bool **)
+
+ let ltb x y =
+ match compare x y with
+ | ExtrNative.Lt -> true
+ | _ -> false
+
+ (** val sqrtrem_step :
+ (positive -> positive) -> (positive -> positive) -> (positive*mask) ->
+ positive*mask **)
+
+ let sqrtrem_step f g = function
+ | s,y ->
+ (match y with
+ | IsPos r ->
+ let s' = XI (XO s) in
+ let r' = g (f r) in
+ if leb s' r' then (XI s),(sub_mask r' s') else (XO s),(IsPos r')
+ | _ -> (XO s),(sub_mask (g (f XH)) (XO (XO XH))))
+
+ (** val sqrtrem : positive -> positive*mask **)
+
+ let rec sqrtrem = function
+ | XI p2 ->
+ (match p2 with
+ | XI p3 -> sqrtrem_step (fun x -> XI x) (fun x -> XI x) (sqrtrem p3)
+ | XO p3 -> sqrtrem_step (fun x -> XO x) (fun x -> XI x) (sqrtrem p3)
+ | XH -> XH,(IsPos (XO XH)))
+ | XO p2 ->
+ (match p2 with
+ | XI p3 -> sqrtrem_step (fun x -> XI x) (fun x -> XO x) (sqrtrem p3)
+ | XO p3 -> sqrtrem_step (fun x -> XO x) (fun x -> XO x) (sqrtrem p3)
+ | XH -> XH,(IsPos XH))
+ | XH -> XH,IsNul
+
+ (** val sqrt : positive -> positive **)
+
+ let sqrt p =
+ fst (sqrtrem p)
+
+ (** val gcdn : nat -> positive -> positive -> positive **)
+
+ let rec gcdn n0 a b =
+ match n0 with
+ | O -> XH
+ | S n1 ->
+ (match a with
+ | XI a' ->
+ (match b with
+ | XI b' ->
+ (match compare a' b' with
+ | ExtrNative.Eq -> a
+ | ExtrNative.Lt -> gcdn n1 (sub b' a') a
+ | ExtrNative.Gt -> gcdn n1 (sub a' b') b)
+ | XO b0 -> gcdn n1 a b0
+ | XH -> XH)
+ | XO a0 ->
+ (match b with
+ | XI p -> gcdn n1 a0 b
+ | XO b0 -> XO (gcdn n1 a0 b0)
+ | XH -> XH)
+ | XH -> XH)
+
+ (** val gcd : positive -> positive -> positive **)
+
+ let gcd a b =
+ gcdn (plus (size_nat a) (size_nat b)) a b
+
+ (** val ggcdn :
+ nat -> positive -> positive -> positive*(positive*positive) **)
+
+ let rec ggcdn n0 a b =
+ match n0 with
+ | O -> XH,(a,b)
+ | S n1 ->
+ (match a with
+ | XI a' ->
+ (match b with
+ | XI b' ->
+ (match compare a' b' with
+ | ExtrNative.Eq -> a,(XH,XH)
+ | ExtrNative.Lt ->
+ let g,p = ggcdn n1 (sub b' a') a in
+ let ba,aa = p in g,(aa,(add aa (XO ba)))
+ | ExtrNative.Gt ->
+ let g,p = ggcdn n1 (sub a' b') b in
+ let ab,bb = p in g,((add bb (XO ab)),bb))
+ | XO b0 ->
+ let g,p = ggcdn n1 a b0 in let aa,bb = p in g,(aa,(XO bb))
+ | XH -> XH,(a,XH))
+ | XO a0 ->
+ (match b with
+ | XI p ->
+ let g,p2 = ggcdn n1 a0 b in let aa,bb = p2 in g,((XO aa),bb)
+ | XO b0 -> let g,p = ggcdn n1 a0 b0 in (XO g),p
+ | XH -> XH,(a,XH))
+ | XH -> XH,(XH,b))
+
+ (** val ggcd : positive -> positive -> positive*(positive*positive) **)
+
+ let ggcd a b =
+ ggcdn (plus (size_nat a) (size_nat b)) a b
+
+ (** val coq_Nsucc_double : n -> n **)
+
+ let coq_Nsucc_double = function
+ | N0 -> Npos XH
+ | Npos p -> Npos (XI p)
+
+ (** val coq_Ndouble : n -> n **)
+
+ let coq_Ndouble = function
+ | N0 -> N0
+ | Npos p -> Npos (XO p)
+
+ (** val coq_lor : positive -> positive -> positive **)
+
+ let rec coq_lor p q =
+ match p with
+ | XI p2 ->
+ (match q with
+ | XI q0 -> XI (coq_lor p2 q0)
+ | XO q0 -> XI (coq_lor p2 q0)
+ | XH -> p)
+ | XO p2 ->
+ (match q with
+ | XI q0 -> XI (coq_lor p2 q0)
+ | XO q0 -> XO (coq_lor p2 q0)
+ | XH -> XI p2)
+ | XH ->
+ (match q with
+ | XO q0 -> XI q0
+ | _ -> q)
+
+ (** val coq_land : positive -> positive -> n **)
+
+ let rec coq_land p q =
+ match p with
+ | XI p2 ->
+ (match q with
+ | XI q0 -> coq_Nsucc_double (coq_land p2 q0)
+ | XO q0 -> coq_Ndouble (coq_land p2 q0)
+ | XH -> Npos XH)
+ | XO p2 ->
+ (match q with
+ | XI q0 -> coq_Ndouble (coq_land p2 q0)
+ | XO q0 -> coq_Ndouble (coq_land p2 q0)
+ | XH -> N0)
+ | XH ->
+ (match q with
+ | XO q0 -> N0
+ | _ -> Npos XH)
+
+ (** val ldiff : positive -> positive -> n **)
+
+ let rec ldiff p q =
+ match p with
+ | XI p2 ->
+ (match q with
+ | XI q0 -> coq_Ndouble (ldiff p2 q0)
+ | XO q0 -> coq_Nsucc_double (ldiff p2 q0)
+ | XH -> Npos (XO p2))
+ | XO p2 ->
+ (match q with
+ | XI q0 -> coq_Ndouble (ldiff p2 q0)
+ | XO q0 -> coq_Ndouble (ldiff p2 q0)
+ | XH -> Npos p)
+ | XH ->
+ (match q with
+ | XO q0 -> Npos XH
+ | _ -> N0)
+
+ (** val coq_lxor : positive -> positive -> n **)
+
+ let rec coq_lxor p q =
+ match p with
+ | XI p2 ->
+ (match q with
+ | XI q0 -> coq_Ndouble (coq_lxor p2 q0)
+ | XO q0 -> coq_Nsucc_double (coq_lxor p2 q0)
+ | XH -> Npos (XO p2))
+ | XO p2 ->
+ (match q with
+ | XI q0 -> coq_Nsucc_double (coq_lxor p2 q0)
+ | XO q0 -> coq_Ndouble (coq_lxor p2 q0)
+ | XH -> Npos (XI p2))
+ | XH ->
+ (match q with
+ | XI q0 -> Npos (XO q0)
+ | XO q0 -> Npos (XI q0)
+ | XH -> N0)
+
+ (** val shiftl_nat : positive -> nat -> positive **)
+
+ let shiftl_nat p n0 =
+ nat_iter n0 (fun x -> XO x) p
+
+ (** val shiftr_nat : positive -> nat -> positive **)
+
+ let shiftr_nat p n0 =
+ nat_iter n0 div2 p
+
+ (** val shiftl : positive -> n -> positive **)
+
+ let shiftl p = function
+ | N0 -> p
+ | Npos n1 -> iter n1 (fun x -> XO x) p
+
+ (** val shiftr : positive -> n -> positive **)
+
+ let shiftr p = function
+ | N0 -> p
+ | Npos n1 -> iter n1 div2 p
+
+ (** val testbit_nat : positive -> nat -> bool **)
+
+ let rec testbit_nat p n0 =
+ match p with
+ | XI p2 ->
+ (match n0 with
+ | O -> true
+ | S n' -> testbit_nat p2 n')
+ | XO p2 ->
+ (match n0 with
+ | O -> false
+ | S n' -> testbit_nat p2 n')
+ | XH ->
+ (match n0 with
+ | O -> true
+ | S n1 -> false)
+
+ (** val testbit : positive -> n -> bool **)
+
+ let rec testbit p n0 =
+ match p with
+ | XI p2 ->
+ (match n0 with
+ | N0 -> true
+ | Npos n1 -> testbit p2 (pred_N n1))
+ | XO p2 ->
+ (match n0 with
+ | N0 -> false
+ | Npos n1 -> testbit p2 (pred_N n1))
+ | XH ->
+ (match n0 with
+ | N0 -> true
+ | Npos p2 -> false)
+
+ (** val iter_op : ('a1 -> 'a1 -> 'a1) -> positive -> 'a1 -> 'a1 **)
+
+ let rec iter_op op p a =
+ match p with
+ | XI p2 -> op a (iter_op op p2 (op a a))
+ | XO p2 -> iter_op op p2 (op a a)
+ | XH -> a
+
+ (** val to_nat : positive -> nat **)
+
+ let to_nat x =
+ iter_op plus x (S O)
+
+ (** val of_nat : nat -> positive **)
+
+ let rec of_nat = function
+ | O -> XH
+ | S x ->
+ (match x with
+ | O -> XH
+ | S n1 -> succ (of_nat x))
+
+ (** val of_succ_nat : nat -> positive **)
+
+ let rec of_succ_nat = function
+ | O -> XH
+ | S x -> succ (of_succ_nat x)
+ end
+
+module Coq_Pos =
+ struct
+ module Coq__1 = struct
+ type t = positive
+ end
+ type t = Coq__1.t
+
+ (** val succ : positive -> positive **)
+
+ let rec succ = function
+ | XI p -> XO (succ p)
+ | XO p -> XI p
+ | XH -> XO XH
+
+ (** val add : positive -> positive -> positive **)
+
+ let rec add x y =
+ match x with
+ | XI p ->
+ (match y with
+ | XI q -> XO (add_carry p q)
+ | XO q -> XI (add p q)
+ | XH -> XO (succ p))
+ | XO p ->
+ (match y with
+ | XI q -> XI (add p q)
+ | XO q -> XO (add p q)
+ | XH -> XI p)
+ | XH ->
+ (match y with
+ | XI q -> XO (succ q)
+ | XO q -> XI q
+ | XH -> XO XH)
+
+ (** val add_carry : positive -> positive -> positive **)
+
+ and add_carry x y =
+ match x with
+ | XI p ->
+ (match y with
+ | XI q -> XI (add_carry p q)
+ | XO q -> XO (add_carry p q)
+ | XH -> XI (succ p))
+ | XO p ->
+ (match y with
+ | XI q -> XO (add_carry p q)
+ | XO q -> XI (add p q)
+ | XH -> XO (succ p))
+ | XH ->
+ (match y with
+ | XI q -> XI (succ q)
+ | XO q -> XO (succ q)
+ | XH -> XI XH)
+
+ (** val pred_double : positive -> positive **)
+
+ let rec pred_double = function
+ | XI p -> XI (XO p)
+ | XO p -> XI (pred_double p)
+ | XH -> XH
+
+ (** val pred : positive -> positive **)
+
+ let pred = function
+ | XI p -> XO p
+ | XO p -> pred_double p
+ | XH -> XH
+
+ (** val pred_N : positive -> n **)
+
+ let pred_N = function
+ | XI p -> Npos (XO p)
+ | XO p -> Npos (pred_double p)
+ | XH -> N0
+
+ type mask = Pos.mask =
+ | IsNul
+ | IsPos of positive
+ | IsNeg
+
+ (** val mask_rect : 'a1 -> (positive -> 'a1) -> 'a1 -> mask -> 'a1 **)
+
+ let mask_rect f f0 f1 = function
+ | IsNul -> f
+ | IsPos x -> f0 x
+ | IsNeg -> f1
+
+ (** val mask_rec : 'a1 -> (positive -> 'a1) -> 'a1 -> mask -> 'a1 **)
+
+ let mask_rec f f0 f1 = function
+ | IsNul -> f
+ | IsPos x -> f0 x
+ | IsNeg -> f1
+
+ (** val succ_double_mask : mask -> mask **)
+
+ let succ_double_mask = function
+ | IsNul -> IsPos XH
+ | IsPos p -> IsPos (XI p)
+ | IsNeg -> IsNeg
+
+ (** val double_mask : mask -> mask **)
+
+ let double_mask = function
+ | IsPos p -> IsPos (XO p)
+ | x0 -> x0
+
+ (** val double_pred_mask : positive -> mask **)
+
+ let double_pred_mask = function
+ | XI p -> IsPos (XO (XO p))
+ | XO p -> IsPos (XO (pred_double p))
+ | XH -> IsNul
+
+ (** val pred_mask : mask -> mask **)
+
+ let pred_mask = function
+ | IsPos q ->
+ (match q with
+ | XH -> IsNul
+ | _ -> IsPos (pred q))
+ | _ -> IsNeg
+
+ (** val sub_mask : positive -> positive -> mask **)
+
+ let rec sub_mask x y =
+ match x with
+ | XI p ->
+ (match y with
+ | XI q -> double_mask (sub_mask p q)
+ | XO q -> succ_double_mask (sub_mask p q)
+ | XH -> IsPos (XO p))
+ | XO p ->
+ (match y with
+ | XI q -> succ_double_mask (sub_mask_carry p q)
+ | XO q -> double_mask (sub_mask p q)
+ | XH -> IsPos (pred_double p))
+ | XH ->
+ (match y with
+ | XH -> IsNul
+ | _ -> IsNeg)
+
+ (** val sub_mask_carry : positive -> positive -> mask **)
+
+ and sub_mask_carry x y =
+ match x with
+ | XI p ->
+ (match y with
+ | XI q -> succ_double_mask (sub_mask_carry p q)
+ | XO q -> double_mask (sub_mask p q)
+ | XH -> IsPos (pred_double p))
+ | XO p ->
+ (match y with
+ | XI q -> double_mask (sub_mask_carry p q)
+ | XO q -> succ_double_mask (sub_mask_carry p q)
+ | XH -> double_pred_mask p)
+ | XH -> IsNeg
+
+ (** val sub : positive -> positive -> positive **)
+
+ let sub x y =
+ match sub_mask x y with
+ | IsPos z0 -> z0
+ | _ -> XH
+
+ (** val mul : positive -> positive -> positive **)
+
+ let rec mul x y =
+ match x with
+ | XI p -> add y (XO (mul p y))
+ | XO p -> XO (mul p y)
+ | XH -> y
+
+ (** val iter : positive -> ('a1 -> 'a1) -> 'a1 -> 'a1 **)
+
+ let rec iter n0 f x =
+ match n0 with
+ | XI n' -> f (iter n' f (iter n' f x))
+ | XO n' -> iter n' f (iter n' f x)
+ | XH -> f x
+
+ (** val pow : positive -> positive -> positive **)
+
+ let pow x y =
+ iter y (mul x) XH
+
+ (** val square : positive -> positive **)
+
+ let rec square = function
+ | XI p2 -> XI (XO (add (square p2) p2))
+ | XO p2 -> XO (XO (square p2))
+ | XH -> XH
+
+ (** val div2 : positive -> positive **)
+
+ let div2 = function
+ | XI p2 -> p2
+ | XO p2 -> p2
+ | XH -> XH
+
+ (** val div2_up : positive -> positive **)
+
+ let div2_up = function
+ | XI p2 -> succ p2
+ | XO p2 -> p2
+ | XH -> XH
+
+ (** val size_nat : positive -> nat **)
+
+ let rec size_nat = function
+ | XI p2 -> S (size_nat p2)
+ | XO p2 -> S (size_nat p2)
+ | XH -> S O
+
+ (** val size : positive -> positive **)
+
+ let rec size = function
+ | XI p2 -> succ (size p2)
+ | XO p2 -> succ (size p2)
+ | XH -> XH
+
+ (** val compare_cont :
+ positive -> positive -> ExtrNative.comparison -> ExtrNative.comparison **)
+
+ let rec compare_cont x y r =
+ match x with
+ | XI p ->
+ (match y with
+ | XI q -> compare_cont p q r
+ | XO q -> compare_cont p q ExtrNative.Gt
+ | XH -> ExtrNative.Gt)
+ | XO p ->
+ (match y with
+ | XI q -> compare_cont p q ExtrNative.Lt
+ | XO q -> compare_cont p q r
+ | XH -> ExtrNative.Gt)
+ | XH ->
+ (match y with
+ | XH -> r
+ | _ -> ExtrNative.Lt)
+
+ (** val compare : positive -> positive -> ExtrNative.comparison **)
+
+ let compare x y =
+ compare_cont x y ExtrNative.Eq
+
+ (** val min : positive -> positive -> positive **)
+
+ let min p p' =
+ match compare p p' with
+ | ExtrNative.Gt -> p'
+ | _ -> p
+
+ (** val max : positive -> positive -> positive **)
+
+ let max p p' =
+ match compare p p' with
+ | ExtrNative.Gt -> p
+ | _ -> p'
+
+ (** val eqb : positive -> positive -> bool **)
+
+ let rec eqb p q =
+ match p with
+ | XI p2 ->
+ (match q with
+ | XI q0 -> eqb p2 q0
+ | _ -> false)
+ | XO p2 ->
+ (match q with
+ | XO q0 -> eqb p2 q0
+ | _ -> false)
+ | XH ->
+ (match q with
+ | XH -> true
+ | _ -> false)
+
+ (** val leb : positive -> positive -> bool **)
+
+ let leb x y =
+ match compare x y with
+ | ExtrNative.Gt -> false
+ | _ -> true
+
+ (** val ltb : positive -> positive -> bool **)
+
+ let ltb x y =
+ match compare x y with
+ | ExtrNative.Lt -> true
+ | _ -> false
+
+ (** val sqrtrem_step :
+ (positive -> positive) -> (positive -> positive) -> (positive*mask) ->
+ positive*mask **)
+
+ let sqrtrem_step f g = function
+ | s,y ->
+ (match y with
+ | IsPos r ->
+ let s' = XI (XO s) in
+ let r' = g (f r) in
+ if leb s' r' then (XI s),(sub_mask r' s') else (XO s),(IsPos r')
+ | _ -> (XO s),(sub_mask (g (f XH)) (XO (XO XH))))
+
+ (** val sqrtrem : positive -> positive*mask **)
+
+ let rec sqrtrem = function
+ | XI p2 ->
+ (match p2 with
+ | XI p3 -> sqrtrem_step (fun x -> XI x) (fun x -> XI x) (sqrtrem p3)
+ | XO p3 -> sqrtrem_step (fun x -> XO x) (fun x -> XI x) (sqrtrem p3)
+ | XH -> XH,(IsPos (XO XH)))
+ | XO p2 ->
+ (match p2 with
+ | XI p3 -> sqrtrem_step (fun x -> XI x) (fun x -> XO x) (sqrtrem p3)
+ | XO p3 -> sqrtrem_step (fun x -> XO x) (fun x -> XO x) (sqrtrem p3)
+ | XH -> XH,(IsPos XH))
+ | XH -> XH,IsNul
+
+ (** val sqrt : positive -> positive **)
+
+ let sqrt p =
+ fst (sqrtrem p)
+
+ (** val gcdn : nat -> positive -> positive -> positive **)
+
+ let rec gcdn n0 a b =
+ match n0 with
+ | O -> XH
+ | S n1 ->
+ (match a with
+ | XI a' ->
+ (match b with
+ | XI b' ->
+ (match compare a' b' with
+ | ExtrNative.Eq -> a
+ | ExtrNative.Lt -> gcdn n1 (sub b' a') a
+ | ExtrNative.Gt -> gcdn n1 (sub a' b') b)
+ | XO b0 -> gcdn n1 a b0
+ | XH -> XH)
+ | XO a0 ->
+ (match b with
+ | XI p -> gcdn n1 a0 b
+ | XO b0 -> XO (gcdn n1 a0 b0)
+ | XH -> XH)
+ | XH -> XH)
+
+ (** val gcd : positive -> positive -> positive **)
+
+ let gcd a b =
+ gcdn (plus (size_nat a) (size_nat b)) a b
+
+ (** val ggcdn :
+ nat -> positive -> positive -> positive*(positive*positive) **)
+
+ let rec ggcdn n0 a b =
+ match n0 with
+ | O -> XH,(a,b)
+ | S n1 ->
+ (match a with
+ | XI a' ->
+ (match b with
+ | XI b' ->
+ (match compare a' b' with
+ | ExtrNative.Eq -> a,(XH,XH)
+ | ExtrNative.Lt ->
+ let g,p = ggcdn n1 (sub b' a') a in
+ let ba,aa = p in g,(aa,(add aa (XO ba)))
+ | ExtrNative.Gt ->
+ let g,p = ggcdn n1 (sub a' b') b in
+ let ab,bb = p in g,((add bb (XO ab)),bb))
+ | XO b0 ->
+ let g,p = ggcdn n1 a b0 in let aa,bb = p in g,(aa,(XO bb))
+ | XH -> XH,(a,XH))
+ | XO a0 ->
+ (match b with
+ | XI p ->
+ let g,p2 = ggcdn n1 a0 b in let aa,bb = p2 in g,((XO aa),bb)
+ | XO b0 -> let g,p = ggcdn n1 a0 b0 in (XO g),p
+ | XH -> XH,(a,XH))
+ | XH -> XH,(XH,b))
+
+ (** val ggcd : positive -> positive -> positive*(positive*positive) **)
+
+ let ggcd a b =
+ ggcdn (plus (size_nat a) (size_nat b)) a b
+
+ (** val coq_Nsucc_double : n -> n **)
+
+ let coq_Nsucc_double = function
+ | N0 -> Npos XH
+ | Npos p -> Npos (XI p)
+
+ (** val coq_Ndouble : n -> n **)
+
+ let coq_Ndouble = function
+ | N0 -> N0
+ | Npos p -> Npos (XO p)
+
+ (** val coq_lor : positive -> positive -> positive **)
+
+ let rec coq_lor p q =
+ match p with
+ | XI p2 ->
+ (match q with
+ | XI q0 -> XI (coq_lor p2 q0)
+ | XO q0 -> XI (coq_lor p2 q0)
+ | XH -> p)
+ | XO p2 ->
+ (match q with
+ | XI q0 -> XI (coq_lor p2 q0)
+ | XO q0 -> XO (coq_lor p2 q0)
+ | XH -> XI p2)
+ | XH ->
+ (match q with
+ | XO q0 -> XI q0
+ | _ -> q)
+
+ (** val coq_land : positive -> positive -> n **)
+
+ let rec coq_land p q =
+ match p with
+ | XI p2 ->
+ (match q with
+ | XI q0 -> coq_Nsucc_double (coq_land p2 q0)
+ | XO q0 -> coq_Ndouble (coq_land p2 q0)
+ | XH -> Npos XH)
+ | XO p2 ->
+ (match q with
+ | XI q0 -> coq_Ndouble (coq_land p2 q0)
+ | XO q0 -> coq_Ndouble (coq_land p2 q0)
+ | XH -> N0)
+ | XH ->
+ (match q with
+ | XO q0 -> N0
+ | _ -> Npos XH)
+
+ (** val ldiff : positive -> positive -> n **)
+
+ let rec ldiff p q =
+ match p with
+ | XI p2 ->
+ (match q with
+ | XI q0 -> coq_Ndouble (ldiff p2 q0)
+ | XO q0 -> coq_Nsucc_double (ldiff p2 q0)
+ | XH -> Npos (XO p2))
+ | XO p2 ->
+ (match q with
+ | XI q0 -> coq_Ndouble (ldiff p2 q0)
+ | XO q0 -> coq_Ndouble (ldiff p2 q0)
+ | XH -> Npos p)
+ | XH ->
+ (match q with
+ | XO q0 -> Npos XH
+ | _ -> N0)
+
+ (** val coq_lxor : positive -> positive -> n **)
+
+ let rec coq_lxor p q =
+ match p with
+ | XI p2 ->
+ (match q with
+ | XI q0 -> coq_Ndouble (coq_lxor p2 q0)
+ | XO q0 -> coq_Nsucc_double (coq_lxor p2 q0)
+ | XH -> Npos (XO p2))
+ | XO p2 ->
+ (match q with
+ | XI q0 -> coq_Nsucc_double (coq_lxor p2 q0)
+ | XO q0 -> coq_Ndouble (coq_lxor p2 q0)
+ | XH -> Npos (XI p2))
+ | XH ->
+ (match q with
+ | XI q0 -> Npos (XO q0)
+ | XO q0 -> Npos (XI q0)
+ | XH -> N0)
+
+ (** val shiftl_nat : positive -> nat -> positive **)
+
+ let shiftl_nat p n0 =
+ nat_iter n0 (fun x -> XO x) p
+
+ (** val shiftr_nat : positive -> nat -> positive **)
+
+ let shiftr_nat p n0 =
+ nat_iter n0 div2 p
+
+ (** val shiftl : positive -> n -> positive **)
+
+ let shiftl p = function
+ | N0 -> p
+ | Npos n1 -> iter n1 (fun x -> XO x) p
+
+ (** val shiftr : positive -> n -> positive **)
+
+ let shiftr p = function
+ | N0 -> p
+ | Npos n1 -> iter n1 div2 p
+
+ (** val testbit_nat : positive -> nat -> bool **)
+
+ let rec testbit_nat p n0 =
+ match p with
+ | XI p2 ->
+ (match n0 with
+ | O -> true
+ | S n' -> testbit_nat p2 n')
+ | XO p2 ->
+ (match n0 with
+ | O -> false
+ | S n' -> testbit_nat p2 n')
+ | XH ->
+ (match n0 with
+ | O -> true
+ | S n1 -> false)
+
+ (** val testbit : positive -> n -> bool **)
+
+ let rec testbit p n0 =
+ match p with
+ | XI p2 ->
+ (match n0 with
+ | N0 -> true
+ | Npos n1 -> testbit p2 (pred_N n1))
+ | XO p2 ->
+ (match n0 with
+ | N0 -> false
+ | Npos n1 -> testbit p2 (pred_N n1))
+ | XH ->
+ (match n0 with
+ | N0 -> true
+ | Npos p2 -> false)
+
+ (** val iter_op : ('a1 -> 'a1 -> 'a1) -> positive -> 'a1 -> 'a1 **)
+
+ let rec iter_op op p a =
+ match p with
+ | XI p2 -> op a (iter_op op p2 (op a a))
+ | XO p2 -> iter_op op p2 (op a a)
+ | XH -> a
+
+ (** val to_nat : positive -> nat **)
+
+ let to_nat x =
+ iter_op plus x (S O)
+
+ (** val of_nat : nat -> positive **)
+
+ let rec of_nat = function
+ | O -> XH
+ | S x ->
+ (match x with
+ | O -> XH
+ | S n1 -> succ (of_nat x))
+
+ (** val of_succ_nat : nat -> positive **)
+
+ let rec of_succ_nat = function
+ | O -> XH
+ | S x -> succ (of_succ_nat x)
+
+ (** val eq_dec : positive -> positive -> sumbool **)
+
+ let rec eq_dec p y0 =
+ match p with
+ | XI p2 ->
+ (match y0 with
+ | XI p3 -> eq_dec p2 p3
+ | _ -> Right)
+ | XO p2 ->
+ (match y0 with
+ | XO p3 -> eq_dec p2 p3
+ | _ -> Right)
+ | XH ->
+ (match y0 with
+ | XH -> Left
+ | _ -> Right)
+
+ (** val peano_rect : 'a1 -> (positive -> 'a1 -> 'a1) -> positive -> 'a1 **)
+
+ let rec peano_rect a f p =
+ let f2 = peano_rect (f XH a) (fun p2 x -> f (succ (XO p2)) (f (XO p2) x))
+ in
+ (match p with
+ | XI q -> f (XO q) (f2 q)
+ | XO q -> f2 q
+ | XH -> a)
+
+ (** val peano_rec : 'a1 -> (positive -> 'a1 -> 'a1) -> positive -> 'a1 **)
+
+ let peano_rec =
+ peano_rect
+
+ type coq_PeanoView =
+ | PeanoOne
+ | PeanoSucc of positive * coq_PeanoView
+
+ (** val coq_PeanoView_rect :
+ 'a1 -> (positive -> coq_PeanoView -> 'a1 -> 'a1) -> positive ->
+ coq_PeanoView -> 'a1 **)
+
+ let rec coq_PeanoView_rect f f0 p = function
+ | PeanoOne -> f
+ | PeanoSucc (p3, p4) -> f0 p3 p4 (coq_PeanoView_rect f f0 p3 p4)
+
+ (** val coq_PeanoView_rec :
+ 'a1 -> (positive -> coq_PeanoView -> 'a1 -> 'a1) -> positive ->
+ coq_PeanoView -> 'a1 **)
+
+ let rec coq_PeanoView_rec f f0 p = function
+ | PeanoOne -> f
+ | PeanoSucc (p3, p4) -> f0 p3 p4 (coq_PeanoView_rec f f0 p3 p4)
+
+ (** val peanoView_xO : positive -> coq_PeanoView -> coq_PeanoView **)
+
+ let rec peanoView_xO p = function
+ | PeanoOne -> PeanoSucc (XH, PeanoOne)
+ | PeanoSucc (p2, q0) ->
+ PeanoSucc ((succ (XO p2)), (PeanoSucc ((XO p2), (peanoView_xO p2 q0))))
+
+ (** val peanoView_xI : positive -> coq_PeanoView -> coq_PeanoView **)
+
+ let rec peanoView_xI p = function
+ | PeanoOne -> PeanoSucc ((succ XH), (PeanoSucc (XH, PeanoOne)))
+ | PeanoSucc (p2, q0) ->
+ PeanoSucc ((succ (XI p2)), (PeanoSucc ((XI p2), (peanoView_xI p2 q0))))
+
+ (** val peanoView : positive -> coq_PeanoView **)
+
+ let rec peanoView = function
+ | XI p2 -> peanoView_xI p2 (peanoView p2)
+ | XO p2 -> peanoView_xO p2 (peanoView p2)
+ | XH -> PeanoOne
+
+ (** val coq_PeanoView_iter :
+ 'a1 -> (positive -> 'a1 -> 'a1) -> positive -> coq_PeanoView -> 'a1 **)
+
+ let rec coq_PeanoView_iter a f p = function
+ | PeanoOne -> a
+ | PeanoSucc (p2, q0) -> f p2 (coq_PeanoView_iter a f p2 q0)
+
+ (** val eqb_spec : positive -> positive -> reflect **)
+
+ let eqb_spec x y =
+ iff_reflect (eqb x y)
+
+ (** val switch_Eq :
+ ExtrNative.comparison -> ExtrNative.comparison -> ExtrNative.comparison **)
+
+ let switch_Eq c = function
+ | ExtrNative.Eq -> c
+ | x -> x
+
+ (** val mask2cmp : mask -> ExtrNative.comparison **)
+
+ let mask2cmp = function
+ | IsNul -> ExtrNative.Eq
+ | IsPos p2 -> ExtrNative.Gt
+ | IsNeg -> ExtrNative.Lt
+
+ (** val leb_spec0 : positive -> positive -> reflect **)
+
+ let leb_spec0 x y =
+ iff_reflect (leb x y)
+
+ (** val ltb_spec0 : positive -> positive -> reflect **)
+
+ let ltb_spec0 x y =
+ iff_reflect (ltb x y)
+
+ module Private_Tac =
+ struct
+
+ end
+
+ module Private_Rev =
+ struct
+ module ORev =
+ struct
+ type t = Coq__1.t
+ end
+
+ module MRev =
+ struct
+ (** val max : t -> t -> t **)
+
+ let max x y =
+ min y x
+ end
+
+ module MPRev = MaxLogicalProperties(ORev)(MRev)
+ end
+
+ module Private_Dec =
+ struct
+ (** val max_case_strong :
+ t -> t -> (t -> t -> __ -> 'a1 -> 'a1) -> (__ -> 'a1) -> (__ -> 'a1)
+ -> 'a1 **)
+
+ let max_case_strong n0 m compat hl hr =
+ let c = compSpec2Type n0 m (compare n0 m) in
+ (match c with
+ | CompGtT -> compat n0 (max n0 m) __ (hl __)
+ | _ -> compat m (max n0 m) __ (hr __))
+
+ (** val max_case :
+ t -> t -> (t -> t -> __ -> 'a1 -> 'a1) -> 'a1 -> 'a1 -> 'a1 **)
+
+ let max_case n0 m x x0 x1 =
+ max_case_strong n0 m x (fun _ -> x0) (fun _ -> x1)
+
+ (** val max_dec : t -> t -> sumbool **)
+
+ let max_dec n0 m =
+ max_case n0 m (fun x y _ h0 -> h0) Left Right
+
+ (** val min_case_strong :
+ t -> t -> (t -> t -> __ -> 'a1 -> 'a1) -> (__ -> 'a1) -> (__ -> 'a1)
+ -> 'a1 **)
+
+ let min_case_strong n0 m compat hl hr =
+ let c = compSpec2Type n0 m (compare n0 m) in
+ (match c with
+ | CompGtT -> compat m (min n0 m) __ (hr __)
+ | _ -> compat n0 (min n0 m) __ (hl __))
+
+ (** val min_case :
+ t -> t -> (t -> t -> __ -> 'a1 -> 'a1) -> 'a1 -> 'a1 -> 'a1 **)
+
+ let min_case n0 m x x0 x1 =
+ min_case_strong n0 m x (fun _ -> x0) (fun _ -> x1)
+
+ (** val min_dec : t -> t -> sumbool **)
+
+ let min_dec n0 m =
+ min_case n0 m (fun x y _ h0 -> h0) Left Right
+ end
+
+ (** val max_case_strong : t -> t -> (__ -> 'a1) -> (__ -> 'a1) -> 'a1 **)
+
+ let max_case_strong n0 m x x0 =
+ Private_Dec.max_case_strong n0 m (fun x1 y _ x2 -> x2) x x0
+
+ (** val max_case : t -> t -> 'a1 -> 'a1 -> 'a1 **)
+
+ let max_case n0 m x x0 =
+ max_case_strong n0 m (fun _ -> x) (fun _ -> x0)
+
+ (** val max_dec : t -> t -> sumbool **)
+
+ let max_dec =
+ Private_Dec.max_dec
+
+ (** val min_case_strong : t -> t -> (__ -> 'a1) -> (__ -> 'a1) -> 'a1 **)
+
+ let min_case_strong n0 m x x0 =
+ Private_Dec.min_case_strong n0 m (fun x1 y _ x2 -> x2) x x0
+
+ (** val min_case : t -> t -> 'a1 -> 'a1 -> 'a1 **)
+
+ let min_case n0 m x x0 =
+ min_case_strong n0 m (fun _ -> x) (fun _ -> x0)
+
+ (** val min_dec : t -> t -> sumbool **)
+
+ let min_dec =
+ Private_Dec.min_dec
+ end
+
+module N =
+ struct
+ type t = n
+
+ (** val zero : n **)
+
+ let zero =
+ N0
+
+ (** val one : n **)
+
+ let one =
+ Npos XH
+
+ (** val two : n **)
+
+ let two =
+ Npos (XO XH)
+
+ (** val succ_double : n -> n **)
+
+ let succ_double = function
+ | N0 -> Npos XH
+ | Npos p -> Npos (XI p)
+
+ (** val double : n -> n **)
+
+ let double = function
+ | N0 -> N0
+ | Npos p -> Npos (XO p)
+
+ (** val succ : n -> n **)
+
+ let succ = function
+ | N0 -> Npos XH
+ | Npos p -> Npos (Coq_Pos.succ p)
+
+ (** val pred : n -> n **)
+
+ let pred = function
+ | N0 -> N0
+ | Npos p -> Coq_Pos.pred_N p
+
+ (** val succ_pos : n -> positive **)
+
+ let succ_pos = function
+ | N0 -> XH
+ | Npos p -> Coq_Pos.succ p
+
+ (** val add : n -> n -> n **)
+
+ let add n0 m =
+ match n0 with
+ | N0 -> m
+ | Npos p ->
+ (match m with
+ | N0 -> n0
+ | Npos q -> Npos (Coq_Pos.add p q))
+
+ (** val sub : n -> n -> n **)
+
+ let sub n0 m =
+ match n0 with
+ | N0 -> N0
+ | Npos n' ->
+ (match m with
+ | N0 -> n0
+ | Npos m' ->
+ (match Coq_Pos.sub_mask n' m' with
+ | Coq_Pos.IsPos p -> Npos p
+ | _ -> N0))
+
+ (** val mul : n -> n -> n **)
+
+ let mul n0 m =
+ match n0 with
+ | N0 -> N0
+ | Npos p ->
+ (match m with
+ | N0 -> N0
+ | Npos q -> Npos (Coq_Pos.mul p q))
+
+ (** val compare : n -> n -> ExtrNative.comparison **)
+
+ let compare n0 m =
+ match n0 with
+ | N0 ->
+ (match m with
+ | N0 -> ExtrNative.Eq
+ | Npos m' -> ExtrNative.Lt)
+ | Npos n' ->
+ (match m with
+ | N0 -> ExtrNative.Gt
+ | Npos m' -> Coq_Pos.compare n' m')
+
+ (** val eqb : n -> n -> bool **)
+
+ let rec eqb n0 m =
+ match n0 with
+ | N0 ->
+ (match m with
+ | N0 -> true
+ | Npos p -> false)
+ | Npos p ->
+ (match m with
+ | N0 -> false
+ | Npos q -> Coq_Pos.eqb p q)
+
+ (** val leb : n -> n -> bool **)
+
+ let leb x y =
+ match compare x y with
+ | ExtrNative.Gt -> false
+ | _ -> true
+
+ (** val ltb : n -> n -> bool **)
+
+ let ltb x y =
+ match compare x y with
+ | ExtrNative.Lt -> true
+ | _ -> false
+
+ (** val min : n -> n -> n **)
+
+ let min n0 n' =
+ match compare n0 n' with
+ | ExtrNative.Gt -> n'
+ | _ -> n0
+
+ (** val max : n -> n -> n **)
+
+ let max n0 n' =
+ match compare n0 n' with
+ | ExtrNative.Gt -> n0
+ | _ -> n'
+
+ (** val div2 : n -> n **)
+
+ let div2 = function
+ | N0 -> N0
+ | Npos p2 ->
+ (match p2 with
+ | XI p -> Npos p
+ | XO p -> Npos p
+ | XH -> N0)
+
+ (** val even : n -> bool **)
+
+ let even = function
+ | N0 -> true
+ | Npos p ->
+ (match p with
+ | XO p2 -> true
+ | _ -> false)
+
+ (** val odd : n -> bool **)
+
+ let odd n0 =
+ negb (even n0)
+
+ (** val pow : n -> n -> n **)
+
+ let pow n0 = function
+ | N0 -> Npos XH
+ | Npos p2 ->
+ (match n0 with
+ | N0 -> N0
+ | Npos q -> Npos (Coq_Pos.pow q p2))
+
+ (** val square : n -> n **)
+
+ let square = function
+ | N0 -> N0
+ | Npos p -> Npos (Coq_Pos.square p)
+
+ (** val log2 : n -> n **)
+
+ let log2 = function
+ | N0 -> N0
+ | Npos p2 ->
+ (match p2 with
+ | XI p -> Npos (Coq_Pos.size p)
+ | XO p -> Npos (Coq_Pos.size p)
+ | XH -> N0)
+
+ (** val size : n -> n **)
+
+ let size = function
+ | N0 -> N0
+ | Npos p -> Npos (Coq_Pos.size p)
+
+ (** val size_nat : n -> nat **)
+
+ let size_nat = function
+ | N0 -> O
+ | Npos p -> Coq_Pos.size_nat p
+
+ (** val pos_div_eucl : positive -> n -> n*n **)
+
+ let rec pos_div_eucl a b =
+ match a with
+ | XI a' ->
+ let q,r = pos_div_eucl a' b in
+ let r' = succ_double r in
+ if leb b r' then (succ_double q),(sub r' b) else (double q),r'
+ | XO a' ->
+ let q,r = pos_div_eucl a' b in
+ let r' = double r in
+ if leb b r' then (succ_double q),(sub r' b) else (double q),r'
+ | XH ->
+ (match b with
+ | N0 -> N0,(Npos XH)
+ | Npos p ->
+ (match p with
+ | XH -> (Npos XH),N0
+ | _ -> N0,(Npos XH)))
+
+ (** val div_eucl : n -> n -> n*n **)
+
+ let div_eucl a b =
+ match a with
+ | N0 -> N0,N0
+ | Npos na ->
+ (match b with
+ | N0 -> N0,a
+ | Npos p -> pos_div_eucl na b)
+
+ (** val div : n -> n -> n **)
+
+ let div a b =
+ fst (div_eucl a b)
+
+ (** val modulo : n -> n -> n **)
+
+ let modulo a b =
+ snd (div_eucl a b)
+
+ (** val gcd : n -> n -> n **)
+
+ let gcd a b =
+ match a with
+ | N0 -> b
+ | Npos p ->
+ (match b with
+ | N0 -> a
+ | Npos q -> Npos (Coq_Pos.gcd p q))
+
+ (** val ggcd : n -> n -> n*(n*n) **)
+
+ let ggcd a b =
+ match a with
+ | N0 -> b,(N0,(Npos XH))
+ | Npos p ->
+ (match b with
+ | N0 -> a,((Npos XH),N0)
+ | Npos q ->
+ let g,p2 = Coq_Pos.ggcd p q in
+ let aa,bb = p2 in (Npos g),((Npos aa),(Npos bb)))
+
+ (** val sqrtrem : n -> n*n **)
+
+ let sqrtrem = function
+ | N0 -> N0,N0
+ | Npos p ->
+ let s,m = Coq_Pos.sqrtrem p in
+ (match m with
+ | Coq_Pos.IsPos r -> (Npos s),(Npos r)
+ | _ -> (Npos s),N0)
+
+ (** val sqrt : n -> n **)
+
+ let sqrt = function
+ | N0 -> N0
+ | Npos p -> Npos (Coq_Pos.sqrt p)
+
+ (** val coq_lor : n -> n -> n **)
+
+ let coq_lor n0 m =
+ match n0 with
+ | N0 -> m
+ | Npos p ->
+ (match m with
+ | N0 -> n0
+ | Npos q -> Npos (Coq_Pos.coq_lor p q))
+
+ (** val coq_land : n -> n -> n **)
+
+ let coq_land n0 m =
+ match n0 with
+ | N0 -> N0
+ | Npos p ->
+ (match m with
+ | N0 -> N0
+ | Npos q -> Coq_Pos.coq_land p q)
+
+ (** val ldiff : n -> n -> n **)
+
+ let rec ldiff n0 m =
+ match n0 with
+ | N0 -> N0
+ | Npos p ->
+ (match m with
+ | N0 -> n0
+ | Npos q -> Coq_Pos.ldiff p q)
+
+ (** val coq_lxor : n -> n -> n **)
+
+ let coq_lxor n0 m =
+ match n0 with
+ | N0 -> m
+ | Npos p ->
+ (match m with
+ | N0 -> n0
+ | Npos q -> Coq_Pos.coq_lxor p q)
+
+ (** val shiftl_nat : n -> nat -> n **)
+
+ let shiftl_nat a n0 =
+ nat_iter n0 double a
+
+ (** val shiftr_nat : n -> nat -> n **)
+
+ let shiftr_nat a n0 =
+ nat_iter n0 div2 a
+
+ (** val shiftl : n -> n -> n **)
+
+ let shiftl a n0 =
+ match a with
+ | N0 -> N0
+ | Npos a0 -> Npos (Coq_Pos.shiftl a0 n0)
+
+ (** val shiftr : n -> n -> n **)
+
+ let shiftr a = function
+ | N0 -> a
+ | Npos p -> Coq_Pos.iter p div2 a
+
+ (** val testbit_nat : n -> nat -> bool **)
+
+ let testbit_nat = function
+ | N0 -> (fun x -> false)
+ | Npos p -> Coq_Pos.testbit_nat p
+
+ (** val testbit : n -> n -> bool **)
+
+ let testbit a n0 =
+ match a with
+ | N0 -> false
+ | Npos p -> Coq_Pos.testbit p n0
+
+ (** val to_nat : n -> nat **)
+
+ let to_nat = function
+ | N0 -> O
+ | Npos p -> Coq_Pos.to_nat p
+
+ (** val of_nat : nat -> n **)
+
+ let of_nat = function
+ | O -> N0
+ | S n' -> Npos (Coq_Pos.of_succ_nat n')
+
+ (** val iter : n -> ('a1 -> 'a1) -> 'a1 -> 'a1 **)
+
+ let iter n0 f x =
+ match n0 with
+ | N0 -> x
+ | Npos p -> Coq_Pos.iter p f x
+
+ (** val eq_dec : n -> n -> sumbool **)
+
+ let eq_dec n0 m =
+ match n0 with
+ | N0 ->
+ (match m with
+ | N0 -> Left
+ | Npos p -> Right)
+ | Npos x ->
+ (match m with
+ | N0 -> Right
+ | Npos p2 -> Coq_Pos.eq_dec x p2)
+
+ (** val discr : n -> positive sumor **)
+
+ let discr = function
+ | N0 -> Inright
+ | Npos p -> Inleft p
+
+ (** val binary_rect :
+ 'a1 -> (n -> 'a1 -> 'a1) -> (n -> 'a1 -> 'a1) -> n -> 'a1 **)
+
+ let binary_rect f0 f2 fS2 n0 =
+ let f2' = fun p -> f2 (Npos p) in
+ let fS2' = fun p -> fS2 (Npos p) in
+ (match n0 with
+ | N0 -> f0
+ | Npos p ->
+ let rec f = function
+ | XI p3 -> fS2' p3 (f p3)
+ | XO p3 -> f2' p3 (f p3)
+ | XH -> fS2 N0 f0
+ in f p)
+
+ (** val binary_rec :
+ 'a1 -> (n -> 'a1 -> 'a1) -> (n -> 'a1 -> 'a1) -> n -> 'a1 **)
+
+ let binary_rec =
+ binary_rect
+
+ (** val peano_rect : 'a1 -> (n -> 'a1 -> 'a1) -> n -> 'a1 **)
+
+ let peano_rect f0 f n0 =
+ let f' = fun p -> f (Npos p) in
+ (match n0 with
+ | N0 -> f0
+ | Npos p -> Coq_Pos.peano_rect (f N0 f0) f' p)
+
+ (** val peano_rec : 'a1 -> (n -> 'a1 -> 'a1) -> n -> 'a1 **)
+
+ let peano_rec =
+ peano_rect
+
+ (** val leb_spec0 : n -> n -> reflect **)
+
+ let leb_spec0 x y =
+ iff_reflect (leb x y)
+
+ (** val ltb_spec0 : n -> n -> reflect **)
+
+ let ltb_spec0 x y =
+ iff_reflect (ltb x y)
+
+ module Private_BootStrap =
+ struct
+
+ end
+
+ (** val recursion : 'a1 -> (n -> 'a1 -> 'a1) -> n -> 'a1 **)
+
+ let recursion x =
+ peano_rect x
+
+ module Private_OrderTac =
+ struct
+ module Elts =
+ struct
+ type t = n
+ end
+
+ module Tac = MakeOrderTac(Elts)
+ end
+
+ module Private_NZPow =
+ struct
+
+ end
+
+ module Private_NZSqrt =
+ struct
+
+ end
+
+ (** val sqrt_up : n -> n **)
+
+ let sqrt_up a =
+ match compare N0 a with
+ | ExtrNative.Lt -> succ (sqrt (pred a))
+ | _ -> N0
+
+ (** val log2_up : n -> n **)
+
+ let log2_up a =
+ match compare (Npos XH) a with
+ | ExtrNative.Lt -> succ (log2 (pred a))
+ | _ -> N0
+
+ module Private_NZDiv =
+ struct
+
+ end
+
+ (** val lcm : n -> n -> n **)
+
+ let lcm a b =
+ mul a (div b (gcd a b))
+
+ (** val eqb_spec : n -> n -> reflect **)
+
+ let eqb_spec x y =
+ iff_reflect (eqb x y)
+
+ (** val b2n : bool -> n **)
+
+ let b2n = function
+ | true -> Npos XH
+ | false -> N0
+
+ (** val setbit : n -> n -> n **)
+
+ let setbit a n0 =
+ coq_lor a (shiftl (Npos XH) n0)
+
+ (** val clearbit : n -> n -> n **)
+
+ let clearbit a n0 =
+ ldiff a (shiftl (Npos XH) n0)
+
+ (** val ones : n -> n **)
+
+ let ones n0 =
+ pred (shiftl (Npos XH) n0)
+
+ (** val lnot : n -> n -> n **)
+
+ let lnot a n0 =
+ coq_lxor a (ones n0)
+
+ module Private_Tac =
+ struct
+
+ end
+
+ module Private_Rev =
+ struct
+ module ORev =
+ struct
+ type t = n
+ end
+
+ module MRev =
+ struct
+ (** val max : n -> n -> n **)
+
+ let max x y =
+ min y x
+ end
+
+ module MPRev = MaxLogicalProperties(ORev)(MRev)
+ end
+
+ module Private_Dec =
+ struct
+ (** val max_case_strong :
+ n -> n -> (n -> n -> __ -> 'a1 -> 'a1) -> (__ -> 'a1) -> (__ -> 'a1)
+ -> 'a1 **)
+
+ let max_case_strong n0 m compat hl hr =
+ let c = compSpec2Type n0 m (compare n0 m) in
+ (match c with
+ | CompGtT -> compat n0 (max n0 m) __ (hl __)
+ | _ -> compat m (max n0 m) __ (hr __))
+
+ (** val max_case :
+ n -> n -> (n -> n -> __ -> 'a1 -> 'a1) -> 'a1 -> 'a1 -> 'a1 **)
+
+ let max_case n0 m x x0 x1 =
+ max_case_strong n0 m x (fun _ -> x0) (fun _ -> x1)
+
+ (** val max_dec : n -> n -> sumbool **)
+
+ let max_dec n0 m =
+ max_case n0 m (fun x y _ h0 -> h0) Left Right
+
+ (** val min_case_strong :
+ n -> n -> (n -> n -> __ -> 'a1 -> 'a1) -> (__ -> 'a1) -> (__ -> 'a1)
+ -> 'a1 **)
+
+ let min_case_strong n0 m compat hl hr =
+ let c = compSpec2Type n0 m (compare n0 m) in
+ (match c with
+ | CompGtT -> compat m (min n0 m) __ (hr __)
+ | _ -> compat n0 (min n0 m) __ (hl __))
+
+ (** val min_case :
+ n -> n -> (n -> n -> __ -> 'a1 -> 'a1) -> 'a1 -> 'a1 -> 'a1 **)
+
+ let min_case n0 m x x0 x1 =
+ min_case_strong n0 m x (fun _ -> x0) (fun _ -> x1)
+
+ (** val min_dec : n -> n -> sumbool **)
+
+ let min_dec n0 m =
+ min_case n0 m (fun x y _ h0 -> h0) Left Right
+ end
+
+ (** val max_case_strong : n -> n -> (__ -> 'a1) -> (__ -> 'a1) -> 'a1 **)
+
+ let max_case_strong n0 m x x0 =
+ Private_Dec.max_case_strong n0 m (fun x1 y _ x2 -> x2) x x0
+
+ (** val max_case : n -> n -> 'a1 -> 'a1 -> 'a1 **)
+
+ let max_case n0 m x x0 =
+ max_case_strong n0 m (fun _ -> x) (fun _ -> x0)
+
+ (** val max_dec : n -> n -> sumbool **)
+
+ let max_dec =
+ Private_Dec.max_dec
+
+ (** val min_case_strong : n -> n -> (__ -> 'a1) -> (__ -> 'a1) -> 'a1 **)
+
+ let min_case_strong n0 m x x0 =
+ Private_Dec.min_case_strong n0 m (fun x1 y _ x2 -> x2) x x0
+
+ (** val min_case : n -> n -> 'a1 -> 'a1 -> 'a1 **)
+
+ let min_case n0 m x x0 =
+ min_case_strong n0 m (fun _ -> x) (fun _ -> x0)
+
+ (** val min_dec : n -> n -> sumbool **)
+
+ let min_dec =
+ Private_Dec.min_dec
+ end
+
+module Z =
+ struct
+ type t = z
+
+ (** val zero : z **)
+
+ let zero =
+ Z0
+
+ (** val one : z **)
+
+ let one =
+ Zpos XH
+
+ (** val two : z **)
+
+ let two =
+ Zpos (XO XH)
+
+ (** val double : z -> z **)
+
+ let double = function
+ | Z0 -> Z0
+ | Zpos p -> Zpos (XO p)
+ | Zneg p -> Zneg (XO p)
+
+ (** val succ_double : z -> z **)
+
+ let succ_double = function
+ | Z0 -> Zpos XH
+ | Zpos p -> Zpos (XI p)
+ | Zneg p -> Zneg (Coq_Pos.pred_double p)
+
+ (** val pred_double : z -> z **)
+
+ let pred_double = function
+ | Z0 -> Zneg XH
+ | Zpos p -> Zpos (Coq_Pos.pred_double p)
+ | Zneg p -> Zneg (XI p)
+
+ (** val pos_sub : positive -> positive -> z **)
+
+ let rec pos_sub x y =
+ match x with
+ | XI p ->
+ (match y with
+ | XI q -> double (pos_sub p q)
+ | XO q -> succ_double (pos_sub p q)
+ | XH -> Zpos (XO p))
+ | XO p ->
+ (match y with
+ | XI q -> pred_double (pos_sub p q)
+ | XO q -> double (pos_sub p q)
+ | XH -> Zpos (Coq_Pos.pred_double p))
+ | XH ->
+ (match y with
+ | XI q -> Zneg (XO q)
+ | XO q -> Zneg (Coq_Pos.pred_double q)
+ | XH -> Z0)
+
+ (** val add : z -> z -> z **)
+
+ let add x y =
+ match x with
+ | Z0 -> y
+ | Zpos x' ->
+ (match y with
+ | Z0 -> x
+ | Zpos y' -> Zpos (Coq_Pos.add x' y')
+ | Zneg y' -> pos_sub x' y')
+ | Zneg x' ->
+ (match y with
+ | Z0 -> x
+ | Zpos y' -> pos_sub y' x'
+ | Zneg y' -> Zneg (Coq_Pos.add x' y'))
+
+ (** val opp : z -> z **)
+
+ let opp = function
+ | Z0 -> Z0
+ | Zpos x0 -> Zneg x0
+ | Zneg x0 -> Zpos x0
+
+ (** val succ : z -> z **)
+
+ let succ x =
+ add x (Zpos XH)
+
+ (** val pred : z -> z **)
+
+ let pred x =
+ add x (Zneg XH)
+
+ (** val sub : z -> z -> z **)
+
+ let sub m n0 =
+ add m (opp n0)
+
+ (** val mul : z -> z -> z **)
+
+ let mul x y =
+ match x with
+ | Z0 -> Z0
+ | Zpos x' ->
+ (match y with
+ | Z0 -> Z0
+ | Zpos y' -> Zpos (Coq_Pos.mul x' y')
+ | Zneg y' -> Zneg (Coq_Pos.mul x' y'))
+ | Zneg x' ->
+ (match y with
+ | Z0 -> Z0
+ | Zpos y' -> Zneg (Coq_Pos.mul x' y')
+ | Zneg y' -> Zpos (Coq_Pos.mul x' y'))
+
+ (** val pow_pos : z -> positive -> z **)
+
+ let pow_pos z0 n0 =
+ Coq_Pos.iter n0 (mul z0) (Zpos XH)
+
+ (** val pow : z -> z -> z **)
+
+ let pow x = function
+ | Z0 -> Zpos XH
+ | Zpos p -> pow_pos x p
+ | Zneg p -> Z0
+
+ (** val square : z -> z **)
+
+ let square = function
+ | Z0 -> Z0
+ | Zpos p -> Zpos (Coq_Pos.square p)
+ | Zneg p -> Zpos (Coq_Pos.square p)
+
+ (** val compare : z -> z -> ExtrNative.comparison **)
+
+ let compare x y =
+ match x with
+ | Z0 ->
+ (match y with
+ | Z0 -> ExtrNative.Eq
+ | Zpos y' -> ExtrNative.Lt
+ | Zneg y' -> ExtrNative.Gt)
+ | Zpos x' ->
+ (match y with
+ | Zpos y' -> Coq_Pos.compare x' y'
+ | _ -> ExtrNative.Gt)
+ | Zneg x' ->
+ (match y with
+ | Zneg y' -> compOpp (Coq_Pos.compare x' y')
+ | _ -> ExtrNative.Lt)
+
+ (** val sgn : z -> z **)
+
+ let sgn = function
+ | Z0 -> Z0
+ | Zpos p -> Zpos XH
+ | Zneg p -> Zneg XH
+
+ (** val leb : z -> z -> bool **)
+
+ let leb x y =
+ match compare x y with
+ | ExtrNative.Gt -> false
+ | _ -> true
+
+ (** val ltb : z -> z -> bool **)
+
+ let ltb x y =
+ match compare x y with
+ | ExtrNative.Lt -> true
+ | _ -> false
+
+ (** val geb : z -> z -> bool **)
+
+ let geb x y =
+ match compare x y with
+ | ExtrNative.Lt -> false
+ | _ -> true
+
+ (** val gtb : z -> z -> bool **)
+
+ let gtb x y =
+ match compare x y with
+ | ExtrNative.Gt -> true
+ | _ -> false
+
+ (** val eqb : z -> z -> bool **)
+
+ let rec eqb x y =
+ match x with
+ | Z0 ->
+ (match y with
+ | Z0 -> true
+ | _ -> false)
+ | Zpos p ->
+ (match y with
+ | Zpos q -> Coq_Pos.eqb p q
+ | _ -> false)
+ | Zneg p ->
+ (match y with
+ | Zneg q -> Coq_Pos.eqb p q
+ | _ -> false)
+
+ (** val max : z -> z -> z **)
+
+ let max n0 m =
+ match compare n0 m with
+ | ExtrNative.Lt -> m
+ | _ -> n0
+
+ (** val min : z -> z -> z **)
+
+ let min n0 m =
+ match compare n0 m with
+ | ExtrNative.Gt -> m
+ | _ -> n0
+
+ (** val abs : z -> z **)
+
+ let abs = function
+ | Zneg p -> Zpos p
+ | x -> x
+
+ (** val abs_nat : z -> nat **)
+
+ let abs_nat = function
+ | Z0 -> O
+ | Zpos p -> Coq_Pos.to_nat p
+ | Zneg p -> Coq_Pos.to_nat p
+
+ (** val abs_N : z -> n **)
+
+ let abs_N = function
+ | Z0 -> N0
+ | Zpos p -> Npos p
+ | Zneg p -> Npos p
+
+ (** val to_nat : z -> nat **)
+
+ let to_nat = function
+ | Zpos p -> Coq_Pos.to_nat p
+ | _ -> O
+
+ (** val to_N : z -> n **)
+
+ let to_N = function
+ | Zpos p -> Npos p
+ | _ -> N0
+
+ (** val of_nat : nat -> z **)
+
+ let of_nat = function
+ | O -> Z0
+ | S n1 -> Zpos (Coq_Pos.of_succ_nat n1)
+
+ (** val of_N : n -> z **)
+
+ let of_N = function
+ | N0 -> Z0
+ | Npos p -> Zpos p
+
+ (** val iter : z -> ('a1 -> 'a1) -> 'a1 -> 'a1 **)
+
+ let iter n0 f x =
+ match n0 with
+ | Zpos p -> Coq_Pos.iter p f x
+ | _ -> x
+
+ (** val pos_div_eucl : positive -> z -> z*z **)
+
+ let rec pos_div_eucl a b =
+ match a with
+ | XI a' ->
+ let q,r = pos_div_eucl a' b in
+ let r' = add (mul (Zpos (XO XH)) r) (Zpos XH) in
+ if ltb r' b
+ then (mul (Zpos (XO XH)) q),r'
+ else (add (mul (Zpos (XO XH)) q) (Zpos XH)),(sub r' b)
+ | XO a' ->
+ let q,r = pos_div_eucl a' b in
+ let r' = mul (Zpos (XO XH)) r in
+ if ltb r' b
+ then (mul (Zpos (XO XH)) q),r'
+ else (add (mul (Zpos (XO XH)) q) (Zpos XH)),(sub r' b)
+ | XH -> if leb (Zpos (XO XH)) b then Z0,(Zpos XH) else (Zpos XH),Z0
+
+ (** val div_eucl : z -> z -> z*z **)
+
+ let div_eucl a b =
+ match a with
+ | Z0 -> Z0,Z0
+ | Zpos a' ->
+ (match b with
+ | Z0 -> Z0,Z0
+ | Zpos p -> pos_div_eucl a' b
+ | Zneg b' ->
+ let q,r = pos_div_eucl a' (Zpos b') in
+ (match r with
+ | Z0 -> (opp q),Z0
+ | _ -> (opp (add q (Zpos XH))),(add b r)))
+ | Zneg a' ->
+ (match b with
+ | Z0 -> Z0,Z0
+ | Zpos p ->
+ let q,r = pos_div_eucl a' b in
+ (match r with
+ | Z0 -> (opp q),Z0
+ | _ -> (opp (add q (Zpos XH))),(sub b r))
+ | Zneg b' -> let q,r = pos_div_eucl a' (Zpos b') in q,(opp r))
+
+ (** val div : z -> z -> z **)
+
+ let div a b =
+ let q,x = div_eucl a b in q
+
+ (** val modulo : z -> z -> z **)
+
+ let modulo a b =
+ let x,r = div_eucl a b in r
+
+ (** val quotrem : z -> z -> z*z **)
+
+ let quotrem a b =
+ match a with
+ | Z0 -> Z0,Z0
+ | Zpos a0 ->
+ (match b with
+ | Z0 -> Z0,a
+ | Zpos b0 ->
+ let q,r = N.pos_div_eucl a0 (Npos b0) in (of_N q),(of_N r)
+ | Zneg b0 ->
+ let q,r = N.pos_div_eucl a0 (Npos b0) in (opp (of_N q)),(of_N r))
+ | Zneg a0 ->
+ (match b with
+ | Z0 -> Z0,a
+ | Zpos b0 ->
+ let q,r = N.pos_div_eucl a0 (Npos b0) in
+ (opp (of_N q)),(opp (of_N r))
+ | Zneg b0 ->
+ let q,r = N.pos_div_eucl a0 (Npos b0) in (of_N q),(opp (of_N r)))
+
+ (** val quot : z -> z -> z **)
+
+ let quot a b =
+ fst (quotrem a b)
+
+ (** val rem : z -> z -> z **)
+
+ let rem a b =
+ snd (quotrem a b)
+
+ (** val even : z -> bool **)
+
+ let even = function
+ | Z0 -> true
+ | Zpos p ->
+ (match p with
+ | XO p2 -> true
+ | _ -> false)
+ | Zneg p ->
+ (match p with
+ | XO p2 -> true
+ | _ -> false)
+
+ (** val odd : z -> bool **)
+
+ let odd = function
+ | Z0 -> false
+ | Zpos p ->
+ (match p with
+ | XO p2 -> false
+ | _ -> true)
+ | Zneg p ->
+ (match p with
+ | XO p2 -> false
+ | _ -> true)
+
+ (** val div2 : z -> z **)
+
+ let div2 = function
+ | Z0 -> Z0
+ | Zpos p ->
+ (match p with
+ | XH -> Z0
+ | _ -> Zpos (Coq_Pos.div2 p))
+ | Zneg p -> Zneg (Coq_Pos.div2_up p)
+
+ (** val quot2 : z -> z **)
+
+ let quot2 = function
+ | Z0 -> Z0
+ | Zpos p ->
+ (match p with
+ | XH -> Z0
+ | _ -> Zpos (Coq_Pos.div2 p))
+ | Zneg p ->
+ (match p with
+ | XH -> Z0
+ | _ -> Zneg (Coq_Pos.div2 p))
+
+ (** val log2 : z -> z **)
+
+ let log2 = function
+ | Zpos p2 ->
+ (match p2 with
+ | XI p -> Zpos (Coq_Pos.size p)
+ | XO p -> Zpos (Coq_Pos.size p)
+ | XH -> Z0)
+ | _ -> Z0
+
+ (** val sqrtrem : z -> z*z **)
+
+ let sqrtrem = function
+ | Zpos p ->
+ let s,m = Coq_Pos.sqrtrem p in
+ (match m with
+ | Coq_Pos.IsPos r -> (Zpos s),(Zpos r)
+ | _ -> (Zpos s),Z0)
+ | _ -> Z0,Z0
+
+ (** val sqrt : z -> z **)
+
+ let sqrt = function
+ | Zpos p -> Zpos (Coq_Pos.sqrt p)
+ | _ -> Z0
+
+ (** val gcd : z -> z -> z **)
+
+ let gcd a b =
+ match a with
+ | Z0 -> abs b
+ | Zpos a0 ->
+ (match b with
+ | Z0 -> abs a
+ | Zpos b0 -> Zpos (Coq_Pos.gcd a0 b0)
+ | Zneg b0 -> Zpos (Coq_Pos.gcd a0 b0))
+ | Zneg a0 ->
+ (match b with
+ | Z0 -> abs a
+ | Zpos b0 -> Zpos (Coq_Pos.gcd a0 b0)
+ | Zneg b0 -> Zpos (Coq_Pos.gcd a0 b0))
+
+ (** val ggcd : z -> z -> z*(z*z) **)
+
+ let ggcd a b =
+ match a with
+ | Z0 -> (abs b),(Z0,(sgn b))
+ | Zpos a0 ->
+ (match b with
+ | Z0 -> (abs a),((sgn a),Z0)
+ | Zpos b0 ->
+ let g,p = Coq_Pos.ggcd a0 b0 in
+ let aa,bb = p in (Zpos g),((Zpos aa),(Zpos bb))
+ | Zneg b0 ->
+ let g,p = Coq_Pos.ggcd a0 b0 in
+ let aa,bb = p in (Zpos g),((Zpos aa),(Zneg bb)))
+ | Zneg a0 ->
+ (match b with
+ | Z0 -> (abs a),((sgn a),Z0)
+ | Zpos b0 ->
+ let g,p = Coq_Pos.ggcd a0 b0 in
+ let aa,bb = p in (Zpos g),((Zneg aa),(Zpos bb))
+ | Zneg b0 ->
+ let g,p = Coq_Pos.ggcd a0 b0 in
+ let aa,bb = p in (Zpos g),((Zneg aa),(Zneg bb)))
+
+ (** val testbit : z -> z -> bool **)
+
+ let testbit a = function
+ | Z0 -> odd a
+ | Zpos p ->
+ (match a with
+ | Z0 -> false
+ | Zpos a0 -> Coq_Pos.testbit a0 (Npos p)
+ | Zneg a0 -> negb (N.testbit (Coq_Pos.pred_N a0) (Npos p)))
+ | Zneg p -> false
+
+ (** val shiftl : z -> z -> z **)
+
+ let shiftl a = function
+ | Z0 -> a
+ | Zpos p -> Coq_Pos.iter p (mul (Zpos (XO XH))) a
+ | Zneg p -> Coq_Pos.iter p div2 a
+
+ (** val shiftr : z -> z -> z **)
+
+ let shiftr a n0 =
+ shiftl a (opp n0)
+
+ (** val coq_lor : z -> z -> z **)
+
+ let coq_lor a b =
+ match a with
+ | Z0 -> b
+ | Zpos a0 ->
+ (match b with
+ | Z0 -> a
+ | Zpos b0 -> Zpos (Coq_Pos.coq_lor a0 b0)
+ | Zneg b0 -> Zneg (N.succ_pos (N.ldiff (Coq_Pos.pred_N b0) (Npos a0))))
+ | Zneg a0 ->
+ (match b with
+ | Z0 -> a
+ | Zpos b0 -> Zneg (N.succ_pos (N.ldiff (Coq_Pos.pred_N a0) (Npos b0)))
+ | Zneg b0 ->
+ Zneg
+ (N.succ_pos (N.coq_land (Coq_Pos.pred_N a0) (Coq_Pos.pred_N b0))))
+
+ (** val coq_land : z -> z -> z **)
+
+ let coq_land a b =
+ match a with
+ | Z0 -> Z0
+ | Zpos a0 ->
+ (match b with
+ | Z0 -> Z0
+ | Zpos b0 -> of_N (Coq_Pos.coq_land a0 b0)
+ | Zneg b0 -> of_N (N.ldiff (Npos a0) (Coq_Pos.pred_N b0)))
+ | Zneg a0 ->
+ (match b with
+ | Z0 -> Z0
+ | Zpos b0 -> of_N (N.ldiff (Npos b0) (Coq_Pos.pred_N a0))
+ | Zneg b0 ->
+ Zneg
+ (N.succ_pos (N.coq_lor (Coq_Pos.pred_N a0) (Coq_Pos.pred_N b0))))
+
+ (** val ldiff : z -> z -> z **)
+
+ let ldiff a b =
+ match a with
+ | Z0 -> Z0
+ | Zpos a0 ->
+ (match b with
+ | Z0 -> a
+ | Zpos b0 -> of_N (Coq_Pos.ldiff a0 b0)
+ | Zneg b0 -> of_N (N.coq_land (Npos a0) (Coq_Pos.pred_N b0)))
+ | Zneg a0 ->
+ (match b with
+ | Z0 -> a
+ | Zpos b0 ->
+ Zneg (N.succ_pos (N.coq_lor (Coq_Pos.pred_N a0) (Npos b0)))
+ | Zneg b0 -> of_N (N.ldiff (Coq_Pos.pred_N b0) (Coq_Pos.pred_N a0)))
+
+ (** val coq_lxor : z -> z -> z **)
+
+ let coq_lxor a b =
+ match a with
+ | Z0 -> b
+ | Zpos a0 ->
+ (match b with
+ | Z0 -> a
+ | Zpos b0 -> of_N (Coq_Pos.coq_lxor a0 b0)
+ | Zneg b0 ->
+ Zneg (N.succ_pos (N.coq_lxor (Npos a0) (Coq_Pos.pred_N b0))))
+ | Zneg a0 ->
+ (match b with
+ | Z0 -> a
+ | Zpos b0 ->
+ Zneg (N.succ_pos (N.coq_lxor (Coq_Pos.pred_N a0) (Npos b0)))
+ | Zneg b0 -> of_N (N.coq_lxor (Coq_Pos.pred_N a0) (Coq_Pos.pred_N b0)))
+
+ (** val eq_dec : z -> z -> sumbool **)
+
+ let eq_dec x y =
+ match x with
+ | Z0 ->
+ (match y with
+ | Z0 -> Left
+ | _ -> Right)
+ | Zpos x0 ->
+ (match y with
+ | Zpos p2 -> Coq_Pos.eq_dec x0 p2
+ | _ -> Right)
+ | Zneg x0 ->
+ (match y with
+ | Zneg p2 -> Coq_Pos.eq_dec x0 p2
+ | _ -> Right)
+
+ module Private_BootStrap =
+ struct
+
+ end
+
+ (** val leb_spec0 : z -> z -> reflect **)
+
+ let leb_spec0 x y =
+ iff_reflect (leb x y)
+
+ (** val ltb_spec0 : z -> z -> reflect **)
+
+ let ltb_spec0 x y =
+ iff_reflect (ltb x y)
+
+ module Private_OrderTac =
+ struct
+ module Elts =
+ struct
+ type t = z
+ end
+
+ module Tac = MakeOrderTac(Elts)
+ end
+
+ (** val sqrt_up : z -> z **)
+
+ let sqrt_up a =
+ match compare Z0 a with
+ | ExtrNative.Lt -> succ (sqrt (pred a))
+ | _ -> Z0
+
+ (** val log2_up : z -> z **)
+
+ let log2_up a =
+ match compare (Zpos XH) a with
+ | ExtrNative.Lt -> succ (log2 (pred a))
+ | _ -> Z0
+
+ module Private_NZDiv =
+ struct
+
+ end
+
+ module Private_Div =
+ struct
+ module Quot2Div =
+ struct
+ (** val div : z -> z -> z **)
+
+ let div =
+ quot
+
+ (** val modulo : z -> z -> z **)
+
+ let modulo =
+ rem
+ end
+
+ module NZQuot =
+ struct
+
+ end
+ end
+
+ (** val lcm : z -> z -> z **)
+
+ let lcm a b =
+ abs (mul a (div b (gcd a b)))
+
+ (** val eqb_spec : z -> z -> reflect **)
+
+ let eqb_spec x y =
+ iff_reflect (eqb x y)
+
+ (** val b2z : bool -> z **)
+
+ let b2z = function
+ | true -> Zpos XH
+ | false -> Z0
+
+ (** val setbit : z -> z -> z **)
+
+ let setbit a n0 =
+ coq_lor a (shiftl (Zpos XH) n0)
+
+ (** val clearbit : z -> z -> z **)
+
+ let clearbit a n0 =
+ ldiff a (shiftl (Zpos XH) n0)
+
+ (** val lnot : z -> z **)
+
+ let lnot a =
+ pred (opp a)
+
+ (** val ones : z -> z **)
+
+ let ones n0 =
+ pred (shiftl (Zpos XH) n0)
+
+ module Private_Tac =
+ struct
+
+ end
+
+ module Private_Rev =
+ struct
+ module ORev =
+ struct
+ type t = z
+ end
+
+ module MRev =
+ struct
+ (** val max : z -> z -> z **)
+
+ let max x y =
+ min y x
+ end
+
+ module MPRev = MaxLogicalProperties(ORev)(MRev)
+ end
+
+ module Private_Dec =
+ struct
+ (** val max_case_strong :
+ z -> z -> (z -> z -> __ -> 'a1 -> 'a1) -> (__ -> 'a1) -> (__ -> 'a1)
+ -> 'a1 **)
+
+ let max_case_strong n0 m compat hl hr =
+ let c = compSpec2Type n0 m (compare n0 m) in
+ (match c with
+ | CompGtT -> compat n0 (max n0 m) __ (hl __)
+ | _ -> compat m (max n0 m) __ (hr __))
+
+ (** val max_case :
+ z -> z -> (z -> z -> __ -> 'a1 -> 'a1) -> 'a1 -> 'a1 -> 'a1 **)
+
+ let max_case n0 m x x0 x1 =
+ max_case_strong n0 m x (fun _ -> x0) (fun _ -> x1)
+
+ (** val max_dec : z -> z -> sumbool **)
+
+ let max_dec n0 m =
+ max_case n0 m (fun x y _ h0 -> h0) Left Right
+
+ (** val min_case_strong :
+ z -> z -> (z -> z -> __ -> 'a1 -> 'a1) -> (__ -> 'a1) -> (__ -> 'a1)
+ -> 'a1 **)
+
+ let min_case_strong n0 m compat hl hr =
+ let c = compSpec2Type n0 m (compare n0 m) in
+ (match c with
+ | CompGtT -> compat m (min n0 m) __ (hr __)
+ | _ -> compat n0 (min n0 m) __ (hl __))
+
+ (** val min_case :
+ z -> z -> (z -> z -> __ -> 'a1 -> 'a1) -> 'a1 -> 'a1 -> 'a1 **)
+
+ let min_case n0 m x x0 x1 =
+ min_case_strong n0 m x (fun _ -> x0) (fun _ -> x1)
+
+ (** val min_dec : z -> z -> sumbool **)
+
+ let min_dec n0 m =
+ min_case n0 m (fun x y _ h0 -> h0) Left Right
+ end
+
+ (** val max_case_strong : z -> z -> (__ -> 'a1) -> (__ -> 'a1) -> 'a1 **)
+
+ let max_case_strong n0 m x x0 =
+ Private_Dec.max_case_strong n0 m (fun x1 y _ x2 -> x2) x x0
+
+ (** val max_case : z -> z -> 'a1 -> 'a1 -> 'a1 **)
+
+ let max_case n0 m x x0 =
+ max_case_strong n0 m (fun _ -> x) (fun _ -> x0)
+
+ (** val max_dec : z -> z -> sumbool **)
+
+ let max_dec =
+ Private_Dec.max_dec
+
+ (** val min_case_strong : z -> z -> (__ -> 'a1) -> (__ -> 'a1) -> 'a1 **)
+
+ let min_case_strong n0 m x x0 =
+ Private_Dec.min_case_strong n0 m (fun x1 y _ x2 -> x2) x x0
+
+ (** val min_case : z -> z -> 'a1 -> 'a1 -> 'a1 **)
+
+ let min_case n0 m x x0 =
+ min_case_strong n0 m (fun _ -> x) (fun _ -> x0)
+
+ (** val min_dec : z -> z -> sumbool **)
+
+ let min_dec =
+ Private_Dec.min_dec
+ end
+
+(** val zeq_bool : z -> z -> bool **)
+
+let zeq_bool x y =
+ match Z.compare x y with
+ | ExtrNative.Eq -> true
+ | _ -> false
+
+(** val nth : nat -> 'a1 list -> 'a1 -> 'a1 **)
+
+let rec nth n0 l default0 =
+ match n0 with
+ | O ->
+ (match l with
+ | Nil -> default0
+ | Cons (x, l') -> x)
+ | S m ->
+ (match l with
+ | Nil -> default0
+ | Cons (x, t0) -> nth m t0 default0)
+
+(** val map : ('a1 -> 'a2) -> 'a1 list -> 'a2 list **)
+
+let rec map f = function
+| Nil -> Nil
+| Cons (a, t0) -> Cons ((f a), (map f t0))
+
+(** val fold_right : ('a2 -> 'a1 -> 'a1) -> 'a1 -> 'a2 list -> 'a1 **)
+
+let rec fold_right f a0 = function
+| Nil -> a0
+| Cons (b, t0) -> f b (fold_right f a0 t0)
+
+(** val existsb : ('a1 -> bool) -> 'a1 list -> bool **)
+
+let rec existsb f = function
+| Nil -> false
+| Cons (a, l0) -> if f a then true else existsb f l0
+
+(** val forallb : ('a1 -> bool) -> 'a1 list -> bool **)
+
+let rec forallb f = function
+| Nil -> true
+| Cons (a, l0) -> if f a then forallb f l0 else false
+
+type int = ExtrNative.uint
+
+(** val lsl0 : int -> int -> int **)
+
+let lsl0 = ExtrNative.l_sl
+
+(** val lsr0 : int -> int -> int **)
+
+let lsr0 = ExtrNative.l_sr
+
+(** val land0 : int -> int -> int **)
+
+let land0 = ExtrNative.l_and
+
+(** val lxor0 : int -> int -> int **)
+
+let lxor0 = ExtrNative.l_xor
+
+(** val sub0 : int -> int -> int **)
+
+let sub0 = ExtrNative.sub
+
+(** val eqb0 : int -> int -> bool **)
+
+let eqb0 = fun i j -> ExtrNative.compare i j = ExtrNative.Eq
+
+(** val ltb0 : int -> int -> bool **)
+
+let ltb0 = ExtrNative.lt
+
+(** val leb0 : int -> int -> bool **)
+
+let leb0 = ExtrNative.le
+
+(** val foldi_cont :
+ (int -> ('a1 -> 'a2) -> 'a1 -> 'a2) -> int -> int -> ('a1 -> 'a2) -> 'a1
+ -> 'a2 **)
+
+let foldi_cont = ExtrNative.foldi_cont
+
+(** val foldi_down_cont :
+ (int -> ('a1 -> 'a2) -> 'a1 -> 'a2) -> int -> int -> ('a1 -> 'a2) -> 'a1
+ -> 'a2 **)
+
+let foldi_down_cont = ExtrNative.foldi_down_cont
+
+(** val is_zero : int -> bool **)
+
+let is_zero i =
+ eqb0 i (ExtrNative.of_uint(0))
+
+(** val is_even : int -> bool **)
+
+let is_even i =
+ is_zero (land0 i (ExtrNative.of_uint(1)))
+
+(** val compare0 : int -> int -> ExtrNative.comparison **)
+
+let compare0 = ExtrNative.compare
+
+(** val foldi : (int -> 'a1 -> 'a1) -> int -> int -> 'a1 -> 'a1 **)
+
+let foldi f from to0 =
+ foldi_cont (fun i cont a -> cont (f i a)) from to0 (fun a -> a)
+
+(** val fold : ('a1 -> 'a1) -> int -> int -> 'a1 -> 'a1 **)
+
+let fold f from to0 =
+ foldi_cont (fun i cont a -> cont (f a)) from to0 (fun a -> a)
+
+(** val foldi_down : (int -> 'a1 -> 'a1) -> int -> int -> 'a1 -> 'a1 **)
+
+let foldi_down f from downto0 =
+ foldi_down_cont (fun i cont a -> cont (f i a)) from downto0 (fun a -> a)
+
+(** val forallb0 : (int -> bool) -> int -> int -> bool **)
+
+let forallb0 f from to0 =
+ foldi_cont (fun i cont x -> if f i then cont Tt else false) from to0
+ (fun x -> true) Tt
+
+(** val existsb0 : (int -> bool) -> int -> int -> bool **)
+
+let existsb0 f from to0 =
+ foldi_cont (fun i cont x -> if f i then true else cont Tt) from to0
+ (fun x -> false) Tt
+
+(** val cast : int -> int -> (__ -> __ -> __) option **)
+
+let cast i j =
+ if eqb0 i j then Some (fun _ hi -> hi) else None
+
+(** val reflect_eqb : int -> int -> reflect **)
+
+let reflect_eqb i j =
+ iff_reflect (eqb0 i j)
+
+type 'a array = 'a ExtrNative.parray
+
+(** val make : int -> 'a1 -> 'a1 array **)
+
+let make = ExtrNative.parray_make
+
+module Coq__2 = struct
+ (** val get : 'a1 array -> int -> 'a1 **)
+
+ let get = ExtrNative.parray_get
+end
+let get = Coq__2.get
+
+(** val default : 'a1 array -> 'a1 **)
+
+let default = ExtrNative.parray_default
+
+(** val set : 'a1 array -> int -> 'a1 -> 'a1 array **)
+
+let set = ExtrNative.parray_set
+
+(** val length : 'a1 array -> int **)
+
+let length = ExtrNative.parray_length
+
+(** val to_list : 'a1 array -> 'a1 list **)
+
+let to_list t0 =
+ let len = length t0 in
+ if eqb0 (ExtrNative.of_uint(0)) len
+ then Nil
+ else foldi_down (fun i l -> Cons ((get t0 i), l))
+ (sub0 len (ExtrNative.of_uint(1))) (ExtrNative.of_uint(0)) Nil
+
+(** val forallbi : (int -> 'a1 -> bool) -> 'a1 array -> bool **)
+
+let forallbi f t0 =
+ let len = length t0 in
+ if eqb0 (ExtrNative.of_uint(0)) len
+ then true
+ else forallb0 (fun i -> f i (get t0 i)) (ExtrNative.of_uint(0))
+ (sub0 len (ExtrNative.of_uint(1)))
+
+(** val forallb1 : ('a1 -> bool) -> 'a1 array -> bool **)
+
+let forallb1 f t0 =
+ let len = length t0 in
+ if eqb0 (ExtrNative.of_uint(0)) len
+ then true
+ else forallb0 (fun i -> f (get t0 i)) (ExtrNative.of_uint(0))
+ (sub0 len (ExtrNative.of_uint(1)))
+
+(** val existsb1 : ('a1 -> bool) -> 'a1 array -> bool **)
+
+let existsb1 f t0 =
+ let len = length t0 in
+ if eqb0 (ExtrNative.of_uint(0)) len
+ then false
+ else existsb0 (fun i -> f (get t0 i)) (ExtrNative.of_uint(0))
+ (sub0 len (ExtrNative.of_uint(1)))
+
+(** val mapi : (int -> 'a1 -> 'a2) -> 'a1 array -> 'a2 array **)
+
+let mapi f t0 =
+ let size0 = length t0 in
+ let def = f size0 (default t0) in
+ let tb = make size0 def in
+ if eqb0 size0 (ExtrNative.of_uint(0))
+ then tb
+ else foldi (fun i tb0 -> set tb0 i (f i (get t0 i)))
+ (ExtrNative.of_uint(0)) (sub0 size0 (ExtrNative.of_uint(1))) tb
+
+(** val foldi_left :
+ (int -> 'a1 -> 'a2 -> 'a1) -> 'a1 -> 'a2 array -> 'a1 **)
+
+let foldi_left f a t0 =
+ let len = length t0 in
+ if eqb0 (ExtrNative.of_uint(0)) len
+ then a
+ else foldi (fun i a0 -> f i a0 (get t0 i)) (ExtrNative.of_uint(0))
+ (sub0 len (ExtrNative.of_uint(1))) a
+
+(** val fold_left : ('a1 -> 'a2 -> 'a1) -> 'a1 -> 'a2 array -> 'a1 **)
+
+let fold_left f a t0 =
+ let len = length t0 in
+ if eqb0 (ExtrNative.of_uint(0)) len
+ then a
+ else foldi (fun i a0 -> f a0 (get t0 i)) (ExtrNative.of_uint(0))
+ (sub0 (length t0) (ExtrNative.of_uint(1))) a
+
+(** val foldi_right :
+ (int -> 'a1 -> 'a2 -> 'a2) -> 'a1 array -> 'a2 -> 'a2 **)
+
+let foldi_right f t0 b =
+ let len = length t0 in
+ if eqb0 (ExtrNative.of_uint(0)) len
+ then b
+ else foldi_down (fun i b0 -> f i (get t0 i) b0)
+ (sub0 len (ExtrNative.of_uint(1))) (ExtrNative.of_uint(0)) b
+
+module Valuation =
+ struct
+ type t = int -> bool
+ end
+
+module Var =
+ struct
+ (** val _true : int **)
+
+ let _true =
+ (ExtrNative.of_uint(0))
+
+ (** val _false : int **)
+
+ let _false =
+ (ExtrNative.of_uint(1))
+
+ (** val interp : Valuation.t -> int -> bool **)
+
+ let interp rho x =
+ rho x
+ end
+
+module Lit =
+ struct
+ (** val is_pos : int -> bool **)
+
+ let is_pos l =
+ is_even l
+
+ (** val blit : int -> int **)
+
+ let blit l =
+ lsr0 l (ExtrNative.of_uint(1))
+
+ (** val lit : int -> int **)
+
+ let lit x =
+ lsl0 x (ExtrNative.of_uint(1))
+
+ (** val neg : int -> int **)
+
+ let neg l =
+ lxor0 l (ExtrNative.of_uint(1))
+
+ (** val nlit : int -> int **)
+
+ let nlit x =
+ neg (lit x)
+
+ (** val _true : int **)
+
+ let _true =
+ (ExtrNative.of_uint(0))
+
+ (** val _false : int **)
+
+ let _false =
+ (ExtrNative.of_uint(2))
+
+ (** val eqb : int -> int -> bool **)
+
+ let eqb l l' =
+ eqb0 l l'
+
+ (** val interp : Valuation.t -> int -> bool **)
+
+ let interp rho l =
+ if is_pos l
+ then Var.interp rho (blit l)
+ else negb (Var.interp rho (blit l))
+ end
+
+module C =
+ struct
+ type t = int list
+
+ (** val interp : Valuation.t -> t -> bool **)
+
+ let interp rho l =
+ existsb (Lit.interp rho) l
+
+ (** val _true : t **)
+
+ let _true =
+ Cons (Lit._true, Nil)
+
+ (** val is_false : t -> bool **)
+
+ let is_false = function
+ | Nil -> true
+ | Cons (i, l) -> false
+
+ (** val or_aux : (t -> t -> t) -> int -> t -> t -> int list **)
+
+ let rec or_aux or0 l1 c1 c2 = match c2 with
+ | Nil -> Cons (l1, c1)
+ | Cons (l2, c2') ->
+ (match compare0 l1 l2 with
+ | ExtrNative.Eq -> Cons (l1, (or0 c1 c2'))
+ | ExtrNative.Lt -> Cons (l1, (or0 c1 c2))
+ | ExtrNative.Gt -> Cons (l2, (or_aux or0 l1 c1 c2')))
+
+ (** val coq_or : t -> t -> t **)
+
+ let rec coq_or c1 c2 =
+ match c1 with
+ | Nil -> c2
+ | Cons (l1, c3) ->
+ (match c2 with
+ | Nil -> c1
+ | Cons (l2, c2') ->
+ (match compare0 l1 l2 with
+ | ExtrNative.Eq -> Cons (l1, (coq_or c3 c2'))
+ | ExtrNative.Lt -> Cons (l1, (coq_or c3 c2))
+ | ExtrNative.Gt -> Cons (l2, (or_aux coq_or l1 c3 c2'))))
+
+ (** val resolve_aux : (t -> t -> t) -> int -> t -> t -> t **)
+
+ let rec resolve_aux resolve0 l1 c1 c2 = match c2 with
+ | Nil -> _true
+ | Cons (l2, c2') ->
+ (match compare0 l1 l2 with
+ | ExtrNative.Eq -> Cons (l1, (resolve0 c1 c2'))
+ | ExtrNative.Lt ->
+ if eqb0 (lxor0 l1 l2) (ExtrNative.of_uint(1))
+ then coq_or c1 c2'
+ else Cons (l1, (resolve0 c1 c2))
+ | ExtrNative.Gt ->
+ if eqb0 (lxor0 l1 l2) (ExtrNative.of_uint(1))
+ then coq_or c1 c2'
+ else Cons (l2, (resolve_aux resolve0 l1 c1 c2')))
+
+ (** val resolve : t -> t -> t **)
+
+ let rec resolve c1 c2 =
+ match c1 with
+ | Nil -> _true
+ | Cons (l1, c3) ->
+ (match c2 with
+ | Nil -> _true
+ | Cons (l2, c2') ->
+ (match compare0 l1 l2 with
+ | ExtrNative.Eq -> Cons (l1, (resolve c3 c2'))
+ | ExtrNative.Lt ->
+ if eqb0 (lxor0 l1 l2) (ExtrNative.of_uint(1))
+ then coq_or c3 c2'
+ else Cons (l1, (resolve c3 c2))
+ | ExtrNative.Gt ->
+ if eqb0 (lxor0 l1 l2) (ExtrNative.of_uint(1))
+ then coq_or c3 c2'
+ else Cons (l2, (resolve_aux resolve l1 c3 c2'))))
+ end
+
+module S =
+ struct
+ type t = C.t array
+
+ (** val get : t -> int -> C.t **)
+
+ let get s cid =
+ get s cid
+
+ (** val internal_set : t -> int -> C.t -> t **)
+
+ let internal_set s cid c =
+ set s cid c
+
+ (** val make : int -> t **)
+
+ let make nclauses =
+ make nclauses C._true
+
+ (** val insert : int -> int list -> int list **)
+
+ let rec insert l1 c = match c with
+ | Nil -> Cons (l1, Nil)
+ | Cons (l2, c') ->
+ (match compare0 l1 l2 with
+ | ExtrNative.Eq -> c
+ | ExtrNative.Lt ->
+ if eqb0 (lxor0 l1 l2) (ExtrNative.of_uint(1))
+ then C._true
+ else Cons (l1, c)
+ | ExtrNative.Gt ->
+ if eqb0 (lxor0 l1 l2) (ExtrNative.of_uint(1))
+ then C._true
+ else Cons (l2, (insert l1 c')))
+
+ (** val sort_uniq : int list -> int list **)
+
+ let rec sort_uniq = function
+ | Nil -> Nil
+ | Cons (l1, c0) -> insert l1 (sort_uniq c0)
+
+ (** val set_clause : t -> int -> C.t -> t **)
+
+ let set_clause s pos c =
+ set s pos (sort_uniq c)
+
+ (** val set_resolve : t -> int -> int array -> t **)
+
+ let set_resolve s pos r =
+ let len = length r in
+ if eqb0 len (ExtrNative.of_uint(0))
+ then s
+ else let c =
+ foldi (fun i c -> C.resolve (get s (Coq__2.get r i)) c)
+ (ExtrNative.of_uint(1)) (sub0 len (ExtrNative.of_uint(1)))
+ (get s (Coq__2.get r (ExtrNative.of_uint(0))))
+ in
+ internal_set s pos c
+ end
+
+(** val afold_left :
+ 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a2 -> 'a1) -> 'a2 array -> 'a1 **)
+
+let afold_left default0 oP f v =
+ let n0 = length v in
+ if eqb0 n0 (ExtrNative.of_uint(0))
+ then default0
+ else foldi (fun i a -> oP a (f (get v i))) (ExtrNative.of_uint(1))
+ (sub0 n0 (ExtrNative.of_uint(1)))
+ (f (get v (ExtrNative.of_uint(0))))
+
+(** val afold_right :
+ 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a2 -> 'a1) -> 'a2 array -> 'a1 **)
+
+let afold_right default0 oP f v =
+ let n0 = length v in
+ if eqb0 n0 (ExtrNative.of_uint(0))
+ then default0
+ else if leb0 n0 (ExtrNative.of_uint(1))
+ then f (get v (ExtrNative.of_uint(0)))
+ else foldi_down (fun i b -> oP (f (get v i)) b)
+ (sub0 n0 (ExtrNative.of_uint(2))) (ExtrNative.of_uint(0))
+ (f (get v (sub0 n0 (ExtrNative.of_uint(1)))))
+
+(** val rev_aux : 'a1 list -> 'a1 list -> 'a1 list **)
+
+let rec rev_aux acc = function
+| Nil -> acc
+| Cons (t0, q) -> rev_aux (Cons (t0, acc)) q
+
+(** val rev : 'a1 list -> 'a1 list **)
+
+let rev l =
+ rev_aux Nil l
+
+(** val distinct_aux2 :
+ ('a1 -> 'a1 -> bool) -> bool -> 'a1 -> 'a1 list -> bool **)
+
+let rec distinct_aux2 eq acc ref = function
+| Nil -> acc
+| Cons (t0, q) ->
+ distinct_aux2 eq (if acc then negb (eq ref t0) else false) ref q
+
+(** val distinct_aux : ('a1 -> 'a1 -> bool) -> bool -> 'a1 list -> bool **)
+
+let rec distinct_aux eq acc = function
+| Nil -> acc
+| Cons (t0, q) ->
+ let acc' = distinct_aux2 eq acc t0 q in distinct_aux eq acc' q
+
+(** val distinct : ('a1 -> 'a1 -> bool) -> 'a1 list -> bool **)
+
+let distinct eq =
+ distinct_aux eq true
+
+(** val forallb2 : ('a1 -> 'a2 -> bool) -> 'a1 list -> 'a2 list -> bool **)
+
+let rec forallb2 f l1 l2 =
+ match l1 with
+ | Nil ->
+ (match l2 with
+ | Nil -> true
+ | Cons (y, l) -> false)
+ | Cons (a, l3) ->
+ (match l2 with
+ | Nil -> false
+ | Cons (b, l4) -> if f a b then forallb2 f l3 l4 else false)
+
+module Form =
+ struct
+ type form =
+ | Fatom of int
+ | Ftrue
+ | Ffalse
+ | Fnot2 of int * int
+ | Fand of int array
+ | For of int array
+ | Fimp of int array
+ | Fxor of int * int
+ | Fiff of int * int
+ | Fite of int * int * int
+
+ (** val form_rect :
+ (int -> 'a1) -> 'a1 -> 'a1 -> (int -> int -> 'a1) -> (int array -> 'a1)
+ -> (int array -> 'a1) -> (int array -> 'a1) -> (int -> int -> 'a1) ->
+ (int -> int -> 'a1) -> (int -> int -> int -> 'a1) -> form -> 'a1 **)
+
+ let form_rect f f0 f1 f2 f3 f4 f5 f6 f7 f8 = function
+ | Fatom x -> f x
+ | Ftrue -> f0
+ | Ffalse -> f1
+ | Fnot2 (x, x0) -> f2 x x0
+ | Fand x -> f3 x
+ | For x -> f4 x
+ | Fimp x -> f5 x
+ | Fxor (x, x0) -> f6 x x0
+ | Fiff (x, x0) -> f7 x x0
+ | Fite (x, x0, x1) -> f8 x x0 x1
+
+ (** val form_rec :
+ (int -> 'a1) -> 'a1 -> 'a1 -> (int -> int -> 'a1) -> (int array -> 'a1)
+ -> (int array -> 'a1) -> (int array -> 'a1) -> (int -> int -> 'a1) ->
+ (int -> int -> 'a1) -> (int -> int -> int -> 'a1) -> form -> 'a1 **)
+
+ let form_rec f f0 f1 f2 f3 f4 f5 f6 f7 f8 = function
+ | Fatom x -> f x
+ | Ftrue -> f0
+ | Ffalse -> f1
+ | Fnot2 (x, x0) -> f2 x x0
+ | Fand x -> f3 x
+ | For x -> f4 x
+ | Fimp x -> f5 x
+ | Fxor (x, x0) -> f6 x x0
+ | Fiff (x, x0) -> f7 x x0
+ | Fite (x, x0, x1) -> f8 x x0 x1
+
+ (** val is_Ftrue : form -> bool **)
+
+ let is_Ftrue = function
+ | Ftrue -> true
+ | _ -> false
+
+ (** val is_Ffalse : form -> bool **)
+
+ let is_Ffalse = function
+ | Ffalse -> true
+ | _ -> false
+
+ (** val interp_aux : (int -> bool) -> (int -> bool) -> form -> bool **)
+
+ let interp_aux interp_atom interp_var = function
+ | Fatom a -> interp_atom a
+ | Ftrue -> true
+ | Ffalse -> false
+ | Fnot2 (i, l) ->
+ fold (fun b -> negb (negb b)) (ExtrNative.of_uint(1)) i
+ (Lit.interp interp_var l)
+ | Fand args ->
+ afold_left true (fun b1 b2 -> if b1 then b2 else false)
+ (Lit.interp interp_var) args
+ | For args ->
+ afold_left false (fun b1 b2 -> if b1 then true else b2)
+ (Lit.interp interp_var) args
+ | Fimp args -> afold_right true implb (Lit.interp interp_var) args
+ | Fxor (a, b) -> xorb (Lit.interp interp_var a) (Lit.interp interp_var b)
+ | Fiff (a, b) -> eqb (Lit.interp interp_var a) (Lit.interp interp_var b)
+ | Fite (a, b, c) ->
+ if Lit.interp interp_var a
+ then Lit.interp interp_var b
+ else Lit.interp interp_var c
+
+ (** val t_interp : (int -> bool) -> form array -> bool array **)
+
+ let t_interp interp_atom t_form =
+ foldi_left (fun i t_b hf ->
+ set t_b i (interp_aux interp_atom (get t_b) hf))
+ (make (length t_form) true) t_form
+
+ (** val lt_form : int -> form -> bool **)
+
+ let rec lt_form i = function
+ | Fnot2 (i0, l) -> ltb0 (Lit.blit l) i
+ | Fand args -> forallb1 (fun l -> ltb0 (Lit.blit l) i) args
+ | For args -> forallb1 (fun l -> ltb0 (Lit.blit l) i) args
+ | Fimp args -> forallb1 (fun l -> ltb0 (Lit.blit l) i) args
+ | Fxor (a, b) -> if ltb0 (Lit.blit a) i then ltb0 (Lit.blit b) i else false
+ | Fiff (a, b) -> if ltb0 (Lit.blit a) i then ltb0 (Lit.blit b) i else false
+ | Fite (a, b, c) ->
+ if if ltb0 (Lit.blit a) i then ltb0 (Lit.blit b) i else false
+ then ltb0 (Lit.blit c) i
+ else false
+ | _ -> true
+
+ (** val wf : form array -> bool **)
+
+ let wf t_form =
+ forallbi lt_form t_form
+
+ (** val interp_state_var : (int -> bool) -> form array -> int -> bool **)
+
+ let interp_state_var interp_atom t_form =
+ let t_interp0 = t_interp interp_atom t_form in get t_interp0
+
+ (** val interp : (int -> bool) -> form array -> form -> bool **)
+
+ let interp interp_atom t_form =
+ interp_aux interp_atom (interp_state_var interp_atom t_form)
+
+ (** val check_form : form array -> bool **)
+
+ let check_form t_form =
+ if if if is_Ftrue (default t_form)
+ then is_Ftrue (get t_form (ExtrNative.of_uint(0)))
+ else false
+ then is_Ffalse (get t_form (ExtrNative.of_uint(1)))
+ else false
+ then wf t_form
+ else false
+ end
+
+type typ_eqb = { te_eqb : (__ -> __ -> bool);
+ te_reflect : (__ -> __ -> reflect) }
+
+type te_carrier = __
+
+(** val te_eqb : typ_eqb -> te_carrier -> te_carrier -> bool **)
+
+let te_eqb x = x.te_eqb
+
+module Typ =
+ struct
+ type coq_type =
+ | Tindex of int
+ | TZ
+ | Tbool
+ | Tpositive
+
+ (** val type_rect :
+ (int -> 'a1) -> 'a1 -> 'a1 -> 'a1 -> coq_type -> 'a1 **)
+
+ let type_rect f f0 f1 f2 = function
+ | Tindex x -> f x
+ | TZ -> f0
+ | Tbool -> f1
+ | Tpositive -> f2
+
+ (** val type_rec : (int -> 'a1) -> 'a1 -> 'a1 -> 'a1 -> coq_type -> 'a1 **)
+
+ let type_rec f f0 f1 f2 = function
+ | Tindex x -> f x
+ | TZ -> f0
+ | Tbool -> f1
+ | Tpositive -> f2
+
+ type ftype = coq_type list*coq_type
+
+ type interp = __
+
+ type interp_ftype = __
+
+ (** val i_eqb : typ_eqb array -> coq_type -> interp -> interp -> bool **)
+
+ let i_eqb t_i = function
+ | Tindex i -> (get t_i i).te_eqb
+ | TZ -> Obj.magic zeq_bool
+ | Tbool -> Obj.magic eqb
+ | Tpositive -> Obj.magic Coq_Pos.eqb
+
+ (** val reflect_i_eqb :
+ typ_eqb array -> coq_type -> interp -> interp -> reflect **)
+
+ let reflect_i_eqb t_i t0 x y =
+ iff_reflect (i_eqb t_i t0 x y)
+
+ type cast_result =
+ | Cast of (__ -> __ -> __)
+ | NoCast
+
+ (** val cast_result_rect :
+ coq_type -> coq_type -> ((__ -> __ -> __) -> 'a1) -> 'a1 -> cast_result
+ -> 'a1 **)
+
+ let cast_result_rect a b f f0 = function
+ | Cast x -> f x
+ | NoCast -> f0
+
+ (** val cast_result_rec :
+ coq_type -> coq_type -> ((__ -> __ -> __) -> 'a1) -> 'a1 -> cast_result
+ -> 'a1 **)
+
+ let cast_result_rec a b f f0 = function
+ | Cast x -> f x
+ | NoCast -> f0
+
+ (** val cast : coq_type -> coq_type -> cast_result **)
+
+ let cast a b =
+ match a with
+ | Tindex i ->
+ (match b with
+ | Tindex j ->
+ (match cast i j with
+ | Some k -> Cast (fun _ -> k __)
+ | None -> NoCast)
+ | _ -> NoCast)
+ | TZ ->
+ (match b with
+ | TZ -> Cast (fun _ x -> x)
+ | _ -> NoCast)
+ | Tbool ->
+ (match b with
+ | Tbool -> Cast (fun _ x -> x)
+ | _ -> NoCast)
+ | Tpositive ->
+ (match b with
+ | Tpositive -> Cast (fun _ x -> x)
+ | _ -> NoCast)
+
+ (** val eqb : coq_type -> coq_type -> bool **)
+
+ let eqb a b =
+ match a with
+ | Tindex i ->
+ (match b with
+ | Tindex j -> eqb0 i j
+ | _ -> false)
+ | TZ ->
+ (match b with
+ | TZ -> true
+ | _ -> false)
+ | Tbool ->
+ (match b with
+ | Tbool -> true
+ | _ -> false)
+ | Tpositive ->
+ (match b with
+ | Tpositive -> true
+ | _ -> false)
+
+ (** val reflect_eqb : coq_type -> coq_type -> reflect **)
+
+ let reflect_eqb x y =
+ match x with
+ | Tindex i ->
+ (match y with
+ | Tindex i0 -> iff_reflect (eqb0 i i0)
+ | _ -> ReflectF)
+ | TZ ->
+ (match y with
+ | TZ -> ReflectT
+ | _ -> ReflectF)
+ | Tbool ->
+ (match y with
+ | Tbool -> ReflectT
+ | _ -> ReflectF)
+ | Tpositive ->
+ (match y with
+ | Tpositive -> ReflectT
+ | _ -> ReflectF)
+ end
+
+(** val list_beq : ('a1 -> 'a1 -> bool) -> 'a1 list -> 'a1 list -> bool **)
+
+let rec list_beq eq_A x y =
+ match x with
+ | Nil ->
+ (match y with
+ | Nil -> true
+ | Cons (a, l) -> false)
+ | Cons (x0, x1) ->
+ (match y with
+ | Nil -> false
+ | Cons (x2, x3) -> if eq_A x0 x2 then list_beq eq_A x1 x3 else false)
+
+(** val reflect_list_beq :
+ ('a1 -> 'a1 -> bool) -> ('a1 -> 'a1 -> reflect) -> 'a1 list -> 'a1 list
+ -> reflect **)
+
+let rec reflect_list_beq beq hbeq x y =
+ match x with
+ | Nil ->
+ (match y with
+ | Nil -> ReflectT
+ | Cons (a, y0) -> ReflectF)
+ | Cons (y0, l) ->
+ (match y with
+ | Nil -> ReflectF
+ | Cons (a0, y1) ->
+ let r = hbeq y0 a0 in
+ (match r with
+ | ReflectT -> reflect_list_beq beq hbeq l y1
+ | ReflectF -> ReflectF))
+
+module Atom =
+ struct
+ type cop =
+ | CO_xH
+ | CO_Z0
+
+ (** val cop_rect : 'a1 -> 'a1 -> cop -> 'a1 **)
+
+ let cop_rect f f0 = function
+ | CO_xH -> f
+ | CO_Z0 -> f0
+
+ (** val cop_rec : 'a1 -> 'a1 -> cop -> 'a1 **)
+
+ let cop_rec f f0 = function
+ | CO_xH -> f
+ | CO_Z0 -> f0
+
+ type unop =
+ | UO_xO
+ | UO_xI
+ | UO_Zpos
+ | UO_Zneg
+ | UO_Zopp
+
+ (** val unop_rect : 'a1 -> 'a1 -> 'a1 -> 'a1 -> 'a1 -> unop -> 'a1 **)
+
+ let unop_rect f f0 f1 f2 f3 = function
+ | UO_xO -> f
+ | UO_xI -> f0
+ | UO_Zpos -> f1
+ | UO_Zneg -> f2
+ | UO_Zopp -> f3
+
+ (** val unop_rec : 'a1 -> 'a1 -> 'a1 -> 'a1 -> 'a1 -> unop -> 'a1 **)
+
+ let unop_rec f f0 f1 f2 f3 = function
+ | UO_xO -> f
+ | UO_xI -> f0
+ | UO_Zpos -> f1
+ | UO_Zneg -> f2
+ | UO_Zopp -> f3
+
+ type binop =
+ | BO_Zplus
+ | BO_Zminus
+ | BO_Zmult
+ | BO_Zlt
+ | BO_Zle
+ | BO_Zge
+ | BO_Zgt
+ | BO_eq of Typ.coq_type
+
+ (** val binop_rect :
+ 'a1 -> 'a1 -> 'a1 -> 'a1 -> 'a1 -> 'a1 -> 'a1 -> (Typ.coq_type -> 'a1)
+ -> binop -> 'a1 **)
+
+ let binop_rect f f0 f1 f2 f3 f4 f5 f6 = function
+ | BO_Zplus -> f
+ | BO_Zminus -> f0
+ | BO_Zmult -> f1
+ | BO_Zlt -> f2
+ | BO_Zle -> f3
+ | BO_Zge -> f4
+ | BO_Zgt -> f5
+ | BO_eq x -> f6 x
+
+ (** val binop_rec :
+ 'a1 -> 'a1 -> 'a1 -> 'a1 -> 'a1 -> 'a1 -> 'a1 -> (Typ.coq_type -> 'a1)
+ -> binop -> 'a1 **)
+
+ let binop_rec f f0 f1 f2 f3 f4 f5 f6 = function
+ | BO_Zplus -> f
+ | BO_Zminus -> f0
+ | BO_Zmult -> f1
+ | BO_Zlt -> f2
+ | BO_Zle -> f3
+ | BO_Zge -> f4
+ | BO_Zgt -> f5
+ | BO_eq x -> f6 x
+
+ type nop =
+ Typ.coq_type
+ (* singleton inductive, whose constructor was NO_distinct *)
+
+ (** val nop_rect : (Typ.coq_type -> 'a1) -> nop -> 'a1 **)
+
+ let nop_rect f n0 =
+ f n0
+
+ (** val nop_rec : (Typ.coq_type -> 'a1) -> nop -> 'a1 **)
+
+ let nop_rec f n0 =
+ f n0
+
+ type atom =
+ | Acop of cop
+ | Auop of unop * int
+ | Abop of binop * int * int
+ | Anop of nop * int list
+ | Aapp of int * int list
+
+ (** val atom_rect :
+ (cop -> 'a1) -> (unop -> int -> 'a1) -> (binop -> int -> int -> 'a1) ->
+ (nop -> int list -> 'a1) -> (int -> int list -> 'a1) -> atom -> 'a1 **)
+
+ let atom_rect f f0 f1 f2 f3 = function
+ | Acop x -> f x
+ | Auop (x, x0) -> f0 x x0
+ | Abop (x, x0, x1) -> f1 x x0 x1
+ | Anop (x, x0) -> f2 x x0
+ | Aapp (x, x0) -> f3 x x0
+
+ (** val atom_rec :
+ (cop -> 'a1) -> (unop -> int -> 'a1) -> (binop -> int -> int -> 'a1) ->
+ (nop -> int list -> 'a1) -> (int -> int list -> 'a1) -> atom -> 'a1 **)
+
+ let atom_rec f f0 f1 f2 f3 = function
+ | Acop x -> f x
+ | Auop (x, x0) -> f0 x x0
+ | Abop (x, x0, x1) -> f1 x x0 x1
+ | Anop (x, x0) -> f2 x x0
+ | Aapp (x, x0) -> f3 x x0
+
+ (** val cop_eqb : cop -> cop -> bool **)
+
+ let cop_eqb o o' =
+ match o with
+ | CO_xH ->
+ (match o' with
+ | CO_xH -> true
+ | CO_Z0 -> false)
+ | CO_Z0 ->
+ (match o' with
+ | CO_xH -> false
+ | CO_Z0 -> true)
+
+ (** val uop_eqb : unop -> unop -> bool **)
+
+ let uop_eqb o o' =
+ match o with
+ | UO_xO ->
+ (match o' with
+ | UO_xO -> true
+ | _ -> false)
+ | UO_xI ->
+ (match o' with
+ | UO_xI -> true
+ | _ -> false)
+ | UO_Zpos ->
+ (match o' with
+ | UO_Zpos -> true
+ | _ -> false)
+ | UO_Zneg ->
+ (match o' with
+ | UO_Zneg -> true
+ | _ -> false)
+ | UO_Zopp ->
+ (match o' with
+ | UO_Zopp -> true
+ | _ -> false)
+
+ (** val bop_eqb : binop -> binop -> bool **)
+
+ let bop_eqb o o' =
+ match o with
+ | BO_Zplus ->
+ (match o' with
+ | BO_Zplus -> true
+ | _ -> false)
+ | BO_Zminus ->
+ (match o' with
+ | BO_Zminus -> true
+ | _ -> false)
+ | BO_Zmult ->
+ (match o' with
+ | BO_Zmult -> true
+ | _ -> false)
+ | BO_Zlt ->
+ (match o' with
+ | BO_Zlt -> true
+ | _ -> false)
+ | BO_Zle ->
+ (match o' with
+ | BO_Zle -> true
+ | _ -> false)
+ | BO_Zge ->
+ (match o' with
+ | BO_Zge -> true
+ | _ -> false)
+ | BO_Zgt ->
+ (match o' with
+ | BO_Zgt -> true
+ | _ -> false)
+ | BO_eq t0 ->
+ (match o' with
+ | BO_eq t' -> Typ.eqb t0 t'
+ | _ -> false)
+
+ (** val nop_eqb : nop -> nop -> bool **)
+
+ let nop_eqb o o' =
+ Typ.eqb o o'
+
+ (** val eqb : atom -> atom -> bool **)
+
+ let eqb t0 t' =
+ match t0 with
+ | Acop o ->
+ (match t' with
+ | Acop o' -> cop_eqb o o'
+ | _ -> false)
+ | Auop (o, t1) ->
+ (match t' with
+ | Auop (o', t'0) -> if uop_eqb o o' then eqb0 t1 t'0 else false
+ | _ -> false)
+ | Abop (o, t1, t2) ->
+ (match t' with
+ | Abop (o', t1', t2') ->
+ if if bop_eqb o o' then eqb0 t1 t1' else false
+ then eqb0 t2 t2'
+ else false
+ | _ -> false)
+ | Anop (o, t1) ->
+ (match t' with
+ | Anop (o', t'0) ->
+ if nop_eqb o o' then list_beq eqb0 t1 t'0 else false
+ | _ -> false)
+ | Aapp (a, la) ->
+ (match t' with
+ | Aapp (b, lb) -> if eqb0 a b then list_beq eqb0 la lb else false
+ | _ -> false)
+
+ (** val reflect_cop_eqb : cop -> cop -> reflect **)
+
+ let reflect_cop_eqb o1 o2 =
+ match o1 with
+ | CO_xH ->
+ (match o2 with
+ | CO_xH -> ReflectT
+ | CO_Z0 -> ReflectF)
+ | CO_Z0 ->
+ (match o2 with
+ | CO_xH -> ReflectF
+ | CO_Z0 -> ReflectT)
+
+ (** val reflect_uop_eqb : unop -> unop -> reflect **)
+
+ let reflect_uop_eqb o1 o2 =
+ match o1 with
+ | UO_xO ->
+ (match o2 with
+ | UO_xO -> ReflectT
+ | _ -> ReflectF)
+ | UO_xI ->
+ (match o2 with
+ | UO_xI -> ReflectT
+ | _ -> ReflectF)
+ | UO_Zpos ->
+ (match o2 with
+ | UO_Zpos -> ReflectT
+ | _ -> ReflectF)
+ | UO_Zneg ->
+ (match o2 with
+ | UO_Zneg -> ReflectT
+ | _ -> ReflectF)
+ | UO_Zopp ->
+ (match o2 with
+ | UO_Zopp -> ReflectT
+ | _ -> ReflectF)
+
+ (** val reflect_bop_eqb : binop -> binop -> reflect **)
+
+ let reflect_bop_eqb o1 o2 =
+ match o1 with
+ | BO_Zplus ->
+ (match o2 with
+ | BO_Zplus -> ReflectT
+ | _ -> ReflectF)
+ | BO_Zminus ->
+ (match o2 with
+ | BO_Zminus -> ReflectT
+ | _ -> ReflectF)
+ | BO_Zmult ->
+ (match o2 with
+ | BO_Zmult -> ReflectT
+ | _ -> ReflectF)
+ | BO_Zlt ->
+ (match o2 with
+ | BO_Zlt -> ReflectT
+ | _ -> ReflectF)
+ | BO_Zle ->
+ (match o2 with
+ | BO_Zle -> ReflectT
+ | _ -> ReflectF)
+ | BO_Zge ->
+ (match o2 with
+ | BO_Zge -> ReflectT
+ | _ -> ReflectF)
+ | BO_Zgt ->
+ (match o2 with
+ | BO_Zgt -> ReflectT
+ | _ -> ReflectF)
+ | BO_eq t0 ->
+ (match o2 with
+ | BO_eq t1 -> Typ.reflect_eqb t0 t1
+ | _ -> ReflectF)
+
+ (** val reflect_nop_eqb : nop -> nop -> reflect **)
+
+ let reflect_nop_eqb o1 o2 =
+ Typ.reflect_eqb o1 o2
+
+ (** val reflect_eqb : atom -> atom -> reflect **)
+
+ let reflect_eqb t1 t2 =
+ match t1 with
+ | Acop c ->
+ (match t2 with
+ | Acop c0 -> reflect_cop_eqb c c0
+ | _ -> ReflectF)
+ | Auop (u, i) ->
+ (match t2 with
+ | Auop (u0, i0) ->
+ let r = reflect_uop_eqb u u0 in
+ (match r with
+ | ReflectT -> reflect_eqb i i0
+ | ReflectF -> ReflectF)
+ | _ -> ReflectF)
+ | Abop (b, i, i0) ->
+ (match t2 with
+ | Abop (b0, i1, i2) ->
+ let r = reflect_bop_eqb b b0 in
+ (match r with
+ | ReflectT ->
+ let r0 = reflect_eqb i i1 in
+ (match r0 with
+ | ReflectT -> reflect_eqb i0 i2
+ | ReflectF -> ReflectF)
+ | ReflectF -> ReflectF)
+ | _ -> ReflectF)
+ | Anop (n0, l) ->
+ (match t2 with
+ | Anop (n1, l0) ->
+ let r = reflect_nop_eqb n0 n1 in
+ (match r with
+ | ReflectT -> reflect_list_beq eqb0 reflect_eqb l l0
+ | ReflectF -> ReflectF)
+ | _ -> ReflectF)
+ | Aapp (i, l) ->
+ (match t2 with
+ | Aapp (i0, l0) ->
+ let r = reflect_eqb i i0 in
+ (match r with
+ | ReflectT -> reflect_list_beq eqb0 reflect_eqb l l0
+ | ReflectF -> ReflectF)
+ | _ -> ReflectF)
+
+ type ('t, 'i) coq_val = { v_type : 't; v_val : 'i }
+
+ (** val val_rect : ('a1 -> 'a2 -> 'a3) -> ('a1, 'a2) coq_val -> 'a3 **)
+
+ let val_rect f v =
+ let { v_type = x; v_val = x0 } = v in f x x0
+
+ (** val val_rec : ('a1 -> 'a2 -> 'a3) -> ('a1, 'a2) coq_val -> 'a3 **)
+
+ let val_rec f v =
+ let { v_type = x; v_val = x0 } = v in f x x0
+
+ (** val v_type : ('a1, 'a2) coq_val -> 'a1 **)
+
+ let v_type x = x.v_type
+
+ (** val v_val : ('a1, 'a2) coq_val -> 'a2 **)
+
+ let v_val x = x.v_val
+
+ type bval = (Typ.coq_type, Typ.interp) coq_val
+
+ (** val coq_Bval :
+ typ_eqb array -> Typ.coq_type -> Typ.interp -> (Typ.coq_type,
+ Typ.interp) coq_val **)
+
+ let coq_Bval t_i x x0 =
+ { v_type = x; v_val = x0 }
+
+ type tval = (Typ.ftype, Typ.interp_ftype) coq_val
+
+ (** val coq_Tval :
+ typ_eqb array -> Typ.ftype -> Typ.interp_ftype -> (Typ.ftype,
+ Typ.interp_ftype) coq_val **)
+
+ let coq_Tval t_i x x0 =
+ { v_type = x; v_val = x0 }
+
+ (** val bvtrue : typ_eqb array -> bval **)
+
+ let bvtrue t_i =
+ coq_Bval t_i Typ.Tbool (Obj.magic true)
+
+ (** val bvfalse : typ_eqb array -> bval **)
+
+ let bvfalse t_i =
+ coq_Bval t_i Typ.Tbool (Obj.magic false)
+
+ (** val typ_cop : cop -> Typ.coq_type **)
+
+ let typ_cop = function
+ | CO_xH -> Typ.Tpositive
+ | CO_Z0 -> Typ.TZ
+
+ (** val typ_uop : unop -> Typ.coq_type*Typ.coq_type **)
+
+ let typ_uop = function
+ | UO_xO -> Typ.Tpositive,Typ.Tpositive
+ | UO_xI -> Typ.Tpositive,Typ.Tpositive
+ | UO_Zopp -> Typ.TZ,Typ.TZ
+ | _ -> Typ.Tpositive,Typ.TZ
+
+ (** val typ_bop : binop -> (Typ.coq_type*Typ.coq_type)*Typ.coq_type **)
+
+ let typ_bop = function
+ | BO_Zplus -> (Typ.TZ,Typ.TZ),Typ.TZ
+ | BO_Zminus -> (Typ.TZ,Typ.TZ),Typ.TZ
+ | BO_Zmult -> (Typ.TZ,Typ.TZ),Typ.TZ
+ | BO_eq t0 -> (t0,t0),Typ.Tbool
+ | _ -> (Typ.TZ,Typ.TZ),Typ.Tbool
+
+ (** val typ_nop : nop -> Typ.coq_type*Typ.coq_type **)
+
+ let typ_nop o =
+ o,Typ.Tbool
+
+ (** val check_args :
+ (int -> Typ.coq_type) -> int list -> Typ.coq_type list -> bool **)
+
+ let rec check_args get_type0 args targs =
+ match args with
+ | Nil ->
+ (match targs with
+ | Nil -> true
+ | Cons (t0, l) -> false)
+ | Cons (a, args0) ->
+ (match targs with
+ | Nil -> false
+ | Cons (t0, targs0) ->
+ if Typ.eqb (get_type0 a) t0
+ then check_args get_type0 args0 targs0
+ else false)
+
+ (** val check_aux :
+ typ_eqb array -> tval array -> (int -> Typ.coq_type) -> atom ->
+ Typ.coq_type -> bool **)
+
+ let check_aux t_i t_func get_type0 a t0 =
+ match a with
+ | Acop o -> Typ.eqb (typ_cop o) t0
+ | Auop (o, a0) ->
+ let ta,t' = typ_uop o in
+ if Typ.eqb t' t0 then Typ.eqb (get_type0 a0) ta else false
+ | Abop (o, a1, a2) ->
+ let ta,t' = typ_bop o in
+ let ta1,ta2 = ta in
+ if if Typ.eqb t' t0 then Typ.eqb (get_type0 a1) ta1 else false
+ then Typ.eqb (get_type0 a2) ta2
+ else false
+ | Anop (o, a0) ->
+ let ta,t' = typ_nop o in
+ if Typ.eqb t' t0
+ then forallb (fun t1 -> Typ.eqb (get_type0 t1) ta) a0
+ else false
+ | Aapp (f, args) ->
+ let targs,tr = (get t_func f).v_type in
+ if check_args get_type0 args targs then Typ.eqb tr t0 else false
+
+ (** val check_args_dec :
+ (int -> Typ.coq_type) -> Typ.coq_type -> int list -> Typ.coq_type list
+ -> sumbool **)
+
+ let rec check_args_dec get_type0 a args targs =
+ match args with
+ | Nil ->
+ (match targs with
+ | Nil -> Left
+ | Cons (t0, l) -> Right)
+ | Cons (y, l) ->
+ (match targs with
+ | Nil -> Right
+ | Cons (b, targs0) ->
+ if Typ.eqb (get_type0 y) b
+ then check_args_dec get_type0 a l targs0
+ else Right)
+
+ (** val check_aux_dec :
+ typ_eqb array -> tval array -> (int -> Typ.coq_type) -> atom -> sumbool **)
+
+ let check_aux_dec t_i t_func get_type0 = function
+ | Acop op -> Left
+ | Auop (op, h) ->
+ (match op with
+ | UO_Zopp -> if Typ.eqb (get_type0 h) Typ.TZ then Left else Right
+ | _ -> if Typ.eqb (get_type0 h) Typ.Tpositive then Left else Right)
+ | Abop (op, h1, h2) ->
+ (match op with
+ | BO_eq t0 ->
+ if Typ.eqb (get_type0 h1) t0
+ then if Typ.eqb (get_type0 h2) t0 then Left else Right
+ else Right
+ | _ ->
+ if Typ.eqb (get_type0 h1) Typ.TZ
+ then if Typ.eqb (get_type0 h2) Typ.TZ then Left else Right
+ else Right)
+ | Anop (op, ha) ->
+ if forallb (fun t1 -> Typ.eqb (get_type0 t1) op) ha then Left else Right
+ | Aapp (f, args) ->
+ let l,t0 = (get t_func f).v_type in check_args_dec get_type0 t0 args l
+
+ (** val apply_unop :
+ typ_eqb array -> Typ.coq_type -> Typ.coq_type -> (Typ.interp ->
+ Typ.interp) -> bval -> (Typ.coq_type, Typ.interp) coq_val **)
+
+ let apply_unop t_i t0 r op tv =
+ let { v_type = t'; v_val = v } = tv in
+ (match Typ.cast t' t0 with
+ | Typ.Cast k -> coq_Bval t_i r (op (k __ v))
+ | Typ.NoCast -> bvtrue t_i)
+
+ (** val apply_binop :
+ typ_eqb array -> Typ.coq_type -> Typ.coq_type -> Typ.coq_type ->
+ (Typ.interp -> Typ.interp -> Typ.interp) -> bval -> bval ->
+ (Typ.coq_type, Typ.interp) coq_val **)
+
+ let apply_binop t_i t1 t2 r op tv1 tv2 =
+ let { v_type = t1'; v_val = v1 } = tv1 in
+ let { v_type = t2'; v_val = v2 } = tv2 in
+ (match Typ.cast t1' t1 with
+ | Typ.Cast k1 ->
+ (match Typ.cast t2' t2 with
+ | Typ.Cast k2 -> coq_Bval t_i r (op (k1 __ v1) (k2 __ v2))
+ | Typ.NoCast -> bvtrue t_i)
+ | Typ.NoCast -> bvtrue t_i)
+
+ (** val apply_func :
+ typ_eqb array -> Typ.coq_type list -> Typ.coq_type -> Typ.interp_ftype
+ -> bval list -> bval **)
+
+ let rec apply_func t_i targs tr f lv =
+ match targs with
+ | Nil ->
+ (match lv with
+ | Nil -> coq_Bval t_i tr f
+ | Cons (b, l) -> bvtrue t_i)
+ | Cons (t0, targs0) ->
+ (match lv with
+ | Nil -> bvtrue t_i
+ | Cons (v, lv0) ->
+ let { v_type = tv; v_val = v0 } = v in
+ (match Typ.cast tv t0 with
+ | Typ.Cast k ->
+ let f0 = Obj.magic f (k __ v0) in apply_func t_i targs0 tr f0 lv0
+ | Typ.NoCast -> bvtrue t_i))
+
+ (** val interp_cop :
+ typ_eqb array -> cop -> (Typ.coq_type, Typ.interp) coq_val **)
+
+ let interp_cop t_i = function
+ | CO_xH -> coq_Bval t_i Typ.Tpositive (Obj.magic XH)
+ | CO_Z0 -> coq_Bval t_i Typ.TZ (Obj.magic Z0)
+
+ (** val interp_uop :
+ typ_eqb array -> unop -> bval -> (Typ.coq_type, Typ.interp) coq_val **)
+
+ let interp_uop t_i = function
+ | UO_xO ->
+ apply_unop t_i Typ.Tpositive Typ.Tpositive (Obj.magic (fun x -> XO x))
+ | UO_xI ->
+ apply_unop t_i Typ.Tpositive Typ.Tpositive (Obj.magic (fun x -> XI x))
+ | UO_Zpos ->
+ apply_unop t_i Typ.Tpositive Typ.TZ (Obj.magic (fun x -> Zpos x))
+ | UO_Zneg ->
+ apply_unop t_i Typ.Tpositive Typ.TZ (Obj.magic (fun x -> Zneg x))
+ | UO_Zopp -> apply_unop t_i Typ.TZ Typ.TZ (Obj.magic Z.opp)
+
+ (** val interp_bop :
+ typ_eqb array -> binop -> bval -> bval -> (Typ.coq_type, Typ.interp)
+ coq_val **)
+
+ let interp_bop t_i = function
+ | BO_Zplus -> apply_binop t_i Typ.TZ Typ.TZ Typ.TZ (Obj.magic Z.add)
+ | BO_Zminus -> apply_binop t_i Typ.TZ Typ.TZ Typ.TZ (Obj.magic Z.sub)
+ | BO_Zmult -> apply_binop t_i Typ.TZ Typ.TZ Typ.TZ (Obj.magic Z.mul)
+ | BO_Zlt -> apply_binop t_i Typ.TZ Typ.TZ Typ.Tbool (Obj.magic Z.ltb)
+ | BO_Zle -> apply_binop t_i Typ.TZ Typ.TZ Typ.Tbool (Obj.magic Z.leb)
+ | BO_Zge -> apply_binop t_i Typ.TZ Typ.TZ Typ.Tbool (Obj.magic Z.geb)
+ | BO_Zgt -> apply_binop t_i Typ.TZ Typ.TZ Typ.Tbool (Obj.magic Z.gtb)
+ | BO_eq t0 ->
+ apply_binop t_i t0 t0 Typ.Tbool (Obj.magic (Typ.i_eqb t_i t0))
+
+ (** val compute_interp :
+ typ_eqb array -> (int -> bval) -> Typ.coq_type -> Typ.interp list ->
+ int list -> Typ.interp list option **)
+
+ let rec compute_interp t_i interp_hatom0 ty acc = function
+ | Nil -> Some acc
+ | Cons (a, q) ->
+ let { v_type = ta; v_val = va } = interp_hatom0 a in
+ (match Typ.cast ta ty with
+ | Typ.Cast ka ->
+ compute_interp t_i interp_hatom0 ty (Cons ((ka __ va), acc)) q
+ | Typ.NoCast -> None)
+
+ (** val interp_aux :
+ typ_eqb array -> tval array -> (int -> bval) -> atom -> bval **)
+
+ let interp_aux t_i t_func interp_hatom0 = function
+ | Acop o -> interp_cop t_i o
+ | Auop (o, a0) -> interp_uop t_i o (interp_hatom0 a0)
+ | Abop (o, a1, a2) ->
+ interp_bop t_i o (interp_hatom0 a1) (interp_hatom0 a2)
+ | Anop (n0, a0) ->
+ (match compute_interp t_i interp_hatom0 n0 Nil a0 with
+ | Some l ->
+ coq_Bval t_i Typ.Tbool
+ (Obj.magic (distinct (Typ.i_eqb t_i n0) (rev l)))
+ | None -> bvtrue t_i)
+ | Aapp (f, args) ->
+ let { v_type = tf; v_val = f0 } = get t_func f in
+ let lv = map interp_hatom0 args in apply_func t_i (fst tf) (snd tf) f0 lv
+
+ (** val interp_bool : typ_eqb array -> bval -> bool **)
+
+ let interp_bool t_i v =
+ let { v_type = t0; v_val = v0 } = v in
+ (match Typ.cast t0 Typ.Tbool with
+ | Typ.Cast k -> Obj.magic k __ v0
+ | Typ.NoCast -> true)
+
+ (** val t_interp :
+ typ_eqb array -> tval array -> atom array -> bval array **)
+
+ let t_interp t_i t_func t_atom =
+ foldi_left (fun i t_a a -> set t_a i (interp_aux t_i t_func (get t_a) a))
+ (make (length t_atom) (interp_cop t_i CO_xH)) t_atom
+
+ (** val lt_atom : int -> atom -> bool **)
+
+ let lt_atom i = function
+ | Acop c -> true
+ | Auop (u, h) -> ltb0 h i
+ | Abop (b, h1, h2) -> if ltb0 h1 i then ltb0 h2 i else false
+ | Anop (n0, ha) -> forallb (fun h -> ltb0 h i) ha
+ | Aapp (f, args) -> forallb (fun h -> ltb0 h i) args
+
+ (** val wf : atom array -> bool **)
+
+ let wf t_atom =
+ forallbi lt_atom t_atom
+
+ (** val get_type' : typ_eqb array -> bval array -> int -> Typ.coq_type **)
+
+ let get_type' t_i t_interp' i =
+ (get t_interp' i).v_type
+
+ (** val get_type :
+ typ_eqb array -> tval array -> atom array -> int -> Typ.coq_type **)
+
+ let get_type t_i t_func t_atom =
+ get_type' t_i (t_interp t_i t_func t_atom)
+
+ (** val wt : typ_eqb array -> tval array -> atom array -> bool **)
+
+ let wt t_i t_func t_atom =
+ let t_interp0 = t_interp t_i t_func t_atom in
+ let get_type0 = get_type' t_i t_interp0 in
+ forallbi (fun i h -> check_aux t_i t_func get_type0 h (get_type0 i))
+ t_atom
+
+ (** val interp_hatom :
+ typ_eqb array -> tval array -> atom array -> int -> bval **)
+
+ let interp_hatom t_i t_func t_atom =
+ let t_a = t_interp t_i t_func t_atom in get t_a
+
+ (** val interp :
+ typ_eqb array -> tval array -> atom array -> atom -> bval **)
+
+ let interp t_i t_func t_atom =
+ interp_aux t_i t_func (interp_hatom t_i t_func t_atom)
+
+ (** val interp_form_hatom :
+ typ_eqb array -> tval array -> atom array -> int -> bool **)
+
+ let interp_form_hatom t_i t_func t_atom =
+ let interp0 = interp_hatom t_i t_func t_atom in
+ (fun a -> interp_bool t_i (interp0 a))
+
+ (** val check_atom : atom array -> bool **)
+
+ let check_atom t_atom =
+ match default t_atom with
+ | Acop c ->
+ (match c with
+ | CO_xH -> wf t_atom
+ | CO_Z0 -> false)
+ | _ -> false
+ end
+
+(** val or_of_imp : int array -> int array **)
+
+let or_of_imp args =
+ let last = sub0 (length args) (ExtrNative.of_uint(1)) in
+ mapi (fun i l -> if eqb0 i last then l else Lit.neg l) args
+
+(** val check_True : C.t **)
+
+let check_True =
+ C._true
+
+(** val check_False : int list **)
+
+let check_False =
+ Cons ((Lit.neg Lit._false), Nil)
+
+(** val check_BuildDef : Form.form array -> int -> C.t **)
+
+let check_BuildDef t_form l =
+ match get t_form (Lit.blit l) with
+ | Form.Fand args ->
+ if Lit.is_pos l then Cons (l, (map Lit.neg (to_list args))) else C._true
+ | Form.For args ->
+ if Lit.is_pos l then C._true else Cons (l, (to_list args))
+ | Form.Fimp args ->
+ if Lit.is_pos l
+ then C._true
+ else let args0 = or_of_imp args in Cons (l, (to_list args0))
+ | Form.Fxor (a, b) ->
+ if Lit.is_pos l
+ then Cons (l, (Cons (a, (Cons ((Lit.neg b), Nil)))))
+ else Cons (l, (Cons (a, (Cons (b, Nil)))))
+ | Form.Fiff (a, b) ->
+ if Lit.is_pos l
+ then Cons (l, (Cons ((Lit.neg a), (Cons ((Lit.neg b), Nil)))))
+ else Cons (l, (Cons (a, (Cons ((Lit.neg b), Nil)))))
+ | Form.Fite (a, b, c) ->
+ if Lit.is_pos l
+ then Cons (l, (Cons (a, (Cons ((Lit.neg c), Nil)))))
+ else Cons (l, (Cons (a, (Cons (c, Nil)))))
+ | _ -> C._true
+
+(** val check_ImmBuildDef : Form.form array -> S.t -> int -> C.t **)
+
+let check_ImmBuildDef t_form s pos =
+ match S.get s pos with
+ | Nil -> C._true
+ | Cons (l, l0) ->
+ (match l0 with
+ | Nil ->
+ (match get t_form (Lit.blit l) with
+ | Form.Fand args ->
+ if Lit.is_pos l then C._true else map Lit.neg (to_list args)
+ | Form.For args -> if Lit.is_pos l then to_list args else C._true
+ | Form.Fimp args ->
+ if Lit.is_pos l
+ then let args0 = or_of_imp args in to_list args0
+ else C._true
+ | Form.Fxor (a, b) ->
+ if Lit.is_pos l
+ then Cons (a, (Cons (b, Nil)))
+ else Cons (a, (Cons ((Lit.neg b), Nil)))
+ | Form.Fiff (a, b) ->
+ if Lit.is_pos l
+ then Cons (a, (Cons ((Lit.neg b), Nil)))
+ else Cons ((Lit.neg a), (Cons ((Lit.neg b), Nil)))
+ | Form.Fite (a, b, c) ->
+ if Lit.is_pos l
+ then Cons (a, (Cons (c, Nil)))
+ else Cons (a, (Cons ((Lit.neg c), Nil)))
+ | _ -> C._true)
+ | Cons (i, l1) -> C._true)
+
+(** val check_BuildDef2 : Form.form array -> int -> C.t **)
+
+let check_BuildDef2 t_form l =
+ match get t_form (Lit.blit l) with
+ | Form.Fxor (a, b) ->
+ if Lit.is_pos l
+ then Cons (l, (Cons ((Lit.neg a), (Cons (b, Nil)))))
+ else Cons (l, (Cons ((Lit.neg a), (Cons ((Lit.neg b), Nil)))))
+ | Form.Fiff (a, b) ->
+ if Lit.is_pos l
+ then Cons (l, (Cons (a, (Cons (b, Nil)))))
+ else Cons (l, (Cons ((Lit.neg a), (Cons (b, Nil)))))
+ | Form.Fite (a, b, c) ->
+ if Lit.is_pos l
+ then Cons (l, (Cons ((Lit.neg a), (Cons ((Lit.neg b), Nil)))))
+ else Cons (l, (Cons ((Lit.neg a), (Cons (b, Nil)))))
+ | _ -> C._true
+
+(** val check_ImmBuildDef2 : Form.form array -> S.t -> int -> C.t **)
+
+let check_ImmBuildDef2 t_form s pos =
+ match S.get s pos with
+ | Nil -> C._true
+ | Cons (l, l0) ->
+ (match l0 with
+ | Nil ->
+ (match get t_form (Lit.blit l) with
+ | Form.Fxor (a, b) ->
+ if Lit.is_pos l
+ then Cons ((Lit.neg a), (Cons ((Lit.neg b), Nil)))
+ else Cons ((Lit.neg a), (Cons (b, Nil)))
+ | Form.Fiff (a, b) ->
+ if Lit.is_pos l
+ then Cons ((Lit.neg a), (Cons (b, Nil)))
+ else Cons (a, (Cons (b, Nil)))
+ | Form.Fite (a, b, c) ->
+ if Lit.is_pos l
+ then Cons ((Lit.neg a), (Cons (b, Nil)))
+ else Cons ((Lit.neg a), (Cons ((Lit.neg b), Nil)))
+ | _ -> C._true)
+ | Cons (i, l1) -> C._true)
+
+(** val check_BuildProj : Form.form array -> int -> int -> C.t **)
+
+let check_BuildProj t_form l i =
+ let x = Lit.blit l in
+ (match get t_form x with
+ | Form.Fand args ->
+ if ltb0 i (length args)
+ then Cons ((Lit.nlit x), (Cons ((get args i), Nil)))
+ else C._true
+ | Form.For args ->
+ if ltb0 i (length args)
+ then Cons ((Lit.lit x), (Cons ((Lit.neg (get args i)), Nil)))
+ else C._true
+ | Form.Fimp args ->
+ let len = length args in
+ if ltb0 i len
+ then if eqb0 i (sub0 len (ExtrNative.of_uint(1)))
+ then Cons ((Lit.lit x), (Cons ((Lit.neg (get args i)), Nil)))
+ else Cons ((Lit.lit x), (Cons ((get args i), Nil)))
+ else C._true
+ | _ -> C._true)
+
+(** val check_ImmBuildProj : Form.form array -> S.t -> int -> int -> C.t **)
+
+let check_ImmBuildProj t_form s pos i =
+ match S.get s pos with
+ | Nil -> C._true
+ | Cons (l, l0) ->
+ (match l0 with
+ | Nil ->
+ let x = Lit.blit l in
+ (match get t_form x with
+ | Form.Fand args ->
+ if if ltb0 i (length args) then Lit.is_pos l else false
+ then Cons ((get args i), Nil)
+ else C._true
+ | Form.For args ->
+ if if ltb0 i (length args) then negb (Lit.is_pos l) else false
+ then Cons ((Lit.neg (get args i)), Nil)
+ else C._true
+ | Form.Fimp args ->
+ let len = length args in
+ if if ltb0 i len then negb (Lit.is_pos l) else false
+ then if eqb0 i (sub0 len (ExtrNative.of_uint(1)))
+ then Cons ((Lit.neg (get args i)), Nil)
+ else Cons ((get args i), Nil)
+ else C._true
+ | _ -> C._true)
+ | Cons (i0, l1) -> C._true)
+
+(** val get_eq :
+ Form.form array -> Atom.atom array -> int -> (int -> int -> C.t) -> C.t **)
+
+let get_eq t_form t_atom x f =
+ match get t_form x with
+ | Form.Fatom xa ->
+ (match get t_atom xa with
+ | Atom.Abop (b0, a, b) ->
+ (match b0 with
+ | Atom.BO_eq t0 -> f a b
+ | _ -> C._true)
+ | _ -> C._true)
+ | _ -> C._true
+
+(** val check_trans_aux :
+ Form.form array -> Atom.atom array -> int -> int -> int list -> int ->
+ C.t -> C.t **)
+
+let rec check_trans_aux t_form t_atom t1 t2 eqs res clause0 =
+ match eqs with
+ | Nil ->
+ let xres = Lit.blit res in
+ get_eq t_form t_atom xres (fun t1' t2' ->
+ if if if eqb0 t1 t1' then eqb0 t2 t2' else false
+ then true
+ else if eqb0 t1 t2' then eqb0 t2 t1' else false
+ then Cons ((Lit.lit xres), clause0)
+ else C._true)
+ | Cons (leq, eqs0) ->
+ let xeq = Lit.blit leq in
+ get_eq t_form t_atom xeq (fun t0 t' ->
+ if eqb0 t2 t'
+ then check_trans_aux t_form t_atom t1 t0 eqs0 res (Cons
+ ((Lit.nlit xeq), clause0))
+ else if eqb0 t2 t0
+ then check_trans_aux t_form t_atom t1 t' eqs0 res (Cons
+ ((Lit.nlit xeq), clause0))
+ else if eqb0 t1 t'
+ then check_trans_aux t_form t_atom t0 t2 eqs0 res (Cons
+ ((Lit.nlit xeq), clause0))
+ else if eqb0 t1 t0
+ then check_trans_aux t_form t_atom t' t2 eqs0 res (Cons
+ ((Lit.nlit xeq), clause0))
+ else C._true)
+
+(** val check_trans :
+ Form.form array -> Atom.atom array -> int -> int list -> C.t **)
+
+let check_trans t_form t_atom res = function
+| Nil ->
+ let xres = Lit.blit res in
+ get_eq t_form t_atom xres (fun t1 t2 ->
+ if eqb0 t1 t2 then Cons ((Lit.lit xres), Nil) else C._true)
+| Cons (leq, eqs0) ->
+ let xeq = Lit.blit leq in
+ get_eq t_form t_atom xeq (fun t1 t2 ->
+ check_trans_aux t_form t_atom t1 t2 eqs0 res (Cons ((Lit.nlit xeq), Nil)))
+
+(** val build_congr :
+ Form.form array -> Atom.atom array -> int option list -> int list -> int
+ list -> C.t -> C.t **)
+
+let rec build_congr t_form t_atom eqs l r c =
+ match eqs with
+ | Nil ->
+ (match l with
+ | Nil ->
+ (match r with
+ | Nil -> c
+ | Cons (i, l0) -> C._true)
+ | Cons (i, l0) -> C._true)
+ | Cons (eq, eqs0) ->
+ (match l with
+ | Nil -> C._true
+ | Cons (t1, l0) ->
+ (match r with
+ | Nil -> C._true
+ | Cons (t2, r0) ->
+ (match eq with
+ | Some leq ->
+ let xeq = Lit.blit leq in
+ get_eq t_form t_atom xeq (fun t1' t2' ->
+ if if if eqb0 t1 t1' then eqb0 t2 t2' else false
+ then true
+ else if eqb0 t1 t2' then eqb0 t2 t1' else false
+ then build_congr t_form t_atom eqs0 l0 r0 (Cons
+ ((Lit.nlit xeq), c))
+ else C._true)
+ | None ->
+ if eqb0 t1 t2
+ then build_congr t_form t_atom eqs0 l0 r0 c
+ else C._true)))
+
+(** val check_congr :
+ Form.form array -> Atom.atom array -> int -> int option list -> C.t **)
+
+let check_congr t_form t_atom leq eqs =
+ let xeq = Lit.blit leq in
+ get_eq t_form t_atom xeq (fun t1 t2 ->
+ match get t_atom t1 with
+ | Atom.Auop (o1, a) ->
+ (match get t_atom t2 with
+ | Atom.Auop (o2, b) ->
+ if Atom.uop_eqb o1 o2
+ then build_congr t_form t_atom eqs (Cons (a, Nil)) (Cons (b, Nil))
+ (Cons ((Lit.lit xeq), Nil))
+ else C._true
+ | _ -> C._true)
+ | Atom.Abop (o1, a1, a2) ->
+ (match get t_atom t2 with
+ | Atom.Abop (o2, b1, b2) ->
+ if Atom.bop_eqb o1 o2
+ then build_congr t_form t_atom eqs (Cons (a1, (Cons (a2, Nil))))
+ (Cons (b1, (Cons (b2, Nil)))) (Cons ((Lit.lit xeq), Nil))
+ else C._true
+ | _ -> C._true)
+ | Atom.Aapp (f1, args1) ->
+ (match get t_atom t2 with
+ | Atom.Aapp (f2, args2) ->
+ if eqb0 f1 f2
+ then build_congr t_form t_atom eqs args1 args2 (Cons ((Lit.lit xeq),
+ Nil))
+ else C._true
+ | _ -> C._true)
+ | _ -> C._true)
+
+(** val check_congr_pred :
+ Form.form array -> Atom.atom array -> int -> int -> int option list ->
+ C.t **)
+
+let check_congr_pred t_form t_atom pA pB eqs =
+ let xPA = Lit.blit pA in
+ let xPB = Lit.blit pB in
+ (match get t_form xPA with
+ | Form.Fatom pa ->
+ (match get t_form xPB with
+ | Form.Fatom pb ->
+ (match get t_atom pa with
+ | Atom.Auop (o1, a) ->
+ (match get t_atom pb with
+ | Atom.Auop (o2, b) ->
+ if Atom.uop_eqb o1 o2
+ then build_congr t_form t_atom eqs (Cons (a, Nil)) (Cons (b,
+ Nil)) (Cons ((Lit.nlit xPA), (Cons ((Lit.lit xPB),
+ Nil))))
+ else C._true
+ | _ -> C._true)
+ | Atom.Abop (o1, a1, a2) ->
+ (match get t_atom pb with
+ | Atom.Abop (o2, b1, b2) ->
+ if Atom.bop_eqb o1 o2
+ then build_congr t_form t_atom eqs (Cons (a1, (Cons (a2,
+ Nil)))) (Cons (b1, (Cons (b2, Nil)))) (Cons
+ ((Lit.nlit xPA), (Cons ((Lit.lit xPB), Nil))))
+ else C._true
+ | _ -> C._true)
+ | Atom.Aapp (p, a) ->
+ (match get t_atom pb with
+ | Atom.Aapp (p', b) ->
+ if eqb0 p p'
+ then build_congr t_form t_atom eqs a b (Cons ((Lit.nlit xPA),
+ (Cons ((Lit.lit xPB), Nil))))
+ else C._true
+ | _ -> C._true)
+ | _ -> C._true)
+ | _ -> C._true)
+ | _ -> C._true)
+
+type 'c pol =
+| Pc of 'c
+| Pinj of positive * 'c pol
+| PX of 'c pol * positive * 'c pol
+
+(** val p0 : 'a1 -> 'a1 pol **)
+
+let p0 cO =
+ Pc cO
+
+(** val p1 : 'a1 -> 'a1 pol **)
+
+let p1 cI =
+ Pc cI
+
+(** val peq : ('a1 -> 'a1 -> bool) -> 'a1 pol -> 'a1 pol -> bool **)
+
+let rec peq ceqb p p' =
+ match p with
+ | Pc c ->
+ (match p' with
+ | Pc c' -> ceqb c c'
+ | _ -> false)
+ | Pinj (j, q) ->
+ (match p' with
+ | Pinj (j', q') ->
+ (match Coq_Pos.compare j j' with
+ | ExtrNative.Eq -> peq ceqb q q'
+ | _ -> false)
+ | _ -> false)
+ | PX (p2, i, q) ->
+ (match p' with
+ | PX (p'0, i', q') ->
+ (match Coq_Pos.compare i i' with
+ | ExtrNative.Eq -> if peq ceqb p2 p'0 then peq ceqb q q' else false
+ | _ -> false)
+ | _ -> false)
+
+(** val mkPinj : positive -> 'a1 pol -> 'a1 pol **)
+
+let mkPinj j p = match p with
+| Pc c -> p
+| Pinj (j', q) -> Pinj ((Coq_Pos.add j j'), q)
+| PX (p2, p3, p4) -> Pinj (j, p)
+
+(** val mkPinj_pred : positive -> 'a1 pol -> 'a1 pol **)
+
+let mkPinj_pred j p =
+ match j with
+ | XI j0 -> Pinj ((XO j0), p)
+ | XO j0 -> Pinj ((Coq_Pos.pred_double j0), p)
+ | XH -> p
+
+(** val mkPX :
+ 'a1 -> ('a1 -> 'a1 -> bool) -> 'a1 pol -> positive -> 'a1 pol -> 'a1 pol **)
+
+let mkPX cO ceqb p i q =
+ match p with
+ | Pc c -> if ceqb c cO then mkPinj XH q else PX (p, i, q)
+ | Pinj (p2, p3) -> PX (p, i, q)
+ | PX (p', i', q') ->
+ if peq ceqb q' (p0 cO)
+ then PX (p', (Coq_Pos.add i' i), q)
+ else PX (p, i, q)
+
+(** val mkXi : 'a1 -> 'a1 -> positive -> 'a1 pol **)
+
+let mkXi cO cI i =
+ PX ((p1 cI), i, (p0 cO))
+
+(** val mkX : 'a1 -> 'a1 -> 'a1 pol **)
+
+let mkX cO cI =
+ mkXi cO cI XH
+
+(** val popp : ('a1 -> 'a1) -> 'a1 pol -> 'a1 pol **)
+
+let rec popp copp = function
+| Pc c -> Pc (copp c)
+| Pinj (j, q) -> Pinj (j, (popp copp q))
+| PX (p2, i, q) -> PX ((popp copp p2), i, (popp copp q))
+
+(** val paddC : ('a1 -> 'a1 -> 'a1) -> 'a1 pol -> 'a1 -> 'a1 pol **)
+
+let rec paddC cadd p c =
+ match p with
+ | Pc c1 -> Pc (cadd c1 c)
+ | Pinj (j, q) -> Pinj (j, (paddC cadd q c))
+ | PX (p2, i, q) -> PX (p2, i, (paddC cadd q c))
+
+(** val psubC : ('a1 -> 'a1 -> 'a1) -> 'a1 pol -> 'a1 -> 'a1 pol **)
+
+let rec psubC csub p c =
+ match p with
+ | Pc c1 -> Pc (csub c1 c)
+ | Pinj (j, q) -> Pinj (j, (psubC csub q c))
+ | PX (p2, i, q) -> PX (p2, i, (psubC csub q c))
+
+(** val paddI :
+ ('a1 -> 'a1 -> 'a1) -> ('a1 pol -> 'a1 pol -> 'a1 pol) -> 'a1 pol ->
+ positive -> 'a1 pol -> 'a1 pol **)
+
+let rec paddI cadd pop q j = function
+| Pc c -> mkPinj j (paddC cadd q c)
+| Pinj (j', q') ->
+ (match Z.pos_sub j' j with
+ | Z0 -> mkPinj j (pop q' q)
+ | Zpos k -> mkPinj j (pop (Pinj (k, q')) q)
+ | Zneg k -> mkPinj j' (paddI cadd pop q k q'))
+| PX (p2, i, q') ->
+ (match j with
+ | XI j0 -> PX (p2, i, (paddI cadd pop q (XO j0) q'))
+ | XO j0 -> PX (p2, i, (paddI cadd pop q (Coq_Pos.pred_double j0) q'))
+ | XH -> PX (p2, i, (pop q' q)))
+
+(** val psubI :
+ ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1) -> ('a1 pol -> 'a1 pol -> 'a1 pol) ->
+ 'a1 pol -> positive -> 'a1 pol -> 'a1 pol **)
+
+let rec psubI cadd copp pop q j = function
+| Pc c -> mkPinj j (paddC cadd (popp copp q) c)
+| Pinj (j', q') ->
+ (match Z.pos_sub j' j with
+ | Z0 -> mkPinj j (pop q' q)
+ | Zpos k -> mkPinj j (pop (Pinj (k, q')) q)
+ | Zneg k -> mkPinj j' (psubI cadd copp pop q k q'))
+| PX (p2, i, q') ->
+ (match j with
+ | XI j0 -> PX (p2, i, (psubI cadd copp pop q (XO j0) q'))
+ | XO j0 -> PX (p2, i, (psubI cadd copp pop q (Coq_Pos.pred_double j0) q'))
+ | XH -> PX (p2, i, (pop q' q)))
+
+(** val paddX :
+ 'a1 -> ('a1 -> 'a1 -> bool) -> ('a1 pol -> 'a1 pol -> 'a1 pol) -> 'a1 pol
+ -> positive -> 'a1 pol -> 'a1 pol **)
+
+let rec paddX cO ceqb pop p' i' p = match p with
+| Pc c -> PX (p', i', p)
+| Pinj (j, q') ->
+ (match j with
+ | XI j0 -> PX (p', i', (Pinj ((XO j0), q')))
+ | XO j0 -> PX (p', i', (Pinj ((Coq_Pos.pred_double j0), q')))
+ | XH -> PX (p', i', q'))
+| PX (p2, i, q') ->
+ (match Z.pos_sub i i' with
+ | Z0 -> mkPX cO ceqb (pop p2 p') i q'
+ | Zpos k -> mkPX cO ceqb (pop (PX (p2, k, (p0 cO))) p') i' q'
+ | Zneg k -> mkPX cO ceqb (paddX cO ceqb pop p' k p2) i q')
+
+(** val psubX :
+ 'a1 -> ('a1 -> 'a1) -> ('a1 -> 'a1 -> bool) -> ('a1 pol -> 'a1 pol -> 'a1
+ pol) -> 'a1 pol -> positive -> 'a1 pol -> 'a1 pol **)
+
+let rec psubX cO copp ceqb pop p' i' p = match p with
+| Pc c -> PX ((popp copp p'), i', p)
+| Pinj (j, q') ->
+ (match j with
+ | XI j0 -> PX ((popp copp p'), i', (Pinj ((XO j0), q')))
+ | XO j0 -> PX ((popp copp p'), i', (Pinj ((Coq_Pos.pred_double j0), q')))
+ | XH -> PX ((popp copp p'), i', q'))
+| PX (p2, i, q') ->
+ (match Z.pos_sub i i' with
+ | Z0 -> mkPX cO ceqb (pop p2 p') i q'
+ | Zpos k -> mkPX cO ceqb (pop (PX (p2, k, (p0 cO))) p') i' q'
+ | Zneg k -> mkPX cO ceqb (psubX cO copp ceqb pop p' k p2) i q')
+
+(** val padd :
+ 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> bool) -> 'a1 pol -> 'a1 pol
+ -> 'a1 pol **)
+
+let rec padd cO cadd ceqb p = function
+| Pc c' -> paddC cadd p c'
+| Pinj (j', q') -> paddI cadd (padd cO cadd ceqb) q' j' p
+| PX (p'0, i', q') ->
+ (match p with
+ | Pc c -> PX (p'0, i', (paddC cadd q' c))
+ | Pinj (j, q) ->
+ (match j with
+ | XI j0 -> PX (p'0, i', (padd cO cadd ceqb (Pinj ((XO j0), q)) q'))
+ | XO j0 ->
+ PX (p'0, i',
+ (padd cO cadd ceqb (Pinj ((Coq_Pos.pred_double j0), q)) q'))
+ | XH -> PX (p'0, i', (padd cO cadd ceqb q q')))
+ | PX (p2, i, q) ->
+ (match Z.pos_sub i i' with
+ | Z0 ->
+ mkPX cO ceqb (padd cO cadd ceqb p2 p'0) i (padd cO cadd ceqb q q')
+ | Zpos k ->
+ mkPX cO ceqb (padd cO cadd ceqb (PX (p2, k, (p0 cO))) p'0) i'
+ (padd cO cadd ceqb q q')
+ | Zneg k ->
+ mkPX cO ceqb (paddX cO ceqb (padd cO cadd ceqb) p'0 k p2) i
+ (padd cO cadd ceqb q q')))
+
+(** val psub :
+ 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1) -> ('a1
+ -> 'a1 -> bool) -> 'a1 pol -> 'a1 pol -> 'a1 pol **)
+
+let rec psub cO cadd csub copp ceqb p = function
+| Pc c' -> psubC csub p c'
+| Pinj (j', q') -> psubI cadd copp (psub cO cadd csub copp ceqb) q' j' p
+| PX (p'0, i', q') ->
+ (match p with
+ | Pc c -> PX ((popp copp p'0), i', (paddC cadd (popp copp q') c))
+ | Pinj (j, q) ->
+ (match j with
+ | XI j0 ->
+ PX ((popp copp p'0), i',
+ (psub cO cadd csub copp ceqb (Pinj ((XO j0), q)) q'))
+ | XO j0 ->
+ PX ((popp copp p'0), i',
+ (psub cO cadd csub copp ceqb (Pinj ((Coq_Pos.pred_double j0), q))
+ q'))
+ | XH -> PX ((popp copp p'0), i', (psub cO cadd csub copp ceqb q q')))
+ | PX (p2, i, q) ->
+ (match Z.pos_sub i i' with
+ | Z0 ->
+ mkPX cO ceqb (psub cO cadd csub copp ceqb p2 p'0) i
+ (psub cO cadd csub copp ceqb q q')
+ | Zpos k ->
+ mkPX cO ceqb (psub cO cadd csub copp ceqb (PX (p2, k, (p0 cO))) p'0)
+ i' (psub cO cadd csub copp ceqb q q')
+ | Zneg k ->
+ mkPX cO ceqb
+ (psubX cO copp ceqb (psub cO cadd csub copp ceqb) p'0 k p2) i
+ (psub cO cadd csub copp ceqb q q')))
+
+(** val pmulC_aux :
+ 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> bool) -> 'a1 pol -> 'a1 ->
+ 'a1 pol **)
+
+let rec pmulC_aux cO cmul ceqb p c =
+ match p with
+ | Pc c' -> Pc (cmul c' c)
+ | Pinj (j, q) -> mkPinj j (pmulC_aux cO cmul ceqb q c)
+ | PX (p2, i, q) ->
+ mkPX cO ceqb (pmulC_aux cO cmul ceqb p2 c) i (pmulC_aux cO cmul ceqb q c)
+
+(** val pmulC :
+ 'a1 -> 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> bool) -> 'a1 pol ->
+ 'a1 -> 'a1 pol **)
+
+let pmulC cO cI cmul ceqb p c =
+ if ceqb c cO
+ then p0 cO
+ else if ceqb c cI then p else pmulC_aux cO cmul ceqb p c
+
+(** val pmulI :
+ 'a1 -> 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> bool) -> ('a1 pol ->
+ 'a1 pol -> 'a1 pol) -> 'a1 pol -> positive -> 'a1 pol -> 'a1 pol **)
+
+let rec pmulI cO cI cmul ceqb pmul0 q j = function
+| Pc c -> mkPinj j (pmulC cO cI cmul ceqb q c)
+| Pinj (j', q') ->
+ (match Z.pos_sub j' j with
+ | Z0 -> mkPinj j (pmul0 q' q)
+ | Zpos k -> mkPinj j (pmul0 (Pinj (k, q')) q)
+ | Zneg k -> mkPinj j' (pmulI cO cI cmul ceqb pmul0 q k q'))
+| PX (p', i', q') ->
+ (match j with
+ | XI j' ->
+ mkPX cO ceqb (pmulI cO cI cmul ceqb pmul0 q j p') i'
+ (pmulI cO cI cmul ceqb pmul0 q (XO j') q')
+ | XO j' ->
+ mkPX cO ceqb (pmulI cO cI cmul ceqb pmul0 q j p') i'
+ (pmulI cO cI cmul ceqb pmul0 q (Coq_Pos.pred_double j') q')
+ | XH -> mkPX cO ceqb (pmulI cO cI cmul ceqb pmul0 q XH p') i' (pmul0 q' q))
+
+(** val pmul :
+ 'a1 -> 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1
+ -> bool) -> 'a1 pol -> 'a1 pol -> 'a1 pol **)
+
+let rec pmul cO cI cadd cmul ceqb p p'' = match p'' with
+| Pc c -> pmulC cO cI cmul ceqb p c
+| Pinj (j', q') -> pmulI cO cI cmul ceqb (pmul cO cI cadd cmul ceqb) q' j' p
+| PX (p', i', q') ->
+ (match p with
+ | Pc c -> pmulC cO cI cmul ceqb p'' c
+ | Pinj (j, q) ->
+ let qQ' =
+ match j with
+ | XI j0 -> pmul cO cI cadd cmul ceqb (Pinj ((XO j0), q)) q'
+ | XO j0 ->
+ pmul cO cI cadd cmul ceqb (Pinj ((Coq_Pos.pred_double j0), q)) q'
+ | XH -> pmul cO cI cadd cmul ceqb q q'
+ in
+ mkPX cO ceqb (pmul cO cI cadd cmul ceqb p p') i' qQ'
+ | PX (p2, i, q) ->
+ let qQ' = pmul cO cI cadd cmul ceqb q q' in
+ let pQ' = pmulI cO cI cmul ceqb (pmul cO cI cadd cmul ceqb) q' XH p2 in
+ let qP' = pmul cO cI cadd cmul ceqb (mkPinj XH q) p' in
+ let pP' = pmul cO cI cadd cmul ceqb p2 p' in
+ padd cO cadd ceqb
+ (mkPX cO ceqb (padd cO cadd ceqb (mkPX cO ceqb pP' i (p0 cO)) qP') i'
+ (p0 cO)) (mkPX cO ceqb pQ' i qQ'))
+
+(** val psquare :
+ 'a1 -> 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1
+ -> bool) -> 'a1 pol -> 'a1 pol **)
+
+let rec psquare cO cI cadd cmul ceqb = function
+| Pc c -> Pc (cmul c c)
+| Pinj (j, q) -> Pinj (j, (psquare cO cI cadd cmul ceqb q))
+| PX (p2, i, q) ->
+ let twoPQ =
+ pmul cO cI cadd cmul ceqb p2
+ (mkPinj XH (pmulC cO cI cmul ceqb q (cadd cI cI)))
+ in
+ let q2 = psquare cO cI cadd cmul ceqb q in
+ let p3 = psquare cO cI cadd cmul ceqb p2 in
+ mkPX cO ceqb (padd cO cadd ceqb (mkPX cO ceqb p3 i (p0 cO)) twoPQ) i q2
+
+type 'c pExpr =
+| PEc of 'c
+| PEX of positive
+| PEadd of 'c pExpr * 'c pExpr
+| PEsub of 'c pExpr * 'c pExpr
+| PEmul of 'c pExpr * 'c pExpr
+| PEopp of 'c pExpr
+| PEpow of 'c pExpr * n
+
+(** val mk_X : 'a1 -> 'a1 -> positive -> 'a1 pol **)
+
+let mk_X cO cI j =
+ mkPinj_pred j (mkX cO cI)
+
+(** val ppow_pos :
+ 'a1 -> 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1
+ -> bool) -> ('a1 pol -> 'a1 pol) -> 'a1 pol -> 'a1 pol -> positive -> 'a1
+ pol **)
+
+let rec ppow_pos cO cI cadd cmul ceqb subst_l res p = function
+| XI p3 ->
+ subst_l
+ (pmul cO cI cadd cmul ceqb
+ (ppow_pos cO cI cadd cmul ceqb subst_l
+ (ppow_pos cO cI cadd cmul ceqb subst_l res p p3) p p3) p)
+| XO p3 ->
+ ppow_pos cO cI cadd cmul ceqb subst_l
+ (ppow_pos cO cI cadd cmul ceqb subst_l res p p3) p p3
+| XH -> subst_l (pmul cO cI cadd cmul ceqb res p)
+
+(** val ppow_N :
+ 'a1 -> 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1
+ -> bool) -> ('a1 pol -> 'a1 pol) -> 'a1 pol -> n -> 'a1 pol **)
+
+let ppow_N cO cI cadd cmul ceqb subst_l p = function
+| N0 -> p1 cI
+| Npos p2 -> ppow_pos cO cI cadd cmul ceqb subst_l (p1 cI) p p2
+
+(** val norm_aux :
+ 'a1 -> 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1
+ -> 'a1) -> ('a1 -> 'a1) -> ('a1 -> 'a1 -> bool) -> 'a1 pExpr -> 'a1 pol **)
+
+let rec norm_aux cO cI cadd cmul csub copp ceqb = function
+| PEc c -> Pc c
+| PEX j -> mk_X cO cI j
+| PEadd (pe1, pe2) ->
+ (match pe1 with
+ | PEopp pe3 ->
+ psub cO cadd csub copp ceqb
+ (norm_aux cO cI cadd cmul csub copp ceqb pe2)
+ (norm_aux cO cI cadd cmul csub copp ceqb pe3)
+ | _ ->
+ (match pe2 with
+ | PEopp pe3 ->
+ psub cO cadd csub copp ceqb
+ (norm_aux cO cI cadd cmul csub copp ceqb pe1)
+ (norm_aux cO cI cadd cmul csub copp ceqb pe3)
+ | _ ->
+ padd cO cadd ceqb (norm_aux cO cI cadd cmul csub copp ceqb pe1)
+ (norm_aux cO cI cadd cmul csub copp ceqb pe2)))
+| PEsub (pe1, pe2) ->
+ psub cO cadd csub copp ceqb (norm_aux cO cI cadd cmul csub copp ceqb pe1)
+ (norm_aux cO cI cadd cmul csub copp ceqb pe2)
+| PEmul (pe1, pe2) ->
+ pmul cO cI cadd cmul ceqb (norm_aux cO cI cadd cmul csub copp ceqb pe1)
+ (norm_aux cO cI cadd cmul csub copp ceqb pe2)
+| PEopp pe1 -> popp copp (norm_aux cO cI cadd cmul csub copp ceqb pe1)
+| PEpow (pe1, n0) ->
+ ppow_N cO cI cadd cmul ceqb (fun p -> p)
+ (norm_aux cO cI cadd cmul csub copp ceqb pe1) n0
+
+type 'a bFormula =
+| TT
+| FF
+| X
+| A of 'a
+| Cj of 'a bFormula * 'a bFormula
+| D of 'a bFormula * 'a bFormula
+| N of 'a bFormula
+| I of 'a bFormula * 'a bFormula
+
+type 'term' clause = 'term' list
+
+type 'term' cnf = 'term' clause list
+
+(** val tt : 'a1 cnf **)
+
+let tt =
+ Nil
+
+(** val ff : 'a1 cnf **)
+
+let ff =
+ Cons (Nil, Nil)
+
+(** val add_term :
+ ('a1 -> bool) -> ('a1 -> 'a1 -> 'a1 option) -> 'a1 -> 'a1 clause -> 'a1
+ clause option **)
+
+let rec add_term unsat deduce t0 = function
+| Nil ->
+ (match deduce t0 t0 with
+ | Some u -> if unsat u then None else Some (Cons (t0, Nil))
+ | None -> Some (Cons (t0, Nil)))
+| Cons (t', cl0) ->
+ (match deduce t0 t' with
+ | Some u ->
+ if unsat u
+ then None
+ else (match add_term unsat deduce t0 cl0 with
+ | Some cl' -> Some (Cons (t', cl'))
+ | None -> None)
+ | None ->
+ (match add_term unsat deduce t0 cl0 with
+ | Some cl' -> Some (Cons (t', cl'))
+ | None -> None))
+
+(** val or_clause :
+ ('a1 -> bool) -> ('a1 -> 'a1 -> 'a1 option) -> 'a1 clause -> 'a1 clause
+ -> 'a1 clause option **)
+
+let rec or_clause unsat deduce cl1 cl2 =
+ match cl1 with
+ | Nil -> Some cl2
+ | Cons (t0, cl) ->
+ (match add_term unsat deduce t0 cl2 with
+ | Some cl' -> or_clause unsat deduce cl cl'
+ | None -> None)
+
+(** val or_clause_cnf :
+ ('a1 -> bool) -> ('a1 -> 'a1 -> 'a1 option) -> 'a1 clause -> 'a1 cnf ->
+ 'a1 cnf **)
+
+let or_clause_cnf unsat deduce t0 f =
+ fold_right (fun e acc ->
+ match or_clause unsat deduce t0 e with
+ | Some cl -> Cons (cl, acc)
+ | None -> acc) Nil f
+
+(** val or_cnf :
+ ('a1 -> bool) -> ('a1 -> 'a1 -> 'a1 option) -> 'a1 cnf -> 'a1 cnf -> 'a1
+ cnf **)
+
+let rec or_cnf unsat deduce f f' =
+ match f with
+ | Nil -> tt
+ | Cons (e, rst) ->
+ app (or_cnf unsat deduce rst f') (or_clause_cnf unsat deduce e f')
+
+(** val and_cnf : 'a1 cnf -> 'a1 cnf -> 'a1 cnf **)
+
+let and_cnf f1 f2 =
+ app f1 f2
+
+(** val xcnf :
+ ('a2 -> bool) -> ('a2 -> 'a2 -> 'a2 option) -> ('a1 -> 'a2 cnf) -> ('a1
+ -> 'a2 cnf) -> bool -> 'a1 bFormula -> 'a2 cnf **)
+
+let rec xcnf unsat deduce normalise0 negate0 pol0 = function
+| TT -> if pol0 then tt else ff
+| FF -> if pol0 then ff else tt
+| X -> ff
+| A x -> if pol0 then normalise0 x else negate0 x
+| Cj (e1, e2) ->
+ if pol0
+ then and_cnf (xcnf unsat deduce normalise0 negate0 pol0 e1)
+ (xcnf unsat deduce normalise0 negate0 pol0 e2)
+ else or_cnf unsat deduce (xcnf unsat deduce normalise0 negate0 pol0 e1)
+ (xcnf unsat deduce normalise0 negate0 pol0 e2)
+| D (e1, e2) ->
+ if pol0
+ then or_cnf unsat deduce (xcnf unsat deduce normalise0 negate0 pol0 e1)
+ (xcnf unsat deduce normalise0 negate0 pol0 e2)
+ else and_cnf (xcnf unsat deduce normalise0 negate0 pol0 e1)
+ (xcnf unsat deduce normalise0 negate0 pol0 e2)
+| N e -> xcnf unsat deduce normalise0 negate0 (negb pol0) e
+| I (e1, e2) ->
+ if pol0
+ then or_cnf unsat deduce
+ (xcnf unsat deduce normalise0 negate0 (negb pol0) e1)
+ (xcnf unsat deduce normalise0 negate0 pol0 e2)
+ else and_cnf (xcnf unsat deduce normalise0 negate0 (negb pol0) e1)
+ (xcnf unsat deduce normalise0 negate0 pol0 e2)
+
+(** val cnf_checker :
+ ('a1 list -> 'a2 -> bool) -> 'a1 cnf -> 'a2 list -> bool **)
+
+let rec cnf_checker checker0 f l =
+ match f with
+ | Nil -> true
+ | Cons (e, f0) ->
+ (match l with
+ | Nil -> false
+ | Cons (c, l0) ->
+ if checker0 e c then cnf_checker checker0 f0 l0 else false)
+
+(** val tauto_checker :
+ ('a2 -> bool) -> ('a2 -> 'a2 -> 'a2 option) -> ('a1 -> 'a2 cnf) -> ('a1
+ -> 'a2 cnf) -> ('a2 list -> 'a3 -> bool) -> 'a1 bFormula -> 'a3 list ->
+ bool **)
+
+let tauto_checker unsat deduce normalise0 negate0 checker0 f w =
+ cnf_checker checker0 (xcnf unsat deduce normalise0 negate0 true f) w
+
+(** val cneqb : ('a1 -> 'a1 -> bool) -> 'a1 -> 'a1 -> bool **)
+
+let cneqb ceqb x y =
+ negb (ceqb x y)
+
+(** val cltb :
+ ('a1 -> 'a1 -> bool) -> ('a1 -> 'a1 -> bool) -> 'a1 -> 'a1 -> bool **)
+
+let cltb ceqb cleb x y =
+ if cleb x y then cneqb ceqb x y else false
+
+type 'c polC = 'c pol
+
+type op1 =
+| Equal
+| NonEqual
+| Strict
+| NonStrict
+
+type 'c nFormula = 'c polC*op1
+
+(** val opMult : op1 -> op1 -> op1 option **)
+
+let opMult o o' =
+ match o with
+ | Equal -> Some Equal
+ | NonEqual ->
+ (match o' with
+ | Strict -> None
+ | NonStrict -> None
+ | x -> Some x)
+ | Strict ->
+ (match o' with
+ | NonEqual -> None
+ | _ -> Some o')
+ | NonStrict ->
+ (match o' with
+ | NonEqual -> None
+ | Strict -> Some NonStrict
+ | x -> Some x)
+
+(** val opAdd : op1 -> op1 -> op1 option **)
+
+let opAdd o o' =
+ match o with
+ | Equal -> Some o'
+ | NonEqual ->
+ (match o' with
+ | Equal -> Some NonEqual
+ | _ -> None)
+ | Strict ->
+ (match o' with
+ | NonEqual -> None
+ | _ -> Some Strict)
+ | NonStrict ->
+ (match o' with
+ | Equal -> Some NonStrict
+ | NonEqual -> None
+ | x -> Some x)
+
+type 'c psatz =
+| PsatzIn of nat
+| PsatzSquare of 'c polC
+| PsatzMulC of 'c polC * 'c psatz
+| PsatzMulE of 'c psatz * 'c psatz
+| PsatzAdd of 'c psatz * 'c psatz
+| PsatzC of 'c
+| PsatzZ
+
+(** val map_option : ('a1 -> 'a2 option) -> 'a1 option -> 'a2 option **)
+
+let map_option f = function
+| Some x -> f x
+| None -> None
+
+(** val map_option2 :
+ ('a1 -> 'a2 -> 'a3 option) -> 'a1 option -> 'a2 option -> 'a3 option **)
+
+let map_option2 f o o' =
+ match o with
+ | Some x ->
+ (match o' with
+ | Some x' -> f x x'
+ | None -> None)
+ | None -> None
+
+(** val pexpr_times_nformula :
+ 'a1 -> 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1
+ -> bool) -> 'a1 polC -> 'a1 nFormula -> 'a1 nFormula option **)
+
+let pexpr_times_nformula cO cI cplus ctimes ceqb e = function
+| ef,o ->
+ (match o with
+ | Equal -> Some ((pmul cO cI cplus ctimes ceqb e ef),Equal)
+ | _ -> None)
+
+(** val nformula_times_nformula :
+ 'a1 -> 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1
+ -> bool) -> 'a1 nFormula -> 'a1 nFormula -> 'a1 nFormula option **)
+
+let nformula_times_nformula cO cI cplus ctimes ceqb f1 f2 =
+ let e1,o1 = f1 in
+ let e2,o2 = f2 in
+ map_option (fun x -> Some ((pmul cO cI cplus ctimes ceqb e1 e2),x))
+ (opMult o1 o2)
+
+(** val nformula_plus_nformula :
+ 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> bool) -> 'a1 nFormula -> 'a1
+ nFormula -> 'a1 nFormula option **)
+
+let nformula_plus_nformula cO cplus ceqb f1 f2 =
+ let e1,o1 = f1 in
+ let e2,o2 = f2 in
+ map_option (fun x -> Some ((padd cO cplus ceqb e1 e2),x)) (opAdd o1 o2)
+
+(** val eval_Psatz :
+ 'a1 -> 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1
+ -> bool) -> ('a1 -> 'a1 -> bool) -> 'a1 nFormula list -> 'a1 psatz -> 'a1
+ nFormula option **)
+
+let rec eval_Psatz cO cI cplus ctimes ceqb cleb l = function
+| PsatzIn n0 -> Some (nth n0 l ((Pc cO),Equal))
+| PsatzSquare e0 -> Some ((psquare cO cI cplus ctimes ceqb e0),NonStrict)
+| PsatzMulC (re, e0) ->
+ map_option (pexpr_times_nformula cO cI cplus ctimes ceqb re)
+ (eval_Psatz cO cI cplus ctimes ceqb cleb l e0)
+| PsatzMulE (f1, f2) ->
+ map_option2 (nformula_times_nformula cO cI cplus ctimes ceqb)
+ (eval_Psatz cO cI cplus ctimes ceqb cleb l f1)
+ (eval_Psatz cO cI cplus ctimes ceqb cleb l f2)
+| PsatzAdd (f1, f2) ->
+ map_option2 (nformula_plus_nformula cO cplus ceqb)
+ (eval_Psatz cO cI cplus ctimes ceqb cleb l f1)
+ (eval_Psatz cO cI cplus ctimes ceqb cleb l f2)
+| PsatzC c -> if cltb ceqb cleb cO c then Some ((Pc c),Strict) else None
+| PsatzZ -> Some ((Pc cO),Equal)
+
+(** val check_inconsistent :
+ 'a1 -> ('a1 -> 'a1 -> bool) -> ('a1 -> 'a1 -> bool) -> 'a1 nFormula ->
+ bool **)
+
+let check_inconsistent cO ceqb cleb = function
+| e,op ->
+ (match e with
+ | Pc c ->
+ (match op with
+ | Equal -> cneqb ceqb c cO
+ | NonEqual -> ceqb c cO
+ | Strict -> cleb c cO
+ | NonStrict -> cltb ceqb cleb c cO)
+ | _ -> false)
+
+type op2 =
+| OpEq
+| OpNEq
+| OpLe
+| OpGe
+| OpLt
+| OpGt
+
+type 't formula = { flhs : 't pExpr; fop : op2; frhs : 't pExpr }
+
+(** val norm :
+ 'a1 -> 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1
+ -> 'a1) -> ('a1 -> 'a1) -> ('a1 -> 'a1 -> bool) -> 'a1 pExpr -> 'a1 pol **)
+
+let norm cO cI cplus ctimes cminus copp ceqb =
+ norm_aux cO cI cplus ctimes cminus copp ceqb
+
+(** val psub0 :
+ 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1) -> ('a1
+ -> 'a1 -> bool) -> 'a1 pol -> 'a1 pol -> 'a1 pol **)
+
+let psub0 cO cplus cminus copp ceqb =
+ psub cO cplus cminus copp ceqb
+
+(** val padd0 :
+ 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> bool) -> 'a1 pol -> 'a1 pol
+ -> 'a1 pol **)
+
+let padd0 cO cplus ceqb =
+ padd cO cplus ceqb
+
+type zWitness = z psatz
+
+(** val psub1 : z pol -> z pol -> z pol **)
+
+let psub1 =
+ psub0 Z0 Z.add Z.sub Z.opp zeq_bool
+
+(** val padd1 : z pol -> z pol -> z pol **)
+
+let padd1 =
+ padd0 Z0 Z.add zeq_bool
+
+(** val norm0 : z pExpr -> z pol **)
+
+let norm0 =
+ norm Z0 (Zpos XH) Z.add Z.mul Z.sub Z.opp zeq_bool
+
+(** val xnormalise : z formula -> z nFormula list **)
+
+let xnormalise t0 =
+ let { flhs = lhs; fop = o; frhs = rhs } = t0 in
+ let lhs0 = norm0 lhs in
+ let rhs0 = norm0 rhs in
+ (match o with
+ | OpEq ->
+ Cons (((psub1 lhs0 (padd1 rhs0 (Pc (Zpos XH)))),NonStrict), (Cons
+ (((psub1 rhs0 (padd1 lhs0 (Pc (Zpos XH)))),NonStrict), Nil)))
+ | OpNEq -> Cons (((psub1 lhs0 rhs0),Equal), Nil)
+ | OpLe -> Cons (((psub1 lhs0 (padd1 rhs0 (Pc (Zpos XH)))),NonStrict), Nil)
+ | OpGe -> Cons (((psub1 rhs0 (padd1 lhs0 (Pc (Zpos XH)))),NonStrict), Nil)
+ | OpLt -> Cons (((psub1 lhs0 rhs0),NonStrict), Nil)
+ | OpGt -> Cons (((psub1 rhs0 lhs0),NonStrict), Nil))
+
+(** val normalise : z formula -> z nFormula cnf **)
+
+let normalise t0 =
+ map (fun x -> Cons (x, Nil)) (xnormalise t0)
+
+(** val xnegate : z formula -> z nFormula list **)
+
+let xnegate t0 =
+ let { flhs = lhs; fop = o; frhs = rhs } = t0 in
+ let lhs0 = norm0 lhs in
+ let rhs0 = norm0 rhs in
+ (match o with
+ | OpEq -> Cons (((psub1 lhs0 rhs0),Equal), Nil)
+ | OpNEq ->
+ Cons (((psub1 lhs0 (padd1 rhs0 (Pc (Zpos XH)))),NonStrict), (Cons
+ (((psub1 rhs0 (padd1 lhs0 (Pc (Zpos XH)))),NonStrict), Nil)))
+ | OpLe -> Cons (((psub1 rhs0 lhs0),NonStrict), Nil)
+ | OpGe -> Cons (((psub1 lhs0 rhs0),NonStrict), Nil)
+ | OpLt -> Cons (((psub1 rhs0 (padd1 lhs0 (Pc (Zpos XH)))),NonStrict), Nil)
+ | OpGt -> Cons (((psub1 lhs0 (padd1 rhs0 (Pc (Zpos XH)))),NonStrict), Nil))
+
+(** val negate : z formula -> z nFormula cnf **)
+
+let negate t0 =
+ map (fun x -> Cons (x, Nil)) (xnegate t0)
+
+(** val zunsat : z nFormula -> bool **)
+
+let zunsat =
+ check_inconsistent Z0 zeq_bool Z.leb
+
+(** val zdeduce : z nFormula -> z nFormula -> z nFormula option **)
+
+let zdeduce =
+ nformula_plus_nformula Z0 Z.add zeq_bool
+
+(** val ceiling : z -> z -> z **)
+
+let ceiling a b =
+ let q,r = Z.div_eucl a b in
+ (match r with
+ | Z0 -> q
+ | _ -> Z.add q (Zpos XH))
+
+type zArithProof =
+| DoneProof
+| RatProof of zWitness * zArithProof
+| CutProof of zWitness * zArithProof
+| EnumProof of zWitness * zWitness * zArithProof list
+
+(** val zgcdM : z -> z -> z **)
+
+let zgcdM x y =
+ Z.max (Z.gcd x y) (Zpos XH)
+
+(** val zgcd_pol : z polC -> z*z **)
+
+let rec zgcd_pol = function
+| Pc c -> Z0,c
+| Pinj (p2, p3) -> zgcd_pol p3
+| PX (p2, p3, q) ->
+ let g1,c1 = zgcd_pol p2 in
+ let g2,c2 = zgcd_pol q in (zgcdM (zgcdM g1 c1) g2),c2
+
+(** val zdiv_pol : z polC -> z -> z polC **)
+
+let rec zdiv_pol p x =
+ match p with
+ | Pc c -> Pc (Z.div c x)
+ | Pinj (j, p2) -> Pinj (j, (zdiv_pol p2 x))
+ | PX (p2, j, q) -> PX ((zdiv_pol p2 x), j, (zdiv_pol q x))
+
+(** val makeCuttingPlane : z polC -> z polC*z **)
+
+let makeCuttingPlane p =
+ let g,c = zgcd_pol p in
+ if Z.gtb g Z0
+ then (zdiv_pol (psubC Z.sub p c) g),(Z.opp (ceiling (Z.opp c) g))
+ else p,Z0
+
+(** val genCuttingPlane : z nFormula -> ((z polC*z)*op1) option **)
+
+let genCuttingPlane = function
+| e,op ->
+ (match op with
+ | Equal ->
+ let g,c = zgcd_pol e in
+ if if Z.gtb g Z0
+ then if negb (zeq_bool c Z0)
+ then negb (zeq_bool (Z.gcd g c) g)
+ else false
+ else false
+ then None
+ else Some ((makeCuttingPlane e),Equal)
+ | NonEqual -> Some ((e,Z0),op)
+ | Strict -> Some ((makeCuttingPlane (psubC Z.sub e (Zpos XH))),NonStrict)
+ | NonStrict -> Some ((makeCuttingPlane e),NonStrict))
+
+(** val nformula_of_cutting_plane : ((z polC*z)*op1) -> z nFormula **)
+
+let nformula_of_cutting_plane = function
+| e_z,o -> let e,z0 = e_z in (padd1 e (Pc z0)),o
+
+(** val is_pol_Z0 : z polC -> bool **)
+
+let is_pol_Z0 = function
+| Pc z0 ->
+ (match z0 with
+ | Z0 -> true
+ | _ -> false)
+| _ -> false
+
+(** val eval_Psatz0 : z nFormula list -> zWitness -> z nFormula option **)
+
+let eval_Psatz0 =
+ eval_Psatz Z0 (Zpos XH) Z.add Z.mul zeq_bool Z.leb
+
+(** val valid_cut_sign : op1 -> bool **)
+
+let valid_cut_sign = function
+| Equal -> true
+| NonStrict -> true
+| _ -> false
+
+(** val zChecker : z nFormula list -> zArithProof -> bool **)
+
+let rec zChecker l = function
+| DoneProof -> false
+| RatProof (w, pf0) ->
+ (match eval_Psatz0 l w with
+ | Some f -> if zunsat f then true else zChecker (Cons (f, l)) pf0
+ | None -> false)
+| CutProof (w, pf0) ->
+ (match eval_Psatz0 l w with
+ | Some f ->
+ (match genCuttingPlane f with
+ | Some cp -> zChecker (Cons ((nformula_of_cutting_plane cp), l)) pf0
+ | None -> true)
+ | None -> false)
+| EnumProof (w1, w2, pf0) ->
+ (match eval_Psatz0 l w1 with
+ | Some f1 ->
+ (match eval_Psatz0 l w2 with
+ | Some f2 ->
+ (match genCuttingPlane f1 with
+ | Some p ->
+ let p2,op3 = p in
+ let e1,z1 = p2 in
+ (match genCuttingPlane f2 with
+ | Some p3 ->
+ let p4,op4 = p3 in
+ let e2,z2 = p4 in
+ if if if valid_cut_sign op3 then valid_cut_sign op4 else false
+ then is_pol_Z0 (padd1 e1 e2)
+ else false
+ then let rec label pfs lb ub =
+ match pfs with
+ | Nil -> Z.gtb lb ub
+ | Cons (pf1, rsr) ->
+ if zChecker (Cons (((psub1 e1 (Pc lb)),Equal), l)) pf1
+ then label rsr (Z.add lb (Zpos XH)) ub
+ else false
+ in label pf0 (Z.opp z1) z2
+ else false
+ | None -> true)
+ | None -> true)
+ | None -> false)
+ | None -> false)
+
+(** val zTautoChecker : z formula bFormula -> zArithProof list -> bool **)
+
+let zTautoChecker f w =
+ tauto_checker zunsat zdeduce normalise negate zChecker f w
+
+(** val build_positive_atom_aux :
+ (int -> positive option) -> Atom.atom -> positive option **)
+
+let build_positive_atom_aux build_positive0 = function
+| Atom.Acop c ->
+ (match c with
+ | Atom.CO_xH -> Some XH
+ | Atom.CO_Z0 -> None)
+| Atom.Auop (u, a0) ->
+ (match u with
+ | Atom.UO_xO -> option_map (fun x -> XO x) (build_positive0 a0)
+ | Atom.UO_xI -> option_map (fun x -> XI x) (build_positive0 a0)
+ | _ -> None)
+| _ -> None
+
+(** val build_positive : Atom.atom array -> int -> positive option **)
+
+let build_positive t_atom =
+ foldi_down_cont (fun i cont h ->
+ build_positive_atom_aux cont (get t_atom h)) (length t_atom)
+ (ExtrNative.of_uint(0)) (fun x -> None)
+
+(** val build_z_atom_aux : Atom.atom array -> Atom.atom -> z option **)
+
+let build_z_atom_aux t_atom = function
+| Atom.Acop c ->
+ (match c with
+ | Atom.CO_xH -> None
+ | Atom.CO_Z0 -> Some Z0)
+| Atom.Auop (u, a0) ->
+ (match u with
+ | Atom.UO_Zpos -> option_map (fun x -> Zpos x) (build_positive t_atom a0)
+ | Atom.UO_Zneg -> option_map (fun x -> Zneg x) (build_positive t_atom a0)
+ | _ -> None)
+| _ -> None
+
+(** val build_z_atom : Atom.atom array -> Atom.atom -> z option **)
+
+let build_z_atom t_atom =
+ build_z_atom_aux t_atom
+
+type vmap = positive*Atom.atom list
+
+(** val find_var_aux :
+ Atom.atom -> positive -> Atom.atom list -> positive option **)
+
+let rec find_var_aux h p = function
+| Nil -> None
+| Cons (h', l0) ->
+ let p2 = Coq_Pos.pred p in
+ if Atom.eqb h h' then Some p2 else find_var_aux h p2 l0
+
+(** val find_var : vmap -> Atom.atom -> vmap*positive **)
+
+let find_var vm h =
+ let count,map0 = vm in
+ (match find_var_aux h count map0 with
+ | Some p -> vm,p
+ | None -> ((Coq_Pos.succ count),(Cons (h, map0))),count)
+
+(** val empty_vmap : vmap **)
+
+let empty_vmap =
+ XH,Nil
+
+(** val build_pexpr_atom_aux :
+ Atom.atom array -> (vmap -> int -> vmap*z pExpr) -> vmap -> Atom.atom ->
+ vmap*z pExpr **)
+
+let build_pexpr_atom_aux t_atom build_pexpr0 vm h = match h with
+| Atom.Auop (u, a) ->
+ (match u with
+ | Atom.UO_Zopp -> let vm0,pe = build_pexpr0 vm a in vm0,(PEopp pe)
+ | _ ->
+ (match build_z_atom t_atom h with
+ | Some z0 -> vm,(PEc z0)
+ | None -> let vm0,p = find_var vm h in vm0,(PEX p)))
+| Atom.Abop (b, a1, a2) ->
+ (match b with
+ | Atom.BO_Zplus ->
+ let vm0,pe1 = build_pexpr0 vm a1 in
+ let vm1,pe2 = build_pexpr0 vm0 a2 in vm1,(PEadd (pe1, pe2))
+ | Atom.BO_Zminus ->
+ let vm0,pe1 = build_pexpr0 vm a1 in
+ let vm1,pe2 = build_pexpr0 vm0 a2 in vm1,(PEsub (pe1, pe2))
+ | Atom.BO_Zmult ->
+ let vm0,pe1 = build_pexpr0 vm a1 in
+ let vm1,pe2 = build_pexpr0 vm0 a2 in vm1,(PEmul (pe1, pe2))
+ | _ ->
+ (match build_z_atom t_atom h with
+ | Some z0 -> vm,(PEc z0)
+ | None -> let vm0,p = find_var vm h in vm0,(PEX p)))
+| _ ->
+ (match build_z_atom t_atom h with
+ | Some z0 -> vm,(PEc z0)
+ | None -> let vm0,p = find_var vm h in vm0,(PEX p))
+
+(** val build_pexpr : Atom.atom array -> vmap -> int -> vmap*z pExpr **)
+
+let build_pexpr t_atom =
+ foldi_down_cont (fun i cont vm h ->
+ build_pexpr_atom_aux t_atom cont vm (get t_atom h)) (length t_atom)
+ (ExtrNative.of_uint(0)) (fun vm x -> vm,(PEc Z0))
+
+(** val build_op2 : Atom.binop -> op2 option **)
+
+let build_op2 = function
+| Atom.BO_Zlt -> Some OpLt
+| Atom.BO_Zle -> Some OpLe
+| Atom.BO_Zge -> Some OpGe
+| Atom.BO_Zgt -> Some OpGt
+| Atom.BO_eq t0 ->
+ (match t0 with
+ | Typ.TZ -> Some OpEq
+ | _ -> None)
+| _ -> None
+
+(** val build_formula_atom :
+ Atom.atom array -> vmap -> Atom.atom -> (vmap*z formula) option **)
+
+let build_formula_atom t_atom vm = function
+| Atom.Abop (op, a1, a2) ->
+ (match build_op2 op with
+ | Some o ->
+ let vm0,pe1 = build_pexpr t_atom vm a1 in
+ let vm1,pe2 = build_pexpr t_atom vm0 a2 in
+ Some (vm1,{ flhs = pe1; fop = o; frhs = pe2 })
+ | None -> None)
+| _ -> None
+
+(** val build_formula :
+ Atom.atom array -> vmap -> int -> (vmap*z formula) option **)
+
+let build_formula t_atom vm h =
+ build_formula_atom t_atom vm (get t_atom h)
+
+(** val build_not2 : int -> z formula bFormula -> z formula bFormula **)
+
+let build_not2 i f =
+ fold (fun f' -> N (N f')) (ExtrNative.of_uint(1)) i f
+
+(** val build_hform :
+ Atom.atom array -> (vmap -> int -> (vmap*z formula bFormula) option) ->
+ vmap -> Form.form -> (vmap*z formula bFormula) option **)
+
+let build_hform t_atom build_var0 vm = function
+| Form.Fatom h ->
+ (match build_formula t_atom vm h with
+ | Some p -> let vm0,f0 = p in Some (vm0,(A f0))
+ | None -> None)
+| Form.Ftrue -> Some (vm,TT)
+| Form.Ffalse -> Some (vm,FF)
+| Form.Fnot2 (i, l) ->
+ (match build_var0 vm (Lit.blit l) with
+ | Some p ->
+ let vm0,f0 = p in
+ let f' = build_not2 i f0 in
+ let f'' = if Lit.is_pos l then f' else N f' in Some (vm0,f'')
+ | None -> None)
+| Form.Fand args ->
+ let n0 = length args in
+ if eqb0 n0 (ExtrNative.of_uint(0))
+ then Some (vm,TT)
+ else foldi (fun i f1 ->
+ match f1 with
+ | Some y ->
+ let vm',f1' = y in
+ let l = get args i in
+ (match build_var0 vm' (Lit.blit l) with
+ | Some p ->
+ let vm2,f2 = p in
+ let f2' = if Lit.is_pos l then f2 else N f2 in
+ Some (vm2,(Cj (f1', f2')))
+ | None -> None)
+ | None -> None) (ExtrNative.of_uint(1))
+ (sub0 n0 (ExtrNative.of_uint(1)))
+ (let l = get args (ExtrNative.of_uint(0)) in
+ match build_var0 vm (Lit.blit l) with
+ | Some p ->
+ let vm',f0 = p in
+ if Lit.is_pos l then Some (vm',f0) else Some (vm',(N f0))
+ | None -> None)
+| Form.For args ->
+ let n0 = length args in
+ if eqb0 n0 (ExtrNative.of_uint(0))
+ then Some (vm,FF)
+ else foldi (fun i f1 ->
+ match f1 with
+ | Some y ->
+ let vm',f1' = y in
+ let l = get args i in
+ (match build_var0 vm' (Lit.blit l) with
+ | Some p ->
+ let vm2,f2 = p in
+ let f2' = if Lit.is_pos l then f2 else N f2 in
+ Some (vm2,(D (f1', f2')))
+ | None -> None)
+ | None -> None) (ExtrNative.of_uint(1))
+ (sub0 n0 (ExtrNative.of_uint(1)))
+ (let l = get args (ExtrNative.of_uint(0)) in
+ match build_var0 vm (Lit.blit l) with
+ | Some p ->
+ let vm',f0 = p in
+ if Lit.is_pos l then Some (vm',f0) else Some (vm',(N f0))
+ | None -> None)
+| Form.Fimp args ->
+ let n0 = length args in
+ if eqb0 n0 (ExtrNative.of_uint(0))
+ then Some (vm,TT)
+ else if leb0 n0 (ExtrNative.of_uint(1))
+ then let l = get args (ExtrNative.of_uint(0)) in
+ (match build_var0 vm (Lit.blit l) with
+ | Some p ->
+ let vm',f0 = p in
+ if Lit.is_pos l then Some (vm',f0) else Some (vm',(N f0))
+ | None -> None)
+ else foldi_down (fun i f1 ->
+ match f1 with
+ | Some y ->
+ let vm',f1' = y in
+ let l = get args i in
+ (match build_var0 vm' (Lit.blit l) with
+ | Some p ->
+ let vm2,f2 = p in
+ let f2' = if Lit.is_pos l then f2 else N f2 in
+ Some (vm2,(I (f2', f1')))
+ | None -> None)
+ | None -> None) (sub0 n0 (ExtrNative.of_uint(2)))
+ (ExtrNative.of_uint(0))
+ (let l = get args (sub0 n0 (ExtrNative.of_uint(1))) in
+ match build_var0 vm (Lit.blit l) with
+ | Some p ->
+ let vm',f0 = p in
+ if Lit.is_pos l then Some (vm',f0) else Some (vm',(N f0))
+ | None -> None)
+| Form.Fxor (a, b) ->
+ (match build_var0 vm (Lit.blit a) with
+ | Some p ->
+ let vm1,f1 = p in
+ (match build_var0 vm1 (Lit.blit b) with
+ | Some p2 ->
+ let vm2,f2 = p2 in
+ let f1' = if Lit.is_pos a then f1 else N f1 in
+ let f2' = if Lit.is_pos b then f2 else N f2 in
+ Some (vm2,(Cj ((D (f1', f2')), (D ((N f1'), (N f2'))))))
+ | None -> None)
+ | None -> None)
+| Form.Fiff (a, b) ->
+ (match build_var0 vm (Lit.blit a) with
+ | Some p ->
+ let vm1,f1 = p in
+ (match build_var0 vm1 (Lit.blit b) with
+ | Some p2 ->
+ let vm2,f2 = p2 in
+ let f1' = if Lit.is_pos a then f1 else N f1 in
+ let f2' = if Lit.is_pos b then f2 else N f2 in
+ Some (vm2,(Cj ((D (f1', (N f2'))), (D ((N f1'), f2')))))
+ | None -> None)
+ | None -> None)
+| Form.Fite (a, b, c) ->
+ (match build_var0 vm (Lit.blit a) with
+ | Some p ->
+ let vm1,f1 = p in
+ (match build_var0 vm1 (Lit.blit b) with
+ | Some p2 ->
+ let vm2,f2 = p2 in
+ (match build_var0 vm2 (Lit.blit c) with
+ | Some p3 ->
+ let vm3,f3 = p3 in
+ let f1' = if Lit.is_pos a then f1 else N f1 in
+ let f2' = if Lit.is_pos b then f2 else N f2 in
+ let f3' = if Lit.is_pos c then f3 else N f3 in
+ Some (vm3,(D ((Cj (f1', f2')), (Cj ((N f1'), f3')))))
+ | None -> None)
+ | None -> None)
+ | None -> None)
+
+(** val build_var :
+ Form.form array -> Atom.atom array -> vmap -> int -> (vmap*z formula
+ bFormula) option **)
+
+let build_var t_form t_atom =
+ foldi_down_cont (fun i cont vm h ->
+ build_hform t_atom cont vm (get t_form h)) (length t_form)
+ (ExtrNative.of_uint(0)) (fun x x0 -> None)
+
+(** val build_form :
+ Form.form array -> Atom.atom array -> vmap -> Form.form -> (vmap*z
+ formula bFormula) option **)
+
+let build_form t_form t_atom =
+ build_hform t_atom (build_var t_form t_atom)
+
+(** val build_nlit :
+ Form.form array -> Atom.atom array -> vmap -> int -> (vmap*z formula
+ bFormula) option **)
+
+let build_nlit t_form t_atom vm l =
+ let l0 = Lit.neg l in
+ (match build_form t_form t_atom vm (get t_form (Lit.blit l0)) with
+ | Some p ->
+ let vm0,f = p in
+ let f0 = if Lit.is_pos l0 then f else N f in Some (vm0,f0)
+ | None -> None)
+
+(** val build_clause_aux :
+ Form.form array -> Atom.atom array -> vmap -> int list -> (vmap*z formula
+ bFormula) option **)
+
+let rec build_clause_aux t_form t_atom vm = function
+| Nil -> None
+| Cons (l, cl0) ->
+ (match cl0 with
+ | Nil -> build_nlit t_form t_atom vm l
+ | Cons (i, l0) ->
+ (match build_nlit t_form t_atom vm l with
+ | Some p ->
+ let vm0,bf1 = p in
+ (match build_clause_aux t_form t_atom vm0 cl0 with
+ | Some p2 -> let vm1,bf2 = p2 in Some (vm1,(Cj (bf1, bf2)))
+ | None -> None)
+ | None -> None))
+
+(** val build_clause :
+ Form.form array -> Atom.atom array -> vmap -> int list -> (vmap*z formula
+ bFormula) option **)
+
+let build_clause t_form t_atom vm cl =
+ match build_clause_aux t_form t_atom vm cl with
+ | Some p -> let vm0,bf = p in Some (vm0,(I (bf, FF)))
+ | None -> None
+
+(** val get_eq0 :
+ Form.form array -> Atom.atom array -> int -> (int -> int -> C.t) -> C.t **)
+
+let get_eq0 t_form t_atom l f =
+ if Lit.is_pos l
+ then (match get t_form (Lit.blit l) with
+ | Form.Fatom xa ->
+ (match get t_atom xa with
+ | Atom.Abop (b0, a, b) ->
+ (match b0 with
+ | Atom.BO_eq t0 -> f a b
+ | _ -> C._true)
+ | _ -> C._true)
+ | _ -> C._true)
+ else C._true
+
+(** val get_not_le :
+ Form.form array -> Atom.atom array -> int -> (int -> int -> C.t) -> C.t **)
+
+let get_not_le t_form t_atom l f =
+ if negb (Lit.is_pos l)
+ then (match get t_form (Lit.blit l) with
+ | Form.Fatom xa ->
+ (match get t_atom xa with
+ | Atom.Abop (b0, a, b) ->
+ (match b0 with
+ | Atom.BO_Zle -> f a b
+ | _ -> C._true)
+ | _ -> C._true)
+ | _ -> C._true)
+ else C._true
+
+(** val check_micromega :
+ Form.form array -> Atom.atom array -> int list -> zArithProof list -> C.t **)
+
+let check_micromega t_form t_atom cl c =
+ match build_clause t_form t_atom empty_vmap cl with
+ | Some p -> let v,bf = p in if zTautoChecker bf c then cl else C._true
+ | None -> C._true
+
+(** val check_diseq : Form.form array -> Atom.atom array -> int -> C.t **)
+
+let check_diseq t_form t_atom l =
+ match get t_form (Lit.blit l) with
+ | Form.For a ->
+ if eqb0 (length a) (ExtrNative.of_uint(3))
+ then let a_eq_b = get a (ExtrNative.of_uint(0)) in
+ let not_a_le_b = get a (ExtrNative.of_uint(1)) in
+ let not_b_le_a = get a (ExtrNative.of_uint(2)) in
+ get_eq0 t_form t_atom a_eq_b (fun a0 b ->
+ get_not_le t_form t_atom not_a_le_b (fun a' b' ->
+ get_not_le t_form t_atom not_b_le_a (fun b'' a'' ->
+ if if if if eqb0 a0 a' then eqb0 a0 a'' else false
+ then eqb0 b b'
+ else false
+ then eqb0 b b''
+ else false
+ then Cons ((Lit.lit (Lit.blit l)), Nil)
+ else if if if if eqb0 a0 b' then eqb0 a0 b'' else false
+ then eqb0 b a'
+ else false
+ then eqb0 b a''
+ else false
+ then Cons ((Lit.lit (Lit.blit l)), Nil)
+ else C._true)))
+ else C._true
+ | _ -> C._true
+
+(** val check_atom_aux :
+ Atom.atom array -> (int -> int -> bool) -> Atom.atom -> Atom.atom -> bool **)
+
+let check_atom_aux t_atom check_hatom0 a b =
+ match a with
+ | Atom.Acop o1 ->
+ (match b with
+ | Atom.Acop o2 -> Atom.cop_eqb o1 o2
+ | _ -> false)
+ | Atom.Auop (o1, a0) ->
+ (match o1 with
+ | Atom.UO_Zneg ->
+ (match b with
+ | Atom.Auop (o2, b0) ->
+ (match o2 with
+ | Atom.UO_Zopp ->
+ (match get t_atom b0 with
+ | Atom.Auop (u, q) ->
+ (match u with
+ | Atom.UO_Zpos -> check_hatom0 a0 q
+ | _ -> false)
+ | _ -> false)
+ | _ -> if Atom.uop_eqb o1 o2 then check_hatom0 a0 b0 else false)
+ | _ -> false)
+ | Atom.UO_Zopp ->
+ (match b with
+ | Atom.Auop (o2, b0) ->
+ (match o2 with
+ | Atom.UO_Zneg ->
+ (match get t_atom a0 with
+ | Atom.Auop (u, p) ->
+ (match u with
+ | Atom.UO_Zpos -> check_hatom0 p b0
+ | _ -> false)
+ | _ -> false)
+ | _ -> if Atom.uop_eqb o1 o2 then check_hatom0 a0 b0 else false)
+ | _ -> false)
+ | _ ->
+ (match b with
+ | Atom.Auop (o2, b0) ->
+ if Atom.uop_eqb o1 o2 then check_hatom0 a0 b0 else false
+ | _ -> false))
+ | Atom.Abop (o1, a1, a2) ->
+ (match b with
+ | Atom.Abop (o2, b1, b2) ->
+ (match o1 with
+ | Atom.BO_Zplus ->
+ (match o2 with
+ | Atom.BO_Zplus ->
+ if if check_hatom0 a1 b1 then check_hatom0 a2 b2 else false
+ then true
+ else if check_hatom0 a1 b2 then check_hatom0 a2 b1 else false
+ | _ -> false)
+ | Atom.BO_Zminus ->
+ (match o2 with
+ | Atom.BO_Zminus ->
+ if check_hatom0 a1 b1 then check_hatom0 a2 b2 else false
+ | _ -> false)
+ | Atom.BO_Zmult ->
+ (match o2 with
+ | Atom.BO_Zmult ->
+ if if check_hatom0 a1 b1 then check_hatom0 a2 b2 else false
+ then true
+ else if check_hatom0 a1 b2 then check_hatom0 a2 b1 else false
+ | _ -> false)
+ | Atom.BO_Zlt ->
+ (match o2 with
+ | Atom.BO_Zlt ->
+ if check_hatom0 a1 b1 then check_hatom0 a2 b2 else false
+ | Atom.BO_Zgt ->
+ if check_hatom0 a1 b2 then check_hatom0 a2 b1 else false
+ | _ -> false)
+ | Atom.BO_Zle ->
+ (match o2 with
+ | Atom.BO_Zle ->
+ if check_hatom0 a1 b1 then check_hatom0 a2 b2 else false
+ | Atom.BO_Zge ->
+ if check_hatom0 a1 b2 then check_hatom0 a2 b1 else false
+ | _ -> false)
+ | Atom.BO_Zge ->
+ (match o2 with
+ | Atom.BO_Zle ->
+ if check_hatom0 a1 b2 then check_hatom0 a2 b1 else false
+ | Atom.BO_Zge ->
+ if check_hatom0 a1 b1 then check_hatom0 a2 b2 else false
+ | _ -> false)
+ | Atom.BO_Zgt ->
+ (match o2 with
+ | Atom.BO_Zlt ->
+ if check_hatom0 a1 b2 then check_hatom0 a2 b1 else false
+ | Atom.BO_Zgt ->
+ if check_hatom0 a1 b1 then check_hatom0 a2 b2 else false
+ | _ -> false)
+ | Atom.BO_eq t1 ->
+ (match o2 with
+ | Atom.BO_eq t2 ->
+ if Typ.eqb t1 t2
+ then if if check_hatom0 a1 b1 then check_hatom0 a2 b2 else false
+ then true
+ else if check_hatom0 a1 b2
+ then check_hatom0 a2 b1
+ else false
+ else false
+ | _ -> false))
+ | _ -> false)
+ | Atom.Anop (o1, l1) ->
+ (match b with
+ | Atom.Anop (o2, l2) ->
+ if Typ.eqb o1 o2 then list_beq check_hatom0 l1 l2 else false
+ | _ -> false)
+ | Atom.Aapp (f1, aargs) ->
+ (match b with
+ | Atom.Aapp (f2, bargs) ->
+ if eqb0 f1 f2 then list_beq check_hatom0 aargs bargs else false
+ | _ -> false)
+
+(** val check_hatom : Atom.atom array -> int -> int -> bool **)
+
+let check_hatom t_atom h1 h2 =
+ foldi_down_cont (fun x cont h3 h4 ->
+ if eqb0 h3 h4
+ then true
+ else check_atom_aux t_atom cont (get t_atom h3) (get t_atom h4))
+ (length t_atom) (ExtrNative.of_uint(0)) (fun h3 h4 -> false) h1 h2
+
+(** val check_neg_hatom : Atom.atom array -> int -> int -> bool **)
+
+let check_neg_hatom t_atom h1 h2 =
+ match get t_atom h1 with
+ | Atom.Abop (op3, a1, a2) ->
+ (match get t_atom h2 with
+ | Atom.Abop (op4, b1, b2) ->
+ (match op3 with
+ | Atom.BO_Zlt ->
+ (match op4 with
+ | Atom.BO_Zle ->
+ if check_hatom t_atom a1 b2
+ then check_hatom t_atom a2 b1
+ else false
+ | Atom.BO_Zge ->
+ if check_hatom t_atom a1 b1
+ then check_hatom t_atom a2 b2
+ else false
+ | _ -> false)
+ | Atom.BO_Zle ->
+ (match op4 with
+ | Atom.BO_Zlt ->
+ if check_hatom t_atom a1 b2
+ then check_hatom t_atom a2 b1
+ else false
+ | Atom.BO_Zgt ->
+ if check_hatom t_atom a1 b1
+ then check_hatom t_atom a2 b2
+ else false
+ | _ -> false)
+ | Atom.BO_Zge ->
+ (match op4 with
+ | Atom.BO_Zlt ->
+ if check_hatom t_atom a1 b1
+ then check_hatom t_atom a2 b2
+ else false
+ | Atom.BO_Zgt ->
+ if check_hatom t_atom a1 b2
+ then check_hatom t_atom a2 b1
+ else false
+ | _ -> false)
+ | Atom.BO_Zgt ->
+ (match op4 with
+ | Atom.BO_Zle ->
+ if check_hatom t_atom a1 b1
+ then check_hatom t_atom a2 b2
+ else false
+ | Atom.BO_Zge ->
+ if check_hatom t_atom a1 b2
+ then check_hatom t_atom a2 b1
+ else false
+ | _ -> false)
+ | _ -> false)
+ | _ -> false)
+ | _ -> false
+
+(** val remove_not : Form.form array -> int -> int **)
+
+let remove_not t_form l =
+ match get t_form (Lit.blit l) with
+ | Form.Fnot2 (i, l') -> if Lit.is_pos l then l' else Lit.neg l'
+ | _ -> l
+
+(** val get_and : Form.form array -> int -> int array option **)
+
+let get_and t_form l =
+ let l0 = remove_not t_form l in
+ if Lit.is_pos l0
+ then (match get t_form (Lit.blit l0) with
+ | Form.Fand args -> Some args
+ | _ -> None)
+ else None
+
+(** val get_or : Form.form array -> int -> int array option **)
+
+let get_or t_form l =
+ let l0 = remove_not t_form l in
+ if Lit.is_pos l0
+ then (match get t_form (Lit.blit l0) with
+ | Form.For args -> Some args
+ | _ -> None)
+ else None
+
+(** val flatten_op_body :
+ (int -> int array option) -> (int list -> int -> int list) -> int list ->
+ int -> int list **)
+
+let flatten_op_body get_op frec largs l =
+ match get_op l with
+ | Some a -> fold_left frec largs a
+ | None -> Cons (l, largs)
+
+(** val flatten_op_lit :
+ (int -> int array option) -> int -> int list -> int -> int list **)
+
+let flatten_op_lit get_op max0 =
+ foldi_cont (fun x -> flatten_op_body get_op) (ExtrNative.of_uint(0)) max0
+ (fun largs l -> Cons (l, largs))
+
+(** val flatten_and : Form.form array -> int array -> int list **)
+
+let flatten_and t_form t0 =
+ fold_left (flatten_op_lit (get_and t_form) (length t_form)) Nil t0
+
+(** val flatten_or : Form.form array -> int array -> int list **)
+
+let flatten_or t_form t0 =
+ fold_left (flatten_op_lit (get_or t_form) (length t_form)) Nil t0
+
+(** val check_flatten_body :
+ Form.form array -> (int -> int -> bool) -> (int -> int -> bool) -> (int
+ -> int -> bool) -> int -> int -> bool **)
+
+let check_flatten_body t_form check_atom0 check_neg_atom frec l lf =
+ let l0 = remove_not t_form l in
+ let lf0 = remove_not t_form lf in
+ if eqb0 l0 lf0
+ then true
+ else if eqb0 (land0 (ExtrNative.of_uint(1)) (lxor0 l0 lf0))
+ (ExtrNative.of_uint(0))
+ then (match get t_form (Lit.blit l0) with
+ | Form.Fatom a1 ->
+ (match get t_form (Lit.blit lf0) with
+ | Form.Fatom a2 -> check_atom0 a1 a2
+ | _ -> false)
+ | Form.Ftrue ->
+ (match get t_form (Lit.blit lf0) with
+ | Form.Ftrue -> true
+ | _ -> false)
+ | Form.Ffalse ->
+ (match get t_form (Lit.blit lf0) with
+ | Form.Ffalse -> true
+ | _ -> false)
+ | Form.Fnot2 (i, i0) -> false
+ | Form.Fand args1 ->
+ (match get t_form (Lit.blit lf0) with
+ | Form.Fand args2 ->
+ let args3 = flatten_and t_form args1 in
+ let args4 = flatten_and t_form args2 in
+ forallb2 frec args3 args4
+ | _ -> false)
+ | Form.For args1 ->
+ (match get t_form (Lit.blit lf0) with
+ | Form.For args2 ->
+ let args3 = flatten_or t_form args1 in
+ let args4 = flatten_or t_form args2 in
+ forallb2 frec args3 args4
+ | _ -> false)
+ | Form.Fimp args1 ->
+ (match get t_form (Lit.blit lf0) with
+ | Form.Fimp args2 ->
+ if eqb0 (length args1) (length args2)
+ then forallbi (fun i l1 -> frec l1 (get args2 i)) args1
+ else false
+ | _ -> false)
+ | Form.Fxor (l1, l2) ->
+ (match get t_form (Lit.blit lf0) with
+ | Form.Fxor (lf1, lf2) ->
+ if frec l1 lf1 then frec l2 lf2 else false
+ | _ -> false)
+ | Form.Fiff (l1, l2) ->
+ (match get t_form (Lit.blit lf0) with
+ | Form.Fiff (lf1, lf2) ->
+ if frec l1 lf1 then frec l2 lf2 else false
+ | _ -> false)
+ | Form.Fite (l1, l2, l3) ->
+ (match get t_form (Lit.blit lf0) with
+ | Form.Fite (lf1, lf2, lf3) ->
+ if if frec l1 lf1 then frec l2 lf2 else false
+ then frec l3 lf3
+ else false
+ | _ -> false))
+ else (match get t_form (Lit.blit l0) with
+ | Form.Fatom a1 ->
+ (match get t_form (Lit.blit lf0) with
+ | Form.Fatom a2 -> check_neg_atom a1 a2
+ | _ -> false)
+ | _ -> false)
+
+(** val check_flatten_aux :
+ Form.form array -> (int -> int -> bool) -> (int -> int -> bool) -> int ->
+ int -> bool **)
+
+let check_flatten_aux t_form check_atom0 check_neg_atom l lf =
+ foldi_cont (fun x -> check_flatten_body t_form check_atom0 check_neg_atom)
+ (ExtrNative.of_uint(0)) (length t_form) (fun x x0 -> false) l lf
+
+(** val check_flatten :
+ Form.form array -> (int -> int -> bool) -> (int -> int -> bool) -> S.t ->
+ int -> int -> C.t **)
+
+let check_flatten t_form check_atom0 check_neg_atom s cid lf =
+ match S.get s cid with
+ | Nil -> C._true
+ | Cons (l, l0) ->
+ (match l0 with
+ | Nil ->
+ if check_flatten_aux t_form check_atom0 check_neg_atom l lf
+ then Cons (lf, Nil)
+ else C._true
+ | Cons (i, l1) -> C._true)
+
+(** val check_spl_arith :
+ Form.form array -> Atom.atom array -> int list -> int -> zArithProof list
+ -> C.t **)
+
+let check_spl_arith t_form t_atom orig res l =
+ match orig with
+ | Nil -> C._true
+ | Cons (li, l0) ->
+ (match l0 with
+ | Nil ->
+ let cl = Cons ((Lit.neg li), (Cons (res, Nil))) in
+ (match build_clause t_form t_atom empty_vmap cl with
+ | Some p ->
+ let v,bf = p in
+ if zTautoChecker bf l then Cons (res, Nil) else C._true
+ | None -> C._true)
+ | Cons (y, l1) -> C._true)
+
+(** val check_in : int -> int list -> bool **)
+
+let rec check_in x = function
+| Nil -> false
+| Cons (t0, q) -> if eqb0 x t0 then true else check_in x q
+
+(** val check_diseqs_complete_aux :
+ int -> int list -> (int*int) option array -> bool **)
+
+let rec check_diseqs_complete_aux a dist t0 =
+ match dist with
+ | Nil -> true
+ | Cons (b, q) ->
+ if existsb1 (fun x ->
+ match x with
+ | Some p ->
+ let a',b' = p in
+ if if eqb0 a a' then eqb0 b b' else false
+ then true
+ else if eqb0 a b' then eqb0 b a' else false
+ | None -> false) t0
+ then check_diseqs_complete_aux a q t0
+ else false
+
+(** val check_diseqs_complete :
+ int list -> (int*int) option array -> bool **)
+
+let rec check_diseqs_complete dist t0 =
+ match dist with
+ | Nil -> true
+ | Cons (a, q) ->
+ if check_diseqs_complete_aux a q t0
+ then check_diseqs_complete q t0
+ else false
+
+(** val check_diseqs :
+ Form.form array -> Atom.atom array -> Typ.coq_type -> int list -> int
+ array -> bool **)
+
+let check_diseqs t_form t_atom ty dist diseq =
+ let t0 =
+ mapi (fun x t0 ->
+ if Lit.is_pos t0
+ then None
+ else (match get t_form (Lit.blit t0) with
+ | Form.Fatom a ->
+ (match get t_atom a with
+ | Atom.Acop c -> None
+ | Atom.Auop (u, i) -> None
+ | Atom.Abop (b, h1, h2) ->
+ (match b with
+ | Atom.BO_Zplus -> None
+ | Atom.BO_Zminus -> None
+ | Atom.BO_Zmult -> None
+ | Atom.BO_Zlt -> None
+ | Atom.BO_Zle -> None
+ | Atom.BO_Zge -> None
+ | Atom.BO_Zgt -> None
+ | Atom.BO_eq a0 ->
+ if if if if Typ.eqb ty a0
+ then negb (eqb0 h1 h2)
+ else false
+ then check_in h1 dist
+ else false
+ then check_in h2 dist
+ else false
+ then Some (h1,h2)
+ else None)
+ | _ -> None)
+ | _ -> None)) diseq
+ in
+ if forallb1 (fun x ->
+ match x with
+ | Some y -> true
+ | None -> false) t0
+ then check_diseqs_complete dist t0
+ else false
+
+(** val check_distinct :
+ Form.form array -> Atom.atom array -> int -> int array -> bool **)
+
+let check_distinct t_form t_atom ha diseq =
+ match get t_atom ha with
+ | Atom.Anop (n0, dist) -> check_diseqs t_form t_atom n0 dist diseq
+ | _ -> false
+
+(** val check_distinct_two_args :
+ Form.form array -> Atom.atom array -> int -> int -> bool **)
+
+let check_distinct_two_args t_form t_atom f1 f2 =
+ match get t_form f1 with
+ | Form.Fatom ha ->
+ (match get t_form f2 with
+ | Form.Fatom hb ->
+ (match get t_atom ha with
+ | Atom.Anop (n0, l) ->
+ (match l with
+ | Nil -> false
+ | Cons (x, l0) ->
+ (match l0 with
+ | Nil -> false
+ | Cons (y, l1) ->
+ (match l1 with
+ | Nil ->
+ (match get t_atom hb with
+ | Atom.Abop (b, x', y') ->
+ (match b with
+ | Atom.BO_eq ty' ->
+ if Typ.eqb n0 ty'
+ then if if eqb0 x x' then eqb0 y y' else false
+ then true
+ else if eqb0 x y' then eqb0 y x' else false
+ else false
+ | _ -> false)
+ | _ -> false)
+ | Cons (i, l2) -> false)))
+ | _ -> false)
+ | _ -> false)
+ | _ -> false
+
+(** val check_lit :
+ Form.form array -> Atom.atom array -> (int -> int -> bool) -> int -> int
+ -> bool **)
+
+let check_lit t_form t_atom check_var l1 l2 =
+ if if eqb0 l1 l2
+ then true
+ else if eqb (Lit.is_pos l1) (Lit.is_pos l2)
+ then check_var (Lit.blit l1) (Lit.blit l2)
+ else false
+ then true
+ else if eqb (Lit.is_pos l1) (negb (Lit.is_pos l2))
+ then check_distinct_two_args t_form t_atom (Lit.blit l1) (Lit.blit l2)
+ else false
+
+(** val check_form_aux :
+ Form.form array -> Atom.atom array -> (int -> int -> bool) -> Form.form
+ -> Form.form -> bool **)
+
+let check_form_aux t_form t_atom check_var a b =
+ match a with
+ | Form.Fatom a0 ->
+ (match b with
+ | Form.Fatom b0 -> eqb0 a0 b0
+ | Form.Fand diseq -> check_distinct t_form t_atom a0 diseq
+ | _ -> false)
+ | Form.Ftrue ->
+ (match b with
+ | Form.Ftrue -> true
+ | _ -> false)
+ | Form.Ffalse ->
+ (match b with
+ | Form.Ffalse -> true
+ | _ -> false)
+ | Form.Fnot2 (i1, l1) ->
+ (match b with
+ | Form.Fnot2 (i2, l2) ->
+ if eqb0 i1 i2 then check_lit t_form t_atom check_var l1 l2 else false
+ | _ -> false)
+ | Form.Fand a1 ->
+ (match b with
+ | Form.Fand a2 ->
+ if eqb0 (length a1) (length a2)
+ then forallbi (fun i l ->
+ check_lit t_form t_atom check_var l (get a2 i)) a1
+ else false
+ | _ -> false)
+ | Form.For a1 ->
+ (match b with
+ | Form.For a2 ->
+ if eqb0 (length a1) (length a2)
+ then forallbi (fun i l ->
+ check_lit t_form t_atom check_var l (get a2 i)) a1
+ else false
+ | _ -> false)
+ | Form.Fimp a1 ->
+ (match b with
+ | Form.Fimp a2 ->
+ if eqb0 (length a1) (length a2)
+ then forallbi (fun i l ->
+ check_lit t_form t_atom check_var l (get a2 i)) a1
+ else false
+ | _ -> false)
+ | Form.Fxor (l1, l2) ->
+ (match b with
+ | Form.Fxor (j1, j2) ->
+ if check_lit t_form t_atom check_var l1 j1
+ then check_lit t_form t_atom check_var l2 j2
+ else false
+ | _ -> false)
+ | Form.Fiff (l1, l2) ->
+ (match b with
+ | Form.Fiff (j1, j2) ->
+ if check_lit t_form t_atom check_var l1 j1
+ then check_lit t_form t_atom check_var l2 j2
+ else false
+ | _ -> false)
+ | Form.Fite (l1, l2, l3) ->
+ (match b with
+ | Form.Fite (j1, j2, j3) ->
+ if if check_lit t_form t_atom check_var l1 j1
+ then check_lit t_form t_atom check_var l2 j2
+ else false
+ then check_lit t_form t_atom check_var l3 j3
+ else false
+ | _ -> false)
+
+(** val check_hform :
+ Form.form array -> Atom.atom array -> int -> int -> bool **)
+
+let check_hform t_form t_atom h1 h2 =
+ foldi_down_cont (fun x cont h3 h4 ->
+ if eqb0 h3 h4
+ then true
+ else check_form_aux t_form t_atom cont (get t_form h3) (get t_form h4))
+ (length t_form) (ExtrNative.of_uint(0)) (fun h3 h4 -> false) h1 h2
+
+(** val check_lit' :
+ Form.form array -> Atom.atom array -> int -> int -> bool **)
+
+let check_lit' t_form t_atom =
+ check_lit t_form t_atom (check_hform t_form t_atom)
+
+(** val check_distinct_elim :
+ Form.form array -> Atom.atom array -> int list -> int -> int list **)
+
+let rec check_distinct_elim t_form t_atom input res =
+ match input with
+ | Nil -> Nil
+ | Cons (l, q) ->
+ if check_lit' t_form t_atom l res
+ then Cons (res, q)
+ else Cons (l, (check_distinct_elim t_form t_atom q res))
+
+type 'step _trace_ = 'step array array
+
+(** val _checker_ :
+ (S.t -> 'a1 -> S.t) -> (C.t -> bool) -> S.t -> 'a1 _trace_ -> int -> bool **)
+
+let _checker_ check_step is_false0 s t0 confl =
+ let s' = fold_left (fun s0 a -> fold_left check_step s0 a) s t0 in
+ is_false0 (S.get s' confl)
+
+module Euf_Checker =
+ struct
+ type step =
+ | Res of int * int array
+ | ImmFlatten of int * int * int
+ | CTrue of int
+ | CFalse of int
+ | BuildDef of int * int
+ | BuildDef2 of int * int
+ | BuildProj of int * int * int
+ | ImmBuildDef of int * int
+ | ImmBuildDef2 of int * int
+ | ImmBuildProj of int * int * int
+ | EqTr of int * int * int list
+ | EqCgr of int * int * int option list
+ | EqCgrP of int * int * int * int option list
+ | LiaMicromega of int * int list * zArithProof list
+ | LiaDiseq of int * int
+ | SplArith of int * int * int * zArithProof list
+ | SplDistinctElim of int * int * int
+
+ (** val step_rect :
+ (int -> int array -> 'a1) -> (int -> int -> int -> 'a1) -> (int -> 'a1)
+ -> (int -> 'a1) -> (int -> int -> 'a1) -> (int -> int -> 'a1) -> (int
+ -> int -> int -> 'a1) -> (int -> int -> 'a1) -> (int -> int -> 'a1) ->
+ (int -> int -> int -> 'a1) -> (int -> int -> int list -> 'a1) -> (int
+ -> int -> int option list -> 'a1) -> (int -> int -> int -> int option
+ list -> 'a1) -> (int -> int list -> zArithProof list -> 'a1) -> (int ->
+ int -> 'a1) -> (int -> int -> int -> zArithProof list -> 'a1) -> (int
+ -> int -> int -> 'a1) -> step -> 'a1 **)
+
+ let step_rect f f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 = function
+ | Res (x, x0) -> f x x0
+ | ImmFlatten (x, x0, x1) -> f0 x x0 x1
+ | CTrue x -> f1 x
+ | CFalse x -> f2 x
+ | BuildDef (x, x0) -> f3 x x0
+ | BuildDef2 (x, x0) -> f4 x x0
+ | BuildProj (x, x0, x1) -> f5 x x0 x1
+ | ImmBuildDef (x, x0) -> f6 x x0
+ | ImmBuildDef2 (x, x0) -> f7 x x0
+ | ImmBuildProj (x, x0, x1) -> f8 x x0 x1
+ | EqTr (x, x0, x1) -> f9 x x0 x1
+ | EqCgr (x, x0, x1) -> f10 x x0 x1
+ | EqCgrP (x, x0, x1, x2) -> f11 x x0 x1 x2
+ | LiaMicromega (x, x0, x1) -> f12 x x0 x1
+ | LiaDiseq (x, x0) -> f13 x x0
+ | SplArith (x, x0, x1, x2) -> f14 x x0 x1 x2
+ | SplDistinctElim (x, x0, x1) -> f15 x x0 x1
+
+ (** val step_rec :
+ (int -> int array -> 'a1) -> (int -> int -> int -> 'a1) -> (int -> 'a1)
+ -> (int -> 'a1) -> (int -> int -> 'a1) -> (int -> int -> 'a1) -> (int
+ -> int -> int -> 'a1) -> (int -> int -> 'a1) -> (int -> int -> 'a1) ->
+ (int -> int -> int -> 'a1) -> (int -> int -> int list -> 'a1) -> (int
+ -> int -> int option list -> 'a1) -> (int -> int -> int -> int option
+ list -> 'a1) -> (int -> int list -> zArithProof list -> 'a1) -> (int ->
+ int -> 'a1) -> (int -> int -> int -> zArithProof list -> 'a1) -> (int
+ -> int -> int -> 'a1) -> step -> 'a1 **)
+
+ let step_rec f f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 = function
+ | Res (x, x0) -> f x x0
+ | ImmFlatten (x, x0, x1) -> f0 x x0 x1
+ | CTrue x -> f1 x
+ | CFalse x -> f2 x
+ | BuildDef (x, x0) -> f3 x x0
+ | BuildDef2 (x, x0) -> f4 x x0
+ | BuildProj (x, x0, x1) -> f5 x x0 x1
+ | ImmBuildDef (x, x0) -> f6 x x0
+ | ImmBuildDef2 (x, x0) -> f7 x x0
+ | ImmBuildProj (x, x0, x1) -> f8 x x0 x1
+ | EqTr (x, x0, x1) -> f9 x x0 x1
+ | EqCgr (x, x0, x1) -> f10 x x0 x1
+ | EqCgrP (x, x0, x1, x2) -> f11 x x0 x1 x2
+ | LiaMicromega (x, x0, x1) -> f12 x x0 x1
+ | LiaDiseq (x, x0) -> f13 x x0
+ | SplArith (x, x0, x1, x2) -> f14 x x0 x1 x2
+ | SplDistinctElim (x, x0, x1) -> f15 x x0 x1
+
+ (** val step_checker :
+ Atom.atom array -> Form.form array -> S.t -> step -> S.t **)
+
+ let step_checker t_atom t_form s = function
+ | Res (pos, res) -> S.set_resolve s pos res
+ | ImmFlatten (pos, cid, lf) ->
+ S.set_clause s pos
+ (check_flatten t_form (check_hatom t_atom) (check_neg_hatom t_atom) s
+ cid lf)
+ | CTrue pos -> S.set_clause s pos check_True
+ | CFalse pos -> S.set_clause s pos check_False
+ | BuildDef (pos, l) -> S.set_clause s pos (check_BuildDef t_form l)
+ | BuildDef2 (pos, l) -> S.set_clause s pos (check_BuildDef2 t_form l)
+ | BuildProj (pos, l, i) -> S.set_clause s pos (check_BuildProj t_form l i)
+ | ImmBuildDef (pos, cid) ->
+ S.set_clause s pos (check_ImmBuildDef t_form s cid)
+ | ImmBuildDef2 (pos, cid) ->
+ S.set_clause s pos (check_ImmBuildDef2 t_form s cid)
+ | ImmBuildProj (pos, cid, i) ->
+ S.set_clause s pos (check_ImmBuildProj t_form s cid i)
+ | EqTr (pos, l, fl) -> S.set_clause s pos (check_trans t_form t_atom l fl)
+ | EqCgr (pos, l, fl) -> S.set_clause s pos (check_congr t_form t_atom l fl)
+ | EqCgrP (pos, l1, l2, fl) ->
+ S.set_clause s pos (check_congr_pred t_form t_atom l1 l2 fl)
+ | LiaMicromega (pos, cl, c) ->
+ S.set_clause s pos (check_micromega t_form t_atom cl c)
+ | LiaDiseq (pos, l) -> S.set_clause s pos (check_diseq t_form t_atom l)
+ | SplArith (pos, orig, res, l) ->
+ S.set_clause s pos (check_spl_arith t_form t_atom (S.get s orig) res l)
+ | SplDistinctElim (pos, orig, res) ->
+ S.set_clause s pos (check_distinct_elim t_form t_atom (S.get s orig) res)
+
+ (** val euf_checker :
+ Atom.atom array -> Form.form array -> (C.t -> bool) -> S.t -> step
+ _trace_ -> int -> bool **)
+
+ let euf_checker t_atom t_form s t0 =
+ _checker_ (step_checker t_atom t_form) s t0
+
+ type certif =
+ | Certif of int * step _trace_ * int
+
+ (** val certif_rect :
+ (int -> step _trace_ -> int -> 'a1) -> certif -> 'a1 **)
+
+ let certif_rect f = function
+ | Certif (x, x0, x1) -> f x x0 x1
+
+ (** val certif_rec :
+ (int -> step _trace_ -> int -> 'a1) -> certif -> 'a1 **)
+
+ let certif_rec f = function
+ | Certif (x, x0, x1) -> f x x0 x1
+
+ (** val add_roots : S.t -> int array -> int array option -> S.t **)
+
+ let add_roots s d = function
+ | Some ur ->
+ foldi_right (fun i c_index s0 ->
+ let c =
+ if ltb0 c_index (length d)
+ then Cons ((get d c_index), Nil)
+ else C._true
+ in
+ S.set_clause s0 i c) ur s
+ | None -> foldi_right (fun i c s0 -> S.set_clause s0 i (Cons (c, Nil))) d s
+
+ (** val valid :
+ typ_eqb array -> Atom.tval array -> Atom.atom array -> Form.form array
+ -> int array -> bool **)
+
+ let valid t_i t_func t_atom t_form d =
+ let rho =
+ Form.interp_state_var (Atom.interp_form_hatom t_i t_func t_atom) t_form
+ in
+ afold_left true (fun b1 b2 -> if b1 then b2 else false) (Lit.interp rho)
+ d
+
+ (** val checker :
+ typ_eqb array -> Atom.tval array -> Atom.atom array -> Form.form array
+ -> int array -> int array option -> certif -> bool **)
+
+ let checker t_i t_func t_atom t_form d used_roots = function
+ | Certif (nclauses, t0, confl) ->
+ if if if Form.check_form t_form then Atom.check_atom t_atom else false
+ then Atom.wt t_i t_func t_atom
+ else false
+ then euf_checker t_atom t_form C.is_false
+ (add_roots (S.make nclauses) d used_roots) t0 confl
+ else false
+
+ (** val checker_b :
+ typ_eqb array -> Atom.tval array -> Atom.atom array -> Form.form array
+ -> int -> bool -> certif -> bool **)
+
+ let checker_b t_i t_func t_atom t_form l b c =
+ let l0 = if b then Lit.neg l else l in
+ let Certif (nclauses, x, x0) = c in
+ checker t_i t_func t_atom t_form (make nclauses l0) None c
+
+ (** val checker_eq :
+ typ_eqb array -> Atom.tval array -> Atom.atom array -> Form.form array
+ -> int -> int -> int -> certif -> bool **)
+
+ let checker_eq t_i t_func t_atom t_form l1 l2 l c =
+ if if negb (Lit.is_pos l)
+ then (match get t_form (Lit.blit l) with
+ | Form.Fiff (l1', l2') ->
+ if eqb0 l1 l1' then eqb0 l2 l2' else false
+ | _ -> false)
+ else false
+ then let Certif (nclauses, x, x0) = c in
+ checker t_i t_func t_atom t_form (make nclauses l) None c
+ else false
+
+ (** val checker_ext :
+ Atom.atom array -> Form.form array -> int array -> int array option ->
+ certif -> bool **)
+
+ let checker_ext t_atom t_form d used_roots = function
+ | Certif (nclauses, t0, confl) ->
+ if if Form.check_form t_form then Atom.check_atom t_atom else false
+ then euf_checker t_atom t_form C.is_false
+ (add_roots (S.make nclauses) d used_roots) t0 confl
+ else false
+ end
+
diff --git a/src/extraction/smt_checker.mli b/src/extraction/smt_checker.mli
new file mode 100644
index 0000000..502d6f3
--- /dev/null
+++ b/src/extraction/smt_checker.mli
@@ -0,0 +1,1889 @@
+type __ = Obj.t
+
+type unit0 =
+| Tt
+
+val implb : bool -> bool -> bool
+
+val xorb : bool -> bool -> bool
+
+val negb : bool -> bool
+
+type nat =
+| O
+| S of nat
+
+type 'a option =
+| Some of 'a
+| None
+
+val option_map : ('a1 -> 'a2) -> 'a1 option -> 'a2 option
+
+val fst : ('a1*'a2) -> 'a1
+
+val snd : ('a1*'a2) -> 'a2
+
+type 'a list =
+| Nil
+| Cons of 'a * 'a list
+
+val app : 'a1 list -> 'a1 list -> 'a1 list
+
+val compOpp : ExtrNative.comparison -> ExtrNative.comparison
+
+type compareSpecT =
+| CompEqT
+| CompLtT
+| CompGtT
+
+val compareSpec2Type : ExtrNative.comparison -> compareSpecT
+
+type 'a compSpecT = compareSpecT
+
+val compSpec2Type : 'a1 -> 'a1 -> ExtrNative.comparison -> 'a1 compSpecT
+
+type 'a sig0 =
+ 'a
+ (* singleton inductive, whose constructor was exist *)
+
+type sumbool =
+| Left
+| Right
+
+type 'a sumor =
+| Inleft of 'a
+| Inright
+
+val plus : nat -> nat -> nat
+
+val nat_iter : nat -> ('a1 -> 'a1) -> 'a1 -> 'a1
+
+type positive =
+| XI of positive
+| XO of positive
+| XH
+
+type n =
+| N0
+| Npos of positive
+
+type z =
+| Z0
+| Zpos of positive
+| Zneg of positive
+
+val eqb : bool -> bool -> bool
+
+type reflect =
+| ReflectT
+| ReflectF
+
+val iff_reflect : bool -> reflect
+
+module type TotalOrder' =
+ sig
+ type t
+ end
+
+module MakeOrderTac :
+ functor (O:TotalOrder') ->
+ sig
+
+ end
+
+module MaxLogicalProperties :
+ functor (O:TotalOrder') ->
+ functor (M:sig
+ val max : O.t -> O.t -> O.t
+ end) ->
+ sig
+ module Private_Tac :
+ sig
+
+ end
+ end
+
+module Pos :
+ sig
+ type t = positive
+
+ val succ : positive -> positive
+
+ val add : positive -> positive -> positive
+
+ val add_carry : positive -> positive -> positive
+
+ val pred_double : positive -> positive
+
+ val pred : positive -> positive
+
+ val pred_N : positive -> n
+
+ type mask =
+ | IsNul
+ | IsPos of positive
+ | IsNeg
+
+ val mask_rect : 'a1 -> (positive -> 'a1) -> 'a1 -> mask -> 'a1
+
+ val mask_rec : 'a1 -> (positive -> 'a1) -> 'a1 -> mask -> 'a1
+
+ val succ_double_mask : mask -> mask
+
+ val double_mask : mask -> mask
+
+ val double_pred_mask : positive -> mask
+
+ val pred_mask : mask -> mask
+
+ val sub_mask : positive -> positive -> mask
+
+ val sub_mask_carry : positive -> positive -> mask
+
+ val sub : positive -> positive -> positive
+
+ val mul : positive -> positive -> positive
+
+ val iter : positive -> ('a1 -> 'a1) -> 'a1 -> 'a1
+
+ val pow : positive -> positive -> positive
+
+ val square : positive -> positive
+
+ val div2 : positive -> positive
+
+ val div2_up : positive -> positive
+
+ val size_nat : positive -> nat
+
+ val size : positive -> positive
+
+ val compare_cont :
+ positive -> positive -> ExtrNative.comparison -> ExtrNative.comparison
+
+ val compare : positive -> positive -> ExtrNative.comparison
+
+ val min : positive -> positive -> positive
+
+ val max : positive -> positive -> positive
+
+ val eqb : positive -> positive -> bool
+
+ val leb : positive -> positive -> bool
+
+ val ltb : positive -> positive -> bool
+
+ val sqrtrem_step :
+ (positive -> positive) -> (positive -> positive) -> (positive*mask) ->
+ positive*mask
+
+ val sqrtrem : positive -> positive*mask
+
+ val sqrt : positive -> positive
+
+ val gcdn : nat -> positive -> positive -> positive
+
+ val gcd : positive -> positive -> positive
+
+ val ggcdn : nat -> positive -> positive -> positive*(positive*positive)
+
+ val ggcd : positive -> positive -> positive*(positive*positive)
+
+ val coq_Nsucc_double : n -> n
+
+ val coq_Ndouble : n -> n
+
+ val coq_lor : positive -> positive -> positive
+
+ val coq_land : positive -> positive -> n
+
+ val ldiff : positive -> positive -> n
+
+ val coq_lxor : positive -> positive -> n
+
+ val shiftl_nat : positive -> nat -> positive
+
+ val shiftr_nat : positive -> nat -> positive
+
+ val shiftl : positive -> n -> positive
+
+ val shiftr : positive -> n -> positive
+
+ val testbit_nat : positive -> nat -> bool
+
+ val testbit : positive -> n -> bool
+
+ val iter_op : ('a1 -> 'a1 -> 'a1) -> positive -> 'a1 -> 'a1
+
+ val to_nat : positive -> nat
+
+ val of_nat : nat -> positive
+
+ val of_succ_nat : nat -> positive
+ end
+
+module Coq_Pos :
+ sig
+ module Coq__1 : sig
+ type t = positive
+ end
+ type t = Coq__1.t
+
+ val succ : positive -> positive
+
+ val add : positive -> positive -> positive
+
+ val add_carry : positive -> positive -> positive
+
+ val pred_double : positive -> positive
+
+ val pred : positive -> positive
+
+ val pred_N : positive -> n
+
+ type mask = Pos.mask =
+ | IsNul
+ | IsPos of positive
+ | IsNeg
+
+ val mask_rect : 'a1 -> (positive -> 'a1) -> 'a1 -> mask -> 'a1
+
+ val mask_rec : 'a1 -> (positive -> 'a1) -> 'a1 -> mask -> 'a1
+
+ val succ_double_mask : mask -> mask
+
+ val double_mask : mask -> mask
+
+ val double_pred_mask : positive -> mask
+
+ val pred_mask : mask -> mask
+
+ val sub_mask : positive -> positive -> mask
+
+ val sub_mask_carry : positive -> positive -> mask
+
+ val sub : positive -> positive -> positive
+
+ val mul : positive -> positive -> positive
+
+ val iter : positive -> ('a1 -> 'a1) -> 'a1 -> 'a1
+
+ val pow : positive -> positive -> positive
+
+ val square : positive -> positive
+
+ val div2 : positive -> positive
+
+ val div2_up : positive -> positive
+
+ val size_nat : positive -> nat
+
+ val size : positive -> positive
+
+ val compare_cont :
+ positive -> positive -> ExtrNative.comparison -> ExtrNative.comparison
+
+ val compare : positive -> positive -> ExtrNative.comparison
+
+ val min : positive -> positive -> positive
+
+ val max : positive -> positive -> positive
+
+ val eqb : positive -> positive -> bool
+
+ val leb : positive -> positive -> bool
+
+ val ltb : positive -> positive -> bool
+
+ val sqrtrem_step :
+ (positive -> positive) -> (positive -> positive) -> (positive*mask) ->
+ positive*mask
+
+ val sqrtrem : positive -> positive*mask
+
+ val sqrt : positive -> positive
+
+ val gcdn : nat -> positive -> positive -> positive
+
+ val gcd : positive -> positive -> positive
+
+ val ggcdn : nat -> positive -> positive -> positive*(positive*positive)
+
+ val ggcd : positive -> positive -> positive*(positive*positive)
+
+ val coq_Nsucc_double : n -> n
+
+ val coq_Ndouble : n -> n
+
+ val coq_lor : positive -> positive -> positive
+
+ val coq_land : positive -> positive -> n
+
+ val ldiff : positive -> positive -> n
+
+ val coq_lxor : positive -> positive -> n
+
+ val shiftl_nat : positive -> nat -> positive
+
+ val shiftr_nat : positive -> nat -> positive
+
+ val shiftl : positive -> n -> positive
+
+ val shiftr : positive -> n -> positive
+
+ val testbit_nat : positive -> nat -> bool
+
+ val testbit : positive -> n -> bool
+
+ val iter_op : ('a1 -> 'a1 -> 'a1) -> positive -> 'a1 -> 'a1
+
+ val to_nat : positive -> nat
+
+ val of_nat : nat -> positive
+
+ val of_succ_nat : nat -> positive
+
+ val eq_dec : positive -> positive -> sumbool
+
+ val peano_rect : 'a1 -> (positive -> 'a1 -> 'a1) -> positive -> 'a1
+
+ val peano_rec : 'a1 -> (positive -> 'a1 -> 'a1) -> positive -> 'a1
+
+ type coq_PeanoView =
+ | PeanoOne
+ | PeanoSucc of positive * coq_PeanoView
+
+ val coq_PeanoView_rect :
+ 'a1 -> (positive -> coq_PeanoView -> 'a1 -> 'a1) -> positive ->
+ coq_PeanoView -> 'a1
+
+ val coq_PeanoView_rec :
+ 'a1 -> (positive -> coq_PeanoView -> 'a1 -> 'a1) -> positive ->
+ coq_PeanoView -> 'a1
+
+ val peanoView_xO : positive -> coq_PeanoView -> coq_PeanoView
+
+ val peanoView_xI : positive -> coq_PeanoView -> coq_PeanoView
+
+ val peanoView : positive -> coq_PeanoView
+
+ val coq_PeanoView_iter :
+ 'a1 -> (positive -> 'a1 -> 'a1) -> positive -> coq_PeanoView -> 'a1
+
+ val eqb_spec : positive -> positive -> reflect
+
+ val switch_Eq :
+ ExtrNative.comparison -> ExtrNative.comparison -> ExtrNative.comparison
+
+ val mask2cmp : mask -> ExtrNative.comparison
+
+ val leb_spec0 : positive -> positive -> reflect
+
+ val ltb_spec0 : positive -> positive -> reflect
+
+ module Private_Tac :
+ sig
+
+ end
+
+ module Private_Rev :
+ sig
+ module ORev :
+ sig
+ type t = Coq__1.t
+ end
+
+ module MRev :
+ sig
+ val max : t -> t -> t
+ end
+
+ module MPRev :
+ sig
+ module Private_Tac :
+ sig
+
+ end
+ end
+ end
+
+ module Private_Dec :
+ sig
+ val max_case_strong :
+ t -> t -> (t -> t -> __ -> 'a1 -> 'a1) -> (__ -> 'a1) -> (__ -> 'a1) ->
+ 'a1
+
+ val max_case :
+ t -> t -> (t -> t -> __ -> 'a1 -> 'a1) -> 'a1 -> 'a1 -> 'a1
+
+ val max_dec : t -> t -> sumbool
+
+ val min_case_strong :
+ t -> t -> (t -> t -> __ -> 'a1 -> 'a1) -> (__ -> 'a1) -> (__ -> 'a1) ->
+ 'a1
+
+ val min_case :
+ t -> t -> (t -> t -> __ -> 'a1 -> 'a1) -> 'a1 -> 'a1 -> 'a1
+
+ val min_dec : t -> t -> sumbool
+ end
+
+ val max_case_strong : t -> t -> (__ -> 'a1) -> (__ -> 'a1) -> 'a1
+
+ val max_case : t -> t -> 'a1 -> 'a1 -> 'a1
+
+ val max_dec : t -> t -> sumbool
+
+ val min_case_strong : t -> t -> (__ -> 'a1) -> (__ -> 'a1) -> 'a1
+
+ val min_case : t -> t -> 'a1 -> 'a1 -> 'a1
+
+ val min_dec : t -> t -> sumbool
+ end
+
+module N :
+ sig
+ type t = n
+
+ val zero : n
+
+ val one : n
+
+ val two : n
+
+ val succ_double : n -> n
+
+ val double : n -> n
+
+ val succ : n -> n
+
+ val pred : n -> n
+
+ val succ_pos : n -> positive
+
+ val add : n -> n -> n
+
+ val sub : n -> n -> n
+
+ val mul : n -> n -> n
+
+ val compare : n -> n -> ExtrNative.comparison
+
+ val eqb : n -> n -> bool
+
+ val leb : n -> n -> bool
+
+ val ltb : n -> n -> bool
+
+ val min : n -> n -> n
+
+ val max : n -> n -> n
+
+ val div2 : n -> n
+
+ val even : n -> bool
+
+ val odd : n -> bool
+
+ val pow : n -> n -> n
+
+ val square : n -> n
+
+ val log2 : n -> n
+
+ val size : n -> n
+
+ val size_nat : n -> nat
+
+ val pos_div_eucl : positive -> n -> n*n
+
+ val div_eucl : n -> n -> n*n
+
+ val div : n -> n -> n
+
+ val modulo : n -> n -> n
+
+ val gcd : n -> n -> n
+
+ val ggcd : n -> n -> n*(n*n)
+
+ val sqrtrem : n -> n*n
+
+ val sqrt : n -> n
+
+ val coq_lor : n -> n -> n
+
+ val coq_land : n -> n -> n
+
+ val ldiff : n -> n -> n
+
+ val coq_lxor : n -> n -> n
+
+ val shiftl_nat : n -> nat -> n
+
+ val shiftr_nat : n -> nat -> n
+
+ val shiftl : n -> n -> n
+
+ val shiftr : n -> n -> n
+
+ val testbit_nat : n -> nat -> bool
+
+ val testbit : n -> n -> bool
+
+ val to_nat : n -> nat
+
+ val of_nat : nat -> n
+
+ val iter : n -> ('a1 -> 'a1) -> 'a1 -> 'a1
+
+ val eq_dec : n -> n -> sumbool
+
+ val discr : n -> positive sumor
+
+ val binary_rect : 'a1 -> (n -> 'a1 -> 'a1) -> (n -> 'a1 -> 'a1) -> n -> 'a1
+
+ val binary_rec : 'a1 -> (n -> 'a1 -> 'a1) -> (n -> 'a1 -> 'a1) -> n -> 'a1
+
+ val peano_rect : 'a1 -> (n -> 'a1 -> 'a1) -> n -> 'a1
+
+ val peano_rec : 'a1 -> (n -> 'a1 -> 'a1) -> n -> 'a1
+
+ val leb_spec0 : n -> n -> reflect
+
+ val ltb_spec0 : n -> n -> reflect
+
+ module Private_BootStrap :
+ sig
+
+ end
+
+ val recursion : 'a1 -> (n -> 'a1 -> 'a1) -> n -> 'a1
+
+ module Private_OrderTac :
+ sig
+ module Elts :
+ sig
+ type t = n
+ end
+
+ module Tac :
+ sig
+
+ end
+ end
+
+ module Private_NZPow :
+ sig
+
+ end
+
+ module Private_NZSqrt :
+ sig
+
+ end
+
+ val sqrt_up : n -> n
+
+ val log2_up : n -> n
+
+ module Private_NZDiv :
+ sig
+
+ end
+
+ val lcm : n -> n -> n
+
+ val eqb_spec : n -> n -> reflect
+
+ val b2n : bool -> n
+
+ val setbit : n -> n -> n
+
+ val clearbit : n -> n -> n
+
+ val ones : n -> n
+
+ val lnot : n -> n -> n
+
+ module Private_Tac :
+ sig
+
+ end
+
+ module Private_Rev :
+ sig
+ module ORev :
+ sig
+ type t = n
+ end
+
+ module MRev :
+ sig
+ val max : n -> n -> n
+ end
+
+ module MPRev :
+ sig
+ module Private_Tac :
+ sig
+
+ end
+ end
+ end
+
+ module Private_Dec :
+ sig
+ val max_case_strong :
+ n -> n -> (n -> n -> __ -> 'a1 -> 'a1) -> (__ -> 'a1) -> (__ -> 'a1) ->
+ 'a1
+
+ val max_case :
+ n -> n -> (n -> n -> __ -> 'a1 -> 'a1) -> 'a1 -> 'a1 -> 'a1
+
+ val max_dec : n -> n -> sumbool
+
+ val min_case_strong :
+ n -> n -> (n -> n -> __ -> 'a1 -> 'a1) -> (__ -> 'a1) -> (__ -> 'a1) ->
+ 'a1
+
+ val min_case :
+ n -> n -> (n -> n -> __ -> 'a1 -> 'a1) -> 'a1 -> 'a1 -> 'a1
+
+ val min_dec : n -> n -> sumbool
+ end
+
+ val max_case_strong : n -> n -> (__ -> 'a1) -> (__ -> 'a1) -> 'a1
+
+ val max_case : n -> n -> 'a1 -> 'a1 -> 'a1
+
+ val max_dec : n -> n -> sumbool
+
+ val min_case_strong : n -> n -> (__ -> 'a1) -> (__ -> 'a1) -> 'a1
+
+ val min_case : n -> n -> 'a1 -> 'a1 -> 'a1
+
+ val min_dec : n -> n -> sumbool
+ end
+
+module Z :
+ sig
+ type t = z
+
+ val zero : z
+
+ val one : z
+
+ val two : z
+
+ val double : z -> z
+
+ val succ_double : z -> z
+
+ val pred_double : z -> z
+
+ val pos_sub : positive -> positive -> z
+
+ val add : z -> z -> z
+
+ val opp : z -> z
+
+ val succ : z -> z
+
+ val pred : z -> z
+
+ val sub : z -> z -> z
+
+ val mul : z -> z -> z
+
+ val pow_pos : z -> positive -> z
+
+ val pow : z -> z -> z
+
+ val square : z -> z
+
+ val compare : z -> z -> ExtrNative.comparison
+
+ val sgn : z -> z
+
+ val leb : z -> z -> bool
+
+ val ltb : z -> z -> bool
+
+ val geb : z -> z -> bool
+
+ val gtb : z -> z -> bool
+
+ val eqb : z -> z -> bool
+
+ val max : z -> z -> z
+
+ val min : z -> z -> z
+
+ val abs : z -> z
+
+ val abs_nat : z -> nat
+
+ val abs_N : z -> n
+
+ val to_nat : z -> nat
+
+ val to_N : z -> n
+
+ val of_nat : nat -> z
+
+ val of_N : n -> z
+
+ val iter : z -> ('a1 -> 'a1) -> 'a1 -> 'a1
+
+ val pos_div_eucl : positive -> z -> z*z
+
+ val div_eucl : z -> z -> z*z
+
+ val div : z -> z -> z
+
+ val modulo : z -> z -> z
+
+ val quotrem : z -> z -> z*z
+
+ val quot : z -> z -> z
+
+ val rem : z -> z -> z
+
+ val even : z -> bool
+
+ val odd : z -> bool
+
+ val div2 : z -> z
+
+ val quot2 : z -> z
+
+ val log2 : z -> z
+
+ val sqrtrem : z -> z*z
+
+ val sqrt : z -> z
+
+ val gcd : z -> z -> z
+
+ val ggcd : z -> z -> z*(z*z)
+
+ val testbit : z -> z -> bool
+
+ val shiftl : z -> z -> z
+
+ val shiftr : z -> z -> z
+
+ val coq_lor : z -> z -> z
+
+ val coq_land : z -> z -> z
+
+ val ldiff : z -> z -> z
+
+ val coq_lxor : z -> z -> z
+
+ val eq_dec : z -> z -> sumbool
+
+ module Private_BootStrap :
+ sig
+
+ end
+
+ val leb_spec0 : z -> z -> reflect
+
+ val ltb_spec0 : z -> z -> reflect
+
+ module Private_OrderTac :
+ sig
+ module Elts :
+ sig
+ type t = z
+ end
+
+ module Tac :
+ sig
+
+ end
+ end
+
+ val sqrt_up : z -> z
+
+ val log2_up : z -> z
+
+ module Private_NZDiv :
+ sig
+
+ end
+
+ module Private_Div :
+ sig
+ module Quot2Div :
+ sig
+ val div : z -> z -> z
+
+ val modulo : z -> z -> z
+ end
+
+ module NZQuot :
+ sig
+
+ end
+ end
+
+ val lcm : z -> z -> z
+
+ val eqb_spec : z -> z -> reflect
+
+ val b2z : bool -> z
+
+ val setbit : z -> z -> z
+
+ val clearbit : z -> z -> z
+
+ val lnot : z -> z
+
+ val ones : z -> z
+
+ module Private_Tac :
+ sig
+
+ end
+
+ module Private_Rev :
+ sig
+ module ORev :
+ sig
+ type t = z
+ end
+
+ module MRev :
+ sig
+ val max : z -> z -> z
+ end
+
+ module MPRev :
+ sig
+ module Private_Tac :
+ sig
+
+ end
+ end
+ end
+
+ module Private_Dec :
+ sig
+ val max_case_strong :
+ z -> z -> (z -> z -> __ -> 'a1 -> 'a1) -> (__ -> 'a1) -> (__ -> 'a1) ->
+ 'a1
+
+ val max_case :
+ z -> z -> (z -> z -> __ -> 'a1 -> 'a1) -> 'a1 -> 'a1 -> 'a1
+
+ val max_dec : z -> z -> sumbool
+
+ val min_case_strong :
+ z -> z -> (z -> z -> __ -> 'a1 -> 'a1) -> (__ -> 'a1) -> (__ -> 'a1) ->
+ 'a1
+
+ val min_case :
+ z -> z -> (z -> z -> __ -> 'a1 -> 'a1) -> 'a1 -> 'a1 -> 'a1
+
+ val min_dec : z -> z -> sumbool
+ end
+
+ val max_case_strong : z -> z -> (__ -> 'a1) -> (__ -> 'a1) -> 'a1
+
+ val max_case : z -> z -> 'a1 -> 'a1 -> 'a1
+
+ val max_dec : z -> z -> sumbool
+
+ val min_case_strong : z -> z -> (__ -> 'a1) -> (__ -> 'a1) -> 'a1
+
+ val min_case : z -> z -> 'a1 -> 'a1 -> 'a1
+
+ val min_dec : z -> z -> sumbool
+ end
+
+val zeq_bool : z -> z -> bool
+
+val nth : nat -> 'a1 list -> 'a1 -> 'a1
+
+val map : ('a1 -> 'a2) -> 'a1 list -> 'a2 list
+
+val fold_right : ('a2 -> 'a1 -> 'a1) -> 'a1 -> 'a2 list -> 'a1
+
+val existsb : ('a1 -> bool) -> 'a1 list -> bool
+
+val forallb : ('a1 -> bool) -> 'a1 list -> bool
+
+type int = ExtrNative.uint
+
+val lsl0 : int -> int -> int
+
+val lsr0 : int -> int -> int
+
+val land0 : int -> int -> int
+
+val lxor0 : int -> int -> int
+
+val sub0 : int -> int -> int
+
+val eqb0 : int -> int -> bool
+
+val ltb0 : int -> int -> bool
+
+val leb0 : int -> int -> bool
+
+val foldi_cont :
+ (int -> ('a1 -> 'a2) -> 'a1 -> 'a2) -> int -> int -> ('a1 -> 'a2) -> 'a1 ->
+ 'a2
+
+val foldi_down_cont :
+ (int -> ('a1 -> 'a2) -> 'a1 -> 'a2) -> int -> int -> ('a1 -> 'a2) -> 'a1 ->
+ 'a2
+
+val is_zero : int -> bool
+
+val is_even : int -> bool
+
+val compare0 : int -> int -> ExtrNative.comparison
+
+val foldi : (int -> 'a1 -> 'a1) -> int -> int -> 'a1 -> 'a1
+
+val fold : ('a1 -> 'a1) -> int -> int -> 'a1 -> 'a1
+
+val foldi_down : (int -> 'a1 -> 'a1) -> int -> int -> 'a1 -> 'a1
+
+val forallb0 : (int -> bool) -> int -> int -> bool
+
+val existsb0 : (int -> bool) -> int -> int -> bool
+
+val cast : int -> int -> (__ -> __ -> __) option
+
+val reflect_eqb : int -> int -> reflect
+
+type 'a array = 'a ExtrNative.parray
+
+val make : int -> 'a1 -> 'a1 array
+
+val get : 'a1 array -> int -> 'a1
+
+val default : 'a1 array -> 'a1
+
+val set : 'a1 array -> int -> 'a1 -> 'a1 array
+
+val length : 'a1 array -> int
+
+val to_list : 'a1 array -> 'a1 list
+
+val forallbi : (int -> 'a1 -> bool) -> 'a1 array -> bool
+
+val forallb1 : ('a1 -> bool) -> 'a1 array -> bool
+
+val existsb1 : ('a1 -> bool) -> 'a1 array -> bool
+
+val mapi : (int -> 'a1 -> 'a2) -> 'a1 array -> 'a2 array
+
+val foldi_left : (int -> 'a1 -> 'a2 -> 'a1) -> 'a1 -> 'a2 array -> 'a1
+
+val fold_left : ('a1 -> 'a2 -> 'a1) -> 'a1 -> 'a2 array -> 'a1
+
+val foldi_right : (int -> 'a1 -> 'a2 -> 'a2) -> 'a1 array -> 'a2 -> 'a2
+
+module Valuation :
+ sig
+ type t = int -> bool
+ end
+
+module Var :
+ sig
+ val _true : int
+
+ val _false : int
+
+ val interp : Valuation.t -> int -> bool
+ end
+
+module Lit :
+ sig
+ val is_pos : int -> bool
+
+ val blit : int -> int
+
+ val lit : int -> int
+
+ val neg : int -> int
+
+ val nlit : int -> int
+
+ val _true : int
+
+ val _false : int
+
+ val eqb : int -> int -> bool
+
+ val interp : Valuation.t -> int -> bool
+ end
+
+module C :
+ sig
+ type t = int list
+
+ val interp : Valuation.t -> t -> bool
+
+ val _true : t
+
+ val is_false : t -> bool
+
+ val or_aux : (t -> t -> t) -> int -> t -> t -> int list
+
+ val coq_or : t -> t -> t
+
+ val resolve_aux : (t -> t -> t) -> int -> t -> t -> t
+
+ val resolve : t -> t -> t
+ end
+
+module S :
+ sig
+ type t = C.t array
+
+ val get : t -> int -> C.t
+
+ val internal_set : t -> int -> C.t -> t
+
+ val make : int -> t
+
+ val insert : int -> int list -> int list
+
+ val sort_uniq : int list -> int list
+
+ val set_clause : t -> int -> C.t -> t
+
+ val set_resolve : t -> int -> int array -> t
+ end
+
+val afold_left :
+ 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a2 -> 'a1) -> 'a2 array -> 'a1
+
+val afold_right :
+ 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a2 -> 'a1) -> 'a2 array -> 'a1
+
+val rev_aux : 'a1 list -> 'a1 list -> 'a1 list
+
+val rev : 'a1 list -> 'a1 list
+
+val distinct_aux2 : ('a1 -> 'a1 -> bool) -> bool -> 'a1 -> 'a1 list -> bool
+
+val distinct_aux : ('a1 -> 'a1 -> bool) -> bool -> 'a1 list -> bool
+
+val distinct : ('a1 -> 'a1 -> bool) -> 'a1 list -> bool
+
+val forallb2 : ('a1 -> 'a2 -> bool) -> 'a1 list -> 'a2 list -> bool
+
+module Form :
+ sig
+ type form =
+ | Fatom of int
+ | Ftrue
+ | Ffalse
+ | Fnot2 of int * int
+ | Fand of int array
+ | For of int array
+ | Fimp of int array
+ | Fxor of int * int
+ | Fiff of int * int
+ | Fite of int * int * int
+
+ val form_rect :
+ (int -> 'a1) -> 'a1 -> 'a1 -> (int -> int -> 'a1) -> (int array -> 'a1)
+ -> (int array -> 'a1) -> (int array -> 'a1) -> (int -> int -> 'a1) ->
+ (int -> int -> 'a1) -> (int -> int -> int -> 'a1) -> form -> 'a1
+
+ val form_rec :
+ (int -> 'a1) -> 'a1 -> 'a1 -> (int -> int -> 'a1) -> (int array -> 'a1)
+ -> (int array -> 'a1) -> (int array -> 'a1) -> (int -> int -> 'a1) ->
+ (int -> int -> 'a1) -> (int -> int -> int -> 'a1) -> form -> 'a1
+
+ val is_Ftrue : form -> bool
+
+ val is_Ffalse : form -> bool
+
+ val interp_aux : (int -> bool) -> (int -> bool) -> form -> bool
+
+ val t_interp : (int -> bool) -> form array -> bool array
+
+ val lt_form : int -> form -> bool
+
+ val wf : form array -> bool
+
+ val interp_state_var : (int -> bool) -> form array -> int -> bool
+
+ val interp : (int -> bool) -> form array -> form -> bool
+
+ val check_form : form array -> bool
+ end
+
+type typ_eqb = { te_eqb : (__ -> __ -> bool);
+ te_reflect : (__ -> __ -> reflect) }
+
+type te_carrier = __
+
+val te_eqb : typ_eqb -> te_carrier -> te_carrier -> bool
+
+module Typ :
+ sig
+ type coq_type =
+ | Tindex of int
+ | TZ
+ | Tbool
+ | Tpositive
+
+ val type_rect : (int -> 'a1) -> 'a1 -> 'a1 -> 'a1 -> coq_type -> 'a1
+
+ val type_rec : (int -> 'a1) -> 'a1 -> 'a1 -> 'a1 -> coq_type -> 'a1
+
+ type ftype = coq_type list*coq_type
+
+ type interp = __
+
+ type interp_ftype = __
+
+ val i_eqb : typ_eqb array -> coq_type -> interp -> interp -> bool
+
+ val reflect_i_eqb :
+ typ_eqb array -> coq_type -> interp -> interp -> reflect
+
+ type cast_result =
+ | Cast of (__ -> __ -> __)
+ | NoCast
+
+ val cast_result_rect :
+ coq_type -> coq_type -> ((__ -> __ -> __) -> 'a1) -> 'a1 -> cast_result
+ -> 'a1
+
+ val cast_result_rec :
+ coq_type -> coq_type -> ((__ -> __ -> __) -> 'a1) -> 'a1 -> cast_result
+ -> 'a1
+
+ val cast : coq_type -> coq_type -> cast_result
+
+ val eqb : coq_type -> coq_type -> bool
+
+ val reflect_eqb : coq_type -> coq_type -> reflect
+ end
+
+val list_beq : ('a1 -> 'a1 -> bool) -> 'a1 list -> 'a1 list -> bool
+
+val reflect_list_beq :
+ ('a1 -> 'a1 -> bool) -> ('a1 -> 'a1 -> reflect) -> 'a1 list -> 'a1 list ->
+ reflect
+
+module Atom :
+ sig
+ type cop =
+ | CO_xH
+ | CO_Z0
+
+ val cop_rect : 'a1 -> 'a1 -> cop -> 'a1
+
+ val cop_rec : 'a1 -> 'a1 -> cop -> 'a1
+
+ type unop =
+ | UO_xO
+ | UO_xI
+ | UO_Zpos
+ | UO_Zneg
+ | UO_Zopp
+
+ val unop_rect : 'a1 -> 'a1 -> 'a1 -> 'a1 -> 'a1 -> unop -> 'a1
+
+ val unop_rec : 'a1 -> 'a1 -> 'a1 -> 'a1 -> 'a1 -> unop -> 'a1
+
+ type binop =
+ | BO_Zplus
+ | BO_Zminus
+ | BO_Zmult
+ | BO_Zlt
+ | BO_Zle
+ | BO_Zge
+ | BO_Zgt
+ | BO_eq of Typ.coq_type
+
+ val binop_rect :
+ 'a1 -> 'a1 -> 'a1 -> 'a1 -> 'a1 -> 'a1 -> 'a1 -> (Typ.coq_type -> 'a1) ->
+ binop -> 'a1
+
+ val binop_rec :
+ 'a1 -> 'a1 -> 'a1 -> 'a1 -> 'a1 -> 'a1 -> 'a1 -> (Typ.coq_type -> 'a1) ->
+ binop -> 'a1
+
+ type nop =
+ Typ.coq_type
+ (* singleton inductive, whose constructor was NO_distinct *)
+
+ val nop_rect : (Typ.coq_type -> 'a1) -> nop -> 'a1
+
+ val nop_rec : (Typ.coq_type -> 'a1) -> nop -> 'a1
+
+ type atom =
+ | Acop of cop
+ | Auop of unop * int
+ | Abop of binop * int * int
+ | Anop of nop * int list
+ | Aapp of int * int list
+
+ val atom_rect :
+ (cop -> 'a1) -> (unop -> int -> 'a1) -> (binop -> int -> int -> 'a1) ->
+ (nop -> int list -> 'a1) -> (int -> int list -> 'a1) -> atom -> 'a1
+
+ val atom_rec :
+ (cop -> 'a1) -> (unop -> int -> 'a1) -> (binop -> int -> int -> 'a1) ->
+ (nop -> int list -> 'a1) -> (int -> int list -> 'a1) -> atom -> 'a1
+
+ val cop_eqb : cop -> cop -> bool
+
+ val uop_eqb : unop -> unop -> bool
+
+ val bop_eqb : binop -> binop -> bool
+
+ val nop_eqb : nop -> nop -> bool
+
+ val eqb : atom -> atom -> bool
+
+ val reflect_cop_eqb : cop -> cop -> reflect
+
+ val reflect_uop_eqb : unop -> unop -> reflect
+
+ val reflect_bop_eqb : binop -> binop -> reflect
+
+ val reflect_nop_eqb : nop -> nop -> reflect
+
+ val reflect_eqb : atom -> atom -> reflect
+
+ type ('t, 'i) coq_val = { v_type : 't; v_val : 'i }
+
+ val val_rect : ('a1 -> 'a2 -> 'a3) -> ('a1, 'a2) coq_val -> 'a3
+
+ val val_rec : ('a1 -> 'a2 -> 'a3) -> ('a1, 'a2) coq_val -> 'a3
+
+ val v_type : ('a1, 'a2) coq_val -> 'a1
+
+ val v_val : ('a1, 'a2) coq_val -> 'a2
+
+ type bval = (Typ.coq_type, Typ.interp) coq_val
+
+ val coq_Bval :
+ typ_eqb array -> Typ.coq_type -> Typ.interp -> (Typ.coq_type, Typ.interp)
+ coq_val
+
+ type tval = (Typ.ftype, Typ.interp_ftype) coq_val
+
+ val coq_Tval :
+ typ_eqb array -> Typ.ftype -> Typ.interp_ftype -> (Typ.ftype,
+ Typ.interp_ftype) coq_val
+
+ val bvtrue : typ_eqb array -> bval
+
+ val bvfalse : typ_eqb array -> bval
+
+ val typ_cop : cop -> Typ.coq_type
+
+ val typ_uop : unop -> Typ.coq_type*Typ.coq_type
+
+ val typ_bop : binop -> (Typ.coq_type*Typ.coq_type)*Typ.coq_type
+
+ val typ_nop : nop -> Typ.coq_type*Typ.coq_type
+
+ val check_args :
+ (int -> Typ.coq_type) -> int list -> Typ.coq_type list -> bool
+
+ val check_aux :
+ typ_eqb array -> tval array -> (int -> Typ.coq_type) -> atom ->
+ Typ.coq_type -> bool
+
+ val check_args_dec :
+ (int -> Typ.coq_type) -> Typ.coq_type -> int list -> Typ.coq_type list ->
+ sumbool
+
+ val check_aux_dec :
+ typ_eqb array -> tval array -> (int -> Typ.coq_type) -> atom -> sumbool
+
+ val apply_unop :
+ typ_eqb array -> Typ.coq_type -> Typ.coq_type -> (Typ.interp ->
+ Typ.interp) -> bval -> (Typ.coq_type, Typ.interp) coq_val
+
+ val apply_binop :
+ typ_eqb array -> Typ.coq_type -> Typ.coq_type -> Typ.coq_type ->
+ (Typ.interp -> Typ.interp -> Typ.interp) -> bval -> bval ->
+ (Typ.coq_type, Typ.interp) coq_val
+
+ val apply_func :
+ typ_eqb array -> Typ.coq_type list -> Typ.coq_type -> Typ.interp_ftype ->
+ bval list -> bval
+
+ val interp_cop : typ_eqb array -> cop -> (Typ.coq_type, Typ.interp) coq_val
+
+ val interp_uop :
+ typ_eqb array -> unop -> bval -> (Typ.coq_type, Typ.interp) coq_val
+
+ val interp_bop :
+ typ_eqb array -> binop -> bval -> bval -> (Typ.coq_type, Typ.interp)
+ coq_val
+
+ val compute_interp :
+ typ_eqb array -> (int -> bval) -> Typ.coq_type -> Typ.interp list -> int
+ list -> Typ.interp list option
+
+ val interp_aux :
+ typ_eqb array -> tval array -> (int -> bval) -> atom -> bval
+
+ val interp_bool : typ_eqb array -> bval -> bool
+
+ val t_interp : typ_eqb array -> tval array -> atom array -> bval array
+
+ val lt_atom : int -> atom -> bool
+
+ val wf : atom array -> bool
+
+ val get_type' : typ_eqb array -> bval array -> int -> Typ.coq_type
+
+ val get_type :
+ typ_eqb array -> tval array -> atom array -> int -> Typ.coq_type
+
+ val wt : typ_eqb array -> tval array -> atom array -> bool
+
+ val interp_hatom : typ_eqb array -> tval array -> atom array -> int -> bval
+
+ val interp : typ_eqb array -> tval array -> atom array -> atom -> bval
+
+ val interp_form_hatom :
+ typ_eqb array -> tval array -> atom array -> int -> bool
+
+ val check_atom : atom array -> bool
+ end
+
+val or_of_imp : int array -> int array
+
+val check_True : C.t
+
+val check_False : int list
+
+val check_BuildDef : Form.form array -> int -> C.t
+
+val check_ImmBuildDef : Form.form array -> S.t -> int -> C.t
+
+val check_BuildDef2 : Form.form array -> int -> C.t
+
+val check_ImmBuildDef2 : Form.form array -> S.t -> int -> C.t
+
+val check_BuildProj : Form.form array -> int -> int -> C.t
+
+val check_ImmBuildProj : Form.form array -> S.t -> int -> int -> C.t
+
+val get_eq :
+ Form.form array -> Atom.atom array -> int -> (int -> int -> C.t) -> C.t
+
+val check_trans_aux :
+ Form.form array -> Atom.atom array -> int -> int -> int list -> int -> C.t
+ -> C.t
+
+val check_trans :
+ Form.form array -> Atom.atom array -> int -> int list -> C.t
+
+val build_congr :
+ Form.form array -> Atom.atom array -> int option list -> int list -> int
+ list -> C.t -> C.t
+
+val check_congr :
+ Form.form array -> Atom.atom array -> int -> int option list -> C.t
+
+val check_congr_pred :
+ Form.form array -> Atom.atom array -> int -> int -> int option list -> C.t
+
+type 'c pol =
+| Pc of 'c
+| Pinj of positive * 'c pol
+| PX of 'c pol * positive * 'c pol
+
+val p0 : 'a1 -> 'a1 pol
+
+val p1 : 'a1 -> 'a1 pol
+
+val peq : ('a1 -> 'a1 -> bool) -> 'a1 pol -> 'a1 pol -> bool
+
+val mkPinj : positive -> 'a1 pol -> 'a1 pol
+
+val mkPinj_pred : positive -> 'a1 pol -> 'a1 pol
+
+val mkPX :
+ 'a1 -> ('a1 -> 'a1 -> bool) -> 'a1 pol -> positive -> 'a1 pol -> 'a1 pol
+
+val mkXi : 'a1 -> 'a1 -> positive -> 'a1 pol
+
+val mkX : 'a1 -> 'a1 -> 'a1 pol
+
+val popp : ('a1 -> 'a1) -> 'a1 pol -> 'a1 pol
+
+val paddC : ('a1 -> 'a1 -> 'a1) -> 'a1 pol -> 'a1 -> 'a1 pol
+
+val psubC : ('a1 -> 'a1 -> 'a1) -> 'a1 pol -> 'a1 -> 'a1 pol
+
+val paddI :
+ ('a1 -> 'a1 -> 'a1) -> ('a1 pol -> 'a1 pol -> 'a1 pol) -> 'a1 pol ->
+ positive -> 'a1 pol -> 'a1 pol
+
+val psubI :
+ ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1) -> ('a1 pol -> 'a1 pol -> 'a1 pol) ->
+ 'a1 pol -> positive -> 'a1 pol -> 'a1 pol
+
+val paddX :
+ 'a1 -> ('a1 -> 'a1 -> bool) -> ('a1 pol -> 'a1 pol -> 'a1 pol) -> 'a1 pol
+ -> positive -> 'a1 pol -> 'a1 pol
+
+val psubX :
+ 'a1 -> ('a1 -> 'a1) -> ('a1 -> 'a1 -> bool) -> ('a1 pol -> 'a1 pol -> 'a1
+ pol) -> 'a1 pol -> positive -> 'a1 pol -> 'a1 pol
+
+val padd :
+ 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> bool) -> 'a1 pol -> 'a1 pol ->
+ 'a1 pol
+
+val psub :
+ 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1) -> ('a1
+ -> 'a1 -> bool) -> 'a1 pol -> 'a1 pol -> 'a1 pol
+
+val pmulC_aux :
+ 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> bool) -> 'a1 pol -> 'a1 -> 'a1
+ pol
+
+val pmulC :
+ 'a1 -> 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> bool) -> 'a1 pol -> 'a1
+ -> 'a1 pol
+
+val pmulI :
+ 'a1 -> 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> bool) -> ('a1 pol ->
+ 'a1 pol -> 'a1 pol) -> 'a1 pol -> positive -> 'a1 pol -> 'a1 pol
+
+val pmul :
+ 'a1 -> 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 ->
+ bool) -> 'a1 pol -> 'a1 pol -> 'a1 pol
+
+val psquare :
+ 'a1 -> 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 ->
+ bool) -> 'a1 pol -> 'a1 pol
+
+type 'c pExpr =
+| PEc of 'c
+| PEX of positive
+| PEadd of 'c pExpr * 'c pExpr
+| PEsub of 'c pExpr * 'c pExpr
+| PEmul of 'c pExpr * 'c pExpr
+| PEopp of 'c pExpr
+| PEpow of 'c pExpr * n
+
+val mk_X : 'a1 -> 'a1 -> positive -> 'a1 pol
+
+val ppow_pos :
+ 'a1 -> 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 ->
+ bool) -> ('a1 pol -> 'a1 pol) -> 'a1 pol -> 'a1 pol -> positive -> 'a1 pol
+
+val ppow_N :
+ 'a1 -> 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 ->
+ bool) -> ('a1 pol -> 'a1 pol) -> 'a1 pol -> n -> 'a1 pol
+
+val norm_aux :
+ 'a1 -> 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 ->
+ 'a1) -> ('a1 -> 'a1) -> ('a1 -> 'a1 -> bool) -> 'a1 pExpr -> 'a1 pol
+
+type 'a bFormula =
+| TT
+| FF
+| X
+| A of 'a
+| Cj of 'a bFormula * 'a bFormula
+| D of 'a bFormula * 'a bFormula
+| N of 'a bFormula
+| I of 'a bFormula * 'a bFormula
+
+type 'term' clause = 'term' list
+
+type 'term' cnf = 'term' clause list
+
+val tt : 'a1 cnf
+
+val ff : 'a1 cnf
+
+val add_term :
+ ('a1 -> bool) -> ('a1 -> 'a1 -> 'a1 option) -> 'a1 -> 'a1 clause -> 'a1
+ clause option
+
+val or_clause :
+ ('a1 -> bool) -> ('a1 -> 'a1 -> 'a1 option) -> 'a1 clause -> 'a1 clause ->
+ 'a1 clause option
+
+val or_clause_cnf :
+ ('a1 -> bool) -> ('a1 -> 'a1 -> 'a1 option) -> 'a1 clause -> 'a1 cnf -> 'a1
+ cnf
+
+val or_cnf :
+ ('a1 -> bool) -> ('a1 -> 'a1 -> 'a1 option) -> 'a1 cnf -> 'a1 cnf -> 'a1
+ cnf
+
+val and_cnf : 'a1 cnf -> 'a1 cnf -> 'a1 cnf
+
+val xcnf :
+ ('a2 -> bool) -> ('a2 -> 'a2 -> 'a2 option) -> ('a1 -> 'a2 cnf) -> ('a1 ->
+ 'a2 cnf) -> bool -> 'a1 bFormula -> 'a2 cnf
+
+val cnf_checker : ('a1 list -> 'a2 -> bool) -> 'a1 cnf -> 'a2 list -> bool
+
+val tauto_checker :
+ ('a2 -> bool) -> ('a2 -> 'a2 -> 'a2 option) -> ('a1 -> 'a2 cnf) -> ('a1 ->
+ 'a2 cnf) -> ('a2 list -> 'a3 -> bool) -> 'a1 bFormula -> 'a3 list -> bool
+
+val cneqb : ('a1 -> 'a1 -> bool) -> 'a1 -> 'a1 -> bool
+
+val cltb : ('a1 -> 'a1 -> bool) -> ('a1 -> 'a1 -> bool) -> 'a1 -> 'a1 -> bool
+
+type 'c polC = 'c pol
+
+type op1 =
+| Equal
+| NonEqual
+| Strict
+| NonStrict
+
+type 'c nFormula = 'c polC*op1
+
+val opMult : op1 -> op1 -> op1 option
+
+val opAdd : op1 -> op1 -> op1 option
+
+type 'c psatz =
+| PsatzIn of nat
+| PsatzSquare of 'c polC
+| PsatzMulC of 'c polC * 'c psatz
+| PsatzMulE of 'c psatz * 'c psatz
+| PsatzAdd of 'c psatz * 'c psatz
+| PsatzC of 'c
+| PsatzZ
+
+val map_option : ('a1 -> 'a2 option) -> 'a1 option -> 'a2 option
+
+val map_option2 :
+ ('a1 -> 'a2 -> 'a3 option) -> 'a1 option -> 'a2 option -> 'a3 option
+
+val pexpr_times_nformula :
+ 'a1 -> 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 ->
+ bool) -> 'a1 polC -> 'a1 nFormula -> 'a1 nFormula option
+
+val nformula_times_nformula :
+ 'a1 -> 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 ->
+ bool) -> 'a1 nFormula -> 'a1 nFormula -> 'a1 nFormula option
+
+val nformula_plus_nformula :
+ 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> bool) -> 'a1 nFormula -> 'a1
+ nFormula -> 'a1 nFormula option
+
+val eval_Psatz :
+ 'a1 -> 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 ->
+ bool) -> ('a1 -> 'a1 -> bool) -> 'a1 nFormula list -> 'a1 psatz -> 'a1
+ nFormula option
+
+val check_inconsistent :
+ 'a1 -> ('a1 -> 'a1 -> bool) -> ('a1 -> 'a1 -> bool) -> 'a1 nFormula -> bool
+
+type op2 =
+| OpEq
+| OpNEq
+| OpLe
+| OpGe
+| OpLt
+| OpGt
+
+type 't formula = { flhs : 't pExpr; fop : op2; frhs : 't pExpr }
+
+val norm :
+ 'a1 -> 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 ->
+ 'a1) -> ('a1 -> 'a1) -> ('a1 -> 'a1 -> bool) -> 'a1 pExpr -> 'a1 pol
+
+val psub0 :
+ 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1) -> ('a1
+ -> 'a1 -> bool) -> 'a1 pol -> 'a1 pol -> 'a1 pol
+
+val padd0 :
+ 'a1 -> ('a1 -> 'a1 -> 'a1) -> ('a1 -> 'a1 -> bool) -> 'a1 pol -> 'a1 pol ->
+ 'a1 pol
+
+type zWitness = z psatz
+
+val psub1 : z pol -> z pol -> z pol
+
+val padd1 : z pol -> z pol -> z pol
+
+val norm0 : z pExpr -> z pol
+
+val xnormalise : z formula -> z nFormula list
+
+val normalise : z formula -> z nFormula cnf
+
+val xnegate : z formula -> z nFormula list
+
+val negate : z formula -> z nFormula cnf
+
+val zunsat : z nFormula -> bool
+
+val zdeduce : z nFormula -> z nFormula -> z nFormula option
+
+val ceiling : z -> z -> z
+
+type zArithProof =
+| DoneProof
+| RatProof of zWitness * zArithProof
+| CutProof of zWitness * zArithProof
+| EnumProof of zWitness * zWitness * zArithProof list
+
+val zgcdM : z -> z -> z
+
+val zgcd_pol : z polC -> z*z
+
+val zdiv_pol : z polC -> z -> z polC
+
+val makeCuttingPlane : z polC -> z polC*z
+
+val genCuttingPlane : z nFormula -> ((z polC*z)*op1) option
+
+val nformula_of_cutting_plane : ((z polC*z)*op1) -> z nFormula
+
+val is_pol_Z0 : z polC -> bool
+
+val eval_Psatz0 : z nFormula list -> zWitness -> z nFormula option
+
+val valid_cut_sign : op1 -> bool
+
+val zChecker : z nFormula list -> zArithProof -> bool
+
+val zTautoChecker : z formula bFormula -> zArithProof list -> bool
+
+val build_positive_atom_aux :
+ (int -> positive option) -> Atom.atom -> positive option
+
+val build_positive : Atom.atom array -> int -> positive option
+
+val build_z_atom_aux : Atom.atom array -> Atom.atom -> z option
+
+val build_z_atom : Atom.atom array -> Atom.atom -> z option
+
+type vmap = positive*Atom.atom list
+
+val find_var_aux : Atom.atom -> positive -> Atom.atom list -> positive option
+
+val find_var : vmap -> Atom.atom -> vmap*positive
+
+val empty_vmap : vmap
+
+val build_pexpr_atom_aux :
+ Atom.atom array -> (vmap -> int -> vmap*z pExpr) -> vmap -> Atom.atom ->
+ vmap*z pExpr
+
+val build_pexpr : Atom.atom array -> vmap -> int -> vmap*z pExpr
+
+val build_op2 : Atom.binop -> op2 option
+
+val build_formula_atom :
+ Atom.atom array -> vmap -> Atom.atom -> (vmap*z formula) option
+
+val build_formula : Atom.atom array -> vmap -> int -> (vmap*z formula) option
+
+val build_not2 : int -> z formula bFormula -> z formula bFormula
+
+val build_hform :
+ Atom.atom array -> (vmap -> int -> (vmap*z formula bFormula) option) ->
+ vmap -> Form.form -> (vmap*z formula bFormula) option
+
+val build_var :
+ Form.form array -> Atom.atom array -> vmap -> int -> (vmap*z formula
+ bFormula) option
+
+val build_form :
+ Form.form array -> Atom.atom array -> vmap -> Form.form -> (vmap*z formula
+ bFormula) option
+
+val build_nlit :
+ Form.form array -> Atom.atom array -> vmap -> int -> (vmap*z formula
+ bFormula) option
+
+val build_clause_aux :
+ Form.form array -> Atom.atom array -> vmap -> int list -> (vmap*z formula
+ bFormula) option
+
+val build_clause :
+ Form.form array -> Atom.atom array -> vmap -> int list -> (vmap*z formula
+ bFormula) option
+
+val get_eq0 :
+ Form.form array -> Atom.atom array -> int -> (int -> int -> C.t) -> C.t
+
+val get_not_le :
+ Form.form array -> Atom.atom array -> int -> (int -> int -> C.t) -> C.t
+
+val check_micromega :
+ Form.form array -> Atom.atom array -> int list -> zArithProof list -> C.t
+
+val check_diseq : Form.form array -> Atom.atom array -> int -> C.t
+
+val check_atom_aux :
+ Atom.atom array -> (int -> int -> bool) -> Atom.atom -> Atom.atom -> bool
+
+val check_hatom : Atom.atom array -> int -> int -> bool
+
+val check_neg_hatom : Atom.atom array -> int -> int -> bool
+
+val remove_not : Form.form array -> int -> int
+
+val get_and : Form.form array -> int -> int array option
+
+val get_or : Form.form array -> int -> int array option
+
+val flatten_op_body :
+ (int -> int array option) -> (int list -> int -> int list) -> int list ->
+ int -> int list
+
+val flatten_op_lit :
+ (int -> int array option) -> int -> int list -> int -> int list
+
+val flatten_and : Form.form array -> int array -> int list
+
+val flatten_or : Form.form array -> int array -> int list
+
+val check_flatten_body :
+ Form.form array -> (int -> int -> bool) -> (int -> int -> bool) -> (int ->
+ int -> bool) -> int -> int -> bool
+
+val check_flatten_aux :
+ Form.form array -> (int -> int -> bool) -> (int -> int -> bool) -> int ->
+ int -> bool
+
+val check_flatten :
+ Form.form array -> (int -> int -> bool) -> (int -> int -> bool) -> S.t ->
+ int -> int -> C.t
+
+val check_spl_arith :
+ Form.form array -> Atom.atom array -> int list -> int -> zArithProof list
+ -> C.t
+
+val check_in : int -> int list -> bool
+
+val check_diseqs_complete_aux :
+ int -> int list -> (int*int) option array -> bool
+
+val check_diseqs_complete : int list -> (int*int) option array -> bool
+
+val check_diseqs :
+ Form.form array -> Atom.atom array -> Typ.coq_type -> int list -> int array
+ -> bool
+
+val check_distinct :
+ Form.form array -> Atom.atom array -> int -> int array -> bool
+
+val check_distinct_two_args :
+ Form.form array -> Atom.atom array -> int -> int -> bool
+
+val check_lit :
+ Form.form array -> Atom.atom array -> (int -> int -> bool) -> int -> int ->
+ bool
+
+val check_form_aux :
+ Form.form array -> Atom.atom array -> (int -> int -> bool) -> Form.form ->
+ Form.form -> bool
+
+val check_hform : Form.form array -> Atom.atom array -> int -> int -> bool
+
+val check_lit' : Form.form array -> Atom.atom array -> int -> int -> bool
+
+val check_distinct_elim :
+ Form.form array -> Atom.atom array -> int list -> int -> int list
+
+type 'step _trace_ = 'step array array
+
+val _checker_ :
+ (S.t -> 'a1 -> S.t) -> (C.t -> bool) -> S.t -> 'a1 _trace_ -> int -> bool
+
+module Euf_Checker :
+ sig
+ type step =
+ | Res of int * int array
+ | ImmFlatten of int * int * int
+ | CTrue of int
+ | CFalse of int
+ | BuildDef of int * int
+ | BuildDef2 of int * int
+ | BuildProj of int * int * int
+ | ImmBuildDef of int * int
+ | ImmBuildDef2 of int * int
+ | ImmBuildProj of int * int * int
+ | EqTr of int * int * int list
+ | EqCgr of int * int * int option list
+ | EqCgrP of int * int * int * int option list
+ | LiaMicromega of int * int list * zArithProof list
+ | LiaDiseq of int * int
+ | SplArith of int * int * int * zArithProof list
+ | SplDistinctElim of int * int * int
+
+ val step_rect :
+ (int -> int array -> 'a1) -> (int -> int -> int -> 'a1) -> (int -> 'a1)
+ -> (int -> 'a1) -> (int -> int -> 'a1) -> (int -> int -> 'a1) -> (int ->
+ int -> int -> 'a1) -> (int -> int -> 'a1) -> (int -> int -> 'a1) -> (int
+ -> int -> int -> 'a1) -> (int -> int -> int list -> 'a1) -> (int -> int
+ -> int option list -> 'a1) -> (int -> int -> int -> int option list ->
+ 'a1) -> (int -> int list -> zArithProof list -> 'a1) -> (int -> int ->
+ 'a1) -> (int -> int -> int -> zArithProof list -> 'a1) -> (int -> int ->
+ int -> 'a1) -> step -> 'a1
+
+ val step_rec :
+ (int -> int array -> 'a1) -> (int -> int -> int -> 'a1) -> (int -> 'a1)
+ -> (int -> 'a1) -> (int -> int -> 'a1) -> (int -> int -> 'a1) -> (int ->
+ int -> int -> 'a1) -> (int -> int -> 'a1) -> (int -> int -> 'a1) -> (int
+ -> int -> int -> 'a1) -> (int -> int -> int list -> 'a1) -> (int -> int
+ -> int option list -> 'a1) -> (int -> int -> int -> int option list ->
+ 'a1) -> (int -> int list -> zArithProof list -> 'a1) -> (int -> int ->
+ 'a1) -> (int -> int -> int -> zArithProof list -> 'a1) -> (int -> int ->
+ int -> 'a1) -> step -> 'a1
+
+ val step_checker : Atom.atom array -> Form.form array -> S.t -> step -> S.t
+
+ val euf_checker :
+ Atom.atom array -> Form.form array -> (C.t -> bool) -> S.t -> step
+ _trace_ -> int -> bool
+
+ type certif =
+ | Certif of int * step _trace_ * int
+
+ val certif_rect : (int -> step _trace_ -> int -> 'a1) -> certif -> 'a1
+
+ val certif_rec : (int -> step _trace_ -> int -> 'a1) -> certif -> 'a1
+
+ val add_roots : S.t -> int array -> int array option -> S.t
+
+ val valid :
+ typ_eqb array -> Atom.tval array -> Atom.atom array -> Form.form array ->
+ int array -> bool
+
+ val checker :
+ typ_eqb array -> Atom.tval array -> Atom.atom array -> Form.form array ->
+ int array -> int array option -> certif -> bool
+
+ val checker_b :
+ typ_eqb array -> Atom.tval array -> Atom.atom array -> Form.form array ->
+ int -> bool -> certif -> bool
+
+ val checker_eq :
+ typ_eqb array -> Atom.tval array -> Atom.atom array -> Form.form array ->
+ int -> int -> int -> certif -> bool
+
+ val checker_ext :
+ Atom.atom array -> Form.form array -> int array -> int array option ->
+ certif -> bool
+ end
+
diff --git a/src/extraction/test.ml b/src/extraction/test.ml
new file mode 100644
index 0000000..0b16b7f
--- /dev/null
+++ b/src/extraction/test.ml
@@ -0,0 +1,42 @@
+let _ = Printf.printf "Zchaff_checker.checker \"tests/sat1.cnf\" \"tests/sat1.zlog\" = %b\n" (Zchaff_checker.checker "tests/sat1.cnf" "tests/sat1.zlog")
+let _ = Printf.printf "Zchaff_checker.checker \"tests/sat2.cnf\" \"tests/sat2.zlog\" = %b\n" (Zchaff_checker.checker "tests/sat2.cnf" "tests/sat2.zlog")
+let _ = Printf.printf "Zchaff_checker.checker \"tests/sat3.cnf\" \"tests/sat3.zlog\" = %b\n" (Zchaff_checker.checker "tests/sat3.cnf" "tests/sat3.zlog")
+let _ = Printf.printf "Zchaff_checker.checker \"tests/sat5.cnf\" \"tests/sat5.zlog\" = %b\n" (Zchaff_checker.checker "tests/sat5.cnf" "tests/sat5.zlog")
+let _ = Printf.printf "Zchaff_checker.checker \"tests/sat6.cnf\" \"tests/sat6.zlog\" = %b\n" (Zchaff_checker.checker "tests/sat6.cnf" "tests/sat6.zlog")
+let _ = Printf.printf "Zchaff_checker.checker \"tests/sat7.cnf\" \"tests/sat7.zlog\" = %b\n" (Zchaff_checker.checker "tests/sat7.cnf" "tests/sat7.zlog")
+let _ = Printf.printf "Zchaff_checker.checker \"tests/hole4.cnf\" \"tests/hole4.zlog\" = %b\n" (Zchaff_checker.checker "tests/hole4.cnf" "tests/hole4.zlog")
+let _ = Printf.printf "Zchaff_checker.checker \"tests/cmu-bmc-barrel6.cnf\" \"tests/cmu-bmc-barrel6.zlog\" = %b\n" (Zchaff_checker.checker "tests/cmu-bmc-barrel6.cnf" "tests/cmu-bmc-barrel6.zlog")
+let _ = Printf.printf "Zchaff_checker.checker \"tests/velev-sss-1.0-05.cnf\" \"tests/velev-sss-1.0-05.zlog\" = %b\n" (Zchaff_checker.checker "tests/velev-sss-1.0-05.cnf" "tests/velev-sss-1.0-05.zlog")
+
+
+
+
+let _ = Printf.printf "Verit_checker.checker \"tests/sat1.smt2\" \"tests/sat1.vtlog\" = %b\n" (Verit_checker.checker "tests/sat1.smt2" "tests/sat1.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/sat2.smt2\" \"tests/sat2.vtlog\" = %b\n" (Verit_checker.checker "tests/sat2.smt2" "tests/sat2.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/sat3.smt2\" \"tests/sat3.vtlog\" = %b\n" (Verit_checker.checker "tests/sat3.smt2" "tests/sat3.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/sat4.smt2\" \"tests/sat4.vtlog\" = %b\n" (Verit_checker.checker "tests/sat4.smt2" "tests/sat4.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/sat5.smt2\" \"tests/sat5.vtlog\" = %b\n" (Verit_checker.checker "tests/sat5.smt2" "tests/sat5.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/sat6.smt2\" \"tests/sat6.vtlog\" = %b\n" (Verit_checker.checker "tests/sat6.smt2" "tests/sat6.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/sat7.smt2\" \"tests/sat7.vtlog\" = %b\n" (Verit_checker.checker "tests/sat7.smt2" "tests/sat7.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/sat8.smt2\" \"tests/sat8.vtlog\" = %b\n" (Verit_checker.checker "tests/sat8.smt2" "tests/sat8.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/sat9.smt2\" \"tests/sat9.vtlog\" = %b\n" (Verit_checker.checker "tests/sat9.smt2" "tests/sat9.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/sat11.smt2\" \"tests/sat11.vtlog\" = %b\n" (Verit_checker.checker "tests/sat11.smt2" "tests/sat11.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/sat12.smt2\" \"tests/sat12.vtlog\" = %b\n" (Verit_checker.checker "tests/sat12.smt2" "tests/sat12.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/sat13.smt2\" \"tests/sat13.vtlog\" = %b\n" (Verit_checker.checker "tests/sat13.smt2" "tests/sat13.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/hole4.smt2\" \"tests/hole4.vtlog\" = %b\n" (Verit_checker.checker "tests/hole4.smt2" "tests/hole4.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/uf1.smt2\" \"tests/uf1.vtlog\" = %b\n" (Verit_checker.checker "tests/uf1.smt2" "tests/uf1.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/uf2.smt2\" \"tests/uf2.vtlog\" = %b\n" (Verit_checker.checker "tests/uf2.smt2" "tests/uf2.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/uf3.smt2\" \"tests/uf3.vtlog\" = %b\n" (Verit_checker.checker "tests/uf3.smt2" "tests/uf3.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/uf4.smt2\" \"tests/uf4.vtlog\" = %b\n" (Verit_checker.checker "tests/uf4.smt2" "tests/uf4.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/uf5.smt2\" \"tests/uf5.vtlog\" = %b\n" (Verit_checker.checker "tests/uf5.smt2" "tests/uf5.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/uf6.smt2\" \"tests/uf6.vtlog\" = %b\n" (Verit_checker.checker "tests/uf6.smt2" "tests/uf6.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/uf7.smt2\" \"tests/uf7.vtlog\" = %b\n" (Verit_checker.checker "tests/uf7.smt2" "tests/uf7.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/lia1.smt2\" \"tests/lia1.vtlog\" = %b\n" (Verit_checker.checker "tests/lia1.smt2" "tests/lia1.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/lia2.smt2\" \"tests/lia2.vtlog\" = %b\n" (Verit_checker.checker "tests/lia2.smt2" "tests/lia2.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/lia3.smt2\" \"tests/lia3.vtlog\" = %b\n" (Verit_checker.checker "tests/lia3.smt2" "tests/lia3.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/lia4.smt2\" \"tests/lia4.vtlog\" = %b\n" (Verit_checker.checker "tests/lia4.smt2" "tests/lia4.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/lia5.smt2\" \"tests/lia5.vtlog\" = %b\n" (Verit_checker.checker "tests/lia5.smt2" "tests/lia5.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/lia6.smt2\" \"tests/lia6.vtlog\" = %b\n" (Verit_checker.checker "tests/lia6.smt2" "tests/lia6.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/lia7.smt2\" \"tests/lia7.vtlog\" = %b\n" (Verit_checker.checker "tests/lia7.smt2" "tests/lia7.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/let1.smt2\" \"tests/let1.vtlog\" = %b\n" (Verit_checker.checker "tests/let1.smt2" "tests/let1.vtlog")
+let _ = Printf.printf "Verit_checker.checker \"tests/let2.smt2\" \"tests/let2.vtlog\" = %b\n" (Verit_checker.checker "tests/let2.smt2" "tests/let2.vtlog")
diff --git a/src/extraction/verit_checker.ml b/src/extraction/verit_checker.ml
new file mode 100644
index 0000000..e317dcf
--- /dev/null
+++ b/src/extraction/verit_checker.ml
@@ -0,0 +1,324 @@
+open SmtMisc
+open SmtCertif
+open SmtForm
+open SmtAtom
+open SmtTrace
+open Verit
+open Smtlib2_ast
+open Smtlib2_genConstr
+(* open Smt_checker *)
+
+
+module Mc = Micromega
+
+
+let mkInt = ExtrNative.of_int
+let mkArray = ExtrNative.of_array
+
+
+let rec dump_nat x =
+ match x with
+ | Mc.O -> Smt_checker.O
+ | Mc.S p -> Smt_checker.S (dump_nat p)
+
+
+let rec dump_positive x =
+ match x with
+ | Mc.XH -> Smt_checker.XH
+ | Mc.XO p -> Smt_checker.XO (dump_positive p)
+ | Mc.XI p -> Smt_checker.XI (dump_positive p)
+
+
+let dump_z x =
+ match x with
+ | Mc.Z0 -> Smt_checker.Z0
+ | Mc.Zpos p -> Smt_checker.Zpos (dump_positive p)
+ | Mc.Zneg p -> Smt_checker.Zneg (dump_positive p)
+
+
+let dump_pol e =
+ let rec dump_pol e =
+ match e with
+ | Mc.Pc n -> Smt_checker.Pc (dump_z n)
+ | Mc.Pinj(p,pol) -> Smt_checker.Pinj (dump_positive p, dump_pol pol)
+ | Mc.PX(pol1,p,pol2) -> Smt_checker.PX (dump_pol pol1, dump_positive p, dump_pol pol2) in
+ dump_pol e
+
+
+let dump_psatz e =
+ let rec dump_cone e =
+ match e with
+ | Mc.PsatzIn n -> Smt_checker.PsatzIn (dump_nat n)
+ | Mc.PsatzMulC(e,c) -> Smt_checker.PsatzMulC (dump_pol e, dump_cone c)
+ | Mc.PsatzSquare e -> Smt_checker.PsatzSquare (dump_pol e)
+ | Mc.PsatzAdd(e1,e2) -> Smt_checker.PsatzAdd (dump_cone e1, dump_cone e2)
+ | Mc.PsatzMulE(e1,e2) -> Smt_checker.PsatzMulE (dump_cone e1, dump_cone e2)
+ | Mc.PsatzC p -> Smt_checker.PsatzC (dump_z p)
+ | Mc.PsatzZ -> Smt_checker.PsatzZ in
+ dump_cone e
+
+
+let rec dump_list dump_elt l =
+ match l with
+ | [] -> Smt_checker.Nil
+ | e :: l -> Smt_checker.Cons (dump_elt e, dump_list dump_elt l)
+
+
+let rec dump_proof_term = function
+ | Micromega.DoneProof -> Smt_checker.DoneProof
+ | Micromega.RatProof(cone,rst) ->
+ Smt_checker.RatProof (dump_psatz cone, dump_proof_term rst)
+ | Micromega.CutProof(cone,prf) ->
+ Smt_checker.CutProof (dump_psatz cone, dump_proof_term prf)
+ | Micromega.EnumProof(c1,c2,prfs) ->
+ Smt_checker.EnumProof (dump_psatz c1, dump_psatz c2, dump_list dump_proof_term prfs)
+
+
+
+let to_coq to_lit confl =
+ let out_f f = to_lit f in
+ let out_c c = mkInt (get_pos c) in
+ let step_to_coq c =
+ match c.kind with
+ | Res res ->
+ let size = List.length res.rtail + 3 in
+ let args = Array.make size (mkInt 0) in
+ args.(0) <- mkInt (get_pos res.rc1);
+ args.(1) <- mkInt (get_pos res.rc2);
+ let l = ref res.rtail in
+ for i = 2 to size - 2 do
+ match !l with
+ | c::tl ->
+ args.(i) <- mkInt (get_pos c);
+ l := tl
+ | _ -> assert false
+ done;
+ Smt_checker.Euf_Checker.Res (mkInt (get_pos c), mkArray args)
+ | Other other ->
+ begin match other with
+ | ImmFlatten (c',f) -> Smt_checker.Euf_Checker.ImmFlatten (out_c c, out_c c', out_f f)
+ | True -> Smt_checker.Euf_Checker.CTrue (out_c c)
+ | False -> Smt_checker.Euf_Checker.CFalse (out_c c)
+ | BuildDef f -> Smt_checker.Euf_Checker.BuildDef (out_c c, out_f f)
+ | BuildDef2 f -> Smt_checker.Euf_Checker.BuildDef2 (out_c c, out_f f)
+ | BuildProj (f, i) -> Smt_checker.Euf_Checker.BuildProj (out_c c, out_f f, mkInt i)
+ | ImmBuildDef c' -> Smt_checker.Euf_Checker.ImmBuildDef (out_c c, out_c c')
+ | ImmBuildDef2 c' -> Smt_checker.Euf_Checker.ImmBuildDef2 (out_c c, out_c c')
+ | ImmBuildProj(c', i) -> Smt_checker.Euf_Checker.ImmBuildProj (out_c c, out_c c',mkInt i)
+ | EqTr (f, fl) ->
+ let res = List.fold_right (fun f l -> Smt_checker.Cons (out_f f, l)) fl Smt_checker.Nil in
+ Smt_checker.Euf_Checker.EqTr (out_c c, out_f f, res)
+ | EqCgr (f, fl) ->
+ let res = List.fold_right (fun f l -> Smt_checker.Cons ((match f with | Some f -> Smt_checker.Some (out_f f) | None -> Smt_checker.None), l)) fl Smt_checker.Nil in
+ Smt_checker.Euf_Checker.EqCgr (out_c c, out_f f, res)
+ | EqCgrP (f1, f2, fl) ->
+ let res = List.fold_right (fun f l -> Smt_checker.Cons ((match f with | Some f -> Smt_checker.Some (out_f f) | None -> Smt_checker.None), l)) fl Smt_checker.Nil in
+ Smt_checker.Euf_Checker.EqCgrP (out_c c, out_f f1, out_f f2, res)
+ | LiaMicromega (cl,d) ->
+ let cl' = List.fold_right (fun f l -> Smt_checker.Cons (out_f f, l)) cl Smt_checker.Nil in
+ let c' = List.fold_right (fun f l -> Smt_checker.Cons (dump_proof_term f, l)) d Smt_checker.Nil in
+ Smt_checker.Euf_Checker.LiaMicromega (out_c c, cl', c')
+ | LiaDiseq l -> Smt_checker.Euf_Checker.LiaDiseq (out_c c, out_f l)
+ | SplArith (orig,res,l) ->
+ let res' = out_f res in
+ let l' = List.fold_right (fun f l -> Smt_checker.Cons (dump_proof_term f, l)) l Smt_checker.Nil in
+ Smt_checker.Euf_Checker.SplArith (out_c c, out_c orig, res', l')
+ | SplDistinctElim (c',f) -> Smt_checker.Euf_Checker.SplDistinctElim (out_c c, out_c c', out_f f)
+ end
+ | _ -> assert false in
+ let def_step =
+ Smt_checker.Euf_Checker.Res (mkInt 0, mkArray [|mkInt 0|]) in
+ let r = ref confl in
+ let nc = ref 0 in
+ while not (isRoot !r.kind) do r := prev !r; incr nc done;
+ let last_root = !r in
+ let size = !nc in
+ let max = (Parray.trunc_size (Uint63.of_int 4194303)) - 1 in
+ let q,r1 = size / max, size mod max in
+
+ let trace =
+ let len = if r1 = 0 then q + 1 else q + 2 in
+ Array.make len (mkArray [|def_step|]) in
+ for j = 0 to q - 1 do
+ let tracej = Array.make (Parray.trunc_size (Uint63.of_int 4194303)) def_step in
+ for i = 0 to max - 1 do
+ r := next !r;
+ tracej.(i) <- step_to_coq !r;
+ done;
+ trace.(j) <- mkArray tracej
+ done;
+ if r1 <> 0 then begin
+ let traceq = Array.make (r1 + 1) def_step in
+ for i = 0 to r1-1 do
+ r := next !r;
+ traceq.(i) <- step_to_coq !r;
+ done;
+ trace.(q) <- mkArray traceq
+ end;
+
+ (mkArray trace, last_root)
+
+
+let btype_to_coq = function
+ | TZ -> Smt_checker.Typ.TZ
+ | Tbool -> Smt_checker.Typ.Tbool
+ | Tpositive -> Smt_checker.Typ.Tpositive
+ | Tindex i -> Smt_checker.Typ.Tindex (mkInt (SmtAtom.indexed_type_index i))
+
+
+let c_to_coq = function
+ | CO_xH -> Smt_checker.Atom.CO_xH
+ | CO_Z0 -> Smt_checker.Atom.CO_Z0
+
+
+let u_to_coq = function
+ | UO_xO -> Smt_checker.Atom.UO_xO
+ | UO_xI -> Smt_checker.Atom.UO_xI
+ | UO_Zpos -> Smt_checker.Atom.UO_Zpos
+ | UO_Zneg -> Smt_checker.Atom.UO_Zneg
+ | UO_Zopp -> Smt_checker.Atom.UO_Zopp
+
+
+let b_to_coq = function
+ | BO_Zplus -> Smt_checker.Atom.BO_Zplus
+ | BO_Zminus -> Smt_checker.Atom.BO_Zminus
+ | BO_Zmult -> Smt_checker.Atom.BO_Zmult
+ | BO_Zlt -> Smt_checker.Atom.BO_Zlt
+ | BO_Zle -> Smt_checker.Atom.BO_Zle
+ | BO_Zge -> Smt_checker.Atom.BO_Zge
+ | BO_Zgt -> Smt_checker.Atom.BO_Zgt
+ | BO_eq t -> Smt_checker.Atom.BO_eq (btype_to_coq t)
+
+
+let n_to_coq = function
+ | NO_distinct t -> btype_to_coq t
+
+
+let i_to_coq i = mkInt (SmtAtom.indexed_op_index i)
+
+
+let a_to_coq a =
+ let to_coq h = mkInt (Atom.index h) in
+ match a with
+ | Acop op -> Smt_checker.Atom.Acop (c_to_coq op)
+ | Auop (op,h) -> Smt_checker.Atom.Auop (u_to_coq op, to_coq h)
+ | Abop (op,h1,h2) ->
+ Smt_checker.Atom.Abop (b_to_coq op, to_coq h1, to_coq h2)
+ | Anop (op,ha) ->
+ let cop = n_to_coq op in
+ let cargs = Array.fold_right (fun h l -> Smt_checker.Cons (to_coq h, l)) ha Smt_checker.Nil in
+ Smt_checker.Atom.Anop (cop, cargs)
+ | Aapp (op,args) ->
+ let cop = i_to_coq op in
+ let cargs = Array.fold_right (fun h l -> Smt_checker.Cons (to_coq h, l)) args Smt_checker.Nil in
+ Smt_checker.Atom.Aapp (cop, cargs)
+
+
+let atom_interp_tbl reify =
+ let t = Atom.to_array reify (Smt_checker.Atom.Acop Smt_checker.Atom.CO_xH) a_to_coq in
+ mkArray t
+
+
+let form_to_coq hf = mkInt (Form.to_lit hf)
+
+let args_to_coq args =
+ let cargs = Array.make (Array.length args + 1) (mkInt 0) in
+ Array.iteri (fun i hf -> cargs.(i) <- form_to_coq hf) args;
+ mkArray cargs
+
+let pf_to_coq = function
+ | Fatom a -> Smt_checker.Form.Fatom (mkInt (Atom.index a))
+ | Fapp(op,args) ->
+ match op with
+ | Ftrue -> Smt_checker.Form.Ftrue
+ | Ffalse -> Smt_checker.Form.Ffalse
+ | Fand -> Smt_checker.Form.Fand (args_to_coq args)
+ | For -> Smt_checker.Form.For (args_to_coq args)
+ | Fimp -> Smt_checker.Form.Fimp (args_to_coq args)
+ | Fxor -> if Array.length args = 2 then Smt_checker.Form.Fxor (form_to_coq args.(0), form_to_coq args.(1)) else assert false
+ | Fiff -> if Array.length args = 2 then Smt_checker.Form.Fiff (form_to_coq args.(0), form_to_coq args.(1)) else assert false
+ | Fite -> if Array.length args = 3 then Smt_checker.Form.Fite (form_to_coq args.(0), form_to_coq args.(1), form_to_coq args.(2)) else assert false
+ | Fnot2 i -> Smt_checker.Form.Fnot2 (mkInt i, form_to_coq args.(0))
+
+
+let form_interp_tbl reify =
+ let (_,t) = Form.to_array reify Smt_checker.Form.Ftrue pf_to_coq in
+ mkArray t
+
+
+(* Importing from SMT-LIB v.2 without generating section variables *)
+
+let count_btype = ref 0
+let count_op = ref 0
+
+
+let declare_sort sym =
+ let s = string_of_symbol sym in
+ let res = Tindex (dummy_indexed_type !count_btype) in
+ incr count_btype;
+ VeritSyntax.add_btype s res;
+ res
+
+
+let declare_fun sym arg cod =
+ let s = string_of_symbol sym in
+ let tyl = List.map sort_of_sort arg in
+ let ty = sort_of_sort cod in
+ let op = dummy_indexed_op !count_op (Array.of_list (List.map fst tyl)) (fst ty) in
+ incr count_op;
+ VeritSyntax.add_fun s op;
+ op
+
+
+let declare_commands ra rf acc = function
+ | CDeclareSort (_,sym,_) -> let _ = declare_sort sym in acc
+ | CDeclareFun (_,sym, (_, arg), cod) -> let _ = declare_fun sym arg cod in acc
+ | CAssert (_, t) -> (make_root ra rf t)::acc
+ | _ -> acc
+
+
+let import_smtlib2 ra rf filename =
+ let chan = open_in filename in
+ let lexbuf = Lexing.from_channel chan in
+ let commands = Smtlib2_parse.main Smtlib2_lex.token lexbuf in
+ close_in chan;
+ match commands with
+ | None -> []
+ | Some (Smtlib2_ast.Commands (_,(_,res))) ->
+ List.rev (List.fold_left (declare_commands ra rf) [] res)
+
+
+(* The final checker *)
+
+let this_clear_all () =
+ Verit.clear_all ();
+ count_btype := 0;
+ count_op := 0
+
+
+let checker fsmt fproof =
+ this_clear_all ();
+ let ra = VeritSyntax.ra in
+ let rf = VeritSyntax.rf in
+ let roots = import_smtlib2 ra rf fsmt in
+ let (max_id, confl) = import_trace fproof None in
+ let (tres,last_root) = to_coq (fun i -> mkInt (SmtAtom.Form.to_lit i)) confl in
+ let certif =
+ Smt_checker.Euf_Checker.Certif (mkInt (max_id + 1), tres, mkInt (get_pos confl)) in
+ let used_roots = compute_roots roots last_root in
+ let used_rootsCstr =
+ let l = List.length used_roots in
+ let res = Array.make (l + 1) (mkInt 0) in
+ let i = ref (l-1) in
+ List.iter (fun j -> res.(!i) <- mkInt j; decr i) used_roots;
+ Smt_checker.Some (mkArray res) in
+ let rootsCstr =
+ let res = Array.make (List.length roots + 1) (mkInt 0) in
+ let i = ref 0 in
+ List.iter (fun j -> res.(!i) <- mkInt (SmtAtom.Form.to_lit j); incr i) roots;
+ mkArray res in
+
+ let t_atom = atom_interp_tbl ra in
+ let t_form = form_interp_tbl rf in
+
+ Smt_checker.Euf_Checker.checker_ext t_atom t_form rootsCstr used_rootsCstr certif
diff --git a/src/extraction/zchaff_checker.ml b/src/extraction/zchaff_checker.ml
new file mode 100644
index 0000000..79e87cc
--- /dev/null
+++ b/src/extraction/zchaff_checker.ml
@@ -0,0 +1,103 @@
+open SmtCertif
+open SmtForm
+open SatAtom
+open SmtTrace
+open Zchaff
+open Sat_checker
+
+
+let mkInt = ExtrNative.of_int
+let mkArray = ExtrNative.of_array
+
+
+let make_roots first last =
+ let roots = Array.make (last.id + 2) (mkArray (Array.make 1 (mkInt 0))) in
+ let mk_elem l =
+ let x = match Form.pform l with
+ | Fatom x -> x + 2
+ | _ -> assert false in
+ mkInt (if Form.is_pos l then x lsl 1 else (x lsl 1) lxor 1) in
+ let r = ref first in
+ while !r.id < last.id do
+ let root = Array.of_list (get_val !r) in
+ let croot = Array.make (Array.length root + 1) (mkInt 0) in
+ Array.iteri (fun i l -> croot.(i) <- mk_elem l) root;
+ roots.(!r.id) <- mkArray croot;
+ r := next !r
+ done;
+ let root = Array.of_list (get_val !r) in
+ let croot = Array.make (Array.length root + 1) (mkInt 0) in
+ Array.iteri (fun i l -> croot.(i) <- mk_elem l) root;
+ roots.(!r.id) <- mkArray croot;
+
+ mkArray roots
+
+
+let to_coq to_lit (cstep,
+ cRes, cImmFlatten,
+ cTrue, cFalse, cBuildDef, cBuildDef2, cBuildProj,
+ cImmBuildProj,cImmBuildDef,cImmBuildDef2,
+ cEqTr, cEqCgr, cEqCgrP,
+ cLiaMicromega, cLiaDiseq, cSplArith, cSplDistinctElim) confl =
+ let step_to_coq c =
+ match c.kind with
+ | Res res ->
+ let size = List.length res.rtail + 3 in
+ let args = Array.make size (mkInt 0) in
+ args.(0) <- mkInt (get_pos res.rc1);
+ args.(1) <- mkInt (get_pos res.rc2);
+ let l = ref res.rtail in
+ for i = 2 to size - 2 do
+ match !l with
+ | c::tl ->
+ args.(i) <- mkInt (get_pos c);
+ l := tl
+ | _ -> assert false
+ done;
+ Sat_Checker.Res (mkInt (get_pos c), mkArray args)
+ | _ -> assert false in
+ let def_step =
+ Sat_Checker.Res (mkInt 0, mkArray [|mkInt 0|]) in
+ let r = ref confl in
+ let nc = ref 0 in
+ while not (isRoot !r.kind) do r := prev !r; incr nc done;
+ let last_root = !r in
+ let size = !nc in
+ let max = (Parray.trunc_size (Uint63.of_int 4194303)) - 1 in
+ let q,r1 = size / max, size mod max in
+
+ let trace =
+ let len = if r1 = 0 then q + 1 else q + 2 in
+ Array.make len (mkArray [|def_step|]) in
+ for j = 0 to q - 1 do
+ let tracej = Array.make (Parray.trunc_size (Uint63.of_int 4194303)) def_step in
+ for i = 0 to max - 1 do
+ r := next !r;
+ tracej.(i) <- step_to_coq !r;
+ done;
+ trace.(j) <- mkArray tracej
+ done;
+ if r1 <> 0 then begin
+ let traceq = Array.make (r1 + 1) def_step in
+ for i = 0 to r1-1 do
+ r := next !r;
+ traceq.(i) <- step_to_coq !r;
+ done;
+ trace.(q) <- mkArray traceq
+ end;
+
+ (mkArray trace, last_root)
+
+
+let checker fdimacs ftrace =
+ SmtTrace.clear ();
+ let _,first,last,reloc = import_cnf fdimacs in
+ let d = make_roots first last in
+
+ let max_id, confl = import_cnf_trace reloc ftrace first last in
+ let (tres,_) =
+ to_coq (fun _ -> assert false) certif_ops confl in
+ let certif =
+ Sat_Checker.Certif (mkInt (max_id + 1), tres, mkInt (get_pos confl)) in
+
+ Sat_Checker.checker d certif
diff --git a/src/lia/Lia.v b/src/lia/Lia.v
new file mode 100644
index 0000000..0969db0
--- /dev/null
+++ b/src/lia/Lia.v
@@ -0,0 +1,1611 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+Require Import Bool.
+Require Import List.
+Require Import Int63.
+Require Import PArray.
+Require Import RingMicromega.
+Require Import ZMicromega.
+Require Import Tauto.
+Require Import Psatz.
+(* Add LoadPath ".." as SMTCoq. *)
+
+Require Import Misc State.
+Require Import SMT_terms.
+Require Import SMTCoq.euf.Euf.
+
+Local Open Scope array_scope.
+Local Open Scope int63_scope.
+
+Section certif.
+
+ Variable t_form : PArray.array Form.form.
+ Variable t_atom : PArray.array Atom.atom.
+
+ Local Notation get_atom := (PArray.get t_atom) (only parsing).
+ Local Notation get_form := (PArray.get t_form) (only parsing).
+
+ Import EnvRing Atom.
+
+ Register option_map as PrimInline.
+
+ Section BuildPositive.
+ Variable build_positive : hatom -> option positive.
+
+ Definition build_positive_atom_aux (a:atom) : option positive :=
+ match a with
+ | Acop CO_xH => Some xH
+ | Auop UO_xO a => option_map xO (build_positive a)
+ | Auop UO_xI a => option_map xI (build_positive a)
+ | _ => None
+ end.
+
+ End BuildPositive.
+
+ Definition build_positive :=
+ foldi_down_cont
+ (fun i cont h =>
+ build_positive_atom_aux cont (get_atom h))
+ (PArray.length t_atom) 0 (fun _ => None).
+
+ Definition build_positive_atom := build_positive_atom_aux build_positive.
+ Register build_positive_atom as PrimInline.
+
+ Section BuildZ.
+
+ Definition build_z_atom_aux a :=
+ match a with
+ | Auop UO_Zpos a => option_map Zpos (build_positive a)
+ | Acop CO_Z0 => Some Z0
+ | Auop UO_Zneg a => option_map Zneg (build_positive a)
+ | _ => None
+ end.
+
+ End BuildZ.
+
+ Definition build_z h := build_z_atom_aux (get_atom h).
+
+ Definition build_z_atom := build_z_atom_aux.
+
+ Definition vmap := (positive * list Atom.atom)%type.
+
+ Fixpoint find_var_aux h p (l:list Atom.atom) :=
+ match l with
+ | nil => None
+ | h' :: l =>
+ let p := Ppred p in
+ if Atom.eqb h h' then Some p else find_var_aux h p l
+ end.
+
+ Definition find_var (vm:vmap) h :=
+ let (count,map) := vm in
+ match find_var_aux h count map with
+ | Some p => (vm, p)
+ | None => ((Psucc count,h::map), count)
+ end.
+
+ Definition empty_vmap : vmap := (1%positive, nil).
+
+ Section BuildPExpr.
+
+ Variable build_pexpr : vmap -> hatom -> (vmap * PExpr Z).
+
+ Definition build_pexpr_atom_aux (vm:vmap) (h:atom) : vmap * PExpr Z :=
+ match h with
+ | Abop BO_Zplus a1 a2 =>
+ let (vm, pe1) := build_pexpr vm a1 in
+ let (vm, pe2) := build_pexpr vm a2 in
+ (vm, PEadd pe1 pe2)
+ | Abop BO_Zminus a1 a2 =>
+ let (vm, pe1) := build_pexpr vm a1 in
+ let (vm, pe2) := build_pexpr vm a2 in
+ (vm, PEsub pe1 pe2)
+ | Abop BO_Zmult a1 a2 =>
+ let (vm, pe1) := build_pexpr vm a1 in
+ let (vm, pe2) := build_pexpr vm a2 in
+ (vm, PEmul pe1 pe2)
+ | Auop UO_Zopp a =>
+ let (vm, pe) := build_pexpr vm a in
+ (vm, PEopp pe)
+ | _ =>
+ match build_z_atom h with
+ | Some z => (vm, PEc z)
+ | None =>
+ let (vm,p) := find_var vm h in
+ (vm,PEX Z p)
+ end
+ end.
+
+ End BuildPExpr.
+
+ Definition build_pexpr :=
+ foldi_down_cont
+ (fun i cont vm h => build_pexpr_atom_aux cont vm (get_atom h))
+ (PArray.length t_atom) 0 (fun vm _ => (vm,PEc 0%Z)).
+
+ Definition build_pexpr_atom := build_pexpr_atom_aux build_pexpr.
+
+ (* Remark: We do not use OpNeq *)
+ Definition build_op2 op :=
+ match op with
+ | (BO_eq Typ.TZ) => Some OpEq
+ | BO_Zle => Some OpLe
+ | BO_Zge => Some OpGe
+ | BO_Zlt => Some OpLt
+ | BO_Zgt => Some OpGt
+ | _ => None
+ end.
+
+ Definition build_formula_atom vm (a:atom) :=
+ match a with
+ | Abop op a1 a2 =>
+ match build_op2 op with
+ | Some o =>
+ let (vm,pe1) := build_pexpr vm a1 in
+ let (vm,pe2) := build_pexpr vm a2 in
+ Some (vm, Build_Formula pe1 o pe2)
+ | None => None
+ end
+ | _ => None
+ end.
+
+ Definition build_formula vm h :=
+ build_formula_atom vm (get_atom h).
+
+
+ Section Build_form.
+
+ Definition build_not2 i f :=
+ fold (fun f' => N (N (A:=Formula Z) f')) 1 i f.
+
+ Variable build_var : vmap -> var -> option (vmap*BFormula (Formula Z)).
+
+
+ Definition build_hform vm f : option (vmap*BFormula (Formula Z)) :=
+ match f with
+ | Form.Fatom h =>
+ match build_formula vm h with
+ | Some (vm,f) => Some (vm, A f)
+ | None => None
+ end
+ | Form.Ftrue => Some (vm, TT (Formula Z))
+ | Form.Ffalse => Some (vm, FF (Formula Z))
+ | Form.Fnot2 i l =>
+ match build_var vm (Lit.blit l) with
+ | Some (vm, f) =>
+ let f' := build_not2 i f in
+ let f'' := if Lit.is_pos l then f' else N f' in
+ Some (vm,f'')
+ | None => None
+ end
+ | Form.Fand args =>
+ let n := length args in
+ if n == 0 then Some (vm,TT (Formula Z))
+ else
+ foldi (fun i f1 => match f1 with | Some(vm',f1') => let l := (args.[i]) in match build_var vm' (Lit.blit l) with | Some(vm2,f2) => let f2' := if Lit.is_pos l then f2 else N f2 in Some(vm2,Cj f1' f2') | None => None end | None => None end) 1 (n-1) (let l := args.[0] in
+ match build_var vm (Lit.blit l) with
+ | Some (vm',f) => if Lit.is_pos l then Some (vm',f) else Some (vm',N f)
+ | None => None
+ end)
+ | Form.For args =>
+ let n := length args in
+ if n == 0 then Some (vm,FF (Formula Z))
+ else
+ foldi (fun i f1 => match f1 with | Some(vm',f1') => let l := (args.[i]) in match build_var vm' (Lit.blit l) with | Some(vm2,f2) => let f2' := if Lit.is_pos l then f2 else N f2 in Some(vm2,D f1' f2') | None => None end | None => None end) 1 (n-1) (let l := args.[0] in
+ match build_var vm (Lit.blit l) with
+ | Some (vm',f) => if Lit.is_pos l then Some (vm',f) else Some (vm',N f)
+ | None => None
+ end)
+ | Form.Fxor a b =>
+ match build_var vm (Lit.blit a) with
+ | Some (vm1, f1) =>
+ match build_var vm1 (Lit.blit b) with
+ | Some (vm2, f2) =>
+ let f1' := if Lit.is_pos a then f1 else N f1 in
+ let f2' := if Lit.is_pos b then f2 else N f2 in
+ Some (vm2, Cj (D f1' f2') (D (N f1') (N f2')))
+ | None => None
+ end
+ | None => None
+ end
+ | Form.Fimp args =>
+ let n := length args in
+ if n == 0 then Some (vm,TT (Formula Z))
+ else if n <= 1 then
+ let l := args.[0] in
+ match build_var vm (Lit.blit l) with
+ | Some (vm',f) => if Lit.is_pos l then Some (vm',f) else Some (vm',N f)
+ | None => None
+ end
+ else
+ foldi_down (fun i f1 => match f1 with | Some(vm',f1') => let l := (args.[i]) in match build_var vm' (Lit.blit l) with | Some(vm2,f2) => let f2' := if Lit.is_pos l then f2 else N f2 in Some(vm2,I f2' f1') | None => None end | None => None end) (n-2) 0 (let l := args.[n-1] in
+ match build_var vm (Lit.blit l) with
+ | Some (vm',f) => if Lit.is_pos l then Some (vm',f) else Some (vm',N f)
+ | None => None
+ end)
+ | Form.Fiff a b =>
+ match build_var vm (Lit.blit a) with
+ | Some (vm1, f1) =>
+ match build_var vm1 (Lit.blit b) with
+ | Some (vm2, f2) =>
+ let f1' := if Lit.is_pos a then f1 else N f1 in
+ let f2' := if Lit.is_pos b then f2 else N f2 in
+ Some (vm2, Cj (D f1' (N f2')) (D (N f1') f2'))
+ | None => None
+ end
+ | None => None
+ end
+ | Form.Fite a b c =>
+ match build_var vm (Lit.blit a) with
+ | Some (vm1, f1) =>
+ match build_var vm1 (Lit.blit b) with
+ | Some (vm2, f2) =>
+ match build_var vm2 (Lit.blit c) with
+ | Some (vm3, f3) =>
+ let f1' := if Lit.is_pos a then f1 else N f1 in
+ let f2' := if Lit.is_pos b then f2 else N f2 in
+ let f3' := if Lit.is_pos c then f3 else N f3 in
+ Some (vm3, D (Cj f1' f2') (Cj (N f1') f3'))
+ | None => None
+ end
+ | None => None
+ end
+ | None => None
+ end
+ end.
+
+ End Build_form.
+
+
+ Definition build_var :=
+ foldi_down_cont
+ (fun i cont vm h => build_hform cont vm (get_form h))
+ (PArray.length t_form) 0 (fun _ _ => None).
+
+ Definition build_form := build_hform build_var.
+
+
+ Definition build_nlit vm l :=
+ let l := Lit.neg l in
+ match build_form vm (get_form (Lit.blit l)) with
+ | Some (vm,f) =>
+ let f := if Lit.is_pos l then f else N f in
+ Some (vm,f)
+ | None => None
+ end.
+
+
+ Fixpoint build_clause_aux vm (cl:list _lit) {struct cl} :
+ option (vmap * BFormula (Formula Z)) :=
+ match cl with
+ | nil => None
+ | l::nil => build_nlit vm l
+ | l::cl =>
+ match build_nlit vm l with
+ | Some (vm,bf1) =>
+ match build_clause_aux vm cl with
+ | Some (vm,bf2) => Some (vm, Cj bf1 bf2)
+ | _ => None
+ end
+ | None => None
+ end
+ end.
+
+ Definition build_clause vm cl :=
+ match build_clause_aux vm cl with
+ | Some (vm, bf) => Some (vm, I bf (FF _))
+ | None => None
+ end.
+
+ Definition get_eq (l:_lit) (f : Atom.hatom -> Atom.hatom -> C.t) :=
+ if Lit.is_pos l then
+ match get_form (Lit.blit l) with
+ | Form.Fatom xa =>
+ match get_atom xa with
+ | Atom.Abop (Atom.BO_eq _) a b => f a b
+ | _ => C._true
+ end
+ | _ => C._true
+ end
+ else C._true.
+ Register get_eq as PrimInline.
+
+ Definition get_not_le (l:_lit) (f : Atom.hatom -> Atom.hatom -> C.t) :=
+ if negb (Lit.is_pos l) then
+ match get_form (Lit.blit l) with
+ | Form.Fatom xa =>
+ match get_atom xa with
+ | Atom.Abop (Atom.BO_Zle) a b => f a b
+ | _ => C._true
+ end
+ | _ => C._true
+ end
+ else C._true.
+ Register get_not_le as PrimInline.
+
+ Definition check_micromega cl c : C.t :=
+ match build_clause empty_vmap cl with
+ | Some (_, bf) =>
+ if ZTautoChecker bf c then cl
+ else C._true
+ | None => C._true
+ end.
+
+ Definition check_diseq l : C.t :=
+ match get_form (Lit.blit l) with
+ |Form.For a =>
+ if PArray.length a == 3 then
+ let a_eq_b := a.[0] in
+ let not_a_le_b := a.[1] in
+ let not_b_le_a := a.[2] in
+ get_eq a_eq_b (fun a b => get_not_le not_a_le_b (fun a' b' => get_not_le not_b_le_a (fun b'' a'' =>
+ if (a == a') && (a == a'') && (b == b') && (b == b'')
+ then (Lit.lit (Lit.blit l))::nil
+ else
+ if (a == b') && (a == b'') && (b == a') && (b == a'')
+ then (Lit.lit (Lit.blit l))::nil
+ else C._true)))
+ else C._true
+ | _ => C._true
+ end.
+
+
+ Section Proof.
+
+ Variables (t_i : array typ_eqb)
+ (t_func : array (Atom.tval t_i))
+ (ch_atom : Atom.check_atom t_atom)
+ (ch_form : Form.check_form t_form)
+ (wt_t_atom : Atom.wt t_i t_func t_atom).
+
+ Local Notation check_atom :=
+ (check_aux t_i t_func (get_type t_i t_func t_atom)).
+
+ Local Notation interp_form_hatom :=
+ (Atom.interp_form_hatom t_i t_func t_atom).
+
+ Local Notation rho :=
+ (Form.interp_state_var interp_form_hatom t_form).
+
+ Local Notation t_interp := (t_interp t_i t_func t_atom).
+
+ Local Notation interp_atom :=
+ (interp_aux t_i t_func (get t_interp)).
+
+ Let wf_t_atom : Atom.wf t_atom.
+ Proof. destruct (Atom.check_atom_correct _ ch_atom); auto. Qed.
+
+ Let def_t_atom : default t_atom = Atom.Acop Atom.CO_xH.
+ Proof. destruct (Atom.check_atom_correct _ ch_atom); auto. Qed.
+
+ Let def_t_form : default t_form = Form.Ftrue.
+ Proof.
+ destruct (Form.check_form_correct interp_form_hatom _ ch_form) as [H _]; destruct H; auto.
+ Qed.
+
+ Let wf_t_form : Form.wf t_form.
+ Proof.
+ destruct (Form.check_form_correct interp_form_hatom _ ch_form) as [H _]; destruct H; auto.
+ Qed.
+
+ Let wf_rho : Valuation.wf rho.
+ Proof.
+ destruct (Form.check_form_correct interp_form_hatom _ ch_form); auto.
+ Qed.
+
+ Lemma build_positive_atom_aux_correct :
+ forall (build_positive : hatom -> option positive),
+ (forall (h : hatom) p,
+ build_positive h = Some p ->
+ t_interp.[h] = Bval t_i Typ.Tpositive p) ->
+ forall (a:atom) (p:positive),
+ build_positive_atom_aux build_positive a = Some p ->
+ interp_atom a = Bval t_i Typ.Tpositive p.
+ Proof.
+ intros build_positive Hbuild a; case a; simpl; try discriminate; auto.
+ destruct c; simpl; try discriminate; intros p H1; inversion_clear H1; auto.
+ destruct u; simpl; try discriminate;
+ intros i p; case_eq (build_positive i); simpl; try discriminate; intros q H1 H2; inversion_clear H2; rewrite (Hbuild _ _ H1); auto.
+ Qed.
+
+ Lemma build_positive_correct : forall h p,
+ build_positive h = Some p ->
+ t_interp.[h] = Bval t_i Typ.Tpositive p.
+ Proof.
+ unfold build_positive.
+ apply foldi_down_cont_ind;intros;try discriminate.
+ rewrite t_interp_wf;trivial.
+ apply build_positive_atom_aux_correct with cont;trivial.
+ Qed.
+
+ Lemma build_positive_atom_correct :
+ forall (a:atom) (p:positive),
+ build_positive_atom a = Some p ->
+ interp_atom a = Bval t_i Typ.Tpositive p.
+ Proof.
+ apply build_positive_atom_aux_correct;apply build_positive_correct.
+ Qed.
+
+ Lemma build_z_atom_aux_correct :
+ forall a z,
+ build_z_atom_aux a = Some z ->
+ interp_atom a = Bval t_i Typ.TZ z.
+ Proof.
+ intros a z.
+ destruct a;simpl;try discriminate;auto.
+ destruct c;[discriminate | intros Heq;inversion Heq;trivial].
+ destruct u;try discriminate;
+ case_eq (build_positive i);try discriminate;
+ intros p Hp Heq;inversion Heq;clear Heq;subst;
+ rewrite (build_positive_correct _ _ Hp);trivial.
+ Qed.
+
+ Lemma build_z_correct :
+ forall h z, build_z h = Some z -> t_interp.[h] = Bval t_i Typ.TZ z.
+ Proof.
+ unfold build_z;intros h z;rewrite t_interp_wf;trivial.
+ apply build_z_atom_aux_correct;discriminate.
+ Qed.
+
+ Lemma build_z_atom_correct :
+ forall a z, build_z_atom a = Some z ->
+ interp_atom a = Bval t_i Typ.TZ z.
+ Proof.
+ apply build_z_atom_aux_correct.
+ Qed.
+
+ Definition wf_vmap (vm:vmap) :=
+ (List.length (snd vm) = nat_of_P (fst vm) - 1)%nat /\
+ List.forallb (fun h => check_atom h Typ.TZ) (snd vm).
+
+ Fixpoint bounded_pexpr (p:positive) (pe:PExpr Z) :=
+ match pe with
+ | PEc _ => true
+ | PEX x => Zlt_bool (Zpos x) (Zpos p)
+ | PEadd pe1 pe2
+ | PEsub pe1 pe2
+ | PEmul pe1 pe2 => bounded_pexpr p pe1 && bounded_pexpr p pe2
+ | PEopp pe => bounded_pexpr p pe
+ | PEpow pe _ => bounded_pexpr p pe
+ end.
+
+ Definition bounded_formula (p:positive) (f:Formula Z) :=
+ bounded_pexpr p (f.(Flhs)) && bounded_pexpr p (f.(Frhs)).
+
+ Fixpoint bounded_bformula (p:positive) (bf:BFormula (Formula Z)) :=
+ match bf with
+ | TT | FF | X _ => true
+ | A f => bounded_formula p f
+ | Cj bf1 bf2
+ | D bf1 bf2
+ | I bf1 bf2 => bounded_bformula p bf1 && bounded_bformula p bf2
+ | N bf => bounded_bformula p bf
+ end.
+
+ Definition interp_vmap (vm:vmap) p :=
+ match nth_error (snd vm) (nat_of_P (fst vm - p) - 1)%nat with
+ | Some a =>
+ let (t,v) := interp_atom a in
+ match Typ.cast t Typ.TZ with
+ | Typ.Cast k => k (Typ.interp t_i) v
+ | _ => 0%Z
+ end
+ | _ => 0%Z
+ end.
+
+ Lemma find_var_aux_lt :
+ forall h p lvm pvm,
+ find_var_aux h pvm lvm = Some p ->
+ Datatypes.length lvm = (nat_of_P pvm - 1)%nat ->
+ (nat_of_P p < nat_of_P pvm)%nat.
+ Proof.
+ induction lvm;simpl;try discriminate.
+ intros pvm Heq1 Heq.
+ assert (1 < pvm)%positive.
+ rewrite Plt_lt;change (nat_of_P 1) with 1%nat ;omega.
+ assert (Datatypes.length lvm = nat_of_P (Ppred pvm) - 1)%nat.
+ rewrite Ppred_minus, Pminus_minus;trivial.
+ change (nat_of_P 1) with 1%nat ;try omega.
+ revert Heq1.
+ destruct (Atom.reflect_eqb h a);subst.
+ intros Heq1;inversion Heq1;clear Heq1;subst;omega.
+ intros Heq1;apply IHlvm in Heq1;trivial.
+ apply lt_trans with (1:= Heq1);omega.
+ Qed.
+
+ Lemma build_pexpr_atom_aux_correct_z :
+ forall (h : atom) (vm vm' : vmap) (pe : PExpr Z),
+ check_atom h Typ.TZ ->
+ match build_z_atom h with
+ | Some z => (vm, PEc z)
+ | None => let (vm0, p) := find_var vm h in (vm0, PEX Z p)
+ end = (vm', pe) ->
+ wf_vmap vm ->
+ wf_vmap vm' /\
+ (nat_of_P (fst vm) <= nat_of_P (fst vm'))%nat /\
+ (forall p,
+ (nat_of_P p < nat_of_P (fst vm))%nat ->
+ nth_error (snd vm) (nat_of_P (fst vm - p) - 1) =
+ nth_error (snd vm')(nat_of_P (fst vm' - p) - 1)) /\
+ bounded_pexpr (fst vm') pe /\
+ interp_atom h = Bval t_i Typ.TZ (Zeval_expr (interp_vmap vm') pe).
+ Proof.
+ intros h vm vm' pe Hh.
+ case_eq (build_z_atom h).
+ intros z Hb Heq;inversion Heq;clear Heq;subst.
+ intros (Hwf1, Hwf2).
+ repeat split;auto with zarith.
+ rewrite (build_z_atom_correct _ _ Hb);trivial.
+ intros _;unfold find_var;destruct vm as (pvm,lvm).
+ case_eq (find_var_aux h pvm lvm).
+ intros p Hf Heq;inversion Heq;clear Heq;subst.
+ intros (Hwf1, Hwf2);repeat split;auto with zarith.
+ simpl; unfold is_true;rewrite <- Zlt_is_lt_bool.
+ rewrite <- !Z_of_nat_of_P; apply inj_lt;simpl in Hwf1.
+ apply find_var_aux_lt with (1:= Hf);trivial.
+ revert lvm pvm p Hf Hwf1 Hwf2.
+ unfold interp_vmap;simpl.
+ induction lvm;simpl;try discriminate.
+ intros pvm p Heq1 Heq.
+ assert (1 < pvm)%positive.
+ rewrite Plt_lt;change (nat_of_P 1) with 1%nat ;omega.
+ assert (Datatypes.length lvm = nat_of_P (Ppred pvm) - 1)%nat.
+ rewrite Ppred_minus, Pminus_minus;trivial.
+ change (nat_of_P 1) with 1%nat ;try omega.
+ revert Heq1.
+ destruct (Atom.reflect_eqb h a);subst.
+ intros Heq1;inversion Heq1;clear Heq1;subst.
+ unfold is_true;rewrite andb_true_iff;intros (H1,H2).
+ assert (1 < nat_of_P pvm)%nat by (rewrite Plt_lt in H;trivial).
+ assert (W:=nat_of_P_pos (Ppred pvm)).
+ assert (nat_of_P (pvm - Ppred pvm) - 1 = 0)%nat.
+ rewrite Pminus_minus;try omega.
+ apply Plt_lt;omega.
+ rewrite H4;simpl.
+ destruct (check_aux_interp_aux _ _ _ wf_t_atom _ _ H1) as (z,Hz).
+ rewrite Hz;trivial.
+ unfold is_true;rewrite andb_true_iff;intros Heq1 (H1,H2).
+ assert (W:= find_var_aux_lt _ _ _ _ Heq1 H0).
+ assert (nat_of_P (pvm - p) - 1 = S (nat_of_P (Ppred pvm - p) - 1))%nat.
+ assert (W1:= W);rewrite <- Plt_lt in W.
+ rewrite !Pminus_minus;trivial.
+ assert (W2:=nat_of_P_pos (Ppred pvm)).
+ omega.
+ rewrite Plt_lt.
+ apply lt_trans with (1:= W1);omega.
+ rewrite H3;simpl;apply IHlvm;trivial.
+ intros _ Heq;inversion Heq;clear Heq;subst;unfold wf_vmap;
+ simpl;intros (Hwf1, Hwf2);repeat split;simpl.
+ rewrite Psucc_S; assert (W:= nat_of_P_pos pvm);omega.
+ rewrite Hh;trivial.
+ rewrite Psucc_S;omega.
+ intros p Hlt;
+ assert (nat_of_P (Psucc pvm - p) - 1 = S (nat_of_P (pvm - p) - 1))%nat.
+ assert (W1:= Hlt);rewrite <- Plt_lt in W1.
+ rewrite !Pminus_minus;trivial.
+ rewrite Psucc_S;omega.
+ rewrite Plt_lt, Psucc_S;omega.
+ rewrite H;trivial.
+ unfold is_true;rewrite <- Zlt_is_lt_bool.
+ rewrite Zpos_succ_morphism;omega.
+ destruct (check_aux_interp_aux _ _ _ wf_t_atom _ _ Hh) as (z,Hz).
+ rewrite Hz;unfold interp_vmap;simpl.
+ assert (nat_of_P (Psucc pvm - pvm) = 1%nat).
+ rewrite Pplus_one_succ_l, Pminus_minus, Pplus_plus.
+ change (nat_of_P 1) with 1%nat;omega.
+ rewrite Plt_lt, Pplus_plus.
+ change (nat_of_P 1) with 1%nat;omega.
+ rewrite H;simpl;rewrite Hz;trivial.
+ Qed.
+
+ Lemma bounded_pexpr_le :
+ forall p p',
+ (nat_of_P p <= nat_of_P p')%nat ->
+ forall pe,
+ bounded_pexpr p pe -> bounded_pexpr p' pe.
+ Proof.
+ unfold is_true;induction pe;simpl;trivial.
+ rewrite <- !Zlt_is_lt_bool; rewrite <- Ple_le in H.
+ intros H1;apply Zlt_le_trans with (1:= H1);trivial.
+ rewrite !andb_true_iff;intros (H1,H2);auto.
+ rewrite !andb_true_iff;intros (H1,H2);auto.
+ rewrite !andb_true_iff;intros (H1,H2);auto.
+ Qed.
+
+ Lemma interp_pexpr_le :
+ forall vm vm',
+ (forall (p : positive),
+ (nat_of_P p < nat_of_P (fst vm))%nat ->
+ nth_error (snd vm) (nat_of_P (fst vm - p) - 1) =
+ nth_error (snd vm') (nat_of_P (fst vm' - p) - 1)) ->
+ forall pe,
+ bounded_pexpr (fst vm) pe ->
+ Zeval_expr (interp_vmap vm) pe = Zeval_expr (interp_vmap vm') pe.
+ Proof.
+ intros vm vm' Hnth.
+ unfold is_true;induction pe;simpl;trivial.
+ unfold interp_vmap, is_true;rewrite <- Zlt_is_lt_bool.
+ intros Hlt;rewrite Hnth;trivial.
+ rewrite <- Plt_lt;trivial.
+ rewrite andb_true_iff;intros (H1,H2);rewrite IHpe1, IHpe2;trivial.
+ rewrite andb_true_iff;intros (H1,H2);rewrite IHpe1, IHpe2;trivial.
+ rewrite andb_true_iff;intros (H1,H2);rewrite IHpe1, IHpe2;trivial.
+ intros H1;rewrite IHpe;trivial.
+ intros H1;rewrite IHpe;trivial.
+ Qed.
+
+ Lemma build_pexpr_atom_aux_correct :
+ forall (build_pexpr : vmap -> hatom -> vmap * PExpr Z) h i,
+ (forall h' vm vm' pe,
+ h' < h ->
+ Typ.eqb (get_type t_i t_func t_atom h') Typ.TZ ->
+ build_pexpr vm h' = (vm',pe) ->
+ wf_vmap vm ->
+ wf_vmap vm' /\
+ (nat_of_P (fst vm) <= nat_of_P (fst vm'))%nat /\
+ (forall p,
+ (nat_of_P p < nat_of_P (fst vm))%nat ->
+ nth_error (snd vm) (nat_of_P (fst vm - p) - 1) =
+ nth_error (snd vm')(nat_of_P (fst vm' - p) - 1)) /\
+ bounded_pexpr (fst vm') pe /\
+ t_interp.[h'] = Bval t_i Typ.TZ (Zeval_expr (interp_vmap vm') pe))->
+ forall a vm vm' pe,
+ h < i ->
+ lt_atom h a ->
+ check_atom a Typ.TZ ->
+ build_pexpr_atom_aux build_pexpr vm a = (vm',pe) ->
+ wf_vmap vm ->
+ wf_vmap vm' /\
+ (nat_of_P (fst vm) <= nat_of_P (fst vm'))%nat /\
+ (forall p,
+ (nat_of_P p < nat_of_P (fst vm))%nat ->
+ nth_error (snd vm) (nat_of_P (fst vm - p) - 1) =
+ nth_error (snd vm')(nat_of_P (fst vm' - p) - 1)) /\
+ bounded_pexpr (fst vm') pe /\
+ interp_atom a = Bval t_i Typ.TZ (Zeval_expr (interp_vmap vm') pe).
+ Proof.
+ intros build_pexpr h i Hb a.
+Opaque build_z_atom interp_aux.
+ case a;simpl;
+ try (intros;apply build_pexpr_atom_aux_correct_z;trivial;fail).
+
+ intros u; destruct u; intros j vm vm' pe _H_ Hlt Ht;
+ try (intros;apply build_pexpr_atom_aux_correct_z;trivial;fail).
+ generalize (Hb j vm vm').
+ destruct (build_pexpr vm j) as (vm0, pe0); intro W1.
+ intros Heq Hwf;inversion Heq;clear Heq;subst.
+ assert (W:= W1 pe0 Hlt Ht (refl_equal _) Hwf).
+ decompose [and] W;clear W W1.
+ destruct H;repeat split;trivial.
+Transparent interp_aux.
+ simpl;rewrite H4;trivial.
+
+ intro b; destruct b; intros j k vm vm' pe HH Hlt Ht;
+ try (intros;apply build_pexpr_atom_aux_correct_z;trivial;fail).
+
+ generalize (Hb j vm). destruct (build_pexpr vm j) as (vm0,pe0). intro IH.
+ generalize (Hb k vm0). destruct (build_pexpr vm0 k) as (vm1,pe1). intro IH'.
+ simpl in Ht;unfold is_true in Ht;rewrite !andb_true_iff in Ht;
+ decompose [and] Ht;clear Ht.
+ unfold is_true in Hlt;rewrite andb_true_iff in Hlt;destruct Hlt as (Hlt1, Hlt2).
+ intros Heq Hwf;inversion Heq;clear Heq;subst.
+ assert (W:= IH _ _ Hlt1 H (refl_equal _) Hwf);clear IH.
+ decompose [and] W;clear W.
+ assert (W:= IH' _ _ Hlt2 H0 (refl_equal _) H1);clear IH'.
+ decompose [and] W;clear W.
+ destruct H5;repeat split;trivial.
+ apply le_trans with (1:= H3);trivial.
+ intros p Hlt;rewrite H2, H7;trivial.
+ apply lt_le_trans with (1:=Hlt);trivial.
+ simpl;rewrite H9, andb_true_r.
+ apply (bounded_pexpr_le (fst vm0));auto with arith.
+ simpl;rewrite H6, H11;simpl.
+ rewrite (interp_pexpr_le _ _ H7 _ H4);trivial.
+
+ generalize (Hb j vm). destruct (build_pexpr vm j) as (vm0,pe0); intro IH.
+ generalize (Hb k vm0). destruct (build_pexpr vm0 k) as (vm1,pe1). intro IH'.
+ simpl in Ht;unfold is_true in Ht;rewrite !andb_true_iff in Ht;
+ decompose [and] Ht;clear Ht.
+ unfold is_true in Hlt;rewrite andb_true_iff in Hlt;destruct Hlt as (Hlt1, Hlt2).
+ intros Heq Hwf;inversion Heq;clear Heq;subst.
+ assert (W:= IH _ _ Hlt1 H (refl_equal _) Hwf);clear IH.
+ decompose [and] W;clear W.
+ assert (W:= IH' _ _ Hlt2 H0 (refl_equal _) H1);clear IH'.
+ decompose [and] W;clear W.
+ destruct H5;repeat split;trivial.
+ apply le_trans with (1:= H3);trivial.
+ intros p Hlt;rewrite H2, H7;trivial.
+ apply lt_le_trans with (1:=Hlt);trivial.
+ simpl;rewrite H9, andb_true_r.
+ apply (bounded_pexpr_le (fst vm0));auto with arith.
+ simpl;rewrite H6, H11;simpl.
+ rewrite (interp_pexpr_le _ _ H7 _ H4);trivial.
+
+ generalize (Hb j vm). destruct (build_pexpr vm j) as (vm0,pe0); intro IH.
+ generalize (Hb k vm0). destruct (build_pexpr vm0 k) as (vm1,pe1). intro IH'.
+ simpl in Ht;unfold is_true in Ht;rewrite !andb_true_iff in Ht;
+ decompose [and] Ht;clear Ht.
+ unfold is_true in Hlt;rewrite andb_true_iff in Hlt;destruct Hlt as (Hlt1, Hlt2).
+ intros Heq Hwf;inversion Heq;clear Heq;subst.
+ assert (W:= IH _ _ Hlt1 H (refl_equal _) Hwf);clear IH.
+ decompose [and] W;clear W.
+ assert (W:= IH' _ _ Hlt2 H0 (refl_equal _) H1);clear IH'.
+ decompose [and] W;clear W.
+ destruct H5;repeat split;trivial.
+ apply le_trans with (1:= H3);trivial.
+ intros p Hlt;rewrite H2, H7;trivial.
+ apply lt_le_trans with (1:=Hlt);trivial.
+ simpl;rewrite H9, andb_true_r.
+ apply (bounded_pexpr_le (fst vm0));auto with arith.
+ simpl;rewrite H6, H11;simpl.
+ rewrite (interp_pexpr_le _ _ H7 _ H4);trivial.
+ Qed.
+Transparent build_z_atom.
+
+ Lemma build_pexpr_atom_aux_correct' :
+ forall (build_pexpr : vmap -> hatom -> vmap * PExpr Z),
+ (forall h' vm vm' pe,
+ Typ.eqb (get_type t_i t_func t_atom h') Typ.TZ ->
+ build_pexpr vm h' = (vm',pe) ->
+ wf_vmap vm ->
+ wf_vmap vm' /\
+ (nat_of_P (fst vm) <= nat_of_P (fst vm'))%nat /\
+ (forall p,
+ (nat_of_P p < nat_of_P (fst vm))%nat ->
+ nth_error (snd vm) (nat_of_P (fst vm - p) - 1) =
+ nth_error (snd vm')(nat_of_P (fst vm' - p) - 1)) /\
+ bounded_pexpr (fst vm') pe /\
+ t_interp.[h'] = Bval t_i Typ.TZ (Zeval_expr (interp_vmap vm') pe))->
+ forall a vm vm' pe,
+ check_atom a Typ.TZ ->
+ build_pexpr_atom_aux build_pexpr vm a = (vm',pe) ->
+ wf_vmap vm ->
+ wf_vmap vm' /\
+ (nat_of_P (fst vm) <= nat_of_P (fst vm'))%nat /\
+ (forall p,
+ (nat_of_P p < nat_of_P (fst vm))%nat ->
+ nth_error (snd vm) (nat_of_P (fst vm - p) - 1) =
+ nth_error (snd vm')(nat_of_P (fst vm' - p) - 1)) /\
+ bounded_pexpr (fst vm') pe /\
+ interp_atom a = Bval t_i Typ.TZ (Zeval_expr (interp_vmap vm') pe).
+ Proof.
+ intros build_pexpr Hb a.
+Opaque build_z_atom interp_aux.
+ case a;simpl;
+ try (intros;apply build_pexpr_atom_aux_correct_z;trivial;fail).
+ intro u; destruct u; intros i vm vm' pe Ht;
+ try (intros;apply build_pexpr_atom_aux_correct_z;trivial;fail).
+ generalize (Hb i vm); clear Hb.
+ destruct (build_pexpr vm i) as (vm0,pe0); intro IH.
+ intros Heq Hwf;inversion Heq;clear Heq;subst.
+ assert (W:= IH vm' pe0 Ht (refl_equal _) Hwf).
+ decompose [and] W;clear W IH.
+ destruct H;repeat split;trivial.
+Transparent interp_aux.
+ simpl;rewrite H4;trivial.
+
+ intro b; destruct b; intros j k vm vm' pe Ht;
+ try (intros;apply build_pexpr_atom_aux_correct_z;trivial;fail).
+ generalize (Hb j vm).
+ destruct (build_pexpr vm j) as (vm0,pe0); intro IH.
+ generalize (Hb k vm0); clear Hb.
+ destruct (build_pexpr vm0 k) as (vm1,pe1); intro IH'.
+ simpl in Ht;unfold is_true in Ht;rewrite !andb_true_iff in Ht;
+ decompose [and] Ht;clear Ht.
+ intros Heq Hwf;inversion Heq;clear Heq;subst.
+ assert (W:= IH _ _ H (refl_equal _) Hwf);clear IH.
+ decompose [and] W;clear W.
+ assert (W:= IH' _ _ H0 (refl_equal _) H1);clear IH'.
+ decompose [and] W;clear W.
+ destruct H5;repeat split;trivial.
+ apply le_trans with (1:= H3);trivial.
+ intros p Hlt;rewrite H2, H7;trivial.
+ apply lt_le_trans with (1:=Hlt);trivial.
+ simpl;rewrite H9, andb_true_r.
+ apply (bounded_pexpr_le (fst vm0));auto with arith.
+ simpl;rewrite H6, H11;simpl.
+ rewrite (interp_pexpr_le _ _ H7 _ H4);trivial.
+
+ generalize (Hb j vm).
+ destruct (build_pexpr vm j) as (vm0,pe0); intro IH.
+ generalize (Hb k vm0); clear Hb.
+ destruct (build_pexpr vm0 k) as (vm1,pe1); intro IH'.
+ simpl in Ht;unfold is_true in Ht;rewrite !andb_true_iff in Ht;
+ decompose [and] Ht;clear Ht.
+ intros Heq Hwf;inversion Heq;clear Heq;subst.
+ assert (W:= IH _ _ H (refl_equal _) Hwf);clear IH.
+ decompose [and] W;clear W.
+ assert (W:= IH' _ _ H0 (refl_equal _) H1);clear IH'.
+ decompose [and] W;clear W.
+ destruct H5;repeat split;trivial.
+ apply le_trans with (1:= H3);trivial.
+ intros p Hlt;rewrite H2, H7;trivial.
+ apply lt_le_trans with (1:=Hlt);trivial.
+ simpl;rewrite H9, andb_true_r.
+ apply (bounded_pexpr_le (fst vm0));auto with arith.
+ simpl;rewrite H6, H11;simpl.
+ rewrite (interp_pexpr_le _ _ H7 _ H4);trivial.
+
+ generalize (Hb j vm).
+ destruct (build_pexpr vm j) as (vm0,pe0); intro IH.
+ generalize (Hb k vm0); clear Hb.
+ destruct (build_pexpr vm0 k) as (vm1,pe1); intro IH'.
+ simpl in Ht;unfold is_true in Ht;rewrite !andb_true_iff in Ht;
+ decompose [and] Ht;clear Ht.
+ intros Heq Hwf;inversion Heq;clear Heq;subst.
+ assert (W:= IH _ _ H (refl_equal _) Hwf);clear IH.
+ decompose [and] W;clear W.
+ assert (W:= IH' _ _ H0 (refl_equal _) H1);clear IH'.
+ decompose [and] W;clear W.
+ destruct H5;repeat split;trivial.
+ apply le_trans with (1:= H3);trivial.
+ intros p Hlt;rewrite H2, H7;trivial.
+ apply lt_le_trans with (1:=Hlt);trivial.
+ simpl;rewrite H9, andb_true_r.
+ apply (bounded_pexpr_le (fst vm0));auto with arith.
+ simpl;rewrite H6, H11;simpl.
+ rewrite (interp_pexpr_le _ _ H7 _ H4);trivial.
+Qed.
+Transparent build_z_atom.
+
+ Lemma build_pexpr_correct_aux :
+ forall h vm vm' pe,
+ (to_Z h < to_Z (length t_atom))%Z ->
+ Typ.eqb (get_type t_i t_func t_atom h) Typ.TZ ->
+ build_pexpr vm h = (vm',pe) ->
+ wf_vmap vm ->
+ wf_vmap vm' /\
+ (nat_of_P (fst vm) <= nat_of_P (fst vm'))%nat /\
+ (forall p,
+ (nat_of_P p < nat_of_P (fst vm))%nat ->
+ nth_error (snd vm) (nat_of_P (fst vm - p) - 1) =
+ nth_error (snd vm')(nat_of_P (fst vm' - p) - 1)) /\
+ bounded_pexpr (fst vm') pe /\
+ t_interp.[h] = Bval t_i Typ.TZ (Zeval_expr (interp_vmap vm') pe).
+ Proof.
+ unfold build_pexpr.
+ apply foldi_down_cont_ZInd.
+ intros z Hz h vm vm' pe Hh.
+ assert (W:=to_Z_bounded h);rewrite to_Z_0 in Hz.
+ elimtype False;omega.
+ intros i cont Hpos Hlen Hrec.
+ intros h vm vm' pe;unfold is_true;rewrite <-ltb_spec;intros.
+ rewrite t_interp_wf;trivial.
+ apply build_pexpr_atom_aux_correct with cont h i;trivial.
+ intros;apply Hrec;auto.
+ unfold is_true in H3;rewrite ltb_spec in H, H3;omega.
+ unfold wf, is_true in wf_t_atom.
+ rewrite forallbi_spec in wf_t_atom.
+ apply wf_t_atom.
+ rewrite ltb_spec in H;rewrite leb_spec in Hlen;rewrite ltb_spec;omega.
+ unfold wt, is_true in wt_t_atom.
+ rewrite forallbi_spec in wt_t_atom.
+ change (is_true(Typ.eqb (get_type t_i t_func t_atom h) Typ.TZ)) in H0.
+ rewrite Typ.eqb_spec in H0;rewrite <- H0.
+ apply wt_t_atom.
+ rewrite ltb_spec in H;rewrite leb_spec in Hlen;rewrite ltb_spec;omega.
+ Qed.
+
+ Lemma build_pexpr_correct :
+ forall h vm vm' pe,
+ Typ.eqb (get_type t_i t_func t_atom h) Typ.TZ ->
+ build_pexpr vm h = (vm',pe) ->
+ wf_vmap vm ->
+ wf_vmap vm' /\
+ (nat_of_P (fst vm) <= nat_of_P (fst vm'))%nat /\
+ (forall p,
+ (nat_of_P p < nat_of_P (fst vm))%nat ->
+ nth_error (snd vm) (nat_of_P (fst vm - p) - 1) =
+ nth_error (snd vm')(nat_of_P (fst vm' - p) - 1)) /\
+ bounded_pexpr (fst vm') pe /\
+ t_interp.[h] = Bval t_i Typ.TZ (Zeval_expr (interp_vmap vm') pe).
+ Proof.
+ intros.
+ case_eq (h < length t_atom);intros.
+ apply build_pexpr_correct_aux;trivial.
+ rewrite <- ltb_spec;trivial.
+ revert H;unfold get_type,get_type'.
+ rewrite PArray.get_outofbound, default_t_interp.
+ revert H0.
+ unfold build_pexpr.
+ case_eq (0 < length t_atom);intros Heq.
+ rewrite foldi_down_cont_gt;trivial.
+ rewrite PArray.get_outofbound;trivial.
+ Opaque build_z_atom.
+ rewrite def_t_atom;simpl.
+ intros HH H;revert HH H1;apply build_pexpr_atom_aux_correct_z;trivial.
+ rewrite foldi_down_cont_eq;trivial.
+ rewrite PArray.get_outofbound;trivial.
+ rewrite def_t_atom;simpl.
+ intros HH H;revert HH H1;apply build_pexpr_atom_aux_correct_z;trivial.
+ rewrite <- not_true_iff_false, ltb_spec, to_Z_0 in Heq.
+ assert (W:= to_Z_bounded (length t_atom)).
+ apply to_Z_inj;rewrite to_Z_0;omega.
+ rewrite length_t_interp;trivial.
+ Qed.
+Transparent build_z_atom.
+
+ Lemma build_pexpr_atom_correct :
+ forall a vm vm' pe,
+ check_atom a Typ.TZ ->
+ build_pexpr_atom_aux build_pexpr vm a = (vm',pe) ->
+ wf_vmap vm ->
+ wf_vmap vm' /\
+ (nat_of_P (fst vm) <= nat_of_P (fst vm'))%nat /\
+ (forall p,
+ (nat_of_P p < nat_of_P (fst vm))%nat ->
+ nth_error (snd vm) (nat_of_P (fst vm - p) - 1) =
+ nth_error (snd vm')(nat_of_P (fst vm' - p) - 1)) /\
+ bounded_pexpr (fst vm') pe /\
+ interp_atom a = Bval t_i Typ.TZ (Zeval_expr (interp_vmap vm') pe).
+ Proof.
+ apply build_pexpr_atom_aux_correct';apply build_pexpr_correct.
+ Qed.
+
+ Lemma build_formula_atom_correct :
+ forall a vm vm' f t,
+ check_atom a t ->
+ build_formula_atom vm a = Some (vm',f) ->
+ wf_vmap vm ->
+ wf_vmap vm' /\
+ (nat_of_P (fst vm) <= nat_of_P (fst vm'))%nat /\
+ (forall p,
+ (nat_of_P p < nat_of_P (fst vm))%nat ->
+ nth_error (snd vm) (nat_of_P (fst vm - p) - 1) =
+ nth_error (snd vm')(nat_of_P (fst vm' - p) - 1)) /\
+ bounded_formula (fst vm') f /\
+ (interp_bool t_i (interp_atom a) <->Zeval_formula (interp_vmap vm') f).
+ Proof.
+ intros a vm vm' f t.
+ destruct a;simpl;try discriminate.
+ case_eq (build_op2 b);try discriminate.
+ intros o Heq Ht.
+ assert (Typ.eqb Typ.Tbool t && Typ.eqb (get_type t_i t_func t_atom i) Typ.TZ && Typ.eqb (get_type t_i t_func t_atom i0) Typ.TZ).
+ destruct b;try discriminate;trivial.
+ destruct t0;try discriminate;trivial.
+ unfold is_true in H;rewrite !andb_true_iff in H;decompose [and] H;clear H.
+ case_eq (build_pexpr vm i);intros vm0 pe1 Heq1.
+ case_eq (build_pexpr vm0 i0);intros vm1 pe2 Heq2.
+ intros H Hwf;inversion H;clear H;subst.
+ assert (W1:= build_pexpr_correct _ _ _ _ H3 Heq1 Hwf).
+ decompose [and] W1;clear W1.
+ assert (W1:= build_pexpr_correct _ _ _ _ H1 Heq2 H).
+ decompose [and] W1;clear W1.
+ split;trivial.
+ split;[ apply le_trans with (1:= H4);trivial | ].
+ split.
+ intros p Hlt;rewrite H0, H8;trivial.
+ apply lt_le_trans with (1:= Hlt);trivial.
+ split.
+ unfold bounded_formula;simpl;rewrite H10, andb_true_r.
+ apply (bounded_pexpr_le (fst vm0));auto with arith.
+ rewrite (interp_pexpr_le _ _ H8 _ H5) in H7.
+ rewrite H7,H12;destruct b;try discriminate;simpl in Heq |- *;
+ inversion Heq;clear Heq;subst;simpl.
+ symmetry;apply Zlt_is_lt_bool.
+ rewrite Zle_is_le_bool;tauto.
+ rewrite Zge_iff_le.
+ unfold Zge_bool;rewrite <- Zcompare_antisym.
+ rewrite Zle_is_le_bool;unfold Zle_bool.
+ destruct
+ (Zeval_expr (interp_vmap vm') pe2 ?= Zeval_expr (interp_vmap vm') pe1)%Z;
+ simpl;tauto.
+ symmetry;apply Zgt_is_gt_bool.
+ destruct t0;inversion H13;clear H13;subst.
+ simpl.
+ symmetry;apply (Zeq_is_eq_bool (Zeval_expr (interp_vmap vm') pe1) (Zeval_expr (interp_vmap vm') pe2)).
+ Qed.
+
+ Lemma build_formula_correct :
+ forall h' vm vm' f,
+ build_formula vm h' = Some (vm',f) ->
+ wf_vmap vm ->
+ wf_vmap vm' /\
+ (nat_of_P (fst vm) <= nat_of_P (fst vm'))%nat /\
+ (forall p,
+ (nat_of_P p < nat_of_P (fst vm))%nat ->
+ nth_error (snd vm) (nat_of_P (fst vm - p) - 1) =
+ nth_error (snd vm')(nat_of_P (fst vm' - p) - 1)) /\
+ bounded_formula (fst vm') f /\
+ (interp_form_hatom h' <-> Zeval_formula (interp_vmap vm') f).
+ Proof.
+ unfold build_formula;intros h.
+ unfold Atom.interp_form_hatom, Atom.interp_hatom.
+ rewrite t_interp_wf;trivial.
+ intros;apply build_formula_atom_correct with
+ (get_type t_i t_func t_atom h);trivial.
+ unfold wt, is_true in wt_t_atom;rewrite forallbi_spec in wt_t_atom.
+ case_eq (h < length t_atom);intros Heq;unfold get_type;auto.
+ unfold get_type'.
+ rewrite !PArray.get_outofbound, default_t_interp, def_t_atom;trivial; try reflexivity.
+ rewrite length_t_interp;trivial.
+ Qed.
+
+
+ Lemma build_not2_pos_correct : forall vm f l i,
+ bounded_bformula (fst vm) f -> (rho (Lit.blit l) <-> eval_f (Zeval_formula (interp_vmap vm)) f) -> Lit.is_pos l -> bounded_bformula (fst vm) (build_not2 i f) /\ (Form.interp interp_form_hatom t_form (Form.Fnot2 i l) <-> eval_f (Zeval_formula (interp_vmap vm)) (build_not2 i f)).
+ Proof.
+ simpl; intros vm f l i H1 H2 H3; split; unfold build_not2.
+ apply fold_ind; auto.
+ apply (fold_ind2 _ _ (fun b f' => b = true <-> eval_f (Zeval_formula (interp_vmap vm)) f')).
+ unfold Lit.interp; rewrite H3; auto.
+ intros b f' H4; rewrite negb_involutive; simpl; split.
+ intros Hb H5; apply H5; rewrite <- H4; auto.
+ intro H5; case_eq b; auto; intro H6; elim H5; intro H7; rewrite <- H4 in H7; rewrite H7 in H6; discriminate.
+ Qed.
+
+
+ Lemma build_not2_neg_correct : forall vm f l i,
+ bounded_bformula (fst vm) f -> (rho (Lit.blit l) <-> eval_f (Zeval_formula (interp_vmap vm)) f) -> Lit.is_pos l = false -> bounded_bformula (fst vm) (N (build_not2 i f)) /\ (Form.interp interp_form_hatom t_form (Form.Fnot2 i l) <-> eval_f (Zeval_formula (interp_vmap vm)) (N (build_not2 i f))).
+ Proof.
+ simpl; intros vm f l i H1 H2 H3; split; unfold build_not2.
+ apply fold_ind; auto.
+ apply (fold_ind2 _ _ (fun b f' => b = true <-> ~ eval_f (Zeval_formula (interp_vmap vm)) f')).
+ unfold Lit.interp; rewrite H3; unfold Var.interp; split.
+ intros H4 H5; rewrite <- H2 in H5; rewrite H5 in H4; discriminate.
+ intro H4; case_eq (rho (Lit.blit l)); auto; intro H5; elim H4; rewrite <- H2; auto.
+ intros b f' H4; rewrite negb_involutive; simpl; split.
+ intros Hb H5; apply H5; rewrite <- H4; auto.
+ intro H5; case_eq b; auto; intro H6; elim H5; intro H7; rewrite <- H4 in H7; rewrite H7 in H6; discriminate.
+ Qed.
+
+
+ Lemma bounded_bformula_le :
+ forall p p',
+ (nat_of_P p <= nat_of_P p')%nat ->
+ forall bf,
+ bounded_bformula p bf -> bounded_bformula p' bf.
+ Proof.
+ unfold is_true;induction bf;simpl;trivial.
+ destruct a;unfold bounded_formula;simpl.
+ rewrite andb_true_iff;intros (H1, H2).
+ rewrite (bounded_pexpr_le _ _ H _ H1), (bounded_pexpr_le _ _ H _ H2);trivial.
+ rewrite !andb_true_iff;intros (H1, H2);auto.
+ rewrite !andb_true_iff;intros (H1, H2);auto.
+ rewrite !andb_true_iff;intros (H1, H2);auto.
+ Qed.
+
+ Lemma interp_bformula_le :
+ forall vm vm',
+ (forall (p : positive),
+ (nat_of_P p < nat_of_P (fst vm))%nat ->
+ nth_error (snd vm) (nat_of_P (fst vm - p) - 1) =
+ nth_error (snd vm') (nat_of_P (fst vm' - p) - 1)) ->
+ forall bf,
+ bounded_bformula (fst vm) bf ->
+ (eval_f (Zeval_formula (interp_vmap vm)) bf <->
+ eval_f (Zeval_formula (interp_vmap vm')) bf).
+ Proof.
+ intros vm vm' Hnth.
+ unfold is_true;induction bf;simpl;try tauto.
+ destruct a;unfold bounded_formula;simpl.
+ rewrite andb_true_iff;intros (H1, H2).
+ rewrite !(interp_pexpr_le _ _ Hnth);tauto.
+ rewrite andb_true_iff;intros (H1,H2);rewrite IHbf1, IHbf2;tauto.
+ rewrite andb_true_iff;intros (H1,H2);rewrite IHbf1, IHbf2;tauto.
+ rewrite andb_true_iff;intros (H1,H2);rewrite IHbf1, IHbf2;tauto.
+ Qed.
+
+
+ Lemma build_hform_correct :
+ forall (build_var : vmap -> var -> option (vmap*BFormula (Formula Z))),
+ (forall v vm vm' bf,
+ build_var vm v = Some (vm', bf) ->
+ wf_vmap vm ->
+ wf_vmap vm' /\
+ (nat_of_P (fst vm) <= nat_of_P (fst vm'))%nat /\
+ (forall p,
+ (nat_of_P p < nat_of_P (fst vm))%nat ->
+ nth_error (snd vm) (nat_of_P (fst vm - p) - 1) =
+ nth_error (snd vm')(nat_of_P (fst vm' - p) - 1)) /\
+ bounded_bformula (fst vm') bf /\
+ (Var.interp rho v <-> eval_f (Zeval_formula (interp_vmap vm')) bf)) ->
+ forall f vm vm' bf,
+ build_hform build_var vm f = Some (vm', bf) ->
+ wf_vmap vm ->
+ wf_vmap vm' /\
+ (nat_of_P (fst vm) <= nat_of_P (fst vm'))%nat /\
+ (forall p,
+ (nat_of_P p < nat_of_P (fst vm))%nat ->
+ nth_error (snd vm) (nat_of_P (fst vm - p) - 1) =
+ nth_error (snd vm')(nat_of_P (fst vm' - p) - 1)) /\
+ bounded_bformula (fst vm') bf /\
+ (Form.interp interp_form_hatom t_form f <-> eval_f (Zeval_formula (interp_vmap vm')) bf).
+ Proof.
+ unfold build_hform; intros build_var Hbv [h| | |i l|l|l|l|a b|a b|a b c] vm vm' bf; try discriminate.
+ (* Fatom *)
+ case_eq (build_formula vm h); try discriminate; intros [vm0 f] Heq H1 H2; inversion H1; subst vm0; subst bf; apply build_formula_correct; auto.
+ (* Ftrue *)
+ intros H H1; inversion H; subst vm'; subst bf; split; auto; split; [omega| ]; do 4 split; auto.
+ (* Ffalse *)
+ intros H H1; inversion H; subst vm'; subst bf; split; auto; split; [omega| ]; do 3 (split; auto); discriminate.
+ (* Fnot2 *)
+ case_eq (build_var vm (Lit.blit l)); try discriminate; intros [vm0 f] Heq H H1; inversion H; subst vm0; subst bf; destruct (Hbv _ _ _ _ Heq H1) as [H2 [H3 [H4 [H5 H6]]]]; do 3 (split; auto); case_eq (Lit.is_pos l); [apply build_not2_pos_correct|apply build_not2_neg_correct]; auto.
+ (* Fand *)
+ simpl; unfold afold_left; case (length l == 0).
+ intro H; inversion H; subst vm'; subst bf; simpl; intro H1; split; auto; split; [omega| ]; do 3 (split; auto).
+ revert vm' bf; apply (foldi_ind2 _ _ (fun f1 b => forall vm' bf, f1 = Some (vm', bf) -> wf_vmap vm -> wf_vmap vm' /\ (Pos.to_nat (fst vm) <= Pos.to_nat (fst vm'))%nat /\ (forall p : positive, (Pos.to_nat p < Pos.to_nat (fst vm))%nat -> nth_error (snd vm) (Pos.to_nat (fst vm - p) - 1) = nth_error (snd vm') (Pos.to_nat (fst vm' - p) - 1)) /\ bounded_bformula (fst vm') bf /\ (b = true <-> eval_f (Zeval_formula (interp_vmap vm')) bf))).
+ intros vm' bf; case_eq (build_var vm (Lit.blit (l .[ 0]))); try discriminate; intros [vm0 f] Heq; case_eq (Lit.is_pos (l .[ 0])); intros Heq2 H1 H2; inversion H1; subst vm'; subst bf; destruct (Hbv _ _ _ _ Heq H2) as [H10 [H11 [H12 [H13 H14]]]]; do 4 (split; auto); unfold Lit.interp; rewrite Heq2; auto; simpl; split.
+ intros H3 H4; rewrite <- H14 in H4; rewrite H4 in H3; discriminate.
+ intro H3; case_eq (Var.interp rho (Lit.blit (l .[ 0]))); auto; intro H4; elim H3; rewrite <- H14; auto.
+ intros i a b _ H1; case a; try discriminate; intros [vm0 f0] IH vm' bf; case_eq (build_var vm0 (Lit.blit (l .[ i]))); try discriminate; intros [vm1 f1] Heq H2 H3; inversion H2; subst vm'; subst bf; destruct (IH _ _ (refl_equal (Some (vm0, f0))) H3) as [H5 [H6 [H7 [H8 H9]]]]; destruct (Hbv _ _ _ _ Heq H5) as [H10 [H11 [H12 [H13 H14]]]]; split; auto; split; [eauto with arith| ]; split.
+ intros p H15; rewrite H7; auto; apply H12; eauto with arith.
+ split.
+ simpl; rewrite (bounded_bformula_le _ _ H11 _ H8); case (Lit.is_pos (l .[ i])); rewrite H13; auto.
+ simpl; rewrite (interp_bformula_le _ _ H12 _ H8) in H9; rewrite <- H9; case_eq (Lit.is_pos (l .[ i])); intro Heq2; simpl; rewrite <- H14; unfold Lit.interp; rewrite Heq2; split; case (Var.interp rho (Lit.blit (l .[ i]))); try rewrite andb_true_r; try rewrite andb_false_r; try (intros; split; auto); try discriminate; intros [H20 H21]; auto.
+ (* For *)
+ simpl; unfold afold_left; case (length l == 0).
+ intro H; inversion H; subst vm'; subst bf; simpl; intro H1; split; auto; split; [omega| ]; do 3 (split; auto); discriminate.
+ revert vm' bf; apply (foldi_ind2 _ _ (fun f1 b => forall vm' bf, f1 = Some (vm', bf) -> wf_vmap vm -> wf_vmap vm' /\ (Pos.to_nat (fst vm) <= Pos.to_nat (fst vm'))%nat /\ (forall p : positive, (Pos.to_nat p < Pos.to_nat (fst vm))%nat -> nth_error (snd vm) (Pos.to_nat (fst vm - p) - 1) = nth_error (snd vm') (Pos.to_nat (fst vm' - p) - 1)) /\ bounded_bformula (fst vm') bf /\ (b = true <-> eval_f (Zeval_formula (interp_vmap vm')) bf))).
+ intros vm' bf; case_eq (build_var vm (Lit.blit (l .[ 0]))); try discriminate; intros [vm0 f] Heq; case_eq (Lit.is_pos (l .[ 0])); intros Heq2 H1 H2; inversion H1; subst vm'; subst bf; destruct (Hbv _ _ _ _ Heq H2) as [H10 [H11 [H12 [H13 H14]]]]; do 4 (split; auto); unfold Lit.interp; rewrite Heq2; auto; simpl; split.
+ intros H3 H4; rewrite <- H14 in H4; rewrite H4 in H3; discriminate.
+ intro H3; case_eq (Var.interp rho (Lit.blit (l .[ 0]))); auto; intro H4; elim H3; rewrite <- H14; auto.
+ intros i a b _ H1; case a; try discriminate; intros [vm0 f0] IH vm' bf; case_eq (build_var vm0 (Lit.blit (l .[ i]))); try discriminate; intros [vm1 f1] Heq H2 H3; inversion H2; subst vm'; subst bf; destruct (IH _ _ (refl_equal (Some (vm0, f0))) H3) as [H5 [H6 [H7 [H8 H9]]]]; destruct (Hbv _ _ _ _ Heq H5) as [H10 [H11 [H12 [H13 H14]]]]; split; auto; split; [eauto with arith| ]; split.
+ intros p H15; rewrite H7; auto; apply H12; eauto with arith.
+ split.
+ simpl; rewrite (bounded_bformula_le _ _ H11 _ H8); case (Lit.is_pos (l .[ i])); rewrite H13; auto.
+ simpl; rewrite (interp_bformula_le _ _ H12 _ H8) in H9; rewrite <- H9; case_eq (Lit.is_pos (l .[ i])); intro Heq2; simpl; rewrite <- H14; unfold Lit.interp; rewrite Heq2; split; case (Var.interp rho (Lit.blit (l .[ i]))); try rewrite orb_false_r; try rewrite orb_true_r; auto; try (intros [H20|H20]; auto; discriminate); right; intro H20; discriminate.
+ (* Fimp *)
+ simpl; unfold afold_right; case (length l == 0).
+ intro H; inversion H; subst vm'; subst bf; simpl; intro H1; split; auto; split; [omega| ]; do 3 (split; auto).
+ case (length l <= 1).
+ case_eq (build_var vm (Lit.blit (l .[ 0]))); try discriminate; intros [vm0 f] Heq; case_eq (Lit.is_pos (l .[ 0])); intros Heq2 H1 H2; inversion H1; subst vm'; subst bf; destruct (Hbv _ _ _ _ Heq H2) as [H3 [H4 [H5 [H6 H7]]]]; do 4 (split; auto); unfold Lit.interp; rewrite Heq2; auto; simpl; split.
+ intros H8 H9; rewrite <- H7 in H9; rewrite H9 in H8; discriminate.
+ intro H8; case_eq (Var.interp rho (Lit.blit (l .[ 0]))); auto; intro H9; rewrite H7 in H9; elim H8; auto.
+ revert vm' bf; apply (foldi_down_ind2 _ _ (fun f1 b => forall vm' bf, f1 = Some (vm', bf) -> wf_vmap vm -> wf_vmap vm' /\ (Pos.to_nat (fst vm) <= Pos.to_nat (fst vm'))%nat /\ (forall p : positive, (Pos.to_nat p < Pos.to_nat (fst vm))%nat -> nth_error (snd vm) (Pos.to_nat (fst vm - p) - 1) = nth_error (snd vm') (Pos.to_nat (fst vm' - p) - 1)) /\ bounded_bformula (fst vm') bf /\ (b = true <-> eval_f (Zeval_formula (interp_vmap vm')) bf))).
+ intros vm' bf; case_eq (build_var vm (Lit.blit (l .[ length l - 1]))); try discriminate; intros [vm0 f] Heq; case_eq (Lit.is_pos (l .[ length l - 1])); intros Heq2 H1 H2; inversion H1; subst vm'; subst bf; destruct (Hbv _ _ _ _ Heq H2) as [H10 [H11 [H12 [H13 H14]]]]; do 4 (split; auto); unfold Lit.interp; rewrite Heq2; auto; simpl; split.
+ intros H3 H4; rewrite <- H14 in H4; rewrite H4 in H3; discriminate.
+ intro H3; case_eq (Var.interp rho (Lit.blit (l .[ length l - 1]))); auto; intro H4; elim H3; rewrite <- H14; auto.
+ intros i a b _ H1; case a; try discriminate; intros [vm0 f0] IH vm' bf; case_eq (build_var vm0 (Lit.blit (l .[ i]))); try discriminate; intros [vm1 f1] Heq H2 H3; inversion H2; subst vm'; subst bf; destruct (IH _ _ (refl_equal (Some (vm0, f0))) H3) as [H5 [H6 [H7 [H8 H9]]]]; destruct (Hbv _ _ _ _ Heq H5) as [H10 [H11 [H12 [H13 H14]]]]; split; auto; split; [eauto with arith| ]; split.
+ intros p H15; rewrite H7; auto; apply H12; eauto with arith.
+ split.
+ simpl; rewrite (bounded_bformula_le _ _ H11 _ H8); case (Lit.is_pos (l .[ i])); rewrite H13; auto.
+ simpl; rewrite (interp_bformula_le _ _ H12 _ H8) in H9; rewrite <- H9; case_eq (Lit.is_pos (l .[ i])); intro Heq2; simpl; rewrite <- H14; unfold Lit.interp; rewrite Heq2; split; case (Var.interp rho (Lit.blit (l .[ i]))); auto; try discriminate; simpl; intro H; apply H; discriminate.
+ (* Fxor *)
+ simpl; case_eq (build_var vm (Lit.blit a)); try discriminate; intros [vm1 f1] Heq1; case_eq (build_var vm1 (Lit.blit b)); try discriminate; intros [vm2 f2] Heq2 H1 H2; inversion H1; subst vm'; subst bf; destruct (Hbv _ _ _ _ Heq1 H2) as [H3 [H4 [H5 [H6 H7]]]]; destruct (Hbv _ _ _ _ Heq2 H3) as [H8 [H9 [H10 [H11 H12]]]]; split; auto; split; [eauto with arith| ]; split.
+ intros p H18; rewrite H5; auto; rewrite H10; eauto with arith.
+ split.
+ case (Lit.is_pos a); case (Lit.is_pos b); simpl; rewrite H11; rewrite (bounded_bformula_le _ _ H9 _ H6); auto.
+ simpl; rewrite (interp_bformula_le _ _ H10 _ H6) in H7; case_eq (Lit.is_pos a); intro Ha; case_eq (Lit.is_pos b); intro Hb; unfold Lit.interp; rewrite Ha, Hb; simpl; rewrite <- H12; rewrite <- H7; (case (Var.interp rho (Lit.blit a)); case (Var.interp rho (Lit.blit b))); split; auto; try discriminate; simpl.
+ intros [_ [H20|H20]]; elim H20; reflexivity.
+ intros _; split; [left; reflexivity|right; intro H20; discriminate].
+ intros _; split; [right; reflexivity|left; intro H20; discriminate].
+ intros [[H20|H20] _]; discriminate.
+ intros [_ [H20|H20]]; elim H20; [reflexivity|discriminate].
+ intros [[H20|H20] _]; [discriminate|elim H20; reflexivity].
+ intros _; split; [right|left]; discriminate.
+ intros [[H20|H20] _]; [elim H20; reflexivity|discriminate].
+ intros [_ [H20|H20]]; elim H20; [discriminate|reflexivity].
+ intros _; split; [left|right]; discriminate.
+ intros [[H20|H20] _]; elim H20; reflexivity.
+ intros _; split; [right; discriminate|left; intro H21; apply H21; reflexivity].
+ intros _; split; [left; discriminate|right; intro H21; apply H21; reflexivity].
+ intros [_ [H20|H20]]; elim H20; discriminate.
+ (* Fiff *)
+ simpl; case_eq (build_var vm (Lit.blit a)); try discriminate; intros [vm1 f1] Heq1; case_eq (build_var vm1 (Lit.blit b)); try discriminate; intros [vm2 f2] Heq2 H1 H2; inversion H1; subst vm'; subst bf; destruct (Hbv _ _ _ _ Heq1 H2) as [H3 [H4 [H5 [H6 H7]]]]; destruct (Hbv _ _ _ _ Heq2 H3) as [H8 [H9 [H10 [H11 H12]]]]; split; auto; split; [eauto with arith| ]; split.
+ intros p H18; rewrite H5; auto; rewrite H10; eauto with arith.
+ split.
+ case (Lit.is_pos a); case (Lit.is_pos b); simpl; rewrite H11; rewrite (bounded_bformula_le _ _ H9 _ H6); auto.
+ simpl; rewrite (interp_bformula_le _ _ H10 _ H6) in H7; case_eq (Lit.is_pos a); intro Ha; case_eq (Lit.is_pos b); intro Hb; unfold Lit.interp; rewrite Ha, Hb; simpl; rewrite <- H12; rewrite <- H7; (case (Var.interp rho (Lit.blit a)); case (Var.interp rho (Lit.blit b))); split; auto; try discriminate; simpl.
+ intros [_ [H20|H20]]; [elim H20; reflexivity|discriminate].
+ intros [[H20|H20] _]; [discriminate|elim H20; reflexivity].
+ intros _; split; [right|left]; discriminate.
+ intros [_ [H20|H20]]; elim H20; reflexivity.
+ intros _; split; [left; reflexivity|right; discriminate].
+ intros _; split; [right; intro H20; apply H20; reflexivity|left; discriminate].
+ intros [[H20|H20] _]; [ |elim H20]; discriminate.
+ intros [[H20|H20] _]; elim H20; reflexivity.
+ intros _; split; [right; discriminate|left; intro H20; apply H20; reflexivity].
+ intros _; split; [left; discriminate|right; reflexivity].
+ intros [_ [H20|H20]]; [elim H20| ]; discriminate.
+ intros [[H20|H20] _]; elim H20; [reflexivity|discriminate].
+ intros [_ [H20|H20]]; elim H20; [discriminate|reflexivity].
+ intros _; split; [left|right]; discriminate.
+ (* Fite *)
+ simpl; case_eq (build_var vm (Lit.blit a)); try discriminate; intros [vm1 f1] Heq1; case_eq (build_var vm1 (Lit.blit b)); try discriminate; intros [vm2 f2] Heq2; case_eq (build_var vm2 (Lit.blit c)); try discriminate; intros [vm3 f3] Heq3 H1 H2; inversion H1; subst vm'; subst bf; destruct (Hbv _ _ _ _ Heq1 H2) as [H3 [H4 [H5 [H6 H7]]]]; destruct (Hbv _ _ _ _ Heq2 H3) as [H8 [H9 [H10 [H11 H12]]]]; destruct (Hbv _ _ _ _ Heq3 H8) as [H13 [H14 [H15 [H16 H17]]]]; split; auto; split; [eauto with arith| ]; split.
+ intros p H18; rewrite H5; auto; rewrite H10; eauto with arith.
+ assert (H18: (Pos.to_nat (fst vm1) <= Pos.to_nat (fst vm3))%nat) by eauto with arith.
+ split.
+ case (Lit.is_pos a); case (Lit.is_pos b); case (Lit.is_pos c); simpl; rewrite H16; rewrite (bounded_bformula_le _ _ H14 _ H11); rewrite (bounded_bformula_le _ _ H18 _ H6); auto.
+ simpl; rewrite (interp_bformula_le _ _ H15 _ H11) in H12; rewrite (interp_bformula_le _ vm3) in H7; [ |intros p Hp; rewrite H10; eauto with arith|auto]; case_eq (Lit.is_pos a); intro Ha; case_eq (Lit.is_pos b); intro Hb; case_eq (Lit.is_pos c); intro Hc; unfold Lit.interp; rewrite Ha, Hb, Hc; simpl; rewrite <- H17; rewrite <- H12; rewrite <- H7; (case (Var.interp rho (Lit.blit a)); [case (Var.interp rho (Lit.blit b))|case (Var.interp rho (Lit.blit c))]); split; auto; try discriminate; try (intros [[H20 H21]|[H20 H21]]; auto); try (intros _; left; split; auto; discriminate); try (intros _; right; split; auto; discriminate); try (elim H20; discriminate); try (elim H21; discriminate); try (simpl; intro H; left; split; auto; discriminate); try (revert H; case (Var.interp rho (Lit.blit c)); discriminate); try (revert H; case (Var.interp rho (Lit.blit b)); discriminate); try (intro H20; rewrite H20 in H; discriminate); simpl.
+ intro H; right; split; auto.
+ intro H; right; split; auto.
+ intro H; right; split; auto.
+ intro H20; rewrite H20 in H; discriminate.
+ revert H21; case (Var.interp rho (Lit.blit c)); auto.
+ right; split; auto; intro H20; rewrite H20 in H; discriminate.
+ revert H21; case (Var.interp rho (Lit.blit c)); auto.
+ intro H; right; split; auto.
+ intro H; right; split; auto.
+ intro H; left; split; try discriminate; revert H; case (Var.interp rho (Lit.blit b)); discriminate.
+ revert H21; case (Var.interp rho (Lit.blit b)); auto.
+ intro H; left; split; try discriminate; revert H; case (Var.interp rho (Lit.blit b)); discriminate.
+ revert H21; case (Var.interp rho (Lit.blit b)); auto.
+ intro H; right; split; auto; revert H; case (Var.interp rho (Lit.blit c)); discriminate.
+ revert H21; case (Var.interp rho (Lit.blit c)); auto.
+ intro H; right; split; auto; revert H; case (Var.interp rho (Lit.blit c)); discriminate.
+ revert H21; case (Var.interp rho (Lit.blit c)); auto.
+ intro H; left; split; auto; revert H; case (Var.interp rho (Lit.blit b)); discriminate.
+ revert H21; case (Var.interp rho (Lit.blit b)); auto.
+ intro H; left; split; auto; revert H; case (Var.interp rho (Lit.blit b)); discriminate.
+ revert H21; case (Var.interp rho (Lit.blit b)); auto.
+ Qed.
+
+
+ Lemma build_var_correct : forall v vm vm' bf,
+ build_var vm v = Some (vm', bf) ->
+ wf_vmap vm ->
+ wf_vmap vm' /\
+ (nat_of_P (fst vm) <= nat_of_P (fst vm'))%nat /\
+ (forall p,
+ (nat_of_P p < nat_of_P (fst vm))%nat ->
+ nth_error (snd vm) (nat_of_P (fst vm - p) - 1) =
+ nth_error (snd vm')(nat_of_P (fst vm' - p) - 1)) /\
+ bounded_bformula (fst vm') bf /\
+ (Var.interp rho v <-> eval_f (Zeval_formula (interp_vmap vm')) bf).
+ Proof.
+ unfold build_var; apply foldi_down_cont_ind; try discriminate.
+ intros i cont _ Hlen Hrec v vm vm' bf; unfold is_true; intros H1 H2; replace (Var.interp rho v) with (Form.interp interp_form_hatom t_form (t_form.[v])).
+ apply (build_hform_correct cont); auto.
+ unfold Var.interp; rewrite <- wf_interp_form; auto.
+ Qed.
+
+
+ Lemma build_form_correct : forall f vm vm' bf,
+ build_form vm f = Some (vm', bf) ->
+ wf_vmap vm ->
+ wf_vmap vm' /\
+ (nat_of_P (fst vm) <= nat_of_P (fst vm'))%nat /\
+ (forall p,
+ (nat_of_P p < nat_of_P (fst vm))%nat ->
+ nth_error (snd vm) (nat_of_P (fst vm - p) - 1) =
+ nth_error (snd vm')(nat_of_P (fst vm' - p) - 1)) /\
+ bounded_bformula (fst vm') bf /\
+ (Form.interp interp_form_hatom t_form f <-> eval_f (Zeval_formula (interp_vmap vm')) bf).
+ Proof. apply build_hform_correct; apply build_var_correct. Qed.
+
+
+ Lemma build_nlit_correct : forall l vm vm' bf,
+ build_nlit vm l = Some (vm', bf) ->
+ wf_vmap vm ->
+ wf_vmap vm' /\
+ (nat_of_P (fst vm) <= nat_of_P (fst vm'))%nat /\
+ (forall p,
+ (nat_of_P p < nat_of_P (fst vm))%nat ->
+ nth_error (snd vm) (nat_of_P (fst vm - p) - 1) =
+ nth_error (snd vm')(nat_of_P (fst vm' - p) - 1)) /\
+ bounded_bformula (fst vm') bf /\
+ (negb (Lit.interp rho l) <-> eval_f (Zeval_formula (interp_vmap vm')) bf).
+ Proof.
+ unfold build_nlit; intros l vm vm' bf; case_eq (build_form vm (t_form .[ Lit.blit (Lit.neg l)])); try discriminate.
+ intros [vm1 f] Heq H1 H2; inversion H1; subst vm1; subst bf; case_eq (Lit.is_pos (Lit.neg l)); intro Heq2.
+ replace (negb (Lit.interp rho l)) with (Form.interp interp_form_hatom t_form (t_form .[ Lit.blit (Lit.neg l)])).
+ apply build_form_correct; auto.
+ unfold Lit.interp; replace (Lit.is_pos l) with false.
+ rewrite negb_involutive; unfold Var.interp; rewrite <- wf_interp_form; auto; rewrite Lit.blit_neg; auto.
+ rewrite Lit.is_pos_neg in Heq2; case_eq (Lit.is_pos l); auto; intro H; rewrite H in Heq2; discriminate.
+ simpl; destruct (build_form_correct (t_form .[ Lit.blit (Lit.neg l)]) vm vm' f Heq H2) as [H3 [H4 [H5 [H6 [H7 H8]]]]]; do 4 (split; auto); split.
+ intros H9 H10; pose (H11 := H8 H10); unfold Lit.interp in H9; replace (Lit.is_pos l) with true in H9.
+ unfold Var.interp in H9; rewrite <- wf_interp_form in H11; auto; rewrite Lit.blit_neg in H11; rewrite H11 in H9; discriminate.
+ rewrite Lit.is_pos_neg in Heq2; case_eq (Lit.is_pos l); auto; intro H; rewrite H in Heq2; discriminate.
+ intro H9; case_eq (Lit.interp rho l); intro Heq3; auto; elim H9; apply H7; unfold Lit.interp in Heq3; replace (Lit.is_pos l) with true in Heq3.
+ unfold Var.interp in Heq3; rewrite <- wf_interp_form; auto; rewrite Lit.blit_neg; auto.
+ rewrite Lit.is_pos_neg in Heq2; case_eq (Lit.is_pos l); auto; intro H; rewrite H in Heq2; discriminate.
+ Qed.
+
+
+ Lemma build_clause_aux_correct :
+ forall cl vm vm' bf,
+ build_clause_aux vm cl = Some (vm',bf) ->
+ wf_vmap vm ->
+ wf_vmap vm' /\
+ (nat_of_P (fst vm) <= nat_of_P (fst vm'))%nat /\
+ (forall p,
+ (nat_of_P p < nat_of_P (fst vm))%nat ->
+ nth_error (snd vm) (nat_of_P (fst vm - p) - 1) =
+ nth_error (snd vm')(nat_of_P (fst vm' - p) - 1)) /\
+ bounded_bformula (fst vm') bf /\
+ (negb (C.interp rho cl) <-> eval_f (Zeval_formula (interp_vmap vm')) bf).
+ Proof.
+ induction cl;try discriminate.
+ case_eq cl.
+ intros _; simpl;intros;rewrite orb_false_r;apply build_nlit_correct;trivial.
+ intros i l Heq vm vm' bf;rewrite <- Heq at 2.
+ change (build_clause_aux vm (a :: i :: l) ) with
+ ( match build_nlit vm a with
+ | Some (vm0, bf1) =>
+ match build_clause_aux vm0 (i::l) with
+ | Some (vm1, bf2) => Some (vm1, Cj bf1 bf2)
+ | None => None
+ end
+ | None => None
+ end).
+ case_eq (build_nlit vm a);try discriminate.
+ intros (vm0, bf1) Heq1 Heq2 Hwf.
+ rewrite <- Heq in Heq2.
+ assert (W:= build_nlit_correct _ _ _ _ Heq1 Hwf).
+ decompose [and] W;clear W.
+ revert Heq2; case_eq (build_clause_aux vm0 cl);try discriminate.
+ intros (vm1, fb2) Heq2 W;inversion W;clear W Heq;subst.
+ assert (W:= IHcl _ _ _ Heq2 H);decompose [and] W;clear W.
+ split;trivial.
+ split.
+ apply le_trans with (1:= H1);trivial.
+ split.
+ intros p Hlt;rewrite H0, H5;trivial.
+ apply lt_le_trans with (1:= Hlt);trivial.
+ split.
+ simpl;rewrite H7, andb_true_r.
+ apply bounded_bformula_le with (2:= H2);trivial.
+ simpl.
+ unfold is_true;
+ rewrite <- (interp_bformula_le _ _ H5), <- H4, <- H9, negb_orb,andb_true_iff;
+ tauto.
+ Qed.
+
+ Lemma build_clause_correct :
+ forall cl vm vm' bf,
+ build_clause vm cl = Some (vm',bf) ->
+ wf_vmap vm ->
+ wf_vmap vm' /\
+ (nat_of_P (fst vm) <= nat_of_P (fst vm'))%nat /\
+ (forall p,
+ (nat_of_P p < nat_of_P (fst vm))%nat ->
+ nth_error (snd vm) (nat_of_P (fst vm - p) - 1) =
+ nth_error (snd vm')(nat_of_P (fst vm' - p) - 1)) /\
+ bounded_bformula (fst vm') bf /\
+ (C.interp rho cl <-> eval_f (Zeval_formula (interp_vmap vm')) bf).
+ Proof.
+ unfold build_clause;intros cl vm vm' bf.
+ case_eq (build_clause_aux vm cl);try discriminate.
+ intros (vm1, bf1) Heq W Hwf;inversion W;clear W;subst.
+ assert (W:= build_clause_aux_correct _ _ _ _ Heq Hwf).
+ decompose [and] W;clear W.
+ repeat (split;[trivial;fail | ]).
+ split;simpl.
+ rewrite H2;reflexivity.
+ unfold is_true in *;
+ destruct (C.interp rho cl);split;simpl;trivial;try discriminate;
+ try tauto.
+ intros _ HH;destruct H4.
+ apply H4 in HH;discriminate.
+ Qed.
+
+ Local Notation hinterp := (Atom.interp_hatom t_i t_func t_atom).
+ Local Notation interp := (Atom.interp t_i t_func t_atom).
+
+ Lemma get_eq_interp :
+ forall (l:_lit) (f:Atom.hatom -> Atom.hatom -> C.t),
+ (forall xa, t_form.[Lit.blit l] = Form.Fatom xa ->
+ forall t a b, t_atom.[xa] = Atom.Abop (Atom.BO_eq t) a b ->
+ Lit.is_pos l ->
+ rho (Lit.blit l) =
+ Atom.interp_bool t_i
+ (Atom.apply_binop t_i t t Typ.Tbool (Typ.i_eqb t_i t)
+ (hinterp a) (hinterp b)) ->
+ Typ.eqb (get_type t_i t_func t_atom a) t -> Typ.eqb (get_type t_i t_func t_atom b) t ->
+ C.interp rho (f a b)) ->
+ C.interp rho (get_eq l f).
+ Proof.
+ intros l f Hf;unfold get_eq.
+ destruct (Lit.is_pos l); case_eq (t_form.[Lit.blit l]);trivial;intros;
+ try(case_eq (t_atom.[i]);trivial;intros); try (apply valid_C_true; trivial).
+ destruct b; try (apply valid_C_true; trivial).
+ generalize wt_t_atom;unfold Atom.wt;unfold is_true;
+ rewrite PArray.forallbi_spec;intros.
+ assert (i < length t_atom).
+ apply PArray.get_not_default_lt.
+ rewrite H0, def_t_atom;discriminate.
+ apply H1 in H2;clear H1;rewrite H0 in H2;simpl in H2.
+ rewrite !andb_true_iff in H2;decompose [and] H2;clear H2.
+ apply Hf with (2:= H0);trivial. auto.
+ rewrite wf_interp_form, H;simpl.
+ unfold Atom.interp_form_hatom, Atom.interp_hatom at 1;simpl.
+ rewrite Atom.t_interp_wf, H0;simpl;trivial.
+ trivial.
+ Qed.
+
+ Lemma get_not_le_interp :
+ forall (l:_lit) (f:Atom.hatom -> Atom.hatom -> C.t),
+ (forall xa, t_form.[Lit.blit l] = Form.Fatom xa ->
+ forall a b, t_atom.[xa] = Atom.Abop Atom.BO_Zle a b ->
+ negb (Lit.is_pos l) ->
+ rho (Lit.blit l) =
+ Atom.interp_bool t_i
+ (Atom.apply_binop t_i Typ.TZ Typ.TZ Typ.Tbool Zle_bool
+ (hinterp a) (hinterp b)) ->
+ Typ.eqb (get_type t_i t_func t_atom a) Typ.TZ -> Typ.eqb (get_type t_i t_func t_atom b) Typ.TZ ->
+ C.interp rho (f a b)) ->
+ C.interp rho (get_not_le l f).
+ Proof.
+ intros l f Hf;unfold get_not_le.
+ destruct (Lit.is_pos l); case_eq (t_form.[Lit.blit l]);trivial;intros;
+ try(case_eq (t_atom.[i]);trivial;intros); try (apply valid_C_true; trivial).
+ destruct b; try (apply valid_C_true; trivial).
+ generalize wt_t_atom;unfold Atom.wt;unfold is_true;
+ rewrite PArray.forallbi_spec;intros.
+ assert (i < length t_atom).
+ apply PArray.get_not_default_lt.
+ rewrite H0, def_t_atom;discriminate.
+ apply H1 in H2;clear H1;rewrite H0 in H2;simpl in H2.
+ rewrite !andb_true_iff in H2;decompose [and] H2;clear H2.
+ simpl; apply Hf with (2:= H0);trivial. auto.
+ rewrite wf_interp_form, H;simpl.
+ unfold Atom.interp_form_hatom, Atom.interp_hatom at 1;simpl.
+ rewrite Atom.t_interp_wf, H0;simpl;trivial.
+ trivial.
+ Qed.
+
+
+ Lemma interp_binop_eqb_antisym:
+ forall a b va vb,
+ interp_atom a = Bval t_i Typ.TZ va -> interp_atom b = Bval t_i Typ.TZ vb ->
+ (interp_bool t_i
+ (apply_binop t_i Typ.TZ Typ.TZ Typ.Tbool (Typ.i_eqb t_i Typ.TZ)
+ (interp a) (interp b)) = false) ->
+ negb
+ (interp_bool t_i
+ (apply_binop t_i Typ.TZ Typ.TZ Typ.Tbool Z.leb
+ (interp a) (interp b))) = false ->
+ negb
+ (interp_bool t_i
+ (apply_binop t_i Typ.TZ Typ.TZ Typ.Tbool Z.leb
+ (interp b) (interp a))) = false ->
+ False.
+ Proof.
+ intros a b va vb HHa HHb.
+ unfold Atom.interp, Atom.interp_hatom.
+ rewrite HHa, HHb; simpl.
+ intros.
+ case_eq (va <=? vb); intros; subst.
+ case_eq (vb <=? va); intros; subst.
+ apply Zle_bool_imp_le in H2.
+ apply Zle_bool_imp_le in H3.
+ apply Zeq_bool_neq in H.
+ (*pour la beauté du geste!*) lia.
+ rewrite H3 in H1; simpl in H1; elim diff_true_false; trivial.
+ rewrite H2 in H0; simpl in H1; elim diff_true_false; trivial.
+ Qed.
+
+
+ Lemma valid_check_micromega :
+ forall cl c, C.valid rho (check_micromega cl c).
+ Proof.
+ unfold check_micromega; intros cl c.
+ case_eq (build_clause empty_vmap cl).
+ intros (vm1, bf) Heq.
+ destruct (build_clause_correct _ _ _ _ Heq).
+ red;simpl;auto.
+ decompose [and] H0.
+ case_eq (ZTautoChecker bf c);intros Heq2.
+ unfold C.valid;rewrite H5.
+ apply ZTautoChecker_sound with c;trivial.
+ apply C.interp_true.
+ destruct (Form.check_form_correct interp_form_hatom _ ch_form);trivial.
+ intros _;apply C.interp_true.
+ destruct (Form.check_form_correct interp_form_hatom _ ch_form);trivial.
+ Qed.
+
+
+ Lemma valid_check_diseq :
+ forall c, C.valid rho (check_diseq c).
+ Proof.
+ unfold check_diseq; intro c.
+ case_eq (t_form.[Lit.blit c]);intros;subst; try (unfold C.valid; apply valid_C_true; trivial).
+ case_eq ((length a) == 3); intros; try (unfold C.valid; apply valid_C_true; trivial).
+ apply eqb_correct in H0.
+ apply get_eq_interp; intros.
+ apply get_not_le_interp; intros.
+ apply get_not_le_interp; intros.
+ case_eq ((a0 == a1) && (a0 == b1) && (b == b0) && (b == a2)); intros; subst;
+ try (unfold C.valid; apply valid_C_true; trivial).
+ repeat(apply andb_prop in H19; destruct H19).
+ apply Int63Properties.eqb_spec in H19;apply Int63Properties.eqb_spec in H20;apply Int63Properties.eqb_spec in H21;apply Int63Properties.eqb_spec in H22;subst.
+ unfold C.interp; simpl; rewrite orb_false_r.
+ unfold Lit.interp; rewrite Lit.is_pos_lit.
+ unfold Var.interp; rewrite Lit.blit_lit.
+ rewrite wf_interp_form, H;simpl.
+ case_eq (Lit.interp rho (a.[0]) || Lit.interp rho (a.[1]) || Lit.interp rho (a.[2])).
+ intros;repeat (rewrite orb_true_iff in H19);destruct H19. destruct H19.
+ apply (afold_left_orb_true int 0); subst; auto.
+ apply ltb_spec;rewrite H0;compute;trivial.
+ apply (afold_left_orb_true int 1); auto.
+ apply ltb_spec;rewrite H0;compute;trivial.
+ apply (afold_left_orb_true int 2); auto.
+ apply ltb_spec;rewrite H0;compute;trivial.
+ intros; repeat (rewrite orb_false_iff in H19);destruct H19. destruct H19.
+ unfold Lit.interp in H19.
+ rewrite H3 in H19; unfold Var.interp in H19; rewrite H4 in H19.
+ unfold Lit.interp in H21.
+ pose (H24 := H15). apply negb_true_iff in H24.
+ rewrite H24 in H21.
+ unfold Var.interp in H21; rewrite H16 in H21.
+ unfold Lit.interp in H23.
+ pose (H25 := H9). apply negb_true_iff in H25.
+ rewrite H25 in H23.
+ unfold Var.interp in H23; rewrite H10 in H23.
+ assert (t = Typ.TZ).
+ generalize H12. clear H12.
+ destruct (Typ.reflect_eqb (get_type t_i t_func t_atom b0) Typ.TZ) as [H12|H12]; [intros _|discriminate].
+ generalize H6. clear H6.
+ destruct (Typ.reflect_eqb (get_type t_i t_func t_atom b0) t) as [H6|H6]; [intros _|discriminate].
+ rewrite <- H6. auto.
+ rewrite H26 in H19.
+ case_eq (interp_atom (t_atom .[ b1])); intros t1 v1 Heq1.
+ assert (H50: t1 = Typ.TZ).
+ unfold get_type, get_type' in H18. rewrite t_interp_wf in H18; trivial. rewrite Heq1 in H18. simpl in H18. rewrite Typ.eqb_spec in H18. assumption.
+ subst t1.
+ case_eq (interp_atom (t_atom .[ a2])); intros t2 v2 Heq2.
+ assert (H50: t2 = Typ.TZ).
+ unfold get_type, get_type' in H17. rewrite t_interp_wf in H17; trivial. rewrite Heq2 in H17. simpl in H17. rewrite Typ.eqb_spec in H17. assumption.
+ subst t2.
+ subst;elim (interp_binop_eqb_antisym (t_atom.[b1]) (t_atom.[a2]) v1 v2);trivial.
+ unfold interp_hatom in H19; do 2 rewrite t_interp_wf in H19; trivial.
+ unfold interp_hatom in H23; do 2 rewrite t_interp_wf in H23; trivial.
+ unfold interp_hatom in H21; do 2 rewrite t_interp_wf in H21; trivial.
+ trivial.
+ destruct H19.
+ case_eq ((a0 == b0) && (a0 == a2) && (b == a1) && (b == b1)); intros; subst;
+ try (unfold C.valid; apply valid_C_true; trivial).
+ repeat(apply andb_prop in H19; destruct H19).
+ apply Int63Properties.eqb_spec in H19;apply Int63Properties.eqb_spec in H20;apply Int63Properties.eqb_spec in H21;apply Int63Properties.eqb_spec in H22;subst.
+ unfold C.interp; simpl; rewrite orb_false_r.
+ unfold Lit.interp; rewrite Lit.is_pos_lit.
+ unfold Var.interp; rewrite Lit.blit_lit.
+ rewrite wf_interp_form, H;simpl.
+ case_eq (Lit.interp rho (a.[0]) || Lit.interp rho (a.[1]) || Lit.interp rho (a.[2])).
+ intros;repeat (rewrite orb_true_iff in H19);destruct H19. destruct H19.
+ apply (afold_left_orb_true int 0); auto.
+ apply ltb_spec;rewrite H0;compute;trivial.
+ apply (afold_left_orb_true int 1); auto.
+ apply ltb_spec;rewrite H0;compute;trivial.
+ apply (afold_left_orb_true int 2); auto.
+ apply ltb_spec;rewrite H0;compute;trivial.
+ intros; repeat (rewrite orb_false_iff in H19);destruct H19. destruct H19.
+ unfold Lit.interp in H19.
+ rewrite H3 in H19; unfold Var.interp in H19; rewrite H4 in H19.
+ unfold Lit.interp in H21.
+ case_eq (Lit.is_pos (a.[2])); intros.
+ apply negb_true_iff in H15;rewrite H15 in H24; discriminate.
+ rewrite H24 in H21.
+ unfold Var.interp in H21;rewrite H16 in H21.
+ unfold Lit.interp in H23.
+ case_eq (Lit.is_pos (a.[1])); intros.
+ apply negb_true_iff in H9; rewrite H9 in H25; discriminate.
+ rewrite H25 in H23.
+ unfold Var.interp in H23; rewrite H10 in H23.
+ rewrite <-H22, <- H20 in H21.
+ assert (t = Typ.TZ).
+ rewrite Typ.eqb_spec in H6; rewrite Typ.eqb_spec in H18; subst; auto.
+ rewrite H26 in H19.
+ case_eq (interp_atom (t_atom .[ b0])); intros t1 v1 Heq1.
+ assert (H50: t1 = Typ.TZ).
+ unfold get_type, get_type' in H12. rewrite t_interp_wf in H12; trivial. rewrite Heq1 in H12. simpl in H12. rewrite Typ.eqb_spec in H12. assumption.
+ subst t1.
+ case_eq (interp_atom (t_atom .[ a1])); intros t2 v2 Heq2.
+ assert (H50: t2 = Typ.TZ).
+ unfold get_type, get_type' in H11. rewrite t_interp_wf in H11; trivial. rewrite Heq2 in H11. simpl in H11. rewrite Typ.eqb_spec in H11. assumption.
+ subst t2.
+ elim (interp_binop_eqb_antisym (t_atom.[b0]) (t_atom.[a1]) v1 v2); trivial.
+ unfold interp_hatom in H19; do 2 rewrite t_interp_wf in H19; trivial.
+ unfold interp_hatom in H21; do 2 rewrite t_interp_wf in H21; trivial.
+ unfold interp_hatom in H23; do 2 rewrite t_interp_wf in H23; trivial.
+ trivial.
+ Qed.
+
+ End Proof.
+
+End certif.
diff --git a/src/lia/lia.ml b/src/lia/lia.ml
new file mode 100644
index 0000000..97415b9
--- /dev/null
+++ b/src/lia/lia.ml
@@ -0,0 +1,208 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+(*** Linking SMT Terms to Micromega Terms ***)
+open Term
+open Coqlib
+open Declare
+open Decl_kinds
+open Entries
+open Util
+open Micromega
+open Coq_micromega
+open Errors
+
+open SmtMisc
+open SmtForm
+open SmtAtom
+
+(* morphism for expression over Z *)
+
+let rec pos_of_int i =
+ if i <= 1
+ then XH
+ else
+ if i land 1 = 0
+ then XO(pos_of_int (i lsr 1))
+ else XI(pos_of_int (i lsr 1))
+
+let z_of_int i =
+ if i = 0
+ then Z0
+ else
+ if i > 0
+ then Zpos (pos_of_int i)
+ else Zneg (pos_of_int (-i))
+
+type my_tbl =
+ {tbl:(hatom,int) Hashtbl.t; mutable count:int}
+
+let get_atom_var tbl ha =
+ try Hashtbl.find tbl.tbl ha
+ with Not_found ->
+ let v = tbl.count in
+ Hashtbl.add tbl.tbl ha v;
+ tbl.count <- v + 1;
+ v
+
+let create_tbl n = {tbl=Hashtbl.create n;count=1}
+
+let rec smt_Atom_to_micromega_pos ha =
+ match Atom.atom ha with
+ | Auop(UO_xO, ha) ->
+ Micromega.XO (smt_Atom_to_micromega_pos ha)
+ | Auop(UO_xI, ha) ->
+ Micromega.XI (smt_Atom_to_micromega_pos ha)
+ | Acop CO_xH -> Micromega.XH
+ | _ -> raise Not_found
+
+let smt_Atom_to_micromega_Z ha =
+ match Atom.atom ha with
+ | Auop(UO_Zpos, ha) ->
+ Micromega.Zpos (smt_Atom_to_micromega_pos ha)
+ | Auop(UO_Zneg, ha) ->
+ Micromega.Zneg (smt_Atom_to_micromega_pos ha)
+ | Acop CO_Z0 -> Micromega.Z0
+ | _ -> raise Not_found
+
+let rec smt_Atom_to_micromega_pExpr tbl ha =
+ match Atom.atom ha with
+ | Abop (BO_Zplus, ha, hb) ->
+ let a = smt_Atom_to_micromega_pExpr tbl ha in
+ let b = smt_Atom_to_micromega_pExpr tbl hb in
+ PEadd(a, b)
+ | Abop (BO_Zmult, ha, hb) ->
+ let a = smt_Atom_to_micromega_pExpr tbl ha in
+ let b = smt_Atom_to_micromega_pExpr tbl hb in
+ PEmul(a, b)
+ | Abop (BO_Zminus, ha, hb) ->
+ let a = smt_Atom_to_micromega_pExpr tbl ha in
+ let b = smt_Atom_to_micromega_pExpr tbl hb in
+ PEsub(a, b)
+ | Auop (UO_Zopp, ha) ->
+ let a = smt_Atom_to_micromega_pExpr tbl ha in
+ PEopp a
+ | _ ->
+ try PEc (smt_Atom_to_micromega_Z ha)
+ with Not_found ->
+ let v = get_atom_var tbl ha in
+ PEX (pos_of_int v)
+
+
+(* morphism for LIA proposition (=, >, ...) *)
+
+let smt_binop_to_micromega_formula tbl op ha hb =
+ let op =
+ match op with
+ | BO_Zlt -> OpLt
+ | BO_Zle -> OpLe
+ | BO_Zge -> OpGe
+ | BO_Zgt -> OpGt
+ | BO_eq _ -> OpEq
+ | _ -> error
+ "lia.ml: smt_binop_to_micromega_formula expecting a formula"
+ in
+ let lhs = smt_Atom_to_micromega_pExpr tbl ha in
+ let rhs = smt_Atom_to_micromega_pExpr tbl hb in
+ {flhs = lhs; fop = op; frhs = rhs }
+
+let rec smt_Atom_to_micromega_formula tbl ha =
+ match Atom.atom ha with
+ | Abop (op,ha,hb) -> smt_binop_to_micromega_formula tbl op ha hb
+ | _ -> error
+ "lia.ml: smt_Atom_to_micromega_formula was expecting an LIA formula"
+
+(* specialized fold *)
+
+let default_constr = mkInt 0
+let default_tag = Mutils.Tag.from 0
+(* morphism for general formulas *)
+
+let binop_array g tbl op def t =
+ let n = Array.length t in
+ if n = 0 then
+ def
+ else
+ let aux = ref (g tbl t.(0)) in
+ for i = 1 to (n-1) do
+ aux := op !aux (g tbl t.(i))
+ done;
+ !aux
+
+let rec smt_Form_to_coq_micromega_formula tbl l =
+ let v =
+ match Form.pform l with
+ | Fatom ha ->
+ A (smt_Atom_to_micromega_formula tbl ha,
+ default_tag,default_constr)
+ | Fapp (Ftrue, _) -> TT
+ | Fapp (Ffalse, _) -> FF
+ | Fapp (Fand, l) -> binop_array smt_Form_to_coq_micromega_formula tbl (fun x y -> C (x,y)) TT l
+ | Fapp (For, l) -> binop_array smt_Form_to_coq_micromega_formula tbl (fun x y -> D (x,y)) FF l
+ | Fapp (Fxor, l) -> failwith "todo:Fxor"
+ | Fapp (Fimp, l) -> binop_array smt_Form_to_coq_micromega_formula tbl (fun x y -> I (x,None,y)) TT l
+ | Fapp (Fiff, l) -> failwith "todo:Fiff"
+ | Fapp (Fite, l) -> failwith "todo:Fite"
+ | Fapp (Fnot2 _, l) ->
+ if Array.length l <> 1 then
+ failwith "Lia.smt_Form_to_coq_micromega_formula: wrong number of arguments for Fnot2"
+ else
+ smt_Form_to_coq_micromega_formula tbl l.(0)
+ in
+ if Form.is_pos l then v
+ else N(v)
+
+let binop_list tbl op def l =
+ match l with
+ | [] -> def
+ | f::l -> List.fold_left (fun x y -> op x (smt_Form_to_coq_micromega_formula tbl y)) (smt_Form_to_coq_micromega_formula tbl f) l
+
+
+(* let rec binop_list tbl op def l = *)
+(* match l with *)
+(* | [] -> def *)
+(* | [f] -> smt_Form_to_coq_micromega_formula tbl f *)
+(* | f::l -> *)
+(* op (smt_Form_to_coq_micromega_formula tbl f) (binop_list tbl op def l) *)
+
+(* and smt_Form_to_coq_micromega_formula tbl l = *)
+(* let v = *)
+(* match Form.pform l with *)
+(* | Fatom ha -> *)
+(* A (smt_Atom_to_micromega_formula tbl ha, *)
+(* default_tag,default_constr) *)
+(* | Fapp (Ftrue, _) -> TT *)
+(* | Fapp (Ffalse, _) -> FF *)
+(* | Fapp (Fand, l) -> binop_list tbl (fun x y -> C (x,y)) TT l *)
+(* | Fapp (For, l) -> binop_list tbl (fun x y -> D (x,y)) FF l *)
+(* | Fapp (Fxor, l) -> failwith "todo:Fxor" *)
+(* | Fapp (Fimp, l) -> binop_list tbl (fun x y -> I (x,None,y)) TT l *)
+(* | Fapp (Fiff, l) -> failwith "todo:Fiff" *)
+(* | Fapp (Fite, l) -> failwith "todo:Fite" *)
+(* | Fapp (Fnot2 _, l) -> smt_Form_to_coq_micromega_formula tbl l *)
+(* in *)
+(* if Form.is_pos l then v *)
+(* else N(v) *)
+
+
+let smt_clause_to_coq_micromega_formula tbl cl =
+ binop_list tbl (fun x y -> C(x,y)) TT (List.map Form.neg cl)
+
+(* call to micromega solver *)
+let build_lia_certif cl =
+ let tbl = create_tbl 13 in
+ let f = I(smt_clause_to_coq_micromega_formula tbl cl, None, FF) in
+ tbl, f, tauto_lia f
+
diff --git a/src/spl/Arithmetic.v b/src/spl/Arithmetic.v
new file mode 100644
index 0000000..a3e3162
--- /dev/null
+++ b/src/spl/Arithmetic.v
@@ -0,0 +1,94 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+(*** Spl -- a small checker for simplifications ***)
+
+(* Add LoadPath ".." as SMTCoq. *)
+(* Add LoadPath "../lia" as SMTCoq.lia. *)
+Require Import List PArray Bool Int63 ZMicromega.
+Require Import Misc State SMT_terms.
+Require Lia.
+
+Local Open Scope array_scope.
+Local Open Scope int63_scope.
+
+
+(* Arbritrary arithmetic simplifications *)
+
+Section Arith.
+
+ Variable t_form : PArray.array Form.form.
+ Variable t_atom : PArray.array Atom.atom.
+
+ Local Notation build_clause := (Lia.build_clause t_form t_atom).
+
+
+ Definition check_spl_arith orig res l :=
+ match orig with
+ | li::nil =>
+ let cl := (Lit.neg li)::res::nil in
+ match build_clause Lia.empty_vmap cl with
+ | Some (_, bf) =>
+ if ZTautoChecker bf l then res::nil
+ else C._true
+ | None => C._true
+ end
+ | _ => C._true
+ end.
+
+
+ Section Valid.
+
+ Variables (t_i : array typ_eqb)
+ (t_func : array (Atom.tval t_i))
+ (ch_atom : Atom.check_atom t_atom)
+ (ch_form : Form.check_form t_form)
+ (wt_t_atom : Atom.wt t_i t_func t_atom).
+
+ Local Notation interp_form_hatom :=
+ (Atom.interp_form_hatom t_i t_func t_atom).
+ Local Notation rho :=
+ (Form.interp_state_var interp_form_hatom t_form).
+
+
+ Let wf_rho : Valuation.wf rho.
+ Proof. destruct (Form.check_form_correct interp_form_hatom _ ch_form); auto. Qed.
+
+ Hint Immediate wf_rho.
+
+
+ Lemma valid_check_spl_arith :
+ forall orig, C.valid rho orig ->
+ forall res l, C.valid rho (check_spl_arith orig res l).
+ Proof.
+ unfold check_spl_arith; intros [ |li [ |t q]].
+ (* Case nil *)
+ intros; apply C.interp_true; auto.
+ (* List with one element *)
+ intros H res l; case_eq (build_clause Lia.empty_vmap (Lit.neg li :: res :: nil)); [ |intros; apply C.interp_true; auto].
+ intros (vm1, bf) Heq; destruct (Lia.build_clause_correct _ _ _ t_func ch_atom ch_form wt_t_atom _ _ _ _ Heq) as [H1 H0].
+ red; simpl; auto.
+ decompose [and] H0; case_eq (ZTautoChecker bf l); [intros Heq3|intros; apply C.interp_true; auto].
+ unfold C.valid; replace (C.interp rho (res :: nil)) with (C.interp rho (Lit.neg li :: res :: nil)).
+ rewrite H6; apply ZTautoChecker_sound with l;trivial.
+ simpl; replace (Lit.interp rho (Lit.neg li)) with false; auto.
+ rewrite Lit.interp_neg; unfold C.valid in H; simpl in H; rewrite orb_false_r in H; rewrite H; auto.
+ (* List with at least two elements *)
+ intros; apply C.interp_true; auto.
+ Qed.
+
+ End Valid.
+
+End Arith.
diff --git a/src/spl/Operators.v b/src/spl/Operators.v
new file mode 100644
index 0000000..90483db
--- /dev/null
+++ b/src/spl/Operators.v
@@ -0,0 +1,549 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+(*** Spl -- a small checker for simplifications ***)
+
+(* Add LoadPath ".." as SMTCoq. *)
+(* Add LoadPath "../lia" as SMTCoq.lia. *)
+Require Import List PArray Bool Int63 ZMicromega.
+Require Import Misc State SMT_terms.
+Require Lia.
+
+Local Open Scope array_scope.
+Local Open Scope int63_scope.
+
+
+(* Simplification of SMTLIB-2 operators *)
+
+Section Operators.
+
+ Import Form.
+
+ Variable t_form : PArray.array Form.form.
+ Variable t_atom : PArray.array Atom.atom.
+
+ Local Notation get_form := (PArray.get t_form).
+ Local Notation get_atom := (PArray.get t_atom).
+
+
+ Fixpoint check_in x l :=
+ match l with
+ | nil => false
+ | t::q => if x == t then true else check_in x q
+ end.
+
+
+ Lemma check_in_spec : forall x l, check_in x l = true <-> In x l.
+ Proof.
+ intro x; induction l as [ |t q IHq]; simpl.
+ split; intro H; try discriminate; elim H.
+ case_eq (x == t).
+ rewrite eqb_spec; intro; subst t; split; auto.
+ intro H; rewrite IHq; split; auto; intros [H1|H1]; auto; rewrite H1, eqb_refl in H; discriminate.
+ Qed.
+
+
+ Fixpoint check_diseqs_complete_aux a dist t :=
+ match dist with
+ | nil => true
+ | b::q => if PArray.existsb (fun (x:option (int*int)) =>
+ match x with
+ | Some (a',b') => ((a == a') && (b == b')) || ((a == b') && (b == a'))
+ | None => false
+ end
+ ) t then check_diseqs_complete_aux a q t else false
+ end.
+
+
+ Lemma check_diseqs_complete_aux_spec : forall a dist t,
+ check_diseqs_complete_aux a dist t = true <->
+ forall y, In y dist -> exists i, i < length t /\
+ (t.[i] = Some (a,y) \/ t.[i] = Some (y,a)).
+ Proof.
+ intros a dist t; induction dist as [ |b q IHq]; simpl; split; auto.
+ intros _ y H; inversion H.
+ case_eq (PArray.existsb (fun x : option (int * int) => match x with | Some (a', b') => (a == a') && (b == b') || (a == b') && (b == a') | None => false end) t); try discriminate; rewrite PArray.existsb_spec; intros [i [H1 H2]]; rewrite IHq; clear IHq; intros H3 y [H4|H4]; auto; subst y; exists i; split; auto; generalize H2; case (t .[ i]); try discriminate; intros [a' b']; rewrite orb_true_iff, !andb_true_iff, !Int63Properties.eqb_spec; intros [[H4 H5]|[H4 H5]]; subst a' b'; auto.
+ intro H1; case_eq (PArray.existsb (fun x : option (int * int) => match x with | Some (a', b') => (a == a') && (b == b') || (a == b') && (b == a') | None => false end) t).
+ intros _; rewrite IHq; clear IHq; intros y Hy; apply H1; auto.
+ rewrite array_existsb_false_spec; destruct (H1 b (or_introl (refl_equal b))) as [i [H2 H3]]; intro H; rewrite <- (H _ H2); destruct H3 as [H3|H3]; rewrite H3; rewrite !eqb_refl; auto; rewrite orb_true_r; auto.
+ Qed.
+
+
+ Lemma check_diseqs_complete_aux_false_spec : forall a dist t,
+ check_diseqs_complete_aux a dist t = false <->
+ exists y, In y dist /\ forall i, i < length t ->
+ (t.[i] <> Some (a,y) /\ t.[i] <> Some (y,a)).
+ Proof.
+ intros a dist t; induction dist as [ |b q IHq]; simpl; split; try discriminate.
+ intros [y [H _]]; elim H.
+ case_eq (PArray.existsb (fun x : option (int * int) => match x with | Some (a', b') => (a == a') && (b == b') || (a == b') && (b == a') | None => false end) t).
+ intros _; rewrite IHq; clear IHq; intros [y [H3 H4]]; exists y; auto.
+ rewrite array_existsb_false_spec; intros H _; exists b; split; auto; intros i Hi; split; intro H1; generalize (H _ Hi); rewrite H1, !eqb_refl; try discriminate; rewrite orb_true_r; discriminate.
+ intros [y [H1 H2]]; case_eq (PArray.existsb (fun x : option (int * int) => match x with | Some (a', b') => (a == a') && (b == b') || (a == b') && (b == a') | None => false end) t); auto; rewrite PArray.existsb_spec; intros [i [H3 H4]]; rewrite IHq; clear IHq; exists y; destruct H1 as [H1|H1]; auto; subst y; case_eq (t.[i]); [intros [a' b'] Heq|intro Heq]; rewrite Heq in H4; try discriminate; rewrite orb_true_iff, !andb_true_iff, !eqb_spec in H4; destruct H4 as [[H4 H5]|[H4 H5]]; subst a' b'; generalize (H2 _ H3); rewrite Heq; intros [H4 H5]; [elim H4|elim H5]; auto.
+ Qed.
+
+
+ Fixpoint check_diseqs_complete dist t :=
+ match dist with
+ | nil => true
+ | a::q => if check_diseqs_complete_aux a q t then check_diseqs_complete q t else false
+ end.
+
+
+ Lemma check_diseqs_complete_spec : forall dist t,
+ check_diseqs_complete dist t = true <->
+ forall x y, In2 x y dist -> exists i, i < length t /\
+ (t.[i] = Some (x,y) \/ t.[i] = Some (y,x)).
+ Proof.
+ intros dist t; induction dist as [ |a q IHq]; simpl; split; auto.
+ intros _ x y H; inversion H.
+ case_eq (check_diseqs_complete_aux a q t); try discriminate; rewrite check_diseqs_complete_aux_spec, IHq; clear IHq; intros H1 H2 x y H3; inversion H3; auto.
+ intro H; case_eq (check_diseqs_complete_aux a q t).
+ rewrite IHq; clear IHq; intros _ x y H1; apply H; constructor 2; auto.
+ rewrite check_diseqs_complete_aux_false_spec; clear IHq; intros [y [H1 H2]]; destruct (H _ _ (In2_hd _ a _ _ H1)) as [i [H3 [H4|H4]]]; elim (H2 _ H3); rewrite H4; intros H5 H6; [elim H5|elim H6]; auto.
+ Qed.
+
+
+ Lemma check_diseqs_complete_false_spec : forall dist t,
+ check_diseqs_complete dist t = false <->
+ exists x y, In2 x y dist /\ forall i, i < length t ->
+ (t.[i] <> Some (x,y) /\ t.[i] <> Some (y,x)).
+ Proof.
+ intros dist t; induction dist as [ |a q IHq]; simpl; split; try discriminate.
+ intros [x [y [H _]]]; inversion H.
+ case_eq (check_diseqs_complete_aux a q t).
+ rewrite IHq; clear IHq; intros _ [x [y [H2 H3]]]; inversion H2; clear H2; subst q; exists x; exists y; split; auto; constructor 2.
+ constructor 1; auto.
+ constructor 2; auto.
+ rewrite check_diseqs_complete_aux_false_spec; intros [y [H1 H2]] _; clear IHq; exists a; exists y; split; auto; constructor; auto.
+ intros [x [y [H1 H2]]]; case_eq (check_diseqs_complete_aux a q t); auto; rewrite IHq; clear IHq; inversion H1; clear H1.
+ subst x q; rewrite check_diseqs_complete_aux_spec; intro H; destruct (H _ H0) as [i [H1 H3]]; elim (H2 _ H1); intros H4 H5; destruct H3; [elim H4|elim H5]; auto.
+ subst k q; intros _; exists x; exists y; split; auto.
+ Qed.
+
+
+ Definition check_diseqs ty dist diseq :=
+ let t := PArray.mapi (fun _ t =>
+ if Lit.is_pos t then None else
+ match get_form (Lit.blit t) with
+ | Fatom a =>
+ match get_atom a with
+ | Atom.Abop (Atom.BO_eq A) h1 h2 =>
+ if (Typ.eqb ty A) && (negb (h1 == h2)) && (check_in h1 dist) && (check_in h2 dist) then
+ Some (h1,h2)
+ else
+ None
+ | _ => None
+ end
+ | _ => None
+ end
+ ) diseq in
+ PArray.forallb (fun x => match x with | None => false | _ => true end) t &&
+ check_diseqs_complete dist t.
+
+
+ Lemma check_diseqs_spec : forall A dist diseq,
+ check_diseqs A dist diseq = true <->
+ ((forall i, i < length diseq ->
+ let t := diseq.[i] in
+ ~ Lit.is_pos t /\
+ exists a, get_form (Lit.blit t) = Fatom a /\
+ exists h1 h2, get_atom a = Atom.Abop (Atom.BO_eq A) h1 h2 /\
+ h1 <> h2 /\ (In2 h1 h2 dist \/ In2 h2 h1 dist))
+ /\
+ (forall x y, In2 x y dist -> exists i, i < length diseq /\
+ let t := diseq.[i] in
+ ~ Lit.is_pos t /\
+ exists a, get_form (Lit.blit t) = Fatom a /\
+ x <> y /\
+ (get_atom a = Atom.Abop (Atom.BO_eq A) x y \/
+ get_atom a = Atom.Abop (Atom.BO_eq A) y x))).
+ Proof.
+ intros A dist diseq; unfold check_diseqs; rewrite andb_true_iff, PArray.forallb_spec, check_diseqs_complete_spec, length_mapi; split; intros [H1 H2]; split.
+ clear H2; intros i Hi; generalize (H1 _ Hi); rewrite get_mapi; auto; case_eq (Lit.is_pos (diseq .[ i])); try discriminate; intro Heq1; case_eq (get_form (Lit.blit (diseq .[ i]))); try discriminate; intros a Heq2; case_eq (get_atom a); try discriminate; intros [ | | | | | | |B]; try discriminate; intros h1 h2 Heq3; case_eq (Typ.eqb A B); try discriminate; change (Typ.eqb A B = true) with (is_true (Typ.eqb A B)); rewrite Typ.eqb_spec; intro; subst B; case_eq (h1 == h2); try discriminate; rewrite eqb_false_spec; intro H2; case_eq (check_in h1 dist); try discriminate; case_eq (check_in h2 dist); try discriminate; rewrite !check_in_spec; intros H3 H4 _; split; try discriminate; exists a; split; auto; exists h1, h2; repeat split; auto; rewrite <- In2_In; auto.
+ clear H1; intros x y Hxy; destruct (H2 _ _ Hxy) as [i [H1 H4]]; clear H2; rewrite get_mapi in H4; auto; exists i; split; auto; generalize H4; case_eq (Lit.is_pos (diseq .[ i])); intro Heq; try (intros [H|H]; discriminate); case_eq (get_form (Lit.blit (diseq .[ i]))); [intros a| | |intros a1 a2|intros a1|intros a1|intros a1|intros a1 a2|intros a1 a2|intros a1 a2 a3]; intro Heq2; try (intros [H|H]; discriminate); case_eq (get_atom a); [intros a1|intros a1 a2|intros [ | | | | | | |B] h1 h2|intros a1 a2|intros a1 a2]; intro Heq3; try (intros [H|H]; discriminate); case_eq (Typ.eqb A B); try (intros _ [H|H]; discriminate); change (Typ.eqb A B = true) with (is_true (Typ.eqb A B)); rewrite Typ.eqb_spec; intro; subst B; case_eq (h1 == h2); try (intros _ [H|H]; discriminate); rewrite eqb_false_spec; intro H10; case (check_in h1 dist); try (intros [H|H]; discriminate); case (check_in h2 dist); try (intros [H|H]; discriminate); simpl; intro H3; split; try discriminate; exists a; split; auto; destruct H3 as [H3|H3]; inversion H3; subst; auto.
+ clear H2; intros i Hi; rewrite get_mapi; auto; destruct (H1 _ Hi) as [H2 [a [H3 [h1 [h2 [H4 [H5 H6]]]]]]]; clear H1; replace (Lit.is_pos (diseq .[ i])) with false by (case_eq (Lit.is_pos (diseq .[ i])); auto); rewrite H3, H4, Typ.eqb_refl; simpl; replace (h1 == h2) with false by (case_eq (h1 == h2); auto; rewrite eqb_spec; intro H; elim H5; auto); simpl; rewrite <- In2_In, <- !check_in_spec in H6; auto; destruct H6 as [H6 H7]; rewrite H6, H7; auto.
+ clear H1; intros x y Hxy; destruct (H2 _ _ Hxy) as [i [H1 [H3 [a [H4 [H6 H5]]]]]]; clear H2; exists i; split; auto; rewrite get_mapi; auto; replace (Lit.is_pos (diseq .[ i])) with false by (case_eq (Lit.is_pos (diseq .[ i])); auto); rewrite H4; assert (H7 := or_introl (In2 y x dist) Hxy); rewrite <- In2_In, <- !check_in_spec in H7; auto; destruct H7 as [H7 H8]; destruct H5 as [H5|H5]; rewrite H5, Typ.eqb_refl; [replace (x == y) with false by (case_eq (x == y); auto; rewrite eqb_spec; auto)|replace (y == x) with false by (case_eq (y == x); auto; rewrite eqb_spec; auto)]; simpl; rewrite H7, H8; auto.
+ Qed.
+
+
+ (* Definition check_diseqs ty dist diseq := *)
+ (* PArray.forallb (fun t => *)
+ (* if Lit.is_pos t then false else *)
+ (* match get_form (Lit.blit t) with *)
+ (* | Fatom a => *)
+ (* match get_atom a with *)
+ (* | Atom.Abop (Atom.BO_eq A) h1 h2 => *)
+ (* (Typ.eqb ty A) && (negb (h1 == h2)) && (check_in h1 dist) && (check_in h2 dist) *)
+ (* | _ => false *)
+ (* end *)
+ (* | _ => false *)
+ (* end) diseq. *)
+
+
+ (* Lemma check_diseqs_spec : forall A dist diseq, *)
+ (* check_diseqs A dist diseq <-> forall i, i < length diseq -> *)
+ (* let t := diseq.[i] in *)
+ (* ~ Lit.is_pos t /\ *)
+ (* exists a, get_form (Lit.blit t) = Fatom a /\ *)
+ (* exists h1 h2, get_atom a = Atom.Abop (Atom.BO_eq A) h1 h2 /\ *)
+ (* (h1 <> h2) /\ ((In2 h1 h2 dist) \/ (In2 h2 h1 dist)). *)
+ (* Proof. *)
+ (* intros A dist diseq; unfold check_diseqs; unfold is_true at 1; rewrite PArray.forallb_spec; split. *)
+ (* intros H i Hi; generalize (H _ Hi); clear H; case (Lit.is_pos (diseq .[ i])); try discriminate; case (get_form (Lit.blit (diseq .[ i]))); try discriminate; intros a H1; split; try discriminate; exists a; split; auto; generalize H1; clear H1; case (get_atom a); try discriminate; intros [ | | | | | | |B] h1 h2; try discriminate; rewrite !andb_true_iff; change (check_in h1 dist = true) with (is_true (check_in h1 dist)); change (check_in h2 dist = true) with (is_true (check_in h2 dist)); rewrite !check_in_spec; intros [[[H1 H4] H2] H3]; change (is_true (Typ.eqb A B)) in H1; rewrite Typ.eqb_spec in H1; subst B; exists h1; exists h2; split; auto; assert (H5: h1 <> h2) by (intro H; rewrite H, eqb_refl in H4; discriminate); split; auto; rewrite <- In2_In; auto. *)
+ (* intros H i Hi; generalize (H _ Hi); clear H; case (Lit.is_pos (diseq .[ i])); try (intros [H _]; elim H; reflexivity); intros [_ [a [H1 [h1 [h2 [H2 [H3 H4]]]]]]]; rewrite H1, H2; rewrite !andb_true_iff; rewrite <- (In2_In H3) in H4; destruct H4 as [H4 H5]; change (check_in h1 dist = true) with (is_true (check_in h1 dist)); change (check_in h2 dist = true) with (is_true (check_in h2 dist)); rewrite !check_in_spec; repeat split; auto; case_eq (h1 == h2); auto; try (rewrite Typ.eqb_refl; auto); rewrite eqb_spec; intro; subst h1; elim H3; auto. *)
+ (* Qed. *)
+
+
+ Definition check_distinct ha diseq :=
+ match get_atom ha with
+ | Atom.Anop (Atom.NO_distinct ty) dist =>
+ check_diseqs ty dist diseq
+ | _ => false
+ end.
+
+
+ Lemma check_distinct_spec : forall ha diseq,
+ check_distinct ha diseq = true <-> exists A dist,
+ get_atom ha = Atom.Anop (Atom.NO_distinct A) dist /\
+ check_diseqs A dist diseq = true.
+ Proof.
+ intros ha diseq; unfold check_distinct; split.
+ case (get_atom ha); try discriminate; intros [A] l H; exists A; exists l; auto.
+ intros [A [dist [H1 H2]]]; rewrite H1; auto.
+ Qed.
+
+
+ Definition check_distinct_two_args f1 f2 :=
+ match get_form f1, get_form f2 with
+ | Fatom ha, Fatom hb =>
+ match get_atom ha, get_atom hb with
+ | Atom.Anop (Atom.NO_distinct ty) (x::y::nil), Atom.Abop (Atom.BO_eq ty') x' y' => (Typ.eqb ty ty') && (((x == x') && (y == y')) || ((x == y') && (y == x')))
+ | _, _ => false
+ end
+ | _, _ => false
+ end.
+
+
+ Lemma check_distinct_two_args_spec : forall f1 f2,
+ check_distinct_two_args f1 f2 = true <-> exists ha hb ty x y,
+ get_form f1 = Fatom ha /\
+ get_form f2 = Fatom hb /\
+ get_atom ha = Atom.Anop (Atom.NO_distinct ty) (x::y::nil) /\
+ (get_atom hb = Atom.Abop (Atom.BO_eq ty) x y \/
+ get_atom hb = Atom.Abop (Atom.BO_eq ty) y x).
+ Proof.
+ intros f1 f2; unfold check_distinct_two_args; split.
+ case (get_form f1); try discriminate; intro ha; case (get_form f2); try discriminate; intro hb; case_eq (get_atom ha); try discriminate; intros [A] [ |x [ |y [ |l]]] Heq1; try discriminate; case_eq (get_atom hb); try discriminate; intros [ | | | | | | |B] x' y' Heq2; try discriminate; rewrite !andb_true_iff, orb_true_iff, !andb_true_iff; change (Typ.eqb A B = true) with (is_true (Typ.eqb A B)); rewrite Typ.eqb_spec, !Int63Properties.eqb_spec; intros [H1 [[H2 H3]|[H2 H3]]]; subst B x' y'; exists ha, hb, A, x, y; auto.
+ intros [ha [hb [A [x [y [H1 [H2 [H3 [H4|H4]]]]]]]]]; rewrite H1, H2, H3, H4, Typ.eqb_refl, !eqb_refl; auto; rewrite orb_true_r; auto.
+ Qed.
+
+
+ Section Valid1.
+
+ Variables (t_i : array typ_eqb)
+ (t_func : array (Atom.tval t_i))
+ (ch_atom : Atom.check_atom t_atom)
+ (ch_form : Form.check_form t_form)
+ (wt_t_atom : Atom.wt t_i t_func t_atom).
+
+ Local Notation interp_form_hatom :=
+ (Atom.interp_form_hatom t_i t_func t_atom).
+ Local Notation rho :=
+ (Form.interp_state_var interp_form_hatom t_form).
+
+ Let wf_t_atom : Atom.wf t_atom.
+ Proof. destruct (Atom.check_atom_correct _ ch_atom); auto. Qed.
+
+ Let default_t_atom : default t_atom = Atom.Acop Atom.CO_xH.
+ Proof. destruct (Atom.check_atom_correct _ ch_atom); auto. Qed.
+
+ Lemma default_t_form : default t_form = Ftrue.
+ Proof. destruct (Form.check_form_correct interp_form_hatom _ ch_form) as [[H _] _]; auto. Qed.
+
+ Lemma wf_t_form : wf t_form.
+ Proof. destruct (Form.check_form_correct interp_form_hatom _ ch_form) as [[_ H] _]; auto. Qed.
+
+ Local Hint Immediate wf_t_atom default_t_atom default_t_form wf_t_form.
+
+ Lemma interp_check_distinct : forall ha diseq,
+ check_distinct ha diseq = true ->
+ interp_form_hatom ha = afold_left bool int true andb (Lit.interp rho) diseq.
+ Proof.
+ intros ha diseq; rewrite check_distinct_spec; intros [A [dist [H1 H2]]]; rewrite check_diseqs_spec in H2; destruct H2 as [H2 H3]; unfold Atom.interp_form_hatom, Atom.interp_bool, Atom.interp_hatom; rewrite Atom.t_interp_wf; auto; rewrite H1; simpl; generalize (Atom.compute_interp_spec_rev t_i (get (Atom.t_interp t_i t_func t_atom)) A dist); case (Atom.compute_interp t_i (get (Atom.t_interp t_i t_func t_atom)) A nil); simpl.
+ intros l H4; case_eq (distinct (Typ.i_eqb t_i A) (rev l)).
+ rewrite distinct_spec; intro H5; symmetry; apply afold_left_andb_true; intros i Hi; destruct (H2 _ Hi) as [H9 [a [H10 [h1 [h2 [H6 [H7 H8]]]]]]]; unfold Lit.interp; replace (Lit.is_pos (diseq .[ i])) with false by (case_eq (Lit.is_pos (diseq .[ i])); auto); unfold Var.interp; rewrite Form.wf_interp_form; auto; rewrite H10; simpl; rewrite Atom.t_interp_wf; auto; rewrite H6; simpl; unfold Atom.apply_binop; unfold Atom.wt in wt_t_atom; unfold is_true in wt_t_atom; rewrite forallbi_spec in wt_t_atom; assert (H11: a < length t_atom).
+ case_eq (a < length t_atom); auto; intro H11; rewrite (get_outofbound _ _ _ H11) in H6; rewrite default_t_atom in H6; inversion H6.
+ generalize (wt_t_atom _ H11); rewrite H6; simpl; rewrite !andb_true_iff; change (Typ.eqb (Atom.get_type' t_i (Atom.t_interp t_i t_func t_atom) h1) A = true) with (is_true (Typ.eqb (Atom.get_type' t_i (Atom.t_interp t_i t_func t_atom) h1) A)); change (Typ.eqb (Atom.get_type' t_i (Atom.t_interp t_i t_func t_atom) h2) A = true) with (is_true (Typ.eqb (Atom.get_type' t_i (Atom.t_interp t_i t_func t_atom) h2) A)); rewrite !Typ.eqb_spec; intros [[_ H13] H12]; generalize (Atom.check_aux_interp_hatom _ t_func _ wf_t_atom h1); rewrite H13; intros [v1 HH1]; generalize (Atom.check_aux_interp_hatom _ t_func _ wf_t_atom h2); rewrite H12; intros [v2 HH2]; rewrite HH1, HH2; simpl; rewrite Typ.cast_refl; simpl; destruct H8 as [H8|H8]; [ |rewrite Typ.i_eqb_sym]; rewrite H5; auto; rewrite H4; [exists h2; exists h1|exists h1; exists h2]; auto.
+ rewrite distinct_false_spec; intros [v2 [v1 [H5 H6]]]; rewrite H4 in H5; destruct H5 as [a [b [H5 [H7 H8]]]]; clear H4; change (Typ.i_eqb t_i A v2 v1 = true) with (is_true (Typ.i_eqb t_i A v2 v1)) in H6; rewrite Typ.i_eqb_spec in H6; subst v2; clear H2; destruct (H3 _ _ H5) as [i [H2 [H4 [hb [H6 [H9 H10]]]]]]; clear H3; symmetry; apply (afold_left_andb_false _ i); auto; unfold Lit.interp; replace (Lit.is_pos (diseq .[ i])) with false by (case_eq (Lit.is_pos (diseq .[ i])); auto); unfold Var.interp; rewrite Form.wf_interp_form; auto; rewrite H6; simpl; rewrite Atom.t_interp_wf; auto; destruct H10 as [H10|H10]; rewrite H10; simpl; rewrite H7, H8; simpl; rewrite Typ.cast_refl; simpl; replace (Typ.i_eqb t_i A v1 v1) with true; auto; symmetry; change (is_true (Typ.i_eqb t_i A v1 v1)); rewrite Typ.i_eqb_spec; auto.
+ intros [a [H20 H21]]; assert (H4: ha < length t_atom).
+ case_eq (ha < length t_atom); auto; intro Heq; generalize H1; rewrite get_outofbound; auto; rewrite default_t_atom; discriminate.
+ unfold Atom.wt in wt_t_atom; unfold is_true in wt_t_atom; rewrite forallbi_spec in wt_t_atom; generalize (wt_t_atom _ H4); rewrite H1; simpl; rewrite andb_true_iff, forallb_forall; intros [_ H5]; assert (H6 := H5 _ H20); generalize (Atom.check_aux_interp_hatom _ t_func _ wf_t_atom a); intros [va Ha]; rewrite Ha in H21; simpl in H21; elim H21; apply Typ.eqb_spec; auto.
+ Qed.
+
+ Lemma interp_check_distinct_two_args : forall f1 f2,
+ check_distinct_two_args f1 f2 = true ->
+ rho f1 = negb (rho f2).
+ Proof.
+ intros f1 f2; rewrite check_distinct_two_args_spec; intros [ha [hb [A [x [y [H1 [H2 [H3 [H4|H4]]]]]]]]]; unfold Form.interp_state_var; assert (H5: f1 < length t_form) by (case_eq (f1 < length t_form); auto; intro Heq; generalize H1; rewrite get_outofbound; auto; rewrite default_t_form; discriminate); assert (H6: f2 < length t_form) by (case_eq (f2 < length t_form); auto; intro Heq; generalize H2; rewrite get_outofbound; auto; rewrite default_t_form; discriminate); rewrite !Form.t_interp_wf; auto; rewrite H1, H2; simpl; unfold Atom.interp_form_hatom, Atom.interp_hatom; rewrite !Atom.t_interp_wf; auto; rewrite H3, H4; simpl; unfold Atom.wt,is_true in wt_t_atom; rewrite forallbi_spec in wt_t_atom; assert (H7: hb < length t_atom) by (case_eq (hb < length t_atom); auto; intro Heq; generalize H4; rewrite get_outofbound; auto; rewrite default_t_atom; discriminate); generalize (wt_t_atom _ H7); rewrite H4; simpl; case (Atom.get_type' t_i (Atom.t_interp t_i t_func t_atom) hb); try discriminate; simpl; rewrite andb_true_iff; change (Typ.eqb (Atom.get_type' t_i (Atom.t_interp t_i t_func t_atom) x) A = true) with (is_true (Typ.eqb (Atom.get_type' t_i (Atom.t_interp t_i t_func t_atom) x) A)); change (Typ.eqb (Atom.get_type' t_i (Atom.t_interp t_i t_func t_atom) y) A = true) with (is_true (Typ.eqb (Atom.get_type' t_i (Atom.t_interp t_i t_func t_atom) y) A)); rewrite !Typ.eqb_spec; intros [H8 H9]; generalize (Atom.check_aux_interp_hatom _ t_func _ wf_t_atom x), (Atom.check_aux_interp_hatom _ t_func _ wf_t_atom y); rewrite H8, H9; intros [v1 HH1] [v2 HH2]; rewrite HH1, HH2; simpl; rewrite Typ.cast_refl; auto; rewrite Typ.i_eqb_sym; auto.
+ Qed.
+
+
+ (* Lemma interp_check_distinct : forall ha diseq, *)
+ (* check_distinct ha diseq -> *)
+ (* interp_form_hatom ha -> afold_left bool int true andb (Lit.interp rho) diseq. *)
+ (* Proof. *)
+ (* intros ha diseq; rewrite check_distinct_spec; intros [A [dist [H1 H]]]; rewrite check_diseqs_spec in H; unfold Atom.interp_form_hatom, Atom.interp_bool, Atom.interp_hatom; rewrite Atom.t_interp_wf; auto; rewrite H1; simpl; generalize (Atom.compute_interp_spec_rev t_i (get (Atom.t_interp t_i t_func t_atom)) A dist); case (Atom.compute_interp t_i (get (Atom.t_interp t_i t_func t_atom)) A nil); simpl. *)
+ (* intros l H2; unfold is_true; rewrite distinct_spec; intro H3; apply afold_left_andb_true; intros i Hi; destruct (H _ Hi) as [H4 [a [H5 [h1 [h2 [H6 [H7 H8]]]]]]]; unfold Lit.interp; replace (Lit.is_pos (diseq .[ i])) with false by (case_eq (Lit.is_pos (diseq .[ i])); auto); unfold Var.interp; rewrite Form.wf_interp_form; auto; rewrite H5; simpl; rewrite Atom.t_interp_wf; auto; rewrite H6; simpl; unfold Atom.apply_binop; unfold Atom.wt in wt_t_atom; unfold is_true in wt_t_atom; rewrite forallbi_spec in wt_t_atom; assert (H10: a < length t_atom). *)
+ (* case_eq (a < length t_atom); auto; intro H10; rewrite (get_outofbound _ _ _ H10) in H6; rewrite default_t_atom in H6; inversion H6. *)
+ (* generalize (wt_t_atom _ H10); rewrite H6; simpl; rewrite !andb_true_iff. change (Typ.eqb (Atom.get_type t_i t_func t_atom h1) A = true) with (is_true (Typ.eqb (Atom.get_type t_i t_func t_atom h1) A)); change (Typ.eqb (Atom.get_type t_i t_func t_atom h2) A = true) with (is_true (Typ.eqb (Atom.get_type t_i t_func t_atom h2) A)); rewrite !Typ.eqb_spec; intros [[_ H11] H12]; generalize (Atom.check_aux_interp_hatom _ t_func _ wf_t_atom h1); rewrite H11; intros [v1 HH1]; generalize (Atom.check_aux_interp_hatom _ t_func _ wf_t_atom h2); rewrite H12; intros [v2 HH2]; rewrite HH1, HH2; simpl; rewrite Typ.cast_refl; simpl; destruct H8 as [H8|H8]; [ |rewrite Typ.i_eqb_sym]; rewrite H3; auto; rewrite H2; [exists h2; exists h1|exists h1; exists h2]; auto. *)
+ (* intros [a [H2 H3]] _; assert (H4: ha < length t_atom). *)
+ (* case_eq (ha < length t_atom); auto; intro Heq; generalize H1; rewrite get_outofbound; auto; rewrite default_t_atom; discriminate. *)
+ (* unfold Atom.wt in wt_t_atom; unfold is_true in wt_t_atom; rewrite forallbi_spec in wt_t_atom; generalize (wt_t_atom _ H4); rewrite H1; simpl; rewrite andb_true_iff, forallb_forall; intros [_ H5]; assert (H6 := H5 _ H2); generalize (Atom.check_aux_interp_hatom _ t_func _ wf_t_atom a); intros [va Ha]; rewrite Ha in H3; simpl in H3; elim H3; apply Typ.eqb_spec; auto. *)
+ (* Qed. *)
+
+ End Valid1.
+
+
+ Section AUX.
+
+ Variable check_var : var -> var -> bool.
+
+ Definition check_lit l1 l2 :=
+ (l1 == l2) || ((Bool.eqb (Lit.is_pos l1) (Lit.is_pos l2)) && (check_var (Lit.blit l1) (Lit.blit l2))) || ((Bool.eqb (Lit.is_pos l1) (negb (Lit.is_pos l2))) && (check_distinct_two_args (Lit.blit l1) (Lit.blit l2))).
+
+ (* Definition check_lit l1 l2 := *)
+ (* (l1 == l2) || ((Lit.is_pos l1) && (Lit.is_pos l2) && (check_var (Lit.blit l1) (Lit.blit l2))) || ((negb (Lit.is_pos l1)) && (negb (Lit.is_pos l2)) && (check_var (Lit.blit l2) (Lit.blit l1))). *)
+
+ Definition check_form_aux a b :=
+ match a, b with
+ | Fatom ha, Fand diseq => check_distinct ha diseq
+ | Fatom a, Fatom b => a == b
+ | Ftrue, Ftrue => true
+ | Ffalse, Ffalse => true
+ | Fnot2 i1 l1, Fnot2 i2 l2 => (i1 == i2) && (check_lit l1 l2)
+ | Fand a1, Fand a2 => (length a1 == length a2) && (forallbi (fun i l => check_lit l (a2.[i])) a1)
+ | For a1, For a2 => (length a1 == length a2) && (forallbi (fun i l => check_lit l (a2.[i])) a1)
+ | Fimp a1, Fimp a2 => (length a1 == length a2) && (forallbi (fun i l => check_lit l (a2.[i])) a1)
+ (* (length a1 == length a2) && (forallbi (fun i l => if i < length a1 - 1 then check_lit (a2.[i]) l else check_lit l (a2.[i])) a1) *)
+ | Fxor l1 l2, Fxor j1 j2 => check_lit l1 j1 && check_lit l2 j2
+ (* check_lit l1 j1 && check_lit j1 l1 && check_lit l2 j2 && check_lit j2 l2 *)
+ (* (* let a := check_lit l1 j1 in *) *)
+ (* (* let b := check_lit l2 j2 in *) *)
+ (* (* let c := check_lit l1 j2 in *) *)
+ (* (* let d := check_lit l2 j1 in *) *)
+ (* (* let e := check_lit j1 l1 in *) *)
+ (* (* let f := check_lit j1 l2 in *) *)
+ (* (* negb (((negb a) && b && (negb c)) || (c && e && (negb f)) || (b && (negb e) && f) || (a && (negb b) && (negb d))) *) *)
+ | Fiff l1 l2, Fiff j1 j2 => check_lit l1 j1 && check_lit l2 j2
+ (* check_lit l1 j1 && check_lit j1 l1 && check_lit l2 j2 && check_lit j2 l2 *)
+ | Fite l1 l2 l3, Fite j1 j2 j3 => check_lit l1 j1 && check_lit l2 j2 && check_lit l3 j3
+ (* check_lit l1 j1 && check_lit j1 l1 && check_lit l2 j2 && check_lit l3 j3 *)
+ | _, _ => false
+ end.
+
+ Variables (t_i : array typ_eqb)
+ (t_func : array (Atom.tval t_i))
+ (ch_atom : Atom.check_atom t_atom)
+ (ch_form : Form.check_form t_form)
+ (wt_t_atom : Atom.wt t_i t_func t_atom).
+
+ Local Notation interp_form_hatom :=
+ (Atom.interp_form_hatom t_i t_func t_atom).
+ Local Notation rho :=
+ (Form.interp_state_var interp_form_hatom t_form).
+
+ Hypothesis interp_check_var : forall x y,
+ check_var x y -> Var.interp rho x = Var.interp rho y.
+
+ (* Hypothesis interp_check_var : forall x y, *)
+ (* check_var x y -> Var.interp rho x -> Var.interp rho y. *)
+
+ (* Local Hint Resolve interp_check_var. *)
+
+ Lemma interp_check_lit : forall l1 l2,
+ check_lit l1 l2 -> Lit.interp rho l1 = Lit.interp rho l2.
+ Proof.
+ unfold check_lit; intros l1 l2; unfold is_true; rewrite !orb_true_iff, !andb_true_iff; intros [[H1|[H1 H2]]|[H1 H2]].
+ rewrite eqb_spec in H1; rewrite H1; auto.
+ rewrite Bool.eqb_true_iff in H1; unfold Lit.interp; rewrite H1, (interp_check_var _ _ H2); auto.
+ generalize H1; unfold Lit.interp; case (Lit.is_pos l1); case (Lit.is_pos l2); try discriminate; intros _; unfold Var.interp; rewrite (interp_check_distinct_two_args _ t_func ch_atom ch_form wt_t_atom _ _ H2); auto; case (rho (Lit.blit l2)); auto.
+ Qed.
+
+ (* Lemma interp_check_lit : forall l1 l2, *)
+ (* check_lit l1 l2 -> Lit.interp rho l1 -> Lit.interp rho l2 = true. *)
+ (* Proof. *)
+ (* unfold check_lit; intros l1 l2; unfold is_true; rewrite !orb_true_iff, !andb_true_iff; intros [[H1|[[H1 H2] H3]]|[[H1 H2] H3]]. *)
+ (* rewrite Int63Properties.eqb_spec in H1; subst l1; auto. *)
+ (* unfold Lit.interp; rewrite H1, H2; apply interp_check_var; auto. *)
+ (* unfold Lit.interp; case_eq (Lit.is_pos l1); intro Heq; rewrite Heq in H1; try discriminate; clear Heq H1; case_eq (Lit.is_pos l2); intro Heq; rewrite Heq in H2; try discriminate; clear Heq H2; case_eq (Var.interp rho (Lit.blit l1)); try discriminate; intros H4 _; case_eq (Var.interp rho (Lit.blit l2)); auto; intro H5; rewrite (interp_check_var _ _ H3 H5) in H4; discriminate. *)
+ (* Qed. *)
+
+ (* Local Hint Resolve interp_check_lit. *)
+
+ Lemma interp_check_form_aux : forall a b,
+ check_form_aux a b ->
+ Form.interp interp_form_hatom t_form a = Form.interp interp_form_hatom t_form b.
+ Proof.
+ intros [a| | |i1 l1|a1|a1|a1|l1 l2|l1 l2|l1 l2 l3] [b| | |j1 m1|a2|a2|a2|j1 j2|j1 j2|j1 j2 j3]; simpl; try discriminate;auto.
+ (* Atom *)
+ unfold is_true; rewrite Int63Properties.eqb_spec; intro; subst a; auto.
+ (* Interesting case *)
+ apply interp_check_distinct; auto.
+ (* Double negation *)
+ unfold is_true; rewrite andb_true_iff, Int63Properties.eqb_spec; intros [H1 H2]; subst j1. rewrite (interp_check_lit _ _ H2). auto.
+ (* Conjunction *)
+ unfold is_true; rewrite andb_true_iff, eqb_spec, forallbi_spec; intros [H1 H2]; apply afold_left_eq; auto; intros i Hi; apply interp_check_lit; auto.
+ (* Disjunction *)
+ unfold is_true; rewrite andb_true_iff, eqb_spec, forallbi_spec; intros [H1 H2]; apply afold_left_eq; auto; intros i Hi; apply interp_check_lit; auto.
+ (* Implication *)
+ unfold is_true; rewrite andb_true_iff, eqb_spec, forallbi_spec; intros [H1 H2]; apply afold_right_eq; auto; intros i Hi; apply interp_check_lit; auto.
+ (* Xor *)
+ unfold is_true; rewrite andb_true_iff; intros [H1 H2]; rewrite (interp_check_lit _ _ H1), (interp_check_lit _ _ H2); auto.
+ (* Iff *)
+ unfold is_true; rewrite andb_true_iff; intros [H1 H2]; rewrite (interp_check_lit _ _ H1), (interp_check_lit _ _ H2); auto.
+ (* Ite *)
+ unfold is_true; rewrite !andb_true_iff; intros [[H1 H2] H3]; rewrite (interp_check_lit _ _ H1), (interp_check_lit _ _ H2), (interp_check_lit _ _ H3); auto.
+ Qed.
+
+ (* Lemma interp_check_lit_equiv : forall l1 l2, *)
+ (* check_lit l1 l2 -> check_lit l2 l1 -> *)
+ (* Lit.interp rho l1 = Lit.interp rho l2. *)
+ (* Proof. *)
+ (* intros l1 l2 H1 H2; generalize (interp_check_lit _ _ H1) (interp_check_lit _ _ H2); case (Lit.interp rho l1); case (Lit.interp rho l2); auto; symmetry; auto. *)
+ (* Qed. *)
+
+ (* Lemma interp_check_form_aux : forall a b, *)
+ (* check_form_aux a b -> *)
+ (* Form.interp interp_form_hatom t_form a -> Form.interp interp_form_hatom t_form b. *)
+ (* Proof. *)
+ (* intros [a| | |i1 l1|a1|a1|a1|l1 l2|l1 l2|l1 l2 l3] [b| | |j1 m1|a2|a2|a2|j1 j2|j1 j2|j1 j2 j3]; simpl; try discriminate;auto. *)
+ (* (* Atom *) *)
+ (* unfold is_true; rewrite Int63Properties.eqb_spec; intro; subst a; auto. *)
+ (* (* Interesting case *) *)
+ (* apply interp_check_distinct; auto. *)
+ (* (* Double negation *) *)
+ (* unfold is_true; rewrite andb_true_iff, Int63Properties.eqb_spec; intros [H1 H2]; subst j1; apply (fold_ind2 _ _ (fun x y => x = true -> y = true)). *)
+ (* apply interp_check_lit; auto. *)
+ (* intros a b; case a; try discriminate; intros H _; rewrite H; auto. *)
+ (* (* Conjunction *) *)
+ (* unfold is_true; rewrite andb_true_iff, Int63Properties.eqb_spec; intros [H1 H2]; rewrite forallbi_spec in H2; intro H3; assert (H4 := afold_left_andb_true_inv _ _ _ H3); clear H3; apply afold_left_andb_true; rewrite <- H1; intros i Hi; eapply interp_check_lit; eauto. *)
+ (* (* Disjunction *) *)
+ (* unfold is_true; rewrite andb_true_iff, Int63Properties.eqb_spec; intros [H1 H2]; rewrite forallbi_spec in H2; intro H3; assert (H4 := afold_left_orb_true_inv _ _ _ H3); clear H3; destruct H4 as [i [H3 H4]]; eapply afold_left_orb_true. *)
+ (* rewrite <- H1; eauto. *)
+ (* eapply interp_check_lit; eauto. *)
+ (* (* Implication *) *)
+ (* unfold is_true; rewrite andb_true_iff, Int63Properties.eqb_spec; intros [H1 H2]; rewrite forallbi_spec in H2; intro H3; apply afold_right_implb_true; case_eq (length a1 == 0); intro Heq. *)
+ (* left; rewrite eqb_spec in Heq; rewrite <- H1; auto. *)
+ (* destruct (afold_right_implb_true_inv _ _ _ H3) as [H4|[[i [H4 H5]]|H4]]. *)
+ (* rewrite H4 in Heq; discriminate. *)
+ (* right; left; exists i; rewrite <- H1; split; auto; case_eq (Lit.interp rho (a2 .[ i])); auto; intro H6; assert (H7: i < length a1 = true). *)
+ (* rewrite ltb_spec in *; rewrite eqb_false_spec in Heq; rewrite to_Z_sub_1_diff in H4; auto; omega. *)
+ (* generalize (H2 _ H7); rewrite H4; intro H8; rewrite (interp_check_lit _ _ H8 H6) in H5; auto. *)
+ (* right; case_eq (existsbi (fun i l => (i < length a2 - 1) && (negb (Lit.interp rho l))) a2). *)
+ (* rewrite existsbi_spec; intros [i [_ H5]]; rewrite andb_true_iff in H5; destruct H5 as [H5 H6]; left; exists i; split; auto; generalize H6; case (Lit.interp rho (a2 .[ i])); auto; discriminate. *)
+ (* rewrite existsbi_false_spec; intro H; right; intros i Hi; assert (Hi' := Hi); rewrite <- H1 in Hi'; generalize (H2 _ Hi') (H _ Hi); rewrite <- H1; case (i < length a1 - 1); simpl. *)
+ (* intros _; case (Lit.interp rho (a2 .[ i])); auto; discriminate. *)
+ (* intros H5 _; apply (interp_check_lit _ _ H5); apply H4; auto. *)
+ (* (* Xor *) *)
+ (* unfold is_true; rewrite !andb_true_iff; intros [[[H1 H2] H3] H4]; rewrite (interp_check_lit_equiv _ _ H1 H2), (interp_check_lit_equiv _ _ H3 H4); auto. *)
+ (* (* Iff *) *)
+ (* unfold is_true; rewrite !andb_true_iff; intros [[[H1 H2] H3] H4]; rewrite (interp_check_lit_equiv _ _ H1 H2), (interp_check_lit_equiv _ _ H3 H4); auto. *)
+ (* (* Ite *) *)
+ (* unfold is_true; rewrite !andb_true_iff; intros [[[H1 H2] H3] H4]; rewrite (interp_check_lit_equiv _ _ H1 H2); case (Lit.interp rho j1); apply interp_check_lit; auto. *)
+ (* Qed. *)
+
+ End AUX.
+
+ Definition check_hform h1 h2 :=
+ foldi_down_cont
+ (fun _ cont h1 h2 => (h1 == h2) || check_form_aux cont (get_form h1) (get_form h2))
+ (PArray.length t_form) 0 (fun h1 h2 => false) h1 h2.
+
+ Definition check_form := check_form_aux check_hform.
+
+ Definition check_lit' := check_lit check_hform.
+
+ Fixpoint check_distinct_elim input res :=
+ match input with
+ | nil => nil
+ | l::q => if check_lit' l res then res::q else l::(check_distinct_elim q res)
+ end.
+
+
+ Section Valid.
+
+ Variables (t_i : array typ_eqb)
+ (t_func : array (Atom.tval t_i))
+ (ch_atom : Atom.check_atom t_atom)
+ (ch_form : Form.check_form t_form)
+ (wt_t_atom : Atom.wt t_i t_func t_atom).
+
+ Local Notation interp_form_hatom :=
+ (Atom.interp_form_hatom t_i t_func t_atom).
+ Local Notation rho :=
+ (Form.interp_state_var interp_form_hatom t_form).
+
+
+ Let wf_rho : Valuation.wf rho.
+ Proof. destruct (Form.check_form_correct interp_form_hatom _ ch_form); auto. Qed.
+
+ Let default_t_form : default t_form = Ftrue.
+ Proof. destruct (Form.check_form_correct interp_form_hatom _ ch_form) as [[H _] _]; auto. Qed.
+
+ Let wf_t_form : wf t_form.
+ Proof. destruct (Form.check_form_correct interp_form_hatom _ ch_form) as [[_ H] _]; auto. Qed.
+
+ Local Hint Immediate wf_rho default_t_form wf_t_form.
+
+
+ Lemma interp_check_hform : forall h1 h2,
+ check_hform h1 h2 -> Var.interp rho h1 = Var.interp rho h2.
+ Proof.
+ unfold check_hform; apply foldi_down_cont_ind; try discriminate. intros i cont _ _ Hrec h1 h2. unfold is_true; rewrite orb_true_iff; intros [H|H].
+ rewrite Int63Properties.eqb_spec in H; rewrite H; auto.
+ unfold Var.interp; rewrite !wf_interp_form; auto; eapply interp_check_form_aux; eauto.
+ Qed.
+
+ Local Hint Resolve interp_check_hform.
+
+
+ Lemma interp_check_form : forall a b,
+ check_form a b ->
+ Form.interp interp_form_hatom t_form a = Form.interp interp_form_hatom t_form b.
+ Proof. apply interp_check_form_aux, interp_check_hform; auto. Qed.
+
+
+ Lemma interp_check_lit' : forall l res,
+ check_lit' l res -> Lit.interp rho l = Lit.interp rho res.
+ Proof. apply interp_check_lit, interp_check_hform; auto. Qed.
+
+
+ Lemma valid_check_distinct_elim :
+ forall input, C.valid rho input ->
+ forall res, C.valid rho (check_distinct_elim input res).
+ Proof.
+ induction input as [ |l c IHc]; auto; simpl; unfold C.valid; simpl; rewrite orb_true_iff; intros [H|H] res.
+ case_eq (check_lit' l res); intro Heq; simpl.
+ rewrite <- (interp_check_lit' _ _ Heq), H; auto.
+ rewrite H; auto.
+ case (check_lit' l res).
+ simpl; rewrite H, orb_true_r; auto.
+ simpl; rewrite (IHc H), orb_true_r; auto.
+ Qed.
+
+ End Valid.
+
+End Operators.
diff --git a/src/spl/Syntactic.v b/src/spl/Syntactic.v
new file mode 100644
index 0000000..d7d2594
--- /dev/null
+++ b/src/spl/Syntactic.v
@@ -0,0 +1,531 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+(*** Spl -- a small checker for simplifications ***)
+
+(* Add LoadPath ".." as SMTCoq. *)
+(* Add LoadPath "../lia" as SMTCoq.lia. *)
+Require Import List PArray Bool Int63 ZMicromega.
+Require Import Misc State SMT_terms.
+Require Lia.
+
+Local Open Scope array_scope.
+Local Open Scope int63_scope.
+
+
+(* Flattening and small arithmetic simplifications *)
+
+Section CheckAtom.
+
+ Import Atom.
+
+ Variable t_i : PArray.array typ_eqb.
+ Variable t_func : PArray.array (tval t_i).
+ Variable t_atom : PArray.array atom.
+
+ Local Notation get_atom := (PArray.get t_atom).
+
+ Section AUX.
+
+ Variable check_hatom : hatom -> hatom -> bool.
+
+ Definition check_atom_aux a b :=
+ match a, b with
+ | Acop o1, Acop o2 => cop_eqb o1 o2
+
+ (* Two ways to define a negative integer *)
+ | Auop UO_Zopp p1, Auop UO_Zneg q =>
+ match get_atom p1 with
+ | Auop UO_Zpos p => check_hatom p q
+ | _ => false
+ end
+ | Auop UO_Zneg p, Auop UO_Zopp q1 =>
+ match get_atom q1 with
+ | Auop UO_Zpos q => check_hatom p q
+ | _ => false
+ end
+
+ | Auop o1 a, Auop o2 b => uop_eqb o1 o2 && check_hatom a b
+ | Abop o1 a1 a2, Abop o2 b1 b2 =>
+ match o1, o2 with
+ | BO_Zplus, BO_Zplus
+ | BO_Zmult, BO_Zmult => (check_hatom a1 b1 && check_hatom a2 b2) || (check_hatom a1 b2 && check_hatom a2 b1)
+ | BO_Zminus, BO_Zminus
+ | BO_Zlt, BO_Zlt
+ | BO_Zle, BO_Zle
+ | BO_Zge, BO_Zge
+ | BO_Zgt, BO_Zgt => check_hatom a1 b1 && check_hatom a2 b2
+ | BO_Zge, BO_Zle
+ | BO_Zle, BO_Zge
+ | BO_Zgt, BO_Zlt
+ | BO_Zlt, BO_Zgt => check_hatom a1 b2 && check_hatom a2 b1
+ | BO_eq t1, BO_eq t2 =>
+ Typ.eqb t1 t2 &&
+ ((check_hatom a1 b1 && check_hatom a2 b2) ||
+ (check_hatom a1 b2 && check_hatom a2 b1))
+ | _, _ => false
+ end
+ | Anop o1 l1, Anop o2 l2 =>
+ match o1, o2 with
+ | NO_distinct t1, NO_distinct t2 => Typ.eqb t1 t2 && list_beq check_hatom l1 l2
+ end
+ | Aapp f1 aargs, Aapp f2 bargs =>(f1 == f2) && list_beq check_hatom aargs bargs
+
+ | _, _ => false
+ end.
+
+
+ Hypothesis check_hatom_correct : forall h1 h2, check_hatom h1 h2 ->
+ interp_hatom t_i t_func t_atom h1 = interp_hatom t_i t_func t_atom h2.
+ Hypothesis Hwf: wf t_atom.
+ Hypothesis Hd: default t_atom = Acop CO_xH.
+
+
+ Lemma list_beq_correct : forall l1 l2,
+ list_beq check_hatom l1 l2 = true ->
+ List.map (interp_hatom t_i t_func t_atom) l1 =
+ List.map (interp_hatom t_i t_func t_atom) l2.
+ Proof.
+ induction l1 as [ |h1 l1 IHl1]; intros [ |h2 l2]; simpl; try discriminate; auto; rewrite andb_true_iff; intros [H1 H2]; rewrite (IHl1 _ H2); rewrite (check_hatom_correct _ _ H1); auto.
+ Qed.
+
+
+ Lemma list_beq_compute_interp : forall t l1 l2,
+ list_beq check_hatom l1 l2 = true -> forall acc,
+ compute_interp t_i (interp_hatom t_i t_func t_atom) t acc l1 =
+ compute_interp t_i (interp_hatom t_i t_func t_atom) t acc l2.
+ Proof.
+ intro t; induction l1 as [ |h1 l1 IHl1]; intros [ |h2 l2]; simpl; try discriminate; auto; rewrite andb_true_iff; intros [H1 H2] acc; rewrite (check_hatom_correct _ _ H1); destruct (interp_hatom t_i t_func t_atom h2) as [ta va]; destruct (Typ.cast ta t) as [ka| ]; auto.
+ Qed.
+
+
+ Lemma check_atom_aux_correct : forall a1 a2, check_atom_aux a1 a2 ->
+ interp t_i t_func t_atom a1 = interp t_i t_func t_atom a2.
+ Proof.
+ intros [op1|op1 i1|op1 i1 j1|op1 li1|f1 args1]; simpl.
+ (* Constants *)
+ intros [op2|op2 i2|op2 i2 j2|op2 li2|f2 args2]; simpl; try discriminate; pose (H:=reflect_cop_eqb op1 op2); inversion H; try discriminate; subst op1; auto.
+ (* Unary operators *)
+ intros [op2|op2 i2|op2 i2 j2|op2 li2|f2 args2]; simpl; try discriminate; try (case op1; discriminate).
+ case op1; case op2; try discriminate; try (unfold is_true; rewrite andb_true_iff; intros [_ H]; rewrite (check_hatom_correct _ _ H); auto).
+ case_eq (get_atom i2); try discriminate; intros [ | | | | ] i Heq H; try discriminate; simpl; unfold apply_unop; rewrite (check_hatom_correct _ _ H); unfold interp_hatom; rewrite (t_interp_wf _ _ _ Hwf Hd i2), Heq; simpl; unfold apply_unop; destruct (t_interp t_i t_func t_atom .[ i]) as [A v]; destruct (Typ.cast A Typ.Tpositive) as [k| ]; auto.
+ case_eq (get_atom i1); try discriminate; intros [ | | | | ] i Heq H; try discriminate; simpl; unfold apply_unop; rewrite <- (check_hatom_correct _ _ H); unfold interp_hatom; rewrite (t_interp_wf _ _ _ Hwf Hd i1), Heq; simpl; unfold apply_unop; destruct (t_interp t_i t_func t_atom .[ i]) as [A v]; destruct (Typ.cast A Typ.Tpositive) as [k| ]; auto.
+ (* Binary operators *)
+ intros [op2|op2 i2|op2 i2 j2|op2 li2|f2 args2]; simpl; try discriminate; case op1; case op2; try discriminate; try (unfold is_true; rewrite andb_true_iff; intros [H1 H2]; rewrite (check_hatom_correct _ _ H1), (check_hatom_correct _ _ H2); auto).
+ unfold is_true, interp_bop, apply_binop. rewrite orb_true_iff, !andb_true_iff. intros [[H1 H2]|[H1 H2]]; rewrite (check_hatom_correct _ _ H1), (check_hatom_correct _ _ H2); destruct (interp_hatom t_i t_func t_atom i2) as [A v1]; destruct (interp_hatom t_i t_func t_atom j2) as [B v2]; destruct (Typ.cast B Typ.TZ) as [k2| ]; destruct (Typ.cast A Typ.TZ) as [k1| ]; auto; rewrite Z.add_comm; reflexivity.
+ unfold is_true, interp_bop, apply_binop. rewrite orb_true_iff, !andb_true_iff. intros [[H1 H2]|[H1 H2]]; rewrite (check_hatom_correct _ _ H1), (check_hatom_correct _ _ H2); destruct (interp_hatom t_i t_func t_atom i2) as [A v1]; destruct (interp_hatom t_i t_func t_atom j2) as [B v2]; destruct (Typ.cast B Typ.TZ) as [k2| ]; destruct (Typ.cast A Typ.TZ) as [k1| ]; auto; rewrite Z.mul_comm; reflexivity.
+ unfold interp_bop, apply_binop; destruct (interp_hatom t_i t_func t_atom j2) as [B v2]; destruct (interp_hatom t_i t_func t_atom i2) as [A v1]; destruct (Typ.cast B Typ.TZ) as [k2| ]; destruct (Typ.cast A Typ.TZ) as [k1| ]; auto; rewrite Z.gtb_ltb; auto.
+ unfold interp_bop, apply_binop; destruct (interp_hatom t_i t_func t_atom j2) as [B v2]; destruct (interp_hatom t_i t_func t_atom i2) as [A v1]; destruct (Typ.cast B Typ.TZ) as [k2| ]; destruct (Typ.cast A Typ.TZ) as [k1| ]; auto; rewrite Z.geb_leb; auto.
+ unfold interp_bop, apply_binop; destruct (interp_hatom t_i t_func t_atom j2) as [B v2]; destruct (interp_hatom t_i t_func t_atom i2) as [A v1]; destruct (Typ.cast B Typ.TZ) as [k2| ]; destruct (Typ.cast A Typ.TZ) as [k1| ]; auto; rewrite Z.geb_leb; auto.
+ unfold interp_bop, apply_binop; destruct (interp_hatom t_i t_func t_atom j2) as [B v2]; destruct (interp_hatom t_i t_func t_atom i2) as [A v1]; destruct (Typ.cast B Typ.TZ) as [k2| ]; destruct (Typ.cast A Typ.TZ) as [k1| ]; auto; rewrite Z.gtb_ltb; auto.
+ intros A B; unfold is_true; rewrite andb_true_iff, orb_true_iff; change (Typ.eqb B A = true) with (is_true (Typ.eqb B A)); rewrite Typ.eqb_spec; intros [H2 [H1|H1]]; subst B; rewrite andb_true_iff in H1; destruct H1 as [H1 H2]; rewrite (check_hatom_correct _ _ H1), (check_hatom_correct _ _ H2); auto; simpl; unfold apply_binop; destruct (interp_hatom t_i t_func t_atom j2) as [B v1]; destruct (interp_hatom t_i t_func t_atom i2) as [C v2]; destruct (Typ.cast B A) as [k1| ]; destruct (Typ.cast C A) as [k2| ]; auto; rewrite Typ.i_eqb_sym; auto.
+ (* N-ary operators *)
+ intros [op2|op2 i2|op2 i2 j2|op2 li2|f2 args2]; simpl; try discriminate; destruct op1 as [t1]; destruct op2 as [t2]; unfold is_true; rewrite andb_true_iff; change (Typ.eqb t1 t2 = true) with (is_true (Typ.eqb t1 t2)); rewrite Typ.eqb_spec; intros [H1 H2]; subst t2; rewrite (list_beq_compute_interp _ _ _ H2); auto.
+ (* Application *)
+ intros [op2|op2 i2|op2 i2 j2|op2 li2|f2 args2]; simpl; try discriminate; unfold is_true; rewrite andb_true_iff, Int63Properties.eqb_spec; intros [H2 H1]; subst f2; rewrite (list_beq_correct _ _ H1); auto.
+ Qed.
+
+ End AUX.
+
+ Definition check_hatom h1 h2 :=
+ foldi_down_cont
+ (fun _ cont h1 h2 => (h1 == h2) || check_atom_aux cont (t_atom.[h1]) (t_atom.[h2]))
+ (PArray.length t_atom) 0 (fun h1 h2 => false) h1 h2.
+
+ Definition check_atom := check_atom_aux check_hatom.
+
+ Definition check_neg_hatom h1 h2 :=
+ match get_atom h1, get_atom h2 with
+ | Abop op1 a1 a2, Abop op2 b1 b2 =>
+ match op1, op2 with
+ | BO_Zlt, BO_Zle => check_hatom a1 b2 && check_hatom a2 b1
+ | BO_Zlt, BO_Zge => check_hatom a1 b1 && check_hatom a2 b2
+ | BO_Zle, BO_Zlt => check_hatom a1 b2 && check_hatom a2 b1
+ | BO_Zle, BO_Zgt => check_hatom a1 b1 && check_hatom a2 b2
+ | BO_Zge, BO_Zlt => check_hatom a1 b1 && check_hatom a2 b2
+ | BO_Zge, BO_Zgt => check_hatom a1 b2 && check_hatom a2 b1
+ | BO_Zgt, BO_Zle => check_hatom a1 b1 && check_hatom a2 b2
+ | BO_Zgt, BO_Zge => check_hatom a1 b2 && check_hatom a2 b1
+ | _, _ => false
+ end
+ | _, _ => false
+ end.
+
+ (* TODO : move this *)
+ Lemma Zge_is_ge_bool : forall x y, (x >= y) <-> (Zge_bool x y = true).
+ Proof.
+ intros x y;assert (W:=Zge_cases x y);destruct (Zge_bool x y).
+ split;auto.
+ split;[intros;elimtype false;auto with zarith | discriminate].
+ Qed.
+
+
+ (* Correctness of check_atom *)
+
+ Lemma check_hatom_correct : wf t_atom ->
+ default t_atom = Acop CO_xH ->
+ forall h1 h2, check_hatom h1 h2 ->
+ interp_hatom t_i t_func t_atom h1 = interp_hatom t_i t_func t_atom h2.
+ Proof.
+ unfold check_hatom;intros Hwf Hdef.
+ apply foldi_down_cont_ind;try discriminate.
+ intros i cont _ _ Hrec h1 h2.
+ unfold is_true; rewrite orb_true_iff; intros [H|H].
+ rewrite Int63Properties.eqb_spec in H; rewrite H; reflexivity.
+ unfold interp_hatom;rewrite !t_interp_wf;trivial.
+ apply check_atom_aux_correct with cont;trivial.
+ Qed.
+
+
+ Lemma check_atom_correct : wf t_atom ->
+ default t_atom = Acop CO_xH ->
+ forall a1 a2, check_atom a1 a2 ->
+ interp t_i t_func t_atom a1 = interp t_i t_func t_atom a2.
+ Proof.
+ intros Hwf Hdef;unfold check_atom;apply check_atom_aux_correct; auto.
+ apply check_hatom_correct;trivial.
+ Qed.
+
+
+ Lemma check_hatom_correct_bool : wf t_atom ->
+ default t_atom = Acop CO_xH ->
+ forall h1 h2, check_hatom h1 h2 ->
+ interp_form_hatom t_i t_func t_atom h1 = interp_form_hatom t_i t_func t_atom h2.
+ Proof.
+ unfold interp_form_hatom; intros H1 H2 h1 h2 H3; rewrite (check_hatom_correct H1 H2 h1 h2 H3); auto.
+ Qed.
+
+
+ (* Correctness of check_neg_atom *)
+
+ Lemma check_neg_hatom_correct : wt t_i t_func t_atom ->
+ wf t_atom -> default t_atom = Acop CO_xH ->
+ forall h1 h2, check_neg_hatom h1 h2 ->
+ match interp_hatom t_i t_func t_atom h1, interp_hatom t_i t_func t_atom h2 with
+ | Val Typ.Tbool v1, Val Typ.Tbool v2 => v1 = negb v2
+ | Val _ _, Val _ _ => False
+ end.
+ Proof.
+ unfold wt; unfold is_true at 1; rewrite forallbi_spec; intros Hwt Hwf Hdef h1 h2; unfold check_neg_hatom; case_eq (get_atom h1); try discriminate; intros b1 t11 t12 H1; case_eq (get_atom h2); try discriminate; intros b2 t21 t22 H2; assert (H7: h1 < length t_atom) by (apply PArray.get_not_default_lt; rewrite H1, Hdef; discriminate); generalize (Hwt _ H7); rewrite H1; simpl; generalize H1; case b1; try discriminate; clear H1 b1; simpl; intro H1; case (get_type' t_i (t_interp t_i t_func t_atom) h1); try discriminate; simpl; rewrite andb_true_iff; intros [H30 H31]; change (is_true (Typ.eqb (get_type' t_i (t_interp t_i t_func t_atom) t11) Typ.TZ)) in H30; change (is_true (Typ.eqb (get_type' t_i (t_interp t_i t_func t_atom) t12) Typ.TZ)) in H31; rewrite Typ.eqb_spec in H30, H31; generalize (check_aux_interp_hatom _ t_func _ Hwf t11), (check_aux_interp_hatom _ t_func _ Hwf t12); rewrite H30, H31; intros [v1 Hv1] [v2 Hv2]; generalize H2; case b2; try discriminate; clear H2 b2; intro H2; unfold is_true; rewrite andb_true_iff; intros [H3 H4]; generalize (check_hatom_correct Hwf Hdef _ _ H3), (check_hatom_correct Hwf Hdef _ _ H4); unfold interp_hatom; intros H5 H6; rewrite t_interp_wf; auto; rewrite H1; simpl; rewrite Hv1, Hv2; simpl; rewrite t_interp_wf; auto; rewrite H2; simpl; rewrite <- H5; rewrite <- H6, Hv1, Hv2; simpl.
+ rewrite Z.ltb_antisym; auto.
+ rewrite Z.geb_leb, Z.ltb_antisym; auto.
+ rewrite Z.leb_antisym; auto.
+ rewrite Z.gtb_ltb, Z.leb_antisym; auto.
+ rewrite Z.geb_leb, Z.leb_antisym; auto.
+ rewrite Z.geb_leb, Z.gtb_ltb, Z.leb_antisym; auto.
+ rewrite Z.gtb_ltb, Z.ltb_antisym; auto.
+ rewrite Z.geb_leb, Z.gtb_ltb, Z.ltb_antisym; auto.
+ Qed.
+
+
+ Lemma check_neg_hatom_correct_bool : wt t_i t_func t_atom ->
+ wf t_atom -> default t_atom = Acop CO_xH ->
+ forall h1 h2, check_neg_hatom h1 h2 ->
+ interp_form_hatom t_i t_func t_atom h1 = negb (interp_form_hatom t_i t_func t_atom h2).
+ Proof.
+ unfold interp_form_hatom. intros Hwt H1 H2 h1 h2 H3. unfold interp_bool. generalize (check_neg_hatom_correct Hwt H1 H2 _ _ H3). case (interp_hatom t_i t_func t_atom h1). case (interp_hatom t_i t_func t_atom h2). simpl. intros [i| | | ] v1 [j| | | ] v2; intro H; inversion H. rewrite Typ.cast_refl. auto.
+ Qed.
+
+End CheckAtom.
+
+
+(* Flattening *)
+
+Section FLATTEN.
+
+ Import Form.
+
+ Variable t_form : PArray.array form.
+
+ Local Notation get_form := (PArray.get t_form).
+
+ Definition remove_not l :=
+ match get_form (Lit.blit l) with
+ | Fnot2 _ l' => if Lit.is_pos l then l' else Lit.neg l'
+ | _ => l
+ end.
+
+ Definition get_and l :=
+ let l := remove_not l in
+ if Lit.is_pos l then
+ match get_form (Lit.blit l) with
+ | Fand args => Some args
+ | _ => None
+ end
+ else None.
+
+ Definition get_or l :=
+ let l := remove_not l in
+ if Lit.is_pos l then
+ match get_form (Lit.blit l) with
+ | For args => Some args
+ | _ => None
+ end
+ else None.
+
+ Definition flatten_op_body (get_op:_lit -> option (array _lit))
+ (frec : list _lit -> _lit -> list _lit)
+ (largs:list _lit) (l:_lit) : list _lit :=
+ match get_op l with
+ | Some a => PArray.fold_left frec largs a
+ | None => l::largs
+ end.
+ Register flatten_op_body as PrimInline.
+
+
+ Definition flatten_op_lit (get_op:_lit -> option (array _lit)) max :=
+ foldi_cont (fun _ => flatten_op_body get_op) 0 max (fun largs l => l::largs).
+
+ Definition flatten_and t :=
+ PArray.fold_left (flatten_op_lit get_and (PArray.length t_form)) nil t.
+
+ Definition flatten_or t :=
+ PArray.fold_left (flatten_op_lit get_or (PArray.length t_form)) nil t.
+
+
+ Variable check_atom check_neg_atom : atom -> atom -> bool.
+
+ Definition check_flatten_body frec (l lf:_lit) :=
+ let l := remove_not l in
+ let lf := remove_not lf in
+ if l == lf then true
+ else if 1 land (l lxor lf) == 0 then
+ match get_form (Lit.blit l), get_form (Lit.blit lf) with
+ | Fatom a1, Fatom a2 => check_atom a1 a2
+ | Ftrue, Ftrue => true
+ | Ffalse, Ffalse => true
+ | Fand args1, Fand args2 =>
+ let args1 := flatten_and args1 in
+ let args2 := flatten_and args2 in
+ forallb2 frec args1 args2
+ | For args1, For args2 =>
+ let args1 := flatten_or args1 in
+ let args2 := flatten_or args2 in
+ forallb2 frec args1 args2
+ | Fxor l1 l2, Fxor lf1 lf2 =>
+ frec l1 lf1 && frec l2 lf2
+ | Fimp args1, Fimp args2 =>
+ if PArray.length args1 == PArray.length args2 then
+ PArray.forallbi (fun i l => frec l (args2.[i])) args1
+ else false
+ | Fiff l1 l2, Fiff lf1 lf2 =>
+ frec l1 lf1 && frec l2 lf2
+ | Fite l1 l2 l3, Fite lf1 lf2 lf3 =>
+ frec l1 lf1 && frec l2 lf2 && frec l3 lf3
+ | _, _ => false
+ end
+ else
+ match get_form (Lit.blit l), get_form (Lit.blit lf) with
+ | Fatom a1, Fatom a2 => check_neg_atom a1 a2
+ | _, _ => false (* We maybe need to extend the rule here ... *)
+ end.
+ Register check_flatten_body as PrimInline.
+
+ Definition check_flatten_aux l lf :=
+ foldi_cont (fun _ => check_flatten_body) 0 (PArray.length t_form) (fun _ _ => false) l lf.
+
+ Definition check_flatten s cid lf :=
+ match S.get s cid with
+ | l :: nil =>
+ if check_flatten_aux l lf then lf::nil else C._true
+ | _ => C._true
+ end.
+
+
+ (** Correctness proofs *)
+ Variable interp_atom : atom -> bool.
+ Hypothesis default_thf : default t_form = Ftrue.
+ Hypothesis wf_thf : wf t_form.
+ Hypothesis check_atom_correct :
+ forall a1 a2, check_atom a1 a2 -> interp_atom a1 = interp_atom a2.
+ Hypothesis check_neg_atom_correct :
+ forall a1 a2, check_neg_atom a1 a2 -> interp_atom a1 = negb (interp_atom a2).
+
+ Local Notation interp_var := (interp_state_var interp_atom t_form).
+ Local Notation interp_lit := (Lit.interp interp_var).
+
+ Lemma interp_Fnot2 : forall i l, interp interp_atom t_form (Fnot2 i l) = interp_lit l.
+ Proof.
+ intros i l;simpl;apply fold_ind;trivial.
+ intros a;rewrite negb_involutive;trivial.
+ Qed.
+
+ Lemma remove_not_correct :
+ forall l, interp_lit (remove_not l) = interp_lit l.
+ Proof.
+ unfold remove_not;intros l.
+ case_eq (get_form (Lit.blit l));intros;trivial.
+ unfold Lit.interp, Var.interp.
+ rewrite (wf_interp_form interp_atom t_form default_thf wf_thf (Lit.blit l)), H, interp_Fnot2.
+ destruct(Lit.is_pos l);trivial.
+ rewrite Lit.is_pos_neg, Lit.blit_neg;unfold Lit.interp;destruct (Lit.is_pos i0);trivial.
+ rewrite negb_involutive;trivial.
+ Qed.
+
+ Lemma get_and_correct : forall l args, get_and l = Some args ->
+ interp_lit l = interp interp_atom t_form (Fand args).
+ Proof.
+ unfold get_and;intros l args.
+ rewrite <- remove_not_correct;unfold Lit.interp;generalize (remove_not l).
+ intros l';unfold Var.interp.
+ destruct (Lit.is_pos l');[ | discriminate].
+ rewrite wf_interp_form;trivial.
+ destruct (get_form (Lit.blit l'));intros Heq;inversion Heq;trivial.
+ Qed.
+
+ Lemma get_or_correct : forall l args, get_or l = Some args ->
+ interp_lit l = interp interp_atom t_form (For args).
+ Proof.
+ unfold get_or;intros l args.
+ rewrite <- remove_not_correct;unfold Lit.interp;generalize (remove_not l).
+ intros l';unfold Var.interp.
+ destruct (Lit.is_pos l');[ | discriminate].
+ rewrite wf_interp_form;trivial.
+ destruct (get_form (Lit.blit l'));intros Heq;inversion Heq;trivial.
+ Qed.
+
+ Lemma flatten_and_correct : forall args,
+ List.fold_right (fun l res => andb res (interp_lit l)) true (flatten_and args) =
+ afold_left _ _ true andb interp_lit args.
+ Proof.
+ intros;rewrite afold_left_spec;auto;unfold flatten_and.
+ set (t:= true);unfold t at 2;
+ change true with
+ (List.fold_right (fun (l : int) (res : bool) => res && interp_lit l) true nil).
+ unfold t;clear t.
+ rewrite !fold_left_to_list.
+ generalize (@nil int);induction (to_list args);simpl;trivial.
+ intros l0;rewrite IHl.
+ clear IHl;f_equal; unfold flatten_op_lit.
+ clear l;revert a l0;apply foldi_cont_ind;simpl;trivial.
+ intros i cont _ Hle Hrec a l;unfold flatten_op_body.
+ case_eq (get_and a);intros;trivial.
+ rewrite get_and_correct with (1:= H);simpl.
+ rewrite afold_left_spec; auto; rewrite !fold_left_to_list.
+ rewrite <- !fold_left_rev_right.
+ clear H a;revert l;induction (List.rev (to_list a0));simpl.
+ intros l;rewrite andb_true_r;trivial.
+ intros;rewrite Hrec, IHl, andb_assoc;trivial.
+ Qed.
+
+ Lemma flatten_or_correct : forall args,
+ List.fold_right (fun l res => orb res (interp_lit l)) false (flatten_or args) =
+ afold_left _ _ false orb interp_lit args.
+ Proof.
+ intros;rewrite afold_left_spec;auto;unfold flatten_or.
+ set (t:= false);unfold t at 2;
+ change false with
+ (List.fold_right (fun (l : int) (res : bool) => res || interp_lit l) false nil).
+ unfold t;clear t.
+ rewrite !fold_left_to_list.
+ generalize (@nil int);induction (to_list args);simpl;trivial.
+ intros l0;rewrite IHl.
+ clear IHl;f_equal; unfold flatten_op_lit.
+ clear l;revert a l0;apply foldi_cont_ind;simpl;trivial.
+ intros i cont _ Hle Hrec a l;unfold flatten_op_body.
+ case_eq (get_or a);intros;trivial.
+ rewrite get_or_correct with (1:= H);simpl.
+ rewrite afold_left_spec; auto; rewrite !fold_left_to_list.
+ rewrite <- !fold_left_rev_right.
+ clear H a;revert l;induction (List.rev (to_list a0));simpl.
+ intros l;rewrite orb_false_r;trivial.
+ intros;rewrite Hrec, IHl, orb_assoc;trivial.
+ Qed.
+
+ Lemma check_flatten_aux_correct : forall l lf,
+ check_flatten_aux l lf = true ->
+ interp_lit l = interp_lit lf.
+ Proof.
+ unfold check_flatten_aux.
+ apply foldi_cont_ind.
+ discriminate.
+ intros i cont _ Hle Hrec l lf;unfold check_flatten_body.
+ rewrite <- (remove_not_correct l), <- (remove_not_correct lf).
+ generalize (remove_not l) (remove_not lf);clear l lf;intros l lf.
+ destruct (reflect_eqb l lf);[ intros;subst;trivial | ].
+ destruct (reflect_eqb (1 land (l lxor lf)) 0).
+ unfold Lit.interp.
+ assert (Lit.is_pos l = Lit.is_pos lf).
+ unfold Lit.is_pos.
+ rewrite <- eqb_spec, land_comm in e.
+ change (is_true (is_even (l lxor lf))) in e.
+ rewrite is_even_xor in e.
+ destruct (is_even l);destruct (is_even lf);trivial;discriminate.
+ rewrite H;match goal with
+ |- ?P -> _ =>
+ assert (W:P -> Var.interp interp_var (Lit.blit l) = Var.interp interp_var (Lit.blit lf));
+ [ | intros;rewrite W;trivial]
+ end.
+ unfold Var.interp;rewrite !wf_interp_form;trivial.
+ clear e n H.
+ destruct (get_form (Lit.blit l));
+ destruct (get_form (Lit.blit lf));intros;try discriminate;simpl;trivial.
+ (* atom *)
+ apply check_atom_correct;trivial.
+ (* and *)
+ rewrite <- !flatten_and_correct.
+ revert H;generalize (flatten_and a) (flatten_and a0);clear a a0.
+ induction l0;intros l1;destruct l1;simpl;trivial;try discriminate.
+ rewrite andb_true_iff;intros (H1, H2).
+ rewrite (Hrec _ _ H1), (IHl0 _ H2);trivial.
+ (* or *)
+ rewrite <- !flatten_or_correct.
+ revert H;generalize (flatten_or a) (flatten_or a0);clear a a0.
+ induction l0;intros l1;destruct l1;simpl;trivial;try discriminate.
+ rewrite andb_true_iff;intros (H1, H2).
+ rewrite (Hrec _ _ H1), (IHl0 _ H2);trivial.
+ (* implb *)
+ revert H;destruct (reflect_eqb (length a) (length a0));[intros|discriminate].
+ apply afold_right_eq;trivial.
+ rewrite forallbi_spec in H;auto.
+ (* xorb *)
+ unfold is_true in H;rewrite andb_true_iff in H;destruct H as [H H0].
+ rewrite (Hrec _ _ H), (Hrec _ _ H0);trivial.
+ (* eqb (i.e iff) *)
+ unfold is_true in H;rewrite andb_true_iff in H;destruct H as [H H0].
+ rewrite (Hrec _ _ H), (Hrec _ _ H0);trivial.
+ (* ifb *)
+ unfold is_true in H;rewrite !andb_true_iff in H;destruct H as [[H H0] H1].
+ rewrite (Hrec _ _ H), (Hrec _ _ H0), (Hrec _ _ H1);trivial.
+ (** opposite sign *)
+ assert (Lit.is_pos l = negb (Lit.is_pos lf)).
+ unfold Lit.is_pos.
+ rewrite <- eqb_spec, land_comm in n0.
+ change (~is_true (is_even (l lxor lf))) in n0.
+ rewrite is_even_xor in n0.
+ destruct (is_even l);destruct (is_even lf);trivial;elim n0;reflexivity.
+ unfold Lit.interp;rewrite H. match goal with
+ |- ?P -> _ =>
+ assert (W:P -> Var.interp interp_var (Lit.blit l) = negb (Var.interp interp_var (Lit.blit lf)));
+ [ | intros;rewrite W;trivial]
+ end.
+ unfold Var.interp;rewrite !wf_interp_form;trivial.
+ destruct (get_form (Lit.blit l));try discriminate.
+ destruct (get_form (Lit.blit lf));try discriminate.
+ apply check_neg_atom_correct.
+ rewrite negb_involutive;destruct (Lit.is_pos lf);trivial.
+ Qed.
+
+ Hypothesis Hwf: Valuation.wf interp_var.
+
+ Lemma valid_check_flatten : forall s, S.valid interp_var s ->
+ forall cid lf, C.valid interp_var (check_flatten s cid lf).
+ Proof.
+ unfold check_flatten; intros s Hs cid lf; case_eq (S.get s cid).
+ intros; apply C.interp_true; auto.
+ intros i [ |l q] Heq; try apply C.interp_true; auto; case_eq (check_flatten_aux i lf); intro Heq2; try apply C.interp_true; auto; unfold C.valid; simpl; rewrite <- (check_flatten_aux_correct _ _ Heq2); unfold S.valid in Hs; generalize (Hs cid); rewrite Heq; auto.
+ Qed.
+
+End FLATTEN.
diff --git a/src/trace/coqTerms.ml b/src/trace/coqTerms.ml
new file mode 100644
index 0000000..1ee6448
--- /dev/null
+++ b/src/trace/coqTerms.ml
@@ -0,0 +1,187 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+open Coqlib
+
+let gen_constant modules constant = lazy (gen_constant_in_modules "SMT" modules constant)
+
+(* Int63 *)
+let int63_modules = [["Coq";"Numbers";"Cyclic";"Int63";"Int63Native"]]
+
+let cint = gen_constant int63_modules "int"
+let ceq63 = gen_constant int63_modules "eqb"
+
+(* PArray *)
+let parray_modules = [["Coq";"Array";"PArray"]]
+
+let carray = gen_constant parray_modules "array"
+
+(* Positive *)
+let positive_modules = [["Coq";"Numbers";"BinNums"];
+ ["Coq";"PArith";"BinPosDef";"Pos"]]
+
+let cpositive = gen_constant positive_modules "positive"
+let cxI = gen_constant positive_modules "xI"
+let cxO = gen_constant positive_modules "xO"
+let cxH = gen_constant positive_modules "xH"
+let ceqbP = gen_constant positive_modules "eqb"
+
+(* Z *)
+let z_modules = [["Coq";"Numbers";"BinNums"];
+ ["Coq";"ZArith";"BinInt"];
+ ["Coq";"ZArith";"BinInt";"Z"]]
+
+let cZ = gen_constant z_modules "Z"
+let cZ0 = gen_constant z_modules "Z0"
+let cZpos = gen_constant z_modules "Zpos"
+let cZneg = gen_constant z_modules "Zneg"
+let copp = gen_constant z_modules "opp"
+let cadd = gen_constant z_modules "add"
+let csub = gen_constant z_modules "sub"
+let cmul = gen_constant z_modules "mul"
+let cltb = gen_constant z_modules "ltb"
+let cleb = gen_constant z_modules "leb"
+let cgeb = gen_constant z_modules "geb"
+let cgtb = gen_constant z_modules "gtb"
+(* Je ne comprends pas pourquoi ça fonctionne avec Zeq_bool et pas avec
+ Z.eqb *)
+(* let ceqbZ = gen_constant z_modules "eqb" *)
+let ceqbZ = gen_constant [["Coq";"ZArith";"Zbool"]] "Zeq_bool"
+
+(* Booleans *)
+let bool_modules = [["Coq";"Bool";"Bool"]]
+
+let cbool = gen_constant init_modules "bool"
+let ctrue = gen_constant init_modules "true"
+let cfalse = gen_constant init_modules "false"
+let candb = gen_constant init_modules "andb"
+let corb = gen_constant init_modules "orb"
+let cxorb = gen_constant init_modules "xorb"
+let cnegb = gen_constant init_modules "negb"
+let cimplb = gen_constant init_modules "implb"
+let ceqb = gen_constant bool_modules "eqb"
+let cifb = gen_constant bool_modules "ifb"
+let creflect = gen_constant bool_modules "reflect"
+
+(* Lists *)
+let clist = gen_constant init_modules "list"
+let cnil = gen_constant init_modules "nil"
+let ccons = gen_constant init_modules "cons"
+
+
+(* Option *)
+let coption = gen_constant init_modules "option"
+let cSome = gen_constant init_modules "Some"
+let cNone = gen_constant init_modules "None"
+
+(* Pairs *)
+let cpair = gen_constant init_modules "pair"
+
+(* Logical Operators *)
+let cnot = gen_constant init_modules "not"
+let ceq = gen_constant init_modules "eq"
+let crefl_equal = gen_constant init_modules "eq_refl"
+
+(* SMT_terms *)
+
+let smt_modules = [ ["SMTCoq";"Misc"];
+ ["SMTCoq";"State"];
+ ["SMTCoq";"SMT_terms"];
+ ["SMTCoq";"SMT_terms";"Typ"];
+ ["SMTCoq";"SMT_terms";"Form"];
+ ["SMTCoq";"SMT_terms";"Atom"]
+ ]
+
+let cdistinct = gen_constant smt_modules "distinct"
+
+let ctype = gen_constant smt_modules "type"
+let cTZ = gen_constant smt_modules "TZ"
+let cTbool = gen_constant smt_modules "Tbool"
+let cTpositive = gen_constant smt_modules "Tpositive"
+let cTindex = gen_constant smt_modules "Tindex"
+
+let ctyp_eqb = gen_constant smt_modules "typ_eqb"
+let cTyp_eqb = gen_constant smt_modules "Typ_eqb"
+let cte_carrier = gen_constant smt_modules "te_carrier"
+let cte_eqb = gen_constant smt_modules "te_eqb"
+let cunit_typ_eqb = gen_constant smt_modules "unit_typ_eqb"
+
+let ctval = gen_constant smt_modules "tval"
+let cTval = gen_constant smt_modules "Tval"
+
+let cCO_xH = gen_constant smt_modules "CO_xH"
+let cCO_Z0 = gen_constant smt_modules "CO_Z0"
+
+let cUO_xO = gen_constant smt_modules "UO_xO"
+let cUO_xI = gen_constant smt_modules "UO_xI"
+let cUO_Zpos = gen_constant smt_modules "UO_Zpos"
+let cUO_Zneg = gen_constant smt_modules "UO_Zneg"
+let cUO_Zopp = gen_constant smt_modules "UO_Zopp"
+
+let cBO_Zplus = gen_constant smt_modules "BO_Zplus"
+let cBO_Zminus = gen_constant smt_modules "BO_Zminus"
+let cBO_Zmult = gen_constant smt_modules "BO_Zmult"
+let cBO_Zlt = gen_constant smt_modules "BO_Zlt"
+let cBO_Zle = gen_constant smt_modules "BO_Zle"
+let cBO_Zge = gen_constant smt_modules "BO_Zge"
+let cBO_Zgt = gen_constant smt_modules "BO_Zgt"
+let cBO_eq = gen_constant smt_modules "BO_eq"
+
+let cNO_distinct = gen_constant smt_modules "NO_distinct"
+
+let catom = gen_constant smt_modules "atom"
+let cAcop = gen_constant smt_modules "Acop"
+let cAuop = gen_constant smt_modules "Auop"
+let cAbop = gen_constant smt_modules "Abop"
+let cAnop = gen_constant smt_modules "Anop"
+let cAapp = gen_constant smt_modules "Aapp"
+
+let cform = gen_constant smt_modules "form"
+let cFatom = gen_constant smt_modules "Fatom"
+let cFtrue = gen_constant smt_modules "Ftrue"
+let cFfalse = gen_constant smt_modules "Ffalse"
+let cFnot2 = gen_constant smt_modules "Fnot2"
+let cFand = gen_constant smt_modules "Fand"
+let cFor = gen_constant smt_modules "For"
+let cFxor = gen_constant smt_modules "Fxor"
+let cFimp = gen_constant smt_modules "Fimp"
+let cFiff = gen_constant smt_modules "Fiff"
+let cFite = gen_constant smt_modules "Fite"
+
+let cis_true = gen_constant smt_modules "is_true"
+
+let make_certif_ops modules =
+ (gen_constant modules "step",
+ gen_constant modules "Res", gen_constant modules "ImmFlatten",
+ gen_constant modules "CTrue", gen_constant modules "CFalse",
+ gen_constant modules "BuildDef", gen_constant modules "BuildDef2",
+ gen_constant modules "BuildProj",
+ gen_constant modules "ImmBuildProj", gen_constant modules"ImmBuildDef",
+ gen_constant modules"ImmBuildDef2",
+ gen_constant modules "EqTr", gen_constant modules "EqCgr", gen_constant modules "EqCgrP",
+ gen_constant modules "LiaMicromega", gen_constant modules "LiaDiseq", gen_constant modules "SplArith", gen_constant modules "SplDistinctElim")
+
+
+(** Usefull construction *)
+
+let ceq_refl_true =
+ lazy (SmtMisc.mklApp crefl_equal [|Lazy.force cbool;Lazy.force ctrue|])
+
+let eq_refl_true () = Lazy.force ceq_refl_true
+
+let vm_cast_true t =
+ Term.mkCast(eq_refl_true (),
+ Term.VMcast,
+ SmtMisc.mklApp ceq [|Lazy.force cbool; t; Lazy.force ctrue|])
diff --git a/src/trace/satAtom.ml b/src/trace/satAtom.ml
new file mode 100644
index 0000000..ca72504
--- /dev/null
+++ b/src/trace/satAtom.ml
@@ -0,0 +1,65 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+open SmtMisc
+open CoqTerms
+
+module Atom =
+ struct
+
+ type t = int
+
+ let index a = a
+
+ let equal a1 a2 = a1 == a2
+
+ let is_bool_type a = true
+
+ type reify_tbl =
+ { mutable count : int;
+ tbl : (Term.constr, int) Hashtbl.t
+ }
+
+ let create () =
+ { count = 0;
+ tbl = Hashtbl.create 17 }
+
+ let declare reify a =
+ let res = reify.count in
+ Hashtbl.add reify.tbl a res;
+ reify.count <- res + 1;
+ res
+
+ let get reify a =
+ try Hashtbl.find reify.tbl a
+ with Not_found -> declare reify a
+
+ let atom_tbl reify =
+ let t = Array.make (reify.count + 1) (Lazy.force ctrue) in
+ let set c i = t.(i) <- c in
+ Hashtbl.iter set reify.tbl;
+ t
+
+ let interp_tbl reify =
+ Term.mkArray (Lazy.force cbool, atom_tbl reify)
+
+ end
+
+module Form = SmtForm.Make(Atom)
+module Trace = SmtTrace.MakeOpt(Form)
+module Cnf = SmtCnf.MakeCnf(Form)
+
+
+
diff --git a/src/trace/smtAtom.ml b/src/trace/smtAtom.ml
new file mode 100644
index 0000000..3164692
--- /dev/null
+++ b/src/trace/smtAtom.ml
@@ -0,0 +1,748 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+open SmtMisc
+open CoqTerms
+
+(** Syntaxified version of Coq type *)
+type indexed_type = Term.constr gen_hashed
+
+let dummy_indexed_type i = {index = i; hval = Term.mkProp}
+let indexed_type_index i = i.index
+
+type btype =
+ | TZ
+ | Tbool
+ | Tpositive
+ | Tindex of indexed_type
+
+module Btype =
+ struct
+
+ let index_tbl = Hashtbl.create 17
+
+ let index_to_coq i =
+ let i = i.index in
+ try Hashtbl.find index_tbl i
+ with Not_found ->
+ let interp = mklApp cTindex [|mkInt i|] in
+ Hashtbl.add index_tbl i interp;
+ interp
+
+ let equal t1 t2 =
+ match t1,t2 with
+ | Tindex i, Tindex j -> i.index == j.index
+ | _ -> t1 == t2
+
+ let to_coq = function
+ | TZ -> Lazy.force cTZ
+ | Tbool -> Lazy.force cTbool
+ | Tpositive -> Lazy.force cTpositive
+ | Tindex i -> index_to_coq i
+
+ let to_smt fmt = function
+ | TZ -> Format.fprintf fmt "Int"
+ | Tbool -> Format.fprintf fmt "Bool"
+ | Tpositive -> Format.fprintf fmt "Int"
+ | Tindex i -> Format.fprintf fmt "Tindex_%i" i.index
+
+ (* reify table *)
+ type reify_tbl =
+ { mutable count : int;
+ tbl : (Term.constr, btype) Hashtbl.t
+ }
+
+ let create () =
+ let htbl = Hashtbl.create 17 in
+ Hashtbl.add htbl (Lazy.force cZ) TZ;
+ Hashtbl.add htbl (Lazy.force cbool) Tbool;
+ (* Hashtbl.add htbl (Lazy.force cpositive) Tpositive; *)
+ { count = 0;
+ tbl = htbl }
+
+ let declare reify t typ_eqb =
+ (* TODO: allows to have only typ_eqb *)
+ assert (not (Hashtbl.mem reify.tbl t));
+ let res = Tindex {index = reify.count; hval = typ_eqb} in
+ Hashtbl.add reify.tbl t res;
+ reify.count <- reify.count + 1;
+ res
+
+ let of_coq reify t =
+ try
+ Hashtbl.find reify.tbl t
+ with | Not_found ->
+ let eq_t = declare_new_variable (Names.id_of_string "eq") (Term.mkArrow t (Term.mkArrow t (Lazy.force cbool))) in
+ let x = mkName "x" in
+ let y = mkName "y" in
+ let rx = Term.mkRel 2 in
+ let ry = Term.mkRel 1 in
+ let eq_refl = Term.mkProd (x,t,Term.mkProd (y,t,mklApp creflect [|mklApp ceq [|t;rx;ry|];mklApp (lazy eq_t) [|rx;ry|]|])) in
+ let eq_refl_v = declare_new_variable (Names.id_of_string ("eq_refl")) eq_refl in
+ let ce = mklApp cTyp_eqb [|t;eq_t;eq_refl_v|] in
+ declare reify t ce
+
+ let interp_tbl reify =
+ let t = Array.make (reify.count + 1) (Lazy.force cunit_typ_eqb) in
+ let set _ = function
+ | Tindex it -> t.(it.index) <- it.hval
+ | _ -> () in
+ Hashtbl.iter set reify.tbl;
+ Term.mkArray (Lazy.force ctyp_eqb, t)
+
+ let to_list reify =
+ let set _ t acc = match t with
+ | Tindex it -> (it.index,it)::acc
+ | _ -> acc in
+ Hashtbl.fold set reify.tbl []
+
+ let interp_to_coq reify = function
+ | TZ -> Lazy.force cZ
+ | Tbool -> Lazy.force cbool
+ | Tpositive -> Lazy.force cpositive
+ | Tindex c -> mklApp cte_carrier [|c.hval|]
+
+ end
+
+(** Operators *)
+
+type cop =
+ | CO_xH
+ | CO_Z0
+
+type uop =
+ | UO_xO
+ | UO_xI
+ | UO_Zpos
+ | UO_Zneg
+ | UO_Zopp
+
+type bop =
+ | BO_Zplus
+ | BO_Zminus
+ | BO_Zmult
+ | BO_Zlt
+ | BO_Zle
+ | BO_Zge
+ | BO_Zgt
+ | BO_eq of btype
+
+type nop =
+ | NO_distinct of btype
+
+type op_def = {
+ tparams : btype array;
+ tres : btype;
+ op_val : Term.constr }
+
+type indexed_op = op_def gen_hashed
+
+let dummy_indexed_op i dom codom = {index = i; hval = {tparams = dom; tres = codom; op_val = Term.mkProp}}
+let indexed_op_index op = op.index
+
+type op =
+ | Cop of cop
+ | Uop of uop
+ | Bop of bop
+ | Nop of nop
+ | Iop of indexed_op
+
+module Op =
+ struct
+ let c_to_coq = function
+ | CO_xH -> Lazy.force cCO_xH
+ | CO_Z0 -> Lazy.force cCO_Z0
+
+ let c_type_of = function
+ | CO_xH -> Tpositive
+ | CO_Z0 -> TZ
+
+ let interp_cop = function
+ | CO_xH -> Lazy.force cxH
+ | CO_Z0 -> Lazy.force cZ0
+
+ let u_to_coq = function
+ | UO_xO -> Lazy.force cUO_xO
+ | UO_xI -> Lazy.force cUO_xI
+ | UO_Zpos -> Lazy.force cUO_Zpos
+ | UO_Zneg -> Lazy.force cUO_Zneg
+ | UO_Zopp -> Lazy.force cUO_Zopp
+
+ let u_type_of = function
+ | UO_xO | UO_xI -> Tpositive
+ | UO_Zpos | UO_Zneg | UO_Zopp -> TZ
+
+ let u_type_arg = function
+ | UO_xO | UO_xI | UO_Zpos | UO_Zneg -> Tpositive
+ | UO_Zopp -> TZ
+
+ let interp_uop = function
+ | UO_xO -> Lazy.force cxO
+ | UO_xI -> Lazy.force cxI
+ | UO_Zpos -> Lazy.force cZpos
+ | UO_Zneg -> Lazy.force cZneg
+ | UO_Zopp -> Lazy.force copp
+
+ let eq_tbl = Hashtbl.create 17
+
+ let eq_to_coq t =
+ try Hashtbl.find eq_tbl t
+ with Not_found ->
+ let op = mklApp cBO_eq [|Btype.to_coq t|] in
+ Hashtbl.add eq_tbl t op;
+ op
+
+ let b_to_coq = function
+ | BO_Zplus -> Lazy.force cBO_Zplus
+ | BO_Zminus -> Lazy.force cBO_Zminus
+ | BO_Zmult -> Lazy.force cBO_Zmult
+ | BO_Zlt -> Lazy.force cBO_Zlt
+ | BO_Zle -> Lazy.force cBO_Zle
+ | BO_Zge -> Lazy.force cBO_Zge
+ | BO_Zgt -> Lazy.force cBO_Zgt
+ | BO_eq t -> eq_to_coq t
+
+ let b_type_of = function
+ | BO_Zplus | BO_Zminus | BO_Zmult -> TZ
+ | BO_Zlt | BO_Zle | BO_Zge | BO_Zgt | BO_eq _ -> Tbool
+
+ let b_type_args = function
+ | BO_Zplus | BO_Zminus | BO_Zmult
+ | BO_Zlt | BO_Zle | BO_Zge | BO_Zgt -> (TZ,TZ)
+ | BO_eq t -> (t,t)
+
+ let interp_eq = function
+ | TZ -> Lazy.force ceqbZ
+ | Tbool -> Lazy.force ceqb
+ | Tpositive -> Lazy.force ceqbP
+ | Tindex i -> mklApp cte_eqb [|i.hval|]
+
+ let interp_bop = function
+ | BO_Zplus -> Lazy.force cadd
+ | BO_Zminus -> Lazy.force csub
+ | BO_Zmult -> Lazy.force cmul
+ | BO_Zlt -> Lazy.force cltb
+ | BO_Zle -> Lazy.force cleb
+ | BO_Zge -> Lazy.force cgeb
+ | BO_Zgt -> Lazy.force cgtb
+ | BO_eq t -> interp_eq t
+
+ let n_to_coq = function
+ | NO_distinct t -> mklApp cNO_distinct [|Btype.to_coq t|]
+
+ let n_type_of = function
+ | NO_distinct _ -> Tbool
+
+ let n_type_args = function
+ | NO_distinct ty -> ty
+
+ let interp_distinct = function
+ | TZ -> Lazy.force cZ
+ | Tbool -> Lazy.force cbool
+ | Tpositive -> Lazy.force cpositive
+ | Tindex i -> mklApp cte_carrier [|i.hval|]
+
+ let interp_nop = function
+ | NO_distinct ty -> mklApp cdistinct [|interp_distinct ty;interp_eq ty|]
+
+ let i_to_coq i = mkInt i.index
+
+ let i_type_of i = i.hval.tres
+
+ let i_type_args i = i.hval.tparams
+
+ (* reify table *)
+ type reify_tbl =
+ { mutable count : int;
+ tbl : (Term.constr, indexed_op) Hashtbl.t
+ }
+
+ let create () =
+ { count = 0;
+ tbl = Hashtbl.create 17 }
+
+ let declare reify op tparams tres =
+ assert (not (Hashtbl.mem reify.tbl op));
+ let v = { tparams = tparams; tres = tres; op_val = op } in
+ let res = {index = reify.count; hval = v } in
+ Hashtbl.add reify.tbl op res;
+ reify.count <- reify.count + 1;
+ res
+
+ let of_coq reify op =
+ Hashtbl.find reify.tbl op
+
+
+ let interp_tbl tval mk_Tval reify =
+ let t = Array.make (reify.count + 1)
+ (mk_Tval [||] Tbool (Lazy.force ctrue)) in
+ let set _ v =
+ t.(v.index) <- mk_Tval v.hval.tparams v.hval.tres v.hval.op_val in
+ Hashtbl.iter set reify.tbl;
+ Term.mkArray (tval, t)
+
+ let to_list reify =
+ let set _ op acc =
+ let value = op.hval in
+ (op.index,value.tparams,value.tres,op)::acc in
+ Hashtbl.fold set reify.tbl []
+
+ let c_equal op1 op2 = op1 == op2
+
+ let u_equal op1 op2 = op1 == op2
+
+ let b_equal op1 op2 =
+ match op1,op2 with
+ | BO_eq t1, BO_eq t2 -> Btype.equal t1 t2
+ | _ -> op1 == op2
+
+ let n_equal op1 op2 =
+ match op1,op2 with
+ | NO_distinct t1, NO_distinct t2 -> Btype.equal t1 t2
+
+ let i_equal op1 op2 = op1.index == op2.index
+
+ end
+
+
+(** Definition of atoms *)
+
+type atom =
+ | Acop of cop
+ | Auop of uop * hatom
+ | Abop of bop * hatom * hatom
+ | Anop of nop * hatom array
+ | Aapp of indexed_op * hatom array
+
+and hatom = atom gen_hashed
+
+(* let pp_acop = function *)
+(* | CO_xH -> "CO_xH" *)
+(* | CO_Z0 -> "CO_Z0" *)
+
+(* let pp_auop = function *)
+(* | UO_xO -> "UO_xO" *)
+(* | UO_xI -> "UO_xI" *)
+(* | UO_Zpos -> "UO_Zpos" *)
+(* | UO_Zneg -> "UO_Zneg" *)
+(* | UO_Zopp -> "UO_Zopp" *)
+
+(* let pp_abop = function *)
+(* | BO_Zplus -> "BO_Zplus" *)
+(* | BO_Zminus -> "BO_Zminus" *)
+(* | BO_Zmult -> "BO_Zmult" *)
+(* | BO_Zlt -> "BO_Zlt" *)
+(* | BO_Zle -> "BO_Zle" *)
+(* | BO_Zge -> "BO_Zge" *)
+(* | BO_Zgt -> "BO_Zgt" *)
+(* | BO_eq _ -> "(BO_eq ??)" *)
+
+(* let rec pp_atom = function *)
+(* | Acop c -> "(Acop "^(pp_acop c)^")" *)
+(* | Auop (u,b) -> "(Auop "^(pp_auop u)^" "^(pp_atom b.hval)^")" *)
+(* | Abop (b,c,d) -> "(Abop "^(pp_abop b)^" "^(pp_atom c.hval)^" "^(pp_atom d.hval)^")" *)
+(* | Aapp (op,a) -> "(Aapp "^(string_of_int op.index)^" ("^(Array.fold_left (fun acc h -> acc^" "^(pp_atom h.hval)) "" a)^"))" *)
+
+module HashedAtom =
+ struct
+ type t = atom
+
+ let equal a b =
+ match a, b with
+ | Acop opa, Acop opb -> Op.c_equal opa opb
+ | Auop(opa,ha), Auop(opb,hb) -> Op.u_equal opa opb && ha.index == hb.index
+ | Abop(opa,ha1,ha2), Abop(opb,hb1,hb2) ->
+ Op.b_equal opa opb && ha1.index == hb1.index && ha2.index == hb2.index
+ | Anop (opa,ha), Anop (opb,hb) ->
+ let na = Array.length ha in
+ let nb = Array.length hb in
+ let i = ref (-1) in
+ Op.n_equal opa opb && na == nb && Array.fold_left (fun b h -> incr i; b && h.index == hb.(!i).index) true ha
+ | Aapp (va,ha), Aapp (vb,hb) ->
+ let na = Array.length ha in
+ let nb = Array.length hb in
+ let i = ref (-1) in
+ Op.i_equal va vb && na == nb && Array.fold_left (fun b h -> incr i; b && h.index == hb.(!i).index) true ha
+ | _, _ -> false
+
+ let hash = function
+ | Acop op -> ((Hashtbl.hash op) lsl 3) lxor 1
+ | Auop (op,h) ->
+ (( (h.index lsl 3) + (Hashtbl.hash op)) lsl 3) lxor 2
+ | Abop (op,h1,h2) ->
+ (((( (h1.index lsl 2) + h2.index) lsl 3) + Hashtbl.hash op) lsl 3) lxor 3
+ | Anop (op, args) ->
+ let hash_args =
+ match Array.length args with
+ | 0 -> 0
+ | 1 -> args.(0).index
+ | 2 -> args.(1).index lsl 2 + args.(0).index
+ | _ -> args.(2).index lsl 4 + args.(1).index lsl 2 + args.(0).index in
+ (hash_args lsl 5 + (Hashtbl.hash op) lsl 3) lxor 4
+ | Aapp (op, args) ->
+ let hash_args =
+ match Array.length args with
+ | 0 -> 0
+ | 1 -> args.(0).index
+ | 2 -> args.(1).index lsl 2 + args.(0).index
+ | _ -> args.(2).index lsl 4 + args.(1).index lsl 2 + args.(0).index in
+ (hash_args lsl 5 + op.index lsl 3) lxor 4
+
+ end
+
+module HashAtom = Hashtbl.Make(HashedAtom)
+
+module Atom =
+ struct
+
+ type t = hatom
+
+ let atom h = h.hval
+ let index h = h.index
+
+ let equal h1 h2 = h1.index == h2.index
+
+ let type_of h =
+ match h.hval with
+ | Acop op -> Op.c_type_of op
+ | Auop (op,_) -> Op.u_type_of op
+ | Abop (op,_,_) -> Op.b_type_of op
+ | Anop (op,_) -> Op.n_type_of op
+ | Aapp (op,_) -> Op.i_type_of op
+
+ let is_bool_type h = Btype.equal (type_of h) Tbool
+
+
+ let rec compute_int = function
+ | Acop c ->
+ (match c with
+ | CO_xH -> 1
+ | CO_Z0 -> 0)
+ | Auop (op,h) ->
+ (match op with
+ | UO_xO -> 2*(compute_hint h)
+ | UO_xI -> 2*(compute_hint h) + 1
+ | UO_Zpos -> compute_hint h
+ | UO_Zneg -> - (compute_hint h)
+ | UO_Zopp -> assert false)
+ | _ -> assert false
+
+ and compute_hint h = compute_int (atom h)
+
+ let to_smt_int fmt i =
+ let s1 = if i < 0 then "(- " else "" in
+ let s2 = if i < 0 then ")" else "" in
+ let j = if i < 0 then -i else i in
+ Format.fprintf fmt "%s%i%s" s1 j s2
+
+ let rec to_smt fmt h = to_smt_atom fmt (atom h)
+
+ and to_smt_atom fmt = function
+ | Acop _ as a -> to_smt_int fmt (compute_int a)
+ | Auop (UO_Zopp,h) ->
+ Format.fprintf fmt "(- ";
+ to_smt fmt h;
+ Format.fprintf fmt ")"
+ | Auop _ as a -> to_smt_int fmt (compute_int a)
+ | Abop (op,h1,h2) -> to_smt_bop fmt op h1 h2
+ | Anop (op,a) -> to_smt_nop fmt op a
+ | Aapp (op,a) ->
+ if Array.length a = 0 then (
+ Format.fprintf fmt "op_%i" op.index;
+ ) else (
+ Format.fprintf fmt "(op_%i" op.index;
+ Array.iter (fun h -> Format.fprintf fmt " "; to_smt fmt h) a;
+ Format.fprintf fmt ")"
+ )
+
+ and to_smt_bop fmt op h1 h2 =
+ let s = match op with
+ | BO_Zplus -> "+"
+ | BO_Zminus -> "-"
+ | BO_Zmult -> "*"
+ | BO_Zlt -> "<"
+ | BO_Zle -> "<="
+ | BO_Zge -> ">="
+ | BO_Zgt -> ">"
+ | BO_eq _ -> "=" in
+ Format.fprintf fmt "(%s " s;
+ to_smt fmt h1;
+ Format.fprintf fmt " ";
+ to_smt fmt h2;
+ Format.fprintf fmt ")"
+
+ and to_smt_nop fmt op a =
+ let s = match op with
+ | NO_distinct _ -> "distinct" in
+ Format.fprintf fmt "(%s" s;
+ Array.iter (fun h -> Format.fprintf fmt " "; to_smt fmt h) a;
+ Format.fprintf fmt ")"
+
+
+
+ exception NotWellTyped of atom
+
+ let check a =
+ match a with
+ | Acop _ -> ()
+ | Auop(op,h) ->
+ if not (Btype.equal (Op.u_type_arg op) (type_of h)) then
+ raise (NotWellTyped a)
+ | Abop(op,h1,h2) ->
+ let (t1,t2) = Op.b_type_args op in
+ if not (Btype.equal t1 (type_of h1) && Btype.equal t2 (type_of h2))
+ then raise (NotWellTyped a)
+ | Anop(op,ha) ->
+ let ty = Op.n_type_args op in
+ Array.iter (fun h -> if not (Btype.equal ty (type_of h)) then raise (NotWellTyped a)) ha
+ | Aapp(op,args) ->
+ let tparams = Op.i_type_args op in
+ Array.iteri (fun i t ->
+ if not (Btype.equal t (type_of args.(i))) then
+ raise (NotWellTyped a)) tparams
+
+ type reify_tbl =
+ { mutable count : int;
+ tbl : hatom HashAtom.t
+ }
+
+ let create () =
+ { count = 0;
+ tbl = HashAtom.create 17 }
+
+ let clear reify =
+ reify.count <- 0;
+ HashAtom.clear reify.tbl
+
+ let declare reify a =
+ check a;
+ let res = {index = reify.count; hval = a} in
+ HashAtom.add reify.tbl a res;
+ reify.count <- reify.count + 1;
+ res
+
+ let get reify a =
+ try HashAtom.find reify.tbl a
+ with Not_found -> declare reify a
+
+
+ (** Given a coq term, build the corresponding atom *)
+ type coq_cst =
+ | CCxH
+ | CCZ0
+ | CCxO
+ | CCxI
+ | CCZpos
+ | CCZneg
+ | CCZopp
+ | CCZplus
+ | CCZminus
+ | CCZmult
+ | CCZlt
+ | CCZle
+ | CCZge
+ | CCZgt
+ | CCeqb
+ | CCeqbP
+ | CCeqbZ
+ | CCunknown
+
+ let op_tbl () =
+ let tbl = Hashtbl.create 29 in
+ let add (c1,c2) = Hashtbl.add tbl (Lazy.force c1) c2 in
+ List.iter add
+ [ cxH,CCxH; cZ0,CCZ0;
+ cxO,CCxO; cxI,CCxI; cZpos,CCZpos; cZneg,CCZneg; copp,CCZopp;
+ cadd,CCZplus; csub,CCZminus; cmul,CCZmult; cltb,CCZlt;
+ cleb,CCZle; cgeb,CCZge; cgtb,CCZgt; ceqb,CCeqb; ceqbP,CCeqbP;
+ ceqbZ, CCeqbZ
+ ];
+ tbl
+
+ let op_tbl = lazy (op_tbl ())
+
+ let of_coq rt ro reify env sigma c =
+ let op_tbl = Lazy.force op_tbl in
+ let get_cst c =
+ try Hashtbl.find op_tbl c with Not_found -> CCunknown in
+ let mk_cop op = get reify (Acop op) in
+ let rec mk_hatom h =
+ let c, args = Term.decompose_app h in
+ match get_cst c with
+ | CCxH -> mk_cop CO_xH
+ | CCZ0 -> mk_cop CO_Z0
+ | CCxO -> mk_uop UO_xO args
+ | CCxI -> mk_uop UO_xI args
+ | CCZpos -> mk_uop UO_Zpos args
+ | CCZneg -> mk_uop UO_Zneg args
+ | CCZopp -> mk_uop UO_Zopp args
+ | CCZplus -> mk_bop BO_Zplus args
+ | CCZminus -> mk_bop BO_Zminus args
+ | CCZmult -> mk_bop BO_Zmult args
+ | CCZlt -> mk_bop BO_Zlt args
+ | CCZle -> mk_bop BO_Zle args
+ | CCZge -> mk_bop BO_Zge args
+ | CCZgt -> mk_bop BO_Zgt args
+ | CCeqb -> mk_bop (BO_eq Tbool) args
+ | CCeqbP -> mk_bop (BO_eq Tpositive) args
+ | CCeqbZ -> mk_bop (BO_eq TZ) args
+ | CCunknown -> mk_unknown c args (Retyping.get_type_of env sigma h)
+
+ and mk_uop op = function
+ | [a] -> let h = mk_hatom a in get reify (Auop (op,h))
+ | _ -> assert false
+
+ and mk_bop op = function
+ | [a1;a2] ->
+ let h1 = mk_hatom a1 in
+ let h2 = mk_hatom a2 in
+ get reify (Abop (op,h1,h2))
+ | _ -> assert false
+
+ and mk_unknown c args ty =
+ let hargs = Array.of_list (List.map mk_hatom args) in
+ let op =
+ try Op.of_coq ro c
+ with | Not_found ->
+ let targs = Array.map type_of hargs in
+ let tres = Btype.of_coq rt ty in
+ Op.declare ro c targs tres in
+ get reify (Aapp (op,hargs)) in
+
+ mk_hatom c
+
+
+ let to_coq h = mkInt h.index
+
+ let a_to_coq a =
+ match a with
+ | Acop op -> mklApp cAcop [|Op.c_to_coq op|]
+ | Auop (op,h) -> mklApp cAuop [|Op.u_to_coq op; to_coq h|]
+ | Abop (op,h1,h2) ->
+ mklApp cAbop [|Op.b_to_coq op;to_coq h1; to_coq h2|]
+ | Anop (op,ha) ->
+ let cop = Op.n_to_coq op in
+ let cargs = Array.fold_right (fun h l -> mklApp ccons [|Lazy.force cint; to_coq h; l|]) ha (mklApp cnil [|Lazy.force cint|]) in
+ mklApp cAnop [|cop; cargs|]
+ | Aapp (op,args) ->
+ let cop = Op.i_to_coq op in
+ let cargs = Array.fold_right (fun h l -> mklApp ccons [|Lazy.force cint; to_coq h; l|]) args (mklApp cnil [|Lazy.force cint|]) in
+ mklApp cAapp [|cop; cargs|]
+
+ let dft_atom = lazy (mklApp cAcop [| Lazy.force cCO_xH |])
+
+ let to_array reify dft f =
+ let t = Array.make (reify.count + 1) dft in
+ let set _ h = t.(h.index) <- f h.hval in
+ HashAtom.iter set reify.tbl;
+ t
+
+ let interp_tbl reify =
+ let t = to_array reify (Lazy.force dft_atom) a_to_coq in
+ Term.mkArray (Lazy.force catom, t)
+
+
+ (** Producing a Coq term corresponding to the interpretation of an atom *)
+ let interp_to_coq atom_tbl a =
+ let rec interp_atom a =
+ let l = index a in
+ try Hashtbl.find atom_tbl l
+ with Not_found ->
+ let pc =
+ match atom a with
+ | Acop c -> Op.interp_cop c
+ | Auop (op,h) -> Term.mkApp (Op.interp_uop op, [|interp_atom h|])
+ | Abop (op,h1,h2) -> Term.mkApp (Op.interp_bop op, [|interp_atom h1; interp_atom h2|])
+ | Anop (NO_distinct ty as op,ha) ->
+ let cop = Op.interp_nop op in
+ let typ = Op.interp_distinct ty in
+ let cargs = Array.fold_right (fun h l -> mklApp ccons [|typ; interp_atom h; l|]) ha (mklApp cnil [|typ|]) in
+ Term.mkApp (cop,[|cargs|])
+ | Aapp (op,t) -> Term.mkApp (op.hval.op_val, Array.map interp_atom t) in
+ Hashtbl.add atom_tbl l pc;
+ pc in
+ interp_atom a
+
+
+ (* Generation of atoms *)
+
+ let mk_nop op reify a = get reify (Anop (op,a))
+
+ let mk_binop op reify h1 h2 = get reify (Abop (op, h1, h2))
+
+ let mk_unop op reify h = get reify (Auop (op, h))
+
+ let rec hatom_pos_of_int reify i =
+ if i <= 1 then
+ get reify (Acop CO_xH)
+ else
+ if i land 1 = 0
+ then mk_unop UO_xO reify (hatom_pos_of_int reify (i lsr 1))
+ else mk_unop UO_xI reify (hatom_pos_of_int reify (i lsr 1))
+
+ let hatom_Z_of_int reify i =
+ if i = 0 then
+ get reify (Acop CO_Z0)
+ else
+ if i > 0
+ then mk_unop UO_Zpos reify (hatom_pos_of_int reify i)
+ else mk_unop UO_Zneg reify (hatom_pos_of_int reify (-i))
+
+ let rec hatom_pos_of_bigint reify i =
+ if Big_int.le_big_int i Big_int.unit_big_int then
+ get reify (Acop CO_xH)
+ else
+ let (q,r) = Big_int.quomod_big_int i (Big_int.big_int_of_int 2) in
+ if Big_int.eq_big_int r Big_int.zero_big_int then
+ mk_unop UO_xO reify (hatom_pos_of_bigint reify q)
+ else
+ mk_unop UO_xI reify (hatom_pos_of_bigint reify q)
+
+ let hatom_Z_of_bigint reify i =
+ if Big_int.eq_big_int i Big_int.zero_big_int then
+ get reify (Acop CO_Z0)
+ else
+ if Big_int.gt_big_int i Big_int.zero_big_int then
+ mk_unop UO_Zpos reify (hatom_pos_of_bigint reify i)
+ else
+ mk_unop UO_Zneg reify (hatom_pos_of_bigint reify (Big_int.minus_big_int i))
+
+ let mk_eq reify ty h1 h2 =
+ let op = BO_eq ty in
+ try
+ HashAtom.find reify.tbl (Abop (op, h1, h2))
+ with
+ | Not_found ->
+ try
+ HashAtom.find reify.tbl (Abop (op, h2, h1))
+ with
+ | Not_found ->
+ declare reify (Abop (op, h1, h2))
+
+ let mk_lt = mk_binop BO_Zlt
+ let mk_le = mk_binop BO_Zle
+ let mk_gt = mk_binop BO_Zgt
+ let mk_ge = mk_binop BO_Zge
+ let mk_plus = mk_binop BO_Zplus
+ let mk_minus = mk_binop BO_Zminus
+ let mk_mult = mk_binop BO_Zmult
+ let mk_opp = mk_unop UO_Zopp
+ let mk_distinct reify ty = mk_nop (NO_distinct ty) reify
+
+ end
+
+
+module Form = SmtForm.Make(Atom)
+module Trace = SmtTrace.MakeOpt(Form)
diff --git a/src/trace/smtAtom.mli b/src/trace/smtAtom.mli
new file mode 100644
index 0000000..8eadb49
--- /dev/null
+++ b/src/trace/smtAtom.mli
@@ -0,0 +1,175 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+
+type indexed_type
+
+val dummy_indexed_type: int -> indexed_type
+val indexed_type_index : indexed_type -> int
+
+type btype =
+ | TZ
+ | Tbool
+ | Tpositive
+ | Tindex of indexed_type
+
+module Btype :
+ sig
+
+ val equal : btype -> btype -> bool
+
+ val to_coq : btype -> Term.constr
+
+ val to_smt : Format.formatter -> btype -> unit
+
+ type reify_tbl
+
+ val create : unit -> reify_tbl
+
+ val declare : reify_tbl -> Term.constr -> Term.constr -> btype
+
+ val of_coq : reify_tbl -> Term.constr -> btype
+
+ val interp_tbl : reify_tbl -> Term.constr
+
+ val to_list : reify_tbl -> (int * indexed_type) list
+
+ val interp_to_coq : reify_tbl -> btype -> Term.constr
+
+ end
+
+(** Operators *)
+
+type cop =
+ | CO_xH
+ | CO_Z0
+
+type uop =
+ | UO_xO
+ | UO_xI
+ | UO_Zpos
+ | UO_Zneg
+ | UO_Zopp
+
+type bop =
+ | BO_Zplus
+ | BO_Zminus
+ | BO_Zmult
+ | BO_Zlt
+ | BO_Zle
+ | BO_Zge
+ | BO_Zgt
+ | BO_eq of btype
+
+type nop =
+ | NO_distinct of btype
+
+type indexed_op
+
+val dummy_indexed_op: int -> btype array -> btype -> indexed_op
+val indexed_op_index : indexed_op -> int
+
+module Op :
+ sig
+
+ type reify_tbl
+
+ val create : unit -> reify_tbl
+
+ val declare : reify_tbl -> Term.constr -> btype array -> btype -> indexed_op
+
+ val of_coq : reify_tbl -> Term.constr -> indexed_op
+
+ val interp_tbl : Term.constr ->
+ (btype array -> btype -> Term.constr -> Term.constr) ->
+ reify_tbl -> Term.constr
+
+ val to_list : reify_tbl -> (int * (btype array) * btype * indexed_op) list
+
+ end
+
+
+(** Definition of atoms *)
+
+type hatom
+
+type atom =
+ | Acop of cop
+ | Auop of uop * hatom
+ | Abop of bop * hatom * hatom
+ | Anop of nop * hatom array
+ | Aapp of indexed_op * hatom array
+
+
+
+module Atom :
+ sig
+
+ type t = hatom
+
+ val equal : hatom -> hatom -> bool
+
+ val index : hatom -> int
+
+ val atom : hatom -> atom
+
+ val type_of : hatom -> btype
+
+ val to_smt : Format.formatter -> t -> unit
+
+ exception NotWellTyped of atom
+
+ type reify_tbl
+
+ val create : unit -> reify_tbl
+
+ val clear : reify_tbl -> unit
+
+ val get : reify_tbl -> atom -> hatom
+
+ (** Given a coq term, build the corresponding atom *)
+ val of_coq : Btype.reify_tbl -> Op.reify_tbl -> reify_tbl ->
+ Environ.env -> Evd.evar_map -> Term.constr -> t
+
+ val to_coq : hatom -> Term.constr
+
+ val to_array : reify_tbl -> 'a -> (atom -> 'a) -> 'a array
+
+ val interp_tbl : reify_tbl -> Term.constr
+
+ val interp_to_coq : (int, Term.constr) Hashtbl.t ->
+ t -> Term.constr
+
+ (* Generation of atoms *)
+ val hatom_Z_of_int : reify_tbl -> int -> hatom
+ val hatom_Z_of_bigint : reify_tbl -> Big_int.big_int -> hatom
+ val mk_eq : reify_tbl -> btype -> hatom -> hatom -> hatom
+ val mk_lt : reify_tbl -> hatom -> hatom -> hatom
+ val mk_le : reify_tbl -> hatom -> hatom -> hatom
+ val mk_gt : reify_tbl -> hatom -> hatom -> hatom
+ val mk_ge : reify_tbl -> hatom -> hatom -> hatom
+ val mk_plus : reify_tbl -> hatom -> hatom -> hatom
+ val mk_minus : reify_tbl -> hatom -> hatom -> hatom
+ val mk_mult : reify_tbl -> hatom -> hatom -> hatom
+ val mk_opp : reify_tbl -> hatom -> hatom
+ val mk_distinct : reify_tbl -> btype -> hatom array -> hatom
+
+ end
+
+
+module Form : SmtForm.FORM with type hatom = hatom
+module Trace : sig
+ val share_prefix : Form.t SmtCertif.clause -> int -> unit
+end
diff --git a/src/trace/smtCertif.ml b/src/trace/smtCertif.ml
new file mode 100644
index 0000000..76036a5
--- /dev/null
+++ b/src/trace/smtCertif.ml
@@ -0,0 +1,140 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+
+open SmtForm
+
+type used = int
+
+type clause_id = int
+
+type 'hform rule =
+ | ImmFlatten of 'hform clause * 'hform
+
+ (* CNF Transformations *)
+ | True
+ (* * true : {true}
+ *)
+ | False
+ (* * false : {(not false)}
+ *)
+ | BuildDef of 'hform (* the first literal of the clause *)
+ (* * and_neg : {(and a_1 ... a_n) (not a_1) ... (not a_n)}
+ * or_pos : {(not (or a_1 ... a_n)) a_1 ... a_n}
+ * implies_pos : {(not (implies a b)) (not a) b}
+ * xor_pos1 : {(not (xor a b)) a b}
+ * xor_neg1 : {(xor a b) a (not b)}
+ * equiv_pos1 : {(not (iff a b)) a (not b)}
+ * equiv_neg1 : {(iff a b) (not a) (not b)}
+ * ite_pos1 : {(not (if_then_else a b c)) a c}
+ * ite_neg1 : {(if_then_else a b c) a (not c)}
+ *)
+ | BuildDef2 of 'hform (* the first literal of the clause *)
+ (* * xor_pos2 : {(not (xor a b)) (not a) (not b)}
+ * xor_neg2 : {(xor a b) (not a) b}
+ * equiv_pos2 : {(not (iff a b)) (not a) b}
+ * equiv_neg2 : {(iff a b) a b}
+ * ite_pos2 : {(not (if_then_else a b c)) (not a) b}
+ * ite_neg2 : {(if_then_else a b c) (not a) (not b)}
+
+ *)
+ | BuildProj of 'hform * int
+ (* * or_neg : {(or a_1 ... a_n) (not a_i)}
+ * and_pos : {(not (and a_1 ... a_n)) a_i}
+ * implies_neg1 : {(implies a b) a}
+ * implies_neg2 : {(implies a b) (not b)}
+ *)
+
+ (* Immediate CNF transformation : CNF transformation + Reso *)
+ | ImmBuildDef of 'hform clause
+ (* * not_and : {(not (and a_1 ... a_n))} --> {(not a_1) ... (not a_n)}
+ * or : {(or a_1 ... a_n)} --> {a_1 ... a_n}
+ * implies : {(implies a b)} --> {(not a) b}
+ * xor1 : {(xor a b)} --> {a b}
+ * not_xor1 : {(not (xor a b))} --> {a (not b)}
+ * equiv2 : {(iff a b)} --> {a (not b)}
+ * not_equiv2 : {(not (iff a b))} --> {(not a) (not b)}
+ * ite1 : {(if_then_else a b c)} --> {a c}
+ * not_ite1 : {(not (if_then_else a b c))} --> {a (not c)}
+ *)
+ | ImmBuildDef2 of 'hform clause
+ (* * xor2 : {(xor a b)} --> {(not a) (not b)}
+ * not_xor2 : {(not (xor a b))} --> {(not a) b}
+ * equiv1 : {(iff a b)} --> {(not a) b}
+ * not_equiv1 : {(not (iff a b))} --> {a b}
+ * ite2 : {(if_then_else a b c)} --> {(not a) b}
+ * not_ite2 : {(not (if_then_else a b c))} --> {(not a) (not b)}
+ *)
+ | ImmBuildProj of 'hform clause * int
+ (* * and : {(and a_1 ... a_n)} --> {a_i}
+ * not_or : {(not (or a_1 ... a_n))} --> {(not a_i)}
+ * not_implies1 : {(not (implies a b))} --> {a}
+ * not_implies2 : {(not (implies a b))} --> {(not b)}
+ *)
+
+ (* Equality *)
+ | EqTr of 'hform * 'hform list
+ (* * eq_reflexive : {(= x x)}
+ * eq_transitive : {(not (= x_1 x_2)) ... (not (= x_{n-1} x_n)) (= x_1 x_n)}
+ *)
+ | EqCgr of 'hform * ('hform option) list
+ (* * eq_congruent : {(not (= x_1 y_1)) ... (not (= x_n y_n))
+ (= (f x_1 ... x_n) (f y_1 ... y_n))}
+ *)
+ | EqCgrP of 'hform * 'hform * ('hform option) list
+ (* * eq_congruent_pred : {(not (= x_1 y_1)) ... (not (= x_n y_n))
+ (not (p x_1 ... x_n)) (p y_1 ... y_n)}
+ *)
+
+ (* Linear arithmetic *)
+ | LiaMicromega of 'hform list * Certificate.Mc.zArithProof list
+ | LiaDiseq of 'hform
+
+ (* Arithmetic simplifications *)
+ | SplArith of 'hform clause * 'hform * Certificate.Mc.zArithProof list
+
+ (* Elimination of operators *)
+ | SplDistinctElim of 'hform clause * 'hform
+
+and 'hform clause = {
+ id : clause_id;
+ mutable kind : 'hform clause_kind;
+ mutable pos : int option;
+ mutable used : used;
+ mutable prev : 'hform clause option;
+ mutable next : 'hform clause option;
+ value : 'hform list option
+ (* This field should be defined for rules which can create atoms :
+ EqTr, EqCgr, EqCgrP, Lia, Dlde, Lra *)
+}
+
+and 'hform clause_kind =
+ | Root
+ | Same of 'hform clause
+ | Res of 'hform resolution
+ | Other of 'hform rule
+
+and 'hform resolution = {
+ mutable rc1 : 'hform clause;
+ mutable rc2 : 'hform clause;
+ mutable rtail : 'hform clause list}
+
+let used_clauses r =
+ match r with
+ | ImmBuildProj (c, _) | ImmBuildDef c | ImmBuildDef2 c
+ | ImmFlatten (c,_) | SplArith (c,_,_) | SplDistinctElim (c,_) -> [c]
+ | True | False | BuildDef _ | BuildDef2 _ | BuildProj _
+ | EqTr _ | EqCgr _ | EqCgrP _
+ | LiaMicromega _ | LiaDiseq _ -> []
diff --git a/src/trace/smtCnf.ml b/src/trace/smtCnf.ml
new file mode 100644
index 0000000..d159db0
--- /dev/null
+++ b/src/trace/smtCnf.ml
@@ -0,0 +1,264 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+
+open SmtForm
+open SmtCertif
+open SmtTrace
+
+module MakeCnf (Form:FORM) =
+ struct
+
+ type form_info =
+ | Immediate of bool (* true if the positive literal is set *)
+ | Done (* means that the equivalence clauses have been generated *)
+ | Todo (* nothing has been done, process the cnf transformation *)
+
+ let info = Hashtbl.create 17
+
+ let init_last =
+ let last = SmtTrace.mk_scertif Root None in
+ SmtTrace.clear ();
+ last
+
+ let last = ref init_last
+
+ let cnf_todo = ref []
+
+ let clear () =
+ Hashtbl.clear info;
+ last := init_last;
+ cnf_todo := []
+
+ let push_cnf args = cnf_todo := args :: !cnf_todo
+
+ let get_info l =
+ try Hashtbl.find info (Form.index l)
+ with Not_found -> Todo
+
+ let set_done l =
+ Hashtbl.add info (Form.index l) Done
+
+ let set_immediate l =
+ Hashtbl.add info (Form.index l) (Immediate (Form.is_pos l))
+
+ let test_immediate l =
+ match get_info l with
+ | Immediate b -> b = Form.is_pos l
+ | _ -> false
+
+ let check_trivial cl =
+ List.exists test_immediate cl
+
+ let link_Other other cl =
+ if not (check_trivial cl) then
+ let c = mkOther other (Some cl) in
+ link !last c;
+ last := c
+
+ let both_lit l = if Form.is_pos l then Form.neg l,l else l, Form.neg l
+
+ let or_of_imp args =
+ Array.mapi (fun i l ->
+ if i = Array.length args - 1 then l else Form.neg l) args
+
+ let rec cnf l =
+ match get_info l with
+ | Immediate _ | Done -> ()
+ | Todo ->
+ match Form.pform l with
+ | Fatom _ -> ()
+
+ | Fapp (op,args) ->
+ match op with
+ | Ftrue | Ffalse -> ()
+
+ | Fand ->
+ let nl,pl = both_lit l in
+ let nargs = Array.map Form.neg args in
+ link_Other (BuildDef pl) (pl::Array.to_list nargs);
+ Array.iteri (fun i l' ->
+ link_Other (BuildProj (nl,i)) [nl;l']) args;
+ set_done l;
+ Array.iter cnf args
+
+ | For ->
+ let nl,pl = both_lit l in
+ link_Other (BuildDef nl) (nl::Array.to_list args);
+ Array.iteri (fun i l' ->
+ link_Other (BuildProj(pl,i)) [pl;Form.neg l']) args;
+ set_done l;
+ Array.iter cnf args
+
+ | Fimp ->
+ let args = or_of_imp args in
+ let nl,pl = both_lit l in
+ link_Other (BuildDef nl) (nl::Array.to_list args);
+ Array.iteri (fun i l' ->
+ link_Other (BuildProj(pl,i)) [pl;Form.neg l']) args;
+ set_done l;
+ Array.iter cnf args
+
+ | Fxor ->
+ let nl,pl = both_lit l in
+ let a, b = args.(0), args.(1) in
+ let na, nb = Form.neg a, Form.neg b in
+ link_Other (BuildDef nl) [nl;a;b];
+ link_Other (BuildDef pl) [pl;a;nb];
+ link_Other (BuildDef2 nl) [nl;na;nb];
+ link_Other (BuildDef2 pl) [pl;na;b];
+ set_done l;
+ cnf a;
+ cnf b
+
+ | Fiff ->
+ let nl,pl = both_lit l in
+ let a, b = args.(0), args.(1) in
+ let na, nb = Form.neg a, Form.neg b in
+ link_Other (BuildDef nl) [nl;a;nb];
+ link_Other (BuildDef pl) [pl;na;nb];
+ link_Other (BuildDef2 nl) [pl;na;b];
+ link_Other (BuildDef2 pl) [pl;a;b];
+ set_done l;
+ cnf a;
+ cnf b
+
+ | Fite ->
+ let nl,pl = both_lit l in
+ let a, b, c = args.(0), args.(1), args.(2) in
+ let na, nb, nc = Form.neg a, Form.neg b, Form.neg c in
+ link_Other (BuildDef nl) [nl;a;c];
+ link_Other (BuildDef pl) [pl;a;nc];
+ link_Other (BuildDef2 nl) [nl;na;b];
+ link_Other (BuildDef2 pl) [pl;na;nb];
+ set_done l;
+ cnf a;
+ cnf b;
+ cnf c
+
+ | Fnot2 _ -> cnf args.(0)
+
+ exception Cnf_done
+
+ let rec imm_link_Other other l =
+ if not (test_immediate l) then
+ let c = mkOther other (Some [l]) in
+ link !last c;
+ last := c;
+ imm_cnf c
+
+ and imm_cnf c =
+ let l =
+ match c.value with
+ | Some [l] ->
+ begin match Form.pform l with
+ | Fapp (Fnot2 _, args) ->
+ let l' = args.(0) in
+ if Form.is_pos l then l'
+ else Form.neg l'
+ | _ -> l
+ end
+ | _ -> assert false in
+ match get_info l with
+ | Immediate b -> if b = Form.is_neg l then raise Cnf_done
+ | Done -> assert false
+ | Todo ->
+ set_immediate l;
+
+ match Form.pform l with
+ | Fatom _ -> ()
+
+ | Fapp (op,args) ->
+ match op with
+ | Ftrue | Ffalse -> ()
+
+ | Fand ->
+ if Form.is_pos l then
+ Array.iteri (fun i l' ->
+ imm_link_Other (ImmBuildProj(c,i)) l') args
+ else begin
+ let nargs = Array.map Form.neg args in
+ link_Other (ImmBuildDef c) (Array.to_list nargs);
+ push_cnf args
+ end
+
+ | For ->
+ if Form.is_pos l then begin
+ link_Other (ImmBuildDef c) (Array.to_list args);
+ push_cnf args
+ end else
+ Array.iteri (fun i l' ->
+ imm_link_Other (ImmBuildProj(c,i)) (Form.neg l')) args
+
+ | Fimp ->
+ let args = or_of_imp args in
+ if Form.is_pos l then begin
+ link_Other (ImmBuildDef c) (Array.to_list args);
+ push_cnf args
+ end else
+ Array.iteri (fun i l' ->
+ imm_link_Other (ImmBuildProj(c,i)) (Form.neg l')) args
+
+ | Fxor ->
+ let args1 =
+ if Form.is_pos l then [args.(0);args.(1)]
+ else [args.(0);Form.neg args.(1)] in
+ let args2 =
+ if Form.is_pos l then [Form.neg args.(0);Form.neg args.(1)]
+ else [Form.neg args.(0); args.(1)] in
+ link_Other (ImmBuildDef c) args1;
+ link_Other (ImmBuildDef2 c) args2;
+ push_cnf args
+
+ | Fiff ->
+ let args1 =
+ if Form.is_pos l then [args.(0);Form.neg args.(1)]
+ else [Form.neg args.(0);Form.neg args.(1)] in
+ let args2 =
+ if Form.is_pos l then [Form.neg args.(0);args.(1)]
+ else [args.(0); args.(1)] in
+ link_Other (ImmBuildDef c) args1;
+ link_Other (ImmBuildDef2 c) args2;
+ push_cnf args
+
+ | Fite ->
+ let args1 =
+ if Form.is_pos l then [args.(0);Form.neg args.(2)]
+ else [args.(0);Form.neg args.(2)] in
+ let args2 =
+ if Form.is_pos l then [Form.neg args.(0);args.(1)]
+ else [Form.neg args.(0); Form.neg args.(1)] in
+ link_Other (ImmBuildDef c) args1;
+ link_Other (ImmBuildDef2 c) args2;
+ push_cnf args
+
+ | Fnot2 _ -> assert false
+
+ let make_cnf reify c =
+ let ftrue = Form.get reify (Fapp(Ftrue, [||])) in
+ let ffalse = Form.get reify (Fapp(Ffalse, [||])) in
+ last := c;
+ link_Other True [ftrue];
+ link_Other False [Form.neg ffalse];
+ (try
+ imm_cnf c;
+ List.iter (Array.iter cnf) !cnf_todo
+ with Cnf_done -> ());
+ let res = !last in
+ clear ();
+ res
+
+ end
+
diff --git a/src/trace/smtForm.ml b/src/trace/smtForm.ml
new file mode 100644
index 0000000..6075b3f
--- /dev/null
+++ b/src/trace/smtForm.ml
@@ -0,0 +1,510 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+open Util
+open SmtMisc
+open CoqTerms
+open Errors
+
+module type ATOM =
+ sig
+
+ type t
+ val index : t -> int
+
+ val equal : t -> t -> bool
+
+ val is_bool_type : t -> bool
+
+ end
+
+
+type fop =
+ | Ftrue
+ | Ffalse
+ | Fand
+ | For
+ | Fxor
+ | Fimp
+ | Fiff
+ | Fite
+ | Fnot2 of int
+
+type ('a,'f) gen_pform =
+ | Fatom of 'a
+ | Fapp of fop * 'f array
+
+
+module type FORM =
+ sig
+ type hatom
+ type t
+ type pform = (hatom, t) gen_pform
+
+ val pform_true : pform
+ val pform_false : pform
+
+ val equal : t -> t -> bool
+
+ val to_lit : t -> int
+ val index : t -> int
+ val pform : t -> pform
+
+ val neg : t -> t
+ val is_pos : t -> bool
+ val is_neg : t -> bool
+
+ val to_smt : (Format.formatter -> hatom -> unit) -> Format.formatter -> t -> unit
+
+ (* Building formula from positive formula *)
+ exception NotWellTyped of pform
+ type reify
+ val create : unit -> reify
+ val clear : reify -> unit
+ val get : reify -> pform -> t
+
+ (** Give a coq term, build the corresponding formula *)
+ val of_coq : (Term.constr -> hatom) -> reify -> Term.constr -> t
+
+ (** Flattening of [Fand] and [For], removing of [Fnot2] *)
+ val flatten : reify -> t -> t
+
+ (** Producing Coq terms *)
+
+ val to_coq : t -> Term.constr
+
+ val pform_tbl : reify -> pform array
+
+ val to_array : reify -> 'a -> (pform -> 'a) -> int * 'a array
+ val interp_tbl : reify -> Term.constr * Term.constr
+ val nvars : reify -> int
+ (** Producing a Coq term corresponding to the interpretation
+ of a formula *)
+ (** [interp_atom] map [hatom] to coq term, it is better if it produce
+ shared terms. *)
+ val interp_to_coq :
+ (hatom -> Term.constr) -> (int, Term.constr) Hashtbl.t ->
+ t -> Term.constr
+ end
+
+module Make (Atom:ATOM) =
+ struct
+
+ type hatom = Atom.t
+
+ type pform = (Atom.t, t) gen_pform
+
+ and hpform = pform gen_hashed
+
+ and t =
+ | Pos of hpform
+ | Neg of hpform
+
+ let pform_true = Fapp (Ftrue,[||])
+ let pform_false = Fapp (Ffalse,[||])
+
+ let equal h1 h2 =
+ match h1, h2 with
+ | Pos hp1, Pos hp2 -> hp1.index == hp2.index
+ | Neg hp1, Neg hp2 -> hp1.index == hp2.index
+ | _, _ -> false
+
+ let index = function
+ | Pos hp -> hp.index
+ | Neg hp -> hp.index
+
+ let to_lit = function
+ | Pos hp -> hp.index * 2
+ | Neg hp -> hp.index * 2 + 1
+
+ let neg = function
+ | Pos hp -> Neg hp
+ | Neg hp -> Pos hp
+
+ let is_pos = function
+ | Pos _ -> true
+ | _ -> false
+
+ let is_neg = function
+ | Neg _ -> true
+ | _ -> false
+
+ let pform = function
+ | Pos hp -> hp.hval
+ | Neg hp -> hp.hval
+
+
+ let rec to_smt atom_to_smt fmt = function
+ | Pos hp -> to_smt_pform atom_to_smt fmt hp.hval
+ | Neg hp ->
+ Format.fprintf fmt "(not ";
+ to_smt_pform atom_to_smt fmt hp.hval;
+ Format.fprintf fmt ")"
+
+ and to_smt_pform atom_to_smt fmt = function
+ | Fatom a -> atom_to_smt fmt a
+ | Fapp (op,args) -> to_smt_op atom_to_smt fmt op args
+
+ and to_smt_op atom_to_smt fmt op args =
+ let s = match op with
+ | Ftrue -> "true"
+ | Ffalse -> "false"
+ | Fand -> "and"
+ | For -> "or"
+ | Fxor -> "xor"
+ | Fimp -> "=>"
+ | Fiff -> "="
+ | Fite -> "ite"
+ | Fnot2 _ -> "" in
+ let (s1,s2) = if Array.length args = 0 then ("","") else ("(",")") in
+ Format.fprintf fmt "%s%s" s1 s;
+ Array.iter (fun h -> Format.fprintf fmt " "; to_smt atom_to_smt fmt h) args;
+ Format.fprintf fmt "%s" s2
+
+
+ module HashedForm =
+ struct
+
+ type t = pform
+
+ let equal pf1 pf2 =
+ match pf1, pf2 with
+ | Fatom ha1, Fatom ha2 -> Atom.equal ha1 ha2
+ | Fapp(op1,args1), Fapp(op2,args2) ->
+ op1 = op2 &&
+ Array.length args1 == Array.length args2 &&
+ (try
+ for i = 0 to Array.length args1 - 1 do
+ if not (equal args1.(i) args2.(i)) then raise Not_found
+ done;
+ true
+ with Not_found -> false)
+ | _, _ -> false
+
+ let hash pf =
+ match pf with
+ | Fatom ha1 -> Atom.index ha1 * 2
+ | Fapp(op, args) ->
+ let hash_args =
+ match Array.length args with
+ | 0 -> 0
+ | 1 -> to_lit args.(0)
+ | 2 -> (to_lit args.(1)) lsl 2 + to_lit args.(0)
+ | _ ->
+ (to_lit args.(2)) lsl 4 + (to_lit args.(1)) lsl 2 +
+ to_lit args.(0) in
+ (hash_args * 10 + Hashtbl.hash op) * 2 + 1
+
+ end
+
+ module HashForm = Hashtbl.Make (HashedForm)
+
+ type reify = {
+ mutable count : int;
+ tbl : t HashForm.t
+ }
+
+ exception NotWellTyped of pform
+
+ let check pf =
+ match pf with
+ | Fatom ha -> if not (Atom.is_bool_type ha) then raise (NotWellTyped pf)
+ | Fapp (op, args) ->
+ match op with
+ | Ftrue | Ffalse ->
+ if Array.length args <> 0 then raise (NotWellTyped pf)
+ | Fnot2 _ ->
+ if Array.length args <> 1 then raise (NotWellTyped pf)
+ | Fand | For -> ()
+ | Fxor | Fimp | Fiff ->
+ if Array.length args <> 2 then raise (NotWellTyped pf)
+ | Fite ->
+ if Array.length args <> 3 then raise (NotWellTyped pf)
+
+ let declare reify pf =
+ check pf;
+ let res = Pos {index = reify.count; hval = pf} in
+ HashForm.add reify.tbl pf res;
+ reify.count <- reify.count + 1;
+ res
+
+ let create () =
+ let reify =
+ { count = 0;
+ tbl = HashForm.create 17 } in
+ let _ = declare reify pform_true in
+ let _ = declare reify pform_false in
+ reify
+
+ let clear r =
+ r.count <- 0;
+ HashForm.clear r.tbl;
+ let _ = declare r pform_true in
+ let _ = declare r pform_false in
+ ()
+
+ let get reify pf =
+ try HashForm.find reify.tbl pf
+ with Not_found -> declare reify pf
+
+
+ (** Given a coq term, build the corresponding formula *)
+ type coq_cst =
+ | CCtrue
+ | CCfalse
+ | CCnot
+ | CCand
+ | CCor
+ | CCxor
+ | CCimp
+ | CCiff
+ | CCifb
+ | CCunknown
+
+ let op_tbl () =
+ let tbl = Hashtbl.create 29 in
+ let add (c1,c2) = Hashtbl.add tbl (Lazy.force c1) c2 in
+ List.iter add
+ [
+ ctrue,CCtrue; cfalse,CCfalse;
+ candb,CCand; corb,CCor; cxorb,CCxor; cimplb,CCimp; cnegb,CCnot;
+ ceqb,CCiff; cifb,CCifb ];
+ tbl
+
+ let op_tbl = lazy (op_tbl ())
+
+ let empty_args = [||]
+
+ let of_coq atom_of_coq reify c =
+ let op_tbl = Lazy.force op_tbl in
+ let get_cst c =
+ try Hashtbl.find op_tbl c with Not_found -> CCunknown in
+ let rec mk_hform h =
+ let c, args = Term.decompose_app h in
+ match get_cst c with
+ | CCtrue -> get reify (Fapp(Ftrue,empty_args))
+ | CCfalse -> get reify (Fapp(Ffalse,empty_args))
+ | CCnot -> mk_fnot 1 args
+ | CCand -> mk_fand [] args
+ | CCor -> mk_for [] args
+ | CCxor -> op2 (fun l -> Fapp(Fxor,l)) args
+ | CCiff -> op2 (fun l -> Fapp(Fiff,l)) args
+ | CCimp ->
+ (match args with
+ | [b1;b2] ->
+ let l1 = mk_hform b1 in
+ let l2 = mk_hform b2 in
+ get reify (Fapp (Fimp, [|l1;l2|]))
+ | _ -> error "SmtForm.Form.of_coq: wrong number of arguments for implb")
+ | CCifb ->
+ (* We should also be able to syntaxify if then else *)
+ begin match args with
+ | [b1;b2;b3] ->
+ let l1 = mk_hform b1 in
+ let l2 = mk_hform b2 in
+ let l3 = mk_hform b3 in
+ get reify (Fapp(Fite, [|l1;l2;l3|]))
+ | _ -> error "SmtForm.Form.of_coq: wrong number of arguments for ifb"
+ end
+ | _ ->
+ let a = atom_of_coq h in
+ get reify (Fatom a)
+
+ and op2 f args =
+ match args with
+ | [b1;b2] ->
+ let l1 = mk_hform b1 in
+ let l2 = mk_hform b2 in
+ get reify (f [|l1; l2|])
+ | _ -> error "SmtForm.Form.of_coq: wrong number of arguments"
+
+ and mk_fnot i args =
+ match args with
+ | [t] ->
+ let c,args = Term.decompose_app t in
+ if c = Lazy.force cnegb then
+ mk_fnot (i+1) args
+ else
+ let q,r = i lsr 1 , i land 1 in
+ let l = mk_hform t in
+ let l = if r = 0 then l else neg l in
+ if q = 0 then l
+ else get reify (Fapp(Fnot2 q, [|l|]))
+ | _ -> error "SmtForm.Form.mk_hform: wrong number of arguments for negb"
+
+ and mk_fand acc args =
+ match args with
+ | [t1;t2] ->
+ let l2 = mk_hform t2 in
+ let c, args = Term.decompose_app t1 in
+ if c = Lazy.force candb then
+ mk_fand (l2::acc) args
+ else
+ let l1 = mk_hform t1 in
+ get reify (Fapp(Fand, Array.of_list (l1::l2::acc)))
+ | _ -> error "SmtForm.Form.mk_hform: wrong number of arguments for andb"
+
+ and mk_for acc args =
+ match args with
+ | [t1;t2] ->
+ let l2 = mk_hform t2 in
+ let c, args = Term.decompose_app t1 in
+ if c = Lazy.force corb then
+ mk_for (l2::acc) args
+ else
+ let l1 = mk_hform t1 in
+ get reify (Fapp(For, Array.of_list (l1::l2::acc)))
+ | _ -> error "SmtForm.Form.mk_hform: wrong number of arguments for orb" in
+
+ let l = mk_hform c in
+ l
+
+ (** Flattening of Fand and For, removing of Fnot2 *)
+ let set_sign f f' =
+ if is_pos f then f' else neg f'
+
+ let rec flatten reify f =
+ match pform f with
+ | Fatom _ -> f
+ | Fapp(Fnot2 _,args) -> set_sign f (flatten reify args.(0))
+ | Fapp(Fand, args) -> set_sign f (flatten_and reify [] (Array.to_list args))
+ | Fapp(For,args) -> set_sign f (flatten_or reify [] (Array.to_list args))
+ | Fapp(op,args) ->
+ (* TODO change Fimp into For ? *)
+ set_sign f (get reify (Fapp(op, Array.map (flatten reify) args)))
+
+ and flatten_and reify acc args =
+ match args with
+ | [] -> get reify (Fapp(Fand, Array.of_list (List.rev acc)))
+ | a::args ->
+ (* TODO change (not For) and (not Fimp) into Fand *)
+ match pform a with
+ | Fapp(Fand, args') when is_pos a ->
+ let args = Array.fold_right (fun a args -> a::args) args' args in
+ flatten_and reify acc args
+ | _ -> flatten_and reify (flatten reify a :: acc) args
+
+ and flatten_or reify acc args =
+ (* TODO change Fimp and (not Fand) into For *)
+ match args with
+ | [] -> get reify (Fapp(For, Array.of_list (List.rev acc)))
+ | a::args ->
+ match pform a with
+ | Fapp(For, args') when is_pos a ->
+ let args = Array.fold_right (fun a args -> a::args) args' args in
+ flatten_or reify acc args
+ | _ -> flatten_or reify (flatten reify a :: acc) args
+
+ (** Producing Coq terms *)
+
+ let to_coq hf = mkInt (to_lit hf)
+
+ let args_to_coq args =
+ let cargs = Array.make (Array.length args + 1) (mkInt 0) in
+ Array.iteri (fun i hf -> cargs.(i) <- to_coq hf) args;
+ Term.mkArray (Lazy.force cint, cargs)
+
+ let pf_to_coq = function
+ | Fatom a -> mklApp cFatom [|mkInt (Atom.index a)|]
+ | Fapp(op,args) ->
+ match op with
+ | Ftrue -> Lazy.force cFtrue
+ | Ffalse -> Lazy.force cFfalse
+ | Fand -> mklApp cFand [| args_to_coq args|]
+ | For -> mklApp cFor [| args_to_coq args|]
+ | Fimp -> mklApp cFimp [| args_to_coq args|]
+ | Fxor -> mklApp cFxor (Array.map to_coq args)
+ | Fiff -> mklApp cFiff (Array.map to_coq args)
+ | Fite -> mklApp cFite (Array.map to_coq args)
+ | Fnot2 i -> mklApp cFnot2 [|mkInt i; to_coq args.(0)|]
+
+ let pform_tbl reify =
+ let t = Array.make reify.count pform_true in
+ let set _ h =
+ match h with
+ | Pos hp -> t.(hp.index) <- hp.hval
+ | _ -> assert false in
+ HashForm.iter set reify.tbl;
+ t
+
+ let to_array reify dft f =
+ let t = Array.make (reify.count + 1) dft in
+ let set _ h =
+ match h with
+ | Pos hp -> t.(hp.index) <- f hp.hval
+ | _ -> assert false in
+ HashForm.iter set reify.tbl;
+ (reify.count, t)
+
+ let interp_tbl reify =
+ let (i,t) = to_array reify (Lazy.force cFtrue) pf_to_coq in
+ (mkInt i, Term.mkArray (Lazy.force cform, t))
+
+ let nvars reify = reify.count
+ (** Producing a Coq term corresponding to the interpretation of a formula *)
+ (** [interp_atom] map [Atom.t] to coq term, it is better if it produce
+ shared terms. *)
+ let interp_to_coq interp_atom form_tbl f =
+ let rec interp_form f =
+ let l = to_lit f in
+ try Hashtbl.find form_tbl l
+ with Not_found ->
+ if is_neg f then
+ let pc = interp_form (neg f) in
+ let nc = mklApp cnegb [|pc|] in
+ Hashtbl.add form_tbl l nc;
+ nc
+ else
+ let pc =
+ match pform f with
+ | Fatom a -> interp_atom a
+ | Fapp(op, args) ->
+ match op with
+ | Ftrue -> Lazy.force ctrue
+ | Ffalse -> Lazy.force cfalse
+ | Fand -> interp_args candb args
+ | For -> interp_args corb args
+ | Fxor -> interp_args cxorb args
+ | Fimp ->
+ let r = ref (interp_form args.(Array.length args - 1)) in
+ for i = Array.length args - 2 downto 0 do
+ r := mklApp cimplb [|interp_form args.(i); !r|]
+ done;
+ !r
+ | Fiff -> interp_args ceqb args
+ | Fite ->
+ (* TODO with if here *)
+ mklApp cifb (Array.map interp_form args)
+ | Fnot2 n ->
+ let r = ref (interp_form args.(0)) in
+ for i = 1 to n do r := mklApp cnegb [|!r|] done;
+ !r in
+ Hashtbl.add form_tbl l pc;
+ pc
+ and interp_args op args =
+ let r = ref (interp_form args.(0)) in
+ for i = 1 to Array.length args - 1 do
+ r := mklApp op [|!r;interp_form args.(i)|]
+ done;
+ !r in
+ interp_form f
+
+ end
+
+
+
+
+
+
+
diff --git a/src/trace/smtForm.mli b/src/trace/smtForm.mli
new file mode 100644
index 0000000..118ecf5
--- /dev/null
+++ b/src/trace/smtForm.mli
@@ -0,0 +1,99 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+module type ATOM =
+ sig
+
+ type t
+ val index : t -> int
+
+ val equal : t -> t -> bool
+
+ val is_bool_type : t -> bool
+
+ end
+
+
+type fop =
+ | Ftrue
+ | Ffalse
+ | Fand
+ | For
+ | Fxor
+ | Fimp
+ | Fiff
+ | Fite
+ | Fnot2 of int
+
+
+type ('a,'f) gen_pform =
+ | Fatom of 'a
+ | Fapp of fop * 'f array
+
+module type FORM =
+ sig
+ type hatom
+ type t
+ type pform = (hatom, t) gen_pform
+
+ val pform_true : pform
+ val pform_false : pform
+
+ val equal : t -> t -> bool
+
+ val to_lit : t -> int
+ val index : t -> int
+ val pform : t -> pform
+
+ val neg : t -> t
+ val is_pos : t -> bool
+ val is_neg : t -> bool
+
+ val to_smt : (Format.formatter -> hatom -> unit) -> Format.formatter -> t -> unit
+
+ (* Building formula from positive formula *)
+ exception NotWellTyped of pform
+ type reify
+ val create : unit -> reify
+ val clear : reify -> unit
+ val get : reify -> pform -> t
+
+ (** Given a coq term, build the corresponding formula *)
+ val of_coq : (Term.constr -> hatom) -> reify -> Term.constr -> t
+
+ (** Flattening of [Fand] and [For], removing of [Fnot2] *)
+ val flatten : reify -> t -> t
+
+ (** Producing Coq terms *)
+
+ val to_coq : t -> Term.constr
+
+ val pform_tbl : reify -> pform array
+
+ val to_array : reify -> 'a -> (pform -> 'a) -> int * 'a array
+ val interp_tbl : reify -> Term.constr * Term.constr
+ val nvars : reify -> int
+ (** Producing a Coq term corresponding to the interpretation
+ of a formula *)
+ (** [interp_atom] map [hatom] to coq term, it is better if it produce
+ shared terms. *)
+ val interp_to_coq :
+ (hatom -> Term.constr) -> (int, Term.constr) Hashtbl.t ->
+ t -> Term.constr
+ end
+
+module Make (Atom:ATOM) : FORM with type hatom = Atom.t
+
+
diff --git a/src/trace/smtMisc.ml b/src/trace/smtMisc.ml
new file mode 100644
index 0000000..02e5f26
--- /dev/null
+++ b/src/trace/smtMisc.ml
@@ -0,0 +1,47 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+
+(** Sharing of coq Int *)
+let cInt_tbl = Hashtbl.create 17
+
+let mkInt i =
+ try Hashtbl.find cInt_tbl i
+ with Not_found ->
+ let ci = Term.mkInt (Uint63.of_int i) in
+ Hashtbl.add cInt_tbl i ci;
+ ci
+
+(** Generic representation of shared object *)
+type 'a gen_hashed = { index : int; hval : 'a }
+
+(** Functions over constr *)
+
+let mklApp f args = Term.mkApp (Lazy.force f, args)
+
+(* TODO : Set -> Type *)
+let coqtype = lazy Term.mkSet
+
+let declare_new_type t =
+ Command.declare_assumption false (Decl_kinds.Local,Decl_kinds.Definitional) (Lazy.force coqtype) [] false None (Pp.dummy_loc,t);
+ Term.mkVar t
+
+let declare_new_variable v constr_t =
+ Command.declare_assumption false (Decl_kinds.Local,Decl_kinds.Definitional) constr_t [] false None (Pp.dummy_loc,v);
+ Term.mkVar v
+
+let mkName s =
+ let id = Names.id_of_string s in
+ Names.Name id
diff --git a/src/trace/smtTrace.ml b/src/trace/smtTrace.ml
new file mode 100644
index 0000000..8420ca1
--- /dev/null
+++ b/src/trace/smtTrace.ml
@@ -0,0 +1,465 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+open SmtMisc
+open CoqTerms
+open SmtCertif
+
+let notUsed = 0
+
+let next_id = ref 0
+
+let clear () = next_id := 0
+
+let next_id () =
+ let id = !next_id in
+ incr next_id;
+ id
+
+(** Basic functions over small certificates *)
+
+let mk_scertif kind ov =
+ {
+ id = next_id ();
+ kind = kind;
+ pos = None;
+ used = notUsed;
+ prev = None;
+ next = None;
+ value = ov
+ }
+
+(** Roots *)
+
+
+let mkRootGen ov =
+ let pos = next_id () in
+ {
+ id = pos;
+ kind = Root;
+ pos = Some pos;
+ used = notUsed;
+ prev = None;
+ next = None;
+ value = ov
+ }
+
+(* let mkRoot = mkRootGen None *)
+let mkRootV v = mkRootGen (Some v)
+
+let isRoot k = k == Root
+
+(** Resolutions *)
+
+let mkRes c1 c2 tl =
+ mk_scertif (Res { rc1 = c1; rc2 = c2; rtail = tl }) None
+
+let isRes k =
+ match k with
+ | Res _ -> true
+ | _ -> false
+
+
+(** Other *)
+
+let mkOther r ov = mk_scertif (Other r) ov
+
+
+(** Moving into the trace *)
+let next c =
+ match c.next with
+ | Some c1 -> c1
+ | None -> assert false
+
+let has_prev c =
+ match c.prev with
+ | Some _ -> true
+ | None -> false
+
+let prev c =
+ match c.prev with
+ | Some c1 -> c1
+ | None -> Printf.printf "prev %i\n" c.id;flush stdout;assert false
+
+let link c1 c2 =
+ c1.next <- Some c2;
+ c2.prev <- Some c1
+
+let clear_links c =
+ c.prev <- None;
+ c.next <- None
+
+let skip c =
+ link (prev c) (next c);
+ clear_links c
+
+let insert_before c cprev =
+ link (prev c) cprev;
+ link cprev c
+
+let get_res c s =
+ match c.kind with
+ | Res res -> res
+ | _ -> Printf.printf "get_res %s\n" s; assert false
+
+let get_other c s =
+ match c.kind with
+ | Other res -> res
+ | _ -> Printf.printf "get_other %s\n" s; assert false
+
+let get_val c =
+ match c.value with
+ | None -> assert false
+ | Some cl -> cl
+
+let rec repr c =
+ match c.kind with
+ | Root | Res _ | Other _ -> c
+ | Same c -> repr c
+
+let set_same c nc =
+ c.kind <- Same (repr nc);
+ skip c
+
+let rec get_pos c =
+ match c.kind with
+ | Root | Res _ | Other _ ->
+ begin match c.pos with
+ | Some n -> n
+ | _ -> assert false
+ end
+ | Same c -> get_pos c
+
+let eq_clause c1 c2 = (repr c1).id = (repr c2).id
+
+(* Selection of useful rules *)
+let select c =
+ let mark c =
+ if not (isRoot c.kind) then c.used <- 1 in
+ mark c;
+ let r = ref c in
+ while not (isRoot !r.kind) do
+ let p = prev !r in
+ (match !r.kind with
+ | Res res ->
+ if !r.used == 1 then begin
+ !r.used <- notUsed;
+ (* let res = get_res !r "select" in *)
+ mark res.rc1; mark res.rc2;
+ List.iter mark res.rtail
+ end else
+ skip !r;
+ | Same _ ->
+ skip !r
+ | _ ->
+ if !r.used == 1 then
+ begin
+ !r.used <- notUsed;
+ let rl = get_other !r "select" in
+ List.iter mark (used_clauses rl)
+ end
+ else skip !r;
+ );
+ r := p
+ done
+
+
+
+
+(* Compute the number of occurence of each_clause *)
+
+let rec occur c =
+ match c.kind with
+ | Root -> c.used <- c.used + 1
+ | Res res ->
+ if c.used == notUsed then
+ begin occur res.rc1; occur res.rc2; List.iter occur res.rtail end;
+ c.used <- c.used + 1
+ | Other res ->
+ if c.used == notUsed then List.iter occur (used_clauses res);
+ c.used <- c.used + 1;
+ | Same c' ->
+ occur c';
+ c.used <- c.used + 1
+
+(* Allocate clause *)
+
+let alloc c =
+ let free_pos = ref [] in
+
+ (* free the unused roots *)
+
+ let r = ref c in
+ while isRoot !r.kind do
+ if !r.used == notUsed then begin
+ free_pos := get_pos !r :: !free_pos;
+ end;
+ r := next !r;
+ done;
+
+ (* r is the first clause defined by resolution or another rule,
+ normaly the first used *)
+ let last_set = ref (get_pos (prev !r)) in
+
+ let decr_clause c =
+ let rc = repr c in
+ assert (rc.used > notUsed);
+ rc.used <- rc.used - 1;
+ if rc.used = notUsed then
+ free_pos := get_pos rc :: !free_pos in
+
+ let decr_res res =
+ decr_clause res.rc1;
+ decr_clause res.rc2;
+ List.iter decr_clause res.rtail in
+
+ let decr_other o =
+ List.iter decr_clause (used_clauses o) in
+
+ while !r.next <> None do
+ let n = next !r in
+ assert (!r.used <> notUsed);
+ if isRes !r.kind then
+ decr_res (get_res !r "alloc")
+ else
+ decr_other (get_other !r "alloc");
+ begin match !free_pos with
+ | p::free -> free_pos := free; !r.pos <- Some p
+ | _ -> incr last_set; !r.pos <- Some !last_set
+ end;
+ r := n
+ done;
+ begin match !free_pos with
+ | p::free -> free_pos := free; !r.pos <- Some p
+ | _ -> incr last_set; !r.pos <- Some !last_set
+ end;
+ !last_set
+
+
+(* A naive allocation for debugging *)
+
+let naive_alloc c =
+ let r = ref c in
+ while isRoot !r.kind do
+ r := next !r
+ done;
+ let last_set = ref (get_pos (prev !r)) in
+ while !r.next <> None do
+ let n = next !r in
+ incr last_set; !r.pos <- Some !last_set;
+ r := n
+ done;
+ incr last_set; !r.pos <- Some !last_set;
+ !last_set
+
+
+(* This function is currently inlined in verit/verit.ml and zchaff/zchaff.ml *)
+
+let build_certif first_root confl =
+ select confl;
+ occur confl;
+ alloc first_root
+
+
+let to_coq to_lit (cstep,
+ cRes, cImmFlatten,
+ cTrue, cFalse, cBuildDef, cBuildDef2, cBuildProj,
+ cImmBuildProj,cImmBuildDef,cImmBuildDef2,
+ cEqTr, cEqCgr, cEqCgrP,
+ cLiaMicromega, cLiaDiseq, cSplArith, cSplDistinctElim) confl =
+ let out_f f = to_lit f in
+ let out_c c = mkInt (get_pos c) in
+ let step_to_coq c =
+ match c.kind with
+ | Res res ->
+ let size = List.length res.rtail + 3 in
+ let args = Array.make size (mkInt 0) in
+ args.(0) <- mkInt (get_pos res.rc1);
+ args.(1) <- mkInt (get_pos res.rc2);
+ let l = ref res.rtail in
+ for i = 2 to size - 2 do
+ match !l with
+ | c::tl ->
+ args.(i) <- mkInt (get_pos c);
+ l := tl
+ | _ -> assert false
+ done;
+ mklApp cRes [|mkInt (get_pos c); Term.mkArray (Lazy.force cint, args)|]
+ | Other other ->
+ begin match other with
+ | ImmFlatten (c',f) -> mklApp cImmFlatten [|out_c c;out_c c'; out_f f|]
+ | True -> mklApp cTrue [|out_c c|]
+ | False -> mklApp cFalse [|out_c c|]
+ | BuildDef f -> mklApp cBuildDef [|out_c c; out_f f|]
+ | BuildDef2 f -> mklApp cBuildDef2 [|out_c c;out_f f|]
+ | BuildProj (f, i) -> mklApp cBuildProj [|out_c c; out_f f;mkInt i|]
+ | ImmBuildDef c' -> mklApp cImmBuildDef [|out_c c; out_c c'|]
+ | ImmBuildDef2 c' -> mklApp cImmBuildDef2 [|out_c c;out_c c'|]
+ | ImmBuildProj(c', i) -> mklApp cImmBuildProj [|out_c c; out_c c';mkInt i|]
+ | EqTr (f, fl) ->
+ let res = List.fold_right (fun f l -> mklApp ccons [|Lazy.force cint; out_f f; l|]) fl (mklApp cnil [|Lazy.force cint|]) in
+ mklApp cEqTr [|out_c c; out_f f; res|]
+ | EqCgr (f, fl) ->
+ let res = List.fold_right (fun f l -> mklApp ccons [|mklApp coption [|Lazy.force cint|]; (match f with | Some f -> mklApp cSome [|Lazy.force cint; out_f f|] | None -> mklApp cNone [|Lazy.force cint|]); l|]) fl (mklApp cnil [|mklApp coption [|Lazy.force cint|]|]) in
+ mklApp cEqCgr [|out_c c; out_f f; res|]
+ | EqCgrP (f1, f2, fl) ->
+ let res = List.fold_right (fun f l -> mklApp ccons [|mklApp coption [|Lazy.force cint|]; (match f with | Some f -> mklApp cSome [|Lazy.force cint; out_f f|] | None -> mklApp cNone [|Lazy.force cint|]); l|]) fl (mklApp cnil [|mklApp coption [|Lazy.force cint|]|]) in
+ mklApp cEqCgrP [|out_c c; out_f f1; out_f f2; res|]
+ | LiaMicromega (cl,d) ->
+ let cl' = List.fold_right (fun f l -> mklApp ccons [|Lazy.force cint; out_f f; l|]) cl (mklApp cnil [|Lazy.force cint|]) in
+ let c' = List.fold_right (fun f l -> mklApp ccons [|Lazy.force Coq_micromega.M.coq_proofTerm; Coq_micromega.dump_proof_term f; l|]) d (mklApp cnil [|Lazy.force Coq_micromega.M.coq_proofTerm|]) in
+ mklApp cLiaMicromega [|out_c c; cl'; c'|]
+ | LiaDiseq l -> mklApp cLiaDiseq [|out_c c; out_f l|]
+ | SplArith (orig,res,l) ->
+ let res' = out_f res in
+ let l' = List.fold_right (fun f l -> mklApp ccons [|Lazy.force Coq_micromega.M.coq_proofTerm; Coq_micromega.dump_proof_term f; l|]) l (mklApp cnil [|Lazy.force Coq_micromega.M.coq_proofTerm|]) in
+ mklApp cSplArith [|out_c c; out_c orig; res'; l'|]
+ | SplDistinctElim (c',f) -> mklApp cSplDistinctElim [|out_c c;out_c c'; out_f f|]
+ end
+ | _ -> assert false in
+ let step = Lazy.force cstep in
+ let def_step =
+ mklApp cRes [|mkInt 0; Term.mkArray (Lazy.force cint, [|mkInt 0|]) |] in
+ let r = ref confl in
+ let nc = ref 0 in
+ while not (isRoot !r.kind) do r := prev !r; incr nc done;
+ let last_root = !r in
+ let size = !nc in
+ let max = (Parray.trunc_size (Uint63.of_int 4194303)) - 1 in
+ let q,r1 = size / max, size mod max in
+
+ let trace =
+ let len = if r1 = 0 then q + 1 else q + 2 in
+ Array.make len (Term.mkArray (step, [|def_step|])) in
+ for j = 0 to q - 1 do
+ let tracej = Array.make (Parray.trunc_size (Uint63.of_int 4194303)) def_step in
+ for i = 0 to max - 1 do
+ r := next !r;
+ tracej.(i) <- step_to_coq !r;
+ done;
+ trace.(j) <- Term.mkArray (step, tracej)
+ done;
+ if r1 <> 0 then begin
+ let traceq = Array.make (r1 + 1) def_step in
+ for i = 0 to r1-1 do
+ r := next !r;
+ traceq.(i) <- step_to_coq !r;
+ done;
+ trace.(q) <- Term.mkArray (step, traceq)
+ end;
+
+ (Term.mkArray (mklApp carray [|step|], trace), last_root)
+
+
+
+(** Optimization of the trace *)
+
+module MakeOpt (Form:SmtForm.FORM) =
+ struct
+ (* Share the certificate building a common clause *)
+ let share_value c =
+ let tbl = Hashtbl.create 17 in
+ let to_lits v = List.map (Form.to_lit) v in
+ let process c =
+ match c.value with
+ | None -> ()
+ | Some v ->
+ let lits = to_lits v in
+ try
+ let c' = Hashtbl.find tbl lits in
+ set_same c c'
+ with Not_found -> Hashtbl.add tbl lits c in
+ let r = ref c in
+ while !r.next <> None do
+ let next = next !r in
+ process !r;
+ r := next
+ done;
+ process !r
+
+ (* Sharing of the common prefix *)
+
+ module HashedHeadRes =
+ struct
+
+ type t = Form.t resolution
+
+ let equal r1 r2 =
+ eq_clause r1.rc1 r2.rc1 && eq_clause r1.rc2 r2.rc2
+
+ let hash r = (repr r.rc1).id * 19 + (repr r.rc2).id
+
+ end
+
+ module HRtbl = Hashtbl.Make (HashedHeadRes)
+
+ let common_head tl1 tl2 =
+ let rec aux rhd tl1 tl2 =
+ match tl1, tl2 with
+ | [], _ -> List.rev rhd, tl1, tl2
+ | _, [] -> List.rev rhd, tl1, tl2
+ | c1::tl1', c2::tl2' ->
+ if eq_clause c1 c2 then aux (repr c1 :: rhd) tl1' tl2'
+ else List.rev rhd, tl1, tl2
+ in aux [] tl1 tl2
+
+ let share_prefix first_c n =
+ let tbl = HRtbl.create (min n Sys.max_array_length) in
+ let rec share c2 =
+ if isRes c2.kind then (
+ let res2 = get_res c2 "share_prefix1" in
+ try
+ let c1 = HRtbl.find tbl res2 in
+ let res1 = get_res c1 "share_prefix2" in
+ (* res1 and res2 have the same head *)
+ let head, tl1, tl2 = common_head res1.rtail res2.rtail in
+ match tl1, tl2 with
+ | [], [] ->
+ set_same c2 c1;
+ | [], c2'::tl2' ->
+ res2.rc1 <- c1;
+ res2.rc2 <- c2';
+ res2.rtail <- tl2';
+ share c2
+ | c1'::tl1', [] ->
+ skip c2;
+ HRtbl.remove tbl res1;
+ insert_before c1 c2;
+ res1.rc1 <- c2;
+ res1.rc2 <- c1';
+ res1.rtail <- tl1';
+ share c1
+ | c1'::tl1', c2'::tl2' ->
+ let c = mkRes res1.rc1 res1.rc2 head in
+ HRtbl.remove tbl res1;
+ insert_before c1 c;
+ res1.rc1 <- c;
+ res1.rc2 <- c1';
+ res1.rtail <- tl1';
+ res2.rc1 <- c;
+ res2.rc2 <- c2';
+ res2.rtail <- tl2';
+ share c;
+ share c1;
+ share c2
+ with Not_found -> HRtbl.add tbl res2 c2
+ ) in
+ let r = ref first_c in
+ while !r.next <> None do
+ let n = next !r in
+ share !r;
+ r := n
+ done
+
+ end
diff --git a/src/trace/smt_tactic.ml4 b/src/trace/smt_tactic.ml4
new file mode 100644
index 0000000..219810d
--- /dev/null
+++ b/src/trace/smt_tactic.ml4
@@ -0,0 +1,55 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+
+VERNAC COMMAND EXTEND Parse_certif_zchaff
+| [ "Parse_certif_zchaff"
+ ident(dimacs) ident(trace) string(fdimacs) string(fproof) ] ->
+ [
+ Zchaff.parse_certif dimacs trace fdimacs fproof
+ ]
+| [ "Zchaff_Checker" string(fdimacs) string(fproof) ] ->
+ [
+ Zchaff.checker fdimacs fproof
+ ]
+| [ "Zchaff_Theorem" ident(name) string(fdimacs) string(fproof) ] ->
+ [
+ Zchaff.theorem name fdimacs fproof
+ ]
+END
+
+VERNAC COMMAND EXTEND Parse_certif_verit
+| [ "Parse_certif_verit"
+ ident(t_i) ident(t_func) ident(t_atom) ident(t_form) ident(root) ident(used_roots) ident(trace) string(fsmt) string(fproof) ] ->
+ [
+ Verit.parse_certif t_i t_func t_atom t_form root used_roots trace fsmt fproof
+ ]
+| [ "Verit_Checker" string(fsmt) string(fproof) ] ->
+ [
+ Verit.checker fsmt fproof
+ ]
+| [ "Verit_Theorem" ident(name) string(fsmt) string(fproof) ] ->
+ [
+ Verit.theorem name fsmt fproof
+ ]
+END
+
+TACTIC EXTEND zchaff
+| [ "zchaff" ] -> [ Zchaff.tactic ]
+END
+
+TACTIC EXTEND verit
+| [ "verit" ] -> [ Verit.tactic ]
+END
diff --git a/src/verit/smtlib2_ast.ml b/src/verit/smtlib2_ast.ml
new file mode 100644
index 0000000..cce4625
--- /dev/null
+++ b/src/verit/smtlib2_ast.ml
@@ -0,0 +1,189 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq, originally belong to The Alt-ergo theorem prover *)
+(* Copyright (C) 2006-2010 *)
+(* *)
+(* Sylvain Conchon *)
+(* Evelyne Contejean *)
+(* Stephane Lescuyer *)
+(* Mohamed Iguernelala *)
+(* Alain Mebsout *)
+(* *)
+(* CNRS - INRIA - Universite Paris Sud *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+open Smtlib2_util
+
+type loc = Lexing.position * Lexing.position
+
+type specconstant =
+ | SpecConstsDec of loc * string
+ | SpecConstNum of loc * string
+ | SpecConstString of loc * string
+ | SpecConstsHex of loc * string
+ | SpecConstsBinary of loc * string
+
+type symbol =
+ | Symbol of loc * string
+ | SymbolWithOr of loc * string
+
+type sexpr =
+ | SexprSpecConst of loc * specconstant
+ | SexprSymbol of loc * symbol
+ | SexprKeyword of loc * string
+ | SexprInParen of loc * (loc * sexpr list)
+
+type attributevalue =
+ | AttributeValSpecConst of loc * specconstant
+ | AttributeValSymbol of loc * symbol
+ | AttributeValSexpr of loc * (loc * sexpr list)
+
+type attribute =
+ | AttributeKeyword of loc * string
+ | AttributeKeywordValue of loc * string * attributevalue
+
+type an_option = AnOptionAttribute of loc * attribute
+
+type infoflag = InfoFlagKeyword of loc * string
+
+type identifier =
+ | IdSymbol of loc * symbol
+ | IdUnderscoreSymNum of loc * symbol * (loc * string list)
+
+type sort =
+ | SortIdentifier of loc * identifier
+ | SortIdSortMulti of loc * identifier * (loc * sort list)
+
+type qualidentifier =
+ | QualIdentifierId of loc * identifier
+ | QualIdentifierAs of loc * identifier * sort
+
+type sortedvar =
+ | SortedVarSymSort of loc * symbol * sort
+
+type varbinding = VarBindingSymTerm of loc * symbol * term
+
+and term =
+ | TermSpecConst of loc * specconstant
+ | TermQualIdentifier of loc * qualidentifier
+ | TermQualIdTerm of loc * qualidentifier * (loc * term list)
+ | TermLetTerm of loc * (loc * varbinding list) * term
+ | TermForAllTerm of loc * (loc * sortedvar list) * term
+ | TermExistsTerm of loc * (loc * sortedvar list) * term
+ | TermExclimationPt of loc * term * (loc * attribute list)
+
+type command =
+ | CSetLogic of loc * symbol
+ | CSetOption of loc * an_option
+ | CSetInfo of loc * attribute
+ | CDeclareSort of loc * symbol * string
+ | CDefineSort of loc * symbol * (loc * symbol list) * sort
+ | CDeclareFun of loc * symbol * (loc * sort list) * sort
+ | CDefineFun of loc * symbol * (loc * sortedvar list) * sort * term
+ | CPush of loc * string
+ | CPop of loc * string
+ | CAssert of loc * term
+ | CCheckSat of loc
+ | CGetAssert of loc
+ | CGetProof of loc
+ | CGetUnsatCore of loc
+ | CGetValue of loc * (loc * term list)
+ | CGetAssign of loc
+ | CGetOption of loc * string
+ | CGetInfo of loc * infoflag
+ | CExit of loc
+
+type commands = Commands of loc * (loc * command list)
+
+
+(* loc stands for pos (position) and extradata *)
+
+let loc_an_option = function
+ | AnOptionAttribute(d,_) -> d
+
+let loc_attribute = function
+ | AttributeKeyword(d,_) -> d
+ | AttributeKeywordValue(d,_,_) -> d
+
+let loc_attributevalue = function
+ | AttributeValSpecConst(d,_) -> d
+ | AttributeValSymbol(d,_) -> d
+ | AttributeValSexpr(d,_) -> d
+
+let loc_command = function
+ | CSetLogic(d,_) -> d
+ | CSetOption(d,_) -> d
+ | CSetInfo(d,_) -> d
+ | CDeclareSort(d,_,_) -> d
+ | CDefineSort(d,_,_,_) -> d
+ | CDeclareFun(d,_,_,_) -> d
+ | CDefineFun(d,_,_,_,_) -> d
+ | CPush(d,_) -> d
+ | CPop(d,_) -> d
+ | CAssert(d,_) -> d
+ | CCheckSat(d) -> d
+ | CGetAssert(d) -> d
+ | CGetProof(d) -> d
+ | CGetUnsatCore(d) -> d
+ | CGetValue(d,_) -> d
+ | CGetAssign(d) -> d
+ | CGetOption(d,_) -> d
+ | CGetInfo(d,_) -> d
+ | CExit(d) -> d
+
+let loc_commands = function
+ | Commands(d,_) -> d
+
+let loc_identifier = function
+ | IdSymbol(d,_) -> d
+ | IdUnderscoreSymNum(d,_,_) -> d
+
+let loc_infoflag = function
+ | InfoFlagKeyword(d,_) -> d
+
+let loc_qualidentifier = function
+ | QualIdentifierId(d,_) -> d
+ | QualIdentifierAs(d,_,_) -> d
+
+let loc_sexpr = function
+ | SexprSpecConst(d,_) -> d
+ | SexprSymbol(d,_) -> d
+ | SexprKeyword(d,_) -> d
+ | SexprInParen(d,_) -> d
+
+let loc_sort = function
+ | SortIdentifier(d,_) -> d
+ | SortIdSortMulti(d,_,_) -> d
+
+let loc_sortedvar = function
+ | SortedVarSymSort(d,_,_) -> d
+
+let loc_specconstant = function
+ | SpecConstsDec(d,_) -> d
+ | SpecConstNum(d,_) -> d
+ | SpecConstString(d,_) -> d
+ | SpecConstsHex(d,_) -> d
+ | SpecConstsBinary(d,_) -> d
+
+let loc_symbol = function
+ | Symbol(d,_) -> d
+ | SymbolWithOr(d,_) -> d
+
+let loc_term = function
+ | TermSpecConst(d,_) -> d
+ | TermQualIdentifier(d,_) -> d
+ | TermQualIdTerm(d,_,_) -> d
+ | TermLetTerm(d,_,_) -> d
+ | TermForAllTerm(d,_,_) -> d
+ | TermExistsTerm(d,_,_) -> d
+ | TermExclimationPt(d,_,_) -> d
+
+let loc_varbinding = function
+ | VarBindingSymTerm(d,_,_) -> d
+
+let loc_couple = fst
+
+let loc_of e = loc_commands e;;
diff --git a/src/verit/smtlib2_genConstr.ml b/src/verit/smtlib2_genConstr.ml
new file mode 100644
index 0000000..f11d650
--- /dev/null
+++ b/src/verit/smtlib2_genConstr.ml
@@ -0,0 +1,226 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+open Smtlib2_ast
+open SmtAtom
+open SmtForm
+open SmtMisc
+open CoqTerms
+
+
+(* For debugging *)
+
+let pp_symbol s =
+ let pp_position p = "{pos_fname = "^p.Lexing.pos_fname^"; pos_lnum = "^(string_of_int p.Lexing.pos_lnum)^"; pos_bol = "^(string_of_int p.Lexing.pos_bol)^"; pos_cnum = "^(string_of_int p.Lexing.pos_cnum)^"}" in
+
+ let pp_loc (p1,p2) = "("^(pp_position p1)^", "^(pp_position p2)^")" in
+
+ match s with
+ | Symbol (l,s) -> "Symbol ("^(pp_loc l)^", "^s^")"
+ | SymbolWithOr (l,s) -> "SymbolWithOr ("^(pp_loc l)^", "^s^")"
+
+
+(* Main functions *)
+
+let string_of_symbol = function | Symbol (_,s) | SymbolWithOr (_,s) -> s
+
+
+let identifier_of_qualidentifier = function
+ | QualIdentifierId (_,id) | QualIdentifierAs (_,id,_) -> id
+
+
+let string_type s = match s with
+ | "Bool" -> Tbool
+ | "Int" -> TZ
+ | _ -> VeritSyntax.get_btype s
+
+
+let sort_of_string s = (string_type s, [])
+
+
+let sort_of_symbol s = sort_of_string (string_of_symbol s)
+
+
+let string_of_identifier = function
+ | IdSymbol (_,s) -> (string_of_symbol s)
+ | IdUnderscoreSymNum (_,s,(_,l)) ->
+ List.fold_left (fun c c' -> c^"_"^c') (string_of_symbol s) l
+
+
+let string_of_qualidentifier id = string_of_identifier (identifier_of_qualidentifier id)
+
+
+let rec sort_of_sort = function
+ | SortIdentifier (_,id) -> sort_of_string (string_of_identifier id)
+ | SortIdSortMulti (_,id,(_,l)) ->
+ (string_type (string_of_identifier id), List.map sort_of_sort l)
+
+
+let declare_sort rt sym =
+ let s = string_of_symbol sym in
+ let cons_t = declare_new_type (Names.id_of_string ("Smt_sort_"^s)) in
+ let eq_t = declare_new_variable (Names.id_of_string ("eq_"^s)) (Term.mkArrow cons_t (Term.mkArrow cons_t (Lazy.force cbool))) in
+ let x = mkName "x" in
+ let y = mkName "y" in
+ let rx = Term.mkRel 2 in
+ let ry = Term.mkRel 1 in
+ let eq_refl = Term.mkProd (x,cons_t,Term.mkProd (y,cons_t,mklApp creflect [|mklApp ceq [|cons_t;rx;ry|];mklApp (lazy eq_t) [|rx;ry|]|])) in
+ let eq_refl_v = declare_new_variable (Names.id_of_string ("eq_refl_"^s)) eq_refl in
+ let ce = mklApp cTyp_eqb [|cons_t;eq_t;eq_refl_v|] in
+ let res = Btype.declare rt cons_t ce in
+ VeritSyntax.add_btype s res;
+ res
+
+
+let declare_fun rt ro sym arg cod =
+ let s = string_of_symbol sym in
+ let tyl = List.map sort_of_sort arg in
+ let ty = sort_of_sort cod in
+
+ let coqTy = List.fold_right (fun typ c -> Term.mkArrow (Btype.interp_to_coq rt (fst typ)) c) tyl (Btype.interp_to_coq rt (fst ty)) in
+ let cons_v = declare_new_variable (Names.id_of_string ("Smt_var_"^s)) coqTy in
+
+ let op = Op.declare ro cons_v (Array.of_list (List.map fst tyl)) (fst ty) in
+ VeritSyntax.add_fun s op;
+ op
+
+
+let make_root_specconstant ra = function
+ | SpecConstsDec _ -> failwith "Smtlib2_genConstr.make_root_specconstant: decimals not implemented yet"
+ | SpecConstNum (_,s) ->
+ (try
+ let i = int_of_string s in
+ Atom.hatom_Z_of_int ra i
+ with
+ | Failure _ ->
+ let i = Big_int.big_int_of_string s in
+ Atom.hatom_Z_of_bigint ra i)
+ | SpecConstString _ -> failwith "Smtlib2_genConstr.make_root_specconstant: strings not implemented yet"
+ | SpecConstsHex _ -> failwith "Smtlib2_genConstr.make_root_specconstant: hexadecimals not implemented yet"
+ | SpecConstsBinary _ -> failwith "Smtlib2_genConstr.make_root_specconstant: binaries not implemented yet"
+
+
+type atom_form = | Atom of SmtAtom.Atom.t | Form of SmtAtom.Form.t
+
+
+let make_root ra rf t =
+
+ let hlets = Hashtbl.create 17 in
+
+ let rec make_root_term = function
+ | TermSpecConst (_,c) -> Atom (make_root_specconstant ra c)
+ | TermQualIdentifier (_,id) ->
+ let v = string_of_qualidentifier id in
+ (try Hashtbl.find hlets v with
+ | Not_found ->
+ make_root_app v [])
+ | TermQualIdTerm (_,id,(_,l)) ->
+ let v = string_of_qualidentifier id in
+ make_root_app v l
+ | TermLetTerm (_,(_,l),t) ->
+ List.iter (fun (VarBindingSymTerm (_, sym, u)) ->
+ let u' = make_root_term u in
+ let s' = string_of_symbol sym in
+ Hashtbl.add hlets s' u') l;
+ make_root_term t
+ | TermForAllTerm _ -> failwith "Smtlib2_genConstr.make_root_term: ForAll not implemented yet"
+ | TermExistsTerm _ -> failwith "Smtlib2_genConstr.make_root_term: Exists not implemented yet"
+ | TermExclimationPt (_,t,_) -> make_root_term t
+
+ and make_root_app v l =
+ match (v,l) with
+ | "=", [a;b] ->
+ (match make_root_term a, make_root_term b with
+ | Atom a', Atom b' ->
+ (match Atom.type_of a' with
+ | Tbool -> Form (Form.get rf (Fapp (Fiff, [|Form.get rf (Fatom a'); Form.get rf (Fatom b')|])))
+ | ty -> Atom (Atom.mk_eq ra ty a' b'))
+ | _, _ -> assert false)
+ | "<", [a;b] ->
+ (match make_root_term a, make_root_term b with
+ | Atom a', Atom b' -> Atom (Atom.mk_lt ra a' b')
+ | _, _ -> assert false)
+ | "<=", [a;b] ->
+ (match make_root_term a, make_root_term b with
+ | Atom a', Atom b' -> Atom (Atom.mk_le ra a' b')
+ | _, _ -> assert false)
+ | ">", [a;b] ->
+ (match make_root_term a, make_root_term b with
+ | Atom a', Atom b' -> Atom (Atom.mk_gt ra a' b')
+ | _, _ -> assert false)
+ | ">=", [a;b] ->
+ (match make_root_term a, make_root_term b with
+ | Atom a', Atom b' -> Atom (Atom.mk_ge ra a' b')
+ | _, _ -> assert false)
+ | "+", [a;b] ->
+ (match make_root_term a, make_root_term b with
+ | Atom a', Atom b' -> Atom (Atom.mk_plus ra a' b')
+ | _, _ -> assert false)
+ | "-", [a;b] ->
+ (match make_root_term a, make_root_term b with
+ | Atom a', Atom b' -> Atom (Atom.mk_minus ra a' b')
+ | _, _ -> assert false)
+ | "*", [a;b] ->
+ (match make_root_term a, make_root_term b with
+ | Atom a', Atom b' -> Atom (Atom.mk_mult ra a' b')
+ | _, _ -> assert false)
+ | "-", [a] ->
+ (match make_root_term a with
+ | Atom a' -> Atom (Atom.mk_opp ra a')
+ | _ -> assert false)
+ | "distinct", _ ->
+ let make_h h =
+ match make_root_term h with
+ | Atom h' -> h'
+ | _ -> assert false in
+ let a = Array.make (List.length l) (make_h (List.hd l)) in
+ let i = ref (-1) in
+ List.iter (fun h ->
+ incr i;
+ a.(!i) <- make_h h) l;
+ Atom (Atom.mk_distinct ra (Atom.type_of a.(0)) a)
+ | "true", _ -> Form (Form.get rf Form.pform_true)
+ | "false", _ -> Form (Form.get rf Form.pform_false)
+ | "and", _ ->
+ Form (Form.get rf (Fapp (Fand, Array.of_list (List.map make_root l))))
+ | "or", _ ->
+ Form (Form.get rf (Fapp (For, Array.of_list (List.map make_root l))))
+ | "xor", _ ->
+ Form (Form.get rf (Fapp (Fxor, Array.of_list (List.map make_root l))))
+ | "=>", _ ->
+ Form (Form.get rf (Fapp (Fimp, Array.of_list (List.map make_root l))))
+ | "ite", _ ->
+ Form (Form.get rf (Fapp (Fite, Array.of_list (List.map make_root l))))
+ | "not", [a] -> Form (Form.neg (make_root a))
+ | _, _ ->
+ let op = VeritSyntax.get_fun v in
+ let l' = List.map (fun t -> match make_root_term t with
+ | Atom h -> h | Form _ -> assert false) l in
+ Atom (Atom.get ra (Aapp (op, Array.of_list l')))
+
+ and make_root t =
+ match make_root_term t with
+ | Atom h -> Form.get rf (Fatom h)
+ | Form f -> f in
+
+ make_root t
+
+
+let declare_commands rt ro ra rf acc = function
+ | CDeclareSort (_,sym,_) -> let _ = declare_sort rt sym in acc
+ | CDeclareFun (_,sym, (_, arg), cod) ->
+ let _ = declare_fun rt ro sym arg cod in acc
+ | CAssert (_, t) -> (make_root ra rf t)::acc
+ | _ -> acc
diff --git a/src/verit/smtlib2_lex.mll b/src/verit/smtlib2_lex.mll
new file mode 100644
index 0000000..f235403
--- /dev/null
+++ b/src/verit/smtlib2_lex.mll
@@ -0,0 +1,88 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq, originally belong to The Alt-ergo theorem prover *)
+(* Copyright (C) 2006-2010 *)
+(* *)
+(* Sylvain Conchon *)
+(* Evelyne Contejean *)
+(* Stephane Lescuyer *)
+(* Mohamed Iguernelala *)
+(* Alain Mebsout *)
+(* *)
+(* CNRS - INRIA - Universite Paris Sud *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+{
+open Lexing
+open Smtlib2_parse
+
+
+let newline lexbuf =
+ let pos = lexbuf.lex_curr_p in
+ lexbuf.lex_curr_p <-
+ { pos with pos_lnum = pos.pos_lnum + 1; pos_bol = pos.pos_cnum;
+ pos_cnum=0 }
+
+}
+
+rule token = parse
+| ['\t' ' ' ]+
+ { token lexbuf }
+| ';' (_ # '\n')*
+ { token lexbuf }
+| ['\n']+ as str
+ { newline lexbuf;
+ Smtlib2_util.line := (!Smtlib2_util.line + (String.length str));
+ token lexbuf }
+| "_" { UNDERSCORE }
+| "(" { LPAREN }
+| ")" { RPAREN }
+| "as" { AS }
+| "let" { LET }
+| "forall" { FORALL }
+| "exists" { EXISTS }
+| "!" { EXCLIMATIONPT }
+| "set-logic" { SETLOGIC }
+| "set-option" { SETOPTION }
+| "set-info" { SETINFO }
+| "declare-sort" { DECLARESORT }
+| "define-sort" { DEFINESORT }
+| "declare-fun" { DECLAREFUN }
+| "define-fun" { DEFINEFUN }
+| "push" { PUSH }
+| "pop" { POP }
+| "assert" { ASSERT }
+| "check-sat" { CHECKSAT }
+| "get-assertions" { GETASSERT }
+| "get-proof" { GETPROOF }
+| "get-unsat-core" { GETUNSATCORE }
+| "get-value" { GETVALUE }
+| "get-assignment" { GETASSIGN }
+| "get-option" { GETOPTION }
+| "get-info" { GETINFO }
+| "exit" { EXIT }
+| '#' 'x' ['0'-'9' 'A'-'F' 'a'-'f']+ as str
+ { HEXADECIMAL(str) }
+| '#' 'b' ['0'-'1']+ as str
+ { BINARY(str) }
+| '|' ([ '!'-'~' ' ' '\n' '\t' '\r'] # ['\\' '|'])* '|' as str
+ { ASCIIWOR(str) }
+| ':' ['a'-'z' 'A'-'Z' '0'-'9' '+' '-' '/' '*' '=' '%' '?' '!' '.' '$' '_' '~' '&' '^' '<' '>' '@']+ as str
+ { KEYWORD(str) }
+| ['a'-'z' 'A'-'Z' '+' '-' '/' '*' '=''%' '?' '!' '.' '$' '_' '~' '&' '^' '<' '>' '@'] ['a'-'z' 'A'-'Z' '0'-'9' '+' '-' '/' '*' '=''%' '?' '!' '.' '$' '_' '~' '&' '^' '<' '>' '@']* as str
+ { SYMBOL(str) }
+| '"' (([ '!'-'~' ' ' '\n' '\t' '\r' ] # ['\\' '"']) | ('\\' ['!'-'~' ' ' '\n' '\t' '\r'] ))* '"' as str
+ { STRINGLIT(str) }
+| ( '0' | ['1'-'9'] ['0'-'9']* ) as str
+ { NUMERAL(str) }
+| ( '0' | ['1'-'9'] ['0'-'9']* ) '.' ['0'-'9']+ as str
+ { DECIMAL(str) }
+| eof
+ { EOF }
+| _
+ {failwith(
+ (Lexing.lexeme lexbuf) ^
+ ": lexing error on line "^(string_of_int !Smtlib2_util.line))}{}
diff --git a/src/verit/smtlib2_parse.mly b/src/verit/smtlib2_parse.mly
new file mode 100644
index 0000000..b4e02a7
--- /dev/null
+++ b/src/verit/smtlib2_parse.mly
@@ -0,0 +1,299 @@
+/**************************************************************************/
+/* */
+/* SMTCoq, originally belong to The Alt-ergo theorem prover */
+/* Copyright (C) 2006-2010 */
+/* */
+/* Sylvain Conchon */
+/* Evelyne Contejean */
+/* Stephane Lescuyer */
+/* Mohamed Iguernelala */
+/* Alain Mebsout */
+/* */
+/* CNRS - INRIA - Universite Paris Sud */
+/* */
+/* This file is distributed under the terms of the CeCILL-C licence */
+/* */
+/**************************************************************************/
+
+%{
+ open Smtlib2_ast
+
+ let loc () = symbol_start_pos (), symbol_end_pos ()
+
+%}
+
+%start main
+
+/* general */
+%token EXCLIMATIONPT
+%token UNDERSCORE
+%token AS
+%token EXISTS
+%token FORALL
+%token LET
+
+/* commands */
+%token SETLOGIC
+%token SETOPTION
+%token SETINFO
+%token DECLARESORT
+%token DEFINESORT
+%token DECLAREFUN
+%token DEFINEFUN
+%token PUSH
+%token POP
+%token ASSERT
+%token CHECKSAT
+%token GETASSERT
+%token GETPROOF
+%token GETUNSATCORE
+%token GETVALUE
+%token GETASSIGN
+%token GETOPTION
+%token GETINFO
+%token EXIT
+
+/* Other tokens */
+%token LPAREN
+%token RPAREN
+%token EOF
+
+%token <string> NUMERAL
+%token <string> DECIMAL
+%token <string> HEXADECIMAL
+%token <string> BINARY
+%token <string> STRINGLIT
+%token <string> ASCIIWOR
+%token <string> KEYWORD
+%token <string> SYMBOL
+
+
+%type <Smtlib2_ast.commands option> main
+%type <Smtlib2_ast.an_option> an_option
+%type <Smtlib2_ast.attribute> attribute
+%type <Smtlib2_ast.attributevalue> attributevalue
+%type <Smtlib2_ast.command> command
+%type <Smtlib2_ast.commands> commands
+%type <Smtlib2_ast.identifier> identifier
+%type <Smtlib2_ast.infoflag> infoflag
+%type <Smtlib2_ast.qualidentifier> qualidentifier
+%type <Smtlib2_ast.sexpr> sexpr
+%type <Smtlib2_ast.sort> sort
+%type <Smtlib2_ast.sortedvar> sortedvar
+%type <Smtlib2_ast.specconstant> specconstant
+%type <Smtlib2_ast.symbol> symbol
+%type <Smtlib2_ast.term> term
+%type <Smtlib2_ast.varbinding> varbinding
+
+/* %type <Smtlib2_ast.attributevalsexpr_attributevalue_sexpr5> attributevalsexpr_attributevalue_sexpr5 */
+/* %type <Smtlib2_ast.commanddeclarefun_command_sort13> commanddeclarefun_command_sort13 */
+/* %type <Smtlib2_ast.commanddefinefun_command_sortedvar15> commanddefinefun_command_sortedvar15 */
+/* %type <Smtlib2_ast.commanddefinesort_command_symbol11> commanddefinesort_command_symbol11 */
+/* %type <Smtlib2_ast.commandgetvalue_command_term24> commandgetvalue_command_term24 */
+/* %type <Smtlib2_ast.commands_commands_command30> commands_commands_command30 */
+/* %type <Smtlib2_ast.sexprinparen_sexpr_sexpr41> sexprinparen_sexpr_sexpr41 */
+/* %type <Smtlib2_ast.sortidsortmulti_sort_sort44> sortidsortmulti_sort_sort44 */
+/* %type <Smtlib2_ast.termexclimationpt_term_attribute64> termexclimationpt_term_attribute64 */
+/* %type <Smtlib2_ast.termexiststerm_term_sortedvar62> termexiststerm_term_sortedvar62 */
+/* %type <Smtlib2_ast.termforallterm_term_sortedvar60> termforallterm_term_sortedvar60 */
+/* %type <Smtlib2_ast.termletterm_term_varbinding58> termletterm_term_varbinding58 */
+/* %type <Smtlib2_ast.termqualidterm_term_term56> termqualidterm_term_term56 */
+/* %type <Smtlib2_ast.idunderscoresymnum_identifier_numeral33> idunderscoresymnum_identifier_numeral33 */
+%%
+
+main:
+| commands { Some($1) }
+| EOF { None }
+;
+
+an_option:
+| attribute { AnOptionAttribute(loc_attribute $1, $1) }
+;
+
+attribute:
+| KEYWORD { AttributeKeyword(loc (), $1) }
+| KEYWORD attributevalue { AttributeKeywordValue(loc (), $1, $2) }
+;
+
+sexpr_list:
+/*sexprinparen_sexpr_sexpr41:*/
+/*attributevalsexpr_attributevalue_sexpr5:*/
+| { (loc (), []) }
+| sexpr sexpr_list { let (_, l1) = $2 in (loc_sexpr $1, ($1)::(l1)) }
+;
+
+attributevalue:
+| specconstant { AttributeValSpecConst(loc_specconstant $1, $1) }
+| symbol { AttributeValSymbol(loc_symbol $1, $1) }
+| LPAREN sexpr_list RPAREN { AttributeValSexpr(loc (), $2) }
+;
+
+symbol_list: /*commanddefinesort_command_symbol11:*/
+| { (loc (), []) }
+| symbol symbol_list { let (_, l1) = $2 in (loc_symbol $1, ($1)::(l1)) }
+;
+
+sort_list0: /*commanddeclarefun_command_sort13:*/
+| { (loc (), []) }
+| sort sort_list0 { let (_, l1) = $2 in (loc_sort $1, ($1)::(l1)) }
+;
+
+sortedvar_list: /*commanddefinefun_command_sortedvar15:*/
+| { (loc (), []) }
+| sortedvar sortedvar_list
+ { let (_, l1) = $2 in (loc_sortedvar $1, ($1)::(l1)) }
+;
+
+command:
+| LPAREN SETLOGIC symbol RPAREN
+ { CSetLogic(loc (), $3) }
+| LPAREN SETOPTION an_option RPAREN
+ { CSetOption(loc (), $3) }
+| LPAREN SETINFO attribute RPAREN
+ { CSetInfo(loc (), $3) }
+| LPAREN DECLARESORT symbol NUMERAL RPAREN
+ { CDeclareSort(loc (), $3, $4) }
+| LPAREN DEFINESORT symbol LPAREN symbol_list RPAREN sort RPAREN
+ { CDefineSort(loc (), $3, $5, $7) }
+| LPAREN DECLAREFUN symbol LPAREN sort_list0 RPAREN sort RPAREN
+ { CDeclareFun(loc (), $3, $5, $7) }
+| LPAREN DEFINEFUN symbol LPAREN sortedvar_list RPAREN sort term RPAREN
+ { CDefineFun(loc (), $3, $5, $7, $8) }
+| LPAREN PUSH NUMERAL RPAREN
+ { CPush(loc (), $3) }
+| LPAREN POP NUMERAL RPAREN
+ { CPop(loc (), $3) }
+| LPAREN ASSERT term RPAREN
+ { CAssert(loc (), $3) }
+| LPAREN CHECKSAT RPAREN
+ { CCheckSat(loc ()) }
+| LPAREN GETASSERT RPAREN
+ { CGetAssert(loc ()) }
+| LPAREN GETPROOF RPAREN
+ { CGetProof(loc ()) }
+| LPAREN GETUNSATCORE RPAREN
+ { CGetUnsatCore(loc ()) }
+| LPAREN GETVALUE LPAREN term_list1 RPAREN RPAREN
+ { CGetValue(loc (), $4) }
+| LPAREN GETASSIGN RPAREN
+ { CGetAssign(loc ()) }
+| LPAREN GETOPTION KEYWORD RPAREN
+ { CGetOption(loc (), $3) }
+| LPAREN GETINFO infoflag RPAREN
+ { CGetInfo(loc (), $3) }
+| LPAREN EXIT RPAREN
+ { CExit(loc ()) }
+;
+
+
+command_list: /*commands_commands_command30:*/
+| { (loc (), []) }
+| command command_list { let (_, l1) = $2 in (loc_command $1, ($1)::(l1)) }
+;
+
+commands:
+| command_list { Commands(loc_couple $1, $1) }
+;
+
+numeral_list: /*idunderscoresymnum_identifier_numeral33:*/
+| NUMERAL { (loc (), ($1)::[]) }
+| NUMERAL numeral_list { let (_, l1) = $2 in (loc (), ($1)::(l1)) }
+;
+
+identifier:
+| symbol { IdSymbol(loc_symbol $1, $1) }
+| LPAREN UNDERSCORE symbol numeral_list RPAREN
+ { IdUnderscoreSymNum(loc (), $3, $4) }
+;
+
+infoflag:
+| KEYWORD { InfoFlagKeyword(loc (), $1) }
+;
+
+qualidentifier:
+| identifier { QualIdentifierId(loc_identifier $1, $1) }
+| LPAREN AS identifier sort RPAREN { QualIdentifierAs(loc (), $3, $4) }
+;
+
+sexpr:
+| specconstant { SexprSpecConst(loc_specconstant $1, $1) }
+| symbol { SexprSymbol(loc_symbol $1, $1) }
+| KEYWORD { SexprKeyword(loc (), $1) }
+| LPAREN sexpr_list RPAREN { SexprInParen(loc (), $2) }
+;
+
+
+sort_list1: /*sortidsortmulti_sort_sort44:*/
+| sort { (loc_sort $1, ($1)::[]) }
+| sort sort_list1 { let (_, l1) = $2 in (loc_sort $1, ($1)::(l1)) }
+;
+
+sort:
+| identifier { SortIdentifier(loc_identifier $1, $1) }
+| LPAREN identifier sort_list1 RPAREN { SortIdSortMulti(loc (), $2, $3) }
+;
+
+sortedvar:
+| LPAREN symbol sort RPAREN { SortedVarSymSort(loc (), $2, $3) }
+;
+
+specconstant:
+| DECIMAL { SpecConstsDec(loc (), $1) }
+| NUMERAL { SpecConstNum(loc (), $1) }
+| STRINGLIT { SpecConstString(loc (), $1) }
+| HEXADECIMAL { SpecConstsHex(loc (), $1) }
+| BINARY { SpecConstsBinary(loc (), $1) }
+;
+
+symbol:
+| SYMBOL { Symbol(loc (), $1) }
+| ASCIIWOR { SymbolWithOr(loc (), $1) }
+;
+
+term_list1:
+/*termqualidterm_term_term56:*/
+/*commandgetvalue_command_term24:*/
+| term { (loc_term $1, ($1)::[]) }
+| term term_list1 { let (_, l1) = $2 in (loc_term $1, ($1)::(l1)) }
+;
+
+varbinding_list1: /*termletterm_term_varbinding58:*/
+| varbinding { (loc_varbinding $1, ($1)::[]) }
+| varbinding varbinding_list1
+ { let (_, l1) = $2 in (loc_varbinding $1, ($1)::(l1)) }
+;
+
+sortedvar_list1:
+/*termforallterm_term_sortedvar60:*/
+/*termexiststerm_term_sortedvar62:*/
+| sortedvar { (loc_sortedvar $1, ($1)::[]) }
+| sortedvar sortedvar_list1
+ { let (_, l1) = $2 in (loc_sortedvar $1, ($1)::(l1)) }
+;
+
+attribute_list1: /*termexclimationpt_term_attribute64:*/
+| attribute { (loc_attribute $1, ($1)::[]) }
+| attribute attribute_list1
+ { let (_, l1) = $2 in (loc_attribute $1, ($1)::(l1)) }
+;
+
+term:
+| specconstant
+ { TermSpecConst(loc_specconstant $1, $1) }
+| qualidentifier
+ { TermQualIdentifier(loc_qualidentifier $1, $1) }
+| LPAREN qualidentifier term_list1 RPAREN
+ { TermQualIdTerm(loc (), $2, $3) }
+| LPAREN LET LPAREN varbinding_list1 RPAREN term RPAREN
+ { TermLetTerm(loc (), $4, $6) }
+| LPAREN FORALL LPAREN sortedvar_list1 RPAREN term RPAREN
+ { TermForAllTerm(loc (), $4, $6) }
+| LPAREN EXISTS LPAREN sortedvar_list1 RPAREN term RPAREN
+ { TermExistsTerm(loc (), $4, $6) }
+| LPAREN EXCLIMATIONPT term attribute_list1 RPAREN
+ { TermExclimationPt(loc (), $3, $4) }
+;
+
+varbinding:
+| LPAREN symbol term RPAREN { VarBindingSymTerm(loc (), $2, $3) }
+;
diff --git a/src/verit/smtlib2_util.ml b/src/verit/smtlib2_util.ml
new file mode 100644
index 0000000..1ce5e46
--- /dev/null
+++ b/src/verit/smtlib2_util.ml
@@ -0,0 +1,29 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq, originally belong to The Alt-ergo theorem prover *)
+(* Copyright (C) 2006-2010 *)
+(* *)
+(* Sylvain Conchon *)
+(* Evelyne Contejean *)
+(* Stephane Lescuyer *)
+(* Mohamed Iguernelala *)
+(* Alain Mebsout *)
+(* *)
+(* CNRS - INRIA - Universite Paris Sud *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+(* auto-generated by gt *)
+
+(* no extra data from grammar file. *)
+type extradata = unit;;
+let initial_data() = ();;
+
+let file = ref "stdin";;
+let line = ref 1;;
+type pos = int;;
+let string_of_pos p = "line "^(string_of_int p);;
+let cur_pd() = (!line, initial_data());; (* "pd": pos + extradata *)
+type pd = pos * extradata;;
diff --git a/src/verit/verit.ml b/src/verit/verit.ml
new file mode 100644
index 0000000..87e74a6
--- /dev/null
+++ b/src/verit/verit.ml
@@ -0,0 +1,542 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+
+open Entries
+open Declare
+open Decl_kinds
+
+open SmtMisc
+open CoqTerms
+open SmtForm
+open SmtCertif
+open SmtTrace
+open SmtAtom
+
+
+let debug = false
+
+
+(* Interpretation tables *)
+
+let mk_ftype cod dom =
+ let typeb = Lazy.force ctype in
+ let typea = mklApp clist [|typeb|] in
+ let a = Array.fold_right (fun bt acc -> mklApp ccons [|typeb; Btype.to_coq bt; acc|]) cod (mklApp cnil [|typeb|]) in
+ let b = Btype.to_coq dom in
+ mklApp cpair [|typea;typeb;a;b|]
+
+let make_t_i rt = Btype.interp_tbl rt
+let make_t_func ro t_i = Op.interp_tbl (mklApp ctval [|t_i|]) (fun cod dom value -> mklApp cTval [|t_i; mk_ftype cod dom; value|]) ro
+
+
+(******************************************************************************)
+(** Given a SMT-LIB2 file and a verit trace build *)
+(* the corresponding object *)
+(******************************************************************************)
+
+
+let import_smtlib2 rt ro ra rf filename =
+ let chan = open_in filename in
+ let lexbuf = Lexing.from_channel chan in
+ let commands = Smtlib2_parse.main Smtlib2_lex.token lexbuf in
+ close_in chan;
+ match commands with
+ | None -> []
+ | Some (Smtlib2_ast.Commands (_,(_,res))) ->
+ List.rev (List.fold_left (Smtlib2_genConstr.declare_commands rt ro ra rf) [] res)
+
+
+let import_trace filename first =
+ let chan = open_in filename in
+ let lexbuf = Lexing.from_channel chan in
+ let confl_num = ref (-1) in
+ let first_num = ref (-1) in
+ let is_first = ref true in
+ let line = ref 1 in
+ (* let _ = Parsing.set_trace true in *)
+ try
+ while true do
+ confl_num := VeritParser.line VeritLexer.token lexbuf;
+ if !is_first then (
+ is_first := false;
+ first_num := !confl_num
+ );
+ incr line
+ done;
+ raise VeritLexer.Eof
+ with
+ | VeritLexer.Eof ->
+ close_in chan;
+ let first =
+ let aux = VeritSyntax.get_clause !first_num in
+ match first, aux.value with
+ | Some (root,l), Some (fl::nil) ->
+ if Form.equal l fl then
+ aux
+ else (
+ aux.kind <- Other (ImmFlatten(root,fl));
+ SmtTrace.link root aux;
+ root
+ )
+ | _,_ -> aux in
+ let confl = VeritSyntax.get_clause !confl_num in
+ SmtTrace.select confl;
+ (* Trace.share_prefix first (2 * last.id); *)
+ occur confl;
+ (alloc first, confl)
+ | Parsing.Parse_error -> failwith ("Verit.import_trace: parsing error line "^(string_of_int !line))
+
+
+let euf_checker_modules = [ ["SMTCoq";"Trace";"Euf_Checker"] ]
+
+let certif_ops = CoqTerms.make_certif_ops euf_checker_modules
+let cCertif = gen_constant euf_checker_modules "Certif"
+
+
+let clear_all () =
+ SmtTrace.clear ();
+ VeritSyntax.clear ()
+
+
+let compute_roots roots last_root =
+ let r = ref last_root in
+ while (has_prev !r) do
+ r := prev !r
+ done;
+
+ let rec find_root i root = function
+ | [] -> assert false
+ | t::q -> if Form.equal t root then (i,q) else find_root (i+1) root q in
+
+ let rec used_roots acc i roots r =
+ if isRoot r.kind then
+ match r.value with
+ | Some [root] ->
+ let (j,roots') = find_root i root roots in
+ used_roots (j::acc) (j+1) roots' (next r)
+ | _ -> assert false
+ else
+ acc in
+
+ used_roots [] 0 roots !r
+
+
+let parse_certif t_i t_func t_atom t_form root used_root trace fsmt fproof =
+ clear_all ();
+ let rt = Btype.create () in
+ let ro = Op.create () in
+ let ra = VeritSyntax.ra in
+ let rf = VeritSyntax.rf in
+ let roots = import_smtlib2 rt ro ra rf fsmt in
+ let (max_id, confl) = import_trace fproof None in
+ let (tres, last_root) = SmtTrace.to_coq (fun i -> mkInt (Form.to_lit i)) certif_ops confl in
+ let certif =
+ mklApp cCertif [|mkInt (max_id + 1); tres;mkInt (get_pos confl)|] in
+ let ce4 =
+ { const_entry_body = certif;
+ const_entry_type = None;
+ const_entry_secctx = None;
+ const_entry_opaque = false;
+ const_entry_inline_code = false} in
+ let _ = declare_constant trace (DefinitionEntry ce4, IsDefinition Definition) in
+ let used_roots = compute_roots roots last_root in
+ let roots =
+ let res = Array.make (List.length roots + 1) (mkInt 0) in
+ let i = ref 0 in
+ List.iter (fun j -> res.(!i) <- mkInt (Form.to_lit j); incr i) roots;
+ Term.mkArray (Lazy.force cint, res) in
+ let used_roots =
+ let l = List.length used_roots in
+ let res = Array.make (l + 1) (mkInt 0) in
+ let i = ref (l-1) in
+ List.iter (fun j -> res.(!i) <- mkInt j; decr i) used_roots;
+ mklApp cSome [|mklApp carray [|Lazy.force cint|]; Term.mkArray (Lazy.force cint, res)|] in
+ let ce3 =
+ { const_entry_body = roots;
+ const_entry_type = None;
+ const_entry_secctx = None;
+ const_entry_opaque = false;
+ const_entry_inline_code = false} in
+ let _ = declare_constant root (DefinitionEntry ce3, IsDefinition Definition) in
+ let ce3' =
+ { const_entry_body = used_roots;
+ const_entry_type = None;
+ const_entry_secctx = None;
+ const_entry_opaque = false;
+ const_entry_inline_code = false} in
+ let _ = declare_constant used_root (DefinitionEntry ce3', IsDefinition Definition) in
+ let t_i' = make_t_i rt in
+ let t_func' = make_t_func ro t_i' in
+ let ce5 =
+ { const_entry_body = t_i';
+ const_entry_type = None;
+ const_entry_secctx = None;
+ const_entry_opaque = false;
+ const_entry_inline_code = false} in
+ let _ = declare_constant t_i (DefinitionEntry ce5, IsDefinition Definition) in
+ let ce6 =
+ { const_entry_body = t_func';
+ const_entry_type = None;
+ const_entry_secctx = None;
+ const_entry_opaque = false;
+ const_entry_inline_code = false} in
+ let _ = declare_constant t_func (DefinitionEntry ce6, IsDefinition Definition) in
+ let ce1 =
+ { const_entry_body = Atom.interp_tbl ra;
+ const_entry_type = None;
+ const_entry_secctx = None;
+ const_entry_opaque = false;
+ const_entry_inline_code = false} in
+ let _ = declare_constant t_atom (DefinitionEntry ce1, IsDefinition Definition) in
+ let ce2 =
+ { const_entry_body = snd (Form.interp_tbl rf);
+ const_entry_type = None;
+ const_entry_secctx = None;
+ const_entry_opaque = false;
+ const_entry_inline_code = false} in
+ let _ = declare_constant t_form (DefinitionEntry ce2, IsDefinition Definition) in
+ ()
+
+
+let ccertif = gen_constant euf_checker_modules "certif"
+let cchecker = gen_constant euf_checker_modules "checker"
+let cchecker_correct = gen_constant euf_checker_modules "checker_correct"
+
+let interp_roots roots =
+ let interp = Form.interp_to_coq (Atom.interp_to_coq (Hashtbl.create 17)) (Hashtbl.create 17) in
+ match roots with
+ | [] -> Lazy.force ctrue
+ | f::roots -> List.fold_left (fun acc f -> mklApp candb [|acc; interp f|]) (interp f) roots
+
+let theorem name fsmt fproof =
+ clear_all ();
+ let rt = Btype.create () in
+ let ro = Op.create () in
+ let ra = VeritSyntax.ra in
+ let rf = VeritSyntax.rf in
+ let roots = import_smtlib2 rt ro ra rf fsmt in
+ let (max_id, confl) = import_trace fproof None in
+ let (tres,last_root) = SmtTrace.to_coq (fun i -> mkInt (Form.to_lit i)) certif_ops confl in
+ let certif =
+ mklApp cCertif [|mkInt (max_id + 1); tres;mkInt (get_pos confl)|] in
+ let used_roots = compute_roots roots last_root in
+ let used_rootsCstr =
+ let l = List.length used_roots in
+ let res = Array.make (l + 1) (mkInt 0) in
+ let i = ref (l-1) in
+ List.iter (fun j -> res.(!i) <- mkInt j; decr i) used_roots;
+ mklApp cSome [|mklApp carray [|Lazy.force cint|]; Term.mkArray (Lazy.force cint, res)|] in
+ let rootsCstr =
+ let res = Array.make (List.length roots + 1) (mkInt 0) in
+ let i = ref 0 in
+ List.iter (fun j -> res.(!i) <- mkInt (Form.to_lit j); incr i) roots;
+ Term.mkArray (Lazy.force cint, res) in
+
+ let t_atom = Atom.interp_tbl ra in
+ let t_form = snd (Form.interp_tbl rf) in
+ let t_i = make_t_i rt in
+ let t_func = make_t_func ro t_i in
+
+ let theorem_concl = mklApp cnot [|mklApp cis_true [|interp_roots roots|]|] in
+ let theorem_proof =
+ Term.mkLetIn (mkName "used_roots", used_rootsCstr, mklApp coption [|mklApp carray [|Lazy.force cint|]|], (*7*)
+ Term.mkLetIn (mkName "t_atom", t_atom, mklApp carray [|Lazy.force catom|], (*6*)
+ Term.mkLetIn (mkName "t_form", t_form, mklApp carray [|Lazy.force cform|], (*5*)
+ Term.mkLetIn (mkName "d", rootsCstr, mklApp carray [|Lazy.force cint|], (*4*)
+ Term.mkLetIn (mkName "c", certif, Lazy.force ccertif, (*3*)
+ Term.mkLetIn (mkName "t_i", t_i, mklApp carray [|Lazy.force ctyp_eqb|], (*2*)
+ Term.mkLetIn (mkName "t_func", t_func, mklApp carray [|mklApp ctval [|t_i|]|], (*1*)
+ mklApp cchecker_correct
+ [|Term.mkRel 2; Term.mkRel 1; Term.mkRel 6; Term.mkRel 5; Term.mkRel 4; Term.mkRel 7; Term.mkRel 3;
+ vm_cast_true
+ (mklApp cchecker [|Term.mkRel 2; Term.mkRel 1; Term.mkRel 6; Term.mkRel 5; Term.mkRel 4; Term.mkRel 7; Term.mkRel 3|])|]))))))) in
+ let ce =
+ { const_entry_body = theorem_proof;
+ const_entry_type = Some theorem_concl;
+ const_entry_secctx = None;
+ const_entry_opaque = true;
+ const_entry_inline_code = false} in
+ let _ = declare_constant name (DefinitionEntry ce, IsDefinition Definition) in
+ ()
+
+
+let checker fsmt fproof =
+ let t1 = Unix.time () in (* for debug *)
+ clear_all ();
+ let t2 = Unix.time () in (* for debug *)
+ let rt = Btype.create () in
+ let ro = Op.create () in
+ let ra = VeritSyntax.ra in
+ let rf = VeritSyntax.rf in
+ let t3 = Unix.time () in (* for debug *)
+ let roots = import_smtlib2 rt ro ra rf fsmt in
+ let t4 = Unix.time () in (* for debug *)
+ let (max_id, confl) = import_trace fproof None in
+ let t5 = Unix.time () in (* for debug *)
+ let (tres,last_root) = SmtTrace.to_coq (fun i -> mkInt (Form.to_lit i)) certif_ops confl in
+ let t6 = Unix.time () in (* for debug *)
+ let certif =
+ mklApp cCertif [|mkInt (max_id + 1); tres;mkInt (get_pos confl)|] in
+ let t7 = Unix.time () in (* for debug *)
+ let used_roots = compute_roots roots last_root in
+ let t8 = Unix.time () in (* for debug *)
+ let used_rootsCstr =
+ let l = List.length used_roots in
+ let res = Array.make (l + 1) (mkInt 0) in
+ let i = ref (l-1) in
+ List.iter (fun j -> res.(!i) <- mkInt j; decr i) used_roots;
+ mklApp cSome [|mklApp carray [|Lazy.force cint|]; Term.mkArray (Lazy.force cint, res)|] in
+ let t9 = Unix.time () in (* for debug *)
+ let rootsCstr =
+ let res = Array.make (List.length roots + 1) (mkInt 0) in
+ let i = ref 0 in
+ List.iter (fun j -> res.(!i) <- mkInt (Form.to_lit j); incr i) roots;
+ Term.mkArray (Lazy.force cint, res) in
+ let t10 = Unix.time () in (* for debug *)
+
+ let t_i = make_t_i rt in
+ let t11 = Unix.time () in (* for debug *)
+ let t_func = make_t_func ro t_i in
+ let t12 = Unix.time () in (* for debug *)
+ let t_atom = Atom.interp_tbl ra in
+ let t13 = Unix.time () in (* for debug *)
+ let t_form = snd (Form.interp_tbl rf) in
+ let t14 = Unix.time () in (* for debug *)
+
+ let tm = mklApp cchecker [|t_i; t_func; t_atom; t_form; rootsCstr; used_rootsCstr; certif|] in
+ let t15 = Unix.time () in (* for debug *)
+
+ let res = Vnorm.cbv_vm (Global.env ()) tm (Lazy.force CoqTerms.cbool) in
+ let t16 = Unix.time () in (* for debug *)
+ Format.eprintf " = %s\n : bool@."
+ (if Term.eq_constr res (Lazy.force CoqTerms.ctrue) then
+ "true" else "false");
+ let t17 = Unix.time () in (* for debug *)
+
+ (* let expr = Constrextern.extern_constr true Environ.empty_env tm in *)
+ (* let t16 = Unix.time () in (\* for debug *\) *)
+ (* let res_aux1 = Glob_term.CbvVm None in *)
+ (* let t17 = Unix.time () in (\* for debug *\) *)
+ (* let res_aux2 = Vernacexpr.VernacCheckMayEval(Some res_aux1, None, expr) in *)
+ (* let t18 = Unix.time () in (\* for debug *\) *)
+ (* Vernacentries.interp res_aux2; *)
+ (* let t19 = Unix.time () in (\* for debug *\) *)
+
+ if debug then (
+ Printf.printf"Clear: %f
+Create hashtables: %f
+Import SMT-LIB: %f
+Import trace: %f
+Compute trace: %f
+Build certif: %f
+Build roots: %f
+Compute used roots: %f
+Build used roots: %f
+Build t_i: %f
+Build t_func: %f
+Build t_atom: %f
+Build t_form: %f
+Build checker call: %f
+Compute checker call: %f
+Print result: %f\n" (t2-.t1) (t3-.t2) (t4-.t3) (t5-.t4) (t6-.t5) (t7-.t6) (t8-.t7) (t9-.t8) (t10-.t9) (t11-.t10) (t12-.t11) (t13-.t12) (t14-.t13) (t15-.t14) (t16-.t15) (t17-.t16);
+(* Printf.printf"Clear: %f *)
+(* Create hashtables: %f *)
+(* Import SMT-LIB: %f *)
+(* Import trace: %f *)
+(* Compute trace: %f *)
+(* Build certif: %f *)
+(* Build roots: %f *)
+(* Compute used roots: %f *)
+(* Build used roots: %f *)
+(* Build t_i: %f *)
+(* Build t_func: %f *)
+(* Build t_atom: %f *)
+(* Build t_form: %f *)
+(* Build checker call: %f *)
+(* Build constr: %f *)
+(* Build conclusion1: %f *)
+(* Build conclusion2: %f *)
+(* Build conclusion: %f\n" (t2-.t1) (t3-.t2) (t4-.t3) (t5-.t4) (t6-.t5) (t7-.t6) (t8-.t7) (t9-.t8) (t10-.t9) (t11-.t10) (t12-.t11) (t13-.t12) (t14-.t13) (t15-.t14) (t16-.t15) (t17-.t16) (t18-.t17) (t19-.t18); *)
+ flush stdout)
+
+
+(******************************************************************************)
+(** Given a Coq formula build the proof *)
+(******************************************************************************)
+
+let export out_channel rt ro l =
+ let fmt = Format.formatter_of_out_channel out_channel in
+ Format.fprintf fmt "(set-logic QF_UFLIA)@.";
+
+ List.iter (fun (i,t) ->
+ let s = "Tindex_"^(string_of_int i) in
+ VeritSyntax.add_btype s (Tindex t);
+ Format.fprintf fmt "(declare-sort %s 0)@." s
+ ) (Btype.to_list rt);
+
+ List.iter (fun (i,cod,dom,op) ->
+ let s = "op_"^(string_of_int i) in
+ VeritSyntax.add_fun s op;
+ Format.fprintf fmt "(declare-fun %s (" s;
+ let is_first = ref true in
+ Array.iter (fun t -> if !is_first then is_first := false else Format.fprintf fmt " "; Btype.to_smt fmt t) cod;
+ Format.fprintf fmt ") ";
+ Btype.to_smt fmt dom;
+ Format.fprintf fmt ")@."
+ ) (Op.to_list ro);
+
+ Format.fprintf fmt "(assert ";
+ Form.to_smt Atom.to_smt fmt l;
+ Format.fprintf fmt ")@\n(check-sat)@\n(exit)@."
+
+
+let call_verit rt ro fl root =
+ let (filename, outchan) = Filename.open_temp_file "verit_coq" ".smt2" in
+ export outchan rt ro fl;
+ close_out outchan;
+ let logfilename = (Filename.chop_extension filename)^".vtlog" in
+
+ let command = "veriT --proof-prune --proof-merge --proof-with-sharing --cnf-definitional --disable-ackermann --input=smtlib2 --proof="^logfilename^" "^filename in
+ Format.eprintf "%s@." command;
+ let t0 = Sys.time () in
+ let exit_code = Sys.command command in
+ let t1 = Sys.time () in
+ Format.eprintf "Verit = %.5f@." (t1-.t0);
+ if exit_code <> 0 then
+ failwith ("Verit.call_verit: command "^command^
+ " exited with code "^(string_of_int exit_code));
+ try
+ import_trace logfilename (Some root)
+ with
+ | VeritSyntax.Sat -> Errors.error "veriT can't prove this"
+
+
+let cchecker_b_correct =
+ gen_constant euf_checker_modules "checker_b_correct"
+let cchecker_b = gen_constant euf_checker_modules "checker_b"
+let cchecker_eq_correct =
+ gen_constant euf_checker_modules "checker_eq_correct"
+let cchecker_eq = gen_constant euf_checker_modules "checker_eq"
+
+
+let build_body rt ro ra rf l b (max_id, confl) =
+ let (tres,_) = SmtTrace.to_coq Form.to_coq certif_ops confl in
+ let certif =
+ mklApp cCertif [|mkInt (max_id + 1); tres;mkInt (get_pos confl)|] in
+
+ let t_atom = Atom.interp_tbl ra in
+ let t_form = snd (Form.interp_tbl rf) in
+ let t_i = make_t_i rt in
+ let t_func = make_t_func ro t_i in
+
+ let ntatom = mkName "t_atom" in
+ let ntform = mkName "t_form" in
+ let nc = mkName "c" in
+ let nti = mkName "t_i" in
+ let ntfunc = mkName "t_func" in
+
+ let vtatom = Term.mkRel 5 in
+ let vtform = Term.mkRel 4 in
+ let vc = Term.mkRel 3 in
+ let vti = Term.mkRel 2 in
+ let vtfunc = Term.mkRel 1 in
+
+ Term.mkLetIn (ntatom, t_atom, mklApp carray [|Lazy.force catom|],
+ Term.mkLetIn (ntform, t_form, mklApp carray [|Lazy.force cform|],
+ Term.mkLetIn (nc, certif, Lazy.force ccertif,
+ Term.mkLetIn (nti, Term.lift 3 t_i, mklApp carray [|Lazy.force ctyp_eqb|],
+ Term.mkLetIn (ntfunc, Term.lift 4 t_func, mklApp carray [|mklApp ctval [|t_i|]|],
+ mklApp cchecker_b_correct
+ [|vti;vtfunc;vtatom; vtform; l; b; vc;
+ vm_cast_true (mklApp cchecker_b [|vti;vtfunc;vtatom;vtform;l;b;vc|])|])))))
+
+
+let build_body_eq rt ro ra rf l1 l2 l (max_id, confl) =
+ let (tres,_) = SmtTrace.to_coq Form.to_coq certif_ops confl in
+ let certif =
+ mklApp cCertif [|mkInt (max_id + 1); tres;mkInt (get_pos confl)|] in
+
+ let t_atom = Atom.interp_tbl ra in
+ let t_form = snd (Form.interp_tbl rf) in
+ let t_i = make_t_i rt in
+ let t_func = make_t_func ro t_i in
+
+ let ntatom = mkName "t_atom" in
+ let ntform = mkName "t_form" in
+ let nc = mkName "c" in
+ let nti = mkName "t_i" in
+ let ntfunc = mkName "t_func" in
+
+ let vtatom = Term.mkRel 5 in
+ let vtform = Term.mkRel 4 in
+ let vc = Term.mkRel 3 in
+ let vti = Term.mkRel 2 in
+ let vtfunc = Term.mkRel 1 in
+
+ Term.mkLetIn (ntatom, t_atom, mklApp carray [|Lazy.force catom|],
+ Term.mkLetIn (ntform, t_form, mklApp carray [|Lazy.force cform|],
+ Term.mkLetIn (nc, certif, Lazy.force ccertif,
+ Term.mkLetIn (nti, Term.lift 3 t_i, mklApp carray [|Lazy.force ctyp_eqb|],
+ Term.mkLetIn (ntfunc, Term.lift 4 t_func, mklApp carray [|mklApp ctval [|t_i|]|],
+ mklApp cchecker_eq_correct
+ [|vti;vtfunc;vtatom; vtform; l1; l2; l; vc;
+ vm_cast_true (mklApp cchecker_eq [|vti;vtfunc;vtatom;vtform;l1;l2;l;vc|])|])))))
+
+
+let get_arguments concl =
+ let f, args = Term.decompose_app concl in
+ match args with
+ | [ty;a;b] when f = Lazy.force ceq && ty = Lazy.force cbool -> a, b
+ | [a] when f = Lazy.force cis_true -> a, Lazy.force ctrue
+ | _ -> failwith ("Verit.tactic: can only deal with equality over bool")
+
+
+let make_proof rt ro rf l =
+ let fl = Form.flatten rf l in
+ let root = SmtTrace.mkRootV [l] in
+ call_verit rt ro fl (root,l)
+
+
+let tactic gl =
+ clear_all ();
+ let rt = Btype.create () in
+ let ro = Op.create () in
+ let ra = VeritSyntax.ra in
+ let rf = VeritSyntax.rf in
+
+ let env = Tacmach.pf_env gl in
+ let sigma = Tacmach.project gl in
+ let t = Tacmach.pf_concl gl in
+
+ let (forall_let, concl) = Term.decompose_prod_assum t in
+ let env = Environ.push_rel_context forall_let env in
+ let a, b = get_arguments concl in
+ let body =
+ if (b = Lazy.force ctrue || b = Lazy.force cfalse) then
+ let l = Form.of_coq (Atom.of_coq rt ro ra env sigma) rf a in
+ let l' = if b = Lazy.force ctrue then Form.neg l else l in
+ let max_id_confl = make_proof rt ro rf l' in
+ build_body rt ro ra rf (Form.to_coq l) b max_id_confl
+ else
+ let l1 = Form.of_coq (Atom.of_coq rt ro ra env sigma) rf a in
+ let l2 = Form.of_coq (Atom.of_coq rt ro ra env sigma) rf b in
+ let l = Form.neg (Form.get rf (Fapp(Fiff,[|l1;l2|]))) in
+ let max_id_confl = make_proof rt ro rf l in
+ build_body_eq rt ro ra rf (Form.to_coq l1) (Form.to_coq l2) (Form.to_coq l) max_id_confl in
+ let compose_lam_assum forall_let body =
+ List.fold_left (fun t rd -> Term.mkLambda_or_LetIn rd t) body forall_let in
+ let res = compose_lam_assum forall_let body in
+ Tactics.exact_no_check res gl
diff --git a/src/verit/veritLexer.mll b/src/verit/veritLexer.mll
new file mode 100644
index 0000000..3314fae
--- /dev/null
+++ b/src/verit/veritLexer.mll
@@ -0,0 +1,148 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+{
+ open VeritParser
+ exception Eof
+
+ let typ_table = Hashtbl.create 53
+ let _ =
+ List.iter (fun (kwd, tok) -> Hashtbl.add typ_table kwd tok)
+ [ "input", INPU;
+ "deep_res", DEEP;
+ "true", TRUE;
+ "false", FALS;
+ "and_pos", ANDP;
+ "and_neg", ANDN;
+ "or_pos", ORP;
+ "or_neg", ORN;
+ "xor_pos1", XORP1;
+ "xor_pos2", XORP2;
+ "xor_neg1", XORN1;
+ "xor_neg2", XORN2;
+ "implies_pos", IMPP;
+ "implies_neg1", IMPN1;
+ "implies_neg2", IMPN2;
+ "equiv_pos1", EQUP1;
+ "equiv_pos2", EQUP2;
+ "equiv_neg1", EQUN1;
+ "equiv_neg2", EQUN2;
+ "ite_pos1", ITEP1;
+ "ite_pos2", ITEP2;
+ "ite_neg1", ITEN1;
+ "ite_neg2", ITEN2;
+ "eq_reflexive", EQRE;
+ "eq_transitive", EQTR;
+ "eq_congruent", EQCO;
+ "eq_congruent_pred", EQCP;
+ "dl_generic", DLGE;
+ "lia_generic", LAGE;
+ "la_generic", LAGE;
+ "la_tautology", LATA;
+ "dl_disequality", DLDE;
+ "la_disequality", LADE;
+ "forall_inst", FINS;
+ "exists_inst", EINS;
+ "skolem_ex_ax", SKEA;
+ "skolem_all_ax", SKAA;
+ "qnt_simplify_ax", QNTS;
+ "qnt_merge_ax", QNTM;
+ "resolution", RESO;
+ "and", AND;
+ "not_or", NOR;
+ "or", OR;
+ "not_and", NAND;
+ "xor1", XOR1;
+ "xor2", XOR2;
+ "not_xor1", NXOR1;
+ "not_xor2", NXOR2;
+ "implies", IMP;
+ "not_implies1", NIMP1;
+ "not_implies2", NIMP2;
+ "equiv1", EQU1;
+ "equiv2", EQU2;
+ "not_equiv1", NEQU1;
+ "not_equiv2", NEQU2;
+ "ite1", ITE1;
+ "ite2", ITE2;
+ "not_ite1", NITE1;
+ "not_ite2", NITE2;
+ "tmp_alphaconv", TPAL;
+ "tmp_LA_pre", TLAP;
+ "tmp_let_elim", TPLE;
+ "tmp_nary_elim", TPNE;
+ "tmp_distinct_elim", TPDE;
+ "tmp_simp_arith", TPSA;
+ "tmp_ite_elim", TPIE;
+ "tmp_macrosubst", TPMA;
+ "tmp_betared", TPBR;
+ "tmp_bfun_elim", TPBE;
+ "tmp_sk_connector", TPSC;
+ "tmp_pm_process", TPPP;
+ "tmp_qnt_tidy", TPQT;
+ "tmp_qnt_simplify", TPQS;
+ "tmp_skolemize", TPSK;
+ "subproof", SUBP ]
+}
+
+
+let digit = [ '0'-'9' ]
+let alpha = [ 'a'-'z' 'A' - 'Z' ]
+let blank = [' ' '\t']
+let newline = ['\n' '\r']
+let var = alpha (alpha|digit|'_')*
+let bindvar = '?' var+
+let int = '-'? digit+
+
+
+rule token = parse
+ | blank + { token lexbuf }
+ | newline + { EOL }
+
+ | ":" { COLON }
+ | "#" { SHARP }
+
+ | "(" { LPAR }
+ | ")" { RPAR }
+
+ | "not" { NOT }
+ | "xor" { XOR }
+ | "ite" { ITE }
+ | "=" { EQ }
+ | "<" { LT }
+ | "<=" { LEQ }
+ | ">" { GT }
+ | ">=" { GEQ }
+ | "+" { PLUS }
+ | "-" { MINUS }
+ | "~" { OPP }
+ | "*" { MULT }
+ | "=>" { IMP }
+ | "let" { LET }
+ | "distinct" { DIST }
+
+ | "Formula is Satisfiable" { SAT }
+
+ | int { try INT (int_of_string (Lexing.lexeme lexbuf))
+ with _ ->
+ BIGINT
+ (Big_int.big_int_of_string
+ (Lexing.lexeme lexbuf)) }
+ | var { let v = Lexing.lexeme lexbuf in
+ try Hashtbl.find typ_table v with
+ | Not_found -> VAR v }
+ | bindvar { BINDVAR (Lexing.lexeme lexbuf) }
+
+ | eof { raise Eof }
diff --git a/src/verit/veritParser.mly b/src/verit/veritParser.mly
new file mode 100644
index 0000000..f36b857
--- /dev/null
+++ b/src/verit/veritParser.mly
@@ -0,0 +1,204 @@
+/**************************************************************************/
+/* */
+/* SMTCoq */
+/* Copyright (C) 2011 - 2015 */
+/* */
+/* Michaël Armand */
+/* Benjamin Grégoire */
+/* Chantal Keller */
+/* */
+/* Inria - École Polytechnique - MSR-Inria Joint Lab */
+/* */
+/* This file is distributed under the terms of the CeCILL-C licence */
+/* */
+/**************************************************************************/
+
+%{
+ open SmtAtom
+ open SmtForm
+ open VeritSyntax
+%}
+
+
+/*
+ définition des lexèmes
+*/
+
+%token EOL SAT
+%token COLON SHARP
+%token LPAR RPAR
+%token NOT XOR ITE EQ LT LEQ GT GEQ PLUS MINUS MULT OPP LET DIST
+%token INPU DEEP TRUE FALS ANDP ANDN ORP ORN XORP1 XORP2 XORN1 XORN2 IMPP IMPN1 IMPN2 EQUP1 EQUP2 EQUN1 EQUN2 ITEP1 ITEP2 ITEN1 ITEN2 EQRE EQTR EQCO EQCP DLGE LAGE LATA DLDE LADE FINS EINS SKEA SKAA QNTS QNTM RESO AND NOR OR NAND XOR1 XOR2 NXOR1 NXOR2 IMP NIMP1 NIMP2 EQU1 EQU2 NEQU1 NEQU2 ITE1 ITE2 NITE1 NITE2 TPAL TLAP TPLE TPNE TPDE TPSA TPIE TPMA TPBR TPBE TPSC TPPP TPQT TPQS TPSK SUBP
+%token <int> INT
+%token <Big_int.big_int> BIGINT
+%token <string> VAR BINDVAR
+
+/* type de "retour" du parseur : une clause */
+%type <int> line
+%start line
+
+
+%%
+
+line:
+ | SAT { raise Sat }
+ | INT COLON LPAR typ clause RPAR EOL { mk_clause ($1,$4,$5,[]) }
+ | INT COLON LPAR typ clause clause_ids_params RPAR EOL { mk_clause ($1,$4,$5,$6) }
+;
+
+typ:
+ | INPU { Inpu }
+ | DEEP { Deep }
+ | TRUE { True }
+ | FALS { Fals }
+ | ANDP { Andp }
+ | ANDN { Andn }
+ | ORP { Orp }
+ | ORN { Orn }
+ | XORP1 { Xorp1 }
+ | XORP2 { Xorp2 }
+ | XORN1 { Xorn1 }
+ | XORN2 { Xorn2 }
+ | IMPP { Impp }
+ | IMPN1 { Impn1 }
+ | IMPN2 { Impn2 }
+ | EQUP1 { Equp1 }
+ | EQUP2 { Equp2 }
+ | EQUN1 { Equn1 }
+ | EQUN2 { Equn2 }
+ | ITEP1 { Itep1 }
+ | ITEP2 { Itep2 }
+ | ITEN1 { Iten1 }
+ | ITEN2 { Iten2 }
+ | EQRE { Eqre }
+ | EQTR { Eqtr }
+ | EQCO { Eqco }
+ | EQCP { Eqcp }
+ | DLGE { Dlge }
+ | LAGE { Lage }
+ | LATA { Lata }
+ | DLDE { Dlde }
+ | LADE { Lade }
+ | FINS { Fins }
+ | EINS { Eins }
+ | SKEA { Skea }
+ | SKAA { Skaa }
+ | QNTS { Qnts }
+ | QNTM { Qntm }
+ | RESO { Reso }
+ | AND { And }
+ | NOR { Nor }
+ | OR { Or }
+ | NAND { Nand }
+ | XOR1 { Xor1 }
+ | XOR2 { Xor2 }
+ | NXOR1 { Nxor1 }
+ | NXOR2 { Nxor2 }
+ | IMP { Imp }
+ | NIMP1 { Nimp1 }
+ | NIMP2 { Nimp2 }
+ | EQU1 { Equ1 }
+ | EQU2 { Equ2 }
+ | NEQU1 { Nequ1 }
+ | NEQU2 { Nequ2 }
+ | ITE1 { Ite1 }
+ | ITE2 { Ite2 }
+ | NITE1 { Nite1 }
+ | NITE2 { Nite2 }
+ | TPAL { Tpal }
+ | TLAP { Tlap }
+ | TPLE { Tple }
+ | TPNE { Tpne }
+ | TPDE { Tpde }
+ | TPSA { Tpsa }
+ | TPIE { Tpie }
+ | TPMA { Tpma }
+ | TPBR { Tpbr }
+ | TPBE { Tpbe }
+ | TPSC { Tpsc }
+ | TPPP { Tppp }
+ | TPQT { Tpqt }
+ | TPQS { Tpqs }
+ | TPSK { Tpsk }
+ | SUBP { Subp }
+;
+
+clause:
+ | LPAR RPAR { [] }
+ | LPAR lit_list RPAR { $2 }
+;
+
+lit_list:
+ | lit { [$1] }
+ | lit lit_list { $1::$2 }
+;
+
+lit: /* returns a SmtAtom.Form.t */
+ | name_term { lit_of_atom_form_lit rf $1 }
+ | LPAR NOT lit RPAR { Form.neg $3 }
+;
+
+name_term: /* returns a SmtAtom.Form.pform or a SmtAtom.hatom */
+ | SHARP INT { get_solver $2 }
+ | SHARP INT COLON LPAR term RPAR { let res = $5 in add_solver $2 res; res }
+ | TRUE { Form Form.pform_true }
+ | FALS { Form Form.pform_false }
+ | VAR { Atom (Atom.get ra (Aapp (get_fun $1,[||]))) }
+ | BINDVAR { Hashtbl.find hlets $1 }
+ | INT { Atom (Atom.hatom_Z_of_int ra $1) }
+ | BIGINT { Atom (Atom.hatom_Z_of_bigint ra $1) }
+;
+
+term: /* returns a SmtAtom.Form.pform or a SmtAtom.hatom */
+ | LPAR term RPAR { $2 }
+
+ /* Formulae */
+ | TRUE { Form Form.pform_true }
+ | FALS { Form Form.pform_false }
+ | AND lit_list { Form (Fapp (Fand, Array.of_list $2)) }
+ | OR lit_list { Form (Fapp (For, Array.of_list $2)) }
+ | IMP lit_list { Form (Fapp (Fimp, Array.of_list $2)) }
+ | XOR lit_list { Form (Fapp (Fxor, Array.of_list $2)) }
+ | ITE lit_list { Form (Fapp (Fite, Array.of_list $2)) }
+
+ /* Atoms */
+ | INT { Atom (Atom.hatom_Z_of_int ra $1) }
+ | BIGINT { Atom (Atom.hatom_Z_of_bigint ra $1) }
+ | LT name_term name_term { match $2,$3 with |Atom h1, Atom h2 -> Atom (Atom.mk_lt ra h1 h2) | _,_ -> assert false }
+ | LEQ name_term name_term { match $2,$3 with |Atom h1, Atom h2 -> Atom (Atom.mk_le ra h1 h2) | _,_ -> assert false }
+ | GT name_term name_term { match $2,$3 with |Atom h1, Atom h2 -> Atom (Atom.mk_gt ra h1 h2) | _,_ -> assert false }
+ | GEQ name_term name_term { match $2,$3 with |Atom h1, Atom h2 -> Atom (Atom.mk_ge ra h1 h2) | _,_ -> assert false }
+ | PLUS name_term name_term { match $2,$3 with |Atom h1, Atom h2 -> Atom (Atom.mk_plus ra h1 h2) | _,_ -> assert false }
+ | MULT name_term name_term { match $2,$3 with |Atom h1, Atom h2 -> Atom (Atom.mk_mult ra h1 h2) | _,_ -> assert false }
+ | MINUS name_term name_term { match $2,$3 with |Atom h1, Atom h2 -> Atom (Atom.mk_minus ra h1 h2) | _,_ -> assert false }
+ | MINUS name_term { match $2 with | Atom h -> Atom (Atom.mk_opp ra h) | _ -> assert false }
+ | OPP name_term { match $2 with | Atom h -> Atom (Atom.mk_opp ra h) | _ -> assert false }
+ | DIST args { let a = Array.of_list $2 in Atom (Atom.mk_distinct ra (Atom.type_of a.(0)) a) }
+ | VAR { Atom (Atom.get ra (Aapp (get_fun $1, [||]))) }
+ | VAR args { Atom (Atom.get ra (Aapp (get_fun $1, Array.of_list $2))) }
+
+ /* Both */
+ | EQ name_term name_term { let t1 = $2 in let t2 = $3 in match t1,t2 with | Atom h1, Atom h2 when (match Atom.type_of h1 with | Tbool -> false | _ -> true) -> Atom (Atom.mk_eq ra (Atom.type_of h1) h1 h2) | _, _ -> Form (Fapp (Fiff, [|lit_of_atom_form_lit rf t1; lit_of_atom_form_lit rf t2|])) }
+ | LET LPAR bindlist RPAR name_term { $3; $5 }
+ | BINDVAR { Hashtbl.find hlets $1 }
+;
+
+bindlist:
+ | LPAR BINDVAR name_term RPAR { Hashtbl.add hlets $2 $3 }
+ | LPAR BINDVAR lit RPAR { Hashtbl.add hlets $2 (Lit $3) }
+ | LPAR BINDVAR name_term RPAR bindlist { Hashtbl.add hlets $2 $3; $5 }
+ | LPAR BINDVAR lit RPAR bindlist { Hashtbl.add hlets $2 (Lit $3); $5 }
+
+args:
+ | name_term { match $1 with Atom h -> [h] | _ -> assert false }
+ | name_term args { match $1 with Atom h -> h::$2 | _ -> assert false }
+;
+
+clause_ids_params:
+ | int_list { $1 }
+;
+
+int_list:
+ | INT { [$1] }
+ | INT int_list { let x1 = $1 in let x2 = $2 in x1::x2 }
+;
diff --git a/src/verit/veritSyntax.ml b/src/verit/veritSyntax.ml
new file mode 100644
index 0000000..c60d34f
--- /dev/null
+++ b/src/verit/veritSyntax.ml
@@ -0,0 +1,355 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+
+open SmtAtom
+open SmtForm
+open SmtCertif
+open SmtTrace
+
+
+(*** Syntax of veriT proof traces ***)
+
+exception Sat
+
+type typ = | Inpu | Deep | True | Fals | Andp | Andn | Orp | Orn | Xorp1 | Xorp2 | Xorn1 | Xorn2 | Impp | Impn1 | Impn2 | Equp1 | Equp2 | Equn1 | Equn2 | Itep1 | Itep2 | Iten1 | Iten2 | Eqre | Eqtr | Eqco | Eqcp | Dlge | Lage | Lata | Dlde | Lade | Fins | Eins | Skea | Skaa | Qnts | Qntm | Reso | And | Nor | Or | Nand | Xor1 | Xor2 | Nxor1 | Nxor2 | Imp | Nimp1 | Nimp2 | Equ1 | Equ2 | Nequ1 | Nequ2 | Ite1 | Ite2 | Nite1 | Nite2 | Tpal | Tlap | Tple | Tpne | Tpde | Tpsa | Tpie | Tpma | Tpbr | Tpbe | Tpsc | Tppp | Tpqt | Tpqs | Tpsk | Subp
+
+
+(* About equality *)
+
+let get_eq l =
+ match Form.pform l with
+ | Fatom ha ->
+ (match Atom.atom ha with
+ | Abop (BO_eq _,a,b) -> (a,b)
+ | _ -> failwith "VeritSyntax.get_eq: equality was expected")
+ | _ -> failwith "VeritSyntax.get_eq: equality was expected"
+
+let get_at l =
+ match Form.pform l with
+ | Fatom ha -> ha
+ | _ -> failwith "VeritSyntax.get_eq: equality was expected"
+
+let is_eq l =
+ match Form.pform l with
+ | Fatom ha ->
+ (match Atom.atom ha with
+ | Abop (BO_eq _,_,_) -> true
+ | _ -> false)
+ | _ -> failwith "VeritSyntax.get_eq: atom was expected"
+
+
+(* Transitivity *)
+
+let rec process_trans a b prem res =
+ try
+ let (l,(c,c')) = List.find (fun (l,(a',b')) -> (a' = b || b' = b)) prem in
+ let prem = List.filter (fun l' -> l' <> (l,(c,c'))) prem in
+ let c = if c = b then c' else c in
+ if a = c
+ then List.rev (l::res)
+ else process_trans a c prem (l::res)
+ with
+ |Not_found -> if a = b then [] else assert false
+
+
+let mkTrans p =
+ let (concl,prem) = List.partition Form.is_pos p in
+ match concl with
+ |[c] ->
+ let a,b = get_eq c in
+ let prem_val = List.map (fun l -> (l,get_eq l)) prem in
+ let cert = (process_trans a b prem_val []) in
+ Other (EqTr (c,cert))
+ |_ -> failwith "VeritSyntax.mkTrans: no conclusion or more than one conclusion in transitivity"
+
+
+(* Congruence *)
+
+let rec process_congr a_args b_args prem res =
+ match a_args,b_args with
+ | a::a_args,b::b_args ->
+ (* if a = b *)
+ (* then process_congr a_args b_args prem (None::res) *)
+ (* else *)
+ let (l,(a',b')) = List.find (fun (l,(a',b')) -> (a = a' && b = b')||(a = b' && b = a')) prem in
+ process_congr a_args b_args prem ((Some l)::res)
+ | [],[] -> List.rev res
+ | _ -> failwith "VeritSyntax.process_congr: incorrect number of arguments in function application"
+
+
+let mkCongr p =
+ let (concl,prem) = List.partition Form.is_pos p in
+ match concl with
+ |[c] ->
+ let a,b = get_eq c in
+ let prem_val = List.map (fun l -> (l,get_eq l)) prem in
+ (match Atom.atom a, Atom.atom b with
+ | Abop(aop,a1,a2), Abop(bop,b1,b2) when (aop = bop) ->
+ let a_args = [a1;a2] in
+ let b_args = [b1;b2] in
+ let cert = process_congr a_args b_args prem_val [] in
+ Other (EqCgr (c,cert))
+ | Auop (aop,a), Auop (bop,b) when (aop = bop) ->
+ let a_args = [a] in
+ let b_args = [b] in
+ let cert = process_congr a_args b_args prem_val [] in
+ Other (EqCgr (c,cert))
+ | Aapp (a_f,a_args), Aapp (b_f,b_args) ->
+ if a_f = b_f then
+ let cert = process_congr (Array.to_list a_args) (Array.to_list b_args) prem_val [] in
+ Other (EqCgr (c,cert))
+ else failwith "VeritSyntax.mkCongr: left function is different from right fucntion"
+ | _, _ -> failwith "VeritSyntax.mkCongr: atoms are not applications")
+ |_ -> failwith "VeritSyntax.mkCongr: no conclusion or more than one conclusion in congruence"
+
+
+let mkCongrPred p =
+ let (concl,prem) = List.partition Form.is_pos p in
+ let (prem,prem_P) = List.partition is_eq prem in
+ match concl with
+ |[c] ->
+ (match prem_P with
+ |[p_p] ->
+ let prem_val = List.map (fun l -> (l,get_eq l)) prem in
+ (match Atom.atom (get_at c), Atom.atom (get_at p_p) with
+ | Abop(aop,a1,a2), Abop(bop,b1,b2) when (aop = bop) ->
+ let a_args = [a1;a2] in
+ let b_args = [b1;b2] in
+ let cert = process_congr a_args b_args prem_val [] in
+ Other (EqCgrP (p_p,c,cert))
+ | Aapp (a_f,a_args), Aapp (b_f,b_args) ->
+ if a_f = b_f then
+ let cert = process_congr (Array.to_list a_args) (Array.to_list b_args) prem_val [] in
+ Other (EqCgrP (p_p,c,cert))
+ else failwith "VeritSyntax.mkCongrPred: unmatching predicates"
+ | _ -> failwith "VeritSyntax.mkCongrPred : not pred app")
+ |_ -> failwith "VeritSyntax.mkCongr: no or more than one predicate app premice in congruence")
+ |[] -> failwith "VeritSyntax.mkCongrPred: no conclusion in congruence"
+ |_ -> failwith "VeritSyntax.mkCongrPred: more than one conclusion in congruence"
+
+
+(* Linear arithmetic *)
+
+let mkMicromega cl =
+ let _tbl, _f, cert = Lia.build_lia_certif cl in
+ let c =
+ match cert with
+ | None -> failwith "VeritSyntax.mkMicromega: micromega can't solve this"
+ | Some c -> c in
+ Other (LiaMicromega (cl,c))
+
+
+let mkSplArith orig cl =
+ let res =
+ match cl with
+ | res::nil -> res
+ | _ -> failwith "VeritSyntax.mkSplArith: wrong number of literals in the resulting clause" in
+ try
+ let orig' =
+ match orig.value with
+ | Some [orig'] -> orig'
+ | _ -> failwith "VeritSyntax.mkSplArith: wrong number of literals in the premise clause" in
+ let _tbl, _f, cert = Lia.build_lia_certif [Form.neg orig';res] in
+ let c =
+ match cert with
+ | None -> failwith "VeritSyntax.mkSplArith: micromega can't solve this"
+ | Some c -> c in
+ Other (SplArith (orig,res,c))
+ with
+ | _ -> Other (ImmFlatten (orig, res))
+
+
+(* Elimination of operators *)
+
+let mkDistinctElim old value =
+ let rec find_res l1 l2 =
+ match l1,l2 with
+ | t1::q1,t2::q2 -> if t1 == t2 then find_res q1 q2 else t2
+ | _, _ -> assert false in
+ let l1 = match old.value with
+ | Some l -> l
+ | None -> assert false in
+ Other (SplDistinctElim (old,find_res l1 value))
+
+
+(* Generating clauses *)
+
+let clauses : (int,Form.t clause) Hashtbl.t = Hashtbl.create 17
+let get_clause id =
+ try Hashtbl.find clauses id
+ with | Not_found -> failwith ("VeritSyntax.get_clause : clause number "^(string_of_int id)^" not found\n")
+let add_clause id cl = Hashtbl.add clauses id cl
+let clear_clauses () = Hashtbl.clear clauses
+
+let mk_clause (id,typ,value,ids_params) =
+ let kind =
+ match typ with
+ (* Roots *)
+ | Inpu -> Root
+ (* Cnf conversion *)
+ | True -> Other SmtCertif.True
+ | Fals -> Other False
+ | Andn | Orp | Impp | Xorp1 | Xorn1 | Equp1 | Equn1 | Itep1 | Iten1 ->
+ (match value with
+ | l::_ -> Other (BuildDef l)
+ | _ -> assert false)
+ | Xorp2 | Xorn2 | Equp2 | Equn2 | Itep2 | Iten2 ->
+ (match value with
+ | l::_ -> Other (BuildDef2 l)
+ | _ -> assert false)
+ | Orn | Andp ->
+ (match value,ids_params with
+ | l::_, [p] -> Other (BuildProj (l,p))
+ | _ -> assert false)
+ | Impn1 ->
+ (match value with
+ | l::_ -> Other (BuildProj (l,0))
+ | _ -> assert false)
+ | Impn2 ->
+ (match value with
+ | l::_ -> Other (BuildProj (l,1))
+ | _ -> assert false)
+ | Nand | Or | Imp | Xor1 | Nxor1 | Equ2 | Nequ2 | Ite1 | Nite1 ->
+ (match ids_params with
+ | [id] -> Other (ImmBuildDef (get_clause id))
+ | _ -> assert false)
+ | Xor2 | Nxor2 | Equ1 | Nequ1 | Ite2 | Nite2 ->
+ (match ids_params with
+ | [id] -> Other (ImmBuildDef2 (get_clause id))
+ | _ -> assert false)
+ | And | Nor ->
+ (match ids_params with
+ | [id;p] -> Other (ImmBuildProj (get_clause id,p))
+ | _ -> assert false)
+ | Nimp1 ->
+ (match ids_params with
+ | [id] -> Other (ImmBuildProj (get_clause id,0))
+ | _ -> assert false)
+ | Nimp2 ->
+ (match ids_params with
+ | [id] -> Other (ImmBuildProj (get_clause id,1))
+ | _ -> assert false)
+ (* Equality *)
+ | Eqre -> mkTrans value
+ | Eqtr -> mkTrans value
+ | Eqco -> mkCongr value
+ | Eqcp -> mkCongrPred value
+ (* Linear integer arithmetic *)
+ | Dlge | Lage | Lata -> mkMicromega value
+ | Lade -> mkMicromega value (* TODO: utiliser un solveur plus simple *)
+ | Dlde ->
+ (match value with
+ | l::_ -> Other (LiaDiseq l)
+ | _ -> assert false)
+ (* Resolution *)
+ | Reso ->
+ (match ids_params with
+ | cl1::cl2::q ->
+ let res = {rc1 = get_clause cl1; rc2 = get_clause cl2; rtail = List.map get_clause q} in
+ Res res
+ | _ -> assert false)
+ (* Simplifications *)
+ | Tpal ->
+ (match ids_params with
+ | id::_ -> Same (get_clause id)
+ | _ -> assert false)
+ | Tple ->
+ (match ids_params with
+ | id::_ -> Same (get_clause id)
+ | _ -> assert false)
+ | Tpde ->
+ (match ids_params with
+ | id::_ -> mkDistinctElim (get_clause id) value
+ | _ -> assert false)
+ | Tpsa | Tlap ->
+ (match ids_params with
+ | id::_ -> mkSplArith (get_clause id) value
+ | _ -> assert false)
+ (* Not implemented *)
+ | Deep -> failwith "VeritSyntax.ml: rule deep_res not implemented yet"
+ | Fins -> failwith "VeritSyntax.ml: rule forall_inst not implemented yet"
+ | Eins -> failwith "VeritSyntax.ml: rule exists_inst not implemented yet"
+ | Skea -> failwith "VeritSyntax.ml: rule skolem_ex_ax not implemented yet"
+ | Skaa -> failwith "VeritSyntax.ml: rule skolem_all_ax not implemented yet"
+ | Qnts -> failwith "VeritSyntax.ml: rule qnt_simplify_ax not implemented yet"
+ | Qntm -> failwith "VeritSyntax.ml: rule qnt_merge_ax not implemented yet"
+ | Tpne -> failwith "VeritSyntax.ml: rule tmp_nary_elim not implemented yet"
+ | Tpie -> failwith "VeritSyntax.ml: rule tmp_ite_elim not implemented yet"
+ | Tpma -> failwith "VeritSyntax.ml: rule tmp_macrosubst not implemented yet"
+ | Tpbr -> failwith "VeritSyntax.ml: rule tmp_betared not implemented yet"
+ | Tpbe -> failwith "VeritSyntax.ml: rule tmp_bfun_elim not implemented yet"
+ | Tpsc -> failwith "VeritSyntax.ml: rule tmp_sk_connector not implemented yet"
+ | Tppp -> failwith "VeritSyntax.ml: rule tmp_pm_process not implemented yet"
+ | Tpqt -> failwith "VeritSyntax.ml: rule tmp_qnt_tidy not implemented yet"
+ | Tpqs -> failwith "VeritSyntax.ml: rule tmp_qnt_simplify not implemented yet"
+ | Tpsk -> failwith "VeritSyntax.ml: rule tmp_skolemize not implemented yet"
+ | Subp -> failwith "VeritSyntax.ml: rule subproof not implemented yet"
+ in
+ let cl =
+ (* TODO: change this into flatten when necessary *)
+ if SmtTrace.isRoot kind then SmtTrace.mkRootV value
+ else SmtTrace.mk_scertif kind (Some value) in
+ add_clause id cl;
+ if id > 1 then SmtTrace.link (get_clause (id-1)) cl;
+ id
+
+
+type atom_form_lit =
+ | Atom of SmtAtom.Atom.t
+ | Form of SmtAtom.Form.pform
+ | Lit of SmtAtom.Form.t
+
+let lit_of_atom_form_lit rf = function
+ | Atom a -> Form.get rf (Fatom a)
+ | Form f -> Form.get rf f
+ | Lit l -> l
+
+let solver : (int,atom_form_lit) Hashtbl.t = Hashtbl.create 17
+let get_solver id =
+ try Hashtbl.find solver id
+ with | Not_found -> failwith ("VeritSyntax.get_solver : solver variable number "^(string_of_int id)^" not found\n")
+let add_solver id cl = Hashtbl.add solver id cl
+let clear_solver () = Hashtbl.clear solver
+
+let btypes : (string,btype) Hashtbl.t = Hashtbl.create 17
+let get_btype id =
+ try Hashtbl.find btypes id
+ with | Not_found -> failwith ("VeritSyntax.get_btype : sort symbol \""^id^"\" not found\n")
+let add_btype id cl = Hashtbl.add btypes id cl
+let clear_btypes () = Hashtbl.clear btypes
+
+let funs : (string,indexed_op) Hashtbl.t = Hashtbl.create 17
+let get_fun id =
+ try Hashtbl.find funs id
+ with | Not_found -> failwith ("VeritSyntax.get_fun : function symbol \""^id^"\" not found\n")
+let add_fun id cl = Hashtbl.add funs id cl
+let clear_funs () = Hashtbl.clear funs
+
+
+let ra = Atom.create ()
+let rf = Form.create ()
+
+let hlets : (string, atom_form_lit) Hashtbl.t = Hashtbl.create 17
+
+
+let clear () =
+ clear_clauses ();
+ clear_solver ();
+ clear_btypes ();
+ clear_funs ();
+ Atom.clear ra;
+ Form.clear rf;
+ Hashtbl.clear hlets
diff --git a/src/verit/veritSyntax.mli b/src/verit/veritSyntax.mli
new file mode 100644
index 0000000..9813b54
--- /dev/null
+++ b/src/verit/veritSyntax.mli
@@ -0,0 +1,44 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+exception Sat
+
+type typ = | Inpu | Deep | True | Fals | Andp | Andn | Orp | Orn | Xorp1 | Xorp2 | Xorn1 | Xorn2 | Impp | Impn1 | Impn2 | Equp1 | Equp2 | Equn1 | Equn2 | Itep1 | Itep2 | Iten1 | Iten2 | Eqre | Eqtr | Eqco | Eqcp | Dlge | Lage | Lata | Dlde | Lade | Fins | Eins | Skea | Skaa | Qnts | Qntm | Reso | And | Nor | Or | Nand | Xor1 | Xor2 | Nxor1 | Nxor2 | Imp | Nimp1 | Nimp2 | Equ1 | Equ2 | Nequ1 | Nequ2 | Ite1 | Ite2 | Nite1 | Nite2 | Tpal | Tlap | Tple | Tpne | Tpde | Tpsa | Tpie | Tpma | Tpbr | Tpbe | Tpsc | Tppp | Tpqt | Tpqs | Tpsk | Subp
+
+val get_clause : int -> SmtAtom.Form.t SmtCertif.clause
+val add_clause : int -> SmtAtom.Form.t SmtCertif.clause -> unit
+
+val mk_clause : SmtCertif.clause_id * typ * SmtAtom.Form.t list * SmtCertif.clause_id list -> SmtCertif.clause_id
+
+type atom_form_lit =
+ | Atom of SmtAtom.Atom.t
+ | Form of SmtAtom.Form.pform
+ | Lit of SmtAtom.Form.t
+val lit_of_atom_form_lit : SmtAtom.Form.reify -> atom_form_lit -> SmtAtom.Form.t
+val get_solver : int -> atom_form_lit
+val add_solver : int -> atom_form_lit -> unit
+
+val get_btype : string -> SmtAtom.btype
+val add_btype : string -> SmtAtom.btype -> unit
+
+val get_fun : string -> SmtAtom.indexed_op
+val add_fun : string -> SmtAtom.indexed_op -> unit
+
+val ra : SmtAtom.Atom.reify_tbl
+val rf : SmtAtom.Form.reify
+
+val hlets : (string, atom_form_lit) Hashtbl.t
+
+val clear : unit -> unit
diff --git a/src/zchaff/cnfParser.ml b/src/zchaff/cnfParser.ml
new file mode 100644
index 0000000..9a21675
--- /dev/null
+++ b/src/zchaff/cnfParser.ml
@@ -0,0 +1,57 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+open SatParser
+
+
+let skip_comment lb =
+ while blank_check_string lb "c" do skip_line lb done
+
+let parse_p_cnf lb =
+ skip_comment lb;
+ blank_match_string lb "p";
+ blank_match_string lb "cnf";
+ let nvar = input_blank_int lb in
+ let _ = input_blank_int lb in
+ nvar
+
+let mklit nvars reify l =
+ let sign = l > 0 in
+ let x = (if sign then l else - l) - 1 in
+ assert (0 <= x && x < nvars);
+ let p = SatAtom.Form.get reify (SmtForm.Fatom x) in
+ if sign then p else SatAtom.Form.neg p
+
+let rec parse_clause nvars reify lb =
+ let i = input_blank_int lb in
+ if i = 0 then []
+ else mklit nvars reify i :: parse_clause nvars reify lb
+
+let rec parse_clauses nvars reify lb last =
+ if is_start_int lb then
+ let c = SmtTrace.mkRootV (parse_clause nvars reify lb) in
+ SmtTrace.link last c;
+ parse_clauses nvars reify lb c
+ else last
+
+let parse_cnf filename =
+ let reify = SatAtom.Form.create () in
+ let lb = open_file "CNF" filename in
+ let nvars = parse_p_cnf lb in
+ let first = SmtTrace.mkRootV (parse_clause nvars reify lb) in
+ let last = parse_clauses nvars reify lb first in
+ close lb;
+ nvars, first, last
+
diff --git a/src/zchaff/satParser.ml b/src/zchaff/satParser.ml
new file mode 100644
index 0000000..731d499
--- /dev/null
+++ b/src/zchaff/satParser.ml
@@ -0,0 +1,178 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+type lex_buff = {
+ buff : string;
+ mutable curr_char : int;
+ mutable buff_end : int;
+ in_ch : in_channel
+ }
+
+let buff_length = 1024
+
+let open_file s name =
+ try
+ let in_channel = open_in name in
+ let buff = String.create buff_length in
+ let buff_end = input in_channel buff 0 buff_length in
+ { buff = buff; curr_char = 0; buff_end = buff_end; in_ch = in_channel }
+ with _ ->
+ Printf.printf ("%s file %s does not exists.\n") s name;
+ exit 1
+
+let close lb =
+ lb.buff_end <- 0;
+ close_in lb.in_ch
+
+let eof lb = lb.buff_end == 0
+
+let curr_char lb =
+ if eof lb then raise End_of_file
+ else lb.buff.[lb.curr_char]
+
+let refill lb =
+ let ne = input lb.in_ch lb.buff 0 buff_length in
+ lb.curr_char <- 0;
+ lb.buff_end <- ne
+
+(* Unsafe function *)
+let is_space c = c == ' ' || c == '\t'
+
+let is_space_ret c = c == ' ' || c == '\n' || c == '\t'
+
+
+let skip to_skip lb =
+ while not (eof lb) && to_skip lb.buff.[lb.curr_char] do
+ while lb.curr_char < lb.buff_end && to_skip lb.buff.[lb.curr_char] do
+ lb.curr_char <- lb.curr_char + 1
+ done;
+ if lb.curr_char = lb.buff_end then refill lb
+ done
+
+let skip_space lb = skip is_space lb
+let skip_blank lb = skip is_space_ret lb
+
+
+let skip_string lb s =
+ let slen = String.length s in
+ let pos = ref 0 in
+ while !pos < slen && not (eof lb) && lb.buff.[lb.curr_char] == s.[!pos] do
+ lb.curr_char <- lb.curr_char + 1;
+ incr pos;
+ while !pos < slen && lb.curr_char < lb.buff_end && lb.buff.[lb.curr_char] == s.[!pos] do
+ lb.curr_char <- lb.curr_char + 1;
+ incr pos
+ done;
+ if lb.curr_char = lb.buff_end then refill lb
+ done;
+ !pos = slen
+
+let match_string lb s =
+ if not (skip_string lb s) then raise (Invalid_argument ("match_string "^s))
+
+let aux_buff = String.create buff_length
+let aux_be = ref 0
+let aux_pi = ref 0
+let aux_cc = ref 0
+
+let save_lb lb =
+ aux_cc := lb.curr_char;
+ aux_be := lb.buff_end;
+ aux_pi := pos_in lb.in_ch;
+ String.blit lb.buff !aux_cc aux_buff !aux_cc (!aux_be - !aux_cc)
+
+let restore_lb lb =
+ lb.curr_char <- !aux_cc;
+ lb.buff_end <- !aux_be;
+ seek_in lb.in_ch !aux_pi;
+ String.blit aux_buff !aux_cc lb.buff !aux_cc (!aux_be - !aux_cc)
+
+let check_string lb s =
+ let slen = String.length s in
+ if String.length s <= lb.buff_end - lb.curr_char then
+ let cc = lb.curr_char in
+ let pos = ref 0 in
+ while !pos < slen && lb.buff.[lb.curr_char] == s.[!pos] do
+ lb.curr_char <- lb.curr_char + 1;
+ incr pos
+ done;
+ if !pos = slen then begin
+ if lb.curr_char = lb.buff_end then refill lb;
+ true
+ end else begin
+ lb.curr_char <- cc;
+ false
+ end
+ else begin
+ save_lb lb;
+ let b = skip_string lb s in
+ if not b then restore_lb lb;
+ b
+ end
+
+let blank_check_string lb s =
+ skip_blank lb;
+ check_string lb s
+
+let blank_match_string lb s =
+ skip_blank lb;
+ match_string lb s
+
+let is_digit c =
+ '0' <= c && c <= '9'
+
+let is_start_int lb =
+ skip_blank lb;
+ not (eof lb) && (is_digit lb.buff.[lb.curr_char] || lb.buff.[lb.curr_char] == '-')
+
+let input_int lb =
+ if eof lb then raise End_of_file
+ else begin
+ let sign =
+ if lb.buff.[lb.curr_char] == '-' then begin
+ lb.curr_char <- lb.curr_char + 1;
+ if lb.curr_char = lb.buff_end then refill lb;
+ -1
+ end else
+ 1 in
+ if eof lb then raise End_of_file;
+ if not (is_digit lb.buff.[lb.curr_char]) then raise (Invalid_argument "input_int");
+ let n = ref (Char.code lb.buff.[lb.curr_char] - Char.code '0') in
+ lb.curr_char <- lb.curr_char + 1;
+ if lb.curr_char = lb.buff_end then refill lb;
+ while not (eof lb) && is_digit lb.buff.[lb.curr_char] do
+ while lb.curr_char < lb.buff_end && is_digit lb.buff.[lb.curr_char] do
+ n := !n*10 + (Char.code lb.buff.[lb.curr_char] - Char.code '0');
+ lb.curr_char <- lb.curr_char + 1
+ done;
+ if lb.curr_char = lb.buff_end then refill lb
+ done;
+ sign * !n
+ end
+
+let input_blank_int lb =
+ skip_blank lb;
+ input_int lb
+
+
+let skip_line lb =
+ let notfound = ref true in
+ while not (eof lb) && !notfound do
+ while lb.curr_char < lb.buff_end && !notfound do
+ if lb.buff.[lb.curr_char] == '\n' then notfound := false;
+ lb.curr_char <- lb.curr_char + 1
+ done;
+ if lb.curr_char = lb.buff_end then refill lb
+ done
diff --git a/src/zchaff/zchaff.ml b/src/zchaff/zchaff.ml
new file mode 100644
index 0000000..b94a0cc
--- /dev/null
+++ b/src/zchaff/zchaff.ml
@@ -0,0 +1,532 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+
+open Entries
+open Declare
+open Decl_kinds
+
+open SmtMisc
+open CoqTerms
+open SmtForm
+open SmtCertif
+open SmtTrace
+open SatAtom
+open SmtMisc
+
+
+(* Detection of trivial clauses *)
+
+let rec is_trivial cl =
+ match cl with
+ | l :: cl ->
+ let nl = Form.neg l in
+ List.exists (fun l' -> Form.equal nl l') cl || is_trivial cl
+ | [] -> false
+
+
+(* Pretty printing *)
+
+let string_of_op = function
+ | Ftrue -> "true"
+ | Ffalse -> "false"
+ | Fand -> "and"
+ | For -> "or"
+ | Fxor -> "xor"
+ | Fimp -> "imp"
+ | Fiff -> "iff"
+ | Fite -> "ite"
+ | Fnot2 i -> "!"^string_of_int i
+
+let rec pp_form fmt l =
+ Format.fprintf fmt "(#%i %a %a)" (Form.to_lit l)pp_sign l pp_pform (Form.pform l)
+and pp_sign fmt l =
+ if Form.is_pos l then ()
+ else Format.fprintf fmt "-"
+and pp_pform fmt p =
+ match p with
+ | Fatom x -> Format.fprintf fmt "x%i" x
+ | Fapp(op,args) ->
+ Format.fprintf fmt "%s" (string_of_op op);
+ Array.iter (fun a -> Format.fprintf fmt "%a " pp_form a) args
+
+let pp_value fmt c =
+ match c.value with
+ | Some cl ->
+ Format.fprintf fmt "VAL = {";
+ List.iter (Format.fprintf fmt "%a " pp_form) cl;
+ Format.fprintf fmt "}@."
+ | _ -> Format.fprintf fmt "Val = empty@."
+
+
+let pp_kind fmt c =
+ match c.kind with
+ | Root -> Format.fprintf fmt "Root"
+ | Res res ->
+ Format.fprintf fmt "(Res %i %i " res.rc1.id res.rc2.id;
+ List.iter (fun c -> Format.fprintf fmt "%i " c.id) res.rtail;
+ Format.fprintf fmt ") "
+ | Other other ->
+ begin match other with
+ | ImmFlatten (c,l) ->
+ Format.fprintf fmt "(ImmFlatten %i %a)"
+ c.id pp_form l
+ | True -> Format.fprintf fmt "True"
+ | False -> Format.fprintf fmt "False"
+ | BuildDef l -> Format.fprintf fmt "(BuildDef %a)" pp_form l
+ | BuildDef2 l -> Format.fprintf fmt "(BuildDef2 %a)" pp_form l
+ | BuildProj (l,i) -> Format.fprintf fmt "(BuildProj %a %i)" pp_form l i
+ | ImmBuildProj (c,i) ->Format.fprintf fmt "(ImmBuildProj %i %i)" c.id i
+ | ImmBuildDef c -> Format.fprintf fmt "(ImmBuildDef %i)" c.id
+ | ImmBuildDef2 c -> Format.fprintf fmt "(ImmBuildDef %i)" c.id
+ | _ -> assert false
+ end
+ | Same c -> Format.fprintf fmt "(Same %i)" c.id
+
+let rec pp_trace fmt c =
+ Format.fprintf fmt "%i = %a %a" c.id pp_kind c pp_value c;
+ if c.next <> None then pp_trace fmt (next c)
+
+
+(******************************************************************************)
+(** Given a cnf (dimacs) files and a resolve_trace build *)
+(* the corresponding object *)
+(******************************************************************************)
+
+
+let import_cnf filename =
+ let nvars, first, last = CnfParser.parse_cnf filename in
+ let reloc = Hashtbl.create 17 in
+ let count = ref 0 in
+ let r = ref first in
+ while !r.next <> None do
+ if not (is_trivial (get_val !r)) then begin
+ Hashtbl.add reloc !count !r;
+ incr count
+ end;
+ r := next !r
+ done;
+ if not (is_trivial (get_val !r)) then Hashtbl.add reloc !count !r;
+ nvars,first,last,reloc
+
+let import_cnf_trace reloc filename first last =
+ (* Format.fprintf Format.err_formatter "init@."; *)
+ (* pp_trace Format.err_formatter first; *)
+ let confl = ZchaffParser.parse_proof reloc filename last in
+ (* Format.fprintf Format.err_formatter "zchaff@."; *)
+ (* pp_trace Format.err_formatter first; *)
+ SmtTrace.select confl;
+ (* Format.fprintf Format.err_formatter "select@."; *)
+ (* pp_trace Format.err_formatter first; *)
+ Trace.share_prefix first (2 * last.id);
+ (* Format.fprintf Format.err_formatter "share_prefix@."; *)
+ (* pp_trace Format.err_formatter first; *)
+ occur confl;
+ let res = alloc first, confl in
+ res
+
+let make_roots first last =
+ let cint = Lazy.force cint in
+ let roots = Array.make (last.id + 2) (Term.mkArray (cint, Array.make 1 (mkInt 0))) in
+ let mk_elem l =
+ let x = match Form.pform l with
+ | Fatom x -> x + 2
+ | _ -> assert false in
+ mkInt (if Form.is_pos l then x lsl 1 else (x lsl 1) lxor 1) in
+ let r = ref first in
+ while !r.id < last.id do
+ let root = Array.of_list (get_val !r) in
+ let croot = Array.make (Array.length root + 1) (mkInt 0) in
+ Array.iteri (fun i l -> croot.(i) <- mk_elem l) root;
+ roots.(!r.id) <- Term.mkArray (cint, croot);
+ r := next !r
+ done;
+ let root = Array.of_list (get_val !r) in
+ let croot = Array.make (Array.length root + 1) (mkInt 0) in
+ Array.iteri (fun i l -> croot.(i) <- mk_elem l) root;
+ roots.(!r.id) <- Term.mkArray (cint, croot);
+
+ Term.mkArray (mklApp carray [|cint|], roots)
+
+let interp_roots first last =
+ let tbl = Hashtbl.create 17 in
+ let mk_elem l =
+ let x = match Form.pform l with
+ | Fatom x -> x
+ | _ -> assert false in
+ let ph = x lsl 1 in
+ let h = if Form.is_pos l then ph else ph lxor 1 in
+ try Hashtbl.find tbl h
+ with Not_found ->
+ let p = Term.mkApp (Term.mkRel 1, [|mkInt (x+1)|]) in
+ let np = mklApp cnegb [|p|] in
+ Hashtbl.add tbl ph p;
+ Hashtbl.add tbl (ph lxor 1) np;
+ if Form.is_pos l then p else np in
+ let interp_root c =
+ match get_val c with
+ | [] -> Lazy.force cfalse
+ | l :: cl ->
+ List.fold_left (fun acc l -> mklApp corb [|acc; mk_elem l|])
+ (mk_elem l) cl in
+ let res = ref (interp_root first) in
+ if first.id <> last.id then begin
+ let r = ref (next first) in
+ while !r.id <= last.id do
+ res := mklApp candb [|!res;interp_root !r|];
+ r := next !r
+ done;
+ end;
+ !res
+
+let sat_checker_modules = [ ["SMTCoq";"Trace";"Sat_Checker"] ]
+
+let certif_ops = CoqTerms.make_certif_ops sat_checker_modules
+let cCertif = gen_constant sat_checker_modules "Certif"
+
+let parse_certif dimacs trace fdimacs ftrace =
+ SmtTrace.clear ();
+ let _,first,last,reloc = import_cnf fdimacs in
+ let d = make_roots first last in
+ let ce1 =
+ { const_entry_body = d;
+ const_entry_type = None;
+ const_entry_secctx = None;
+ const_entry_opaque = false;
+ const_entry_inline_code = false} in
+ let _ = declare_constant dimacs (DefinitionEntry ce1, IsDefinition Definition) in
+
+ let max_id, confl = import_cnf_trace reloc ftrace first last in
+ let (tres,_) = SmtTrace.to_coq (fun _ -> assert false) certif_ops confl in
+ let certif =
+ mklApp cCertif [|mkInt (max_id + 1); tres;mkInt (get_pos confl)|] in
+ let ce2 =
+ { const_entry_body = certif;
+ const_entry_type = None;
+ const_entry_secctx = None;
+ const_entry_opaque = false;
+ const_entry_inline_code = false} in
+ let _ = declare_constant trace (DefinitionEntry ce2, IsDefinition Definition) in
+ ()
+
+let cdimacs = gen_constant sat_checker_modules "dimacs"
+let ccertif = gen_constant sat_checker_modules "certif"
+let ctheorem_checker = gen_constant sat_checker_modules "theorem_checker"
+let cchecker = gen_constant sat_checker_modules "checker"
+
+let theorem name fdimacs ftrace =
+ SmtTrace.clear ();
+ let _,first,last,reloc = import_cnf fdimacs in
+ let d = make_roots first last in
+
+ let max_id, confl = import_cnf_trace reloc ftrace first last in
+ let (tres,_) =
+ SmtTrace.to_coq (fun _ -> assert false) certif_ops confl in
+ let certif =
+ mklApp cCertif [|mkInt (max_id + 1);tres;mkInt (get_pos confl)|] in
+
+ let theorem_concl = mklApp cnot [|mklApp cis_true [|interp_roots first last|] |] in
+ let vtype = Term.mkProd(Names.Anonymous, Lazy.force cint, Lazy.force cbool) in
+ let theorem_type =
+ Term.mkProd (mkName "v", vtype, theorem_concl) in
+ let theorem_proof =
+ Term.mkLetIn (mkName "d", d, Lazy.force cdimacs,
+ Term.mkLetIn (mkName "c", certif, Lazy.force ccertif,
+ Term.mkLambda (mkName "v", vtype,
+ mklApp ctheorem_checker
+ [| Term.mkRel 3(*d*); Term.mkRel 2(*c*);
+ vm_cast_true
+ (mklApp cchecker [|Term.mkRel 3(*d*); Term.mkRel 2(*c*)|]);
+ Term.mkRel 1(*v*)|]))) in
+ let ce =
+ { const_entry_body = theorem_proof;
+ const_entry_type = Some theorem_type;
+ const_entry_secctx = None;
+ const_entry_opaque = true;
+ const_entry_inline_code = false} in
+ let _ = declare_constant name (DefinitionEntry ce, IsDefinition Definition) in
+ ()
+
+
+let checker fdimacs ftrace =
+ SmtTrace.clear ();
+ let _,first,last,reloc = import_cnf fdimacs in
+ let d = make_roots first last in
+
+ let max_id, confl = import_cnf_trace reloc ftrace first last in
+ let (tres,_) =
+ SmtTrace.to_coq (fun _ -> assert false) certif_ops confl in
+ let certif =
+ mklApp cCertif [|mkInt (max_id + 1);tres;mkInt (get_pos confl)|] in
+
+ let tm = mklApp cchecker [|d; certif|] in
+ let expr = Constrextern.extern_constr true Environ.empty_env tm in
+ Vernacentries.interp (Vernacexpr.VernacCheckMayEval (Some (Glob_term.CbvVm None), None, expr))
+
+
+
+
+
+(******************************************************************************)
+(** Given a Coq formula build the proof *)
+(******************************************************************************)
+
+let export_clause fmt cl =
+ List.iter
+ (fun l -> Format.fprintf fmt "%s%i "
+ (if Form.is_pos l then "" else "-") (Form.index l + 1)) cl;
+ Format.fprintf fmt "0@\n"
+
+let export out_channel nvars first =
+ let fmt = Format.formatter_of_out_channel out_channel in
+ let reloc = Hashtbl.create 17 in
+ let count = ref 0 in
+ (* count the number of non trivial clause *)
+ let r = ref first in
+ let add_count c =
+ match c.value with
+ | Some cl -> if not (is_trivial cl) then incr count
+ | _ -> () in
+ while !r.next <> None do add_count !r; r := next !r done;
+ add_count !r;
+ Format.fprintf fmt "p cnf %i %i@." nvars !count;
+ count := 0; r := first;
+ (* ouput clause *)
+ let out c =
+ match c.value with
+ | Some cl ->
+ if not (is_trivial cl) then begin
+ Hashtbl.add reloc !count c;
+ incr count;
+ export_clause fmt cl
+ end
+ | None -> assert false in
+ while !r.next <> None do out !r; r := next !r done;
+ out !r;
+ Format.fprintf fmt "@.";
+ reloc, !r
+
+
+(* Call zchaff *)
+
+let call_zchaff nvars root =
+ let (filename, outchan) = Filename.open_temp_file "zchaff_coq" ".cnf" in
+ let resfilename = (Filename.chop_extension filename)^".zlog" in
+ let reloc, last = export outchan nvars root in
+ close_out outchan;
+ let command = "zchaff "^filename^" > "^resfilename in
+ Format.eprintf "%s@." command;
+ let t0 = Sys.time () in
+ let exit_code = Sys.command command in
+ let t1 = Sys.time () in
+ Format.eprintf "Zchaff = %.5f@." (t1-.t0);
+ if exit_code <> 0 then
+ failwith ("Zchaff.call_zchaff: command "^command^
+ " exited with code "^(string_of_int exit_code));
+ let logfilename = (Filename.chop_extension filename)^".log" in
+ let command2 = "mv resolve_trace "^logfilename in
+ let exit_code2 = Sys.command command2 in
+ if exit_code2 <> 0 then
+ failwith ("Zchaff.call_zchaff: command "^command2^
+ " exited with code "^(string_of_int exit_code2));
+ (* import_cnf_trace reloc logfilename root last *)
+ (reloc, resfilename, logfilename, last)
+
+
+(* Build the problem that it may be understoof by zchaff *)
+
+let cnf_checker_modules = [ ["SMTCoq";"Trace";"Cnf_Checker"] ]
+
+let certif_ops = CoqTerms.make_certif_ops cnf_checker_modules
+let ccertif = gen_constant cnf_checker_modules "certif"
+let cCertif = gen_constant cnf_checker_modules "Certif"
+let cchecker_b_correct =
+ gen_constant cnf_checker_modules "checker_b_correct"
+let cchecker_b = gen_constant cnf_checker_modules "checker_b"
+let cchecker_eq_correct =
+ gen_constant cnf_checker_modules "checker_eq_correct"
+let cchecker_eq = gen_constant cnf_checker_modules "checker_eq"
+
+let build_body reify_atom reify_form l b (max_id, confl) =
+ let ntvar = mkName "t_var" in
+ let ntform = mkName "t_form" in
+ let nc = mkName "c" in
+ let tvar = Atom.interp_tbl reify_atom in
+ let _, tform = Form.interp_tbl reify_form in
+ let (tres,_) =
+ SmtTrace.to_coq Form.to_coq certif_ops confl in
+ let certif =
+ mklApp cCertif [|mkInt (max_id + 1);tres;mkInt (get_pos confl)|] in
+ let vtvar = Term.mkRel 3 in
+ let vtform = Term.mkRel 2 in
+ let vc = Term.mkRel 1 in
+ Term.mkLetIn (ntvar, tvar, mklApp carray [|Lazy.force cbool|],
+ Term.mkLetIn (ntform, tform, mklApp carray [|Lazy.force cform|],
+ Term.mkLetIn (nc, certif, Lazy.force ccertif,
+ mklApp cchecker_b_correct
+ [|vtvar; vtform; l; b; vc;
+ vm_cast_true (mklApp cchecker_b [|vtform;l;b;vc|])|])))
+
+
+let build_body_eq reify_atom reify_form l1 l2 l (max_id, confl) =
+ let ntvar = mkName "t_var" in
+ let ntform = mkName "t_form" in
+ let nc = mkName "c" in
+ let tvar = Atom.interp_tbl reify_atom in
+ let _, tform = Form.interp_tbl reify_form in
+ let (tres,_) =
+ SmtTrace.to_coq Form.to_coq certif_ops confl in
+ let certif =
+ mklApp cCertif [|mkInt (max_id + 1);tres;mkInt (get_pos confl)|] in
+ let vtvar = Term.mkRel 3 in
+ let vtform = Term.mkRel 2 in
+ let vc = Term.mkRel 1 in
+ Term.mkLetIn (ntvar, tvar, mklApp carray [|Lazy.force cbool|],
+ Term.mkLetIn (ntform, tform, mklApp carray [|Lazy.force cform|],
+ Term.mkLetIn (nc, certif, Lazy.force ccertif,
+ mklApp cchecker_eq_correct
+ [|vtvar; vtform; l1; l2; l; vc;
+ vm_cast_true (mklApp cchecker_eq [|vtform;l1;l2;l;vc|])|])))
+
+let get_arguments concl =
+ let f, args = Term.decompose_app concl in
+ match args with
+ | [ty;a;b] when f = Lazy.force ceq && ty = Lazy.force cbool -> a, b
+ | [a] when f = Lazy.force cis_true -> a, Lazy.force ctrue
+ | _ -> failwith ("Zchaff.tactic :can only deal with equality over bool")
+
+
+(* Check that the result is Unsat, otherwise raise a model *)
+
+exception Sat of int list
+exception Finished
+
+let input_int file =
+ let rec input_int acc flag =
+ let c = input_char file in
+ if c = '-' then
+ input_int acc true
+ else if c = '0' then
+ input_int (10*acc) flag
+ else if c = '1' then
+ input_int (10*acc+1) flag
+ else if c = '2' then
+ input_int (10*acc+2) flag
+ else if c = '3' then
+ input_int (10*acc+3) flag
+ else if c = '4' then
+ input_int (10*acc+4) flag
+ else if c = '5' then
+ input_int (10*acc+5) flag
+ else if c = '6' then
+ input_int (10*acc+6) flag
+ else if c = '7' then
+ input_int (10*acc+7) flag
+ else if c = '8' then
+ input_int (10*acc+8) flag
+ else if c = '9' then
+ input_int (10*acc+9) flag
+ else if c = ' ' then
+ if flag then -acc else acc
+ else raise Finished in
+ input_int 0 false
+
+let check_unsat filename =
+ let f = open_in filename in
+ let rec get_model acc =
+ try
+ let i = input_int f in
+ get_model (i::acc)
+ with
+ | Finished -> acc in
+ try
+ while true do
+ let l = input_line f in
+ let n = String.length l in
+ if n >= 8 && String.sub l 0 8 = "Instance" then
+ if n >= 20 && String.sub l 9 11 = "Satisfiable" then
+ raise (Sat (get_model []))
+ else
+ raise End_of_file
+ done
+ with
+ | End_of_file -> close_in f
+
+
+(* Pre-process the proof given by zchaff *)
+
+let make_proof pform_tbl atom_tbl env reify_form l =
+ let fl = Form.flatten reify_form l in
+ let root = SmtTrace.mkRootV [l] in
+ let _ =
+ if Form.equal l fl then Cnf.make_cnf reify_form root
+ else
+ let first_c = SmtTrace.mkOther (ImmFlatten(root,fl)) (Some [fl]) in
+ SmtTrace.link root first_c;
+ Cnf.make_cnf reify_form first_c in
+ let (reloc, resfilename, logfilename, last) =
+ call_zchaff (Form.nvars reify_form) root in
+ (try check_unsat resfilename with
+ | Sat model -> Errors.error (List.fold_left (fun acc i ->
+ let index = if i > 0 then i-1 else -i-1 in
+ let ispos = i > 0 in
+ try (
+ let f = pform_tbl.(index) in
+ match f with
+ | Fatom a ->
+ let t = atom_tbl.(a) in
+ let value = if ispos then " = true" else " = false" in
+ acc^" "^(Pp.string_of_ppcmds (Printer.pr_constr_env env t))^value
+ | Fapp _ -> acc
+ ) with | Invalid_argument _ -> acc (* Because cnf computation does not put the new formulas in the table... Perhaps it should? *)
+ ) "zchaff found a counterexample:\n" model)
+ );
+ import_cnf_trace reloc logfilename root last
+
+
+(* The whole tactic *)
+
+let tactic gl =
+ SmtTrace.clear ();
+
+ let env = Tacmach.pf_env gl in
+ (* let sigma = Tacmach.project gl in *)
+ let t = Tacmach.pf_concl gl in
+
+ let (forall_let, concl) = Term.decompose_prod_assum t in
+ let a, b = get_arguments concl in
+ let reify_atom = Atom.create () in
+ let reify_form = Form.create () in
+ let body =
+ if (b = Lazy.force ctrue || b = Lazy.force cfalse) then
+ let l = Form.of_coq (Atom.get reify_atom) reify_form a in
+ let l' = if b = Lazy.force ctrue then Form.neg l else l in
+ let atom_tbl = Atom.atom_tbl reify_atom in
+ let pform_tbl = Form.pform_tbl reify_form in
+ let max_id_confl = make_proof pform_tbl atom_tbl (Environ.push_rel_context forall_let env) reify_form l' in
+ build_body reify_atom reify_form (Form.to_coq l) b max_id_confl
+ else
+ let l1 = Form.of_coq (Atom.get reify_atom) reify_form a in
+ let l2 = Form.of_coq (Atom.get reify_atom) reify_form b in
+ let l = Form.neg (Form.get reify_form (Fapp(Fiff,[|l1;l2|]))) in
+ let atom_tbl = Atom.atom_tbl reify_atom in
+ let pform_tbl = Form.pform_tbl reify_form in
+ let max_id_confl = make_proof pform_tbl atom_tbl (Environ.push_rel_context forall_let env) reify_form l in
+ build_body_eq reify_atom reify_form
+ (Form.to_coq l1) (Form.to_coq l2) (Form.to_coq l) max_id_confl in
+ let compose_lam_assum forall_let body =
+ List.fold_left (fun t rd -> Term.mkLambda_or_LetIn rd t) body forall_let in
+ let res = compose_lam_assum forall_let body in
+ Tactics.exact_no_check res gl
diff --git a/src/zchaff/zchaffParser.ml b/src/zchaff/zchaffParser.ml
new file mode 100644
index 0000000..c5bcb09
--- /dev/null
+++ b/src/zchaff/zchaffParser.ml
@@ -0,0 +1,161 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+open SatParser
+open SmtForm
+open SmtCertif
+open SmtTrace
+
+let _CL = "CL:"
+let _INF = "<="
+let _VAR = "VAR:"
+let _L = "L:"
+let _V = "V:"
+let _A = "A:"
+let _LITS = "Lits:"
+let _CONF = "CONF:"
+let _EQ = "=="
+
+(** Parsing of zchaff proof *)
+
+let alloc_res last c1 c2 tail =
+ let c = mkRes c1 c2 tail in
+ link last c;
+ c
+
+let rec parse_tailres reloc lb =
+ if is_start_int lb then
+ let cl_id = Hashtbl.find reloc (input_int lb) in
+ cl_id :: parse_tailres reloc lb
+ else []
+
+let parse_resolution reloc lb last =
+ let id = input_blank_int lb in
+ blank_match_string lb _INF;
+ let c1 = Hashtbl.find reloc (input_blank_int lb) in
+ let c2 = Hashtbl.find reloc (input_blank_int lb) in
+ let tl = parse_tailres reloc lb in
+ let c = alloc_res last c1 c2 tl in
+ Hashtbl.add reloc id c;
+ c
+
+let parse_CL reloc lb last =
+ let last = ref last in
+ while blank_check_string lb _CL do
+ last := parse_resolution reloc lb !last
+ done;
+ !last
+
+
+(* Parsing of the VAR and CONF part *)
+
+let var_of_lit l = l lsr 1
+
+type var_key =
+ | Var of int
+ | Level of int
+
+type 'hform var_decl = {
+ var : int;
+ ante : 'hform clause;
+ ante_val : int list;
+ mutable vclause : 'hform clause option
+}
+
+type 'hform parse_var_info = (var_key, 'hform var_decl) Hashtbl.t
+
+let var_of_lit l = l lsr 1
+
+let parse_zclause lb =
+ let zc = ref [var_of_lit (input_blank_int lb)] in
+ while is_start_int lb do
+ zc := var_of_lit (input_int lb) :: !zc;
+ done;
+ !zc
+
+let parse_VAR_CONF reloc lb last =
+ let max_level = ref (-1) in
+ let vartbl = Hashtbl.create 100 in
+ (* parsing of the VAR part *)
+ while blank_check_string lb _VAR do
+ let x = input_blank_int lb in
+ blank_match_string lb _L;
+ let lv = input_blank_int lb in
+ blank_match_string lb _V;
+ let _ = input_blank_int lb in
+ blank_match_string lb _A;
+ let ante = Hashtbl.find reloc (input_blank_int lb) in
+ blank_match_string lb _LITS;
+ let ante_val = parse_zclause lb in
+ max_level := max !max_level lv;
+ let vd = { var = x; ante = ante; ante_val = ante_val; vclause = None } in
+ Hashtbl.add vartbl (Var x) vd;
+ Hashtbl.add vartbl (Level lv) vd;
+ done;
+ (* Adding the resolution *)
+ let rec build_res0 l =
+ match l with
+ | [] -> []
+ | y :: l ->
+ let yd =
+ try Hashtbl.find vartbl (Var y)
+ with Not_found ->
+ Printf.printf "Var %i not found.\n" y;raise Not_found in
+ match yd.vclause with
+ | Some cy -> cy :: build_res0 l
+ | _ -> assert false in
+ let rec build_res1 x l =
+ match l with
+ | [] -> assert false
+ | y :: l ->
+ if x = y then build_res0 l
+ else
+ let yd =
+ try Hashtbl.find vartbl (Var y)
+ with Not_found ->
+ Printf.printf "Var %i not found.\n" y;raise Not_found in
+ match yd.vclause with
+ | Some cy -> cy :: build_res1 x l
+ | _ -> assert false in
+ let last = ref last in
+ for lv = 0 to !max_level do
+ try
+ let vd = Hashtbl.find vartbl (Level lv) in
+ let c =
+ match build_res1 vd.var vd.ante_val with
+ | [] -> vd.ante
+ | c2::tl ->
+ last := alloc_res !last vd.ante c2 tl; !last in
+ vd.vclause <- Some c;
+ with Not_found -> ()
+ done;
+ (* parsing of the CONF *)
+ blank_match_string lb _CONF;
+ let conf =
+ let id = input_blank_int lb in
+ Hashtbl.find reloc id in
+ blank_match_string lb _EQ;
+ let conf_val = parse_zclause lb in
+ match build_res0 conf_val with
+ | [] -> assert false
+ | c2::tl -> alloc_res !last conf c2 tl
+
+
+let parse_proof reloc filename last =
+ let lb = open_file "Proof" filename in
+ let last = parse_CL reloc lb last in
+ let last = parse_VAR_CONF reloc lb last in
+ close lb;
+ last
+
diff --git a/unit-tests/Makefile b/unit-tests/Makefile
new file mode 100644
index 0000000..4c29362
--- /dev/null
+++ b/unit-tests/Makefile
@@ -0,0 +1,32 @@
+ZCHAFFSRC=$(wildcard sat*.cnf) hole4.cnf cmu-bmc-barrel6.cnf velev-sss-1.0-05.cnf
+VERITSRC=$(wildcard sat*.smt2) hole4.smt2 $(wildcard uf*.smt2) $(wildcard lia*.smt2) $(wildcard let*.smt2)
+ZCHAFFLOG=$(ZCHAFFSRC:.cnf=.zlog)
+VERITLOG=$(VERITSRC:.smt2=.vtlog)
+OBJ=$(ZCHAFFLOG) $(VERITLOG)
+
+COQLIBS?= -R ../src SMTCoq
+OPT?=
+COQFLAGS?=-q $(OPT) $(COQLIBS) $(OTHERFLAGS) $(COQ_XML)
+COQC?=$(COQBIN)coqc
+
+
+all: $(OBJ) Tests.vo
+
+
+logs: $(OBJ)
+
+
+%.zlog: %.cnf
+ ./runzchaff.sh $<
+
+
+%.vtlog: %.smt2
+ ./runverit.sh $<
+
+
+%.vo %.glob: %.v
+ $(COQC) $(COQDEBUG) $(COQFLAGS) $*
+
+
+clean:
+ rm -rf *~ *.zlog *.vtlog
diff --git a/unit-tests/Tests.v b/unit-tests/Tests.v
new file mode 100644
index 0000000..5f75204
--- /dev/null
+++ b/unit-tests/Tests.v
@@ -0,0 +1,1273 @@
+(* Add LoadPath ".." as SMTCoq. *)
+Require Import SMTCoq.
+Require Import Bool PArray Int63 List ZArith.
+
+Local Open Scope int63_scope.
+
+
+(* zChaff vernacular commands *)
+
+Time Zchaff_Checker "sat1.cnf" "sat1.zlog".
+Time Zchaff_Checker "sat2.cnf" "sat2.zlog".
+Time Zchaff_Checker "sat3.cnf" "sat3.zlog".
+Time Zchaff_Checker "sat5.cnf" "sat5.zlog".
+Time Zchaff_Checker "sat6.cnf" "sat6.zlog".
+Time Zchaff_Checker "sat7.cnf" "sat7.zlog".
+Time Zchaff_Checker "hole4.cnf" "hole4.zlog".
+Time Zchaff_Checker "cmu-bmc-barrel6.cnf" "cmu-bmc-barrel6.zlog".
+Time Zchaff_Checker "velev-sss-1.0-05.cnf" "velev-sss-1.0-05.zlog".
+
+
+Time Zchaff_Theorem sat1 "sat1.cnf" "sat1.zlog".
+Time Zchaff_Theorem sat2 "sat2.cnf" "sat2.zlog".
+Time Zchaff_Theorem sat3 "sat3.cnf" "sat3.zlog".
+Time Zchaff_Theorem sat5 "sat5.cnf" "sat5.zlog".
+Time Zchaff_Theorem sat6 "sat6.cnf" "sat6.zlog".
+Time Zchaff_Theorem sat7 "sat7.cnf" "sat7.zlog".
+Time Zchaff_Theorem hole4 "hole4.cnf" "hole4.zlog".
+
+
+Parse_certif_zchaff d1 t1 "sat1.cnf" "sat1.zlog".
+Compute Sat_Checker.checker d1 t1.
+
+Parse_certif_zchaff d2 t2 "sat2.cnf" "sat2.zlog".
+Compute Sat_Checker.checker d2 t2.
+
+Parse_certif_zchaff d3 t3 "sat3.cnf" "sat3.zlog".
+Compute Sat_Checker.checker d3 t3.
+
+Parse_certif_zchaff d5 t5 "sat5.cnf" "sat5.zlog".
+Compute Sat_Checker.checker d5 t5.
+
+Parse_certif_zchaff d6 t6 "sat6.cnf" "sat6.zlog".
+Compute Sat_Checker.checker d6 t6.
+
+Parse_certif_zchaff d7 t7 "sat7.cnf" "sat7.zlog".
+Compute Sat_Checker.checker d7 t7.
+
+Parse_certif_zchaff dhole4 thole4 "hole4.cnf" "hole4.zlog".
+Compute Sat_Checker.checker dhole4 thole4.
+
+Parse_certif_zchaff dcmubmcbarrel6 tcmubmcbarrel6 "cmu-bmc-barrel6.cnf" "cmu-bmc-barrel6.zlog".
+Compute Sat_Checker.checker dcmubmcbarrel6 tcmubmcbarrel6.
+
+Parse_certif_zchaff dvelevsss1005 tvelevsss1005 "velev-sss-1.0-05.cnf" "velev-sss-1.0-05.zlog".
+Compute Sat_Checker.checker dvelevsss1005 tvelevsss1005.
+
+
+(* zChaff tactic *)
+
+Goal forall a, a || negb a.
+ zchaff.
+Qed.
+
+Goal forall a, negb (a || negb a) = false.
+ zchaff.
+Qed.
+
+Goal forall a, (a && negb a) = false.
+ zchaff.
+Qed.
+
+Goal forall a, negb (a && negb a).
+ zchaff.
+Qed.
+
+Goal forall a, implb a a.
+ zchaff.
+Qed.
+
+Goal forall a, negb (implb a a) = false.
+ zchaff.
+Qed.
+
+Goal forall a , (xorb a a) || negb (xorb a a).
+ zchaff.
+Qed.
+Print Unnamed_thm5.
+
+Goal forall a, (a||negb a) || negb (a||negb a).
+ zchaff.
+Qed.
+
+Goal true.
+ zchaff.
+Qed.
+
+Goal negb false.
+ zchaff.
+Qed.
+
+Goal forall a, Bool.eqb a a.
+Proof.
+ zchaff.
+Qed.
+
+Goal forall (a:bool), a = a.
+ zchaff.
+Qed.
+
+
+(* sat2.smt *)
+(* ((a ∧ b) ∨ (b ∧ c)) ∧ ¬b = ⊥ *)
+
+Goal forall a b c, (((a && b) || (b && c)) && (negb b)) = false.
+Proof.
+ zchaff.
+Qed.
+
+
+(* sat3.smt *)
+(* (a ∨ a) ∧ ¬a = ⊥ *)
+
+Goal forall a, ((a || a) && (negb a)) = false.
+Proof.
+ zchaff.
+Qed.
+
+
+(* sat4.smt *)
+(* ¬(a ∨ ¬a) = ⊥ *)
+
+Goal forall a, (negb (a || (negb a))) = false.
+Proof.
+ zchaff.
+Qed.
+
+
+(* sat5.smt *)
+(* (a ∨ b ∨ c) ∧ (¬a ∨ ¬b ∨ ¬c) ∧ (¬a ∨ b) ∧ (¬b ∨ c) ∧ (¬c ∨ a) = ⊥ *)
+
+Goal forall a b c,
+ (a || b || c) && ((negb a) || (negb b) || (negb c)) && ((negb a) || b) && ((negb b) || c) && ((negb c) || a) = false.
+Proof.
+ zchaff.
+Qed.
+
+
+(* Le même, mais où a, b et c sont des termes concrets *)
+
+Goal forall i j k,
+ ((i == j) || (j == k) || (k == i)) && ((negb (i == j)) || (negb (j == k)) || (negb (k == i))) && ((negb (i == j)) || (j == k)) && ((negb (j == k)) || (k == i)) && ((negb (k == i)) || (i == j)) = false.
+Proof.
+ zchaff.
+Qed.
+
+Goal forall i j k,
+ let a := i == j in
+ let b := j == k in
+ let c := k == i in
+ (a || b || c) && ((negb a) || (negb b) || (negb c)) && ((negb a) || b) && ((negb b) || c) && ((negb c) || a) = false.
+Proof.
+ zchaff.
+Qed.
+
+
+(* sat6.smt *)
+(* (a ∧ b) ∧ (c ∨ d) ∧ ¬(c ∨ (a ∧ b ∧ d)) = ⊥ *)
+
+Goal forall a b c d, ((a && b) && (c || d) && (negb (c || (a && b && d)))) = false.
+Proof.
+ zchaff.
+Qed.
+
+
+(* sat7.smt *)
+(* a ∧ b ∧ c ∧ (¬a ∨ ¬b ∨ d) ∧ (¬d ∨ ¬c) = ⊥ *)
+
+Goal forall a b c d, (a && b && c && ((negb a) || (negb b) || d) && ((negb d) || (negb c))) = false.
+Proof.
+ zchaff.
+Qed.
+
+
+(* Other connectors *)
+
+Goal (false || true) && false = false.
+Proof.
+ zchaff.
+Qed.
+
+
+Goal negb true = false.
+Proof.
+ zchaff.
+Qed.
+
+
+Goal false = false.
+Proof.
+ zchaff.
+Qed.
+
+
+Goal forall x y, Bool.eqb (xorb x y) ((x && (negb y)) || ((negb x) && y)).
+Proof.
+ zchaff.
+Qed.
+
+
+Goal forall x y, Bool.eqb (implb x y) ((x && y) || (negb x)).
+Proof.
+ zchaff.
+Qed.
+
+
+Goal forall x y z, Bool.eqb (ifb x y z) ((x && y) || ((negb x) && z)).
+Proof.
+ zchaff.
+Qed.
+
+
+(* Multiple negations *)
+
+Goal forall a, orb a (negb (negb (negb a))) = true.
+Proof.
+ zchaff.
+Qed.
+
+
+(* Polarities *)
+
+Goal forall a b, andb (orb a b) (negb (orb a b)) = false.
+Proof.
+ zchaff.
+Qed.
+
+
+Goal forall a b, andb (orb a b) (andb (negb a) (negb b)) = false.
+Proof.
+ zchaff.
+Qed.
+
+
+(* Pigeon hole: 4 holes, 5 pigeons. xij stands for "pidgeon i goes to
+ hole j". *)
+
+Goal forall x11 x12 x13 x14 x15 x21 x22 x23 x24 x25 x31 x32 x33 x34 x35 x41 x42 x43 x44 x45, (
+ (orb (negb x11) (negb x21)) &&
+ (orb (negb x11) (negb x31)) &&
+ (orb (negb x11) (negb x41)) &&
+ (orb (negb x21) (negb x31)) &&
+ (orb (negb x21) (negb x41)) &&
+ (orb (negb x31) (negb x41)) &&
+
+ (orb (negb x12) (negb x22)) &&
+ (orb (negb x12) (negb x32)) &&
+ (orb (negb x12) (negb x42)) &&
+ (orb (negb x22) (negb x32)) &&
+ (orb (negb x22) (negb x42)) &&
+ (orb (negb x32) (negb x42)) &&
+
+ (orb (negb x13) (negb x23)) &&
+ (orb (negb x13) (negb x33)) &&
+ (orb (negb x13) (negb x43)) &&
+ (orb (negb x23) (negb x33)) &&
+ (orb (negb x23) (negb x43)) &&
+ (orb (negb x33) (negb x43)) &&
+
+ (orb (negb x14) (negb x24)) &&
+ (orb (negb x14) (negb x34)) &&
+ (orb (negb x14) (negb x44)) &&
+ (orb (negb x24) (negb x34)) &&
+ (orb (negb x24) (negb x44)) &&
+ (orb (negb x34) (negb x44)) &&
+
+ (orb (negb x15) (negb x25)) &&
+ (orb (negb x15) (negb x35)) &&
+ (orb (negb x15) (negb x45)) &&
+ (orb (negb x25) (negb x35)) &&
+ (orb (negb x25) (negb x45)) &&
+ (orb (negb x35) (negb x45)) &&
+
+
+ (orb (negb x11) (negb x12)) &&
+ (orb (negb x11) (negb x13)) &&
+ (orb (negb x11) (negb x14)) &&
+ (orb (negb x11) (negb x15)) &&
+ (orb (negb x12) (negb x13)) &&
+ (orb (negb x12) (negb x14)) &&
+ (orb (negb x12) (negb x15)) &&
+ (orb (negb x13) (negb x14)) &&
+ (orb (negb x13) (negb x15)) &&
+ (orb (negb x14) (negb x15)) &&
+
+ (orb (negb x21) (negb x22)) &&
+ (orb (negb x21) (negb x23)) &&
+ (orb (negb x21) (negb x24)) &&
+ (orb (negb x21) (negb x25)) &&
+ (orb (negb x22) (negb x23)) &&
+ (orb (negb x22) (negb x24)) &&
+ (orb (negb x22) (negb x25)) &&
+ (orb (negb x23) (negb x24)) &&
+ (orb (negb x23) (negb x25)) &&
+ (orb (negb x24) (negb x25)) &&
+
+ (orb (negb x31) (negb x32)) &&
+ (orb (negb x31) (negb x33)) &&
+ (orb (negb x31) (negb x34)) &&
+ (orb (negb x31) (negb x35)) &&
+ (orb (negb x32) (negb x33)) &&
+ (orb (negb x32) (negb x34)) &&
+ (orb (negb x32) (negb x35)) &&
+ (orb (negb x33) (negb x34)) &&
+ (orb (negb x33) (negb x35)) &&
+ (orb (negb x34) (negb x35)) &&
+
+ (orb (negb x41) (negb x42)) &&
+ (orb (negb x41) (negb x43)) &&
+ (orb (negb x41) (negb x44)) &&
+ (orb (negb x41) (negb x45)) &&
+ (orb (negb x42) (negb x43)) &&
+ (orb (negb x42) (negb x44)) &&
+ (orb (negb x42) (negb x45)) &&
+ (orb (negb x43) (negb x44)) &&
+ (orb (negb x43) (negb x45)) &&
+ (orb (negb x44) (negb x45)) &&
+
+
+ (orb (orb (orb x11 x21) x31) x41) &&
+ (orb (orb (orb x12 x22) x32) x42) &&
+ (orb (orb (orb x13 x23) x33) x43) &&
+ (orb (orb (orb x14 x24) x34) x44) &&
+ (orb (orb (orb x15 x25) x35) x45)) = false.
+Proof.
+ zchaff.
+Qed.
+
+
+(* Counter examples *)
+
+(*
+Goal forall x, x && (negb x).
+Proof.
+ zchaff.
+Abort.
+
+Goal forall x y, (implb (implb x y) (implb y x)).
+Proof.
+ zchaff.
+Abort.
+
+(* Pigeon hole: 4 holes, 4 pigeons. xij stands for "pidgeon i goes to
+ hole j". *)
+
+Goal forall x11 x12 x13 x14 x21 x22 x23 x24 x31 x32 x33 x34 x41 x42 x43 x44, (
+ (orb (negb x11) (negb x21)) &&
+ (orb (negb x11) (negb x31)) &&
+ (orb (negb x11) (negb x41)) &&
+ (orb (negb x21) (negb x31)) &&
+ (orb (negb x21) (negb x41)) &&
+ (orb (negb x31) (negb x41)) &&
+
+ (orb (negb x12) (negb x22)) &&
+ (orb (negb x12) (negb x32)) &&
+ (orb (negb x12) (negb x42)) &&
+ (orb (negb x22) (negb x32)) &&
+ (orb (negb x22) (negb x42)) &&
+ (orb (negb x32) (negb x42)) &&
+
+ (orb (negb x13) (negb x23)) &&
+ (orb (negb x13) (negb x33)) &&
+ (orb (negb x13) (negb x43)) &&
+ (orb (negb x23) (negb x33)) &&
+ (orb (negb x23) (negb x43)) &&
+ (orb (negb x33) (negb x43)) &&
+
+ (orb (negb x14) (negb x24)) &&
+ (orb (negb x14) (negb x34)) &&
+ (orb (negb x14) (negb x44)) &&
+ (orb (negb x24) (negb x34)) &&
+ (orb (negb x24) (negb x44)) &&
+ (orb (negb x34) (negb x44)) &&
+
+
+ (orb (negb x11) (negb x12)) &&
+ (orb (negb x11) (negb x13)) &&
+ (orb (negb x11) (negb x14)) &&
+ (orb (negb x12) (negb x13)) &&
+ (orb (negb x12) (negb x14)) &&
+ (orb (negb x13) (negb x14)) &&
+
+ (orb (negb x21) (negb x22)) &&
+ (orb (negb x21) (negb x23)) &&
+ (orb (negb x21) (negb x24)) &&
+ (orb (negb x22) (negb x23)) &&
+ (orb (negb x22) (negb x24)) &&
+ (orb (negb x23) (negb x24)) &&
+
+ (orb (negb x31) (negb x32)) &&
+ (orb (negb x31) (negb x33)) &&
+ (orb (negb x31) (negb x34)) &&
+ (orb (negb x32) (negb x33)) &&
+ (orb (negb x32) (negb x34)) &&
+ (orb (negb x33) (negb x34)) &&
+
+ (orb (negb x41) (negb x42)) &&
+ (orb (negb x41) (negb x43)) &&
+ (orb (negb x41) (negb x44)) &&
+ (orb (negb x42) (negb x43)) &&
+ (orb (negb x42) (negb x44)) &&
+ (orb (negb x43) (negb x44)) &&
+
+
+ (orb (orb (orb x11 x21) x31) x41) &&
+ (orb (orb (orb x12 x22) x32) x42) &&
+ (orb (orb (orb x13 x23) x33) x43) &&
+ (orb (orb (orb x14 x24) x34) x44)) = false.
+Proof.
+ zchaff.
+Abort.
+*)
+
+
+(* veriT vernacular commands *)
+
+Section Checker_Sat1.
+ Verit_Checker "sat1.smt2" "sat1.vtlog".
+End Checker_Sat1.
+
+Section Checker_Sat2.
+ Verit_Checker "sat2.smt2" "sat2.vtlog".
+End Checker_Sat2.
+
+Section Checker_Sat3.
+ Verit_Checker "sat3.smt2" "sat3.vtlog".
+End Checker_Sat3.
+
+Section Checker_Sat4.
+ Verit_Checker "sat4.smt2" "sat4.vtlog".
+End Checker_Sat4.
+
+Section Checker_Sat5.
+ Verit_Checker "sat5.smt2" "sat5.vtlog".
+End Checker_Sat5.
+
+Section Checker_Sat6.
+ Verit_Checker "sat6.smt2" "sat6.vtlog".
+End Checker_Sat6.
+
+Section Checker_Sat7.
+ Verit_Checker "sat7.smt2" "sat7.vtlog".
+End Checker_Sat7.
+
+Section Checker_Sat8.
+ Verit_Checker "sat8.smt2" "sat8.vtlog".
+End Checker_Sat8.
+
+Section Checker_Sat9.
+ Verit_Checker "sat9.smt2" "sat9.vtlog".
+End Checker_Sat9.
+(*
+Section Checker_Sat10.
+ Verit_Checker "sat10.smt2" "sat10.vtlog".
+End Checker_Sat10.
+*)
+Section Checker_Sat11.
+ Verit_Checker "sat11.smt2" "sat11.vtlog".
+End Checker_Sat11.
+
+Section Checker_Sat12.
+ Verit_Checker "sat12.smt2" "sat12.vtlog".
+End Checker_Sat12.
+
+Section Checker_Sat13.
+ Verit_Checker "sat13.smt2" "sat13.vtlog".
+End Checker_Sat13.
+
+Section Checker_Hole4.
+ Verit_Checker "hole4.smt2" "hole4.vtlog".
+End Checker_Hole4.
+
+Section Checker_Uf1.
+ Verit_Checker "uf1.smt2" "uf1.vtlog".
+End Checker_Uf1.
+
+Section Checker_Uf2.
+ Verit_Checker "uf2.smt2" "uf2.vtlog".
+End Checker_Uf2.
+
+Section Checker_Uf3.
+ Verit_Checker "uf3.smt2" "uf3.vtlog".
+End Checker_Uf3.
+
+Section Checker_Uf4.
+ Verit_Checker "uf4.smt2" "uf4.vtlog".
+End Checker_Uf4.
+
+Section Checker_Uf5.
+ Verit_Checker "uf5.smt2" "uf5.vtlog".
+End Checker_Uf5.
+
+Section Checker_Uf6.
+ Verit_Checker "uf6.smt2" "uf6.vtlog".
+End Checker_Uf6.
+
+Section Checker_Uf7.
+ Verit_Checker "uf7.smt2" "uf7.vtlog".
+End Checker_Uf7.
+
+Section Checker_Lia1.
+ Verit_Checker "lia1.smt2" "lia1.vtlog".
+End Checker_Lia1.
+
+Section Checker_Lia2.
+ Verit_Checker "lia2.smt2" "lia2.vtlog".
+End Checker_Lia2.
+
+Section Checker_Lia3.
+ Verit_Checker "lia3.smt2" "lia3.vtlog".
+End Checker_Lia3.
+
+Section Checker_Lia4.
+ Verit_Checker "lia4.smt2" "lia4.vtlog".
+End Checker_Lia4.
+
+Section Checker_Lia5.
+ Verit_Checker "lia5.smt2" "lia5.vtlog".
+End Checker_Lia5.
+
+Section Checker_Lia6.
+ Verit_Checker "lia6.smt2" "lia6.vtlog".
+End Checker_Lia6.
+
+Section Checker_Lia7.
+ Verit_Checker "lia7.smt2" "lia7.vtlog".
+End Checker_Lia7.
+
+(* Section Checker_Let1. *)
+(* Verit_Checker "let1.smt2" "let1.vtlog". *)
+(* End Checker_Let1. *)
+
+(* Section Checker_Let2. *)
+(* Verit_Checker "let2.smt2" "let2.vtlog". *)
+(* End Checker_Let2. *)
+
+
+Section Sat1.
+ Parse_certif_verit t_i1 t_func1 t_atom1 t_form1 root1 used_roots1 trace1 "sat1.smt2" "sat1.vtlog".
+ Compute Euf_Checker.checker t_i1 t_func1 t_atom1 t_form1 root1 used_roots1 trace1.
+End Sat1.
+
+Section Sat2.
+ Parse_certif_verit t_i2 t_func2 t_atom2 t_form2 root2 used_roots2 trace2 "sat2.smt2" "sat2.vtlog".
+ Compute Euf_Checker.checker t_i2 t_func2 t_atom2 t_form2 root2 used_roots2 trace2.
+End Sat2.
+
+Section Sat3.
+ Parse_certif_verit t_i3 t_func3 t_atom3 t_form3 root3 used_roots3 trace3 "sat3.smt2" "sat3.vtlog".
+ Compute Euf_Checker.checker t_i3 t_func3 t_atom3 t_form3 root3 used_roots3 trace3.
+End Sat3.
+
+Section Sat4.
+ Parse_certif_verit t_i4 t_func4 t_atom4 t_form4 root4 used_roots4 trace4 "sat4.smt2" "sat4.vtlog".
+ Compute Euf_Checker.checker t_i4 t_func4 t_atom4 t_form4 root4 used_roots4 trace4.
+End Sat4.
+
+Section Sat5.
+ Parse_certif_verit t_i5 t_func5 t_atom5 t_form5 root5 used_roots5 trace5 "sat5.smt2" "sat5.vtlog".
+ Compute Euf_Checker.checker t_i5 t_func5 t_atom5 t_form5 root5 used_roots5 trace5.
+End Sat5.
+
+Section Sat6.
+ Parse_certif_verit t_i6 t_func6 t_atom6 t_form6 root6 used_roots6 trace6 "sat6.smt2" "sat6.vtlog".
+ Compute Euf_Checker.checker t_i6 t_func6 t_atom6 t_form6 root6 used_roots6 trace6.
+End Sat6.
+
+Section Sat7.
+ Parse_certif_verit t_i7 t_func7 t_atom7 t_form7 root7 used_roots7 trace7 "sat7.smt2" "sat7.vtlog".
+ Compute Euf_Checker.checker t_i7 t_func7 t_atom7 t_form7 root7 used_roots7 trace7.
+End Sat7.
+
+Section Sat8.
+ Parse_certif_verit t_i8 t_func8 t_atom8 t_form8 root8 used_roots8 trace8 "sat8.smt2" "sat8.vtlog".
+ Compute Euf_Checker.checker t_i8 t_func8 t_atom8 t_form8 root8 used_roots8 trace8.
+End Sat8.
+
+Section Sat9.
+ Parse_certif_verit t_i9 t_func9 t_atom9 t_form9 root9 used_roots9 trace9 "sat9.smt2" "sat9.vtlog".
+ Compute Euf_Checker.checker t_i9 t_func9 t_atom9 t_form9 root9 used_roots9 trace9.
+End Sat9.
+(*
+Section Sat10.
+ Parse_certif_verit t_i10 t_func10 t_atom10 t_form10 root10 used_roots10 trace10 "sat10.smt2" "sat10.vtlog".
+ Compute Euf_Checker.checker t_i10 t_func10 t_atom10 t_form10 root10 used_roots10 trace10.
+End Sat10.
+*)
+Section Sat11.
+ Parse_certif_verit t_i11 t_func11 t_atom11 t_form11 root11 used_roots11 trace11 "sat11.smt2" "sat11.vtlog".
+ Compute Euf_Checker.checker t_i11 t_func11 t_atom11 t_form11 root11 used_roots11 trace11.
+End Sat11.
+
+Section Sat12.
+ Parse_certif_verit t_i12 t_func12 t_atom12 t_form12 root12 used_roots12 trace12 "sat12.smt2" "sat12.vtlog".
+ Compute Euf_Checker.checker t_i12 t_func12 t_atom12 t_form12 root12 used_roots12 trace12.
+End Sat12.
+
+Section Hole4.
+ Parse_certif_verit t_i_hole4 t_func_hole4 t_atom_hole4 t_form_hole4 root_hole4 used_roots_hole4 trace_hole4 "hole4.smt2" "hole4.vtlog".
+ Compute Euf_Checker.checker t_i_hole4 t_func_hole4 t_atom_hole4 t_form_hole4 root_hole4 used_roots_hole4 trace_hole4.
+End Hole4.
+
+Section Uf1.
+ Parse_certif_verit t_i_uf1 t_func_uf1 t_atom_uf1 t_form_uf1 root_uf1 used_roots_uf1 trace_uf1 "uf1.smt2" "uf1.vtlog".
+ Compute Euf_Checker.checker t_i_uf1 t_func_uf1 t_atom_uf1 t_form_uf1 root_uf1 used_roots_uf1 trace_uf1.
+End Uf1.
+
+Section Uf2.
+ Parse_certif_verit t_i_uf2 t_func_uf2 t_atom_uf2 t_form_uf2 root_uf2 used_roots_uf2 trace_uf2 "uf2.smt2" "uf2.vtlog".
+ Compute Euf_Checker.checker t_i_uf2 t_func_uf2 t_atom_uf2 t_form_uf2 root_uf2 used_roots_uf2 trace_uf2.
+End Uf2.
+
+Section Uf3.
+ Parse_certif_verit t_i_uf3 t_func_uf3 t_atom_uf3 t_form_uf3 root_uf3 used_roots_uf3 trace_uf3 "uf3.smt2" "uf3.vtlog".
+ Compute Euf_Checker.checker t_i_uf3 t_func_uf3 t_atom_uf3 t_form_uf3 root_uf3 used_roots_uf3 trace_uf3.
+End Uf3.
+
+Section Uf4.
+ Parse_certif_verit t_i_uf4 t_func_uf4 t_atom_uf4 t_form_uf4 root_uf4 used_roots_uf4 trace_uf4 "uf4.smt2" "uf4.vtlog".
+ Compute Euf_Checker.checker t_i_uf4 t_func_uf4 t_atom_uf4 t_form_uf4 root_uf4 used_roots_uf4 trace_uf4.
+End Uf4.
+
+Section Uf5.
+ Parse_certif_verit t_i_uf5 t_func_uf5 t_atom_uf5 t_form_uf5 root_uf5 used_roots_uf5 trace_uf5 "uf5.smt2" "uf5.vtlog".
+ Compute Euf_Checker.checker t_i_uf5 t_func_uf5 t_atom_uf5 t_form_uf5 root_uf5 used_roots_uf5 trace_uf5.
+End Uf5.
+
+Section Uf6.
+ Parse_certif_verit t_i_uf6 t_func_uf6 t_atom_uf6 t_form_uf6 root_uf6 used_roots_uf6 trace_uf6 "uf6.smt2" "uf6.vtlog".
+ Compute Euf_Checker.checker t_i_uf6 t_func_uf6 t_atom_uf6 t_form_uf6 root_uf6 used_roots_uf6 trace_uf6.
+End Uf6.
+
+Section Uf7.
+ Parse_certif_verit t_i_uf7 t_func_uf7 t_atom_uf7 t_form_uf7 root_uf7 used_roots_uf7 trace_uf7 "uf7.smt2" "uf7.vtlog".
+ Compute Euf_Checker.checker t_i_uf7 t_func_uf7 t_atom_uf7 t_form_uf7 root_uf7 used_roots_uf7 trace_uf7.
+End Uf7.
+
+Section Lia1.
+ Parse_certif_verit t_i_lia1 t_func_lia1 t_atom_lia1 t_form_lia1 root_lia1 used_roots_lia1 trace_lia1 "lia1.smt2" "lia1.vtlog".
+ Compute Euf_Checker.checker t_i_lia1 t_func_lia1 t_atom_lia1 t_form_lia1 root_lia1 used_roots_lia1 trace_lia1.
+End Lia1.
+
+Section Lia2.
+ Parse_certif_verit t_i_lia2 t_func_lia2 t_atom_lia2 t_form_lia2 root_lia2 used_roots_lia2 trace_lia2 "lia2.smt2" "lia2.vtlog".
+ Compute Euf_Checker.checker t_i_lia2 t_func_lia2 t_atom_lia2 t_form_lia2 root_lia2 used_roots_lia2 trace_lia2.
+End Lia2.
+
+Section Lia3.
+ Parse_certif_verit t_i_lia3 t_func_lia3 t_atom_lia3 t_form_lia3 root_lia3 used_roots_lia3 trace_lia3 "lia3.smt2" "lia3.vtlog".
+ Compute Euf_Checker.checker t_i_lia3 t_func_lia3 t_atom_lia3 t_form_lia3 root_lia3 used_roots_lia3 trace_lia3.
+End Lia3.
+
+Section Lia4.
+ Parse_certif_verit t_i_lia4 t_func_lia4 t_atom_lia4 t_form_lia4 root_lia4 used_roots_lia4 trace_lia4 "lia4.smt2" "lia4.vtlog".
+ Compute Euf_Checker.checker t_i_lia4 t_func_lia4 t_atom_lia4 t_form_lia4 root_lia4 used_roots_lia4 trace_lia4.
+End Lia4.
+
+Section Lia5.
+ Parse_certif_verit t_i_lia5 t_func_lia5 t_atom_lia5 t_form_lia5 root_lia5 used_roots_lia5 trace_lia5 "lia5.smt2" "lia5.vtlog".
+ Compute Euf_Checker.checker t_i_lia5 t_func_lia5 t_atom_lia5 t_form_lia5 root_lia5 used_roots_lia5 trace_lia5.
+End Lia5.
+
+Section Lia6.
+ Parse_certif_verit t_i_lia6 t_func_lia6 t_atom_lia6 t_form_lia6 root_lia6 used_roots_lia6 trace_lia6 "lia6.smt2" "lia6.vtlog".
+ Compute Euf_Checker.checker t_i_lia6 t_func_lia6 t_atom_lia6 t_form_lia6 root_lia6 used_roots_lia6 trace_lia6.
+End Lia6.
+
+Section Lia7.
+ Parse_certif_verit t_i_lia7 t_func_lia7 t_atom_lia7 t_form_lia7 root_lia7 used_roots_lia7 trace_lia7 "lia7.smt2" "lia7.vtlog".
+ Compute Euf_Checker.checker t_i_lia7 t_func_lia7 t_atom_lia7 t_form_lia7 root_lia7 used_roots_lia7 trace_lia7.
+End Lia7.
+
+(* Section Let1. *)
+(* Parse_certif_verit t_i_let1 t_func_let1 t_atom_let1 t_form_let1 root_let1 used_roots_let1 trace_let1 "let1.smt2" "let1.vtlog". *)
+(* Compute Euf_Checker.checker t_i_let1 t_func_let1 t_atom_let1 t_form_let1 root_let1 used_roots_let1 trace_let1. *)
+(* End Let1. *)
+
+(* Section Let2. *)
+(* Parse_certif_verit t_i_let2 t_func_let2 t_atom_let2 t_form_let2 root_let2 used_roots_let2 trace_let2 "let2.smt2" "let2.vtlog". *)
+(* Compute Euf_Checker.checker t_i_let2 t_func_let2 t_atom_let2 t_form_let2 root_let2 used_roots_let2 trace_let2. *)
+(* End Let2. *)
+
+
+Section Theorem_Sat1.
+ Time Verit_Theorem theorem_sat1 "sat1.smt2" "sat1.vtlog".
+End Theorem_Sat1.
+
+Section Theorem_Sat2.
+ Time Verit_Theorem theorem_sat2 "sat2.smt2" "sat2.vtlog".
+End Theorem_Sat2.
+
+Section Theorem_Sat3.
+ Time Verit_Theorem theorem_sat3 "sat3.smt2" "sat3.vtlog".
+End Theorem_Sat3.
+
+Section Theorem_Sat4.
+ Time Verit_Theorem theorem_sat4 "sat4.smt2" "sat4.vtlog".
+End Theorem_Sat4.
+
+Section Theorem_Sat5.
+ Time Verit_Theorem theorem_sat5 "sat5.smt2" "sat5.vtlog".
+End Theorem_Sat5.
+
+Section Theorem_Sat6.
+ Time Verit_Theorem theorem_sat6 "sat6.smt2" "sat6.vtlog".
+End Theorem_Sat6.
+
+Section Theorem_Sat7.
+ Time Verit_Theorem theorem_sat7 "sat7.smt2" "sat7.vtlog".
+End Theorem_Sat7.
+
+Section Theorem_Sat8.
+ Time Verit_Theorem theorem_sat8 "sat8.smt2" "sat8.vtlog".
+End Theorem_Sat8.
+
+Section Theorem_Sat9.
+ Time Verit_Theorem theorem_sat9 "sat9.smt2" "sat9.vtlog".
+End Theorem_Sat9.
+(*
+Section Theorem_Sat10.
+ Time Verit_Theorem theorem_sat10 "sat10.smt2" "sat10.vtlog".
+End Theorem_Sat10.
+*)
+Section Theorem_Sat11.
+ Time Verit_Theorem theorem_sat11 "sat11.smt2" "sat11.vtlog".
+End Theorem_Sat11.
+
+Section Theorem_Sat12.
+ Time Verit_Theorem theorem_sat12 "sat12.smt2" "sat12.vtlog".
+End Theorem_Sat12.
+
+Section Theorem_Hole4.
+ Time Verit_Theorem theorem_hole4 "hole4.smt2" "hole4.vtlog".
+End Theorem_Hole4.
+
+Section Theorem_Uf1.
+ Time Verit_Theorem theorem_uf1 "uf1.smt2" "uf1.vtlog".
+End Theorem_Uf1.
+
+Section Theorem_Uf2.
+ Time Verit_Theorem theorem_uf2 "uf2.smt2" "uf2.vtlog".
+End Theorem_Uf2.
+
+Section Theorem_Uf3.
+ Time Verit_Theorem theorem_uf3 "uf3.smt2" "uf3.vtlog".
+End Theorem_Uf3.
+
+Section Theorem_Uf4.
+ Time Verit_Theorem theorem_uf4 "uf4.smt2" "uf4.vtlog".
+End Theorem_Uf4.
+
+Section Theorem_Uf5.
+ Time Verit_Theorem theorem_uf5 "uf5.smt2" "uf5.vtlog".
+End Theorem_Uf5.
+
+Section Theorem_Uf6.
+ Time Verit_Theorem theorem_uf6 "uf6.smt2" "uf6.vtlog".
+End Theorem_Uf6.
+
+Section Theorem_Uf7.
+ Time Verit_Theorem theorem_uf7 "uf7.smt2" "uf7.vtlog".
+End Theorem_Uf7.
+
+Section Theorem_Lia1.
+ Time Verit_Theorem theorem_lia1 "lia1.smt2" "lia1.vtlog".
+End Theorem_Lia1.
+
+Section Theorem_Lia2.
+ Time Verit_Theorem theorem_lia2 "lia2.smt2" "lia2.vtlog".
+End Theorem_Lia2.
+
+Section Theorem_Lia3.
+ Time Verit_Theorem theorem_lia3 "lia3.smt2" "lia3.vtlog".
+End Theorem_Lia3.
+
+Section Theorem_Lia4.
+ Time Verit_Theorem theorem_lia4 "lia4.smt2" "lia4.vtlog".
+End Theorem_Lia4.
+
+Section Theorem_Lia5.
+ Time Verit_Theorem theorem_lia5 "lia5.smt2" "lia5.vtlog".
+End Theorem_Lia5.
+
+Section Theorem_Lia6.
+ Time Verit_Theorem theorem_lia6 "lia6.smt2" "lia6.vtlog".
+End Theorem_Lia6.
+
+Section Theorem_Lia7.
+ Time Verit_Theorem theorem_lia7 "lia7.smt2" "lia7.vtlog".
+End Theorem_Lia7.
+
+(* Section Theorem_Let1. *)
+(* Time Verit_Theorem theorem_let1 "let1.smt2" "let1.vtlog". *)
+(* End Theorem_Let1. *)
+
+(* Section Theorem_Let2. *)
+(* Time Verit_Theorem theorem_let2 "let2.smt2" "let2.vtlog". *)
+(* End Theorem_Let2. *)
+
+
+(* verit tactic *)
+
+(* Simple connectors *)
+
+Goal forall (a:bool), a || negb a.
+ verit.
+Qed.
+
+Goal forall a, negb (a || negb a) = false.
+ verit.
+Qed.
+
+Goal forall a, (a && negb a) = false.
+ verit.
+Qed.
+
+Goal forall a, negb (a && negb a).
+ verit.
+Qed.
+
+Goal forall a, implb a a.
+ verit.
+Qed.
+
+Goal forall a, negb (implb a a) = false.
+ verit.
+Qed.
+
+Goal forall a , (xorb a a) || negb (xorb a a).
+ verit.
+Qed.
+Print Unnamed_thm5.
+
+Goal forall a, (a||negb a) || negb (a||negb a).
+ verit.
+Qed.
+
+Goal true.
+ verit.
+Qed.
+
+Goal negb false.
+ verit.
+Qed.
+
+Goal forall a, Bool.eqb a a.
+Proof.
+ verit.
+Qed.
+
+Goal forall (a:bool), a = a.
+ verit.
+Qed.
+
+
+(* Other connectors *)
+
+Goal (false || true) && false = false.
+Proof.
+ verit.
+Qed.
+
+
+Goal negb true = false.
+Proof.
+ verit.
+Qed.
+
+
+Goal false = false.
+Proof.
+ verit.
+Qed.
+
+
+Goal forall x y, Bool.eqb (xorb x y) ((x && (negb y)) || ((negb x) && y)).
+Proof.
+ verit.
+Qed.
+
+
+Goal forall x y, Bool.eqb (implb x y) ((x && y) || (negb x)).
+Proof.
+ verit.
+Qed.
+
+
+Goal forall x y z, Bool.eqb (ifb x y z) ((x && y) || ((negb x) && z)).
+Proof.
+ verit.
+Qed.
+
+
+(* Multiple negations *)
+
+Goal forall a, orb a (negb (negb (negb a))) = true.
+Proof.
+ verit.
+Qed.
+
+
+(* Polarities *)
+
+Goal forall a b, andb (orb a b) (negb (orb a b)) = false.
+Proof.
+ verit.
+Qed.
+
+
+Goal forall a b, andb (orb a b) (andb (negb a) (negb b)) = false.
+Proof.
+ verit.
+Qed.
+
+
+(* sat2.smt *)
+(* ((a ∧ b) ∨ (b ∧ c)) ∧ ¬b = ⊥ *)
+
+Goal forall a b c, (((a && b) || (b && c)) && (negb b)) = false.
+Proof.
+ verit.
+Qed.
+
+
+(* sat3.smt *)
+(* (a ∨ a) ∧ ¬a = ⊥ *)
+
+Goal forall a, ((a || a) && (negb a)) = false.
+Proof.
+ verit.
+Qed.
+
+
+(* sat4.smt *)
+(* ¬(a ∨ ¬a) = ⊥ *)
+
+Goal forall a, (negb (a || (negb a))) = false.
+Proof.
+ verit.
+Qed.
+
+
+(* sat5.smt *)
+(* (a ∨ b ∨ c) ∧ (¬a ∨ ¬b ∨ ¬c) ∧ (¬a ∨ b) ∧ (¬b ∨ c) ∧ (¬c ∨ a) = ⊥ *)
+
+Goal forall a b c,
+ (a || b || c) && ((negb a) || (negb b) || (negb c)) && ((negb a) || b) && ((negb b) || c) && ((negb c) || a) = false.
+Proof.
+ verit.
+Qed.
+
+
+(* Le même, mais où a, b et c sont des termes concrets *)
+
+Goal forall i j k,
+ let a := i == j in
+ let b := j == k in
+ let c := k == i in
+ (a || b || c) && ((negb a) || (negb b) || (negb c)) && ((negb a) || b) && ((negb b) || c) && ((negb c) || a) = false.
+Proof.
+ verit.
+Qed.
+
+
+(* sat6.smt *)
+(* (a ∧ b) ∧ (c ∨ d) ∧ ¬(c ∨ (a ∧ b ∧ d)) = ⊥ *)
+
+Goal forall a b c d, ((a && b) && (c || d) && (negb (c || (a && b && d)))) = false.
+Proof.
+ verit.
+Qed.
+
+
+(* sat7.smt *)
+(* a ∧ b ∧ c ∧ (¬a ∨ ¬b ∨ d) ∧ (¬d ∨ ¬c) = ⊥ *)
+
+Goal forall a b c d, (a && b && c && ((negb a) || (negb b) || d) && ((negb d) || (negb c))) = false.
+Proof.
+ verit.
+Qed.
+
+
+(* Pigeon hole: 4 holes, 5 pigeons *)
+
+Goal forall x11 x12 x13 x14 x15 x21 x22 x23 x24 x25 x31 x32 x33 x34 x35 x41 x42 x43 x44 x45, (
+ (orb (negb x11) (negb x21)) &&
+ (orb (negb x11) (negb x31)) &&
+ (orb (negb x11) (negb x41)) &&
+ (orb (negb x21) (negb x31)) &&
+ (orb (negb x21) (negb x41)) &&
+ (orb (negb x31) (negb x41)) &&
+
+ (orb (negb x12) (negb x22)) &&
+ (orb (negb x12) (negb x32)) &&
+ (orb (negb x12) (negb x42)) &&
+ (orb (negb x22) (negb x32)) &&
+ (orb (negb x22) (negb x42)) &&
+ (orb (negb x32) (negb x42)) &&
+
+ (orb (negb x13) (negb x23)) &&
+ (orb (negb x13) (negb x33)) &&
+ (orb (negb x13) (negb x43)) &&
+ (orb (negb x23) (negb x33)) &&
+ (orb (negb x23) (negb x43)) &&
+ (orb (negb x33) (negb x43)) &&
+
+ (orb (negb x14) (negb x24)) &&
+ (orb (negb x14) (negb x34)) &&
+ (orb (negb x14) (negb x44)) &&
+ (orb (negb x24) (negb x34)) &&
+ (orb (negb x24) (negb x44)) &&
+ (orb (negb x34) (negb x44)) &&
+
+ (orb (negb x15) (negb x25)) &&
+ (orb (negb x15) (negb x35)) &&
+ (orb (negb x15) (negb x45)) &&
+ (orb (negb x25) (negb x35)) &&
+ (orb (negb x25) (negb x45)) &&
+ (orb (negb x35) (negb x45)) &&
+
+
+ (orb (negb x11) (negb x12)) &&
+ (orb (negb x11) (negb x13)) &&
+ (orb (negb x11) (negb x14)) &&
+ (orb (negb x11) (negb x15)) &&
+ (orb (negb x12) (negb x13)) &&
+ (orb (negb x12) (negb x14)) &&
+ (orb (negb x12) (negb x15)) &&
+ (orb (negb x13) (negb x14)) &&
+ (orb (negb x13) (negb x15)) &&
+ (orb (negb x14) (negb x15)) &&
+
+ (orb (negb x21) (negb x22)) &&
+ (orb (negb x21) (negb x23)) &&
+ (orb (negb x21) (negb x24)) &&
+ (orb (negb x21) (negb x25)) &&
+ (orb (negb x22) (negb x23)) &&
+ (orb (negb x22) (negb x24)) &&
+ (orb (negb x22) (negb x25)) &&
+ (orb (negb x23) (negb x24)) &&
+ (orb (negb x23) (negb x25)) &&
+ (orb (negb x24) (negb x25)) &&
+
+ (orb (negb x31) (negb x32)) &&
+ (orb (negb x31) (negb x33)) &&
+ (orb (negb x31) (negb x34)) &&
+ (orb (negb x31) (negb x35)) &&
+ (orb (negb x32) (negb x33)) &&
+ (orb (negb x32) (negb x34)) &&
+ (orb (negb x32) (negb x35)) &&
+ (orb (negb x33) (negb x34)) &&
+ (orb (negb x33) (negb x35)) &&
+ (orb (negb x34) (negb x35)) &&
+
+ (orb (negb x41) (negb x42)) &&
+ (orb (negb x41) (negb x43)) &&
+ (orb (negb x41) (negb x44)) &&
+ (orb (negb x41) (negb x45)) &&
+ (orb (negb x42) (negb x43)) &&
+ (orb (negb x42) (negb x44)) &&
+ (orb (negb x42) (negb x45)) &&
+ (orb (negb x43) (negb x44)) &&
+ (orb (negb x43) (negb x45)) &&
+ (orb (negb x44) (negb x45)) &&
+
+
+ (orb (orb (orb x11 x21) x31) x41) &&
+ (orb (orb (orb x12 x22) x32) x42) &&
+ (orb (orb (orb x13 x23) x33) x43) &&
+ (orb (orb (orb x14 x24) x34) x44) &&
+ (orb (orb (orb x15 x25) x35) x45)) = false.
+Proof.
+ verit.
+Qed.
+
+
+(* uf1.smt *)
+
+Goal forall a b c f p, ((Zeq_bool a c) && (Zeq_bool b c) && ((negb (Zeq_bool (f a) (f b))) || ((p a) && (negb (p b))))) = false.
+Proof.
+ verit.
+Qed.
+
+
+(* uf2.smt *)
+
+Goal forall a b c (p : Z -> bool), ((((p a) && (p b)) || ((p b) && (p c))) && (negb (p b))) = false.
+Proof.
+ verit.
+Qed.
+
+
+(* uf3.smt *)
+
+Goal forall x y z f, ((Zeq_bool x y) && (Zeq_bool y z) && (negb (Zeq_bool (f x) (f z)))) = false.
+Proof.
+ verit.
+Qed.
+
+
+(* uf4.smt *)
+
+Goal forall x y z f, ((negb (Zeq_bool (f x) (f y))) && (Zeq_bool y z) && (Zeq_bool (f x) (f (f z))) && (Zeq_bool x y)) = false.
+Proof.
+ verit.
+Qed.
+
+
+(* uf5.smt *)
+
+Goal forall a b c d e f, ((Zeq_bool a b) && (Zeq_bool b c) && (Zeq_bool c d) && (Zeq_bool c e) && (Zeq_bool e f) && (negb (Zeq_bool a f))) = false.
+Proof.
+ verit.
+Qed.
+
+
+(* lia1.smt *)
+
+Goal forall x y z, implb ((x <=? 3) && ((y <=? 7) || (z <=? 9)))
+ ((x + y <=? 10) || (x + z <=? 12)) = true.
+Proof.
+ verit.
+Qed.
+
+(* lia2.smt *)
+
+Goal forall x, implb (Zeq_bool (x - 3) 7) (x >=? 10) = true.
+Proof.
+ verit.
+Qed.
+
+(* lia3.smt *)
+
+Goal forall x y, implb (x >? y) (y + 1 <=? x) = true.
+Proof.
+ verit.
+Qed.
+
+(* lia4.smt *)
+
+Goal forall x y, Bool.eqb (x <? y) (x <=? y - 1) = true.
+Proof.
+ verit.
+Qed.
+
+(* lia5.smt *)
+
+Goal forall x y, ((x + y <=? - (3)) && (y >=? 0)
+ || (x <=? - (3))) && (x >=? 0) = false.
+Proof.
+ verit.
+Qed.
+
+(* lia6.smt *)
+
+Goal forall x, implb (andb ((x - 3) <=? 7) (7 <=? (x - 3))) (x >=? 10) = true.
+Proof.
+ verit.
+Qed.
+
+(* lia7.smt *)
+
+Goal forall x, implb (Zeq_bool (x - 3) 7) (10 <=? x) = true.
+Proof.
+ verit.
+Qed.
+
+(* More general examples *)
+
+Goal forall a b c, ((a || b || c) && ((negb a) || (negb b) || (negb c)) && ((negb a) || b) && ((negb b) || c) && ((negb c) || a)) = false.
+Proof.
+ verit.
+Qed.
+
+
+Goal forall (a b : Z) (P : Z -> bool) (f : Z -> Z),
+ (negb (Zeq_bool (f a) b)) || (negb (P (f a))) || (P b).
+Proof.
+ verit.
+Qed.
+
+
+Goal forall b1 b2 x1 x2,
+ implb
+ (ifb b1
+ (ifb b2 (Zeq_bool (2*x1+1) (2*x2+1)) (Zeq_bool (2*x1+1) (2*x2)))
+ (ifb b2 (Zeq_bool (2*x1) (2*x2+1)) (Zeq_bool (2*x1) (2*x2))))
+ ((implb b1 b2) && (implb b2 b1) && (Zeq_bool x1 x2)).
+Proof.
+ verit.
+Qed.
+
+
+(* With let ... in ... *)
+
+Goal forall b,
+ let a := b in
+ a && (negb a) = false.
+Proof.
+ verit.
+Qed.
+
+Goal forall b,
+ let a := b in
+ a || (negb a) = true.
+Proof.
+ verit.
+Qed.
+(* Ne marche pas car la coercion is_true inclut le [let in]
+Goal forall b,
+ let a := b in
+ a || (negb a).
+Proof.
+ verit.
+Qed.
+*)
+
+(* With concrete terms *)
+
+Goal forall i j,
+ let a := i == j in
+ a && (negb a) = false.
+Proof.
+ verit.
+Qed.
+
+Goal forall i j,
+ let a := i == j in
+ a || (negb a) = true.
+Proof.
+ verit.
+Qed.
+
+Section Concret.
+ Goal forall i j,
+ (i == j) && (negb (i == j)) = false.
+ Proof.
+ verit.
+ Qed.
+End Concret.
+
+Section Concret2.
+ Lemma concret : forall i j, (i == j) || (negb (i == j)).
+ Proof.
+ verit.
+ Qed.
+ Check concret.
+End Concret2.
+Check concret.
+
+
+(* Congruence in which some premices are REFL *)
+
+Goal forall (f:Z -> Z -> Z) x y z,
+ implb (Zeq_bool x y) (Zeq_bool (f z x) (f z y)).
+Proof.
+ verit.
+Qed.
+
+Goal forall (P:Z -> Z -> bool) x y z,
+ implb (Zeq_bool x y) (implb (P z x) (P z y)).
+Proof.
+ verit.
+Qed.
diff --git a/unit-tests/cmu-bmc-barrel6.cnf b/unit-tests/cmu-bmc-barrel6.cnf
new file mode 100644
index 0000000..a25a2dc
--- /dev/null
+++ b/unit-tests/cmu-bmc-barrel6.cnf
@@ -0,0 +1,8932 @@
+p cnf 2306 8931
+1 2 -5 0
+1 -2 5 0
+-1 2 5 0
+-1 -2 -5 0
+3 -6 8 0
+-3 6 8 0
+3 6 -8 0
+-3 -6 -8 0
+4 -7 9 0
+-4 7 9 0
+4 7 -9 0
+-4 -7 -9 0
+-9 10 0
+-8 10 0
+-1 10 0
+1 8 9 -10 0
+11 12 15 0
+11 -12 -15 0
+-11 12 -15 0
+-11 -12 15 0
+13 16 18 0
+-13 -16 18 0
+13 -16 -18 0
+-13 16 -18 0
+14 17 19 0
+-14 -17 19 0
+14 -17 -19 0
+-14 17 -19 0
+19 -20 0
+18 -20 0
+11 -20 0
+10 -20 0
+2 -15 21 0
+-2 15 21 0
+2 15 -21 0
+-2 -15 -21 0
+3 -16 22 0
+-3 16 22 0
+3 16 -22 0
+-3 -16 -22 0
+4 -17 23 0
+-4 17 23 0
+4 17 -23 0
+-4 -17 -23 0
+-23 24 0
+-22 24 0
+-21 24 0
+21 22 23 -24 0
+12 25 26 0
+-12 25 -26 0
+12 -25 -26 0
+-12 -25 26 0
+13 27 29 0
+-13 -27 29 0
+13 -27 -29 0
+-13 27 -29 0
+14 28 30 0
+-14 -28 30 0
+14 -28 -30 0
+-14 28 -30 0
+30 -31 0
+29 -31 0
+25 -31 0
+24 -31 0
+2 -26 32 0
+-2 26 32 0
+2 26 -32 0
+-2 -26 -32 0
+3 -27 33 0
+-3 27 33 0
+3 27 -33 0
+-3 -27 -33 0
+4 -28 34 0
+-4 28 34 0
+4 28 -34 0
+-4 -28 -34 0
+-34 35 0
+-33 35 0
+-32 35 0
+32 33 34 -35 0
+12 36 37 0
+-12 36 -37 0
+12 -36 -37 0
+-12 -36 37 0
+13 38 40 0
+-13 -38 40 0
+13 -38 -40 0
+-13 38 -40 0
+14 39 41 0
+-14 -39 41 0
+14 -39 -41 0
+-14 39 -41 0
+41 -42 0
+40 -42 0
+36 -42 0
+35 -42 0
+2 -37 43 0
+-2 37 43 0
+2 37 -43 0
+-2 -37 -43 0
+3 -38 44 0
+-3 38 44 0
+3 38 -44 0
+-3 -38 -44 0
+4 -39 45 0
+-4 39 45 0
+4 39 -45 0
+-4 -39 -45 0
+-45 46 0
+-44 46 0
+-43 46 0
+43 44 45 -46 0
+12 47 48 0
+-12 47 -48 0
+12 -47 -48 0
+-12 -47 48 0
+13 49 51 0
+-13 -49 51 0
+13 -49 -51 0
+-13 49 -51 0
+14 50 52 0
+-14 -50 52 0
+14 -50 -52 0
+-14 50 -52 0
+52 -53 0
+51 -53 0
+47 -53 0
+46 -53 0
+2 -48 54 0
+-2 48 54 0
+2 48 -54 0
+-2 -48 -54 0
+3 -49 55 0
+-3 49 55 0
+3 49 -55 0
+-3 -49 -55 0
+4 -50 56 0
+-4 50 56 0
+4 50 -56 0
+-4 -50 -56 0
+-56 57 0
+-55 57 0
+-54 57 0
+54 55 56 -57 0
+12 58 59 0
+-12 58 -59 0
+12 -58 -59 0
+-12 -58 59 0
+13 60 62 0
+-13 -60 62 0
+13 -60 -62 0
+-13 60 -62 0
+14 61 63 0
+-14 -61 63 0
+14 -61 -63 0
+-14 61 -63 0
+63 -64 0
+62 -64 0
+58 -64 0
+57 -64 0
+2 -59 65 0
+-2 59 65 0
+2 59 -65 0
+-2 -59 -65 0
+3 -60 66 0
+-3 60 66 0
+3 60 -66 0
+-3 -60 -66 0
+4 -61 67 0
+-4 61 67 0
+4 61 -67 0
+-4 -61 -67 0
+-67 68 0
+-66 68 0
+-65 68 0
+65 66 67 -68 0
+5 12 69 0
+-5 -12 69 0
+-5 12 -69 0
+5 -12 -69 0
+6 13 70 0
+-6 -13 70 0
+-6 13 -70 0
+6 -13 -70 0
+7 14 71 0
+-7 -14 71 0
+-7 14 -71 0
+7 -14 -71 0
+71 -72 0
+70 -72 0
+69 -72 0
+68 -72 0
+-5 12 73 0
+5 -12 73 0
+5 12 -73 0
+-5 -12 -73 0
+-6 13 74 0
+6 -13 74 0
+6 13 -74 0
+-6 -13 -74 0
+-7 14 75 0
+7 -14 75 0
+7 14 -75 0
+-7 -14 -75 0
+-75 76 0
+-74 76 0
+-73 76 0
+73 74 75 -76 0
+15 77 78 0
+-15 77 -78 0
+-15 -77 78 0
+15 -77 -78 0
+16 79 81 0
+-16 -79 81 0
+-16 79 -81 0
+16 -79 -81 0
+17 80 82 0
+-17 -80 82 0
+-17 80 -82 0
+17 -80 -82 0
+82 -83 0
+81 -83 0
+77 -83 0
+76 -83 0
+12 -15 84 0
+-12 15 84 0
+12 15 -84 0
+-12 -15 -84 0
+13 -16 85 0
+-13 16 85 0
+13 16 -85 0
+-13 -16 -85 0
+14 -17 86 0
+-14 17 86 0
+14 17 -86 0
+-14 -17 -86 0
+-86 87 0
+-85 87 0
+-84 87 0
+84 85 86 -87 0
+26 78 88 0
+-26 -78 88 0
+-26 78 -88 0
+26 -78 -88 0
+27 79 89 0
+-27 -79 89 0
+-27 79 -89 0
+27 -79 -89 0
+28 80 90 0
+-28 -80 90 0
+-28 80 -90 0
+28 -80 -90 0
+90 -91 0
+89 -91 0
+88 -91 0
+87 -91 0
+12 -26 92 0
+-12 26 92 0
+12 26 -92 0
+-12 -26 -92 0
+13 -27 93 0
+-13 27 93 0
+13 27 -93 0
+-13 -27 -93 0
+14 -28 94 0
+-14 28 94 0
+14 28 -94 0
+-14 -28 -94 0
+-94 95 0
+-93 95 0
+-92 95 0
+92 93 94 -95 0
+37 78 96 0
+-37 -78 96 0
+-37 78 -96 0
+37 -78 -96 0
+38 79 97 0
+-38 -79 97 0
+-38 79 -97 0
+38 -79 -97 0
+39 80 98 0
+-39 -80 98 0
+-39 80 -98 0
+39 -80 -98 0
+98 -99 0
+97 -99 0
+96 -99 0
+95 -99 0
+12 -37 100 0
+-12 37 100 0
+12 37 -100 0
+-12 -37 -100 0
+13 -38 101 0
+-13 38 101 0
+13 38 -101 0
+-13 -38 -101 0
+14 -39 102 0
+-14 39 102 0
+14 39 -102 0
+-14 -39 -102 0
+-102 103 0
+-101 103 0
+-100 103 0
+100 101 102 -103 0
+48 78 104 0
+-48 -78 104 0
+-48 78 -104 0
+48 -78 -104 0
+49 79 105 0
+-49 -79 105 0
+-49 79 -105 0
+49 -79 -105 0
+50 80 106 0
+-50 -80 106 0
+-50 80 -106 0
+50 -80 -106 0
+106 -107 0
+105 -107 0
+104 -107 0
+103 -107 0
+12 -48 108 0
+-12 48 108 0
+12 48 -108 0
+-12 -48 -108 0
+13 -49 109 0
+-13 49 109 0
+13 49 -109 0
+-13 -49 -109 0
+14 -50 110 0
+-14 50 110 0
+14 50 -110 0
+-14 -50 -110 0
+-110 111 0
+-109 111 0
+-108 111 0
+108 109 110 -111 0
+59 78 112 0
+-59 -78 112 0
+-59 78 -112 0
+59 -78 -112 0
+60 79 113 0
+-60 -79 113 0
+-60 79 -113 0
+60 -79 -113 0
+61 80 114 0
+-61 -80 114 0
+-61 80 -114 0
+61 -80 -114 0
+114 -115 0
+113 -115 0
+112 -115 0
+111 -115 0
+12 -59 116 0
+-12 59 116 0
+12 59 -116 0
+-12 -59 -116 0
+13 -60 117 0
+-13 60 117 0
+13 60 -117 0
+-13 -60 -117 0
+14 -61 118 0
+-14 61 118 0
+14 61 -118 0
+-14 -61 -118 0
+-118 119 0
+-117 119 0
+-116 119 0
+116 117 118 -119 0
+5 78 120 0
+-5 -78 120 0
+-5 78 -120 0
+5 -78 -120 0
+6 79 121 0
+-6 -79 121 0
+-6 79 -121 0
+6 -79 -121 0
+7 80 122 0
+-7 -80 122 0
+-7 80 -122 0
+7 -80 -122 0
+122 -123 0
+121 -123 0
+120 -123 0
+119 -123 0
+-5 78 124 0
+5 -78 124 0
+5 78 -124 0
+-5 -78 -124 0
+-6 79 125 0
+6 -79 125 0
+6 79 -125 0
+-6 -79 -125 0
+-7 80 126 0
+7 -80 126 0
+7 80 -126 0
+-7 -80 -126 0
+-126 127 0
+-125 127 0
+-124 127 0
+124 125 126 -127 0
+15 128 129 0
+-15 128 -129 0
+-15 -128 129 0
+15 -128 -129 0
+16 130 132 0
+-16 -130 132 0
+-16 130 -132 0
+16 -130 -132 0
+17 131 133 0
+-17 -131 133 0
+-17 131 -133 0
+17 -131 -133 0
+133 -134 0
+132 -134 0
+128 -134 0
+127 -134 0
+-15 78 135 0
+15 -78 135 0
+15 78 -135 0
+-15 -78 -135 0
+-16 79 136 0
+16 -79 136 0
+16 79 -136 0
+-16 -79 -136 0
+-17 80 137 0
+17 -80 137 0
+17 80 -137 0
+-17 -80 -137 0
+-137 138 0
+-136 138 0
+-135 138 0
+135 136 137 -138 0
+26 129 139 0
+-26 -129 139 0
+-26 129 -139 0
+26 -129 -139 0
+27 130 140 0
+-27 -130 140 0
+-27 130 -140 0
+27 -130 -140 0
+28 131 141 0
+-28 -131 141 0
+-28 131 -141 0
+28 -131 -141 0
+141 -142 0
+140 -142 0
+139 -142 0
+138 -142 0
+-26 78 143 0
+26 -78 143 0
+26 78 -143 0
+-26 -78 -143 0
+-27 79 144 0
+27 -79 144 0
+27 79 -144 0
+-27 -79 -144 0
+-28 80 145 0
+28 -80 145 0
+28 80 -145 0
+-28 -80 -145 0
+-145 146 0
+-144 146 0
+-143 146 0
+143 144 145 -146 0
+37 129 147 0
+-37 -129 147 0
+-37 129 -147 0
+37 -129 -147 0
+38 130 148 0
+-38 -130 148 0
+-38 130 -148 0
+38 -130 -148 0
+39 131 149 0
+-39 -131 149 0
+-39 131 -149 0
+39 -131 -149 0
+149 -150 0
+148 -150 0
+147 -150 0
+146 -150 0
+-37 78 151 0
+37 -78 151 0
+37 78 -151 0
+-37 -78 -151 0
+-38 79 152 0
+38 -79 152 0
+38 79 -152 0
+-38 -79 -152 0
+-39 80 153 0
+39 -80 153 0
+39 80 -153 0
+-39 -80 -153 0
+-153 154 0
+-152 154 0
+-151 154 0
+151 152 153 -154 0
+48 129 155 0
+-48 -129 155 0
+-48 129 -155 0
+48 -129 -155 0
+49 130 156 0
+-49 -130 156 0
+-49 130 -156 0
+49 -130 -156 0
+50 131 157 0
+-50 -131 157 0
+-50 131 -157 0
+50 -131 -157 0
+157 -158 0
+156 -158 0
+155 -158 0
+154 -158 0
+-48 78 159 0
+48 -78 159 0
+48 78 -159 0
+-48 -78 -159 0
+-49 79 160 0
+49 -79 160 0
+49 79 -160 0
+-49 -79 -160 0
+-50 80 161 0
+50 -80 161 0
+50 80 -161 0
+-50 -80 -161 0
+-161 162 0
+-160 162 0
+-159 162 0
+159 160 161 -162 0
+59 129 163 0
+-59 -129 163 0
+-59 129 -163 0
+59 -129 -163 0
+60 130 164 0
+-60 -130 164 0
+-60 130 -164 0
+60 -130 -164 0
+61 131 165 0
+-61 -131 165 0
+-61 131 -165 0
+61 -131 -165 0
+165 -166 0
+164 -166 0
+163 -166 0
+162 -166 0
+-59 78 167 0
+59 -78 167 0
+59 78 -167 0
+-59 -78 -167 0
+-60 79 168 0
+60 -79 168 0
+60 79 -168 0
+-60 -79 -168 0
+-61 80 169 0
+61 -80 169 0
+61 80 -169 0
+-61 -80 -169 0
+-169 170 0
+-168 170 0
+-167 170 0
+167 168 169 -170 0
+5 129 171 0
+-5 -129 171 0
+-5 129 -171 0
+5 -129 -171 0
+6 130 172 0
+-6 -130 172 0
+-6 130 -172 0
+6 -130 -172 0
+7 131 173 0
+-7 -131 173 0
+-7 131 -173 0
+7 -131 -173 0
+173 -174 0
+172 -174 0
+171 -174 0
+170 -174 0
+-5 129 175 0
+5 -129 175 0
+5 129 -175 0
+-5 -129 -175 0
+-6 130 176 0
+6 -130 176 0
+6 130 -176 0
+-6 -130 -176 0
+-7 131 177 0
+7 -131 177 0
+7 131 -177 0
+-7 -131 -177 0
+-177 178 0
+-176 178 0
+-175 178 0
+175 176 177 -178 0
+15 179 180 0
+-15 179 -180 0
+-15 -179 180 0
+15 -179 -180 0
+16 181 183 0
+-16 -181 183 0
+-16 181 -183 0
+16 -181 -183 0
+17 182 184 0
+-17 -182 184 0
+-17 182 -184 0
+17 -182 -184 0
+184 -185 0
+183 -185 0
+179 -185 0
+178 -185 0
+-15 129 186 0
+15 -129 186 0
+15 129 -186 0
+-15 -129 -186 0
+-16 130 187 0
+16 -130 187 0
+16 130 -187 0
+-16 -130 -187 0
+-17 131 188 0
+17 -131 188 0
+17 131 -188 0
+-17 -131 -188 0
+-188 189 0
+-187 189 0
+-186 189 0
+186 187 188 -189 0
+26 180 190 0
+-26 -180 190 0
+-26 180 -190 0
+26 -180 -190 0
+27 181 191 0
+-27 -181 191 0
+-27 181 -191 0
+27 -181 -191 0
+28 182 192 0
+-28 -182 192 0
+-28 182 -192 0
+28 -182 -192 0
+192 -193 0
+191 -193 0
+190 -193 0
+189 -193 0
+-26 129 194 0
+26 -129 194 0
+26 129 -194 0
+-26 -129 -194 0
+-27 130 195 0
+27 -130 195 0
+27 130 -195 0
+-27 -130 -195 0
+-28 131 196 0
+28 -131 196 0
+28 131 -196 0
+-28 -131 -196 0
+-196 197 0
+-195 197 0
+-194 197 0
+194 195 196 -197 0
+37 180 198 0
+-37 -180 198 0
+-37 180 -198 0
+37 -180 -198 0
+38 181 199 0
+-38 -181 199 0
+-38 181 -199 0
+38 -181 -199 0
+39 182 200 0
+-39 -182 200 0
+-39 182 -200 0
+39 -182 -200 0
+200 -201 0
+199 -201 0
+198 -201 0
+197 -201 0
+-37 129 202 0
+37 -129 202 0
+37 129 -202 0
+-37 -129 -202 0
+-38 130 203 0
+38 -130 203 0
+38 130 -203 0
+-38 -130 -203 0
+-39 131 204 0
+39 -131 204 0
+39 131 -204 0
+-39 -131 -204 0
+-204 205 0
+-203 205 0
+-202 205 0
+202 203 204 -205 0
+48 180 206 0
+-48 -180 206 0
+-48 180 -206 0
+48 -180 -206 0
+49 181 207 0
+-49 -181 207 0
+-49 181 -207 0
+49 -181 -207 0
+50 182 208 0
+-50 -182 208 0
+-50 182 -208 0
+50 -182 -208 0
+208 -209 0
+207 -209 0
+206 -209 0
+205 -209 0
+-48 129 210 0
+48 -129 210 0
+48 129 -210 0
+-48 -129 -210 0
+-49 130 211 0
+49 -130 211 0
+49 130 -211 0
+-49 -130 -211 0
+-50 131 212 0
+50 -131 212 0
+50 131 -212 0
+-50 -131 -212 0
+-212 213 0
+-211 213 0
+-210 213 0
+210 211 212 -213 0
+59 180 214 0
+-59 -180 214 0
+-59 180 -214 0
+59 -180 -214 0
+60 181 215 0
+-60 -181 215 0
+-60 181 -215 0
+60 -181 -215 0
+61 182 216 0
+-61 -182 216 0
+-61 182 -216 0
+61 -182 -216 0
+216 -217 0
+215 -217 0
+214 -217 0
+213 -217 0
+-59 129 218 0
+59 -129 218 0
+59 129 -218 0
+-59 -129 -218 0
+-60 130 219 0
+60 -130 219 0
+60 130 -219 0
+-60 -130 -219 0
+-61 131 220 0
+61 -131 220 0
+61 131 -220 0
+-61 -131 -220 0
+-220 221 0
+-219 221 0
+-218 221 0
+218 219 220 -221 0
+5 180 222 0
+-5 -180 222 0
+-5 180 -222 0
+5 -180 -222 0
+6 181 223 0
+-6 -181 223 0
+-6 181 -223 0
+6 -181 -223 0
+7 182 224 0
+-7 -182 224 0
+-7 182 -224 0
+7 -182 -224 0
+224 -225 0
+223 -225 0
+222 -225 0
+221 -225 0
+-5 180 226 0
+5 -180 226 0
+5 180 -226 0
+-5 -180 -226 0
+-6 181 227 0
+6 -181 227 0
+6 181 -227 0
+-6 -181 -227 0
+-7 182 228 0
+7 -182 228 0
+7 182 -228 0
+-7 -182 -228 0
+-228 229 0
+-227 229 0
+-226 229 0
+226 227 228 -229 0
+15 230 231 0
+-15 230 -231 0
+-15 -230 231 0
+15 -230 -231 0
+16 232 234 0
+-16 -232 234 0
+-16 232 -234 0
+16 -232 -234 0
+17 233 235 0
+-17 -233 235 0
+-17 233 -235 0
+17 -233 -235 0
+235 -236 0
+234 -236 0
+230 -236 0
+229 -236 0
+-15 180 237 0
+15 -180 237 0
+15 180 -237 0
+-15 -180 -237 0
+-16 181 238 0
+16 -181 238 0
+16 181 -238 0
+-16 -181 -238 0
+-17 182 239 0
+17 -182 239 0
+17 182 -239 0
+-17 -182 -239 0
+-239 240 0
+-238 240 0
+-237 240 0
+237 238 239 -240 0
+26 231 241 0
+-26 -231 241 0
+-26 231 -241 0
+26 -231 -241 0
+27 232 242 0
+-27 -232 242 0
+-27 232 -242 0
+27 -232 -242 0
+28 233 243 0
+-28 -233 243 0
+-28 233 -243 0
+28 -233 -243 0
+243 -244 0
+242 -244 0
+241 -244 0
+240 -244 0
+-26 180 245 0
+26 -180 245 0
+26 180 -245 0
+-26 -180 -245 0
+-27 181 246 0
+27 -181 246 0
+27 181 -246 0
+-27 -181 -246 0
+-28 182 247 0
+28 -182 247 0
+28 182 -247 0
+-28 -182 -247 0
+-247 248 0
+-246 248 0
+-245 248 0
+245 246 247 -248 0
+37 231 249 0
+-37 -231 249 0
+-37 231 -249 0
+37 -231 -249 0
+38 232 250 0
+-38 -232 250 0
+-38 232 -250 0
+38 -232 -250 0
+39 233 251 0
+-39 -233 251 0
+-39 233 -251 0
+39 -233 -251 0
+251 -252 0
+250 -252 0
+249 -252 0
+248 -252 0
+-37 180 253 0
+37 -180 253 0
+37 180 -253 0
+-37 -180 -253 0
+-38 181 254 0
+38 -181 254 0
+38 181 -254 0
+-38 -181 -254 0
+-39 182 255 0
+39 -182 255 0
+39 182 -255 0
+-39 -182 -255 0
+-255 256 0
+-254 256 0
+-253 256 0
+253 254 255 -256 0
+48 231 257 0
+-48 -231 257 0
+-48 231 -257 0
+48 -231 -257 0
+49 232 258 0
+-49 -232 258 0
+-49 232 -258 0
+49 -232 -258 0
+50 233 259 0
+-50 -233 259 0
+-50 233 -259 0
+50 -233 -259 0
+259 -260 0
+258 -260 0
+257 -260 0
+256 -260 0
+-48 180 261 0
+48 -180 261 0
+48 180 -261 0
+-48 -180 -261 0
+-49 181 262 0
+49 -181 262 0
+49 181 -262 0
+-49 -181 -262 0
+-50 182 263 0
+50 -182 263 0
+50 182 -263 0
+-50 -182 -263 0
+-263 264 0
+-262 264 0
+-261 264 0
+261 262 263 -264 0
+59 231 265 0
+-59 -231 265 0
+-59 231 -265 0
+59 -231 -265 0
+60 232 266 0
+-60 -232 266 0
+-60 232 -266 0
+60 -232 -266 0
+61 233 267 0
+-61 -233 267 0
+-61 233 -267 0
+61 -233 -267 0
+267 -268 0
+266 -268 0
+265 -268 0
+264 -268 0
+-59 180 269 0
+59 -180 269 0
+59 180 -269 0
+-59 -180 -269 0
+-60 181 270 0
+60 -181 270 0
+60 181 -270 0
+-60 -181 -270 0
+-61 182 271 0
+61 -182 271 0
+61 182 -271 0
+-61 -182 -271 0
+-271 272 0
+-270 272 0
+-269 272 0
+269 270 271 -272 0
+5 231 273 0
+-5 -231 273 0
+-5 231 -273 0
+5 -231 -273 0
+6 232 274 0
+-6 -232 274 0
+-6 232 -274 0
+6 -232 -274 0
+7 233 275 0
+-7 -233 275 0
+-7 233 -275 0
+7 -233 -275 0
+275 -276 0
+274 -276 0
+273 -276 0
+272 -276 0
+-5 231 277 0
+5 -231 277 0
+5 231 -277 0
+-5 -231 -277 0
+-6 232 278 0
+6 -232 278 0
+6 232 -278 0
+-6 -232 -278 0
+-7 233 279 0
+7 -233 279 0
+7 233 -279 0
+-7 -233 -279 0
+-279 280 0
+-278 280 0
+-277 280 0
+277 278 279 -280 0
+2 15 281 0
+-2 -15 281 0
+2 -15 -281 0
+-2 15 -281 0
+3 16 282 0
+-3 -16 282 0
+3 -16 -282 0
+-3 16 -282 0
+4 17 283 0
+-4 -17 283 0
+4 -17 -283 0
+-4 17 -283 0
+283 -284 0
+282 -284 0
+281 -284 0
+280 -284 0
+-15 231 285 0
+15 -231 285 0
+15 231 -285 0
+-15 -231 -285 0
+-16 232 286 0
+16 -232 286 0
+16 232 -286 0
+-16 -232 -286 0
+-17 233 287 0
+17 -233 287 0
+17 233 -287 0
+-17 -233 -287 0
+-287 288 0
+-286 288 0
+-285 288 0
+285 286 287 -288 0
+2 26 289 0
+-2 -26 289 0
+2 -26 -289 0
+-2 26 -289 0
+3 27 290 0
+-3 -27 290 0
+3 -27 -290 0
+-3 27 -290 0
+4 28 291 0
+-4 -28 291 0
+4 -28 -291 0
+-4 28 -291 0
+291 -292 0
+290 -292 0
+289 -292 0
+288 -292 0
+-26 231 293 0
+26 -231 293 0
+26 231 -293 0
+-26 -231 -293 0
+-27 232 294 0
+27 -232 294 0
+27 232 -294 0
+-27 -232 -294 0
+-28 233 295 0
+28 -233 295 0
+28 233 -295 0
+-28 -233 -295 0
+-295 296 0
+-294 296 0
+-293 296 0
+293 294 295 -296 0
+2 37 297 0
+-2 -37 297 0
+2 -37 -297 0
+-2 37 -297 0
+3 38 298 0
+-3 -38 298 0
+3 -38 -298 0
+-3 38 -298 0
+4 39 299 0
+-4 -39 299 0
+4 -39 -299 0
+-4 39 -299 0
+299 -300 0
+298 -300 0
+297 -300 0
+296 -300 0
+-37 231 301 0
+37 -231 301 0
+37 231 -301 0
+-37 -231 -301 0
+-38 232 302 0
+38 -232 302 0
+38 232 -302 0
+-38 -232 -302 0
+-39 233 303 0
+39 -233 303 0
+39 233 -303 0
+-39 -233 -303 0
+-303 304 0
+-302 304 0
+-301 304 0
+301 302 303 -304 0
+2 48 305 0
+-2 -48 305 0
+2 -48 -305 0
+-2 48 -305 0
+3 49 306 0
+-3 -49 306 0
+3 -49 -306 0
+-3 49 -306 0
+4 50 307 0
+-4 -50 307 0
+4 -50 -307 0
+-4 50 -307 0
+307 -308 0
+306 -308 0
+305 -308 0
+304 -308 0
+-48 231 309 0
+48 -231 309 0
+48 231 -309 0
+-48 -231 -309 0
+-49 232 310 0
+49 -232 310 0
+49 232 -310 0
+-49 -232 -310 0
+-50 233 311 0
+50 -233 311 0
+50 233 -311 0
+-50 -233 -311 0
+-311 312 0
+-310 312 0
+-309 312 0
+309 310 311 -312 0
+2 59 313 0
+-2 -59 313 0
+2 -59 -313 0
+-2 59 -313 0
+3 60 314 0
+-3 -60 314 0
+3 -60 -314 0
+-3 60 -314 0
+4 61 315 0
+-4 -61 315 0
+4 -61 -315 0
+-4 61 -315 0
+315 -316 0
+314 -316 0
+313 -316 0
+312 -316 0
+-59 231 317 0
+59 -231 317 0
+59 231 -317 0
+-59 -231 -317 0
+-60 232 318 0
+60 -232 318 0
+60 232 -318 0
+-60 -232 -318 0
+-61 233 319 0
+61 -233 319 0
+61 233 -319 0
+-61 -233 -319 0
+-319 320 0
+-318 320 0
+-317 320 0
+317 318 319 -320 0
+2 5 321 0
+-2 -5 321 0
+2 -5 -321 0
+-2 5 -321 0
+3 6 322 0
+-3 -6 322 0
+3 -6 -322 0
+-3 6 -322 0
+4 7 323 0
+-4 -7 323 0
+4 -7 -323 0
+-4 7 -323 0
+323 -324 0
+322 -324 0
+321 -324 0
+320 -324 0
+-324 325 0
+-316 325 0
+-308 325 0
+-300 325 0
+-292 325 0
+-284 325 0
+-276 325 0
+-268 325 0
+-260 325 0
+-252 325 0
+-244 325 0
+-236 325 0
+-225 325 0
+-217 325 0
+-209 325 0
+-201 325 0
+-193 325 0
+-185 325 0
+-174 325 0
+-166 325 0
+-158 325 0
+-150 325 0
+-142 325 0
+-134 325 0
+-123 325 0
+-115 325 0
+-107 325 0
+-99 325 0
+-91 325 0
+-83 325 0
+-72 325 0
+-64 325 0
+-53 325 0
+-42 325 0
+-31 325 0
+-20 325 0
+20 31 308 300 292 284 276 268 260 252 244 236 225 217 209 201 193 185 174 166 158 150 142 134 123 115 107 99 91 83 72 64 53 42 316 324 -325 0
+326 327 -330 0
+326 -327 330 0
+-326 327 330 0
+-326 -327 -330 0
+328 -331 333 0
+-328 331 333 0
+328 331 -333 0
+-328 -331 -333 0
+329 -332 334 0
+-329 332 334 0
+329 332 -334 0
+-329 -332 -334 0
+-334 335 0
+-333 335 0
+-326 335 0
+326 333 334 -335 0
+336 337 340 0
+336 -337 -340 0
+-336 337 -340 0
+-336 -337 340 0
+338 341 343 0
+-338 -341 343 0
+338 -341 -343 0
+-338 341 -343 0
+339 342 344 0
+-339 -342 344 0
+339 -342 -344 0
+-339 342 -344 0
+344 -345 0
+343 -345 0
+336 -345 0
+335 -345 0
+327 -340 346 0
+-327 340 346 0
+327 340 -346 0
+-327 -340 -346 0
+328 -341 347 0
+-328 341 347 0
+328 341 -347 0
+-328 -341 -347 0
+329 -342 348 0
+-329 342 348 0
+329 342 -348 0
+-329 -342 -348 0
+-348 349 0
+-347 349 0
+-346 349 0
+346 347 348 -349 0
+337 350 351 0
+-337 350 -351 0
+337 -350 -351 0
+-337 -350 351 0
+338 352 354 0
+-338 -352 354 0
+338 -352 -354 0
+-338 352 -354 0
+339 353 355 0
+-339 -353 355 0
+339 -353 -355 0
+-339 353 -355 0
+355 -356 0
+354 -356 0
+350 -356 0
+349 -356 0
+327 -351 357 0
+-327 351 357 0
+327 351 -357 0
+-327 -351 -357 0
+328 -352 358 0
+-328 352 358 0
+328 352 -358 0
+-328 -352 -358 0
+329 -353 359 0
+-329 353 359 0
+329 353 -359 0
+-329 -353 -359 0
+-359 360 0
+-358 360 0
+-357 360 0
+357 358 359 -360 0
+337 361 362 0
+-337 361 -362 0
+337 -361 -362 0
+-337 -361 362 0
+338 363 365 0
+-338 -363 365 0
+338 -363 -365 0
+-338 363 -365 0
+339 364 366 0
+-339 -364 366 0
+339 -364 -366 0
+-339 364 -366 0
+366 -367 0
+365 -367 0
+361 -367 0
+360 -367 0
+327 -362 368 0
+-327 362 368 0
+327 362 -368 0
+-327 -362 -368 0
+328 -363 369 0
+-328 363 369 0
+328 363 -369 0
+-328 -363 -369 0
+329 -364 370 0
+-329 364 370 0
+329 364 -370 0
+-329 -364 -370 0
+-370 371 0
+-369 371 0
+-368 371 0
+368 369 370 -371 0
+337 372 373 0
+-337 372 -373 0
+337 -372 -373 0
+-337 -372 373 0
+338 374 376 0
+-338 -374 376 0
+338 -374 -376 0
+-338 374 -376 0
+339 375 377 0
+-339 -375 377 0
+339 -375 -377 0
+-339 375 -377 0
+377 -378 0
+376 -378 0
+372 -378 0
+371 -378 0
+327 -373 379 0
+-327 373 379 0
+327 373 -379 0
+-327 -373 -379 0
+328 -374 380 0
+-328 374 380 0
+328 374 -380 0
+-328 -374 -380 0
+329 -375 381 0
+-329 375 381 0
+329 375 -381 0
+-329 -375 -381 0
+-381 382 0
+-380 382 0
+-379 382 0
+379 380 381 -382 0
+337 383 384 0
+-337 383 -384 0
+337 -383 -384 0
+-337 -383 384 0
+338 385 387 0
+-338 -385 387 0
+338 -385 -387 0
+-338 385 -387 0
+339 386 388 0
+-339 -386 388 0
+339 -386 -388 0
+-339 386 -388 0
+388 -389 0
+387 -389 0
+383 -389 0
+382 -389 0
+327 -384 390 0
+-327 384 390 0
+327 384 -390 0
+-327 -384 -390 0
+328 -385 391 0
+-328 385 391 0
+328 385 -391 0
+-328 -385 -391 0
+329 -386 392 0
+-329 386 392 0
+329 386 -392 0
+-329 -386 -392 0
+-392 393 0
+-391 393 0
+-390 393 0
+390 391 392 -393 0
+330 337 394 0
+-330 -337 394 0
+-330 337 -394 0
+330 -337 -394 0
+331 338 395 0
+-331 -338 395 0
+-331 338 -395 0
+331 -338 -395 0
+332 339 396 0
+-332 -339 396 0
+-332 339 -396 0
+332 -339 -396 0
+396 -397 0
+395 -397 0
+394 -397 0
+393 -397 0
+-330 337 398 0
+330 -337 398 0
+330 337 -398 0
+-330 -337 -398 0
+-331 338 399 0
+331 -338 399 0
+331 338 -399 0
+-331 -338 -399 0
+-332 339 400 0
+332 -339 400 0
+332 339 -400 0
+-332 -339 -400 0
+-400 401 0
+-399 401 0
+-398 401 0
+398 399 400 -401 0
+340 402 403 0
+-340 402 -403 0
+-340 -402 403 0
+340 -402 -403 0
+341 404 406 0
+-341 -404 406 0
+-341 404 -406 0
+341 -404 -406 0
+342 405 407 0
+-342 -405 407 0
+-342 405 -407 0
+342 -405 -407 0
+407 -408 0
+406 -408 0
+402 -408 0
+401 -408 0
+337 -340 409 0
+-337 340 409 0
+337 340 -409 0
+-337 -340 -409 0
+338 -341 410 0
+-338 341 410 0
+338 341 -410 0
+-338 -341 -410 0
+339 -342 411 0
+-339 342 411 0
+339 342 -411 0
+-339 -342 -411 0
+-411 412 0
+-410 412 0
+-409 412 0
+409 410 411 -412 0
+351 403 413 0
+-351 -403 413 0
+-351 403 -413 0
+351 -403 -413 0
+352 404 414 0
+-352 -404 414 0
+-352 404 -414 0
+352 -404 -414 0
+353 405 415 0
+-353 -405 415 0
+-353 405 -415 0
+353 -405 -415 0
+415 -416 0
+414 -416 0
+413 -416 0
+412 -416 0
+337 -351 417 0
+-337 351 417 0
+337 351 -417 0
+-337 -351 -417 0
+338 -352 418 0
+-338 352 418 0
+338 352 -418 0
+-338 -352 -418 0
+339 -353 419 0
+-339 353 419 0
+339 353 -419 0
+-339 -353 -419 0
+-419 420 0
+-418 420 0
+-417 420 0
+417 418 419 -420 0
+362 403 421 0
+-362 -403 421 0
+-362 403 -421 0
+362 -403 -421 0
+363 404 422 0
+-363 -404 422 0
+-363 404 -422 0
+363 -404 -422 0
+364 405 423 0
+-364 -405 423 0
+-364 405 -423 0
+364 -405 -423 0
+423 -424 0
+422 -424 0
+421 -424 0
+420 -424 0
+337 -362 425 0
+-337 362 425 0
+337 362 -425 0
+-337 -362 -425 0
+338 -363 426 0
+-338 363 426 0
+338 363 -426 0
+-338 -363 -426 0
+339 -364 427 0
+-339 364 427 0
+339 364 -427 0
+-339 -364 -427 0
+-427 428 0
+-426 428 0
+-425 428 0
+425 426 427 -428 0
+373 403 429 0
+-373 -403 429 0
+-373 403 -429 0
+373 -403 -429 0
+374 404 430 0
+-374 -404 430 0
+-374 404 -430 0
+374 -404 -430 0
+375 405 431 0
+-375 -405 431 0
+-375 405 -431 0
+375 -405 -431 0
+431 -432 0
+430 -432 0
+429 -432 0
+428 -432 0
+337 -373 433 0
+-337 373 433 0
+337 373 -433 0
+-337 -373 -433 0
+338 -374 434 0
+-338 374 434 0
+338 374 -434 0
+-338 -374 -434 0
+339 -375 435 0
+-339 375 435 0
+339 375 -435 0
+-339 -375 -435 0
+-435 436 0
+-434 436 0
+-433 436 0
+433 434 435 -436 0
+384 403 437 0
+-384 -403 437 0
+-384 403 -437 0
+384 -403 -437 0
+385 404 438 0
+-385 -404 438 0
+-385 404 -438 0
+385 -404 -438 0
+386 405 439 0
+-386 -405 439 0
+-386 405 -439 0
+386 -405 -439 0
+439 -440 0
+438 -440 0
+437 -440 0
+436 -440 0
+337 -384 441 0
+-337 384 441 0
+337 384 -441 0
+-337 -384 -441 0
+338 -385 442 0
+-338 385 442 0
+338 385 -442 0
+-338 -385 -442 0
+339 -386 443 0
+-339 386 443 0
+339 386 -443 0
+-339 -386 -443 0
+-443 444 0
+-442 444 0
+-441 444 0
+441 442 443 -444 0
+330 403 445 0
+-330 -403 445 0
+-330 403 -445 0
+330 -403 -445 0
+331 404 446 0
+-331 -404 446 0
+-331 404 -446 0
+331 -404 -446 0
+332 405 447 0
+-332 -405 447 0
+-332 405 -447 0
+332 -405 -447 0
+447 -448 0
+446 -448 0
+445 -448 0
+444 -448 0
+-330 403 449 0
+330 -403 449 0
+330 403 -449 0
+-330 -403 -449 0
+-331 404 450 0
+331 -404 450 0
+331 404 -450 0
+-331 -404 -450 0
+-332 405 451 0
+332 -405 451 0
+332 405 -451 0
+-332 -405 -451 0
+-451 452 0
+-450 452 0
+-449 452 0
+449 450 451 -452 0
+340 453 454 0
+-340 453 -454 0
+-340 -453 454 0
+340 -453 -454 0
+341 455 457 0
+-341 -455 457 0
+-341 455 -457 0
+341 -455 -457 0
+342 456 458 0
+-342 -456 458 0
+-342 456 -458 0
+342 -456 -458 0
+458 -459 0
+457 -459 0
+453 -459 0
+452 -459 0
+-340 403 460 0
+340 -403 460 0
+340 403 -460 0
+-340 -403 -460 0
+-341 404 461 0
+341 -404 461 0
+341 404 -461 0
+-341 -404 -461 0
+-342 405 462 0
+342 -405 462 0
+342 405 -462 0
+-342 -405 -462 0
+-462 463 0
+-461 463 0
+-460 463 0
+460 461 462 -463 0
+351 454 464 0
+-351 -454 464 0
+-351 454 -464 0
+351 -454 -464 0
+352 455 465 0
+-352 -455 465 0
+-352 455 -465 0
+352 -455 -465 0
+353 456 466 0
+-353 -456 466 0
+-353 456 -466 0
+353 -456 -466 0
+466 -467 0
+465 -467 0
+464 -467 0
+463 -467 0
+-351 403 468 0
+351 -403 468 0
+351 403 -468 0
+-351 -403 -468 0
+-352 404 469 0
+352 -404 469 0
+352 404 -469 0
+-352 -404 -469 0
+-353 405 470 0
+353 -405 470 0
+353 405 -470 0
+-353 -405 -470 0
+-470 471 0
+-469 471 0
+-468 471 0
+468 469 470 -471 0
+362 454 472 0
+-362 -454 472 0
+-362 454 -472 0
+362 -454 -472 0
+363 455 473 0
+-363 -455 473 0
+-363 455 -473 0
+363 -455 -473 0
+364 456 474 0
+-364 -456 474 0
+-364 456 -474 0
+364 -456 -474 0
+474 -475 0
+473 -475 0
+472 -475 0
+471 -475 0
+-362 403 476 0
+362 -403 476 0
+362 403 -476 0
+-362 -403 -476 0
+-363 404 477 0
+363 -404 477 0
+363 404 -477 0
+-363 -404 -477 0
+-364 405 478 0
+364 -405 478 0
+364 405 -478 0
+-364 -405 -478 0
+-478 479 0
+-477 479 0
+-476 479 0
+476 477 478 -479 0
+373 454 480 0
+-373 -454 480 0
+-373 454 -480 0
+373 -454 -480 0
+374 455 481 0
+-374 -455 481 0
+-374 455 -481 0
+374 -455 -481 0
+375 456 482 0
+-375 -456 482 0
+-375 456 -482 0
+375 -456 -482 0
+482 -483 0
+481 -483 0
+480 -483 0
+479 -483 0
+-373 403 484 0
+373 -403 484 0
+373 403 -484 0
+-373 -403 -484 0
+-374 404 485 0
+374 -404 485 0
+374 404 -485 0
+-374 -404 -485 0
+-375 405 486 0
+375 -405 486 0
+375 405 -486 0
+-375 -405 -486 0
+-486 487 0
+-485 487 0
+-484 487 0
+484 485 486 -487 0
+384 454 488 0
+-384 -454 488 0
+-384 454 -488 0
+384 -454 -488 0
+385 455 489 0
+-385 -455 489 0
+-385 455 -489 0
+385 -455 -489 0
+386 456 490 0
+-386 -456 490 0
+-386 456 -490 0
+386 -456 -490 0
+490 -491 0
+489 -491 0
+488 -491 0
+487 -491 0
+-384 403 492 0
+384 -403 492 0
+384 403 -492 0
+-384 -403 -492 0
+-385 404 493 0
+385 -404 493 0
+385 404 -493 0
+-385 -404 -493 0
+-386 405 494 0
+386 -405 494 0
+386 405 -494 0
+-386 -405 -494 0
+-494 495 0
+-493 495 0
+-492 495 0
+492 493 494 -495 0
+330 454 496 0
+-330 -454 496 0
+-330 454 -496 0
+330 -454 -496 0
+331 455 497 0
+-331 -455 497 0
+-331 455 -497 0
+331 -455 -497 0
+332 456 498 0
+-332 -456 498 0
+-332 456 -498 0
+332 -456 -498 0
+498 -499 0
+497 -499 0
+496 -499 0
+495 -499 0
+-330 454 500 0
+330 -454 500 0
+330 454 -500 0
+-330 -454 -500 0
+-331 455 501 0
+331 -455 501 0
+331 455 -501 0
+-331 -455 -501 0
+-332 456 502 0
+332 -456 502 0
+332 456 -502 0
+-332 -456 -502 0
+-502 503 0
+-501 503 0
+-500 503 0
+500 501 502 -503 0
+340 504 505 0
+-340 504 -505 0
+-340 -504 505 0
+340 -504 -505 0
+341 506 508 0
+-341 -506 508 0
+-341 506 -508 0
+341 -506 -508 0
+342 507 509 0
+-342 -507 509 0
+-342 507 -509 0
+342 -507 -509 0
+509 -510 0
+508 -510 0
+504 -510 0
+503 -510 0
+-340 454 511 0
+340 -454 511 0
+340 454 -511 0
+-340 -454 -511 0
+-341 455 512 0
+341 -455 512 0
+341 455 -512 0
+-341 -455 -512 0
+-342 456 513 0
+342 -456 513 0
+342 456 -513 0
+-342 -456 -513 0
+-513 514 0
+-512 514 0
+-511 514 0
+511 512 513 -514 0
+351 505 515 0
+-351 -505 515 0
+-351 505 -515 0
+351 -505 -515 0
+352 506 516 0
+-352 -506 516 0
+-352 506 -516 0
+352 -506 -516 0
+353 507 517 0
+-353 -507 517 0
+-353 507 -517 0
+353 -507 -517 0
+517 -518 0
+516 -518 0
+515 -518 0
+514 -518 0
+-351 454 519 0
+351 -454 519 0
+351 454 -519 0
+-351 -454 -519 0
+-352 455 520 0
+352 -455 520 0
+352 455 -520 0
+-352 -455 -520 0
+-353 456 521 0
+353 -456 521 0
+353 456 -521 0
+-353 -456 -521 0
+-521 522 0
+-520 522 0
+-519 522 0
+519 520 521 -522 0
+362 505 523 0
+-362 -505 523 0
+-362 505 -523 0
+362 -505 -523 0
+363 506 524 0
+-363 -506 524 0
+-363 506 -524 0
+363 -506 -524 0
+364 507 525 0
+-364 -507 525 0
+-364 507 -525 0
+364 -507 -525 0
+525 -526 0
+524 -526 0
+523 -526 0
+522 -526 0
+-362 454 527 0
+362 -454 527 0
+362 454 -527 0
+-362 -454 -527 0
+-363 455 528 0
+363 -455 528 0
+363 455 -528 0
+-363 -455 -528 0
+-364 456 529 0
+364 -456 529 0
+364 456 -529 0
+-364 -456 -529 0
+-529 530 0
+-528 530 0
+-527 530 0
+527 528 529 -530 0
+373 505 531 0
+-373 -505 531 0
+-373 505 -531 0
+373 -505 -531 0
+374 506 532 0
+-374 -506 532 0
+-374 506 -532 0
+374 -506 -532 0
+375 507 533 0
+-375 -507 533 0
+-375 507 -533 0
+375 -507 -533 0
+533 -534 0
+532 -534 0
+531 -534 0
+530 -534 0
+-373 454 535 0
+373 -454 535 0
+373 454 -535 0
+-373 -454 -535 0
+-374 455 536 0
+374 -455 536 0
+374 455 -536 0
+-374 -455 -536 0
+-375 456 537 0
+375 -456 537 0
+375 456 -537 0
+-375 -456 -537 0
+-537 538 0
+-536 538 0
+-535 538 0
+535 536 537 -538 0
+384 505 539 0
+-384 -505 539 0
+-384 505 -539 0
+384 -505 -539 0
+385 506 540 0
+-385 -506 540 0
+-385 506 -540 0
+385 -506 -540 0
+386 507 541 0
+-386 -507 541 0
+-386 507 -541 0
+386 -507 -541 0
+541 -542 0
+540 -542 0
+539 -542 0
+538 -542 0
+-384 454 543 0
+384 -454 543 0
+384 454 -543 0
+-384 -454 -543 0
+-385 455 544 0
+385 -455 544 0
+385 455 -544 0
+-385 -455 -544 0
+-386 456 545 0
+386 -456 545 0
+386 456 -545 0
+-386 -456 -545 0
+-545 546 0
+-544 546 0
+-543 546 0
+543 544 545 -546 0
+330 505 547 0
+-330 -505 547 0
+-330 505 -547 0
+330 -505 -547 0
+331 506 548 0
+-331 -506 548 0
+-331 506 -548 0
+331 -506 -548 0
+332 507 549 0
+-332 -507 549 0
+-332 507 -549 0
+332 -507 -549 0
+549 -550 0
+548 -550 0
+547 -550 0
+546 -550 0
+-330 505 551 0
+330 -505 551 0
+330 505 -551 0
+-330 -505 -551 0
+-331 506 552 0
+331 -506 552 0
+331 506 -552 0
+-331 -506 -552 0
+-332 507 553 0
+332 -507 553 0
+332 507 -553 0
+-332 -507 -553 0
+-553 554 0
+-552 554 0
+-551 554 0
+551 552 553 -554 0
+340 555 556 0
+-340 555 -556 0
+-340 -555 556 0
+340 -555 -556 0
+341 557 559 0
+-341 -557 559 0
+-341 557 -559 0
+341 -557 -559 0
+342 558 560 0
+-342 -558 560 0
+-342 558 -560 0
+342 -558 -560 0
+560 -561 0
+559 -561 0
+555 -561 0
+554 -561 0
+-340 505 562 0
+340 -505 562 0
+340 505 -562 0
+-340 -505 -562 0
+-341 506 563 0
+341 -506 563 0
+341 506 -563 0
+-341 -506 -563 0
+-342 507 564 0
+342 -507 564 0
+342 507 -564 0
+-342 -507 -564 0
+-564 565 0
+-563 565 0
+-562 565 0
+562 563 564 -565 0
+351 556 566 0
+-351 -556 566 0
+-351 556 -566 0
+351 -556 -566 0
+352 557 567 0
+-352 -557 567 0
+-352 557 -567 0
+352 -557 -567 0
+353 558 568 0
+-353 -558 568 0
+-353 558 -568 0
+353 -558 -568 0
+568 -569 0
+567 -569 0
+566 -569 0
+565 -569 0
+-351 505 570 0
+351 -505 570 0
+351 505 -570 0
+-351 -505 -570 0
+-352 506 571 0
+352 -506 571 0
+352 506 -571 0
+-352 -506 -571 0
+-353 507 572 0
+353 -507 572 0
+353 507 -572 0
+-353 -507 -572 0
+-572 573 0
+-571 573 0
+-570 573 0
+570 571 572 -573 0
+362 556 574 0
+-362 -556 574 0
+-362 556 -574 0
+362 -556 -574 0
+363 557 575 0
+-363 -557 575 0
+-363 557 -575 0
+363 -557 -575 0
+364 558 576 0
+-364 -558 576 0
+-364 558 -576 0
+364 -558 -576 0
+576 -577 0
+575 -577 0
+574 -577 0
+573 -577 0
+-362 505 578 0
+362 -505 578 0
+362 505 -578 0
+-362 -505 -578 0
+-363 506 579 0
+363 -506 579 0
+363 506 -579 0
+-363 -506 -579 0
+-364 507 580 0
+364 -507 580 0
+364 507 -580 0
+-364 -507 -580 0
+-580 581 0
+-579 581 0
+-578 581 0
+578 579 580 -581 0
+373 556 582 0
+-373 -556 582 0
+-373 556 -582 0
+373 -556 -582 0
+374 557 583 0
+-374 -557 583 0
+-374 557 -583 0
+374 -557 -583 0
+375 558 584 0
+-375 -558 584 0
+-375 558 -584 0
+375 -558 -584 0
+584 -585 0
+583 -585 0
+582 -585 0
+581 -585 0
+-373 505 586 0
+373 -505 586 0
+373 505 -586 0
+-373 -505 -586 0
+-374 506 587 0
+374 -506 587 0
+374 506 -587 0
+-374 -506 -587 0
+-375 507 588 0
+375 -507 588 0
+375 507 -588 0
+-375 -507 -588 0
+-588 589 0
+-587 589 0
+-586 589 0
+586 587 588 -589 0
+384 556 590 0
+-384 -556 590 0
+-384 556 -590 0
+384 -556 -590 0
+385 557 591 0
+-385 -557 591 0
+-385 557 -591 0
+385 -557 -591 0
+386 558 592 0
+-386 -558 592 0
+-386 558 -592 0
+386 -558 -592 0
+592 -593 0
+591 -593 0
+590 -593 0
+589 -593 0
+-384 505 594 0
+384 -505 594 0
+384 505 -594 0
+-384 -505 -594 0
+-385 506 595 0
+385 -506 595 0
+385 506 -595 0
+-385 -506 -595 0
+-386 507 596 0
+386 -507 596 0
+386 507 -596 0
+-386 -507 -596 0
+-596 597 0
+-595 597 0
+-594 597 0
+594 595 596 -597 0
+330 556 598 0
+-330 -556 598 0
+-330 556 -598 0
+330 -556 -598 0
+331 557 599 0
+-331 -557 599 0
+-331 557 -599 0
+331 -557 -599 0
+332 558 600 0
+-332 -558 600 0
+-332 558 -600 0
+332 -558 -600 0
+600 -601 0
+599 -601 0
+598 -601 0
+597 -601 0
+-330 556 602 0
+330 -556 602 0
+330 556 -602 0
+-330 -556 -602 0
+-331 557 603 0
+331 -557 603 0
+331 557 -603 0
+-331 -557 -603 0
+-332 558 604 0
+332 -558 604 0
+332 558 -604 0
+-332 -558 -604 0
+-604 605 0
+-603 605 0
+-602 605 0
+602 603 604 -605 0
+327 340 606 0
+-327 -340 606 0
+327 -340 -606 0
+-327 340 -606 0
+328 341 607 0
+-328 -341 607 0
+328 -341 -607 0
+-328 341 -607 0
+329 342 608 0
+-329 -342 608 0
+329 -342 -608 0
+-329 342 -608 0
+608 -609 0
+607 -609 0
+606 -609 0
+605 -609 0
+-340 556 610 0
+340 -556 610 0
+340 556 -610 0
+-340 -556 -610 0
+-341 557 611 0
+341 -557 611 0
+341 557 -611 0
+-341 -557 -611 0
+-342 558 612 0
+342 -558 612 0
+342 558 -612 0
+-342 -558 -612 0
+-612 613 0
+-611 613 0
+-610 613 0
+610 611 612 -613 0
+327 351 614 0
+-327 -351 614 0
+327 -351 -614 0
+-327 351 -614 0
+328 352 615 0
+-328 -352 615 0
+328 -352 -615 0
+-328 352 -615 0
+329 353 616 0
+-329 -353 616 0
+329 -353 -616 0
+-329 353 -616 0
+616 -617 0
+615 -617 0
+614 -617 0
+613 -617 0
+-351 556 618 0
+351 -556 618 0
+351 556 -618 0
+-351 -556 -618 0
+-352 557 619 0
+352 -557 619 0
+352 557 -619 0
+-352 -557 -619 0
+-353 558 620 0
+353 -558 620 0
+353 558 -620 0
+-353 -558 -620 0
+-620 621 0
+-619 621 0
+-618 621 0
+618 619 620 -621 0
+327 362 622 0
+-327 -362 622 0
+327 -362 -622 0
+-327 362 -622 0
+328 363 623 0
+-328 -363 623 0
+328 -363 -623 0
+-328 363 -623 0
+329 364 624 0
+-329 -364 624 0
+329 -364 -624 0
+-329 364 -624 0
+624 -625 0
+623 -625 0
+622 -625 0
+621 -625 0
+-362 556 626 0
+362 -556 626 0
+362 556 -626 0
+-362 -556 -626 0
+-363 557 627 0
+363 -557 627 0
+363 557 -627 0
+-363 -557 -627 0
+-364 558 628 0
+364 -558 628 0
+364 558 -628 0
+-364 -558 -628 0
+-628 629 0
+-627 629 0
+-626 629 0
+626 627 628 -629 0
+327 373 630 0
+-327 -373 630 0
+327 -373 -630 0
+-327 373 -630 0
+328 374 631 0
+-328 -374 631 0
+328 -374 -631 0
+-328 374 -631 0
+329 375 632 0
+-329 -375 632 0
+329 -375 -632 0
+-329 375 -632 0
+632 -633 0
+631 -633 0
+630 -633 0
+629 -633 0
+-373 556 634 0
+373 -556 634 0
+373 556 -634 0
+-373 -556 -634 0
+-374 557 635 0
+374 -557 635 0
+374 557 -635 0
+-374 -557 -635 0
+-375 558 636 0
+375 -558 636 0
+375 558 -636 0
+-375 -558 -636 0
+-636 637 0
+-635 637 0
+-634 637 0
+634 635 636 -637 0
+327 384 638 0
+-327 -384 638 0
+327 -384 -638 0
+-327 384 -638 0
+328 385 639 0
+-328 -385 639 0
+328 -385 -639 0
+-328 385 -639 0
+329 386 640 0
+-329 -386 640 0
+329 -386 -640 0
+-329 386 -640 0
+640 -641 0
+639 -641 0
+638 -641 0
+637 -641 0
+-384 556 642 0
+384 -556 642 0
+384 556 -642 0
+-384 -556 -642 0
+-385 557 643 0
+385 -557 643 0
+385 557 -643 0
+-385 -557 -643 0
+-386 558 644 0
+386 -558 644 0
+386 558 -644 0
+-386 -558 -644 0
+-644 645 0
+-643 645 0
+-642 645 0
+642 643 644 -645 0
+327 330 646 0
+-327 -330 646 0
+327 -330 -646 0
+-327 330 -646 0
+328 331 647 0
+-328 -331 647 0
+328 -331 -647 0
+-328 331 -647 0
+329 332 648 0
+-329 -332 648 0
+329 -332 -648 0
+-329 332 -648 0
+648 -649 0
+647 -649 0
+646 -649 0
+645 -649 0
+650 651 -654 0
+650 -651 654 0
+-650 651 654 0
+-650 -651 -654 0
+652 -655 657 0
+-652 655 657 0
+652 655 -657 0
+-652 -655 -657 0
+653 -656 658 0
+-653 656 658 0
+653 656 -658 0
+-653 -656 -658 0
+-658 659 0
+-657 659 0
+-650 659 0
+650 657 658 -659 0
+660 661 664 0
+660 -661 -664 0
+-660 661 -664 0
+-660 -661 664 0
+662 665 667 0
+-662 -665 667 0
+662 -665 -667 0
+-662 665 -667 0
+663 666 668 0
+-663 -666 668 0
+663 -666 -668 0
+-663 666 -668 0
+668 -669 0
+667 -669 0
+660 -669 0
+659 -669 0
+651 -664 670 0
+-651 664 670 0
+651 664 -670 0
+-651 -664 -670 0
+652 -665 671 0
+-652 665 671 0
+652 665 -671 0
+-652 -665 -671 0
+653 -666 672 0
+-653 666 672 0
+653 666 -672 0
+-653 -666 -672 0
+-672 673 0
+-671 673 0
+-670 673 0
+670 671 672 -673 0
+661 674 675 0
+-661 674 -675 0
+661 -674 -675 0
+-661 -674 675 0
+662 676 678 0
+-662 -676 678 0
+662 -676 -678 0
+-662 676 -678 0
+663 677 679 0
+-663 -677 679 0
+663 -677 -679 0
+-663 677 -679 0
+679 -680 0
+678 -680 0
+674 -680 0
+673 -680 0
+651 -675 681 0
+-651 675 681 0
+651 675 -681 0
+-651 -675 -681 0
+652 -676 682 0
+-652 676 682 0
+652 676 -682 0
+-652 -676 -682 0
+653 -677 683 0
+-653 677 683 0
+653 677 -683 0
+-653 -677 -683 0
+-683 684 0
+-682 684 0
+-681 684 0
+681 682 683 -684 0
+661 685 686 0
+-661 685 -686 0
+661 -685 -686 0
+-661 -685 686 0
+662 687 689 0
+-662 -687 689 0
+662 -687 -689 0
+-662 687 -689 0
+663 688 690 0
+-663 -688 690 0
+663 -688 -690 0
+-663 688 -690 0
+690 -691 0
+689 -691 0
+685 -691 0
+684 -691 0
+651 -686 692 0
+-651 686 692 0
+651 686 -692 0
+-651 -686 -692 0
+652 -687 693 0
+-652 687 693 0
+652 687 -693 0
+-652 -687 -693 0
+653 -688 694 0
+-653 688 694 0
+653 688 -694 0
+-653 -688 -694 0
+-694 695 0
+-693 695 0
+-692 695 0
+692 693 694 -695 0
+661 696 697 0
+-661 696 -697 0
+661 -696 -697 0
+-661 -696 697 0
+662 698 700 0
+-662 -698 700 0
+662 -698 -700 0
+-662 698 -700 0
+663 699 701 0
+-663 -699 701 0
+663 -699 -701 0
+-663 699 -701 0
+701 -702 0
+700 -702 0
+696 -702 0
+695 -702 0
+651 -697 703 0
+-651 697 703 0
+651 697 -703 0
+-651 -697 -703 0
+652 -698 704 0
+-652 698 704 0
+652 698 -704 0
+-652 -698 -704 0
+653 -699 705 0
+-653 699 705 0
+653 699 -705 0
+-653 -699 -705 0
+-705 706 0
+-704 706 0
+-703 706 0
+703 704 705 -706 0
+661 707 708 0
+-661 707 -708 0
+661 -707 -708 0
+-661 -707 708 0
+662 709 711 0
+-662 -709 711 0
+662 -709 -711 0
+-662 709 -711 0
+663 710 712 0
+-663 -710 712 0
+663 -710 -712 0
+-663 710 -712 0
+712 -713 0
+711 -713 0
+707 -713 0
+706 -713 0
+651 -708 714 0
+-651 708 714 0
+651 708 -714 0
+-651 -708 -714 0
+652 -709 715 0
+-652 709 715 0
+652 709 -715 0
+-652 -709 -715 0
+653 -710 716 0
+-653 710 716 0
+653 710 -716 0
+-653 -710 -716 0
+-716 717 0
+-715 717 0
+-714 717 0
+714 715 716 -717 0
+654 661 718 0
+-654 -661 718 0
+-654 661 -718 0
+654 -661 -718 0
+655 662 719 0
+-655 -662 719 0
+-655 662 -719 0
+655 -662 -719 0
+656 663 720 0
+-656 -663 720 0
+-656 663 -720 0
+656 -663 -720 0
+720 -721 0
+719 -721 0
+718 -721 0
+717 -721 0
+-654 661 722 0
+654 -661 722 0
+654 661 -722 0
+-654 -661 -722 0
+-655 662 723 0
+655 -662 723 0
+655 662 -723 0
+-655 -662 -723 0
+-656 663 724 0
+656 -663 724 0
+656 663 -724 0
+-656 -663 -724 0
+-724 725 0
+-723 725 0
+-722 725 0
+722 723 724 -725 0
+664 726 727 0
+-664 726 -727 0
+-664 -726 727 0
+664 -726 -727 0
+665 728 730 0
+-665 -728 730 0
+-665 728 -730 0
+665 -728 -730 0
+666 729 731 0
+-666 -729 731 0
+-666 729 -731 0
+666 -729 -731 0
+731 -732 0
+730 -732 0
+726 -732 0
+725 -732 0
+661 -664 733 0
+-661 664 733 0
+661 664 -733 0
+-661 -664 -733 0
+662 -665 734 0
+-662 665 734 0
+662 665 -734 0
+-662 -665 -734 0
+663 -666 735 0
+-663 666 735 0
+663 666 -735 0
+-663 -666 -735 0
+-735 736 0
+-734 736 0
+-733 736 0
+733 734 735 -736 0
+675 727 737 0
+-675 -727 737 0
+-675 727 -737 0
+675 -727 -737 0
+676 728 738 0
+-676 -728 738 0
+-676 728 -738 0
+676 -728 -738 0
+677 729 739 0
+-677 -729 739 0
+-677 729 -739 0
+677 -729 -739 0
+739 -740 0
+738 -740 0
+737 -740 0
+736 -740 0
+661 -675 741 0
+-661 675 741 0
+661 675 -741 0
+-661 -675 -741 0
+662 -676 742 0
+-662 676 742 0
+662 676 -742 0
+-662 -676 -742 0
+663 -677 743 0
+-663 677 743 0
+663 677 -743 0
+-663 -677 -743 0
+-743 744 0
+-742 744 0
+-741 744 0
+741 742 743 -744 0
+686 727 745 0
+-686 -727 745 0
+-686 727 -745 0
+686 -727 -745 0
+687 728 746 0
+-687 -728 746 0
+-687 728 -746 0
+687 -728 -746 0
+688 729 747 0
+-688 -729 747 0
+-688 729 -747 0
+688 -729 -747 0
+747 -748 0
+746 -748 0
+745 -748 0
+744 -748 0
+661 -686 749 0
+-661 686 749 0
+661 686 -749 0
+-661 -686 -749 0
+662 -687 750 0
+-662 687 750 0
+662 687 -750 0
+-662 -687 -750 0
+663 -688 751 0
+-663 688 751 0
+663 688 -751 0
+-663 -688 -751 0
+-751 752 0
+-750 752 0
+-749 752 0
+749 750 751 -752 0
+697 727 753 0
+-697 -727 753 0
+-697 727 -753 0
+697 -727 -753 0
+698 728 754 0
+-698 -728 754 0
+-698 728 -754 0
+698 -728 -754 0
+699 729 755 0
+-699 -729 755 0
+-699 729 -755 0
+699 -729 -755 0
+755 -756 0
+754 -756 0
+753 -756 0
+752 -756 0
+661 -697 757 0
+-661 697 757 0
+661 697 -757 0
+-661 -697 -757 0
+662 -698 758 0
+-662 698 758 0
+662 698 -758 0
+-662 -698 -758 0
+663 -699 759 0
+-663 699 759 0
+663 699 -759 0
+-663 -699 -759 0
+-759 760 0
+-758 760 0
+-757 760 0
+757 758 759 -760 0
+708 727 761 0
+-708 -727 761 0
+-708 727 -761 0
+708 -727 -761 0
+709 728 762 0
+-709 -728 762 0
+-709 728 -762 0
+709 -728 -762 0
+710 729 763 0
+-710 -729 763 0
+-710 729 -763 0
+710 -729 -763 0
+763 -764 0
+762 -764 0
+761 -764 0
+760 -764 0
+661 -708 765 0
+-661 708 765 0
+661 708 -765 0
+-661 -708 -765 0
+662 -709 766 0
+-662 709 766 0
+662 709 -766 0
+-662 -709 -766 0
+663 -710 767 0
+-663 710 767 0
+663 710 -767 0
+-663 -710 -767 0
+-767 768 0
+-766 768 0
+-765 768 0
+765 766 767 -768 0
+654 727 769 0
+-654 -727 769 0
+-654 727 -769 0
+654 -727 -769 0
+655 728 770 0
+-655 -728 770 0
+-655 728 -770 0
+655 -728 -770 0
+656 729 771 0
+-656 -729 771 0
+-656 729 -771 0
+656 -729 -771 0
+771 -772 0
+770 -772 0
+769 -772 0
+768 -772 0
+-654 727 773 0
+654 -727 773 0
+654 727 -773 0
+-654 -727 -773 0
+-655 728 774 0
+655 -728 774 0
+655 728 -774 0
+-655 -728 -774 0
+-656 729 775 0
+656 -729 775 0
+656 729 -775 0
+-656 -729 -775 0
+-775 776 0
+-774 776 0
+-773 776 0
+773 774 775 -776 0
+664 777 778 0
+-664 777 -778 0
+-664 -777 778 0
+664 -777 -778 0
+665 779 781 0
+-665 -779 781 0
+-665 779 -781 0
+665 -779 -781 0
+666 780 782 0
+-666 -780 782 0
+-666 780 -782 0
+666 -780 -782 0
+782 -783 0
+781 -783 0
+777 -783 0
+776 -783 0
+-664 727 784 0
+664 -727 784 0
+664 727 -784 0
+-664 -727 -784 0
+-665 728 785 0
+665 -728 785 0
+665 728 -785 0
+-665 -728 -785 0
+-666 729 786 0
+666 -729 786 0
+666 729 -786 0
+-666 -729 -786 0
+-786 787 0
+-785 787 0
+-784 787 0
+784 785 786 -787 0
+675 778 788 0
+-675 -778 788 0
+-675 778 -788 0
+675 -778 -788 0
+676 779 789 0
+-676 -779 789 0
+-676 779 -789 0
+676 -779 -789 0
+677 780 790 0
+-677 -780 790 0
+-677 780 -790 0
+677 -780 -790 0
+790 -791 0
+789 -791 0
+788 -791 0
+787 -791 0
+-675 727 792 0
+675 -727 792 0
+675 727 -792 0
+-675 -727 -792 0
+-676 728 793 0
+676 -728 793 0
+676 728 -793 0
+-676 -728 -793 0
+-677 729 794 0
+677 -729 794 0
+677 729 -794 0
+-677 -729 -794 0
+-794 795 0
+-793 795 0
+-792 795 0
+792 793 794 -795 0
+686 778 796 0
+-686 -778 796 0
+-686 778 -796 0
+686 -778 -796 0
+687 779 797 0
+-687 -779 797 0
+-687 779 -797 0
+687 -779 -797 0
+688 780 798 0
+-688 -780 798 0
+-688 780 -798 0
+688 -780 -798 0
+798 -799 0
+797 -799 0
+796 -799 0
+795 -799 0
+-686 727 800 0
+686 -727 800 0
+686 727 -800 0
+-686 -727 -800 0
+-687 728 801 0
+687 -728 801 0
+687 728 -801 0
+-687 -728 -801 0
+-688 729 802 0
+688 -729 802 0
+688 729 -802 0
+-688 -729 -802 0
+-802 803 0
+-801 803 0
+-800 803 0
+800 801 802 -803 0
+697 778 804 0
+-697 -778 804 0
+-697 778 -804 0
+697 -778 -804 0
+698 779 805 0
+-698 -779 805 0
+-698 779 -805 0
+698 -779 -805 0
+699 780 806 0
+-699 -780 806 0
+-699 780 -806 0
+699 -780 -806 0
+806 -807 0
+805 -807 0
+804 -807 0
+803 -807 0
+-697 727 808 0
+697 -727 808 0
+697 727 -808 0
+-697 -727 -808 0
+-698 728 809 0
+698 -728 809 0
+698 728 -809 0
+-698 -728 -809 0
+-699 729 810 0
+699 -729 810 0
+699 729 -810 0
+-699 -729 -810 0
+-810 811 0
+-809 811 0
+-808 811 0
+808 809 810 -811 0
+708 778 812 0
+-708 -778 812 0
+-708 778 -812 0
+708 -778 -812 0
+709 779 813 0
+-709 -779 813 0
+-709 779 -813 0
+709 -779 -813 0
+710 780 814 0
+-710 -780 814 0
+-710 780 -814 0
+710 -780 -814 0
+814 -815 0
+813 -815 0
+812 -815 0
+811 -815 0
+-708 727 816 0
+708 -727 816 0
+708 727 -816 0
+-708 -727 -816 0
+-709 728 817 0
+709 -728 817 0
+709 728 -817 0
+-709 -728 -817 0
+-710 729 818 0
+710 -729 818 0
+710 729 -818 0
+-710 -729 -818 0
+-818 819 0
+-817 819 0
+-816 819 0
+816 817 818 -819 0
+654 778 820 0
+-654 -778 820 0
+-654 778 -820 0
+654 -778 -820 0
+655 779 821 0
+-655 -779 821 0
+-655 779 -821 0
+655 -779 -821 0
+656 780 822 0
+-656 -780 822 0
+-656 780 -822 0
+656 -780 -822 0
+822 -823 0
+821 -823 0
+820 -823 0
+819 -823 0
+-654 778 824 0
+654 -778 824 0
+654 778 -824 0
+-654 -778 -824 0
+-655 779 825 0
+655 -779 825 0
+655 779 -825 0
+-655 -779 -825 0
+-656 780 826 0
+656 -780 826 0
+656 780 -826 0
+-656 -780 -826 0
+-826 827 0
+-825 827 0
+-824 827 0
+824 825 826 -827 0
+664 828 829 0
+-664 828 -829 0
+-664 -828 829 0
+664 -828 -829 0
+665 830 832 0
+-665 -830 832 0
+-665 830 -832 0
+665 -830 -832 0
+666 831 833 0
+-666 -831 833 0
+-666 831 -833 0
+666 -831 -833 0
+833 -834 0
+832 -834 0
+828 -834 0
+827 -834 0
+-664 778 835 0
+664 -778 835 0
+664 778 -835 0
+-664 -778 -835 0
+-665 779 836 0
+665 -779 836 0
+665 779 -836 0
+-665 -779 -836 0
+-666 780 837 0
+666 -780 837 0
+666 780 -837 0
+-666 -780 -837 0
+-837 838 0
+-836 838 0
+-835 838 0
+835 836 837 -838 0
+675 829 839 0
+-675 -829 839 0
+-675 829 -839 0
+675 -829 -839 0
+676 830 840 0
+-676 -830 840 0
+-676 830 -840 0
+676 -830 -840 0
+677 831 841 0
+-677 -831 841 0
+-677 831 -841 0
+677 -831 -841 0
+841 -842 0
+840 -842 0
+839 -842 0
+838 -842 0
+-675 778 843 0
+675 -778 843 0
+675 778 -843 0
+-675 -778 -843 0
+-676 779 844 0
+676 -779 844 0
+676 779 -844 0
+-676 -779 -844 0
+-677 780 845 0
+677 -780 845 0
+677 780 -845 0
+-677 -780 -845 0
+-845 846 0
+-844 846 0
+-843 846 0
+843 844 845 -846 0
+686 829 847 0
+-686 -829 847 0
+-686 829 -847 0
+686 -829 -847 0
+687 830 848 0
+-687 -830 848 0
+-687 830 -848 0
+687 -830 -848 0
+688 831 849 0
+-688 -831 849 0
+-688 831 -849 0
+688 -831 -849 0
+849 -850 0
+848 -850 0
+847 -850 0
+846 -850 0
+-686 778 851 0
+686 -778 851 0
+686 778 -851 0
+-686 -778 -851 0
+-687 779 852 0
+687 -779 852 0
+687 779 -852 0
+-687 -779 -852 0
+-688 780 853 0
+688 -780 853 0
+688 780 -853 0
+-688 -780 -853 0
+-853 854 0
+-852 854 0
+-851 854 0
+851 852 853 -854 0
+697 829 855 0
+-697 -829 855 0
+-697 829 -855 0
+697 -829 -855 0
+698 830 856 0
+-698 -830 856 0
+-698 830 -856 0
+698 -830 -856 0
+699 831 857 0
+-699 -831 857 0
+-699 831 -857 0
+699 -831 -857 0
+857 -858 0
+856 -858 0
+855 -858 0
+854 -858 0
+-697 778 859 0
+697 -778 859 0
+697 778 -859 0
+-697 -778 -859 0
+-698 779 860 0
+698 -779 860 0
+698 779 -860 0
+-698 -779 -860 0
+-699 780 861 0
+699 -780 861 0
+699 780 -861 0
+-699 -780 -861 0
+-861 862 0
+-860 862 0
+-859 862 0
+859 860 861 -862 0
+708 829 863 0
+-708 -829 863 0
+-708 829 -863 0
+708 -829 -863 0
+709 830 864 0
+-709 -830 864 0
+-709 830 -864 0
+709 -830 -864 0
+710 831 865 0
+-710 -831 865 0
+-710 831 -865 0
+710 -831 -865 0
+865 -866 0
+864 -866 0
+863 -866 0
+862 -866 0
+-708 778 867 0
+708 -778 867 0
+708 778 -867 0
+-708 -778 -867 0
+-709 779 868 0
+709 -779 868 0
+709 779 -868 0
+-709 -779 -868 0
+-710 780 869 0
+710 -780 869 0
+710 780 -869 0
+-710 -780 -869 0
+-869 870 0
+-868 870 0
+-867 870 0
+867 868 869 -870 0
+654 829 871 0
+-654 -829 871 0
+-654 829 -871 0
+654 -829 -871 0
+655 830 872 0
+-655 -830 872 0
+-655 830 -872 0
+655 -830 -872 0
+656 831 873 0
+-656 -831 873 0
+-656 831 -873 0
+656 -831 -873 0
+873 -874 0
+872 -874 0
+871 -874 0
+870 -874 0
+-654 829 875 0
+654 -829 875 0
+654 829 -875 0
+-654 -829 -875 0
+-655 830 876 0
+655 -830 876 0
+655 830 -876 0
+-655 -830 -876 0
+-656 831 877 0
+656 -831 877 0
+656 831 -877 0
+-656 -831 -877 0
+-877 878 0
+-876 878 0
+-875 878 0
+875 876 877 -878 0
+664 879 880 0
+-664 879 -880 0
+-664 -879 880 0
+664 -879 -880 0
+665 881 883 0
+-665 -881 883 0
+-665 881 -883 0
+665 -881 -883 0
+666 882 884 0
+-666 -882 884 0
+-666 882 -884 0
+666 -882 -884 0
+884 -885 0
+883 -885 0
+879 -885 0
+878 -885 0
+-664 829 886 0
+664 -829 886 0
+664 829 -886 0
+-664 -829 -886 0
+-665 830 887 0
+665 -830 887 0
+665 830 -887 0
+-665 -830 -887 0
+-666 831 888 0
+666 -831 888 0
+666 831 -888 0
+-666 -831 -888 0
+-888 889 0
+-887 889 0
+-886 889 0
+886 887 888 -889 0
+675 880 890 0
+-675 -880 890 0
+-675 880 -890 0
+675 -880 -890 0
+676 881 891 0
+-676 -881 891 0
+-676 881 -891 0
+676 -881 -891 0
+677 882 892 0
+-677 -882 892 0
+-677 882 -892 0
+677 -882 -892 0
+892 -893 0
+891 -893 0
+890 -893 0
+889 -893 0
+-675 829 894 0
+675 -829 894 0
+675 829 -894 0
+-675 -829 -894 0
+-676 830 895 0
+676 -830 895 0
+676 830 -895 0
+-676 -830 -895 0
+-677 831 896 0
+677 -831 896 0
+677 831 -896 0
+-677 -831 -896 0
+-896 897 0
+-895 897 0
+-894 897 0
+894 895 896 -897 0
+686 880 898 0
+-686 -880 898 0
+-686 880 -898 0
+686 -880 -898 0
+687 881 899 0
+-687 -881 899 0
+-687 881 -899 0
+687 -881 -899 0
+688 882 900 0
+-688 -882 900 0
+-688 882 -900 0
+688 -882 -900 0
+900 -901 0
+899 -901 0
+898 -901 0
+897 -901 0
+-686 829 902 0
+686 -829 902 0
+686 829 -902 0
+-686 -829 -902 0
+-687 830 903 0
+687 -830 903 0
+687 830 -903 0
+-687 -830 -903 0
+-688 831 904 0
+688 -831 904 0
+688 831 -904 0
+-688 -831 -904 0
+-904 905 0
+-903 905 0
+-902 905 0
+902 903 904 -905 0
+697 880 906 0
+-697 -880 906 0
+-697 880 -906 0
+697 -880 -906 0
+698 881 907 0
+-698 -881 907 0
+-698 881 -907 0
+698 -881 -907 0
+699 882 908 0
+-699 -882 908 0
+-699 882 -908 0
+699 -882 -908 0
+908 -909 0
+907 -909 0
+906 -909 0
+905 -909 0
+-697 829 910 0
+697 -829 910 0
+697 829 -910 0
+-697 -829 -910 0
+-698 830 911 0
+698 -830 911 0
+698 830 -911 0
+-698 -830 -911 0
+-699 831 912 0
+699 -831 912 0
+699 831 -912 0
+-699 -831 -912 0
+-912 913 0
+-911 913 0
+-910 913 0
+910 911 912 -913 0
+708 880 914 0
+-708 -880 914 0
+-708 880 -914 0
+708 -880 -914 0
+709 881 915 0
+-709 -881 915 0
+-709 881 -915 0
+709 -881 -915 0
+710 882 916 0
+-710 -882 916 0
+-710 882 -916 0
+710 -882 -916 0
+916 -917 0
+915 -917 0
+914 -917 0
+913 -917 0
+-708 829 918 0
+708 -829 918 0
+708 829 -918 0
+-708 -829 -918 0
+-709 830 919 0
+709 -830 919 0
+709 830 -919 0
+-709 -830 -919 0
+-710 831 920 0
+710 -831 920 0
+710 831 -920 0
+-710 -831 -920 0
+-920 921 0
+-919 921 0
+-918 921 0
+918 919 920 -921 0
+654 880 922 0
+-654 -880 922 0
+-654 880 -922 0
+654 -880 -922 0
+655 881 923 0
+-655 -881 923 0
+-655 881 -923 0
+655 -881 -923 0
+656 882 924 0
+-656 -882 924 0
+-656 882 -924 0
+656 -882 -924 0
+924 -925 0
+923 -925 0
+922 -925 0
+921 -925 0
+-654 880 926 0
+654 -880 926 0
+654 880 -926 0
+-654 -880 -926 0
+-655 881 927 0
+655 -881 927 0
+655 881 -927 0
+-655 -881 -927 0
+-656 882 928 0
+656 -882 928 0
+656 882 -928 0
+-656 -882 -928 0
+-928 929 0
+-927 929 0
+-926 929 0
+926 927 928 -929 0
+651 664 930 0
+-651 -664 930 0
+651 -664 -930 0
+-651 664 -930 0
+652 665 931 0
+-652 -665 931 0
+652 -665 -931 0
+-652 665 -931 0
+653 666 932 0
+-653 -666 932 0
+653 -666 -932 0
+-653 666 -932 0
+932 -933 0
+931 -933 0
+930 -933 0
+929 -933 0
+-664 880 934 0
+664 -880 934 0
+664 880 -934 0
+-664 -880 -934 0
+-665 881 935 0
+665 -881 935 0
+665 881 -935 0
+-665 -881 -935 0
+-666 882 936 0
+666 -882 936 0
+666 882 -936 0
+-666 -882 -936 0
+-936 937 0
+-935 937 0
+-934 937 0
+934 935 936 -937 0
+651 675 938 0
+-651 -675 938 0
+651 -675 -938 0
+-651 675 -938 0
+652 676 939 0
+-652 -676 939 0
+652 -676 -939 0
+-652 676 -939 0
+653 677 940 0
+-653 -677 940 0
+653 -677 -940 0
+-653 677 -940 0
+940 -941 0
+939 -941 0
+938 -941 0
+937 -941 0
+-675 880 942 0
+675 -880 942 0
+675 880 -942 0
+-675 -880 -942 0
+-676 881 943 0
+676 -881 943 0
+676 881 -943 0
+-676 -881 -943 0
+-677 882 944 0
+677 -882 944 0
+677 882 -944 0
+-677 -882 -944 0
+-944 945 0
+-943 945 0
+-942 945 0
+942 943 944 -945 0
+651 686 946 0
+-651 -686 946 0
+651 -686 -946 0
+-651 686 -946 0
+652 687 947 0
+-652 -687 947 0
+652 -687 -947 0
+-652 687 -947 0
+653 688 948 0
+-653 -688 948 0
+653 -688 -948 0
+-653 688 -948 0
+948 -949 0
+947 -949 0
+946 -949 0
+945 -949 0
+-686 880 950 0
+686 -880 950 0
+686 880 -950 0
+-686 -880 -950 0
+-687 881 951 0
+687 -881 951 0
+687 881 -951 0
+-687 -881 -951 0
+-688 882 952 0
+688 -882 952 0
+688 882 -952 0
+-688 -882 -952 0
+-952 953 0
+-951 953 0
+-950 953 0
+950 951 952 -953 0
+651 697 954 0
+-651 -697 954 0
+651 -697 -954 0
+-651 697 -954 0
+652 698 955 0
+-652 -698 955 0
+652 -698 -955 0
+-652 698 -955 0
+653 699 956 0
+-653 -699 956 0
+653 -699 -956 0
+-653 699 -956 0
+956 -957 0
+955 -957 0
+954 -957 0
+953 -957 0
+-697 880 958 0
+697 -880 958 0
+697 880 -958 0
+-697 -880 -958 0
+-698 881 959 0
+698 -881 959 0
+698 881 -959 0
+-698 -881 -959 0
+-699 882 960 0
+699 -882 960 0
+699 882 -960 0
+-699 -882 -960 0
+-960 961 0
+-959 961 0
+-958 961 0
+958 959 960 -961 0
+651 708 962 0
+-651 -708 962 0
+651 -708 -962 0
+-651 708 -962 0
+652 709 963 0
+-652 -709 963 0
+652 -709 -963 0
+-652 709 -963 0
+653 710 964 0
+-653 -710 964 0
+653 -710 -964 0
+-653 710 -964 0
+964 -965 0
+963 -965 0
+962 -965 0
+961 -965 0
+-708 880 966 0
+708 -880 966 0
+708 880 -966 0
+-708 -880 -966 0
+-709 881 967 0
+709 -881 967 0
+709 881 -967 0
+-709 -881 -967 0
+-710 882 968 0
+710 -882 968 0
+710 882 -968 0
+-710 -882 -968 0
+-968 969 0
+-967 969 0
+-966 969 0
+966 967 968 -969 0
+651 654 970 0
+-651 -654 970 0
+651 -654 -970 0
+-651 654 -970 0
+652 655 971 0
+-652 -655 971 0
+652 -655 -971 0
+-652 655 -971 0
+653 656 972 0
+-653 -656 972 0
+653 -656 -972 0
+-653 656 -972 0
+972 -973 0
+971 -973 0
+970 -973 0
+969 -973 0
+974 975 -978 0
+974 -975 978 0
+-974 975 978 0
+-974 -975 -978 0
+976 -979 981 0
+-976 979 981 0
+976 979 -981 0
+-976 -979 -981 0
+977 -980 982 0
+-977 980 982 0
+977 980 -982 0
+-977 -980 -982 0
+-982 983 0
+-981 983 0
+-974 983 0
+974 981 982 -983 0
+984 985 988 0
+984 -985 -988 0
+-984 985 -988 0
+-984 -985 988 0
+986 989 991 0
+-986 -989 991 0
+986 -989 -991 0
+-986 989 -991 0
+987 990 992 0
+-987 -990 992 0
+987 -990 -992 0
+-987 990 -992 0
+992 -993 0
+991 -993 0
+984 -993 0
+983 -993 0
+975 -988 994 0
+-975 988 994 0
+975 988 -994 0
+-975 -988 -994 0
+976 -989 995 0
+-976 989 995 0
+976 989 -995 0
+-976 -989 -995 0
+977 -990 996 0
+-977 990 996 0
+977 990 -996 0
+-977 -990 -996 0
+-996 997 0
+-995 997 0
+-994 997 0
+994 995 996 -997 0
+985 998 999 0
+-985 998 -999 0
+985 -998 -999 0
+-985 -998 999 0
+986 1000 1002 0
+-986 -1000 1002 0
+986 -1000 -1002 0
+-986 1000 -1002 0
+987 1001 1003 0
+-987 -1001 1003 0
+987 -1001 -1003 0
+-987 1001 -1003 0
+1003 -1004 0
+1002 -1004 0
+998 -1004 0
+997 -1004 0
+975 -999 1005 0
+-975 999 1005 0
+975 999 -1005 0
+-975 -999 -1005 0
+976 -1000 1006 0
+-976 1000 1006 0
+976 1000 -1006 0
+-976 -1000 -1006 0
+977 -1001 1007 0
+-977 1001 1007 0
+977 1001 -1007 0
+-977 -1001 -1007 0
+-1007 1008 0
+-1006 1008 0
+-1005 1008 0
+1005 1006 1007 -1008 0
+985 1009 1010 0
+-985 1009 -1010 0
+985 -1009 -1010 0
+-985 -1009 1010 0
+986 1011 1013 0
+-986 -1011 1013 0
+986 -1011 -1013 0
+-986 1011 -1013 0
+987 1012 1014 0
+-987 -1012 1014 0
+987 -1012 -1014 0
+-987 1012 -1014 0
+1014 -1015 0
+1013 -1015 0
+1009 -1015 0
+1008 -1015 0
+975 -1010 1016 0
+-975 1010 1016 0
+975 1010 -1016 0
+-975 -1010 -1016 0
+976 -1011 1017 0
+-976 1011 1017 0
+976 1011 -1017 0
+-976 -1011 -1017 0
+977 -1012 1018 0
+-977 1012 1018 0
+977 1012 -1018 0
+-977 -1012 -1018 0
+-1018 1019 0
+-1017 1019 0
+-1016 1019 0
+1016 1017 1018 -1019 0
+985 1020 1021 0
+-985 1020 -1021 0
+985 -1020 -1021 0
+-985 -1020 1021 0
+986 1022 1024 0
+-986 -1022 1024 0
+986 -1022 -1024 0
+-986 1022 -1024 0
+987 1023 1025 0
+-987 -1023 1025 0
+987 -1023 -1025 0
+-987 1023 -1025 0
+1025 -1026 0
+1024 -1026 0
+1020 -1026 0
+1019 -1026 0
+975 -1021 1027 0
+-975 1021 1027 0
+975 1021 -1027 0
+-975 -1021 -1027 0
+976 -1022 1028 0
+-976 1022 1028 0
+976 1022 -1028 0
+-976 -1022 -1028 0
+977 -1023 1029 0
+-977 1023 1029 0
+977 1023 -1029 0
+-977 -1023 -1029 0
+-1029 1030 0
+-1028 1030 0
+-1027 1030 0
+1027 1028 1029 -1030 0
+985 1031 1032 0
+-985 1031 -1032 0
+985 -1031 -1032 0
+-985 -1031 1032 0
+986 1033 1035 0
+-986 -1033 1035 0
+986 -1033 -1035 0
+-986 1033 -1035 0
+987 1034 1036 0
+-987 -1034 1036 0
+987 -1034 -1036 0
+-987 1034 -1036 0
+1036 -1037 0
+1035 -1037 0
+1031 -1037 0
+1030 -1037 0
+975 -1032 1038 0
+-975 1032 1038 0
+975 1032 -1038 0
+-975 -1032 -1038 0
+976 -1033 1039 0
+-976 1033 1039 0
+976 1033 -1039 0
+-976 -1033 -1039 0
+977 -1034 1040 0
+-977 1034 1040 0
+977 1034 -1040 0
+-977 -1034 -1040 0
+-1040 1041 0
+-1039 1041 0
+-1038 1041 0
+1038 1039 1040 -1041 0
+978 985 1042 0
+-978 -985 1042 0
+-978 985 -1042 0
+978 -985 -1042 0
+979 986 1043 0
+-979 -986 1043 0
+-979 986 -1043 0
+979 -986 -1043 0
+980 987 1044 0
+-980 -987 1044 0
+-980 987 -1044 0
+980 -987 -1044 0
+1044 -1045 0
+1043 -1045 0
+1042 -1045 0
+1041 -1045 0
+-978 985 1046 0
+978 -985 1046 0
+978 985 -1046 0
+-978 -985 -1046 0
+-979 986 1047 0
+979 -986 1047 0
+979 986 -1047 0
+-979 -986 -1047 0
+-980 987 1048 0
+980 -987 1048 0
+980 987 -1048 0
+-980 -987 -1048 0
+-1048 1049 0
+-1047 1049 0
+-1046 1049 0
+1046 1047 1048 -1049 0
+988 1050 1051 0
+-988 1050 -1051 0
+-988 -1050 1051 0
+988 -1050 -1051 0
+989 1052 1054 0
+-989 -1052 1054 0
+-989 1052 -1054 0
+989 -1052 -1054 0
+990 1053 1055 0
+-990 -1053 1055 0
+-990 1053 -1055 0
+990 -1053 -1055 0
+1055 -1056 0
+1054 -1056 0
+1050 -1056 0
+1049 -1056 0
+985 -988 1057 0
+-985 988 1057 0
+985 988 -1057 0
+-985 -988 -1057 0
+986 -989 1058 0
+-986 989 1058 0
+986 989 -1058 0
+-986 -989 -1058 0
+987 -990 1059 0
+-987 990 1059 0
+987 990 -1059 0
+-987 -990 -1059 0
+-1059 1060 0
+-1058 1060 0
+-1057 1060 0
+1057 1058 1059 -1060 0
+999 1051 1061 0
+-999 -1051 1061 0
+-999 1051 -1061 0
+999 -1051 -1061 0
+1000 1052 1062 0
+-1000 -1052 1062 0
+-1000 1052 -1062 0
+1000 -1052 -1062 0
+1001 1053 1063 0
+-1001 -1053 1063 0
+-1001 1053 -1063 0
+1001 -1053 -1063 0
+1063 -1064 0
+1062 -1064 0
+1061 -1064 0
+1060 -1064 0
+985 -999 1065 0
+-985 999 1065 0
+985 999 -1065 0
+-985 -999 -1065 0
+986 -1000 1066 0
+-986 1000 1066 0
+986 1000 -1066 0
+-986 -1000 -1066 0
+987 -1001 1067 0
+-987 1001 1067 0
+987 1001 -1067 0
+-987 -1001 -1067 0
+-1067 1068 0
+-1066 1068 0
+-1065 1068 0
+1065 1066 1067 -1068 0
+1010 1051 1069 0
+-1010 -1051 1069 0
+-1010 1051 -1069 0
+1010 -1051 -1069 0
+1011 1052 1070 0
+-1011 -1052 1070 0
+-1011 1052 -1070 0
+1011 -1052 -1070 0
+1012 1053 1071 0
+-1012 -1053 1071 0
+-1012 1053 -1071 0
+1012 -1053 -1071 0
+1071 -1072 0
+1070 -1072 0
+1069 -1072 0
+1068 -1072 0
+985 -1010 1073 0
+-985 1010 1073 0
+985 1010 -1073 0
+-985 -1010 -1073 0
+986 -1011 1074 0
+-986 1011 1074 0
+986 1011 -1074 0
+-986 -1011 -1074 0
+987 -1012 1075 0
+-987 1012 1075 0
+987 1012 -1075 0
+-987 -1012 -1075 0
+-1075 1076 0
+-1074 1076 0
+-1073 1076 0
+1073 1074 1075 -1076 0
+1021 1051 1077 0
+-1021 -1051 1077 0
+-1021 1051 -1077 0
+1021 -1051 -1077 0
+1022 1052 1078 0
+-1022 -1052 1078 0
+-1022 1052 -1078 0
+1022 -1052 -1078 0
+1023 1053 1079 0
+-1023 -1053 1079 0
+-1023 1053 -1079 0
+1023 -1053 -1079 0
+1079 -1080 0
+1078 -1080 0
+1077 -1080 0
+1076 -1080 0
+985 -1021 1081 0
+-985 1021 1081 0
+985 1021 -1081 0
+-985 -1021 -1081 0
+986 -1022 1082 0
+-986 1022 1082 0
+986 1022 -1082 0
+-986 -1022 -1082 0
+987 -1023 1083 0
+-987 1023 1083 0
+987 1023 -1083 0
+-987 -1023 -1083 0
+-1083 1084 0
+-1082 1084 0
+-1081 1084 0
+1081 1082 1083 -1084 0
+1032 1051 1085 0
+-1032 -1051 1085 0
+-1032 1051 -1085 0
+1032 -1051 -1085 0
+1033 1052 1086 0
+-1033 -1052 1086 0
+-1033 1052 -1086 0
+1033 -1052 -1086 0
+1034 1053 1087 0
+-1034 -1053 1087 0
+-1034 1053 -1087 0
+1034 -1053 -1087 0
+1087 -1088 0
+1086 -1088 0
+1085 -1088 0
+1084 -1088 0
+985 -1032 1089 0
+-985 1032 1089 0
+985 1032 -1089 0
+-985 -1032 -1089 0
+986 -1033 1090 0
+-986 1033 1090 0
+986 1033 -1090 0
+-986 -1033 -1090 0
+987 -1034 1091 0
+-987 1034 1091 0
+987 1034 -1091 0
+-987 -1034 -1091 0
+-1091 1092 0
+-1090 1092 0
+-1089 1092 0
+1089 1090 1091 -1092 0
+978 1051 1093 0
+-978 -1051 1093 0
+-978 1051 -1093 0
+978 -1051 -1093 0
+979 1052 1094 0
+-979 -1052 1094 0
+-979 1052 -1094 0
+979 -1052 -1094 0
+980 1053 1095 0
+-980 -1053 1095 0
+-980 1053 -1095 0
+980 -1053 -1095 0
+1095 -1096 0
+1094 -1096 0
+1093 -1096 0
+1092 -1096 0
+-978 1051 1097 0
+978 -1051 1097 0
+978 1051 -1097 0
+-978 -1051 -1097 0
+-979 1052 1098 0
+979 -1052 1098 0
+979 1052 -1098 0
+-979 -1052 -1098 0
+-980 1053 1099 0
+980 -1053 1099 0
+980 1053 -1099 0
+-980 -1053 -1099 0
+-1099 1100 0
+-1098 1100 0
+-1097 1100 0
+1097 1098 1099 -1100 0
+988 1101 1102 0
+-988 1101 -1102 0
+-988 -1101 1102 0
+988 -1101 -1102 0
+989 1103 1105 0
+-989 -1103 1105 0
+-989 1103 -1105 0
+989 -1103 -1105 0
+990 1104 1106 0
+-990 -1104 1106 0
+-990 1104 -1106 0
+990 -1104 -1106 0
+1106 -1107 0
+1105 -1107 0
+1101 -1107 0
+1100 -1107 0
+-988 1051 1108 0
+988 -1051 1108 0
+988 1051 -1108 0
+-988 -1051 -1108 0
+-989 1052 1109 0
+989 -1052 1109 0
+989 1052 -1109 0
+-989 -1052 -1109 0
+-990 1053 1110 0
+990 -1053 1110 0
+990 1053 -1110 0
+-990 -1053 -1110 0
+-1110 1111 0
+-1109 1111 0
+-1108 1111 0
+1108 1109 1110 -1111 0
+999 1102 1112 0
+-999 -1102 1112 0
+-999 1102 -1112 0
+999 -1102 -1112 0
+1000 1103 1113 0
+-1000 -1103 1113 0
+-1000 1103 -1113 0
+1000 -1103 -1113 0
+1001 1104 1114 0
+-1001 -1104 1114 0
+-1001 1104 -1114 0
+1001 -1104 -1114 0
+1114 -1115 0
+1113 -1115 0
+1112 -1115 0
+1111 -1115 0
+-999 1051 1116 0
+999 -1051 1116 0
+999 1051 -1116 0
+-999 -1051 -1116 0
+-1000 1052 1117 0
+1000 -1052 1117 0
+1000 1052 -1117 0
+-1000 -1052 -1117 0
+-1001 1053 1118 0
+1001 -1053 1118 0
+1001 1053 -1118 0
+-1001 -1053 -1118 0
+-1118 1119 0
+-1117 1119 0
+-1116 1119 0
+1116 1117 1118 -1119 0
+1010 1102 1120 0
+-1010 -1102 1120 0
+-1010 1102 -1120 0
+1010 -1102 -1120 0
+1011 1103 1121 0
+-1011 -1103 1121 0
+-1011 1103 -1121 0
+1011 -1103 -1121 0
+1012 1104 1122 0
+-1012 -1104 1122 0
+-1012 1104 -1122 0
+1012 -1104 -1122 0
+1122 -1123 0
+1121 -1123 0
+1120 -1123 0
+1119 -1123 0
+-1010 1051 1124 0
+1010 -1051 1124 0
+1010 1051 -1124 0
+-1010 -1051 -1124 0
+-1011 1052 1125 0
+1011 -1052 1125 0
+1011 1052 -1125 0
+-1011 -1052 -1125 0
+-1012 1053 1126 0
+1012 -1053 1126 0
+1012 1053 -1126 0
+-1012 -1053 -1126 0
+-1126 1127 0
+-1125 1127 0
+-1124 1127 0
+1124 1125 1126 -1127 0
+1021 1102 1128 0
+-1021 -1102 1128 0
+-1021 1102 -1128 0
+1021 -1102 -1128 0
+1022 1103 1129 0
+-1022 -1103 1129 0
+-1022 1103 -1129 0
+1022 -1103 -1129 0
+1023 1104 1130 0
+-1023 -1104 1130 0
+-1023 1104 -1130 0
+1023 -1104 -1130 0
+1130 -1131 0
+1129 -1131 0
+1128 -1131 0
+1127 -1131 0
+-1021 1051 1132 0
+1021 -1051 1132 0
+1021 1051 -1132 0
+-1021 -1051 -1132 0
+-1022 1052 1133 0
+1022 -1052 1133 0
+1022 1052 -1133 0
+-1022 -1052 -1133 0
+-1023 1053 1134 0
+1023 -1053 1134 0
+1023 1053 -1134 0
+-1023 -1053 -1134 0
+-1134 1135 0
+-1133 1135 0
+-1132 1135 0
+1132 1133 1134 -1135 0
+1032 1102 1136 0
+-1032 -1102 1136 0
+-1032 1102 -1136 0
+1032 -1102 -1136 0
+1033 1103 1137 0
+-1033 -1103 1137 0
+-1033 1103 -1137 0
+1033 -1103 -1137 0
+1034 1104 1138 0
+-1034 -1104 1138 0
+-1034 1104 -1138 0
+1034 -1104 -1138 0
+1138 -1139 0
+1137 -1139 0
+1136 -1139 0
+1135 -1139 0
+-1032 1051 1140 0
+1032 -1051 1140 0
+1032 1051 -1140 0
+-1032 -1051 -1140 0
+-1033 1052 1141 0
+1033 -1052 1141 0
+1033 1052 -1141 0
+-1033 -1052 -1141 0
+-1034 1053 1142 0
+1034 -1053 1142 0
+1034 1053 -1142 0
+-1034 -1053 -1142 0
+-1142 1143 0
+-1141 1143 0
+-1140 1143 0
+1140 1141 1142 -1143 0
+978 1102 1144 0
+-978 -1102 1144 0
+-978 1102 -1144 0
+978 -1102 -1144 0
+979 1103 1145 0
+-979 -1103 1145 0
+-979 1103 -1145 0
+979 -1103 -1145 0
+980 1104 1146 0
+-980 -1104 1146 0
+-980 1104 -1146 0
+980 -1104 -1146 0
+1146 -1147 0
+1145 -1147 0
+1144 -1147 0
+1143 -1147 0
+-978 1102 1148 0
+978 -1102 1148 0
+978 1102 -1148 0
+-978 -1102 -1148 0
+-979 1103 1149 0
+979 -1103 1149 0
+979 1103 -1149 0
+-979 -1103 -1149 0
+-980 1104 1150 0
+980 -1104 1150 0
+980 1104 -1150 0
+-980 -1104 -1150 0
+-1150 1151 0
+-1149 1151 0
+-1148 1151 0
+1148 1149 1150 -1151 0
+988 1152 1153 0
+-988 1152 -1153 0
+-988 -1152 1153 0
+988 -1152 -1153 0
+989 1154 1156 0
+-989 -1154 1156 0
+-989 1154 -1156 0
+989 -1154 -1156 0
+990 1155 1157 0
+-990 -1155 1157 0
+-990 1155 -1157 0
+990 -1155 -1157 0
+1157 -1158 0
+1156 -1158 0
+1152 -1158 0
+1151 -1158 0
+-988 1102 1159 0
+988 -1102 1159 0
+988 1102 -1159 0
+-988 -1102 -1159 0
+-989 1103 1160 0
+989 -1103 1160 0
+989 1103 -1160 0
+-989 -1103 -1160 0
+-990 1104 1161 0
+990 -1104 1161 0
+990 1104 -1161 0
+-990 -1104 -1161 0
+-1161 1162 0
+-1160 1162 0
+-1159 1162 0
+1159 1160 1161 -1162 0
+999 1153 1163 0
+-999 -1153 1163 0
+-999 1153 -1163 0
+999 -1153 -1163 0
+1000 1154 1164 0
+-1000 -1154 1164 0
+-1000 1154 -1164 0
+1000 -1154 -1164 0
+1001 1155 1165 0
+-1001 -1155 1165 0
+-1001 1155 -1165 0
+1001 -1155 -1165 0
+1165 -1166 0
+1164 -1166 0
+1163 -1166 0
+1162 -1166 0
+-999 1102 1167 0
+999 -1102 1167 0
+999 1102 -1167 0
+-999 -1102 -1167 0
+-1000 1103 1168 0
+1000 -1103 1168 0
+1000 1103 -1168 0
+-1000 -1103 -1168 0
+-1001 1104 1169 0
+1001 -1104 1169 0
+1001 1104 -1169 0
+-1001 -1104 -1169 0
+-1169 1170 0
+-1168 1170 0
+-1167 1170 0
+1167 1168 1169 -1170 0
+1010 1153 1171 0
+-1010 -1153 1171 0
+-1010 1153 -1171 0
+1010 -1153 -1171 0
+1011 1154 1172 0
+-1011 -1154 1172 0
+-1011 1154 -1172 0
+1011 -1154 -1172 0
+1012 1155 1173 0
+-1012 -1155 1173 0
+-1012 1155 -1173 0
+1012 -1155 -1173 0
+1173 -1174 0
+1172 -1174 0
+1171 -1174 0
+1170 -1174 0
+-1010 1102 1175 0
+1010 -1102 1175 0
+1010 1102 -1175 0
+-1010 -1102 -1175 0
+-1011 1103 1176 0
+1011 -1103 1176 0
+1011 1103 -1176 0
+-1011 -1103 -1176 0
+-1012 1104 1177 0
+1012 -1104 1177 0
+1012 1104 -1177 0
+-1012 -1104 -1177 0
+-1177 1178 0
+-1176 1178 0
+-1175 1178 0
+1175 1176 1177 -1178 0
+1021 1153 1179 0
+-1021 -1153 1179 0
+-1021 1153 -1179 0
+1021 -1153 -1179 0
+1022 1154 1180 0
+-1022 -1154 1180 0
+-1022 1154 -1180 0
+1022 -1154 -1180 0
+1023 1155 1181 0
+-1023 -1155 1181 0
+-1023 1155 -1181 0
+1023 -1155 -1181 0
+1181 -1182 0
+1180 -1182 0
+1179 -1182 0
+1178 -1182 0
+-1021 1102 1183 0
+1021 -1102 1183 0
+1021 1102 -1183 0
+-1021 -1102 -1183 0
+-1022 1103 1184 0
+1022 -1103 1184 0
+1022 1103 -1184 0
+-1022 -1103 -1184 0
+-1023 1104 1185 0
+1023 -1104 1185 0
+1023 1104 -1185 0
+-1023 -1104 -1185 0
+-1185 1186 0
+-1184 1186 0
+-1183 1186 0
+1183 1184 1185 -1186 0
+1032 1153 1187 0
+-1032 -1153 1187 0
+-1032 1153 -1187 0
+1032 -1153 -1187 0
+1033 1154 1188 0
+-1033 -1154 1188 0
+-1033 1154 -1188 0
+1033 -1154 -1188 0
+1034 1155 1189 0
+-1034 -1155 1189 0
+-1034 1155 -1189 0
+1034 -1155 -1189 0
+1189 -1190 0
+1188 -1190 0
+1187 -1190 0
+1186 -1190 0
+-1032 1102 1191 0
+1032 -1102 1191 0
+1032 1102 -1191 0
+-1032 -1102 -1191 0
+-1033 1103 1192 0
+1033 -1103 1192 0
+1033 1103 -1192 0
+-1033 -1103 -1192 0
+-1034 1104 1193 0
+1034 -1104 1193 0
+1034 1104 -1193 0
+-1034 -1104 -1193 0
+-1193 1194 0
+-1192 1194 0
+-1191 1194 0
+1191 1192 1193 -1194 0
+978 1153 1195 0
+-978 -1153 1195 0
+-978 1153 -1195 0
+978 -1153 -1195 0
+979 1154 1196 0
+-979 -1154 1196 0
+-979 1154 -1196 0
+979 -1154 -1196 0
+980 1155 1197 0
+-980 -1155 1197 0
+-980 1155 -1197 0
+980 -1155 -1197 0
+1197 -1198 0
+1196 -1198 0
+1195 -1198 0
+1194 -1198 0
+-978 1153 1199 0
+978 -1153 1199 0
+978 1153 -1199 0
+-978 -1153 -1199 0
+-979 1154 1200 0
+979 -1154 1200 0
+979 1154 -1200 0
+-979 -1154 -1200 0
+-980 1155 1201 0
+980 -1155 1201 0
+980 1155 -1201 0
+-980 -1155 -1201 0
+-1201 1202 0
+-1200 1202 0
+-1199 1202 0
+1199 1200 1201 -1202 0
+988 1203 1204 0
+-988 1203 -1204 0
+-988 -1203 1204 0
+988 -1203 -1204 0
+989 1205 1207 0
+-989 -1205 1207 0
+-989 1205 -1207 0
+989 -1205 -1207 0
+990 1206 1208 0
+-990 -1206 1208 0
+-990 1206 -1208 0
+990 -1206 -1208 0
+1208 -1209 0
+1207 -1209 0
+1203 -1209 0
+1202 -1209 0
+-988 1153 1210 0
+988 -1153 1210 0
+988 1153 -1210 0
+-988 -1153 -1210 0
+-989 1154 1211 0
+989 -1154 1211 0
+989 1154 -1211 0
+-989 -1154 -1211 0
+-990 1155 1212 0
+990 -1155 1212 0
+990 1155 -1212 0
+-990 -1155 -1212 0
+-1212 1213 0
+-1211 1213 0
+-1210 1213 0
+1210 1211 1212 -1213 0
+999 1204 1214 0
+-999 -1204 1214 0
+-999 1204 -1214 0
+999 -1204 -1214 0
+1000 1205 1215 0
+-1000 -1205 1215 0
+-1000 1205 -1215 0
+1000 -1205 -1215 0
+1001 1206 1216 0
+-1001 -1206 1216 0
+-1001 1206 -1216 0
+1001 -1206 -1216 0
+1216 -1217 0
+1215 -1217 0
+1214 -1217 0
+1213 -1217 0
+-999 1153 1218 0
+999 -1153 1218 0
+999 1153 -1218 0
+-999 -1153 -1218 0
+-1000 1154 1219 0
+1000 -1154 1219 0
+1000 1154 -1219 0
+-1000 -1154 -1219 0
+-1001 1155 1220 0
+1001 -1155 1220 0
+1001 1155 -1220 0
+-1001 -1155 -1220 0
+-1220 1221 0
+-1219 1221 0
+-1218 1221 0
+1218 1219 1220 -1221 0
+1010 1204 1222 0
+-1010 -1204 1222 0
+-1010 1204 -1222 0
+1010 -1204 -1222 0
+1011 1205 1223 0
+-1011 -1205 1223 0
+-1011 1205 -1223 0
+1011 -1205 -1223 0
+1012 1206 1224 0
+-1012 -1206 1224 0
+-1012 1206 -1224 0
+1012 -1206 -1224 0
+1224 -1225 0
+1223 -1225 0
+1222 -1225 0
+1221 -1225 0
+-1010 1153 1226 0
+1010 -1153 1226 0
+1010 1153 -1226 0
+-1010 -1153 -1226 0
+-1011 1154 1227 0
+1011 -1154 1227 0
+1011 1154 -1227 0
+-1011 -1154 -1227 0
+-1012 1155 1228 0
+1012 -1155 1228 0
+1012 1155 -1228 0
+-1012 -1155 -1228 0
+-1228 1229 0
+-1227 1229 0
+-1226 1229 0
+1226 1227 1228 -1229 0
+1021 1204 1230 0
+-1021 -1204 1230 0
+-1021 1204 -1230 0
+1021 -1204 -1230 0
+1022 1205 1231 0
+-1022 -1205 1231 0
+-1022 1205 -1231 0
+1022 -1205 -1231 0
+1023 1206 1232 0
+-1023 -1206 1232 0
+-1023 1206 -1232 0
+1023 -1206 -1232 0
+1232 -1233 0
+1231 -1233 0
+1230 -1233 0
+1229 -1233 0
+-1021 1153 1234 0
+1021 -1153 1234 0
+1021 1153 -1234 0
+-1021 -1153 -1234 0
+-1022 1154 1235 0
+1022 -1154 1235 0
+1022 1154 -1235 0
+-1022 -1154 -1235 0
+-1023 1155 1236 0
+1023 -1155 1236 0
+1023 1155 -1236 0
+-1023 -1155 -1236 0
+-1236 1237 0
+-1235 1237 0
+-1234 1237 0
+1234 1235 1236 -1237 0
+1032 1204 1238 0
+-1032 -1204 1238 0
+-1032 1204 -1238 0
+1032 -1204 -1238 0
+1033 1205 1239 0
+-1033 -1205 1239 0
+-1033 1205 -1239 0
+1033 -1205 -1239 0
+1034 1206 1240 0
+-1034 -1206 1240 0
+-1034 1206 -1240 0
+1034 -1206 -1240 0
+1240 -1241 0
+1239 -1241 0
+1238 -1241 0
+1237 -1241 0
+-1032 1153 1242 0
+1032 -1153 1242 0
+1032 1153 -1242 0
+-1032 -1153 -1242 0
+-1033 1154 1243 0
+1033 -1154 1243 0
+1033 1154 -1243 0
+-1033 -1154 -1243 0
+-1034 1155 1244 0
+1034 -1155 1244 0
+1034 1155 -1244 0
+-1034 -1155 -1244 0
+-1244 1245 0
+-1243 1245 0
+-1242 1245 0
+1242 1243 1244 -1245 0
+978 1204 1246 0
+-978 -1204 1246 0
+-978 1204 -1246 0
+978 -1204 -1246 0
+979 1205 1247 0
+-979 -1205 1247 0
+-979 1205 -1247 0
+979 -1205 -1247 0
+980 1206 1248 0
+-980 -1206 1248 0
+-980 1206 -1248 0
+980 -1206 -1248 0
+1248 -1249 0
+1247 -1249 0
+1246 -1249 0
+1245 -1249 0
+-978 1204 1250 0
+978 -1204 1250 0
+978 1204 -1250 0
+-978 -1204 -1250 0
+-979 1205 1251 0
+979 -1205 1251 0
+979 1205 -1251 0
+-979 -1205 -1251 0
+-980 1206 1252 0
+980 -1206 1252 0
+980 1206 -1252 0
+-980 -1206 -1252 0
+-1252 1253 0
+-1251 1253 0
+-1250 1253 0
+1250 1251 1252 -1253 0
+975 988 1254 0
+-975 -988 1254 0
+975 -988 -1254 0
+-975 988 -1254 0
+976 989 1255 0
+-976 -989 1255 0
+976 -989 -1255 0
+-976 989 -1255 0
+977 990 1256 0
+-977 -990 1256 0
+977 -990 -1256 0
+-977 990 -1256 0
+1256 -1257 0
+1255 -1257 0
+1254 -1257 0
+1253 -1257 0
+-988 1204 1258 0
+988 -1204 1258 0
+988 1204 -1258 0
+-988 -1204 -1258 0
+-989 1205 1259 0
+989 -1205 1259 0
+989 1205 -1259 0
+-989 -1205 -1259 0
+-990 1206 1260 0
+990 -1206 1260 0
+990 1206 -1260 0
+-990 -1206 -1260 0
+-1260 1261 0
+-1259 1261 0
+-1258 1261 0
+1258 1259 1260 -1261 0
+975 999 1262 0
+-975 -999 1262 0
+975 -999 -1262 0
+-975 999 -1262 0
+976 1000 1263 0
+-976 -1000 1263 0
+976 -1000 -1263 0
+-976 1000 -1263 0
+977 1001 1264 0
+-977 -1001 1264 0
+977 -1001 -1264 0
+-977 1001 -1264 0
+1264 -1265 0
+1263 -1265 0
+1262 -1265 0
+1261 -1265 0
+-999 1204 1266 0
+999 -1204 1266 0
+999 1204 -1266 0
+-999 -1204 -1266 0
+-1000 1205 1267 0
+1000 -1205 1267 0
+1000 1205 -1267 0
+-1000 -1205 -1267 0
+-1001 1206 1268 0
+1001 -1206 1268 0
+1001 1206 -1268 0
+-1001 -1206 -1268 0
+-1268 1269 0
+-1267 1269 0
+-1266 1269 0
+1266 1267 1268 -1269 0
+975 1010 1270 0
+-975 -1010 1270 0
+975 -1010 -1270 0
+-975 1010 -1270 0
+976 1011 1271 0
+-976 -1011 1271 0
+976 -1011 -1271 0
+-976 1011 -1271 0
+977 1012 1272 0
+-977 -1012 1272 0
+977 -1012 -1272 0
+-977 1012 -1272 0
+1272 -1273 0
+1271 -1273 0
+1270 -1273 0
+1269 -1273 0
+-1010 1204 1274 0
+1010 -1204 1274 0
+1010 1204 -1274 0
+-1010 -1204 -1274 0
+-1011 1205 1275 0
+1011 -1205 1275 0
+1011 1205 -1275 0
+-1011 -1205 -1275 0
+-1012 1206 1276 0
+1012 -1206 1276 0
+1012 1206 -1276 0
+-1012 -1206 -1276 0
+-1276 1277 0
+-1275 1277 0
+-1274 1277 0
+1274 1275 1276 -1277 0
+975 1021 1278 0
+-975 -1021 1278 0
+975 -1021 -1278 0
+-975 1021 -1278 0
+976 1022 1279 0
+-976 -1022 1279 0
+976 -1022 -1279 0
+-976 1022 -1279 0
+977 1023 1280 0
+-977 -1023 1280 0
+977 -1023 -1280 0
+-977 1023 -1280 0
+1280 -1281 0
+1279 -1281 0
+1278 -1281 0
+1277 -1281 0
+-1021 1204 1282 0
+1021 -1204 1282 0
+1021 1204 -1282 0
+-1021 -1204 -1282 0
+-1022 1205 1283 0
+1022 -1205 1283 0
+1022 1205 -1283 0
+-1022 -1205 -1283 0
+-1023 1206 1284 0
+1023 -1206 1284 0
+1023 1206 -1284 0
+-1023 -1206 -1284 0
+-1284 1285 0
+-1283 1285 0
+-1282 1285 0
+1282 1283 1284 -1285 0
+975 1032 1286 0
+-975 -1032 1286 0
+975 -1032 -1286 0
+-975 1032 -1286 0
+976 1033 1287 0
+-976 -1033 1287 0
+976 -1033 -1287 0
+-976 1033 -1287 0
+977 1034 1288 0
+-977 -1034 1288 0
+977 -1034 -1288 0
+-977 1034 -1288 0
+1288 -1289 0
+1287 -1289 0
+1286 -1289 0
+1285 -1289 0
+-1032 1204 1290 0
+1032 -1204 1290 0
+1032 1204 -1290 0
+-1032 -1204 -1290 0
+-1033 1205 1291 0
+1033 -1205 1291 0
+1033 1205 -1291 0
+-1033 -1205 -1291 0
+-1034 1206 1292 0
+1034 -1206 1292 0
+1034 1206 -1292 0
+-1034 -1206 -1292 0
+-1292 1293 0
+-1291 1293 0
+-1290 1293 0
+1290 1291 1292 -1293 0
+975 978 1294 0
+-975 -978 1294 0
+975 -978 -1294 0
+-975 978 -1294 0
+976 979 1295 0
+-976 -979 1295 0
+976 -979 -1295 0
+-976 979 -1295 0
+977 980 1296 0
+-977 -980 1296 0
+977 -980 -1296 0
+-977 980 -1296 0
+1296 -1297 0
+1295 -1297 0
+1294 -1297 0
+1293 -1297 0
+1298 1299 -1302 0
+1298 -1299 1302 0
+-1298 1299 1302 0
+-1298 -1299 -1302 0
+1300 -1303 1305 0
+-1300 1303 1305 0
+1300 1303 -1305 0
+-1300 -1303 -1305 0
+1301 -1304 1306 0
+-1301 1304 1306 0
+1301 1304 -1306 0
+-1301 -1304 -1306 0
+-1306 1307 0
+-1305 1307 0
+-1298 1307 0
+1298 1305 1306 -1307 0
+1308 1309 1312 0
+1308 -1309 -1312 0
+-1308 1309 -1312 0
+-1308 -1309 1312 0
+1310 1313 1315 0
+-1310 -1313 1315 0
+1310 -1313 -1315 0
+-1310 1313 -1315 0
+1311 1314 1316 0
+-1311 -1314 1316 0
+1311 -1314 -1316 0
+-1311 1314 -1316 0
+1316 -1317 0
+1315 -1317 0
+1308 -1317 0
+1307 -1317 0
+1299 -1312 1318 0
+-1299 1312 1318 0
+1299 1312 -1318 0
+-1299 -1312 -1318 0
+1300 -1313 1319 0
+-1300 1313 1319 0
+1300 1313 -1319 0
+-1300 -1313 -1319 0
+1301 -1314 1320 0
+-1301 1314 1320 0
+1301 1314 -1320 0
+-1301 -1314 -1320 0
+-1320 1321 0
+-1319 1321 0
+-1318 1321 0
+1318 1319 1320 -1321 0
+1309 1322 1323 0
+-1309 1322 -1323 0
+1309 -1322 -1323 0
+-1309 -1322 1323 0
+1310 1324 1326 0
+-1310 -1324 1326 0
+1310 -1324 -1326 0
+-1310 1324 -1326 0
+1311 1325 1327 0
+-1311 -1325 1327 0
+1311 -1325 -1327 0
+-1311 1325 -1327 0
+1327 -1328 0
+1326 -1328 0
+1322 -1328 0
+1321 -1328 0
+1299 -1323 1329 0
+-1299 1323 1329 0
+1299 1323 -1329 0
+-1299 -1323 -1329 0
+1300 -1324 1330 0
+-1300 1324 1330 0
+1300 1324 -1330 0
+-1300 -1324 -1330 0
+1301 -1325 1331 0
+-1301 1325 1331 0
+1301 1325 -1331 0
+-1301 -1325 -1331 0
+-1331 1332 0
+-1330 1332 0
+-1329 1332 0
+1329 1330 1331 -1332 0
+1309 1333 1334 0
+-1309 1333 -1334 0
+1309 -1333 -1334 0
+-1309 -1333 1334 0
+1310 1335 1337 0
+-1310 -1335 1337 0
+1310 -1335 -1337 0
+-1310 1335 -1337 0
+1311 1336 1338 0
+-1311 -1336 1338 0
+1311 -1336 -1338 0
+-1311 1336 -1338 0
+1338 -1339 0
+1337 -1339 0
+1333 -1339 0
+1332 -1339 0
+1299 -1334 1340 0
+-1299 1334 1340 0
+1299 1334 -1340 0
+-1299 -1334 -1340 0
+1300 -1335 1341 0
+-1300 1335 1341 0
+1300 1335 -1341 0
+-1300 -1335 -1341 0
+1301 -1336 1342 0
+-1301 1336 1342 0
+1301 1336 -1342 0
+-1301 -1336 -1342 0
+-1342 1343 0
+-1341 1343 0
+-1340 1343 0
+1340 1341 1342 -1343 0
+1309 1344 1345 0
+-1309 1344 -1345 0
+1309 -1344 -1345 0
+-1309 -1344 1345 0
+1310 1346 1348 0
+-1310 -1346 1348 0
+1310 -1346 -1348 0
+-1310 1346 -1348 0
+1311 1347 1349 0
+-1311 -1347 1349 0
+1311 -1347 -1349 0
+-1311 1347 -1349 0
+1349 -1350 0
+1348 -1350 0
+1344 -1350 0
+1343 -1350 0
+1299 -1345 1351 0
+-1299 1345 1351 0
+1299 1345 -1351 0
+-1299 -1345 -1351 0
+1300 -1346 1352 0
+-1300 1346 1352 0
+1300 1346 -1352 0
+-1300 -1346 -1352 0
+1301 -1347 1353 0
+-1301 1347 1353 0
+1301 1347 -1353 0
+-1301 -1347 -1353 0
+-1353 1354 0
+-1352 1354 0
+-1351 1354 0
+1351 1352 1353 -1354 0
+1309 1355 1356 0
+-1309 1355 -1356 0
+1309 -1355 -1356 0
+-1309 -1355 1356 0
+1310 1357 1359 0
+-1310 -1357 1359 0
+1310 -1357 -1359 0
+-1310 1357 -1359 0
+1311 1358 1360 0
+-1311 -1358 1360 0
+1311 -1358 -1360 0
+-1311 1358 -1360 0
+1360 -1361 0
+1359 -1361 0
+1355 -1361 0
+1354 -1361 0
+1299 -1356 1362 0
+-1299 1356 1362 0
+1299 1356 -1362 0
+-1299 -1356 -1362 0
+1300 -1357 1363 0
+-1300 1357 1363 0
+1300 1357 -1363 0
+-1300 -1357 -1363 0
+1301 -1358 1364 0
+-1301 1358 1364 0
+1301 1358 -1364 0
+-1301 -1358 -1364 0
+-1364 1365 0
+-1363 1365 0
+-1362 1365 0
+1362 1363 1364 -1365 0
+1302 1309 1366 0
+-1302 -1309 1366 0
+-1302 1309 -1366 0
+1302 -1309 -1366 0
+1303 1310 1367 0
+-1303 -1310 1367 0
+-1303 1310 -1367 0
+1303 -1310 -1367 0
+1304 1311 1368 0
+-1304 -1311 1368 0
+-1304 1311 -1368 0
+1304 -1311 -1368 0
+1368 -1369 0
+1367 -1369 0
+1366 -1369 0
+1365 -1369 0
+-1302 1309 1370 0
+1302 -1309 1370 0
+1302 1309 -1370 0
+-1302 -1309 -1370 0
+-1303 1310 1371 0
+1303 -1310 1371 0
+1303 1310 -1371 0
+-1303 -1310 -1371 0
+-1304 1311 1372 0
+1304 -1311 1372 0
+1304 1311 -1372 0
+-1304 -1311 -1372 0
+-1372 1373 0
+-1371 1373 0
+-1370 1373 0
+1370 1371 1372 -1373 0
+1312 1374 1375 0
+-1312 1374 -1375 0
+-1312 -1374 1375 0
+1312 -1374 -1375 0
+1313 1376 1378 0
+-1313 -1376 1378 0
+-1313 1376 -1378 0
+1313 -1376 -1378 0
+1314 1377 1379 0
+-1314 -1377 1379 0
+-1314 1377 -1379 0
+1314 -1377 -1379 0
+1379 -1380 0
+1378 -1380 0
+1374 -1380 0
+1373 -1380 0
+1309 -1312 1381 0
+-1309 1312 1381 0
+1309 1312 -1381 0
+-1309 -1312 -1381 0
+1310 -1313 1382 0
+-1310 1313 1382 0
+1310 1313 -1382 0
+-1310 -1313 -1382 0
+1311 -1314 1383 0
+-1311 1314 1383 0
+1311 1314 -1383 0
+-1311 -1314 -1383 0
+-1383 1384 0
+-1382 1384 0
+-1381 1384 0
+1381 1382 1383 -1384 0
+1323 1375 1385 0
+-1323 -1375 1385 0
+-1323 1375 -1385 0
+1323 -1375 -1385 0
+1324 1376 1386 0
+-1324 -1376 1386 0
+-1324 1376 -1386 0
+1324 -1376 -1386 0
+1325 1377 1387 0
+-1325 -1377 1387 0
+-1325 1377 -1387 0
+1325 -1377 -1387 0
+1387 -1388 0
+1386 -1388 0
+1385 -1388 0
+1384 -1388 0
+1309 -1323 1389 0
+-1309 1323 1389 0
+1309 1323 -1389 0
+-1309 -1323 -1389 0
+1310 -1324 1390 0
+-1310 1324 1390 0
+1310 1324 -1390 0
+-1310 -1324 -1390 0
+1311 -1325 1391 0
+-1311 1325 1391 0
+1311 1325 -1391 0
+-1311 -1325 -1391 0
+-1391 1392 0
+-1390 1392 0
+-1389 1392 0
+1389 1390 1391 -1392 0
+1334 1375 1393 0
+-1334 -1375 1393 0
+-1334 1375 -1393 0
+1334 -1375 -1393 0
+1335 1376 1394 0
+-1335 -1376 1394 0
+-1335 1376 -1394 0
+1335 -1376 -1394 0
+1336 1377 1395 0
+-1336 -1377 1395 0
+-1336 1377 -1395 0
+1336 -1377 -1395 0
+1395 -1396 0
+1394 -1396 0
+1393 -1396 0
+1392 -1396 0
+1309 -1334 1397 0
+-1309 1334 1397 0
+1309 1334 -1397 0
+-1309 -1334 -1397 0
+1310 -1335 1398 0
+-1310 1335 1398 0
+1310 1335 -1398 0
+-1310 -1335 -1398 0
+1311 -1336 1399 0
+-1311 1336 1399 0
+1311 1336 -1399 0
+-1311 -1336 -1399 0
+-1399 1400 0
+-1398 1400 0
+-1397 1400 0
+1397 1398 1399 -1400 0
+1345 1375 1401 0
+-1345 -1375 1401 0
+-1345 1375 -1401 0
+1345 -1375 -1401 0
+1346 1376 1402 0
+-1346 -1376 1402 0
+-1346 1376 -1402 0
+1346 -1376 -1402 0
+1347 1377 1403 0
+-1347 -1377 1403 0
+-1347 1377 -1403 0
+1347 -1377 -1403 0
+1403 -1404 0
+1402 -1404 0
+1401 -1404 0
+1400 -1404 0
+1309 -1345 1405 0
+-1309 1345 1405 0
+1309 1345 -1405 0
+-1309 -1345 -1405 0
+1310 -1346 1406 0
+-1310 1346 1406 0
+1310 1346 -1406 0
+-1310 -1346 -1406 0
+1311 -1347 1407 0
+-1311 1347 1407 0
+1311 1347 -1407 0
+-1311 -1347 -1407 0
+-1407 1408 0
+-1406 1408 0
+-1405 1408 0
+1405 1406 1407 -1408 0
+1356 1375 1409 0
+-1356 -1375 1409 0
+-1356 1375 -1409 0
+1356 -1375 -1409 0
+1357 1376 1410 0
+-1357 -1376 1410 0
+-1357 1376 -1410 0
+1357 -1376 -1410 0
+1358 1377 1411 0
+-1358 -1377 1411 0
+-1358 1377 -1411 0
+1358 -1377 -1411 0
+1411 -1412 0
+1410 -1412 0
+1409 -1412 0
+1408 -1412 0
+1309 -1356 1413 0
+-1309 1356 1413 0
+1309 1356 -1413 0
+-1309 -1356 -1413 0
+1310 -1357 1414 0
+-1310 1357 1414 0
+1310 1357 -1414 0
+-1310 -1357 -1414 0
+1311 -1358 1415 0
+-1311 1358 1415 0
+1311 1358 -1415 0
+-1311 -1358 -1415 0
+-1415 1416 0
+-1414 1416 0
+-1413 1416 0
+1413 1414 1415 -1416 0
+1302 1375 1417 0
+-1302 -1375 1417 0
+-1302 1375 -1417 0
+1302 -1375 -1417 0
+1303 1376 1418 0
+-1303 -1376 1418 0
+-1303 1376 -1418 0
+1303 -1376 -1418 0
+1304 1377 1419 0
+-1304 -1377 1419 0
+-1304 1377 -1419 0
+1304 -1377 -1419 0
+1419 -1420 0
+1418 -1420 0
+1417 -1420 0
+1416 -1420 0
+-1302 1375 1421 0
+1302 -1375 1421 0
+1302 1375 -1421 0
+-1302 -1375 -1421 0
+-1303 1376 1422 0
+1303 -1376 1422 0
+1303 1376 -1422 0
+-1303 -1376 -1422 0
+-1304 1377 1423 0
+1304 -1377 1423 0
+1304 1377 -1423 0
+-1304 -1377 -1423 0
+-1423 1424 0
+-1422 1424 0
+-1421 1424 0
+1421 1422 1423 -1424 0
+1312 1425 1426 0
+-1312 1425 -1426 0
+-1312 -1425 1426 0
+1312 -1425 -1426 0
+1313 1427 1429 0
+-1313 -1427 1429 0
+-1313 1427 -1429 0
+1313 -1427 -1429 0
+1314 1428 1430 0
+-1314 -1428 1430 0
+-1314 1428 -1430 0
+1314 -1428 -1430 0
+1430 -1431 0
+1429 -1431 0
+1425 -1431 0
+1424 -1431 0
+-1312 1375 1432 0
+1312 -1375 1432 0
+1312 1375 -1432 0
+-1312 -1375 -1432 0
+-1313 1376 1433 0
+1313 -1376 1433 0
+1313 1376 -1433 0
+-1313 -1376 -1433 0
+-1314 1377 1434 0
+1314 -1377 1434 0
+1314 1377 -1434 0
+-1314 -1377 -1434 0
+-1434 1435 0
+-1433 1435 0
+-1432 1435 0
+1432 1433 1434 -1435 0
+1323 1426 1436 0
+-1323 -1426 1436 0
+-1323 1426 -1436 0
+1323 -1426 -1436 0
+1324 1427 1437 0
+-1324 -1427 1437 0
+-1324 1427 -1437 0
+1324 -1427 -1437 0
+1325 1428 1438 0
+-1325 -1428 1438 0
+-1325 1428 -1438 0
+1325 -1428 -1438 0
+1438 -1439 0
+1437 -1439 0
+1436 -1439 0
+1435 -1439 0
+-1323 1375 1440 0
+1323 -1375 1440 0
+1323 1375 -1440 0
+-1323 -1375 -1440 0
+-1324 1376 1441 0
+1324 -1376 1441 0
+1324 1376 -1441 0
+-1324 -1376 -1441 0
+-1325 1377 1442 0
+1325 -1377 1442 0
+1325 1377 -1442 0
+-1325 -1377 -1442 0
+-1442 1443 0
+-1441 1443 0
+-1440 1443 0
+1440 1441 1442 -1443 0
+1334 1426 1444 0
+-1334 -1426 1444 0
+-1334 1426 -1444 0
+1334 -1426 -1444 0
+1335 1427 1445 0
+-1335 -1427 1445 0
+-1335 1427 -1445 0
+1335 -1427 -1445 0
+1336 1428 1446 0
+-1336 -1428 1446 0
+-1336 1428 -1446 0
+1336 -1428 -1446 0
+1446 -1447 0
+1445 -1447 0
+1444 -1447 0
+1443 -1447 0
+-1334 1375 1448 0
+1334 -1375 1448 0
+1334 1375 -1448 0
+-1334 -1375 -1448 0
+-1335 1376 1449 0
+1335 -1376 1449 0
+1335 1376 -1449 0
+-1335 -1376 -1449 0
+-1336 1377 1450 0
+1336 -1377 1450 0
+1336 1377 -1450 0
+-1336 -1377 -1450 0
+-1450 1451 0
+-1449 1451 0
+-1448 1451 0
+1448 1449 1450 -1451 0
+1345 1426 1452 0
+-1345 -1426 1452 0
+-1345 1426 -1452 0
+1345 -1426 -1452 0
+1346 1427 1453 0
+-1346 -1427 1453 0
+-1346 1427 -1453 0
+1346 -1427 -1453 0
+1347 1428 1454 0
+-1347 -1428 1454 0
+-1347 1428 -1454 0
+1347 -1428 -1454 0
+1454 -1455 0
+1453 -1455 0
+1452 -1455 0
+1451 -1455 0
+-1345 1375 1456 0
+1345 -1375 1456 0
+1345 1375 -1456 0
+-1345 -1375 -1456 0
+-1346 1376 1457 0
+1346 -1376 1457 0
+1346 1376 -1457 0
+-1346 -1376 -1457 0
+-1347 1377 1458 0
+1347 -1377 1458 0
+1347 1377 -1458 0
+-1347 -1377 -1458 0
+-1458 1459 0
+-1457 1459 0
+-1456 1459 0
+1456 1457 1458 -1459 0
+1356 1426 1460 0
+-1356 -1426 1460 0
+-1356 1426 -1460 0
+1356 -1426 -1460 0
+1357 1427 1461 0
+-1357 -1427 1461 0
+-1357 1427 -1461 0
+1357 -1427 -1461 0
+1358 1428 1462 0
+-1358 -1428 1462 0
+-1358 1428 -1462 0
+1358 -1428 -1462 0
+1462 -1463 0
+1461 -1463 0
+1460 -1463 0
+1459 -1463 0
+-1356 1375 1464 0
+1356 -1375 1464 0
+1356 1375 -1464 0
+-1356 -1375 -1464 0
+-1357 1376 1465 0
+1357 -1376 1465 0
+1357 1376 -1465 0
+-1357 -1376 -1465 0
+-1358 1377 1466 0
+1358 -1377 1466 0
+1358 1377 -1466 0
+-1358 -1377 -1466 0
+-1466 1467 0
+-1465 1467 0
+-1464 1467 0
+1464 1465 1466 -1467 0
+1302 1426 1468 0
+-1302 -1426 1468 0
+-1302 1426 -1468 0
+1302 -1426 -1468 0
+1303 1427 1469 0
+-1303 -1427 1469 0
+-1303 1427 -1469 0
+1303 -1427 -1469 0
+1304 1428 1470 0
+-1304 -1428 1470 0
+-1304 1428 -1470 0
+1304 -1428 -1470 0
+1470 -1471 0
+1469 -1471 0
+1468 -1471 0
+1467 -1471 0
+-1302 1426 1472 0
+1302 -1426 1472 0
+1302 1426 -1472 0
+-1302 -1426 -1472 0
+-1303 1427 1473 0
+1303 -1427 1473 0
+1303 1427 -1473 0
+-1303 -1427 -1473 0
+-1304 1428 1474 0
+1304 -1428 1474 0
+1304 1428 -1474 0
+-1304 -1428 -1474 0
+-1474 1475 0
+-1473 1475 0
+-1472 1475 0
+1472 1473 1474 -1475 0
+1312 1476 1477 0
+-1312 1476 -1477 0
+-1312 -1476 1477 0
+1312 -1476 -1477 0
+1313 1478 1480 0
+-1313 -1478 1480 0
+-1313 1478 -1480 0
+1313 -1478 -1480 0
+1314 1479 1481 0
+-1314 -1479 1481 0
+-1314 1479 -1481 0
+1314 -1479 -1481 0
+1481 -1482 0
+1480 -1482 0
+1476 -1482 0
+1475 -1482 0
+-1312 1426 1483 0
+1312 -1426 1483 0
+1312 1426 -1483 0
+-1312 -1426 -1483 0
+-1313 1427 1484 0
+1313 -1427 1484 0
+1313 1427 -1484 0
+-1313 -1427 -1484 0
+-1314 1428 1485 0
+1314 -1428 1485 0
+1314 1428 -1485 0
+-1314 -1428 -1485 0
+-1485 1486 0
+-1484 1486 0
+-1483 1486 0
+1483 1484 1485 -1486 0
+1323 1477 1487 0
+-1323 -1477 1487 0
+-1323 1477 -1487 0
+1323 -1477 -1487 0
+1324 1478 1488 0
+-1324 -1478 1488 0
+-1324 1478 -1488 0
+1324 -1478 -1488 0
+1325 1479 1489 0
+-1325 -1479 1489 0
+-1325 1479 -1489 0
+1325 -1479 -1489 0
+1489 -1490 0
+1488 -1490 0
+1487 -1490 0
+1486 -1490 0
+-1323 1426 1491 0
+1323 -1426 1491 0
+1323 1426 -1491 0
+-1323 -1426 -1491 0
+-1324 1427 1492 0
+1324 -1427 1492 0
+1324 1427 -1492 0
+-1324 -1427 -1492 0
+-1325 1428 1493 0
+1325 -1428 1493 0
+1325 1428 -1493 0
+-1325 -1428 -1493 0
+-1493 1494 0
+-1492 1494 0
+-1491 1494 0
+1491 1492 1493 -1494 0
+1334 1477 1495 0
+-1334 -1477 1495 0
+-1334 1477 -1495 0
+1334 -1477 -1495 0
+1335 1478 1496 0
+-1335 -1478 1496 0
+-1335 1478 -1496 0
+1335 -1478 -1496 0
+1336 1479 1497 0
+-1336 -1479 1497 0
+-1336 1479 -1497 0
+1336 -1479 -1497 0
+1497 -1498 0
+1496 -1498 0
+1495 -1498 0
+1494 -1498 0
+-1334 1426 1499 0
+1334 -1426 1499 0
+1334 1426 -1499 0
+-1334 -1426 -1499 0
+-1335 1427 1500 0
+1335 -1427 1500 0
+1335 1427 -1500 0
+-1335 -1427 -1500 0
+-1336 1428 1501 0
+1336 -1428 1501 0
+1336 1428 -1501 0
+-1336 -1428 -1501 0
+-1501 1502 0
+-1500 1502 0
+-1499 1502 0
+1499 1500 1501 -1502 0
+1345 1477 1503 0
+-1345 -1477 1503 0
+-1345 1477 -1503 0
+1345 -1477 -1503 0
+1346 1478 1504 0
+-1346 -1478 1504 0
+-1346 1478 -1504 0
+1346 -1478 -1504 0
+1347 1479 1505 0
+-1347 -1479 1505 0
+-1347 1479 -1505 0
+1347 -1479 -1505 0
+1505 -1506 0
+1504 -1506 0
+1503 -1506 0
+1502 -1506 0
+-1345 1426 1507 0
+1345 -1426 1507 0
+1345 1426 -1507 0
+-1345 -1426 -1507 0
+-1346 1427 1508 0
+1346 -1427 1508 0
+1346 1427 -1508 0
+-1346 -1427 -1508 0
+-1347 1428 1509 0
+1347 -1428 1509 0
+1347 1428 -1509 0
+-1347 -1428 -1509 0
+-1509 1510 0
+-1508 1510 0
+-1507 1510 0
+1507 1508 1509 -1510 0
+1356 1477 1511 0
+-1356 -1477 1511 0
+-1356 1477 -1511 0
+1356 -1477 -1511 0
+1357 1478 1512 0
+-1357 -1478 1512 0
+-1357 1478 -1512 0
+1357 -1478 -1512 0
+1358 1479 1513 0
+-1358 -1479 1513 0
+-1358 1479 -1513 0
+1358 -1479 -1513 0
+1513 -1514 0
+1512 -1514 0
+1511 -1514 0
+1510 -1514 0
+-1356 1426 1515 0
+1356 -1426 1515 0
+1356 1426 -1515 0
+-1356 -1426 -1515 0
+-1357 1427 1516 0
+1357 -1427 1516 0
+1357 1427 -1516 0
+-1357 -1427 -1516 0
+-1358 1428 1517 0
+1358 -1428 1517 0
+1358 1428 -1517 0
+-1358 -1428 -1517 0
+-1517 1518 0
+-1516 1518 0
+-1515 1518 0
+1515 1516 1517 -1518 0
+1302 1477 1519 0
+-1302 -1477 1519 0
+-1302 1477 -1519 0
+1302 -1477 -1519 0
+1303 1478 1520 0
+-1303 -1478 1520 0
+-1303 1478 -1520 0
+1303 -1478 -1520 0
+1304 1479 1521 0
+-1304 -1479 1521 0
+-1304 1479 -1521 0
+1304 -1479 -1521 0
+1521 -1522 0
+1520 -1522 0
+1519 -1522 0
+1518 -1522 0
+-1302 1477 1523 0
+1302 -1477 1523 0
+1302 1477 -1523 0
+-1302 -1477 -1523 0
+-1303 1478 1524 0
+1303 -1478 1524 0
+1303 1478 -1524 0
+-1303 -1478 -1524 0
+-1304 1479 1525 0
+1304 -1479 1525 0
+1304 1479 -1525 0
+-1304 -1479 -1525 0
+-1525 1526 0
+-1524 1526 0
+-1523 1526 0
+1523 1524 1525 -1526 0
+1312 1527 1528 0
+-1312 1527 -1528 0
+-1312 -1527 1528 0
+1312 -1527 -1528 0
+1313 1529 1531 0
+-1313 -1529 1531 0
+-1313 1529 -1531 0
+1313 -1529 -1531 0
+1314 1530 1532 0
+-1314 -1530 1532 0
+-1314 1530 -1532 0
+1314 -1530 -1532 0
+1532 -1533 0
+1531 -1533 0
+1527 -1533 0
+1526 -1533 0
+-1312 1477 1534 0
+1312 -1477 1534 0
+1312 1477 -1534 0
+-1312 -1477 -1534 0
+-1313 1478 1535 0
+1313 -1478 1535 0
+1313 1478 -1535 0
+-1313 -1478 -1535 0
+-1314 1479 1536 0
+1314 -1479 1536 0
+1314 1479 -1536 0
+-1314 -1479 -1536 0
+-1536 1537 0
+-1535 1537 0
+-1534 1537 0
+1534 1535 1536 -1537 0
+1323 1528 1538 0
+-1323 -1528 1538 0
+-1323 1528 -1538 0
+1323 -1528 -1538 0
+1324 1529 1539 0
+-1324 -1529 1539 0
+-1324 1529 -1539 0
+1324 -1529 -1539 0
+1325 1530 1540 0
+-1325 -1530 1540 0
+-1325 1530 -1540 0
+1325 -1530 -1540 0
+1540 -1541 0
+1539 -1541 0
+1538 -1541 0
+1537 -1541 0
+-1323 1477 1542 0
+1323 -1477 1542 0
+1323 1477 -1542 0
+-1323 -1477 -1542 0
+-1324 1478 1543 0
+1324 -1478 1543 0
+1324 1478 -1543 0
+-1324 -1478 -1543 0
+-1325 1479 1544 0
+1325 -1479 1544 0
+1325 1479 -1544 0
+-1325 -1479 -1544 0
+-1544 1545 0
+-1543 1545 0
+-1542 1545 0
+1542 1543 1544 -1545 0
+1334 1528 1546 0
+-1334 -1528 1546 0
+-1334 1528 -1546 0
+1334 -1528 -1546 0
+1335 1529 1547 0
+-1335 -1529 1547 0
+-1335 1529 -1547 0
+1335 -1529 -1547 0
+1336 1530 1548 0
+-1336 -1530 1548 0
+-1336 1530 -1548 0
+1336 -1530 -1548 0
+1548 -1549 0
+1547 -1549 0
+1546 -1549 0
+1545 -1549 0
+-1334 1477 1550 0
+1334 -1477 1550 0
+1334 1477 -1550 0
+-1334 -1477 -1550 0
+-1335 1478 1551 0
+1335 -1478 1551 0
+1335 1478 -1551 0
+-1335 -1478 -1551 0
+-1336 1479 1552 0
+1336 -1479 1552 0
+1336 1479 -1552 0
+-1336 -1479 -1552 0
+-1552 1553 0
+-1551 1553 0
+-1550 1553 0
+1550 1551 1552 -1553 0
+1345 1528 1554 0
+-1345 -1528 1554 0
+-1345 1528 -1554 0
+1345 -1528 -1554 0
+1346 1529 1555 0
+-1346 -1529 1555 0
+-1346 1529 -1555 0
+1346 -1529 -1555 0
+1347 1530 1556 0
+-1347 -1530 1556 0
+-1347 1530 -1556 0
+1347 -1530 -1556 0
+1556 -1557 0
+1555 -1557 0
+1554 -1557 0
+1553 -1557 0
+-1345 1477 1558 0
+1345 -1477 1558 0
+1345 1477 -1558 0
+-1345 -1477 -1558 0
+-1346 1478 1559 0
+1346 -1478 1559 0
+1346 1478 -1559 0
+-1346 -1478 -1559 0
+-1347 1479 1560 0
+1347 -1479 1560 0
+1347 1479 -1560 0
+-1347 -1479 -1560 0
+-1560 1561 0
+-1559 1561 0
+-1558 1561 0
+1558 1559 1560 -1561 0
+1356 1528 1562 0
+-1356 -1528 1562 0
+-1356 1528 -1562 0
+1356 -1528 -1562 0
+1357 1529 1563 0
+-1357 -1529 1563 0
+-1357 1529 -1563 0
+1357 -1529 -1563 0
+1358 1530 1564 0
+-1358 -1530 1564 0
+-1358 1530 -1564 0
+1358 -1530 -1564 0
+1564 -1565 0
+1563 -1565 0
+1562 -1565 0
+1561 -1565 0
+-1356 1477 1566 0
+1356 -1477 1566 0
+1356 1477 -1566 0
+-1356 -1477 -1566 0
+-1357 1478 1567 0
+1357 -1478 1567 0
+1357 1478 -1567 0
+-1357 -1478 -1567 0
+-1358 1479 1568 0
+1358 -1479 1568 0
+1358 1479 -1568 0
+-1358 -1479 -1568 0
+-1568 1569 0
+-1567 1569 0
+-1566 1569 0
+1566 1567 1568 -1569 0
+1302 1528 1570 0
+-1302 -1528 1570 0
+-1302 1528 -1570 0
+1302 -1528 -1570 0
+1303 1529 1571 0
+-1303 -1529 1571 0
+-1303 1529 -1571 0
+1303 -1529 -1571 0
+1304 1530 1572 0
+-1304 -1530 1572 0
+-1304 1530 -1572 0
+1304 -1530 -1572 0
+1572 -1573 0
+1571 -1573 0
+1570 -1573 0
+1569 -1573 0
+-1302 1528 1574 0
+1302 -1528 1574 0
+1302 1528 -1574 0
+-1302 -1528 -1574 0
+-1303 1529 1575 0
+1303 -1529 1575 0
+1303 1529 -1575 0
+-1303 -1529 -1575 0
+-1304 1530 1576 0
+1304 -1530 1576 0
+1304 1530 -1576 0
+-1304 -1530 -1576 0
+-1576 1577 0
+-1575 1577 0
+-1574 1577 0
+1574 1575 1576 -1577 0
+1299 1312 1578 0
+-1299 -1312 1578 0
+1299 -1312 -1578 0
+-1299 1312 -1578 0
+1300 1313 1579 0
+-1300 -1313 1579 0
+1300 -1313 -1579 0
+-1300 1313 -1579 0
+1301 1314 1580 0
+-1301 -1314 1580 0
+1301 -1314 -1580 0
+-1301 1314 -1580 0
+1580 -1581 0
+1579 -1581 0
+1578 -1581 0
+1577 -1581 0
+-1312 1528 1582 0
+1312 -1528 1582 0
+1312 1528 -1582 0
+-1312 -1528 -1582 0
+-1313 1529 1583 0
+1313 -1529 1583 0
+1313 1529 -1583 0
+-1313 -1529 -1583 0
+-1314 1530 1584 0
+1314 -1530 1584 0
+1314 1530 -1584 0
+-1314 -1530 -1584 0
+-1584 1585 0
+-1583 1585 0
+-1582 1585 0
+1582 1583 1584 -1585 0
+1299 1323 1586 0
+-1299 -1323 1586 0
+1299 -1323 -1586 0
+-1299 1323 -1586 0
+1300 1324 1587 0
+-1300 -1324 1587 0
+1300 -1324 -1587 0
+-1300 1324 -1587 0
+1301 1325 1588 0
+-1301 -1325 1588 0
+1301 -1325 -1588 0
+-1301 1325 -1588 0
+1588 -1589 0
+1587 -1589 0
+1586 -1589 0
+1585 -1589 0
+-1323 1528 1590 0
+1323 -1528 1590 0
+1323 1528 -1590 0
+-1323 -1528 -1590 0
+-1324 1529 1591 0
+1324 -1529 1591 0
+1324 1529 -1591 0
+-1324 -1529 -1591 0
+-1325 1530 1592 0
+1325 -1530 1592 0
+1325 1530 -1592 0
+-1325 -1530 -1592 0
+-1592 1593 0
+-1591 1593 0
+-1590 1593 0
+1590 1591 1592 -1593 0
+1299 1334 1594 0
+-1299 -1334 1594 0
+1299 -1334 -1594 0
+-1299 1334 -1594 0
+1300 1335 1595 0
+-1300 -1335 1595 0
+1300 -1335 -1595 0
+-1300 1335 -1595 0
+1301 1336 1596 0
+-1301 -1336 1596 0
+1301 -1336 -1596 0
+-1301 1336 -1596 0
+1596 -1597 0
+1595 -1597 0
+1594 -1597 0
+1593 -1597 0
+-1334 1528 1598 0
+1334 -1528 1598 0
+1334 1528 -1598 0
+-1334 -1528 -1598 0
+-1335 1529 1599 0
+1335 -1529 1599 0
+1335 1529 -1599 0
+-1335 -1529 -1599 0
+-1336 1530 1600 0
+1336 -1530 1600 0
+1336 1530 -1600 0
+-1336 -1530 -1600 0
+-1600 1601 0
+-1599 1601 0
+-1598 1601 0
+1598 1599 1600 -1601 0
+1299 1345 1602 0
+-1299 -1345 1602 0
+1299 -1345 -1602 0
+-1299 1345 -1602 0
+1300 1346 1603 0
+-1300 -1346 1603 0
+1300 -1346 -1603 0
+-1300 1346 -1603 0
+1301 1347 1604 0
+-1301 -1347 1604 0
+1301 -1347 -1604 0
+-1301 1347 -1604 0
+1604 -1605 0
+1603 -1605 0
+1602 -1605 0
+1601 -1605 0
+-1345 1528 1606 0
+1345 -1528 1606 0
+1345 1528 -1606 0
+-1345 -1528 -1606 0
+-1346 1529 1607 0
+1346 -1529 1607 0
+1346 1529 -1607 0
+-1346 -1529 -1607 0
+-1347 1530 1608 0
+1347 -1530 1608 0
+1347 1530 -1608 0
+-1347 -1530 -1608 0
+-1608 1609 0
+-1607 1609 0
+-1606 1609 0
+1606 1607 1608 -1609 0
+1299 1356 1610 0
+-1299 -1356 1610 0
+1299 -1356 -1610 0
+-1299 1356 -1610 0
+1300 1357 1611 0
+-1300 -1357 1611 0
+1300 -1357 -1611 0
+-1300 1357 -1611 0
+1301 1358 1612 0
+-1301 -1358 1612 0
+1301 -1358 -1612 0
+-1301 1358 -1612 0
+1612 -1613 0
+1611 -1613 0
+1610 -1613 0
+1609 -1613 0
+-1356 1528 1614 0
+1356 -1528 1614 0
+1356 1528 -1614 0
+-1356 -1528 -1614 0
+-1357 1529 1615 0
+1357 -1529 1615 0
+1357 1529 -1615 0
+-1357 -1529 -1615 0
+-1358 1530 1616 0
+1358 -1530 1616 0
+1358 1530 -1616 0
+-1358 -1530 -1616 0
+-1616 1617 0
+-1615 1617 0
+-1614 1617 0
+1614 1615 1616 -1617 0
+1299 1302 1618 0
+-1299 -1302 1618 0
+1299 -1302 -1618 0
+-1299 1302 -1618 0
+1300 1303 1619 0
+-1300 -1303 1619 0
+1300 -1303 -1619 0
+-1300 1303 -1619 0
+1301 1304 1620 0
+-1301 -1304 1620 0
+1301 -1304 -1620 0
+-1301 1304 -1620 0
+1620 -1621 0
+1619 -1621 0
+1618 -1621 0
+1617 -1621 0
+1622 1623 -1626 0
+1622 -1623 1626 0
+-1622 1623 1626 0
+-1622 -1623 -1626 0
+1624 -1627 1629 0
+-1624 1627 1629 0
+1624 1627 -1629 0
+-1624 -1627 -1629 0
+1625 -1628 1630 0
+-1625 1628 1630 0
+1625 1628 -1630 0
+-1625 -1628 -1630 0
+-1630 1631 0
+-1629 1631 0
+-1622 1631 0
+1622 1629 1630 -1631 0
+1632 1633 1636 0
+1632 -1633 -1636 0
+-1632 1633 -1636 0
+-1632 -1633 1636 0
+1634 1637 1639 0
+-1634 -1637 1639 0
+1634 -1637 -1639 0
+-1634 1637 -1639 0
+1635 1638 1640 0
+-1635 -1638 1640 0
+1635 -1638 -1640 0
+-1635 1638 -1640 0
+1640 -1641 0
+1639 -1641 0
+1632 -1641 0
+1631 -1641 0
+1623 -1636 1642 0
+-1623 1636 1642 0
+1623 1636 -1642 0
+-1623 -1636 -1642 0
+1624 -1637 1643 0
+-1624 1637 1643 0
+1624 1637 -1643 0
+-1624 -1637 -1643 0
+1625 -1638 1644 0
+-1625 1638 1644 0
+1625 1638 -1644 0
+-1625 -1638 -1644 0
+-1644 1645 0
+-1643 1645 0
+-1642 1645 0
+1642 1643 1644 -1645 0
+1633 1646 1647 0
+-1633 1646 -1647 0
+1633 -1646 -1647 0
+-1633 -1646 1647 0
+1634 1648 1650 0
+-1634 -1648 1650 0
+1634 -1648 -1650 0
+-1634 1648 -1650 0
+1635 1649 1651 0
+-1635 -1649 1651 0
+1635 -1649 -1651 0
+-1635 1649 -1651 0
+1651 -1652 0
+1650 -1652 0
+1646 -1652 0
+1645 -1652 0
+1623 -1647 1653 0
+-1623 1647 1653 0
+1623 1647 -1653 0
+-1623 -1647 -1653 0
+1624 -1648 1654 0
+-1624 1648 1654 0
+1624 1648 -1654 0
+-1624 -1648 -1654 0
+1625 -1649 1655 0
+-1625 1649 1655 0
+1625 1649 -1655 0
+-1625 -1649 -1655 0
+-1655 1656 0
+-1654 1656 0
+-1653 1656 0
+1653 1654 1655 -1656 0
+1633 1657 1658 0
+-1633 1657 -1658 0
+1633 -1657 -1658 0
+-1633 -1657 1658 0
+1634 1659 1661 0
+-1634 -1659 1661 0
+1634 -1659 -1661 0
+-1634 1659 -1661 0
+1635 1660 1662 0
+-1635 -1660 1662 0
+1635 -1660 -1662 0
+-1635 1660 -1662 0
+1662 -1663 0
+1661 -1663 0
+1657 -1663 0
+1656 -1663 0
+1623 -1658 1664 0
+-1623 1658 1664 0
+1623 1658 -1664 0
+-1623 -1658 -1664 0
+1624 -1659 1665 0
+-1624 1659 1665 0
+1624 1659 -1665 0
+-1624 -1659 -1665 0
+1625 -1660 1666 0
+-1625 1660 1666 0
+1625 1660 -1666 0
+-1625 -1660 -1666 0
+-1666 1667 0
+-1665 1667 0
+-1664 1667 0
+1664 1665 1666 -1667 0
+1633 1668 1669 0
+-1633 1668 -1669 0
+1633 -1668 -1669 0
+-1633 -1668 1669 0
+1634 1670 1672 0
+-1634 -1670 1672 0
+1634 -1670 -1672 0
+-1634 1670 -1672 0
+1635 1671 1673 0
+-1635 -1671 1673 0
+1635 -1671 -1673 0
+-1635 1671 -1673 0
+1673 -1674 0
+1672 -1674 0
+1668 -1674 0
+1667 -1674 0
+1623 -1669 1675 0
+-1623 1669 1675 0
+1623 1669 -1675 0
+-1623 -1669 -1675 0
+1624 -1670 1676 0
+-1624 1670 1676 0
+1624 1670 -1676 0
+-1624 -1670 -1676 0
+1625 -1671 1677 0
+-1625 1671 1677 0
+1625 1671 -1677 0
+-1625 -1671 -1677 0
+-1677 1678 0
+-1676 1678 0
+-1675 1678 0
+1675 1676 1677 -1678 0
+1633 1679 1680 0
+-1633 1679 -1680 0
+1633 -1679 -1680 0
+-1633 -1679 1680 0
+1634 1681 1683 0
+-1634 -1681 1683 0
+1634 -1681 -1683 0
+-1634 1681 -1683 0
+1635 1682 1684 0
+-1635 -1682 1684 0
+1635 -1682 -1684 0
+-1635 1682 -1684 0
+1684 -1685 0
+1683 -1685 0
+1679 -1685 0
+1678 -1685 0
+1623 -1680 1686 0
+-1623 1680 1686 0
+1623 1680 -1686 0
+-1623 -1680 -1686 0
+1624 -1681 1687 0
+-1624 1681 1687 0
+1624 1681 -1687 0
+-1624 -1681 -1687 0
+1625 -1682 1688 0
+-1625 1682 1688 0
+1625 1682 -1688 0
+-1625 -1682 -1688 0
+-1688 1689 0
+-1687 1689 0
+-1686 1689 0
+1686 1687 1688 -1689 0
+1626 1633 1690 0
+-1626 -1633 1690 0
+-1626 1633 -1690 0
+1626 -1633 -1690 0
+1627 1634 1691 0
+-1627 -1634 1691 0
+-1627 1634 -1691 0
+1627 -1634 -1691 0
+1628 1635 1692 0
+-1628 -1635 1692 0
+-1628 1635 -1692 0
+1628 -1635 -1692 0
+1692 -1693 0
+1691 -1693 0
+1690 -1693 0
+1689 -1693 0
+-1626 1633 1694 0
+1626 -1633 1694 0
+1626 1633 -1694 0
+-1626 -1633 -1694 0
+-1627 1634 1695 0
+1627 -1634 1695 0
+1627 1634 -1695 0
+-1627 -1634 -1695 0
+-1628 1635 1696 0
+1628 -1635 1696 0
+1628 1635 -1696 0
+-1628 -1635 -1696 0
+-1696 1697 0
+-1695 1697 0
+-1694 1697 0
+1694 1695 1696 -1697 0
+1636 1698 1699 0
+-1636 1698 -1699 0
+-1636 -1698 1699 0
+1636 -1698 -1699 0
+1637 1700 1702 0
+-1637 -1700 1702 0
+-1637 1700 -1702 0
+1637 -1700 -1702 0
+1638 1701 1703 0
+-1638 -1701 1703 0
+-1638 1701 -1703 0
+1638 -1701 -1703 0
+1703 -1704 0
+1702 -1704 0
+1698 -1704 0
+1697 -1704 0
+1633 -1636 1705 0
+-1633 1636 1705 0
+1633 1636 -1705 0
+-1633 -1636 -1705 0
+1634 -1637 1706 0
+-1634 1637 1706 0
+1634 1637 -1706 0
+-1634 -1637 -1706 0
+1635 -1638 1707 0
+-1635 1638 1707 0
+1635 1638 -1707 0
+-1635 -1638 -1707 0
+-1707 1708 0
+-1706 1708 0
+-1705 1708 0
+1705 1706 1707 -1708 0
+1647 1699 1709 0
+-1647 -1699 1709 0
+-1647 1699 -1709 0
+1647 -1699 -1709 0
+1648 1700 1710 0
+-1648 -1700 1710 0
+-1648 1700 -1710 0
+1648 -1700 -1710 0
+1649 1701 1711 0
+-1649 -1701 1711 0
+-1649 1701 -1711 0
+1649 -1701 -1711 0
+1711 -1712 0
+1710 -1712 0
+1709 -1712 0
+1708 -1712 0
+1633 -1647 1713 0
+-1633 1647 1713 0
+1633 1647 -1713 0
+-1633 -1647 -1713 0
+1634 -1648 1714 0
+-1634 1648 1714 0
+1634 1648 -1714 0
+-1634 -1648 -1714 0
+1635 -1649 1715 0
+-1635 1649 1715 0
+1635 1649 -1715 0
+-1635 -1649 -1715 0
+-1715 1716 0
+-1714 1716 0
+-1713 1716 0
+1713 1714 1715 -1716 0
+1658 1699 1717 0
+-1658 -1699 1717 0
+-1658 1699 -1717 0
+1658 -1699 -1717 0
+1659 1700 1718 0
+-1659 -1700 1718 0
+-1659 1700 -1718 0
+1659 -1700 -1718 0
+1660 1701 1719 0
+-1660 -1701 1719 0
+-1660 1701 -1719 0
+1660 -1701 -1719 0
+1719 -1720 0
+1718 -1720 0
+1717 -1720 0
+1716 -1720 0
+1633 -1658 1721 0
+-1633 1658 1721 0
+1633 1658 -1721 0
+-1633 -1658 -1721 0
+1634 -1659 1722 0
+-1634 1659 1722 0
+1634 1659 -1722 0
+-1634 -1659 -1722 0
+1635 -1660 1723 0
+-1635 1660 1723 0
+1635 1660 -1723 0
+-1635 -1660 -1723 0
+-1723 1724 0
+-1722 1724 0
+-1721 1724 0
+1721 1722 1723 -1724 0
+1669 1699 1725 0
+-1669 -1699 1725 0
+-1669 1699 -1725 0
+1669 -1699 -1725 0
+1670 1700 1726 0
+-1670 -1700 1726 0
+-1670 1700 -1726 0
+1670 -1700 -1726 0
+1671 1701 1727 0
+-1671 -1701 1727 0
+-1671 1701 -1727 0
+1671 -1701 -1727 0
+1727 -1728 0
+1726 -1728 0
+1725 -1728 0
+1724 -1728 0
+1633 -1669 1729 0
+-1633 1669 1729 0
+1633 1669 -1729 0
+-1633 -1669 -1729 0
+1634 -1670 1730 0
+-1634 1670 1730 0
+1634 1670 -1730 0
+-1634 -1670 -1730 0
+1635 -1671 1731 0
+-1635 1671 1731 0
+1635 1671 -1731 0
+-1635 -1671 -1731 0
+-1731 1732 0
+-1730 1732 0
+-1729 1732 0
+1729 1730 1731 -1732 0
+1680 1699 1733 0
+-1680 -1699 1733 0
+-1680 1699 -1733 0
+1680 -1699 -1733 0
+1681 1700 1734 0
+-1681 -1700 1734 0
+-1681 1700 -1734 0
+1681 -1700 -1734 0
+1682 1701 1735 0
+-1682 -1701 1735 0
+-1682 1701 -1735 0
+1682 -1701 -1735 0
+1735 -1736 0
+1734 -1736 0
+1733 -1736 0
+1732 -1736 0
+1633 -1680 1737 0
+-1633 1680 1737 0
+1633 1680 -1737 0
+-1633 -1680 -1737 0
+1634 -1681 1738 0
+-1634 1681 1738 0
+1634 1681 -1738 0
+-1634 -1681 -1738 0
+1635 -1682 1739 0
+-1635 1682 1739 0
+1635 1682 -1739 0
+-1635 -1682 -1739 0
+-1739 1740 0
+-1738 1740 0
+-1737 1740 0
+1737 1738 1739 -1740 0
+1626 1699 1741 0
+-1626 -1699 1741 0
+-1626 1699 -1741 0
+1626 -1699 -1741 0
+1627 1700 1742 0
+-1627 -1700 1742 0
+-1627 1700 -1742 0
+1627 -1700 -1742 0
+1628 1701 1743 0
+-1628 -1701 1743 0
+-1628 1701 -1743 0
+1628 -1701 -1743 0
+1743 -1744 0
+1742 -1744 0
+1741 -1744 0
+1740 -1744 0
+-1626 1699 1745 0
+1626 -1699 1745 0
+1626 1699 -1745 0
+-1626 -1699 -1745 0
+-1627 1700 1746 0
+1627 -1700 1746 0
+1627 1700 -1746 0
+-1627 -1700 -1746 0
+-1628 1701 1747 0
+1628 -1701 1747 0
+1628 1701 -1747 0
+-1628 -1701 -1747 0
+-1747 1748 0
+-1746 1748 0
+-1745 1748 0
+1745 1746 1747 -1748 0
+1636 1749 1750 0
+-1636 1749 -1750 0
+-1636 -1749 1750 0
+1636 -1749 -1750 0
+1637 1751 1753 0
+-1637 -1751 1753 0
+-1637 1751 -1753 0
+1637 -1751 -1753 0
+1638 1752 1754 0
+-1638 -1752 1754 0
+-1638 1752 -1754 0
+1638 -1752 -1754 0
+1754 -1755 0
+1753 -1755 0
+1749 -1755 0
+1748 -1755 0
+-1636 1699 1756 0
+1636 -1699 1756 0
+1636 1699 -1756 0
+-1636 -1699 -1756 0
+-1637 1700 1757 0
+1637 -1700 1757 0
+1637 1700 -1757 0
+-1637 -1700 -1757 0
+-1638 1701 1758 0
+1638 -1701 1758 0
+1638 1701 -1758 0
+-1638 -1701 -1758 0
+-1758 1759 0
+-1757 1759 0
+-1756 1759 0
+1756 1757 1758 -1759 0
+1647 1750 1760 0
+-1647 -1750 1760 0
+-1647 1750 -1760 0
+1647 -1750 -1760 0
+1648 1751 1761 0
+-1648 -1751 1761 0
+-1648 1751 -1761 0
+1648 -1751 -1761 0
+1649 1752 1762 0
+-1649 -1752 1762 0
+-1649 1752 -1762 0
+1649 -1752 -1762 0
+1762 -1763 0
+1761 -1763 0
+1760 -1763 0
+1759 -1763 0
+-1647 1699 1764 0
+1647 -1699 1764 0
+1647 1699 -1764 0
+-1647 -1699 -1764 0
+-1648 1700 1765 0
+1648 -1700 1765 0
+1648 1700 -1765 0
+-1648 -1700 -1765 0
+-1649 1701 1766 0
+1649 -1701 1766 0
+1649 1701 -1766 0
+-1649 -1701 -1766 0
+-1766 1767 0
+-1765 1767 0
+-1764 1767 0
+1764 1765 1766 -1767 0
+1658 1750 1768 0
+-1658 -1750 1768 0
+-1658 1750 -1768 0
+1658 -1750 -1768 0
+1659 1751 1769 0
+-1659 -1751 1769 0
+-1659 1751 -1769 0
+1659 -1751 -1769 0
+1660 1752 1770 0
+-1660 -1752 1770 0
+-1660 1752 -1770 0
+1660 -1752 -1770 0
+1770 -1771 0
+1769 -1771 0
+1768 -1771 0
+1767 -1771 0
+-1658 1699 1772 0
+1658 -1699 1772 0
+1658 1699 -1772 0
+-1658 -1699 -1772 0
+-1659 1700 1773 0
+1659 -1700 1773 0
+1659 1700 -1773 0
+-1659 -1700 -1773 0
+-1660 1701 1774 0
+1660 -1701 1774 0
+1660 1701 -1774 0
+-1660 -1701 -1774 0
+-1774 1775 0
+-1773 1775 0
+-1772 1775 0
+1772 1773 1774 -1775 0
+1669 1750 1776 0
+-1669 -1750 1776 0
+-1669 1750 -1776 0
+1669 -1750 -1776 0
+1670 1751 1777 0
+-1670 -1751 1777 0
+-1670 1751 -1777 0
+1670 -1751 -1777 0
+1671 1752 1778 0
+-1671 -1752 1778 0
+-1671 1752 -1778 0
+1671 -1752 -1778 0
+1778 -1779 0
+1777 -1779 0
+1776 -1779 0
+1775 -1779 0
+-1669 1699 1780 0
+1669 -1699 1780 0
+1669 1699 -1780 0
+-1669 -1699 -1780 0
+-1670 1700 1781 0
+1670 -1700 1781 0
+1670 1700 -1781 0
+-1670 -1700 -1781 0
+-1671 1701 1782 0
+1671 -1701 1782 0
+1671 1701 -1782 0
+-1671 -1701 -1782 0
+-1782 1783 0
+-1781 1783 0
+-1780 1783 0
+1780 1781 1782 -1783 0
+1680 1750 1784 0
+-1680 -1750 1784 0
+-1680 1750 -1784 0
+1680 -1750 -1784 0
+1681 1751 1785 0
+-1681 -1751 1785 0
+-1681 1751 -1785 0
+1681 -1751 -1785 0
+1682 1752 1786 0
+-1682 -1752 1786 0
+-1682 1752 -1786 0
+1682 -1752 -1786 0
+1786 -1787 0
+1785 -1787 0
+1784 -1787 0
+1783 -1787 0
+-1680 1699 1788 0
+1680 -1699 1788 0
+1680 1699 -1788 0
+-1680 -1699 -1788 0
+-1681 1700 1789 0
+1681 -1700 1789 0
+1681 1700 -1789 0
+-1681 -1700 -1789 0
+-1682 1701 1790 0
+1682 -1701 1790 0
+1682 1701 -1790 0
+-1682 -1701 -1790 0
+-1790 1791 0
+-1789 1791 0
+-1788 1791 0
+1788 1789 1790 -1791 0
+1626 1750 1792 0
+-1626 -1750 1792 0
+-1626 1750 -1792 0
+1626 -1750 -1792 0
+1627 1751 1793 0
+-1627 -1751 1793 0
+-1627 1751 -1793 0
+1627 -1751 -1793 0
+1628 1752 1794 0
+-1628 -1752 1794 0
+-1628 1752 -1794 0
+1628 -1752 -1794 0
+1794 -1795 0
+1793 -1795 0
+1792 -1795 0
+1791 -1795 0
+-1626 1750 1796 0
+1626 -1750 1796 0
+1626 1750 -1796 0
+-1626 -1750 -1796 0
+-1627 1751 1797 0
+1627 -1751 1797 0
+1627 1751 -1797 0
+-1627 -1751 -1797 0
+-1628 1752 1798 0
+1628 -1752 1798 0
+1628 1752 -1798 0
+-1628 -1752 -1798 0
+-1798 1799 0
+-1797 1799 0
+-1796 1799 0
+1796 1797 1798 -1799 0
+1636 1800 1801 0
+-1636 1800 -1801 0
+-1636 -1800 1801 0
+1636 -1800 -1801 0
+1637 1802 1804 0
+-1637 -1802 1804 0
+-1637 1802 -1804 0
+1637 -1802 -1804 0
+1638 1803 1805 0
+-1638 -1803 1805 0
+-1638 1803 -1805 0
+1638 -1803 -1805 0
+1805 -1806 0
+1804 -1806 0
+1800 -1806 0
+1799 -1806 0
+-1636 1750 1807 0
+1636 -1750 1807 0
+1636 1750 -1807 0
+-1636 -1750 -1807 0
+-1637 1751 1808 0
+1637 -1751 1808 0
+1637 1751 -1808 0
+-1637 -1751 -1808 0
+-1638 1752 1809 0
+1638 -1752 1809 0
+1638 1752 -1809 0
+-1638 -1752 -1809 0
+-1809 1810 0
+-1808 1810 0
+-1807 1810 0
+1807 1808 1809 -1810 0
+1647 1801 1811 0
+-1647 -1801 1811 0
+-1647 1801 -1811 0
+1647 -1801 -1811 0
+1648 1802 1812 0
+-1648 -1802 1812 0
+-1648 1802 -1812 0
+1648 -1802 -1812 0
+1649 1803 1813 0
+-1649 -1803 1813 0
+-1649 1803 -1813 0
+1649 -1803 -1813 0
+1813 -1814 0
+1812 -1814 0
+1811 -1814 0
+1810 -1814 0
+-1647 1750 1815 0
+1647 -1750 1815 0
+1647 1750 -1815 0
+-1647 -1750 -1815 0
+-1648 1751 1816 0
+1648 -1751 1816 0
+1648 1751 -1816 0
+-1648 -1751 -1816 0
+-1649 1752 1817 0
+1649 -1752 1817 0
+1649 1752 -1817 0
+-1649 -1752 -1817 0
+-1817 1818 0
+-1816 1818 0
+-1815 1818 0
+1815 1816 1817 -1818 0
+1658 1801 1819 0
+-1658 -1801 1819 0
+-1658 1801 -1819 0
+1658 -1801 -1819 0
+1659 1802 1820 0
+-1659 -1802 1820 0
+-1659 1802 -1820 0
+1659 -1802 -1820 0
+1660 1803 1821 0
+-1660 -1803 1821 0
+-1660 1803 -1821 0
+1660 -1803 -1821 0
+1821 -1822 0
+1820 -1822 0
+1819 -1822 0
+1818 -1822 0
+-1658 1750 1823 0
+1658 -1750 1823 0
+1658 1750 -1823 0
+-1658 -1750 -1823 0
+-1659 1751 1824 0
+1659 -1751 1824 0
+1659 1751 -1824 0
+-1659 -1751 -1824 0
+-1660 1752 1825 0
+1660 -1752 1825 0
+1660 1752 -1825 0
+-1660 -1752 -1825 0
+-1825 1826 0
+-1824 1826 0
+-1823 1826 0
+1823 1824 1825 -1826 0
+1669 1801 1827 0
+-1669 -1801 1827 0
+-1669 1801 -1827 0
+1669 -1801 -1827 0
+1670 1802 1828 0
+-1670 -1802 1828 0
+-1670 1802 -1828 0
+1670 -1802 -1828 0
+1671 1803 1829 0
+-1671 -1803 1829 0
+-1671 1803 -1829 0
+1671 -1803 -1829 0
+1829 -1830 0
+1828 -1830 0
+1827 -1830 0
+1826 -1830 0
+-1669 1750 1831 0
+1669 -1750 1831 0
+1669 1750 -1831 0
+-1669 -1750 -1831 0
+-1670 1751 1832 0
+1670 -1751 1832 0
+1670 1751 -1832 0
+-1670 -1751 -1832 0
+-1671 1752 1833 0
+1671 -1752 1833 0
+1671 1752 -1833 0
+-1671 -1752 -1833 0
+-1833 1834 0
+-1832 1834 0
+-1831 1834 0
+1831 1832 1833 -1834 0
+1680 1801 1835 0
+-1680 -1801 1835 0
+-1680 1801 -1835 0
+1680 -1801 -1835 0
+1681 1802 1836 0
+-1681 -1802 1836 0
+-1681 1802 -1836 0
+1681 -1802 -1836 0
+1682 1803 1837 0
+-1682 -1803 1837 0
+-1682 1803 -1837 0
+1682 -1803 -1837 0
+1837 -1838 0
+1836 -1838 0
+1835 -1838 0
+1834 -1838 0
+-1680 1750 1839 0
+1680 -1750 1839 0
+1680 1750 -1839 0
+-1680 -1750 -1839 0
+-1681 1751 1840 0
+1681 -1751 1840 0
+1681 1751 -1840 0
+-1681 -1751 -1840 0
+-1682 1752 1841 0
+1682 -1752 1841 0
+1682 1752 -1841 0
+-1682 -1752 -1841 0
+-1841 1842 0
+-1840 1842 0
+-1839 1842 0
+1839 1840 1841 -1842 0
+1626 1801 1843 0
+-1626 -1801 1843 0
+-1626 1801 -1843 0
+1626 -1801 -1843 0
+1627 1802 1844 0
+-1627 -1802 1844 0
+-1627 1802 -1844 0
+1627 -1802 -1844 0
+1628 1803 1845 0
+-1628 -1803 1845 0
+-1628 1803 -1845 0
+1628 -1803 -1845 0
+1845 -1846 0
+1844 -1846 0
+1843 -1846 0
+1842 -1846 0
+-1626 1801 1847 0
+1626 -1801 1847 0
+1626 1801 -1847 0
+-1626 -1801 -1847 0
+-1627 1802 1848 0
+1627 -1802 1848 0
+1627 1802 -1848 0
+-1627 -1802 -1848 0
+-1628 1803 1849 0
+1628 -1803 1849 0
+1628 1803 -1849 0
+-1628 -1803 -1849 0
+-1849 1850 0
+-1848 1850 0
+-1847 1850 0
+1847 1848 1849 -1850 0
+1636 1851 1852 0
+-1636 1851 -1852 0
+-1636 -1851 1852 0
+1636 -1851 -1852 0
+1637 1853 1855 0
+-1637 -1853 1855 0
+-1637 1853 -1855 0
+1637 -1853 -1855 0
+1638 1854 1856 0
+-1638 -1854 1856 0
+-1638 1854 -1856 0
+1638 -1854 -1856 0
+1856 -1857 0
+1855 -1857 0
+1851 -1857 0
+1850 -1857 0
+-1636 1801 1858 0
+1636 -1801 1858 0
+1636 1801 -1858 0
+-1636 -1801 -1858 0
+-1637 1802 1859 0
+1637 -1802 1859 0
+1637 1802 -1859 0
+-1637 -1802 -1859 0
+-1638 1803 1860 0
+1638 -1803 1860 0
+1638 1803 -1860 0
+-1638 -1803 -1860 0
+-1860 1861 0
+-1859 1861 0
+-1858 1861 0
+1858 1859 1860 -1861 0
+1647 1852 1862 0
+-1647 -1852 1862 0
+-1647 1852 -1862 0
+1647 -1852 -1862 0
+1648 1853 1863 0
+-1648 -1853 1863 0
+-1648 1853 -1863 0
+1648 -1853 -1863 0
+1649 1854 1864 0
+-1649 -1854 1864 0
+-1649 1854 -1864 0
+1649 -1854 -1864 0
+1864 -1865 0
+1863 -1865 0
+1862 -1865 0
+1861 -1865 0
+-1647 1801 1866 0
+1647 -1801 1866 0
+1647 1801 -1866 0
+-1647 -1801 -1866 0
+-1648 1802 1867 0
+1648 -1802 1867 0
+1648 1802 -1867 0
+-1648 -1802 -1867 0
+-1649 1803 1868 0
+1649 -1803 1868 0
+1649 1803 -1868 0
+-1649 -1803 -1868 0
+-1868 1869 0
+-1867 1869 0
+-1866 1869 0
+1866 1867 1868 -1869 0
+1658 1852 1870 0
+-1658 -1852 1870 0
+-1658 1852 -1870 0
+1658 -1852 -1870 0
+1659 1853 1871 0
+-1659 -1853 1871 0
+-1659 1853 -1871 0
+1659 -1853 -1871 0
+1660 1854 1872 0
+-1660 -1854 1872 0
+-1660 1854 -1872 0
+1660 -1854 -1872 0
+1872 -1873 0
+1871 -1873 0
+1870 -1873 0
+1869 -1873 0
+-1658 1801 1874 0
+1658 -1801 1874 0
+1658 1801 -1874 0
+-1658 -1801 -1874 0
+-1659 1802 1875 0
+1659 -1802 1875 0
+1659 1802 -1875 0
+-1659 -1802 -1875 0
+-1660 1803 1876 0
+1660 -1803 1876 0
+1660 1803 -1876 0
+-1660 -1803 -1876 0
+-1876 1877 0
+-1875 1877 0
+-1874 1877 0
+1874 1875 1876 -1877 0
+1669 1852 1878 0
+-1669 -1852 1878 0
+-1669 1852 -1878 0
+1669 -1852 -1878 0
+1670 1853 1879 0
+-1670 -1853 1879 0
+-1670 1853 -1879 0
+1670 -1853 -1879 0
+1671 1854 1880 0
+-1671 -1854 1880 0
+-1671 1854 -1880 0
+1671 -1854 -1880 0
+1880 -1881 0
+1879 -1881 0
+1878 -1881 0
+1877 -1881 0
+-1669 1801 1882 0
+1669 -1801 1882 0
+1669 1801 -1882 0
+-1669 -1801 -1882 0
+-1670 1802 1883 0
+1670 -1802 1883 0
+1670 1802 -1883 0
+-1670 -1802 -1883 0
+-1671 1803 1884 0
+1671 -1803 1884 0
+1671 1803 -1884 0
+-1671 -1803 -1884 0
+-1884 1885 0
+-1883 1885 0
+-1882 1885 0
+1882 1883 1884 -1885 0
+1680 1852 1886 0
+-1680 -1852 1886 0
+-1680 1852 -1886 0
+1680 -1852 -1886 0
+1681 1853 1887 0
+-1681 -1853 1887 0
+-1681 1853 -1887 0
+1681 -1853 -1887 0
+1682 1854 1888 0
+-1682 -1854 1888 0
+-1682 1854 -1888 0
+1682 -1854 -1888 0
+1888 -1889 0
+1887 -1889 0
+1886 -1889 0
+1885 -1889 0
+-1680 1801 1890 0
+1680 -1801 1890 0
+1680 1801 -1890 0
+-1680 -1801 -1890 0
+-1681 1802 1891 0
+1681 -1802 1891 0
+1681 1802 -1891 0
+-1681 -1802 -1891 0
+-1682 1803 1892 0
+1682 -1803 1892 0
+1682 1803 -1892 0
+-1682 -1803 -1892 0
+-1892 1893 0
+-1891 1893 0
+-1890 1893 0
+1890 1891 1892 -1893 0
+1626 1852 1894 0
+-1626 -1852 1894 0
+-1626 1852 -1894 0
+1626 -1852 -1894 0
+1627 1853 1895 0
+-1627 -1853 1895 0
+-1627 1853 -1895 0
+1627 -1853 -1895 0
+1628 1854 1896 0
+-1628 -1854 1896 0
+-1628 1854 -1896 0
+1628 -1854 -1896 0
+1896 -1897 0
+1895 -1897 0
+1894 -1897 0
+1893 -1897 0
+-1626 1852 1898 0
+1626 -1852 1898 0
+1626 1852 -1898 0
+-1626 -1852 -1898 0
+-1627 1853 1899 0
+1627 -1853 1899 0
+1627 1853 -1899 0
+-1627 -1853 -1899 0
+-1628 1854 1900 0
+1628 -1854 1900 0
+1628 1854 -1900 0
+-1628 -1854 -1900 0
+-1900 1901 0
+-1899 1901 0
+-1898 1901 0
+1898 1899 1900 -1901 0
+1623 1636 1902 0
+-1623 -1636 1902 0
+1623 -1636 -1902 0
+-1623 1636 -1902 0
+1624 1637 1903 0
+-1624 -1637 1903 0
+1624 -1637 -1903 0
+-1624 1637 -1903 0
+1625 1638 1904 0
+-1625 -1638 1904 0
+1625 -1638 -1904 0
+-1625 1638 -1904 0
+1904 -1905 0
+1903 -1905 0
+1902 -1905 0
+1901 -1905 0
+-1636 1852 1906 0
+1636 -1852 1906 0
+1636 1852 -1906 0
+-1636 -1852 -1906 0
+-1637 1853 1907 0
+1637 -1853 1907 0
+1637 1853 -1907 0
+-1637 -1853 -1907 0
+-1638 1854 1908 0
+1638 -1854 1908 0
+1638 1854 -1908 0
+-1638 -1854 -1908 0
+-1908 1909 0
+-1907 1909 0
+-1906 1909 0
+1906 1907 1908 -1909 0
+1623 1647 1910 0
+-1623 -1647 1910 0
+1623 -1647 -1910 0
+-1623 1647 -1910 0
+1624 1648 1911 0
+-1624 -1648 1911 0
+1624 -1648 -1911 0
+-1624 1648 -1911 0
+1625 1649 1912 0
+-1625 -1649 1912 0
+1625 -1649 -1912 0
+-1625 1649 -1912 0
+1912 -1913 0
+1911 -1913 0
+1910 -1913 0
+1909 -1913 0
+-1647 1852 1914 0
+1647 -1852 1914 0
+1647 1852 -1914 0
+-1647 -1852 -1914 0
+-1648 1853 1915 0
+1648 -1853 1915 0
+1648 1853 -1915 0
+-1648 -1853 -1915 0
+-1649 1854 1916 0
+1649 -1854 1916 0
+1649 1854 -1916 0
+-1649 -1854 -1916 0
+-1916 1917 0
+-1915 1917 0
+-1914 1917 0
+1914 1915 1916 -1917 0
+1623 1658 1918 0
+-1623 -1658 1918 0
+1623 -1658 -1918 0
+-1623 1658 -1918 0
+1624 1659 1919 0
+-1624 -1659 1919 0
+1624 -1659 -1919 0
+-1624 1659 -1919 0
+1625 1660 1920 0
+-1625 -1660 1920 0
+1625 -1660 -1920 0
+-1625 1660 -1920 0
+1920 -1921 0
+1919 -1921 0
+1918 -1921 0
+1917 -1921 0
+-1658 1852 1922 0
+1658 -1852 1922 0
+1658 1852 -1922 0
+-1658 -1852 -1922 0
+-1659 1853 1923 0
+1659 -1853 1923 0
+1659 1853 -1923 0
+-1659 -1853 -1923 0
+-1660 1854 1924 0
+1660 -1854 1924 0
+1660 1854 -1924 0
+-1660 -1854 -1924 0
+-1924 1925 0
+-1923 1925 0
+-1922 1925 0
+1922 1923 1924 -1925 0
+1623 1669 1926 0
+-1623 -1669 1926 0
+1623 -1669 -1926 0
+-1623 1669 -1926 0
+1624 1670 1927 0
+-1624 -1670 1927 0
+1624 -1670 -1927 0
+-1624 1670 -1927 0
+1625 1671 1928 0
+-1625 -1671 1928 0
+1625 -1671 -1928 0
+-1625 1671 -1928 0
+1928 -1929 0
+1927 -1929 0
+1926 -1929 0
+1925 -1929 0
+-1669 1852 1930 0
+1669 -1852 1930 0
+1669 1852 -1930 0
+-1669 -1852 -1930 0
+-1670 1853 1931 0
+1670 -1853 1931 0
+1670 1853 -1931 0
+-1670 -1853 -1931 0
+-1671 1854 1932 0
+1671 -1854 1932 0
+1671 1854 -1932 0
+-1671 -1854 -1932 0
+-1932 1933 0
+-1931 1933 0
+-1930 1933 0
+1930 1931 1932 -1933 0
+1623 1680 1934 0
+-1623 -1680 1934 0
+1623 -1680 -1934 0
+-1623 1680 -1934 0
+1624 1681 1935 0
+-1624 -1681 1935 0
+1624 -1681 -1935 0
+-1624 1681 -1935 0
+1625 1682 1936 0
+-1625 -1682 1936 0
+1625 -1682 -1936 0
+-1625 1682 -1936 0
+1936 -1937 0
+1935 -1937 0
+1934 -1937 0
+1933 -1937 0
+-1680 1852 1938 0
+1680 -1852 1938 0
+1680 1852 -1938 0
+-1680 -1852 -1938 0
+-1681 1853 1939 0
+1681 -1853 1939 0
+1681 1853 -1939 0
+-1681 -1853 -1939 0
+-1682 1854 1940 0
+1682 -1854 1940 0
+1682 1854 -1940 0
+-1682 -1854 -1940 0
+-1940 1941 0
+-1939 1941 0
+-1938 1941 0
+1938 1939 1940 -1941 0
+1623 1626 1942 0
+-1623 -1626 1942 0
+1623 -1626 -1942 0
+-1623 1626 -1942 0
+1624 1627 1943 0
+-1624 -1627 1943 0
+1624 -1627 -1943 0
+-1624 1627 -1943 0
+1625 1628 1944 0
+-1625 -1628 1944 0
+1625 -1628 -1944 0
+-1625 1628 -1944 0
+1944 -1945 0
+1943 -1945 0
+1942 -1945 0
+1941 -1945 0
+-1946 1947 0
+-1946 1948 0
+-1946 1949 0
+-1946 1950 0
+-1951 1952 0
+-1951 1953 0
+-1951 1954 0
+-1951 1955 0
+-1956 1957 0
+-1956 1958 0
+-1956 1959 0
+-1956 1960 0
+-1961 1962 0
+-1961 1963 0
+-1961 1964 0
+-1961 1965 0
+-1966 1967 0
+-1966 1968 0
+-1966 1969 0
+-1966 1970 0
+-1971 1972 0
+-1971 1973 0
+-1971 1974 0
+-1971 1975 0
+-1976 1977 0
+-1976 1978 0
+-1976 1979 0
+-1976 1980 0
+-1981 1982 0
+-1981 1983 0
+-1981 1984 0
+-1981 1985 0
+-1986 1987 0
+-1986 1988 0
+-1986 1989 0
+-1986 1990 0
+-1991 1992 0
+-1991 1993 0
+-1991 1994 0
+-1991 1995 0
+-1996 1997 0
+-1996 1998 0
+-1996 1999 0
+-1996 2000 0
+-2001 2002 0
+-2001 2003 0
+-2001 2004 0
+-2001 2005 0
+-2006 2007 0
+-2006 2008 0
+-2006 2009 0
+-2006 2010 0
+-2011 2012 0
+-2011 2013 0
+-2011 2014 0
+-2011 2015 0
+-2016 2017 0
+-2016 2018 0
+-2016 2019 0
+-2016 2020 0
+-2021 2022 0
+-2021 2023 0
+-2021 2024 0
+-2021 2025 0
+-2026 2027 0
+-2026 2028 0
+-2026 2029 0
+-2026 2030 0
+-2031 2032 0
+-2031 2033 0
+-2031 2034 0
+-2031 2035 0
+-2036 2037 0
+-2036 2038 0
+-2036 2039 0
+-2036 2040 0
+-2041 2042 0
+-2041 2043 0
+-2041 2044 0
+-2041 2045 0
+-2046 2047 0
+-2046 2048 0
+-2046 2049 0
+-2046 2050 0
+-2051 2052 0
+-2051 2053 0
+-2051 2054 0
+-2051 2055 0
+-2056 2057 0
+-2056 2058 0
+-2056 2059 0
+-2056 2060 0
+-2061 2062 0
+-2061 2063 0
+-2061 2064 0
+-2061 2065 0
+-2066 2067 0
+-2066 2068 0
+-2066 2069 0
+-2066 2070 0
+-2071 2072 0
+-2071 2073 0
+-2071 2074 0
+-2071 2075 0
+-2076 2077 0
+-2076 2078 0
+-2076 2079 0
+-2076 2080 0
+-2081 2082 0
+-2081 2083 0
+-2081 2084 0
+-2081 2085 0
+-2086 2087 0
+-2086 2088 0
+-2086 2089 0
+-2086 2090 0
+-2091 2092 0
+-2091 2093 0
+-2091 2094 0
+-2091 2095 0
+-2096 2097 0
+-2096 2098 0
+-2096 2099 0
+-2096 2100 0
+-2101 2102 0
+-2101 2103 0
+-2101 2104 0
+-2101 2105 0
+-2106 2107 0
+-2106 2108 0
+-2106 2109 0
+-2106 2110 0
+-2111 2112 0
+-2111 2113 0
+-2111 2114 0
+-2111 2115 0
+-2116 2117 0
+-2116 2118 0
+-2116 2119 0
+-2116 2120 0
+-2121 2122 0
+-2121 2123 0
+-2121 2124 0
+-2121 2125 0
+-2121 2126 0
+-2116 2126 0
+-2111 2126 0
+-2106 2126 0
+-2101 2126 0
+-2096 2126 0
+-2091 2126 0
+-2086 2126 0
+-2081 2126 0
+-2076 2126 0
+-2071 2126 0
+-2066 2126 0
+-2061 2126 0
+-2056 2126 0
+-2051 2126 0
+-2046 2126 0
+-2041 2126 0
+-2036 2126 0
+-2031 2126 0
+-2026 2126 0
+-2021 2126 0
+-2016 2126 0
+-2011 2126 0
+-2006 2126 0
+-2001 2126 0
+-1996 2126 0
+-1991 2126 0
+-1986 2126 0
+-1981 2126 0
+-1976 2126 0
+-1971 2126 0
+-1966 2126 0
+-1961 2126 0
+-1956 2126 0
+-1951 2126 0
+-1946 2126 0
+-1945 2126 0
+-1937 2126 0
+-1929 2126 0
+-1921 2126 0
+-1913 2126 0
+-1905 2126 0
+-1897 2126 0
+-1889 2126 0
+-1881 2126 0
+-1873 2126 0
+-1865 2126 0
+-1857 2126 0
+-1846 2126 0
+-1838 2126 0
+-1830 2126 0
+-1822 2126 0
+-1814 2126 0
+-1806 2126 0
+-1795 2126 0
+-1787 2126 0
+-1779 2126 0
+-1771 2126 0
+-1763 2126 0
+-1755 2126 0
+-1744 2126 0
+-1736 2126 0
+-1728 2126 0
+-1720 2126 0
+-1712 2126 0
+-1704 2126 0
+-1693 2126 0
+-1685 2126 0
+-1674 2126 0
+-1663 2126 0
+-1652 2126 0
+-1641 2126 0
+-1621 2126 0
+-1613 2126 0
+-1605 2126 0
+-1597 2126 0
+-1589 2126 0
+-1581 2126 0
+-1573 2126 0
+-1565 2126 0
+-1557 2126 0
+-1549 2126 0
+-1541 2126 0
+-1533 2126 0
+-1522 2126 0
+-1514 2126 0
+-1506 2126 0
+-1498 2126 0
+-1490 2126 0
+-1482 2126 0
+-1471 2126 0
+-1463 2126 0
+-1455 2126 0
+-1447 2126 0
+-1439 2126 0
+-1431 2126 0
+-1420 2126 0
+-1412 2126 0
+-1404 2126 0
+-1396 2126 0
+-1388 2126 0
+-1380 2126 0
+-1369 2126 0
+-1361 2126 0
+-1350 2126 0
+-1339 2126 0
+-1328 2126 0
+-1317 2126 0
+-1297 2126 0
+-1289 2126 0
+-1281 2126 0
+-1273 2126 0
+-1265 2126 0
+-1257 2126 0
+-1249 2126 0
+-1241 2126 0
+-1233 2126 0
+-1225 2126 0
+-1217 2126 0
+-1209 2126 0
+-1198 2126 0
+-1190 2126 0
+-1182 2126 0
+-1174 2126 0
+-1166 2126 0
+-1158 2126 0
+-1147 2126 0
+-1139 2126 0
+-1131 2126 0
+-1123 2126 0
+-1115 2126 0
+-1107 2126 0
+-1096 2126 0
+-1088 2126 0
+-1080 2126 0
+-1072 2126 0
+-1064 2126 0
+-1056 2126 0
+-1045 2126 0
+-1037 2126 0
+-1026 2126 0
+-1015 2126 0
+-1004 2126 0
+-993 2126 0
+-973 2126 0
+-965 2126 0
+-957 2126 0
+-949 2126 0
+-941 2126 0
+-933 2126 0
+-925 2126 0
+-917 2126 0
+-909 2126 0
+-901 2126 0
+-893 2126 0
+-885 2126 0
+-874 2126 0
+-866 2126 0
+-858 2126 0
+-850 2126 0
+-842 2126 0
+-834 2126 0
+-823 2126 0
+-815 2126 0
+-807 2126 0
+-799 2126 0
+-791 2126 0
+-783 2126 0
+-772 2126 0
+-764 2126 0
+-756 2126 0
+-748 2126 0
+-740 2126 0
+-732 2126 0
+-721 2126 0
+-713 2126 0
+-702 2126 0
+-691 2126 0
+-680 2126 0
+-669 2126 0
+-649 2126 0
+-641 2126 0
+-633 2126 0
+-625 2126 0
+-617 2126 0
+-609 2126 0
+-601 2126 0
+-593 2126 0
+-585 2126 0
+-577 2126 0
+-569 2126 0
+-561 2126 0
+-550 2126 0
+-542 2126 0
+-534 2126 0
+-526 2126 0
+-518 2126 0
+-510 2126 0
+-499 2126 0
+-491 2126 0
+-483 2126 0
+-475 2126 0
+-467 2126 0
+-459 2126 0
+-448 2126 0
+-440 2126 0
+-432 2126 0
+-424 2126 0
+-416 2126 0
+-408 2126 0
+-397 2126 0
+-389 2126 0
+-378 2126 0
+-367 2126 0
+-356 2126 0
+-345 2126 0
+345 356 2111 2106 2101 2096 2091 2086 2081 2076 2071 2066 2061 2056 2051 2046 2041 2036 2031 2026 2021 2016 2011 2006 2001 1996 1991 1986 1981 1976 1971 1966 1961 1956 1951 1946 1945 1937 1929 1921 1913 1905 1897 1889 1881 1873 1865 1857 1846 1838 1830 1822 1814 1806 1795 1787 1779 1771 1763 1755 1744 1736 1728 1720 1712 1704 1693 1685 1674 1663 1652 1641 1621 1613 1605 1597 1589 1581 1573 1565 1557 1549 1541 1533 1522 1514 1506 1498 1490 1482 1471 1463 1455 1447 1439 1431 1420 1412 1404 1396 1388 1380 1369 1361 1350 1339 1328 1317 1297 1289 1281 1273 1265 1257 1249 1241 1233 1225 1217 1209 1198 1190 1182 1174 1166 1158 1147 1139 1131 1123 1115 1107 1096 1088 1080 1072 1064 1056 1045 1037 1026 1015 1004 993 973 965 957 949 941 933 925 917 909 901 893 885 874 866 858 850 842 834 823 815 807 799 791 783 772 764 756 748 740 732 721 713 702 691 680 669 649 641 633 625 617 609 601 593 585 577 569 561 550 542 534 526 518 510 499 491 483 475 467 459 448 440 432 424 416 408 397 389 378 367 2116 2121 -2126 0
+2124 2127 2130 0
+2124 -2127 -2130 0
+-2124 2127 -2130 0
+-2124 -2127 2130 0
+2123 2128 2131 0
+2123 -2128 -2131 0
+-2123 2128 -2131 0
+-2123 -2128 2131 0
+2122 2129 2132 0
+2122 -2129 -2132 0
+-2122 2129 -2132 0
+-2122 -2129 2132 0
+2122 -2133 0
+2123 -2133 0
+2124 -2133 0
+2134 2135 -2138 0
+2134 -2135 2138 0
+-2134 2135 2138 0
+-2134 -2135 -2138 0
+2136 -2139 2141 0
+-2136 2139 2141 0
+2136 2139 -2141 0
+-2136 -2139 -2141 0
+2137 -2140 2142 0
+-2137 2140 2142 0
+2137 2140 -2142 0
+-2137 -2140 -2142 0
+1985 -2142 0
+1985 -2141 0
+1985 -2134 0
+-1985 2134 2141 2142 0
+2099 2127 2138 0
+2099 -2127 -2138 0
+-2099 2127 -2138 0
+-2099 -2127 2138 0
+2098 2128 2139 0
+2098 -2128 -2139 0
+-2098 2128 -2139 0
+-2098 -2128 2139 0
+2097 2129 2140 0
+2097 -2129 -2140 0
+-2097 2129 -2140 0
+-2097 -2129 2140 0
+2097 -2143 0
+2098 -2143 0
+2099 -2143 0
+2135 2144 -2145 0
+-2135 2144 2145 0
+2135 -2144 2145 0
+-2135 -2144 -2145 0
+2136 -2146 2148 0
+-2136 2146 2148 0
+2136 2146 -2148 0
+-2136 -2146 -2148 0
+2137 -2147 2149 0
+-2137 2147 2149 0
+2137 2147 -2149 0
+-2137 -2147 -2149 0
+1990 -2149 0
+1990 -2148 0
+1990 -2144 0
+-1990 2144 2148 2149 0
+2104 2127 2145 0
+2104 -2127 -2145 0
+-2104 2127 -2145 0
+-2104 -2127 2145 0
+2103 2128 2146 0
+2103 -2128 -2146 0
+-2103 2128 -2146 0
+-2103 -2128 2146 0
+2102 2129 2147 0
+2102 -2129 -2147 0
+-2102 2129 -2147 0
+-2102 -2129 2147 0
+2102 -2150 0
+2103 -2150 0
+2104 -2150 0
+2135 2151 -2152 0
+-2135 2151 2152 0
+2135 -2151 2152 0
+-2135 -2151 -2152 0
+2136 -2153 2155 0
+-2136 2153 2155 0
+2136 2153 -2155 0
+-2136 -2153 -2155 0
+2137 -2154 2156 0
+-2137 2154 2156 0
+2137 2154 -2156 0
+-2137 -2154 -2156 0
+1995 -2156 0
+1995 -2155 0
+1995 -2151 0
+-1995 2151 2155 2156 0
+2109 2127 2152 0
+2109 -2127 -2152 0
+-2109 2127 -2152 0
+-2109 -2127 2152 0
+2108 2128 2153 0
+2108 -2128 -2153 0
+-2108 2128 -2153 0
+-2108 -2128 2153 0
+2107 2129 2154 0
+2107 -2129 -2154 0
+-2107 2129 -2154 0
+-2107 -2129 2154 0
+2107 -2157 0
+2108 -2157 0
+2109 -2157 0
+2135 2158 -2159 0
+-2135 2158 2159 0
+2135 -2158 2159 0
+-2135 -2158 -2159 0
+2136 -2160 2162 0
+-2136 2160 2162 0
+2136 2160 -2162 0
+-2136 -2160 -2162 0
+2137 -2161 2163 0
+-2137 2161 2163 0
+2137 2161 -2163 0
+-2137 -2161 -2163 0
+2000 -2163 0
+2000 -2162 0
+2000 -2158 0
+-2000 2158 2162 2163 0
+2114 2127 2159 0
+2114 -2127 -2159 0
+-2114 2127 -2159 0
+-2114 -2127 2159 0
+2113 2128 2160 0
+2113 -2128 -2160 0
+-2113 2128 -2160 0
+-2113 -2128 2160 0
+2112 2129 2161 0
+2112 -2129 -2161 0
+-2112 2129 -2161 0
+-2112 -2129 2161 0
+2112 -2164 0
+2113 -2164 0
+2114 -2164 0
+2135 2165 -2166 0
+-2135 2165 2166 0
+2135 -2165 2166 0
+-2135 -2165 -2166 0
+2136 -2167 2169 0
+-2136 2167 2169 0
+2136 2167 -2169 0
+-2136 -2167 -2169 0
+2137 -2168 2170 0
+-2137 2168 2170 0
+2137 2168 -2170 0
+-2137 -2168 -2170 0
+2005 -2170 0
+2005 -2169 0
+2005 -2165 0
+-2005 2165 2169 2170 0
+2119 2127 2166 0
+2119 -2127 -2166 0
+-2119 2127 -2166 0
+-2119 -2127 2166 0
+2118 2128 2167 0
+2118 -2128 -2167 0
+-2118 2128 -2167 0
+-2118 -2128 2167 0
+2117 2129 2168 0
+2117 -2129 -2168 0
+-2117 2129 -2168 0
+-2117 -2129 2168 0
+2117 -2171 0
+2118 -2171 0
+2119 -2171 0
+-2130 2135 2172 0
+2130 -2135 2172 0
+2130 2135 -2172 0
+-2130 -2135 -2172 0
+-2131 2136 2173 0
+2131 -2136 2173 0
+2131 2136 -2173 0
+-2131 -2136 -2173 0
+-2132 2137 2174 0
+2132 -2137 2174 0
+2132 2137 -2174 0
+-2132 -2137 -2174 0
+1980 -2174 0
+1980 -2173 0
+1980 -2172 0
+-1980 2172 2173 2174 0
+1974 2130 2135 0
+1974 -2130 -2135 0
+-1974 -2130 2135 0
+-1974 2130 -2135 0
+1973 2131 2136 0
+1973 -2131 -2136 0
+-1973 -2131 2136 0
+-1973 2131 -2136 0
+1972 2132 2137 0
+1972 -2132 -2137 0
+-1972 -2132 2137 0
+-1972 2132 -2137 0
+1972 -2175 0
+1973 -2175 0
+1974 -2175 0
+-2138 2176 2177 0
+2138 2176 -2177 0
+2138 -2176 2177 0
+-2138 -2176 -2177 0
+-2139 2178 2180 0
+2139 -2178 2180 0
+2139 2178 -2180 0
+-2139 -2178 -2180 0
+-2140 2179 2181 0
+2140 -2179 2181 0
+2140 2179 -2181 0
+-2140 -2179 -2181 0
+2015 -2181 0
+2015 -2180 0
+2015 -2176 0
+-2015 2176 2180 2181 0
+1949 2135 2138 0
+1949 -2135 -2138 0
+-1949 2135 -2138 0
+-1949 -2135 2138 0
+1948 2136 2139 0
+1948 -2136 -2139 0
+-1948 2136 -2139 0
+-1948 -2136 2139 0
+1947 2137 2140 0
+1947 -2137 -2140 0
+-1947 2137 -2140 0
+-1947 -2137 2140 0
+1947 -2182 0
+1948 -2182 0
+1949 -2182 0
+-2145 2177 2183 0
+2145 -2177 2183 0
+2145 2177 -2183 0
+-2145 -2177 -2183 0
+-2146 2178 2184 0
+2146 -2178 2184 0
+2146 2178 -2184 0
+-2146 -2178 -2184 0
+-2147 2179 2185 0
+2147 -2179 2185 0
+2147 2179 -2185 0
+-2147 -2179 -2185 0
+2020 -2185 0
+2020 -2184 0
+2020 -2183 0
+-2020 2183 2184 2185 0
+1954 2135 2145 0
+1954 -2135 -2145 0
+-1954 2135 -2145 0
+-1954 -2135 2145 0
+1953 2136 2146 0
+1953 -2136 -2146 0
+-1953 2136 -2146 0
+-1953 -2136 2146 0
+1952 2137 2147 0
+1952 -2137 -2147 0
+-1952 2137 -2147 0
+-1952 -2137 2147 0
+1952 -2186 0
+1953 -2186 0
+1954 -2186 0
+-2152 2177 2187 0
+2152 -2177 2187 0
+2152 2177 -2187 0
+-2152 -2177 -2187 0
+-2153 2178 2188 0
+2153 -2178 2188 0
+2153 2178 -2188 0
+-2153 -2178 -2188 0
+-2154 2179 2189 0
+2154 -2179 2189 0
+2154 2179 -2189 0
+-2154 -2179 -2189 0
+2025 -2189 0
+2025 -2188 0
+2025 -2187 0
+-2025 2187 2188 2189 0
+1959 2135 2152 0
+1959 -2135 -2152 0
+-1959 2135 -2152 0
+-1959 -2135 2152 0
+1958 2136 2153 0
+1958 -2136 -2153 0
+-1958 2136 -2153 0
+-1958 -2136 2153 0
+1957 2137 2154 0
+1957 -2137 -2154 0
+-1957 2137 -2154 0
+-1957 -2137 2154 0
+1957 -2190 0
+1958 -2190 0
+1959 -2190 0
+-2159 2177 2191 0
+2159 -2177 2191 0
+2159 2177 -2191 0
+-2159 -2177 -2191 0
+-2160 2178 2192 0
+2160 -2178 2192 0
+2160 2178 -2192 0
+-2160 -2178 -2192 0
+-2161 2179 2193 0
+2161 -2179 2193 0
+2161 2179 -2193 0
+-2161 -2179 -2193 0
+2030 -2193 0
+2030 -2192 0
+2030 -2191 0
+-2030 2191 2192 2193 0
+1964 2135 2159 0
+1964 -2135 -2159 0
+-1964 2135 -2159 0
+-1964 -2135 2159 0
+1963 2136 2160 0
+1963 -2136 -2160 0
+-1963 2136 -2160 0
+-1963 -2136 2160 0
+1962 2137 2161 0
+1962 -2137 -2161 0
+-1962 2137 -2161 0
+-1962 -2137 2161 0
+1962 -2194 0
+1963 -2194 0
+1964 -2194 0
+-2166 2177 2195 0
+2166 -2177 2195 0
+2166 2177 -2195 0
+-2166 -2177 -2195 0
+-2167 2178 2196 0
+2167 -2178 2196 0
+2167 2178 -2196 0
+-2167 -2178 -2196 0
+-2168 2179 2197 0
+2168 -2179 2197 0
+2168 2179 -2197 0
+-2168 -2179 -2197 0
+2035 -2197 0
+2035 -2196 0
+2035 -2195 0
+-2035 2195 2196 2197 0
+1969 2135 2166 0
+1969 -2135 -2166 0
+-1969 2135 -2166 0
+-1969 -2135 2166 0
+1968 2136 2167 0
+1968 -2136 -2167 0
+-1968 2136 -2167 0
+-1968 -2136 2167 0
+1967 2137 2168 0
+1967 -2137 -2168 0
+-1967 2137 -2168 0
+-1967 -2137 2168 0
+1967 -2198 0
+1968 -2198 0
+1969 -2198 0
+-2130 2177 2199 0
+2130 -2177 2199 0
+2130 2177 -2199 0
+-2130 -2177 -2199 0
+-2131 2178 2200 0
+2131 -2178 2200 0
+2131 2178 -2200 0
+-2131 -2178 -2200 0
+-2132 2179 2201 0
+2132 -2179 2201 0
+2132 2179 -2201 0
+-2132 -2179 -2201 0
+2010 -2201 0
+2010 -2200 0
+2010 -2199 0
+-2010 2199 2200 2201 0
+2004 2130 2177 0
+2004 -2130 -2177 0
+-2004 -2130 2177 0
+-2004 2130 -2177 0
+2003 2131 2178 0
+2003 -2131 -2178 0
+-2003 -2131 2178 0
+-2003 2131 -2178 0
+2002 2132 2179 0
+2002 -2132 -2179 0
+-2002 -2132 2179 0
+-2002 2132 -2179 0
+2002 -2202 0
+2003 -2202 0
+2004 -2202 0
+-2138 2203 2204 0
+2138 2203 -2204 0
+2138 -2203 2204 0
+-2138 -2203 -2204 0
+-2139 2205 2207 0
+2139 -2205 2207 0
+2139 2205 -2207 0
+-2139 -2205 -2207 0
+-2140 2206 2208 0
+2140 -2206 2208 0
+2140 2206 -2208 0
+-2140 -2206 -2208 0
+2045 -2208 0
+2045 -2207 0
+2045 -2203 0
+-2045 2203 2207 2208 0
+1979 2138 2177 0
+1979 -2138 -2177 0
+-1979 -2138 2177 0
+-1979 2138 -2177 0
+1978 2139 2178 0
+1978 -2139 -2178 0
+-1978 -2139 2178 0
+-1978 2139 -2178 0
+1977 2140 2179 0
+1977 -2140 -2179 0
+-1977 -2140 2179 0
+-1977 2140 -2179 0
+1977 -2209 0
+1978 -2209 0
+1979 -2209 0
+-2145 2204 2210 0
+2145 -2204 2210 0
+2145 2204 -2210 0
+-2145 -2204 -2210 0
+-2146 2205 2211 0
+2146 -2205 2211 0
+2146 2205 -2211 0
+-2146 -2205 -2211 0
+-2147 2206 2212 0
+2147 -2206 2212 0
+2147 2206 -2212 0
+-2147 -2206 -2212 0
+2050 -2212 0
+2050 -2211 0
+2050 -2210 0
+-2050 2210 2211 2212 0
+1984 2145 2177 0
+1984 -2145 -2177 0
+-1984 -2145 2177 0
+-1984 2145 -2177 0
+1983 2146 2178 0
+1983 -2146 -2178 0
+-1983 -2146 2178 0
+-1983 2146 -2178 0
+1982 2147 2179 0
+1982 -2147 -2179 0
+-1982 -2147 2179 0
+-1982 2147 -2179 0
+1982 -2213 0
+1983 -2213 0
+1984 -2213 0
+-2152 2204 2214 0
+2152 -2204 2214 0
+2152 2204 -2214 0
+-2152 -2204 -2214 0
+-2153 2205 2215 0
+2153 -2205 2215 0
+2153 2205 -2215 0
+-2153 -2205 -2215 0
+-2154 2206 2216 0
+2154 -2206 2216 0
+2154 2206 -2216 0
+-2154 -2206 -2216 0
+2055 -2216 0
+2055 -2215 0
+2055 -2214 0
+-2055 2214 2215 2216 0
+1989 2152 2177 0
+1989 -2152 -2177 0
+-1989 -2152 2177 0
+-1989 2152 -2177 0
+1988 2153 2178 0
+1988 -2153 -2178 0
+-1988 -2153 2178 0
+-1988 2153 -2178 0
+1987 2154 2179 0
+1987 -2154 -2179 0
+-1987 -2154 2179 0
+-1987 2154 -2179 0
+1987 -2217 0
+1988 -2217 0
+1989 -2217 0
+-2159 2204 2218 0
+2159 -2204 2218 0
+2159 2204 -2218 0
+-2159 -2204 -2218 0
+-2160 2205 2219 0
+2160 -2205 2219 0
+2160 2205 -2219 0
+-2160 -2205 -2219 0
+-2161 2206 2220 0
+2161 -2206 2220 0
+2161 2206 -2220 0
+-2161 -2206 -2220 0
+2060 -2220 0
+2060 -2219 0
+2060 -2218 0
+-2060 2218 2219 2220 0
+1994 2159 2177 0
+1994 -2159 -2177 0
+-1994 -2159 2177 0
+-1994 2159 -2177 0
+1993 2160 2178 0
+1993 -2160 -2178 0
+-1993 -2160 2178 0
+-1993 2160 -2178 0
+1992 2161 2179 0
+1992 -2161 -2179 0
+-1992 -2161 2179 0
+-1992 2161 -2179 0
+1992 -2221 0
+1993 -2221 0
+1994 -2221 0
+-2166 2204 2222 0
+2166 -2204 2222 0
+2166 2204 -2222 0
+-2166 -2204 -2222 0
+-2167 2205 2223 0
+2167 -2205 2223 0
+2167 2205 -2223 0
+-2167 -2205 -2223 0
+-2168 2206 2224 0
+2168 -2206 2224 0
+2168 2206 -2224 0
+-2168 -2206 -2224 0
+2065 -2224 0
+2065 -2223 0
+2065 -2222 0
+-2065 2222 2223 2224 0
+1999 2166 2177 0
+1999 -2166 -2177 0
+-1999 -2166 2177 0
+-1999 2166 -2177 0
+1998 2167 2178 0
+1998 -2167 -2178 0
+-1998 -2167 2178 0
+-1998 2167 -2178 0
+1997 2168 2179 0
+1997 -2168 -2179 0
+-1997 -2168 2179 0
+-1997 2168 -2179 0
+1997 -2225 0
+1998 -2225 0
+1999 -2225 0
+-2130 2204 2226 0
+2130 -2204 2226 0
+2130 2204 -2226 0
+-2130 -2204 -2226 0
+-2131 2205 2227 0
+2131 -2205 2227 0
+2131 2205 -2227 0
+-2131 -2205 -2227 0
+-2132 2206 2228 0
+2132 -2206 2228 0
+2132 2206 -2228 0
+-2132 -2206 -2228 0
+2040 -2228 0
+2040 -2227 0
+2040 -2226 0
+-2040 2226 2227 2228 0
+2034 2130 2204 0
+2034 -2130 -2204 0
+-2034 -2130 2204 0
+-2034 2130 -2204 0
+2033 2131 2205 0
+2033 -2131 -2205 0
+-2033 -2131 2205 0
+-2033 2131 -2205 0
+2032 2132 2206 0
+2032 -2132 -2206 0
+-2032 -2132 2206 0
+-2032 2132 -2206 0
+2032 -2229 0
+2033 -2229 0
+2034 -2229 0
+-2138 2230 2231 0
+2138 2230 -2231 0
+2138 -2230 2231 0
+-2138 -2230 -2231 0
+-2139 2232 2234 0
+2139 -2232 2234 0
+2139 2232 -2234 0
+-2139 -2232 -2234 0
+-2140 2233 2235 0
+2140 -2233 2235 0
+2140 2233 -2235 0
+-2140 -2233 -2235 0
+2075 -2235 0
+2075 -2234 0
+2075 -2230 0
+-2075 2230 2234 2235 0
+2009 2138 2204 0
+2009 -2138 -2204 0
+-2009 -2138 2204 0
+-2009 2138 -2204 0
+2008 2139 2205 0
+2008 -2139 -2205 0
+-2008 -2139 2205 0
+-2008 2139 -2205 0
+2007 2140 2206 0
+2007 -2140 -2206 0
+-2007 -2140 2206 0
+-2007 2140 -2206 0
+2007 -2236 0
+2008 -2236 0
+2009 -2236 0
+-2145 2231 2237 0
+2145 -2231 2237 0
+2145 2231 -2237 0
+-2145 -2231 -2237 0
+-2146 2232 2238 0
+2146 -2232 2238 0
+2146 2232 -2238 0
+-2146 -2232 -2238 0
+-2147 2233 2239 0
+2147 -2233 2239 0
+2147 2233 -2239 0
+-2147 -2233 -2239 0
+2080 -2239 0
+2080 -2238 0
+2080 -2237 0
+-2080 2237 2238 2239 0
+2014 2145 2204 0
+2014 -2145 -2204 0
+-2014 -2145 2204 0
+-2014 2145 -2204 0
+2013 2146 2205 0
+2013 -2146 -2205 0
+-2013 -2146 2205 0
+-2013 2146 -2205 0
+2012 2147 2206 0
+2012 -2147 -2206 0
+-2012 -2147 2206 0
+-2012 2147 -2206 0
+2012 -2240 0
+2013 -2240 0
+2014 -2240 0
+-2152 2231 2241 0
+2152 -2231 2241 0
+2152 2231 -2241 0
+-2152 -2231 -2241 0
+-2153 2232 2242 0
+2153 -2232 2242 0
+2153 2232 -2242 0
+-2153 -2232 -2242 0
+-2154 2233 2243 0
+2154 -2233 2243 0
+2154 2233 -2243 0
+-2154 -2233 -2243 0
+2085 -2243 0
+2085 -2242 0
+2085 -2241 0
+-2085 2241 2242 2243 0
+2019 2152 2204 0
+2019 -2152 -2204 0
+-2019 -2152 2204 0
+-2019 2152 -2204 0
+2018 2153 2205 0
+2018 -2153 -2205 0
+-2018 -2153 2205 0
+-2018 2153 -2205 0
+2017 2154 2206 0
+2017 -2154 -2206 0
+-2017 -2154 2206 0
+-2017 2154 -2206 0
+2017 -2244 0
+2018 -2244 0
+2019 -2244 0
+-2159 2231 2245 0
+2159 -2231 2245 0
+2159 2231 -2245 0
+-2159 -2231 -2245 0
+-2160 2232 2246 0
+2160 -2232 2246 0
+2160 2232 -2246 0
+-2160 -2232 -2246 0
+-2161 2233 2247 0
+2161 -2233 2247 0
+2161 2233 -2247 0
+-2161 -2233 -2247 0
+2090 -2247 0
+2090 -2246 0
+2090 -2245 0
+-2090 2245 2246 2247 0
+2024 2159 2204 0
+2024 -2159 -2204 0
+-2024 -2159 2204 0
+-2024 2159 -2204 0
+2023 2160 2205 0
+2023 -2160 -2205 0
+-2023 -2160 2205 0
+-2023 2160 -2205 0
+2022 2161 2206 0
+2022 -2161 -2206 0
+-2022 -2161 2206 0
+-2022 2161 -2206 0
+2022 -2248 0
+2023 -2248 0
+2024 -2248 0
+-2166 2231 2249 0
+2166 -2231 2249 0
+2166 2231 -2249 0
+-2166 -2231 -2249 0
+-2167 2232 2250 0
+2167 -2232 2250 0
+2167 2232 -2250 0
+-2167 -2232 -2250 0
+-2168 2233 2251 0
+2168 -2233 2251 0
+2168 2233 -2251 0
+-2168 -2233 -2251 0
+2095 -2251 0
+2095 -2250 0
+2095 -2249 0
+-2095 2249 2250 2251 0
+2029 2166 2204 0
+2029 -2166 -2204 0
+-2029 -2166 2204 0
+-2029 2166 -2204 0
+2028 2167 2205 0
+2028 -2167 -2205 0
+-2028 -2167 2205 0
+-2028 2167 -2205 0
+2027 2168 2206 0
+2027 -2168 -2206 0
+-2027 -2168 2206 0
+-2027 2168 -2206 0
+2027 -2252 0
+2028 -2252 0
+2029 -2252 0
+-2130 2231 2253 0
+2130 -2231 2253 0
+2130 2231 -2253 0
+-2130 -2231 -2253 0
+-2131 2232 2254 0
+2131 -2232 2254 0
+2131 2232 -2254 0
+-2131 -2232 -2254 0
+-2132 2233 2255 0
+2132 -2233 2255 0
+2132 2233 -2255 0
+-2132 -2233 -2255 0
+2070 -2255 0
+2070 -2254 0
+2070 -2253 0
+-2070 2253 2254 2255 0
+2064 2130 2231 0
+2064 -2130 -2231 0
+-2064 -2130 2231 0
+-2064 2130 -2231 0
+2063 2131 2232 0
+2063 -2131 -2232 0
+-2063 -2131 2232 0
+-2063 2131 -2232 0
+2062 2132 2233 0
+2062 -2132 -2233 0
+-2062 -2132 2233 0
+-2062 2132 -2233 0
+2062 -2256 0
+2063 -2256 0
+2064 -2256 0
+-2138 2257 2258 0
+2138 2257 -2258 0
+2138 -2257 2258 0
+-2138 -2257 -2258 0
+-2139 2259 2261 0
+2139 -2259 2261 0
+2139 2259 -2261 0
+-2139 -2259 -2261 0
+-2140 2260 2262 0
+2140 -2260 2262 0
+2140 2260 -2262 0
+-2140 -2260 -2262 0
+2105 -2262 0
+2105 -2261 0
+2105 -2257 0
+-2105 2257 2261 2262 0
+2039 2138 2231 0
+2039 -2138 -2231 0
+-2039 -2138 2231 0
+-2039 2138 -2231 0
+2038 2139 2232 0
+2038 -2139 -2232 0
+-2038 -2139 2232 0
+-2038 2139 -2232 0
+2037 2140 2233 0
+2037 -2140 -2233 0
+-2037 -2140 2233 0
+-2037 2140 -2233 0
+2037 -2263 0
+2038 -2263 0
+2039 -2263 0
+-2145 2258 2264 0
+2145 -2258 2264 0
+2145 2258 -2264 0
+-2145 -2258 -2264 0
+-2146 2259 2265 0
+2146 -2259 2265 0
+2146 2259 -2265 0
+-2146 -2259 -2265 0
+-2147 2260 2266 0
+2147 -2260 2266 0
+2147 2260 -2266 0
+-2147 -2260 -2266 0
+2110 -2266 0
+2110 -2265 0
+2110 -2264 0
+-2110 2264 2265 2266 0
+2044 2145 2231 0
+2044 -2145 -2231 0
+-2044 -2145 2231 0
+-2044 2145 -2231 0
+2043 2146 2232 0
+2043 -2146 -2232 0
+-2043 -2146 2232 0
+-2043 2146 -2232 0
+2042 2147 2233 0
+2042 -2147 -2233 0
+-2042 -2147 2233 0
+-2042 2147 -2233 0
+2042 -2267 0
+2043 -2267 0
+2044 -2267 0
+-2152 2258 2268 0
+2152 -2258 2268 0
+2152 2258 -2268 0
+-2152 -2258 -2268 0
+-2153 2259 2269 0
+2153 -2259 2269 0
+2153 2259 -2269 0
+-2153 -2259 -2269 0
+-2154 2260 2270 0
+2154 -2260 2270 0
+2154 2260 -2270 0
+-2154 -2260 -2270 0
+2115 -2270 0
+2115 -2269 0
+2115 -2268 0
+-2115 2268 2269 2270 0
+2049 2152 2231 0
+2049 -2152 -2231 0
+-2049 -2152 2231 0
+-2049 2152 -2231 0
+2048 2153 2232 0
+2048 -2153 -2232 0
+-2048 -2153 2232 0
+-2048 2153 -2232 0
+2047 2154 2233 0
+2047 -2154 -2233 0
+-2047 -2154 2233 0
+-2047 2154 -2233 0
+2047 -2271 0
+2048 -2271 0
+2049 -2271 0
+-2159 2258 2272 0
+2159 -2258 2272 0
+2159 2258 -2272 0
+-2159 -2258 -2272 0
+-2160 2259 2273 0
+2160 -2259 2273 0
+2160 2259 -2273 0
+-2160 -2259 -2273 0
+-2161 2260 2274 0
+2161 -2260 2274 0
+2161 2260 -2274 0
+-2161 -2260 -2274 0
+2120 -2274 0
+2120 -2273 0
+2120 -2272 0
+-2120 2272 2273 2274 0
+2054 2159 2231 0
+2054 -2159 -2231 0
+-2054 -2159 2231 0
+-2054 2159 -2231 0
+2053 2160 2232 0
+2053 -2160 -2232 0
+-2053 -2160 2232 0
+-2053 2160 -2232 0
+2052 2161 2233 0
+2052 -2161 -2233 0
+-2052 -2161 2233 0
+-2052 2161 -2233 0
+2052 -2275 0
+2053 -2275 0
+2054 -2275 0
+-2166 2258 2276 0
+2166 -2258 2276 0
+2166 2258 -2276 0
+-2166 -2258 -2276 0
+-2167 2259 2277 0
+2167 -2259 2277 0
+2167 2259 -2277 0
+-2167 -2259 -2277 0
+-2168 2260 2278 0
+2168 -2260 2278 0
+2168 2260 -2278 0
+-2168 -2260 -2278 0
+2125 -2278 0
+2125 -2277 0
+2125 -2276 0
+-2125 2276 2277 2278 0
+2059 2166 2231 0
+2059 -2166 -2231 0
+-2059 -2166 2231 0
+-2059 2166 -2231 0
+2058 2167 2232 0
+2058 -2167 -2232 0
+-2058 -2167 2232 0
+-2058 2167 -2232 0
+2057 2168 2233 0
+2057 -2168 -2233 0
+-2057 -2168 2233 0
+-2057 2168 -2233 0
+2057 -2279 0
+2058 -2279 0
+2059 -2279 0
+-2130 2258 2280 0
+2130 -2258 2280 0
+2130 2258 -2280 0
+-2130 -2258 -2280 0
+-2131 2259 2281 0
+2131 -2259 2281 0
+2131 2259 -2281 0
+-2131 -2259 -2281 0
+-2132 2260 2282 0
+2132 -2260 2282 0
+2132 2260 -2282 0
+-2132 -2260 -2282 0
+2100 -2282 0
+2100 -2281 0
+2100 -2280 0
+-2100 2280 2281 2282 0
+2094 2130 2258 0
+2094 -2130 -2258 0
+-2094 -2130 2258 0
+-2094 2130 -2258 0
+2093 2131 2259 0
+2093 -2131 -2259 0
+-2093 -2131 2259 0
+-2093 2131 -2259 0
+2092 2132 2260 0
+2092 -2132 -2260 0
+-2092 -2132 2260 0
+-2092 2132 -2260 0
+2092 -2283 0
+2093 -2283 0
+2094 -2283 0
+2127 -2138 2284 0
+-2127 2138 2284 0
+2127 2138 -2284 0
+-2127 -2138 -2284 0
+2128 -2139 2285 0
+-2128 2139 2285 0
+2128 2139 -2285 0
+-2128 -2139 -2285 0
+2129 -2140 2286 0
+-2129 2140 2286 0
+2129 2140 -2286 0
+-2129 -2140 -2286 0
+1955 -2286 0
+1955 -2285 0
+1955 -2284 0
+-1955 2284 2285 2286 0
+2069 2138 2258 0
+2069 -2138 -2258 0
+-2069 -2138 2258 0
+-2069 2138 -2258 0
+2068 2139 2259 0
+2068 -2139 -2259 0
+-2068 -2139 2259 0
+-2068 2139 -2259 0
+2067 2140 2260 0
+2067 -2140 -2260 0
+-2067 -2140 2260 0
+-2067 2140 -2260 0
+2067 -2287 0
+2068 -2287 0
+2069 -2287 0
+2127 -2145 2288 0
+-2127 2145 2288 0
+2127 2145 -2288 0
+-2127 -2145 -2288 0
+2128 -2146 2289 0
+-2128 2146 2289 0
+2128 2146 -2289 0
+-2128 -2146 -2289 0
+2129 -2147 2290 0
+-2129 2147 2290 0
+2129 2147 -2290 0
+-2129 -2147 -2290 0
+1960 -2290 0
+1960 -2289 0
+1960 -2288 0
+-1960 2288 2289 2290 0
+2074 2145 2258 0
+2074 -2145 -2258 0
+-2074 -2145 2258 0
+-2074 2145 -2258 0
+2073 2146 2259 0
+2073 -2146 -2259 0
+-2073 -2146 2259 0
+-2073 2146 -2259 0
+2072 2147 2260 0
+2072 -2147 -2260 0
+-2072 -2147 2260 0
+-2072 2147 -2260 0
+2072 -2291 0
+2073 -2291 0
+2074 -2291 0
+2127 -2152 2292 0
+-2127 2152 2292 0
+2127 2152 -2292 0
+-2127 -2152 -2292 0
+2128 -2153 2293 0
+-2128 2153 2293 0
+2128 2153 -2293 0
+-2128 -2153 -2293 0
+2129 -2154 2294 0
+-2129 2154 2294 0
+2129 2154 -2294 0
+-2129 -2154 -2294 0
+1965 -2294 0
+1965 -2293 0
+1965 -2292 0
+-1965 2292 2293 2294 0
+2079 2152 2258 0
+2079 -2152 -2258 0
+-2079 -2152 2258 0
+-2079 2152 -2258 0
+2078 2153 2259 0
+2078 -2153 -2259 0
+-2078 -2153 2259 0
+-2078 2153 -2259 0
+2077 2154 2260 0
+2077 -2154 -2260 0
+-2077 -2154 2260 0
+-2077 2154 -2260 0
+2077 -2295 0
+2078 -2295 0
+2079 -2295 0
+2127 -2159 2296 0
+-2127 2159 2296 0
+2127 2159 -2296 0
+-2127 -2159 -2296 0
+2128 -2160 2297 0
+-2128 2160 2297 0
+2128 2160 -2297 0
+-2128 -2160 -2297 0
+2129 -2161 2298 0
+-2129 2161 2298 0
+2129 2161 -2298 0
+-2129 -2161 -2298 0
+1970 -2298 0
+1970 -2297 0
+1970 -2296 0
+-1970 2296 2297 2298 0
+2084 2159 2258 0
+2084 -2159 -2258 0
+-2084 -2159 2258 0
+-2084 2159 -2258 0
+2083 2160 2259 0
+2083 -2160 -2259 0
+-2083 -2160 2259 0
+-2083 2160 -2259 0
+2082 2161 2260 0
+2082 -2161 -2260 0
+-2082 -2161 2260 0
+-2082 2161 -2260 0
+2082 -2299 0
+2083 -2299 0
+2084 -2299 0
+2127 -2166 2300 0
+-2127 2166 2300 0
+2127 2166 -2300 0
+-2127 -2166 -2300 0
+2128 -2167 2301 0
+-2128 2167 2301 0
+2128 2167 -2301 0
+-2128 -2167 -2301 0
+2129 -2168 2302 0
+-2129 2168 2302 0
+2129 2168 -2302 0
+-2129 -2168 -2302 0
+1975 -2302 0
+1975 -2301 0
+1975 -2300 0
+-1975 2300 2301 2302 0
+2089 2166 2258 0
+2089 -2166 -2258 0
+-2089 -2166 2258 0
+-2089 2166 -2258 0
+2088 2167 2259 0
+2088 -2167 -2259 0
+-2088 -2167 2259 0
+-2088 2167 -2259 0
+2087 2168 2260 0
+2087 -2168 -2260 0
+-2087 -2168 2260 0
+-2087 2168 -2260 0
+2087 -2303 0
+2088 -2303 0
+2089 -2303 0
+2127 -2130 2304 0
+-2127 2130 2304 0
+2127 2130 -2304 0
+-2127 -2130 -2304 0
+2128 -2131 2305 0
+-2128 2131 2305 0
+2128 2131 -2305 0
+-2128 -2131 -2305 0
+2129 -2132 2306 0
+-2129 2132 2306 0
+2129 2132 -2306 0
+-2129 -2132 -2306 0
+1950 -2306 0
+1950 -2305 0
+1950 -2304 0
+-1950 2304 2305 2306 0
+1950 2303 0
+1975 2299 0
+1970 2295 0
+1965 2291 0
+1960 2287 0
+1955 2283 0
+2100 2279 0
+2125 2275 0
+2120 2271 0
+2115 2267 0
+2110 2263 0
+2105 2256 0
+2070 2252 0
+2095 2248 0
+2090 2244 0
+2085 2240 0
+2080 2236 0
+2075 2229 0
+2040 2225 0
+2065 2221 0
+2060 2217 0
+2055 2213 0
+2050 2209 0
+2045 2202 0
+2010 2198 0
+2035 2194 0
+2030 2190 0
+2025 2186 0
+2020 2182 0
+2015 2175 0
+1980 2171 0
+2005 2164 0
+2000 2157 0
+1995 2150 0
+1990 2143 0
+1985 2133 0
+-2127 2130 0
+2127 -2130 0
+-2128 2131 0
+2128 -2131 0
+-2129 2132 0
+2129 -2132 0
+2166 -2258 0
+-2166 2258 0
+2167 -2259 0
+-2167 2259 0
+2168 -2260 0
+-2168 2260 0
+2159 -2231 0
+-2159 2231 0
+2160 -2232 0
+-2160 2232 0
+2161 -2233 0
+-2161 2233 0
+2152 -2204 0
+-2152 2204 0
+2153 -2205 0
+-2153 2205 0
+2154 -2206 0
+-2154 2206 0
+2145 -2177 0
+-2145 2177 0
+2146 -2178 0
+-2146 2178 0
+2147 -2179 0
+-2147 2179 0
+-2135 2138 0
+2135 -2138 0
+-2136 2139 0
+2136 -2139 0
+-2137 2140 0
+2137 -2140 0
+-1623 2135 0
+1623 -2135 0
+-1624 2136 0
+1624 -2136 0
+-1625 2137 0
+1625 -2137 0
+-1852 2127 0
+1852 -2127 0
+-1853 2128 0
+1853 -2128 0
+-1854 2129 0
+1854 -2129 0
+-1801 2258 0
+1801 -2258 0
+-1802 2259 0
+1802 -2259 0
+-1803 2260 0
+1803 -2260 0
+-1750 2231 0
+1750 -2231 0
+-1751 2232 0
+1751 -2232 0
+-1752 2233 0
+1752 -2233 0
+-1699 2204 0
+1699 -2204 0
+-1700 2205 0
+1700 -2205 0
+-1701 2206 0
+1701 -2206 0
+-1633 2177 0
+1633 -2177 0
+-1634 2178 0
+1634 -2178 0
+-1635 2179 0
+1635 -2179 0
+-1626 2130 0
+1626 -2130 0
+-1627 2131 0
+1627 -2131 0
+-1628 2132 0
+1628 -2132 0
+-1680 2166 0
+1680 -2166 0
+-1681 2167 0
+1681 -2167 0
+-1682 2168 0
+1682 -2168 0
+-1669 2159 0
+1669 -2159 0
+-1670 2160 0
+1670 -2160 0
+-1671 2161 0
+1671 -2161 0
+-1658 2152 0
+1658 -2152 0
+-1659 2153 0
+1659 -2153 0
+-1660 2154 0
+1660 -2154 0
+-1647 2145 0
+1647 -2145 0
+-1648 2146 0
+1648 -2146 0
+-1649 2147 0
+1649 -2147 0
+-1636 2138 0
+1636 -2138 0
+-1637 2139 0
+1637 -2139 0
+-1638 2140 0
+1638 -2140 0
+-1299 1633 0
+1299 -1633 0
+-1300 1634 0
+1300 -1634 0
+-1301 1635 0
+1301 -1635 0
+-1528 1623 0
+1528 -1623 0
+-1529 1624 0
+1529 -1624 0
+-1530 1625 0
+1530 -1625 0
+-1477 1852 0
+1477 -1852 0
+-1478 1853 0
+1478 -1853 0
+-1479 1854 0
+1479 -1854 0
+-1426 1801 0
+1426 -1801 0
+-1427 1802 0
+1427 -1802 0
+-1428 1803 0
+1428 -1803 0
+-1375 1750 0
+1375 -1750 0
+-1376 1751 0
+1376 -1751 0
+-1377 1752 0
+1377 -1752 0
+-1309 1699 0
+1309 -1699 0
+-1310 1700 0
+1310 -1700 0
+-1311 1701 0
+1311 -1701 0
+-1302 1626 0
+1302 -1626 0
+-1303 1627 0
+1303 -1627 0
+-1304 1628 0
+1304 -1628 0
+-1356 1680 0
+1356 -1680 0
+-1357 1681 0
+1357 -1681 0
+-1358 1682 0
+1358 -1682 0
+-1345 1669 0
+1345 -1669 0
+-1346 1670 0
+1346 -1670 0
+-1347 1671 0
+1347 -1671 0
+-1334 1658 0
+1334 -1658 0
+-1335 1659 0
+1335 -1659 0
+-1336 1660 0
+1336 -1660 0
+-1323 1647 0
+1323 -1647 0
+-1324 1648 0
+1324 -1648 0
+-1325 1649 0
+1325 -1649 0
+-1312 1636 0
+1312 -1636 0
+-1313 1637 0
+1313 -1637 0
+-1314 1638 0
+1314 -1638 0
+-975 1309 0
+975 -1309 0
+-976 1310 0
+976 -1310 0
+-977 1311 0
+977 -1311 0
+-1204 1299 0
+1204 -1299 0
+-1205 1300 0
+1205 -1300 0
+-1206 1301 0
+1206 -1301 0
+-1153 1528 0
+1153 -1528 0
+-1154 1529 0
+1154 -1529 0
+-1155 1530 0
+1155 -1530 0
+-1102 1477 0
+1102 -1477 0
+-1103 1478 0
+1103 -1478 0
+-1104 1479 0
+1104 -1479 0
+-1051 1426 0
+1051 -1426 0
+-1052 1427 0
+1052 -1427 0
+-1053 1428 0
+1053 -1428 0
+-985 1375 0
+985 -1375 0
+-986 1376 0
+986 -1376 0
+-987 1377 0
+987 -1377 0
+-978 1302 0
+978 -1302 0
+-979 1303 0
+979 -1303 0
+-980 1304 0
+980 -1304 0
+-1032 1356 0
+1032 -1356 0
+-1033 1357 0
+1033 -1357 0
+-1034 1358 0
+1034 -1358 0
+-1021 1345 0
+1021 -1345 0
+-1022 1346 0
+1022 -1346 0
+-1023 1347 0
+1023 -1347 0
+-1010 1334 0
+1010 -1334 0
+-1011 1335 0
+1011 -1335 0
+-1012 1336 0
+1012 -1336 0
+-999 1323 0
+999 -1323 0
+-1000 1324 0
+1000 -1324 0
+-1001 1325 0
+1001 -1325 0
+-988 1312 0
+988 -1312 0
+-989 1313 0
+989 -1313 0
+-990 1314 0
+990 -1314 0
+-651 985 0
+651 -985 0
+-652 986 0
+652 -986 0
+-653 987 0
+653 -987 0
+-880 975 0
+880 -975 0
+-881 976 0
+881 -976 0
+-882 977 0
+882 -977 0
+-829 1204 0
+829 -1204 0
+-830 1205 0
+830 -1205 0
+-831 1206 0
+831 -1206 0
+-778 1153 0
+778 -1153 0
+-779 1154 0
+779 -1154 0
+-780 1155 0
+780 -1155 0
+-727 1102 0
+727 -1102 0
+-728 1103 0
+728 -1103 0
+-729 1104 0
+729 -1104 0
+-661 1051 0
+661 -1051 0
+-662 1052 0
+662 -1052 0
+-663 1053 0
+663 -1053 0
+-654 978 0
+654 -978 0
+-655 979 0
+655 -979 0
+-656 980 0
+656 -980 0
+-708 1032 0
+708 -1032 0
+-709 1033 0
+709 -1033 0
+-710 1034 0
+710 -1034 0
+-697 1021 0
+697 -1021 0
+-698 1022 0
+698 -1022 0
+-699 1023 0
+699 -1023 0
+-686 1010 0
+686 -1010 0
+-687 1011 0
+687 -1011 0
+-688 1012 0
+688 -1012 0
+-675 999 0
+675 -999 0
+-676 1000 0
+676 -1000 0
+-677 1001 0
+677 -1001 0
+-664 988 0
+664 -988 0
+-665 989 0
+665 -989 0
+-666 990 0
+666 -990 0
+-327 661 0
+327 -661 0
+-328 662 0
+328 -662 0
+-329 663 0
+329 -663 0
+-556 651 0
+556 -651 0
+-557 652 0
+557 -652 0
+-558 653 0
+558 -653 0
+-505 880 0
+505 -880 0
+-506 881 0
+506 -881 0
+-507 882 0
+507 -882 0
+-454 829 0
+454 -829 0
+-455 830 0
+455 -830 0
+-456 831 0
+456 -831 0
+-403 778 0
+403 -778 0
+-404 779 0
+404 -779 0
+-405 780 0
+405 -780 0
+-337 727 0
+337 -727 0
+-338 728 0
+338 -728 0
+-339 729 0
+339 -729 0
+-330 654 0
+330 -654 0
+-331 655 0
+331 -655 0
+-332 656 0
+332 -656 0
+-384 708 0
+384 -708 0
+-385 709 0
+385 -709 0
+-386 710 0
+386 -710 0
+-373 697 0
+373 -697 0
+-374 698 0
+374 -698 0
+-375 699 0
+375 -699 0
+-362 686 0
+362 -686 0
+-363 687 0
+363 -687 0
+-364 688 0
+364 -688 0
+-351 675 0
+351 -675 0
+-352 676 0
+352 -676 0
+-353 677 0
+353 -677 0
+-340 664 0
+340 -664 0
+-341 665 0
+341 -665 0
+-342 666 0
+342 -666 0
+-2 337 0
+2 -337 0
+-3 338 0
+3 -338 0
+-4 339 0
+4 -339 0
+-231 327 0
+231 -327 0
+-232 328 0
+232 -328 0
+-233 329 0
+233 -329 0
+-180 556 0
+180 -556 0
+-181 557 0
+181 -557 0
+-182 558 0
+182 -558 0
+-129 505 0
+129 -505 0
+-130 506 0
+130 -506 0
+-131 507 0
+131 -507 0
+-78 454 0
+78 -454 0
+-79 455 0
+79 -455 0
+-80 456 0
+80 -456 0
+-12 403 0
+12 -403 0
+-13 404 0
+13 -404 0
+-14 405 0
+14 -405 0
+-5 330 0
+5 -330 0
+-6 331 0
+6 -331 0
+-7 332 0
+7 -332 0
+-59 384 0
+59 -384 0
+-60 385 0
+60 -385 0
+-61 386 0
+61 -386 0
+-48 373 0
+48 -373 0
+-49 374 0
+49 -374 0
+-50 375 0
+50 -375 0
+-37 362 0
+37 -362 0
+-38 363 0
+38 -363 0
+-39 364 0
+39 -364 0
+-26 351 0
+26 -351 0
+-27 352 0
+27 -352 0
+-28 353 0
+28 -353 0
+-15 340 0
+15 -340 0
+-16 341 0
+16 -341 0
+-17 342 0
+17 -342 0
+325 2126 0
diff --git a/unit-tests/hole4.cnf b/unit-tests/hole4.cnf
new file mode 100644
index 0000000..9dd148c
--- /dev/null
+++ b/unit-tests/hole4.cnf
@@ -0,0 +1,76 @@
+p cnf 20 75
+1 2 3 4 0
+5 6 7 8 0
+9 10 11 12 0
+13 14 15 16 0
+17 18 19 20 0
+-1 -2 0
+-1 -3 0
+-1 -4 0
+-2 -3 0
+-2 -4 0
+-3 -4 0
+-5 -6 0
+-5 -7 0
+-5 -8 0
+-6 -7 0
+-6 -8 0
+-7 -8 0
+-9 -10 0
+-9 -11 0
+-9 -12 0
+-10 -11 0
+-10 -12 0
+-11 -12 0
+-13 -14 0
+-13 -15 0
+-13 -16 0
+-14 -15 0
+-14 -16 0
+-15 -16 0
+-17 -18 0
+-17 -19 0
+-17 -20 0
+-18 -19 0
+-18 -20 0
+-19 -20 0
+-1 -5 0
+-1 -9 0
+-1 -13 0
+-1 -17 0
+-5 -9 0
+-5 -13 0
+-5 -17 0
+-9 -13 0
+-9 -17 0
+-13 -17 0
+-2 -6 0
+-2 -10 0
+-2 -14 0
+-2 -18 0
+-6 -10 0
+-6 -14 0
+-6 -18 0
+-10 -14 0
+-10 -18 0
+-14 -18 0
+-3 -7 0
+-3 -11 0
+-3 -15 0
+-3 -19 0
+-7 -11 0
+-7 -15 0
+-7 -19 0
+-11 -15 0
+-11 -19 0
+-15 -19 0
+-4 -8 0
+-4 -12 0
+-4 -16 0
+-4 -20 0
+-8 -12 0
+-8 -16 0
+-8 -20 0
+-12 -16 0
+-12 -20 0
+-16 -20 0
diff --git a/unit-tests/hole4.smt2 b/unit-tests/hole4.smt2
new file mode 100644
index 0000000..816bd39
--- /dev/null
+++ b/unit-tests/hole4.smt2
@@ -0,0 +1,99 @@
+(set-logic QF_UF)
+(declare-fun a1 () Bool)
+(declare-fun a2 () Bool)
+(declare-fun a3 () Bool)
+(declare-fun a4 () Bool)
+(declare-fun a5 () Bool)
+(declare-fun a6 () Bool)
+(declare-fun a7 () Bool)
+(declare-fun a8 () Bool)
+(declare-fun a9 () Bool)
+(declare-fun a10 () Bool)
+(declare-fun a11 () Bool)
+(declare-fun a12 () Bool)
+(declare-fun a13 () Bool)
+(declare-fun a14 () Bool)
+(declare-fun a15 () Bool)
+(declare-fun a16 () Bool)
+(declare-fun a17 () Bool)
+(declare-fun a18 () Bool)
+(declare-fun a19 () Bool)
+(declare-fun a20 () Bool)
+(assert (and
+(or a1 a2 a3 a4)
+(or a5 a6 a7 a8)
+(or a9 a10 a11 a12)
+(or a13 a14 a15 a16)
+(or a17 a18 a19 a20)
+(or (not a1) (not a2))
+(or (not a1) (not a3))
+(or (not a1) (not a4))
+(or (not a2) (not a3))
+(or (not a2) (not a4))
+(or (not a3) (not a4))
+(or (not a5) (not a6))
+(or (not a5) (not a7))
+(or (not a5) (not a8))
+(or (not a6) (not a7))
+(or (not a6) (not a8))
+(or (not a7) (not a8))
+(or (not a9) (not a10))
+(or (not a9) (not a11))
+(or (not a9) (not a12))
+(or (not a10) (not a11))
+(or (not a10) (not a12))
+(or (not a11) (not a12))
+(or (not a13) (not a14))
+(or (not a13) (not a15))
+(or (not a13) (not a16))
+(or (not a14) (not a15))
+(or (not a14) (not a16))
+(or (not a15) (not a16))
+(or (not a17) (not a18))
+(or (not a17) (not a19))
+(or (not a17) (not a20))
+(or (not a18) (not a19))
+(or (not a18) (not a20))
+(or (not a19) (not a20))
+(or (not a1) (not a5))
+(or (not a1) (not a9))
+(or (not a1) (not a13))
+(or (not a1) (not a17))
+(or (not a5) (not a9))
+(or (not a5) (not a13))
+(or (not a5) (not a17))
+(or (not a9) (not a13))
+(or (not a9) (not a17))
+(or (not a13) (not a17))
+(or (not a2) (not a6))
+(or (not a2) (not a10))
+(or (not a2) (not a14))
+(or (not a2) (not a18))
+(or (not a6) (not a10))
+(or (not a6) (not a14))
+(or (not a6) (not a18))
+(or (not a10) (not a14))
+(or (not a10) (not a18))
+(or (not a14) (not a18))
+(or (not a3) (not a7))
+(or (not a3) (not a11))
+(or (not a3) (not a15))
+(or (not a3) (not a19))
+(or (not a7) (not a11))
+(or (not a7) (not a15))
+(or (not a7) (not a19))
+(or (not a11) (not a15))
+(or (not a11) (not a19))
+(or (not a15) (not a19))
+(or (not a4) (not a8))
+(or (not a4) (not a12))
+(or (not a4) (not a16))
+(or (not a4) (not a20))
+(or (not a8) (not a12))
+(or (not a8) (not a16))
+(or (not a8) (not a20))
+(or (not a12) (not a16))
+(or (not a12) (not a20))
+(or (not a16) (not a20))))
+(check-sat)
+(exit)
diff --git a/unit-tests/let1.smt2 b/unit-tests/let1.smt2
new file mode 100644
index 0000000..38b426c
--- /dev/null
+++ b/unit-tests/let1.smt2
@@ -0,0 +1,5 @@
+(set-logic QF_UF)
+(declare-fun a () Bool)
+(assert (let ((?v_1 (not (not a))) (?v_2 (not a))) (and ?v_1 ?v_2)))
+(check-sat)
+(exit)
diff --git a/unit-tests/let2.smt2 b/unit-tests/let2.smt2
new file mode 100644
index 0000000..5de04b5
--- /dev/null
+++ b/unit-tests/let2.smt2
@@ -0,0 +1,6 @@
+(set-logic QF_UF)
+(declare-fun a () Bool)
+(declare-fun b () Bool)
+(assert (let ((?v_1 (and a b)) (?v_2 (not a))) (and ?v_1 ?v_2)))
+(check-sat)
+(exit)
diff --git a/unit-tests/lia1.smt2 b/unit-tests/lia1.smt2
new file mode 100644
index 0000000..694ec17
--- /dev/null
+++ b/unit-tests/lia1.smt2
@@ -0,0 +1,7 @@
+(set-logic QF_LIA)
+(declare-fun x () Int)
+(declare-fun y () Int)
+(declare-fun z () Int)
+(assert (not (=> (and (<= x 3) (or (<= y 7) (<= z 9))) (or (<= (+ x y) 10) (<= (+ x z) 12)))))
+(check-sat)
+(exit)
diff --git a/unit-tests/lia2.smt2 b/unit-tests/lia2.smt2
new file mode 100644
index 0000000..2e9d9a0
--- /dev/null
+++ b/unit-tests/lia2.smt2
@@ -0,0 +1,5 @@
+(set-logic QF_LIA)
+(declare-fun x () Int)
+(assert (not (=> (= (- x 3) 7) (>= x 10))))
+(check-sat)
+(exit)
diff --git a/unit-tests/lia3.smt2 b/unit-tests/lia3.smt2
new file mode 100644
index 0000000..c9af34f
--- /dev/null
+++ b/unit-tests/lia3.smt2
@@ -0,0 +1,6 @@
+(set-logic QF_LIA)
+(declare-fun x () Int)
+(declare-fun y () Int)
+(assert (not (=> (> x y) (<= (+ y 1) x))))
+(check-sat)
+(exit)
diff --git a/unit-tests/lia4.smt2 b/unit-tests/lia4.smt2
new file mode 100644
index 0000000..dde6e91
--- /dev/null
+++ b/unit-tests/lia4.smt2
@@ -0,0 +1,6 @@
+(set-logic QF_LIA)
+(declare-fun x () Int)
+(declare-fun y () Int)
+(assert (not (= (< x y) (<= x (- y 1)))))
+(check-sat)
+(exit)
diff --git a/unit-tests/lia5.smt2 b/unit-tests/lia5.smt2
new file mode 100644
index 0000000..541aa6c
--- /dev/null
+++ b/unit-tests/lia5.smt2
@@ -0,0 +1,6 @@
+(set-logic QF_LIA)
+(declare-fun x () Int)
+(declare-fun y () Int)
+(assert (and (or (and (<= (+ x y) (- 3)) (>= y 0)) (<= x (- 3))) (>= x 0)))
+(check-sat)
+(exit)
diff --git a/unit-tests/lia6.smt2 b/unit-tests/lia6.smt2
new file mode 100644
index 0000000..a50fde8
--- /dev/null
+++ b/unit-tests/lia6.smt2
@@ -0,0 +1,5 @@
+(set-logic QF_LIA)
+(declare-fun x () Int)
+(assert (not (=> (and (<= (- x 3) 7) (<= 7 (- x 3))) (>= x 10))))
+(check-sat)
+(exit)
diff --git a/unit-tests/lia7.smt2 b/unit-tests/lia7.smt2
new file mode 100644
index 0000000..df290d0
--- /dev/null
+++ b/unit-tests/lia7.smt2
@@ -0,0 +1,5 @@
+(set-logic QF_LIA)
+(declare-fun x () Int)
+(assert (not (=> (= (- x 3) 7) (<= 10 x))))
+(check-sat)
+(exit)
diff --git a/unit-tests/runverit.sh b/unit-tests/runverit.sh
new file mode 100755
index 0000000..0b950e9
--- /dev/null
+++ b/unit-tests/runverit.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+count=1
+i=$1
+file=$(echo "$i" | sed "s/.smt2/.vtlog/")
+
+veriT --proof-prune --proof-merge --proof-with-sharing --cnf-definitional --disable-ackermann --input=smtlib2 --proof=$file $i
diff --git a/unit-tests/runzchaff.sh b/unit-tests/runzchaff.sh
new file mode 100755
index 0000000..651ab19
--- /dev/null
+++ b/unit-tests/runzchaff.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+count=1
+i=$1
+file=$(echo "$i" | sed "s/.cnf/.zlog/")
+
+zchaff $i
+mv resolve_trace $file
diff --git a/unit-tests/sat1.cnf b/unit-tests/sat1.cnf
new file mode 100644
index 0000000..41c00e0
--- /dev/null
+++ b/unit-tests/sat1.cnf
@@ -0,0 +1,3 @@
+p cnf 1 2
+1 0
+-1 0
diff --git a/unit-tests/sat1.smt2 b/unit-tests/sat1.smt2
new file mode 100644
index 0000000..f0a67bc
--- /dev/null
+++ b/unit-tests/sat1.smt2
@@ -0,0 +1,5 @@
+(set-logic QF_UF)
+(declare-fun a () Bool)
+(assert (and a (not a)))
+(check-sat)
+(exit)
diff --git a/unit-tests/sat10.smt2 b/unit-tests/sat10.smt2
new file mode 100644
index 0000000..1bcba51
--- /dev/null
+++ b/unit-tests/sat10.smt2
@@ -0,0 +1,7 @@
+(set-logic QF_UF)
+(declare-fun a () Bool)
+(declare-fun b () Bool)
+(declare-fun c () Bool)
+(assert (distinct a b c))
+(check-sat)
+(exit)
diff --git a/unit-tests/sat11.smt2 b/unit-tests/sat11.smt2
new file mode 100644
index 0000000..8912ada
--- /dev/null
+++ b/unit-tests/sat11.smt2
@@ -0,0 +1,8 @@
+(set-logic QF_UF)
+(declare-sort U 0)
+(declare-fun a () U)
+(declare-fun b () U)
+(declare-fun c () U)
+(assert (and (not (distinct a b c)) (not (= a b)) (not (= a c)) (not (= c b))))
+(check-sat)
+(exit)
diff --git a/unit-tests/sat12.smt2 b/unit-tests/sat12.smt2
new file mode 100644
index 0000000..6762004
--- /dev/null
+++ b/unit-tests/sat12.smt2
@@ -0,0 +1,11 @@
+(set-logic QF_UF)
+(declare-fun a () Bool)
+(declare-fun b () Bool)
+(declare-fun c () Bool)
+(declare-fun d () Bool)
+(assert (and a b))
+(assert (or c d))
+(assert (= a a))
+(assert (not (or c (and a b d))))
+(check-sat)
+(exit)
diff --git a/unit-tests/sat13.smt2 b/unit-tests/sat13.smt2
new file mode 100644
index 0000000..63bcdb8
--- /dev/null
+++ b/unit-tests/sat13.smt2
@@ -0,0 +1,7 @@
+(set-logic QF_UF)
+(declare-sort U 0)
+(declare-fun a () U)
+(declare-fun b () U)
+(assert (and (not (distinct a b)) (not (= a b))))
+(check-sat)
+(exit)
diff --git a/unit-tests/sat2.cnf b/unit-tests/sat2.cnf
new file mode 100644
index 0000000..fa572f4
--- /dev/null
+++ b/unit-tests/sat2.cnf
@@ -0,0 +1,6 @@
+p cnf 3 5
+1 2 0
+1 3 0
+2 0
+2 3 0
+-2 0
diff --git a/unit-tests/sat2.smt2 b/unit-tests/sat2.smt2
new file mode 100644
index 0000000..738caa1
--- /dev/null
+++ b/unit-tests/sat2.smt2
@@ -0,0 +1,7 @@
+(set-logic QF_UF)
+(declare-fun a () Bool)
+(declare-fun b () Bool)
+(declare-fun c () Bool)
+(assert (and (or (and a b) (and b c)) (not b)))
+(check-sat)
+(exit)
diff --git a/unit-tests/sat3.cnf b/unit-tests/sat3.cnf
new file mode 100644
index 0000000..2606f19
--- /dev/null
+++ b/unit-tests/sat3.cnf
@@ -0,0 +1,3 @@
+p cnf 1 2
+1 1 0
+-1 0
diff --git a/unit-tests/sat3.smt2 b/unit-tests/sat3.smt2
new file mode 100644
index 0000000..5af31f5
--- /dev/null
+++ b/unit-tests/sat3.smt2
@@ -0,0 +1,5 @@
+(set-logic QF_UF)
+(declare-fun a () Bool)
+(assert (and (or a a) (not a)))
+(check-sat)
+(exit)
diff --git a/unit-tests/sat4.smt2 b/unit-tests/sat4.smt2
new file mode 100644
index 0000000..e366eb3
--- /dev/null
+++ b/unit-tests/sat4.smt2
@@ -0,0 +1,5 @@
+(set-logic QF_UF)
+(declare-fun a () Bool)
+(assert (not (or a (not a))))
+(check-sat)
+(exit)
diff --git a/unit-tests/sat5.cnf b/unit-tests/sat5.cnf
new file mode 100644
index 0000000..508791a
--- /dev/null
+++ b/unit-tests/sat5.cnf
@@ -0,0 +1,6 @@
+p cnf 3 5
+1 2 3 0
+-1 -2 -3 0
+-1 2 0
+-2 3 0
+-3 1 0
diff --git a/unit-tests/sat5.smt2 b/unit-tests/sat5.smt2
new file mode 100644
index 0000000..d46092c
--- /dev/null
+++ b/unit-tests/sat5.smt2
@@ -0,0 +1,7 @@
+(set-logic QF_UF)
+(declare-fun a () Bool)
+(declare-fun b () Bool)
+(declare-fun c () Bool)
+(assert (and (or a b c) (or (not a) (not b) (not c)) (or (not a) b) (or (not b) c) (or (not c) a)))
+(check-sat)
+(exit)
diff --git a/unit-tests/sat6.cnf b/unit-tests/sat6.cnf
new file mode 100644
index 0000000..0c89619
--- /dev/null
+++ b/unit-tests/sat6.cnf
@@ -0,0 +1,6 @@
+p cnf 4 5
+1 0
+2 0
+3 4 0
+-3 0
+-1 -2 -4 0
diff --git a/unit-tests/sat6.smt2 b/unit-tests/sat6.smt2
new file mode 100644
index 0000000..acef584
--- /dev/null
+++ b/unit-tests/sat6.smt2
@@ -0,0 +1,10 @@
+(set-logic QF_UF)
+(declare-fun a () Bool)
+(declare-fun b () Bool)
+(declare-fun c () Bool)
+(declare-fun d () Bool)
+(assert (and a b))
+(assert (or c d))
+(assert (not (or c (and a b d))))
+(check-sat)
+(exit)
diff --git a/unit-tests/sat7.cnf b/unit-tests/sat7.cnf
new file mode 100644
index 0000000..da8ffa2
--- /dev/null
+++ b/unit-tests/sat7.cnf
@@ -0,0 +1,6 @@
+p cnf 4 5
+1 0
+2 0
+3 0
+-1 -2 4 0
+-4 -3 0
diff --git a/unit-tests/sat7.smt2 b/unit-tests/sat7.smt2
new file mode 100644
index 0000000..952c85e
--- /dev/null
+++ b/unit-tests/sat7.smt2
@@ -0,0 +1,8 @@
+(set-logic QF_UF)
+(declare-fun a () Bool)
+(declare-fun b () Bool)
+(declare-fun c () Bool)
+(declare-fun d () Bool)
+(assert (and a b c (or (not a) (not b) d) (or (not d) (not c))))
+(check-sat)
+(exit)
diff --git a/unit-tests/sat8.smt2 b/unit-tests/sat8.smt2
new file mode 100644
index 0000000..03c73cc
--- /dev/null
+++ b/unit-tests/sat8.smt2
@@ -0,0 +1,5 @@
+(set-logic QF_UF)
+(declare-fun a () Bool)
+(assert (and (not (not a)) (not a)))
+(check-sat)
+(exit)
diff --git a/unit-tests/sat9.smt2 b/unit-tests/sat9.smt2
new file mode 100644
index 0000000..f44982e
--- /dev/null
+++ b/unit-tests/sat9.smt2
@@ -0,0 +1,8 @@
+(set-logic QF_UF)
+(declare-sort U 0)
+(declare-fun a () U)
+(declare-fun b () U)
+(declare-fun c () U)
+(assert (and (distinct a b c) (= a b)))
+(check-sat)
+(exit)
diff --git a/unit-tests/uf1.smt2 b/unit-tests/uf1.smt2
new file mode 100644
index 0000000..7aaea55
--- /dev/null
+++ b/unit-tests/uf1.smt2
@@ -0,0 +1,10 @@
+(set-logic QF_UF)
+(declare-sort U 0)
+(declare-fun a () U)
+(declare-fun b () U)
+(declare-fun c () U)
+(declare-fun f (U) U)
+(declare-fun p (U) Bool)
+(assert (and (= a c) (= b c) (or (not (= (f a) (f b))) (and (p a) (not (p b))))))
+(check-sat)
+(exit)
diff --git a/unit-tests/uf2.smt2 b/unit-tests/uf2.smt2
new file mode 100644
index 0000000..9b2e47b
--- /dev/null
+++ b/unit-tests/uf2.smt2
@@ -0,0 +1,9 @@
+(set-logic QF_UF)
+(declare-sort U 0)
+(declare-fun a () U)
+(declare-fun b () U)
+(declare-fun c () U)
+(declare-fun p (U) Bool)
+(assert (and (or (and (p a) (p b)) (and (p b) (p c))) (not (p b))))
+(check-sat)
+(exit)
diff --git a/unit-tests/uf3.smt2 b/unit-tests/uf3.smt2
new file mode 100644
index 0000000..3d514cd
--- /dev/null
+++ b/unit-tests/uf3.smt2
@@ -0,0 +1,9 @@
+(set-logic QF_UF)
+(declare-sort U 0)
+(declare-fun x () U)
+(declare-fun y () U)
+(declare-fun z () U)
+(declare-fun f (U) U)
+(assert (and (= x y) (= y z) (not (= (f x) (f z)))))
+(check-sat)
+(exit)
diff --git a/unit-tests/uf4.smt2 b/unit-tests/uf4.smt2
new file mode 100644
index 0000000..ec27526
--- /dev/null
+++ b/unit-tests/uf4.smt2
@@ -0,0 +1,9 @@
+(set-logic QF_UF)
+(declare-sort U 0)
+(declare-fun x () U)
+(declare-fun y () U)
+(declare-fun z () U)
+(declare-fun f (U) U)
+(assert (and (not (= (f x) (f y))) (= y z) (= (f x) (f (f z))) (= x y)))
+(check-sat)
+(exit)
diff --git a/unit-tests/uf5.smt2 b/unit-tests/uf5.smt2
new file mode 100644
index 0000000..c151654
--- /dev/null
+++ b/unit-tests/uf5.smt2
@@ -0,0 +1,11 @@
+(set-logic QF_UF)
+(declare-sort U 0)
+(declare-fun a () U)
+(declare-fun b () U)
+(declare-fun c () U)
+(declare-fun d () U)
+(declare-fun e () U)
+(declare-fun f () U)
+(assert (and (= a b) (= b c) (= c d) (= c e) (= e f) (not (= a f))))
+(check-sat)
+(exit)
diff --git a/unit-tests/uf6.smt2 b/unit-tests/uf6.smt2
new file mode 100644
index 0000000..8921422
--- /dev/null
+++ b/unit-tests/uf6.smt2
@@ -0,0 +1,10 @@
+(set-logic QF_UF)
+(declare-sort U 0)
+(declare-fun x () U)
+(declare-fun y () U)
+(declare-fun z () U)
+(declare-fun f (U U) U)
+(assert (= x y))
+(assert (not (= (f z x) (f z y))))
+(check-sat)
+(exit)
diff --git a/unit-tests/uf7.smt2 b/unit-tests/uf7.smt2
new file mode 100644
index 0000000..30efa7c
--- /dev/null
+++ b/unit-tests/uf7.smt2
@@ -0,0 +1,11 @@
+(set-logic QF_UF)
+(declare-sort U 0)
+(declare-fun x () U)
+(declare-fun y () U)
+(declare-fun z () U)
+(declare-fun P (U U) Bool)
+(assert (= x y))
+(assert (P z x))
+(assert (not (P z y)))
+(check-sat)
+(exit)
diff --git a/unit-tests/velev-sss-1.0-05.cnf b/unit-tests/velev-sss-1.0-05.cnf
new file mode 100644
index 0000000..cf8f4d1
--- /dev/null
+++ b/unit-tests/velev-sss-1.0-05.cnf
@@ -0,0 +1,12813 @@
+p cnf 1516 12812
+1516 0
+1 1516 0
+-1 -1516 0
+-1 2 1004 1223 0
+1 -1223 0
+1223 -1224 -1429 -1503 0
+-1223 1503 0
+-1503 1504 1511 1510 1509 1508 1507 1506 1512 1513 0
+1503 -1513 0
+13 101 -526 512 809 -913 714 -1514 1513 0
+-1513 1514 0
+-1505 1514 -1515 0
+-1505 -1514 1515 0
+-1220 1505 1514 0
+1220 1505 -1514 0
+30 31 -1338 -1249 1007 665 615 -1493 57 -1467 1515 0
+1493 -1515 0
+1467 -1515 0
+1338 -1515 0
+1249 -1515 0
+-1007 -1515 0
+-665 -1515 0
+-615 -1515 0
+-30 -1515 0
+-57 -1515 0
+-31 -1515 0
+-809 -1513 0
+526 -1513 0
+-512 -1513 0
+-101 -1513 0
+913 -1513 0
+-714 -1513 0
+-13 -1513 0
+1503 -1512 0
+-925 -1218 1505 1512 0
+-1505 -1512 0
+1218 -1512 0
+925 -1512 0
+1503 -1511 0
+-5 7 -653 -641 -825 529 741 -923 13 -837 1505 -65 1511 0
+-1505 -1511 0
+837 -1511 0
+653 -1511 0
+641 -1511 0
+825 -1511 0
+-529 -1511 0
+-741 -1511 0
+923 -1511 0
+-13 -1511 0
+-7 -1511 0
+5 -1511 0
+65 -1511 0
+1503 -1510 0
+7 13 -331 -318 -305 741 916 912 -747 1505 -36 -35 1510 0
+-1505 -1510 0
+747 -1510 0
+331 -1510 0
+318 -1510 0
+305 -1510 0
+-741 -1510 0
+-916 -1510 0
+-912 -1510 0
+-13 -1510 0
+-7 -1510 0
+36 -1510 0
+35 -1510 0
+1503 -1509 0
+12 -293 299 298 741 757 296 294 916 912 738 1505 1509 0
+-1505 -1509 0
+-738 -1509 0
+-299 -1509 0
+-298 -1509 0
+-741 -1509 0
+-757 -1509 0
+-296 -1509 0
+-294 -1509 0
+-916 -1509 0
+-912 -1509 0
+293 -1509 0
+-12 -1509 0
+1503 -1508 0
+7 -295 299 298 741 757 296 916 912 738 1505 1508 0
+-1505 -1508 0
+-738 -1508 0
+-299 -1508 0
+-298 -1508 0
+-741 -1508 0
+-757 -1508 0
+-296 -1508 0
+-916 -1508 0
+-912 -1508 0
+295 -1508 0
+-7 -1508 0
+1503 -1507 0
+7 21 299 298 741 757 916 912 738 -297 1505 1507 0
+-1505 -1507 0
+-738 -1507 0
+-299 -1507 0
+-298 -1507 0
+-741 -1507 0
+-757 -1507 0
+-916 -1507 0
+-912 -1507 0
+-21 -1507 0
+297 -1507 0
+-7 -1507 0
+1503 -1506 0
+-291 292 299 298 741 757 296 294 738 916 912 1505 1506 0
+-1505 -1506 0
+-738 -1506 0
+-299 -1506 0
+-298 -1506 0
+-741 -1506 0
+-757 -1506 0
+-296 -1506 0
+-294 -1506 0
+-292 -1506 0
+-916 -1506 0
+-912 -1506 0
+291 -1506 0
+1503 -1504 0
+291 292 299 298 741 757 296 294 738 1505 916 912 1504 0
+-1504 -1505 0
+1233 1240 -1441 1505 0
+1441 -1505 0
+-1233 -1505 0
+-1240 -1505 0
+-738 -1504 0
+-299 -1504 0
+-298 -1504 0
+-741 -1504 0
+-757 -1504 0
+-296 -1504 0
+-294 -1504 0
+-292 -1504 0
+-291 -1504 0
+-916 -1504 0
+-912 -1504 0
+-1223 1429 0
+-1429 1430 1464 1463 1462 1461 1460 1459 1458 1457 1456 1455 1454 1453 1452 1451 1450 1449 1448 1447 1490 1502 0
+1429 -1502 0
+845 847 866 864 863 862 861 856 855 853 851 849 1119 1431 1502 0
+-1431 -1502 0
+-1119 -1502 0
+-866 -1502 0
+-864 -1502 0
+-863 -1502 0
+-862 -1502 0
+-861 -1502 0
+-856 -1502 0
+-855 -1502 0
+-853 -1502 0
+-851 -1502 0
+-849 -1502 0
+-847 -1502 0
+-845 -1502 0
+1429 -1490 0
+13 101 -612 -606 -602 -526 512 809 714 -1491 1490 0
+-1490 1491 0
+-1431 1491 -1492 0
+-1431 -1491 1492 0
+-1195 1431 1491 0
+1195 1431 -1491 0
+30 31 -1441 1233 -1338 -1249 -1240 1007 665 615 -1493 57 -1467 1492 0
+-1492 1493 0
+-1493 1494 1499 1498 1497 1496 1495 1500 1501 0
+1493 -1501 0
+13 101 432 418 -107 -739 -1218 1501 0
+1218 -1501 0
+739 -1501 0
+-432 -1501 0
+-418 -1501 0
+107 -1501 0
+-101 -1501 0
+-13 -1501 0
+1493 -1500 0
+-5 7 -653 -641 -825 529 741 13 -837 -749 -65 1500 0
+749 -1500 0
+837 -1500 0
+653 -1500 0
+641 -1500 0
+825 -1500 0
+-529 -1500 0
+-741 -1500 0
+-13 -1500 0
+-7 -1500 0
+5 -1500 0
+65 -1500 0
+1493 -1499 0
+7 13 -318 -305 741 916 -331 -747 -36 -35 1499 0
+747 -1499 0
+331 -1499 0
+318 -1499 0
+305 -1499 0
+-741 -1499 0
+-916 -1499 0
+-13 -1499 0
+-7 -1499 0
+36 -1499 0
+35 -1499 0
+1493 -1498 0
+12 -293 298 741 757 296 294 916 299 738 1498 0
+-738 -1498 0
+-299 -1498 0
+-298 -1498 0
+-741 -1498 0
+-757 -1498 0
+-296 -1498 0
+-294 -1498 0
+-916 -1498 0
+293 -1498 0
+-12 -1498 0
+1493 -1497 0
+7 -295 298 741 757 296 916 299 738 1497 0
+-738 -1497 0
+-299 -1497 0
+-298 -1497 0
+-741 -1497 0
+-757 -1497 0
+-296 -1497 0
+-916 -1497 0
+295 -1497 0
+-7 -1497 0
+1493 -1496 0
+7 21 298 741 757 916 299 -297 738 1496 0
+-738 -1496 0
+-299 -1496 0
+-298 -1496 0
+-741 -1496 0
+-757 -1496 0
+-916 -1496 0
+-21 -1496 0
+297 -1496 0
+-7 -1496 0
+1493 -1495 0
+-291 292 298 741 757 296 294 299 916 738 1495 0
+-738 -1495 0
+-299 -1495 0
+-298 -1495 0
+-741 -1495 0
+-757 -1495 0
+-296 -1495 0
+-294 -1495 0
+-292 -1495 0
+-916 -1495 0
+291 -1495 0
+1493 -1494 0
+291 292 298 741 757 296 294 299 738 916 1494 0
+-738 -1494 0
+-299 -1494 0
+-298 -1494 0
+-741 -1494 0
+-757 -1494 0
+-296 -1494 0
+-294 -1494 0
+-292 -1494 0
+-291 -1494 0
+-916 -1494 0
+1467 -1492 0
+1441 -1492 0
+-1233 -1492 0
+1338 -1492 0
+1249 -1492 0
+1240 -1492 0
+-1007 -1492 0
+-665 -1492 0
+-615 -1492 0
+-30 -1492 0
+-57 -1492 0
+-31 -1492 0
+-809 -1490 0
+612 -1490 0
+606 -1490 0
+602 -1490 0
+526 -1490 0
+-512 -1490 0
+-101 -1490 0
+-714 -1490 0
+-13 -1490 0
+1429 -1464 0
+13 101 615 612 -606 -602 -526 512 665 -1465 1464 0
+-1464 1465 0
+-1431 1465 -1466 0
+-1431 -1465 1466 0
+-1169 1431 1465 0
+1169 1431 -1465 0
+30 31 -1338 1007 1489 57 -1467 1466 0
+-1466 -1489 0
+1233 -1240 -1441 1489 0
+1441 -1489 0
+-1233 -1489 0
+1240 -1489 0
+-1466 1467 0
+-1467 1468 1485 1484 1483 1482 1481 1480 1479 1478 1477 1476 1475 1474 1473 1472 1471 1470 1469 1486 1487 0
+1467 -1487 0
+30 31 129 1488 57 1007 1487 0
+-1487 -1488 0
+1233 1240 1441 1488 0
+-1441 -1488 0
+-1233 -1488 0
+-1240 -1488 0
+-1007 -1487 0
+-129 -1487 0
+-30 -1487 0
+-57 -1487 0
+-31 -1487 0
+1467 -1486 0
+30 31 1337 1313 1306 1292 1285 1278 1271 1264 1257 1240 1007 -129 461 457 453 100 90 85 141 350 452 1441 57 1233 1486 0
+-1441 -1486 0
+-1233 -1486 0
+-1337 -1486 0
+-1313 -1486 0
+-1306 -1486 0
+-1292 -1486 0
+-1285 -1486 0
+-1278 -1486 0
+-1271 -1486 0
+-1264 -1486 0
+-1257 -1486 0
+-1240 -1486 0
+-1007 -1486 0
+129 -1486 0
+-461 -1486 0
+-457 -1486 0
+-453 -1486 0
+-100 -1486 0
+-90 -1486 0
+-85 -1486 0
+-141 -1486 0
+-350 -1486 0
+-452 -1486 0
+-30 -1486 0
+-57 -1486 0
+-31 -1486 0
+1467 -1485 0
+13 101 -1333 1240 -129 432 418 -286 -119 -112 -107 1233 1441 1485 0
+-1441 -1485 0
+-1233 -1485 0
+1333 -1485 0
+-1240 -1485 0
+129 -1485 0
+-432 -1485 0
+-418 -1485 0
+286 -1485 0
+119 -1485 0
+112 -1485 0
+107 -1485 0
+-101 -1485 0
+-13 -1485 0
+1467 -1484 0
+13 101 -1329 1240 -129 366 286 352 -119 -112 -107 1233 1441 1484 0
+-1441 -1484 0
+-1233 -1484 0
+1329 -1484 0
+-1240 -1484 0
+129 -1484 0
+-366 -1484 0
+-286 -1484 0
+-352 -1484 0
+119 -1484 0
+112 -1484 0
+107 -1484 0
+-101 -1484 0
+-13 -1484 0
+1467 -1483 0
+12 85 1292 1285 1278 1271 1264 -1258 1240 -129 100 90 1233 141 350 -347 -203 1441 -156 1483 0
+-1441 -1483 0
+-1233 -1483 0
+-1292 -1483 0
+-1285 -1483 0
+-1278 -1483 0
+-1271 -1483 0
+-1264 -1483 0
+1258 -1483 0
+-1240 -1483 0
+129 -1483 0
+-100 -1483 0
+-90 -1483 0
+-85 -1483 0
+-141 -1483 0
+-350 -1483 0
+347 -1483 0
+203 -1483 0
+-12 -1483 0
+156 -1483 0
+1467 -1482 0
+7 -51 1292 1285 1278 1271 -1265 1240 -129 100 90 85 141 -137 1441 -52 1233 1482 0
+-1441 -1482 0
+-1233 -1482 0
+-1292 -1482 0
+-1285 -1482 0
+-1278 -1482 0
+-1271 -1482 0
+1265 -1482 0
+-1240 -1482 0
+129 -1482 0
+-100 -1482 0
+-90 -1482 0
+-85 -1482 0
+-141 -1482 0
+137 -1482 0
+-7 -1482 0
+52 -1482 0
+51 -1482 0
+1467 -1481 0
+7 21 1292 1285 1278 -1272 1240 -129 100 90 85 -29 1233 1441 -26 -27 1481 0
+-1441 -1481 0
+-1233 -1481 0
+-1292 -1481 0
+-1285 -1481 0
+-1278 -1481 0
+1272 -1481 0
+-1240 -1481 0
+129 -1481 0
+-100 -1481 0
+-90 -1481 0
+-85 -1481 0
+29 -1481 0
+-21 -1481 0
+-7 -1481 0
+26 -1481 0
+27 -1481 0
+1467 -1480 0
+7 13 1292 1285 -1279 1240 -129 -331 -318 -305 -144 1233 1441 -42 -36 -48 1480 0
+-1441 -1480 0
+-1233 -1480 0
+-1292 -1480 0
+-1285 -1480 0
+1279 -1480 0
+-1240 -1480 0
+129 -1480 0
+331 -1480 0
+318 -1480 0
+305 -1480 0
+144 -1480 0
+-13 -1480 0
+-7 -1480 0
+42 -1480 0
+36 -1480 0
+48 -1480 0
+1467 -1479 0
+-5 -6 1292 -1286 1240 -837 -653 -129 -641 -825 529 -705 13 7 1233 1441 -22 1479 0
+-1441 -1479 0
+-1233 -1479 0
+-1292 -1479 0
+1286 -1479 0
+-1240 -1479 0
+837 -1479 0
+653 -1479 0
+129 -1479 0
+641 -1479 0
+825 -1479 0
+-529 -1479 0
+705 -1479 0
+-13 -1479 0
+-7 -1479 0
+6 -1479 0
+5 -1479 0
+22 -1479 0
+1467 -1478 0
+7 51 1292 1285 1278 1271 -1265 1240 -129 100 90 85 141 -137 1233 1441 -52 1478 0
+-1441 -1478 0
+-1233 -1478 0
+-1292 -1478 0
+-1285 -1478 0
+-1278 -1478 0
+-1271 -1478 0
+1265 -1478 0
+-1240 -1478 0
+129 -1478 0
+-100 -1478 0
+-90 -1478 0
+-85 -1478 0
+-141 -1478 0
+137 -1478 0
+-51 -1478 0
+-7 -1478 0
+52 -1478 0
+1467 -1477 0
+7 21 1292 1285 1278 -1272 1240 -129 100 90 85 -29 27 1233 1441 -26 1477 0
+-1441 -1477 0
+-1233 -1477 0
+-1292 -1477 0
+-1285 -1477 0
+-1278 -1477 0
+1272 -1477 0
+-1240 -1477 0
+129 -1477 0
+-100 -1477 0
+-90 -1477 0
+-85 -1477 0
+29 -1477 0
+-27 -1477 0
+-21 -1477 0
+-7 -1477 0
+26 -1477 0
+1467 -1476 0
+7 13 1292 1285 -1279 1240 -129 -331 -318 -474 48 1233 1441 -42 -36 1476 0
+-1441 -1476 0
+-1233 -1476 0
+-1292 -1476 0
+-1285 -1476 0
+1279 -1476 0
+-1240 -1476 0
+129 -1476 0
+331 -1476 0
+318 -1476 0
+474 -1476 0
+-48 -1476 0
+-13 -1476 0
+-7 -1476 0
+42 -1476 0
+36 -1476 0
+1467 -1475 0
+-5 -6 1292 -1286 1240 -653 -129 -641 529 -699 22 13 7 1233 1441 1475 0
+-1441 -1475 0
+-1233 -1475 0
+-1292 -1475 0
+1286 -1475 0
+-1240 -1475 0
+653 -1475 0
+129 -1475 0
+641 -1475 0
+-529 -1475 0
+699 -1475 0
+-22 -1475 0
+-13 -1475 0
+-7 -1475 0
+6 -1475 0
+5 -1475 0
+1467 -1474 0
+12 85 1292 1285 1278 1271 1264 -1258 1240 -129 100 90 1233 141 350 -347 203 1441 -156 1474 0
+-1441 -1474 0
+-1233 -1474 0
+-1292 -1474 0
+-1285 -1474 0
+-1278 -1474 0
+-1271 -1474 0
+-1264 -1474 0
+1258 -1474 0
+-1240 -1474 0
+129 -1474 0
+-100 -1474 0
+-90 -1474 0
+-85 -1474 0
+-141 -1474 0
+-350 -1474 0
+347 -1474 0
+-203 -1474 0
+-12 -1474 0
+156 -1474 0
+1467 -1473 0
+85 90 1292 1285 1278 1271 1264 1257 -1251 1240 -129 100 1233 1441 141 350 452 -458 149 -148 1473 0
+-1441 -1473 0
+-1233 -1473 0
+-1292 -1473 0
+-1285 -1473 0
+-1278 -1473 0
+-1271 -1473 0
+-1264 -1473 0
+-1257 -1473 0
+1251 -1473 0
+-1240 -1473 0
+129 -1473 0
+-100 -1473 0
+-90 -1473 0
+-85 -1473 0
+-141 -1473 0
+-350 -1473 0
+-452 -1473 0
+458 -1473 0
+-149 -1473 0
+148 -1473 0
+1467 -1472 0
+85 90 1313 1292 1285 1278 1271 1264 1257 -1307 1240 -129 457 100 1233 1441 141 350 452 -454 -188 -199 1472 0
+-1441 -1472 0
+-1233 -1472 0
+-1313 -1472 0
+-1292 -1472 0
+-1285 -1472 0
+-1278 -1472 0
+-1271 -1472 0
+-1264 -1472 0
+-1257 -1472 0
+1307 -1472 0
+-1240 -1472 0
+129 -1472 0
+-457 -1472 0
+-100 -1472 0
+-90 -1472 0
+-85 -1472 0
+-141 -1472 0
+-350 -1472 0
+-452 -1472 0
+454 -1472 0
+188 -1472 0
+199 -1472 0
+1467 -1471 0
+85 90 1313 1292 1285 1278 1271 1264 1257 -1307 1240 -129 457 100 1233 1441 141 350 452 -454 199 -188 1471 0
+-1441 -1471 0
+-1233 -1471 0
+-1313 -1471 0
+-1292 -1471 0
+-1285 -1471 0
+-1278 -1471 0
+-1271 -1471 0
+-1264 -1471 0
+-1257 -1471 0
+1307 -1471 0
+-1240 -1471 0
+129 -1471 0
+-457 -1471 0
+-100 -1471 0
+-90 -1471 0
+-85 -1471 0
+-141 -1471 0
+-350 -1471 0
+-452 -1471 0
+454 -1471 0
+-199 -1471 0
+188 -1471 0
+1467 -1470 0
+85 90 1313 1306 1292 1285 1278 1271 1264 1257 -1300 1240 -129 457 453 100 1233 1441 141 350 452 -462 -180 -181 1470 0
+-1441 -1470 0
+-1233 -1470 0
+-1313 -1470 0
+-1306 -1470 0
+-1292 -1470 0
+-1285 -1470 0
+-1278 -1470 0
+-1271 -1470 0
+-1264 -1470 0
+-1257 -1470 0
+1300 -1470 0
+-1240 -1470 0
+129 -1470 0
+-457 -1470 0
+-453 -1470 0
+-100 -1470 0
+-90 -1470 0
+-85 -1470 0
+-141 -1470 0
+-350 -1470 0
+-452 -1470 0
+462 -1470 0
+180 -1470 0
+181 -1470 0
+1467 -1469 0
+85 90 1313 1306 1292 1285 1278 1271 1264 1257 -1300 1240 -129 457 453 100 1233 1441 141 350 452 -462 181 -180 1469 0
+-1441 -1469 0
+-1233 -1469 0
+-1313 -1469 0
+-1306 -1469 0
+-1292 -1469 0
+-1285 -1469 0
+-1278 -1469 0
+-1271 -1469 0
+-1264 -1469 0
+-1257 -1469 0
+1300 -1469 0
+-1240 -1469 0
+129 -1469 0
+-457 -1469 0
+-453 -1469 0
+-100 -1469 0
+-90 -1469 0
+-85 -1469 0
+-141 -1469 0
+-350 -1469 0
+-452 -1469 0
+462 -1469 0
+-181 -1469 0
+180 -1469 0
+1467 -1468 0
+85 90 1292 1285 1278 1271 1264 1257 -1251 1240 -129 100 1233 1441 141 350 452 -458 -149 -148 1468 0
+-1441 -1468 0
+-1233 -1468 0
+-1292 -1468 0
+-1285 -1468 0
+-1278 -1468 0
+-1271 -1468 0
+-1264 -1468 0
+-1257 -1468 0
+1251 -1468 0
+-1240 -1468 0
+129 -1468 0
+-100 -1468 0
+-90 -1468 0
+-85 -1468 0
+-141 -1468 0
+-350 -1468 0
+-452 -1468 0
+458 -1468 0
+149 -1468 0
+148 -1468 0
+1338 -1466 0
+-1007 -1466 0
+-30 -1466 0
+-57 -1466 0
+-31 -1466 0
+-665 -1464 0
+-615 -1464 0
+-612 -1464 0
+606 -1464 0
+602 -1464 0
+526 -1464 0
+-512 -1464 0
+-101 -1464 0
+-13 -1464 0
+1429 -1463 0
+-904 -1158 1431 1463 0
+-1431 -1463 0
+1158 -1463 0
+904 -1463 0
+1429 -1462 0
+-897 -1136 1431 1462 0
+-1431 -1462 0
+1136 -1462 0
+897 -1462 0
+1429 -1461 0
+12 -156 863 862 861 856 855 853 851 849 -848 -203 1431 1119 1461 0
+-1431 -1461 0
+-1119 -1461 0
+-863 -1461 0
+-862 -1461 0
+-861 -1461 0
+-856 -1461 0
+-855 -1461 0
+-853 -1461 0
+-851 -1461 0
+-849 -1461 0
+848 -1461 0
+203 -1461 0
+-12 -1461 0
+156 -1461 0
+1429 -1460 0
+7 -51 863 862 861 856 855 853 851 -850 1431 -52 1119 1460 0
+-1431 -1460 0
+-1119 -1460 0
+-863 -1460 0
+-862 -1460 0
+-861 -1460 0
+-856 -1460 0
+-855 -1460 0
+-853 -1460 0
+-851 -1460 0
+850 -1460 0
+-7 -1460 0
+52 -1460 0
+51 -1460 0
+1429 -1459 0
+7 21 863 862 861 856 855 853 -852 1119 1431 -26 -27 1459 0
+-1431 -1459 0
+-1119 -1459 0
+-863 -1459 0
+-862 -1459 0
+-861 -1459 0
+-856 -1459 0
+-855 -1459 0
+-853 -1459 0
+852 -1459 0
+-21 -1459 0
+-7 -1459 0
+26 -1459 0
+27 -1459 0
+1429 -1458 0
+7 13 -891 863 861 -854 -331 -318 -305 1119 1431 -42 -36 -48 1458 0
+-1431 -1458 0
+-1119 -1458 0
+891 -1458 0
+-863 -1458 0
+-861 -1458 0
+854 -1458 0
+331 -1458 0
+318 -1458 0
+305 -1458 0
+-13 -1458 0
+-7 -1458 0
+42 -1458 0
+36 -1458 0
+48 -1458 0
+1429 -1457 0
+-5 -6 -837 -886 -653 -601 -641 -825 529 13 7 1119 1431 -22 1457 0
+-1431 -1457 0
+-1119 -1457 0
+837 -1457 0
+886 -1457 0
+653 -1457 0
+601 -1457 0
+641 -1457 0
+825 -1457 0
+-529 -1457 0
+-13 -1457 0
+-7 -1457 0
+6 -1457 0
+5 -1457 0
+22 -1457 0
+1429 -1456 0
+7 51 863 862 861 856 855 853 851 -850 1119 1431 -52 1456 0
+-1431 -1456 0
+-1119 -1456 0
+-863 -1456 0
+-862 -1456 0
+-861 -1456 0
+-856 -1456 0
+-855 -1456 0
+-853 -1456 0
+-851 -1456 0
+850 -1456 0
+-51 -1456 0
+-7 -1456 0
+52 -1456 0
+1429 -1455 0
+7 21 863 862 861 856 855 853 -852 27 1119 1431 -26 1455 0
+-1431 -1455 0
+-1119 -1455 0
+-863 -1455 0
+-862 -1455 0
+-861 -1455 0
+-856 -1455 0
+-855 -1455 0
+-853 -1455 0
+852 -1455 0
+-27 -1455 0
+-21 -1455 0
+-7 -1455 0
+26 -1455 0
+1429 -1454 0
+7 13 -881 863 861 -854 -331 -318 48 1119 1431 -42 -36 1454 0
+-1431 -1454 0
+-1119 -1454 0
+881 -1454 0
+-863 -1454 0
+-861 -1454 0
+854 -1454 0
+331 -1454 0
+318 -1454 0
+-48 -1454 0
+-13 -1454 0
+-7 -1454 0
+42 -1454 0
+36 -1454 0
+1429 -1453 0
+-5 -6 -653 -876 -601 -641 529 22 13 7 1119 1431 1453 0
+-1431 -1453 0
+-1119 -1453 0
+653 -1453 0
+876 -1453 0
+601 -1453 0
+641 -1453 0
+-529 -1453 0
+-22 -1453 0
+-13 -1453 0
+-7 -1453 0
+6 -1453 0
+5 -1453 0
+1429 -1452 0
+12 -156 863 862 861 856 855 853 851 849 -848 203 1431 1119 1452 0
+-1431 -1452 0
+-1119 -1452 0
+-863 -1452 0
+-862 -1452 0
+-861 -1452 0
+-856 -1452 0
+-855 -1452 0
+-853 -1452 0
+-851 -1452 0
+-849 -1452 0
+848 -1452 0
+-203 -1452 0
+-12 -1452 0
+156 -1452 0
+1429 -1451 0
+-148 149 863 862 861 856 855 853 851 849 847 -867 1119 1431 1451 0
+-1431 -1451 0
+-1119 -1451 0
+-863 -1451 0
+-862 -1451 0
+-861 -1451 0
+-856 -1451 0
+-855 -1451 0
+-853 -1451 0
+-851 -1451 0
+-849 -1451 0
+-847 -1451 0
+867 -1451 0
+-149 -1451 0
+148 -1451 0
+1429 -1450 0
+-188 -199 866 863 862 861 856 855 853 851 849 847 -865 1431 1119 1450 0
+-1431 -1450 0
+-1119 -1450 0
+-866 -1450 0
+-863 -1450 0
+-862 -1450 0
+-861 -1450 0
+-856 -1450 0
+-855 -1450 0
+-853 -1450 0
+-851 -1450 0
+-849 -1450 0
+-847 -1450 0
+865 -1450 0
+188 -1450 0
+199 -1450 0
+1429 -1449 0
+-188 199 866 863 862 861 856 855 853 851 849 847 -865 1119 1431 1449 0
+-1431 -1449 0
+-1119 -1449 0
+-866 -1449 0
+-863 -1449 0
+-862 -1449 0
+-861 -1449 0
+-856 -1449 0
+-855 -1449 0
+-853 -1449 0
+-851 -1449 0
+-849 -1449 0
+-847 -1449 0
+865 -1449 0
+-199 -1449 0
+188 -1449 0
+1429 -1448 0
+-180 -181 866 864 863 862 861 856 855 853 851 849 847 -846 1431 1119 1448 0
+-1431 -1448 0
+-1119 -1448 0
+-866 -1448 0
+-864 -1448 0
+-863 -1448 0
+-862 -1448 0
+-861 -1448 0
+-856 -1448 0
+-855 -1448 0
+-853 -1448 0
+-851 -1448 0
+-849 -1448 0
+-847 -1448 0
+846 -1448 0
+180 -1448 0
+181 -1448 0
+1429 -1447 0
+-180 181 866 864 863 862 861 856 855 853 851 849 847 -846 1119 1431 1447 0
+-1431 -1447 0
+-1119 -1447 0
+-866 -1447 0
+-864 -1447 0
+-863 -1447 0
+-862 -1447 0
+-861 -1447 0
+-856 -1447 0
+-855 -1447 0
+-853 -1447 0
+-851 -1447 0
+-849 -1447 0
+-847 -1447 0
+846 -1447 0
+-181 -1447 0
+180 -1447 0
+1429 -1430 0
+-148 -149 863 862 861 856 855 853 851 849 847 -867 1119 1431 1430 0
+-1430 -1431 0
+1233 1431 -1432 -1440 0
+-1431 1440 0
+1240 -1440 -1441 0
+1440 1441 0
+-1007 1441 -1442 0
+-1007 -1441 1442 0
+-134 1007 1441 0
+134 1007 -1441 0
+-1115 1442 -1443 0
+-1115 -1442 1443 0
+1115 1442 -1444 0
+1115 -1442 1444 0
+-1237 1444 -1445 0
+-1237 -1444 1445 0
+1237 1444 -1446 0
+1237 -1444 1446 0
+-1240 1440 0
+-1233 -1431 0
+-1431 1432 0
+-1432 1433 1434 1436 1438 0
+1432 -1438 0
+31 -57 -1089 -1439 -1007 1115 1438 0
+-1115 -1438 0
+1007 -1438 0
+1089 -1438 0
+-1438 1439 0
+57 -1438 0
+-31 -1438 0
+1432 -1436 0
+-1007 1115 1237 -1437 1436 0
+-1237 -1436 0
+-1115 -1436 0
+1007 -1436 0
+-1436 1437 0
+1432 -1434 0
+30 31 -1007 57 -1435 -1037 1434 0
+1007 -1434 0
+-1434 1435 0
+-30 -1434 0
+-57 -1434 0
+-31 -1434 0
+1037 -1434 0
+1432 -1433 0
+-611 1007 1433 0
+-1007 -1433 0
+611 -1433 0
+-1119 -1430 0
+-863 -1430 0
+-862 -1430 0
+-861 -1430 0
+-856 -1430 0
+-855 -1430 0
+-853 -1430 0
+-851 -1430 0
+-849 -1430 0
+-847 -1430 0
+867 -1430 0
+149 -1430 0
+148 -1430 0
+-1223 1224 0
+-1224 1225 1428 0
+1224 -1428 0
+30 31 1007 984 983 -934 -1231 57 -1338 1428 0
+1231 -1428 0
+1338 -1428 0
+-1007 -1428 0
+-984 -1428 0
+-983 -1428 0
+934 -1428 0
+-30 -1428 0
+-57 -1428 0
+-31 -1428 0
+1224 -1225 0
+512 934 1007 -1226 1231 1225 0
+-1225 -1231 0
+-1231 1232 1246 0
+1231 -1246 0
+-1233 -1240 -1247 1246 0
+-1246 1247 0
+-947 1247 -1248 0
+947 -1247 -1248 0
+1247 1248 -1427 0
+-1247 1248 1427 0
+30 31 1007 -1338 57 -1249 1248 0
+-1248 1338 0
+-1338 1339 1417 1416 1415 1414 1413 1412 1411 1410 1409 1408 1407 1406 1405 1404 1403 1388 1419 1423 0
+1338 -1423 0
+13 101 418 -286 -563 -112 -107 432 -1424 1423 0
+-1423 1424 0
+-1159 -1381 1424 0
+1159 -1381 -1424 0
+1381 1424 -1425 0
+1381 -1424 1425 0
+-908 -1374 1425 0
+908 -1374 -1425 0
+1374 1425 -1426 0
+1374 -1425 1426 0
+7 13 -447 -419 -289 30 83 450 -1368 -42 -36 -48 1426 0
+1368 -1426 0
+-450 -1426 0
+447 -1426 0
+419 -1426 0
+289 -1426 0
+-30 -1426 0
+-83 -1426 0
+-13 -1426 0
+-7 -1426 0
+42 -1426 0
+36 -1426 0
+48 -1426 0
+-432 -1423 0
+-418 -1423 0
+286 -1423 0
+563 -1423 0
+112 -1423 0
+107 -1423 0
+-101 -1423 0
+-13 -1423 0
+1338 -1419 0
+13 101 286 352 -563 -112 -107 366 -1420 1419 0
+-1419 1420 0
+-1137 -1381 1420 0
+1137 -1381 -1420 0
+1381 1420 -1421 0
+1381 -1420 1421 0
+-901 -1374 1421 0
+901 -1374 -1421 0
+1374 1421 -1422 0
+1374 -1421 1422 0
+7 13 -403 -353 30 83 48 416 -1368 -42 -36 1422 0
+1368 -1422 0
+-416 -1422 0
+403 -1422 0
+353 -1422 0
+-30 -1422 0
+-83 -1422 0
+-48 -1422 0
+-13 -1422 0
+-7 -1422 0
+42 -1422 0
+36 -1422 0
+-366 -1419 0
+-286 -1419 0
+-352 -1419 0
+563 -1419 0
+112 -1419 0
+107 -1419 0
+-101 -1419 0
+-13 -1419 0
+1338 -1417 0
+30 31 1395 1381 1374 1367 1360 1353 1346 1007 581 577 573 562 558 554 550 546 542 1418 57 1402 1417 0
+-1417 -1418 0
+-180 -1389 1418 0
+1389 -1418 0
+180 -1418 0
+-1402 -1417 0
+-1395 -1417 0
+-1381 -1417 0
+-1374 -1417 0
+-1367 -1417 0
+-1360 -1417 0
+-1353 -1417 0
+-1346 -1417 0
+-1007 -1417 0
+-581 -1417 0
+-577 -1417 0
+-573 -1417 0
+-562 -1417 0
+-558 -1417 0
+-554 -1417 0
+-550 -1417 0
+-546 -1417 0
+-542 -1417 0
+-30 -1417 0
+-57 -1417 0
+-31 -1417 0
+1338 -1416 0
+12 -156 1367 1360 1353 -1347 562 558 554 550 546 -543 -203 1381 1374 1416 0
+-1381 -1416 0
+-1374 -1416 0
+-1367 -1416 0
+-1360 -1416 0
+-1353 -1416 0
+1347 -1416 0
+-562 -1416 0
+-558 -1416 0
+-554 -1416 0
+-550 -1416 0
+-546 -1416 0
+543 -1416 0
+203 -1416 0
+-12 -1416 0
+156 -1416 0
+1338 -1415 0
+7 -51 1367 1360 -1354 562 558 554 550 -547 1381 -52 1374 1415 0
+-1381 -1415 0
+-1374 -1415 0
+-1367 -1415 0
+-1360 -1415 0
+1354 -1415 0
+-562 -1415 0
+-558 -1415 0
+-554 -1415 0
+-550 -1415 0
+547 -1415 0
+-7 -1415 0
+52 -1415 0
+51 -1415 0
+1338 -1414 0
+7 21 1367 -1361 562 558 554 -551 1374 1381 -26 -27 1414 0
+-1381 -1414 0
+-1374 -1414 0
+-1367 -1414 0
+1361 -1414 0
+-562 -1414 0
+-558 -1414 0
+-554 -1414 0
+551 -1414 0
+-21 -1414 0
+-7 -1414 0
+26 -1414 0
+27 -1414 0
+1338 -1413 0
+7 13 -1368 -331 -318 -305 -594 1374 1381 -42 -36 -48 1413 0
+-1381 -1413 0
+-1374 -1413 0
+1368 -1413 0
+331 -1413 0
+318 -1413 0
+305 -1413 0
+594 -1413 0
+-13 -1413 0
+-7 -1413 0
+42 -1413 0
+36 -1413 0
+48 -1413 0
+1338 -1412 0
+-5 -6 -837 -653 -641 -825 529 -683 13 7 -1375 1381 -22 1412 0
+-1381 -1412 0
+1375 -1412 0
+837 -1412 0
+653 -1412 0
+641 -1412 0
+825 -1412 0
+-529 -1412 0
+683 -1412 0
+-13 -1412 0
+-7 -1412 0
+6 -1412 0
+5 -1412 0
+22 -1412 0
+1338 -1411 0
+7 51 1367 1360 -1354 562 558 554 550 -547 1374 1381 -52 1411 0
+-1381 -1411 0
+-1374 -1411 0
+-1367 -1411 0
+-1360 -1411 0
+1354 -1411 0
+-562 -1411 0
+-558 -1411 0
+-554 -1411 0
+-550 -1411 0
+547 -1411 0
+-51 -1411 0
+-7 -1411 0
+52 -1411 0
+1338 -1410 0
+7 21 1367 -1361 562 558 554 -551 27 1374 1381 -26 1410 0
+-1381 -1410 0
+-1374 -1410 0
+-1367 -1410 0
+1361 -1410 0
+-562 -1410 0
+-558 -1410 0
+-554 -1410 0
+551 -1410 0
+-27 -1410 0
+-21 -1410 0
+-7 -1410 0
+26 -1410 0
+1338 -1409 0
+7 13 -1368 -331 -318 -589 48 1374 1381 -42 -36 1409 0
+-1381 -1409 0
+-1374 -1409 0
+1368 -1409 0
+331 -1409 0
+318 -1409 0
+589 -1409 0
+-48 -1409 0
+-13 -1409 0
+-7 -1409 0
+42 -1409 0
+36 -1409 0
+1338 -1408 0
+-5 -6 -653 -641 529 -676 22 13 7 -1375 1381 1408 0
+-1381 -1408 0
+1375 -1408 0
+653 -1408 0
+641 -1408 0
+-529 -1408 0
+676 -1408 0
+-22 -1408 0
+-13 -1408 0
+-7 -1408 0
+6 -1408 0
+5 -1408 0
+1338 -1407 0
+12 -156 1367 1360 1353 -1347 562 558 554 550 546 -543 203 1381 1374 1407 0
+-1381 -1407 0
+-1374 -1407 0
+-1367 -1407 0
+-1360 -1407 0
+-1353 -1407 0
+1347 -1407 0
+-562 -1407 0
+-558 -1407 0
+-554 -1407 0
+-550 -1407 0
+-546 -1407 0
+543 -1407 0
+-203 -1407 0
+-12 -1407 0
+156 -1407 0
+1338 -1406 0
+-148 149 1367 1360 1353 1346 -1340 562 558 554 550 546 542 -539 1374 1381 1406 0
+-1381 -1406 0
+-1374 -1406 0
+-1367 -1406 0
+-1360 -1406 0
+-1353 -1406 0
+-1346 -1406 0
+1340 -1406 0
+-562 -1406 0
+-558 -1406 0
+-554 -1406 0
+-550 -1406 0
+-546 -1406 0
+-542 -1406 0
+539 -1406 0
+-149 -1406 0
+148 -1406 0
+1338 -1405 0
+-188 -199 1374 1367 1360 1353 1346 -1396 581 562 558 554 550 546 542 -578 1402 1381 1405 0
+-1402 -1405 0
+-1381 -1405 0
+-1374 -1405 0
+-1367 -1405 0
+-1360 -1405 0
+-1353 -1405 0
+-1346 -1405 0
+1396 -1405 0
+-581 -1405 0
+-562 -1405 0
+-558 -1405 0
+-554 -1405 0
+-550 -1405 0
+-546 -1405 0
+-542 -1405 0
+578 -1405 0
+188 -1405 0
+199 -1405 0
+1338 -1404 0
+-188 199 1374 1367 1360 1353 1346 -1396 581 562 558 554 550 546 542 -578 1381 1402 1404 0
+-1402 -1404 0
+-1381 -1404 0
+-1374 -1404 0
+-1367 -1404 0
+-1360 -1404 0
+-1353 -1404 0
+-1346 -1404 0
+1396 -1404 0
+-581 -1404 0
+-562 -1404 0
+-558 -1404 0
+-554 -1404 0
+-550 -1404 0
+-546 -1404 0
+-542 -1404 0
+578 -1404 0
+-199 -1404 0
+188 -1404 0
+1338 -1403 0
+-180 -181 1381 1374 1367 1360 1353 1346 -1389 581 577 562 558 554 550 546 542 -574 1402 1395 1403 0
+-1402 -1403 0
+-1395 -1403 0
+-1381 -1403 0
+-1374 -1403 0
+-1367 -1403 0
+-1360 -1403 0
+-1353 -1403 0
+-1346 -1403 0
+1389 -1403 0
+-581 -1403 0
+-577 -1403 0
+-562 -1403 0
+-558 -1403 0
+-554 -1403 0
+-550 -1403 0
+-546 -1403 0
+-542 -1403 0
+574 -1403 0
+180 -1403 0
+181 -1403 0
+1338 -1388 0
+-180 181 1381 1374 1367 1360 1353 1346 -1389 581 577 562 558 554 550 546 542 -574 1395 1402 1388 0
+-1388 -1402 0
+-148 -1340 1402 0
+1340 -1402 0
+148 -1402 0
+-1388 -1395 0
+-188 1395 -1396 0
+-1395 1396 0
+-1007 1396 -1397 0
+-1007 -1396 1397 0
+-580 1007 1396 0
+580 1007 -1396 0
+-1115 1397 -1398 0
+-1115 -1397 1398 0
+1115 1397 -1399 0
+1115 -1397 1399 0
+-1237 1399 -1400 0
+-1237 -1399 1400 0
+1237 1399 -1401 0
+1237 -1399 1401 0
+188 -1395 0
+-1381 -1388 0
+-1374 -1388 0
+-1367 -1388 0
+-1360 -1388 0
+-1353 -1388 0
+-1346 -1388 0
+-1388 1389 0
+-1007 1389 -1390 0
+-1007 -1389 1390 0
+-576 1007 1389 0
+576 1007 -1389 0
+-1115 1390 -1391 0
+-1115 -1390 1391 0
+1115 1390 -1392 0
+1115 -1390 1392 0
+-1237 1392 -1393 0
+-1237 -1392 1393 0
+1237 1392 -1394 0
+1237 -1392 1394 0
+-581 -1388 0
+-577 -1388 0
+-562 -1388 0
+-558 -1388 0
+-554 -1388 0
+-550 -1388 0
+-546 -1388 0
+-542 -1388 0
+574 -1388 0
+-181 -1388 0
+180 -1388 0
+1338 -1339 0
+-148 -149 1367 1360 1353 1346 -1340 562 558 554 550 546 542 -539 1374 1381 1339 0
+-1339 -1381 0
+115 -116 -1382 1381 0
+-1381 1382 0
+-1007 1382 -1383 0
+-1007 -1382 1383 0
+-570 1007 1382 0
+570 1007 -1382 0
+-1115 1383 -1384 0
+-1115 -1383 1384 0
+1115 1383 -1385 0
+1115 -1383 1385 0
+-1237 1385 -1386 0
+-1237 -1385 1386 0
+1237 1385 -1387 0
+1237 -1385 1387 0
+116 -1381 0
+-115 -1381 0
+-1339 -1374 0
+-5 -6 13 7 529 -1375 1374 0
+-1374 1375 0
+-1007 1375 -1376 0
+-1007 -1375 1376 0
+-561 1007 1375 0
+561 1007 -1375 0
+-1115 1376 -1377 0
+-1115 -1376 1377 0
+1115 1376 -1378 0
+1115 -1376 1378 0
+-1237 1378 -1379 0
+-1237 -1378 1379 0
+1237 1378 -1380 0
+1237 -1378 1380 0
+-529 -1374 0
+-13 -1374 0
+-7 -1374 0
+6 -1374 0
+5 -1374 0
+-1339 -1367 0
+7 13 -1368 -42 -36 1367 0
+-1367 1368 0
+-1007 1368 -1369 0
+-1007 -1368 1369 0
+-557 1007 1368 0
+557 1007 -1368 0
+-1115 1369 -1370 0
+-1115 -1369 1370 0
+1115 1369 -1371 0
+1115 -1369 1371 0
+-1237 1371 -1372 0
+-1237 -1371 1372 0
+1237 1371 -1373 0
+1237 -1371 1373 0
+-13 -1367 0
+-7 -1367 0
+42 -1367 0
+36 -1367 0
+-1339 -1360 0
+7 21 -1361 -26 1360 0
+-1360 1361 0
+-1007 1361 -1362 0
+-1007 -1361 1362 0
+-553 1007 1361 0
+553 1007 -1361 0
+-1115 1362 -1363 0
+-1115 -1362 1363 0
+1115 1362 -1364 0
+1115 -1362 1364 0
+-1237 1364 -1365 0
+-1237 -1364 1365 0
+1237 1364 -1366 0
+1237 -1364 1366 0
+-21 -1360 0
+-7 -1360 0
+26 -1360 0
+-1339 -1353 0
+7 -52 -1354 1353 0
+-1353 1354 0
+-1007 1354 -1355 0
+-1007 -1354 1355 0
+-549 1007 1354 0
+549 1007 -1354 0
+-1115 1355 -1356 0
+-1115 -1355 1356 0
+1115 1355 -1357 0
+1115 -1355 1357 0
+-1237 1357 -1358 0
+-1237 -1357 1358 0
+1237 1357 -1359 0
+1237 -1357 1359 0
+-7 -1353 0
+52 -1353 0
+-1339 -1346 0
+12 -156 -1347 1346 0
+-1346 1347 0
+-1007 1347 -1348 0
+-1007 -1347 1348 0
+-545 1007 1347 0
+545 1007 -1347 0
+-1115 1348 -1349 0
+-1115 -1348 1349 0
+1115 1348 -1350 0
+1115 -1348 1350 0
+-1237 1350 -1351 0
+-1237 -1350 1351 0
+1237 1350 -1352 0
+1237 -1350 1352 0
+-12 -1346 0
+156 -1346 0
+-1339 1340 0
+-1007 1340 -1341 0
+-1007 -1340 1341 0
+-541 1007 1340 0
+541 1007 -1340 0
+-1115 1341 -1342 0
+-1115 -1341 1342 0
+1115 1341 -1343 0
+1115 -1341 1343 0
+-1237 1343 -1344 0
+-1237 -1343 1344 0
+1237 1343 -1345 0
+1237 -1343 1345 0
+-562 -1339 0
+-558 -1339 0
+-554 -1339 0
+-550 -1339 0
+-546 -1339 0
+-542 -1339 0
+539 -1339 0
+149 -1339 0
+148 -1339 0
+-1248 1249 0
+-1249 1250 1328 1327 1326 1325 1324 1323 1322 1321 1320 1319 1318 1317 1316 1315 1314 1299 1332 1336 0
+1249 -1336 0
+30 31 1306 1292 1285 1278 1271 1264 1257 1007 461 457 453 100 90 85 141 350 452 1337 57 1313 1336 0
+-1336 -1337 0
+-180 -1300 1337 0
+1300 -1337 0
+180 -1337 0
+-1313 -1336 0
+-1306 -1336 0
+-1292 -1336 0
+-1285 -1336 0
+-1278 -1336 0
+-1271 -1336 0
+-1264 -1336 0
+-1257 -1336 0
+-1007 -1336 0
+-461 -1336 0
+-457 -1336 0
+-453 -1336 0
+-100 -1336 0
+-90 -1336 0
+-85 -1336 0
+-141 -1336 0
+-350 -1336 0
+-452 -1336 0
+-30 -1336 0
+-57 -1336 0
+-31 -1336 0
+1249 -1332 0
+13 101 418 -286 -119 -112 -107 432 -1333 1332 0
+-1332 1333 0
+-1159 -1292 1333 0
+1159 -1292 -1333 0
+1292 1333 -1334 0
+1292 -1333 1334 0
+-908 -1285 1334 0
+908 -1285 -1334 0
+1285 1334 -1335 0
+1285 -1334 1335 0
+7 13 -447 -419 -289 30 83 450 -1279 -42 -36 -48 1335 0
+1279 -1335 0
+-450 -1335 0
+447 -1335 0
+419 -1335 0
+289 -1335 0
+-30 -1335 0
+-83 -1335 0
+-13 -1335 0
+-7 -1335 0
+42 -1335 0
+36 -1335 0
+48 -1335 0
+-432 -1332 0
+-418 -1332 0
+286 -1332 0
+119 -1332 0
+112 -1332 0
+107 -1332 0
+-101 -1332 0
+-13 -1332 0
+1249 -1328 0
+13 101 286 352 -119 -112 -107 366 -1329 1328 0
+-1328 1329 0
+-1137 -1292 1329 0
+1137 -1292 -1329 0
+1292 1329 -1330 0
+1292 -1329 1330 0
+-901 -1285 1330 0
+901 -1285 -1330 0
+1285 1330 -1331 0
+1285 -1330 1331 0
+7 13 -403 -353 30 83 48 416 -1279 -42 -36 1331 0
+1279 -1331 0
+-416 -1331 0
+403 -1331 0
+353 -1331 0
+-30 -1331 0
+-83 -1331 0
+-48 -1331 0
+-13 -1331 0
+-7 -1331 0
+42 -1331 0
+36 -1331 0
+-366 -1328 0
+-286 -1328 0
+-352 -1328 0
+119 -1328 0
+112 -1328 0
+107 -1328 0
+-101 -1328 0
+-13 -1328 0
+1249 -1327 0
+12 85 1278 1271 1264 -1258 100 90 1285 141 350 -347 -203 1292 -156 1327 0
+-1292 -1327 0
+-1285 -1327 0
+-1278 -1327 0
+-1271 -1327 0
+-1264 -1327 0
+1258 -1327 0
+-100 -1327 0
+-90 -1327 0
+-85 -1327 0
+-141 -1327 0
+-350 -1327 0
+347 -1327 0
+203 -1327 0
+-12 -1327 0
+156 -1327 0
+1249 -1326 0
+7 -51 1278 1271 -1265 100 90 85 141 -137 1292 -52 1285 1326 0
+-1292 -1326 0
+-1285 -1326 0
+-1278 -1326 0
+-1271 -1326 0
+1265 -1326 0
+-100 -1326 0
+-90 -1326 0
+-85 -1326 0
+-141 -1326 0
+137 -1326 0
+-7 -1326 0
+52 -1326 0
+51 -1326 0
+1249 -1325 0
+7 21 1278 -1272 100 90 85 -29 1285 1292 -26 -27 1325 0
+-1292 -1325 0
+-1285 -1325 0
+-1278 -1325 0
+1272 -1325 0
+-100 -1325 0
+-90 -1325 0
+-85 -1325 0
+29 -1325 0
+-21 -1325 0
+-7 -1325 0
+26 -1325 0
+27 -1325 0
+1249 -1324 0
+7 13 -1279 -331 -318 -305 -144 1285 1292 -42 -36 -48 1324 0
+-1292 -1324 0
+-1285 -1324 0
+1279 -1324 0
+331 -1324 0
+318 -1324 0
+305 -1324 0
+144 -1324 0
+-13 -1324 0
+-7 -1324 0
+42 -1324 0
+36 -1324 0
+48 -1324 0
+1249 -1323 0
+-5 -6 -837 -653 -641 -825 529 -705 13 7 -1286 1292 -22 1323 0
+-1292 -1323 0
+1286 -1323 0
+837 -1323 0
+653 -1323 0
+641 -1323 0
+825 -1323 0
+-529 -1323 0
+705 -1323 0
+-13 -1323 0
+-7 -1323 0
+6 -1323 0
+5 -1323 0
+22 -1323 0
+1249 -1322 0
+7 51 1278 1271 -1265 100 90 85 141 -137 1285 1292 -52 1322 0
+-1292 -1322 0
+-1285 -1322 0
+-1278 -1322 0
+-1271 -1322 0
+1265 -1322 0
+-100 -1322 0
+-90 -1322 0
+-85 -1322 0
+-141 -1322 0
+137 -1322 0
+-51 -1322 0
+-7 -1322 0
+52 -1322 0
+1249 -1321 0
+7 21 1278 -1272 100 90 85 -29 27 1285 1292 -26 1321 0
+-1292 -1321 0
+-1285 -1321 0
+-1278 -1321 0
+1272 -1321 0
+-100 -1321 0
+-90 -1321 0
+-85 -1321 0
+29 -1321 0
+-27 -1321 0
+-21 -1321 0
+-7 -1321 0
+26 -1321 0
+1249 -1320 0
+7 13 -1279 -331 -318 -474 48 1285 1292 -42 -36 1320 0
+-1292 -1320 0
+-1285 -1320 0
+1279 -1320 0
+331 -1320 0
+318 -1320 0
+474 -1320 0
+-48 -1320 0
+-13 -1320 0
+-7 -1320 0
+42 -1320 0
+36 -1320 0
+1249 -1319 0
+-5 -6 -653 -641 529 -699 22 13 7 -1286 1292 1319 0
+-1292 -1319 0
+1286 -1319 0
+653 -1319 0
+641 -1319 0
+-529 -1319 0
+699 -1319 0
+-22 -1319 0
+-13 -1319 0
+-7 -1319 0
+6 -1319 0
+5 -1319 0
+1249 -1318 0
+12 85 1278 1271 1264 -1258 100 90 1285 141 350 -347 203 1292 -156 1318 0
+-1292 -1318 0
+-1285 -1318 0
+-1278 -1318 0
+-1271 -1318 0
+-1264 -1318 0
+1258 -1318 0
+-100 -1318 0
+-90 -1318 0
+-85 -1318 0
+-141 -1318 0
+-350 -1318 0
+347 -1318 0
+-203 -1318 0
+-12 -1318 0
+156 -1318 0
+1249 -1317 0
+85 90 1278 1271 1264 1257 -1251 100 1285 1292 141 350 452 -458 149 -148 1317 0
+-1292 -1317 0
+-1285 -1317 0
+-1278 -1317 0
+-1271 -1317 0
+-1264 -1317 0
+-1257 -1317 0
+1251 -1317 0
+-100 -1317 0
+-90 -1317 0
+-85 -1317 0
+-141 -1317 0
+-350 -1317 0
+-452 -1317 0
+458 -1317 0
+-149 -1317 0
+148 -1317 0
+1249 -1316 0
+85 90 1285 1278 1271 1264 1257 -1307 457 100 1292 1313 141 350 452 -454 -188 -199 1316 0
+-1313 -1316 0
+-1292 -1316 0
+-1285 -1316 0
+-1278 -1316 0
+-1271 -1316 0
+-1264 -1316 0
+-1257 -1316 0
+1307 -1316 0
+-457 -1316 0
+-100 -1316 0
+-90 -1316 0
+-85 -1316 0
+-141 -1316 0
+-350 -1316 0
+-452 -1316 0
+454 -1316 0
+188 -1316 0
+199 -1316 0
+1249 -1315 0
+85 90 1285 1278 1271 1264 1257 -1307 457 100 1292 1313 141 350 452 -454 199 -188 1315 0
+-1313 -1315 0
+-1292 -1315 0
+-1285 -1315 0
+-1278 -1315 0
+-1271 -1315 0
+-1264 -1315 0
+-1257 -1315 0
+1307 -1315 0
+-457 -1315 0
+-100 -1315 0
+-90 -1315 0
+-85 -1315 0
+-141 -1315 0
+-350 -1315 0
+-452 -1315 0
+454 -1315 0
+-199 -1315 0
+188 -1315 0
+1249 -1314 0
+85 90 1292 1285 1278 1271 1264 1257 -1300 457 453 100 1306 1313 141 350 452 -462 -180 -181 1314 0
+-1313 -1314 0
+-1306 -1314 0
+-1292 -1314 0
+-1285 -1314 0
+-1278 -1314 0
+-1271 -1314 0
+-1264 -1314 0
+-1257 -1314 0
+1300 -1314 0
+-457 -1314 0
+-453 -1314 0
+-100 -1314 0
+-90 -1314 0
+-85 -1314 0
+-141 -1314 0
+-350 -1314 0
+-452 -1314 0
+462 -1314 0
+180 -1314 0
+181 -1314 0
+1249 -1299 0
+85 90 1292 1285 1278 1271 1264 1257 -1300 457 453 100 1306 1313 141 350 452 -462 181 -180 1299 0
+-1299 -1313 0
+-148 -1251 1313 0
+1251 -1313 0
+148 -1313 0
+-1299 -1306 0
+-188 1306 -1307 0
+-1306 1307 0
+-1007 1307 -1308 0
+-1007 -1307 1308 0
+-456 1007 1307 0
+456 1007 -1307 0
+-1115 1308 -1309 0
+-1115 -1308 1309 0
+1115 1308 -1310 0
+1115 -1308 1310 0
+-1237 1310 -1311 0
+-1237 -1310 1311 0
+1237 1310 -1312 0
+1237 -1310 1312 0
+188 -1306 0
+-1292 -1299 0
+-1285 -1299 0
+-1278 -1299 0
+-1271 -1299 0
+-1264 -1299 0
+-1257 -1299 0
+-1299 1300 0
+-1007 1300 -1301 0
+-1007 -1300 1301 0
+-464 1007 1300 0
+464 1007 -1300 0
+-1115 1301 -1302 0
+-1115 -1301 1302 0
+1115 1301 -1303 0
+1115 -1301 1303 0
+-1237 1303 -1304 0
+-1237 -1303 1304 0
+1237 1303 -1305 0
+1237 -1303 1305 0
+-457 -1299 0
+-453 -1299 0
+-100 -1299 0
+-90 -1299 0
+-85 -1299 0
+-141 -1299 0
+-350 -1299 0
+-452 -1299 0
+462 -1299 0
+-181 -1299 0
+180 -1299 0
+1249 -1250 0
+85 90 1278 1271 1264 1257 -1251 100 1285 1292 141 350 452 -458 -149 -148 1250 0
+-1250 -1292 0
+115 -116 -1293 1292 0
+-1292 1293 0
+-1007 1293 -1294 0
+-1007 -1293 1294 0
+-126 1007 1293 0
+126 1007 -1293 0
+-1115 1294 -1295 0
+-1115 -1294 1295 0
+1115 1294 -1296 0
+1115 -1294 1296 0
+-1237 1296 -1297 0
+-1237 -1296 1297 0
+1237 1296 -1298 0
+1237 -1296 1298 0
+116 -1292 0
+-115 -1292 0
+-1250 -1285 0
+-5 -6 13 7 529 -1286 1285 0
+-1285 1286 0
+-1007 1286 -1287 0
+-1007 -1286 1287 0
+-98 1007 1286 0
+98 1007 -1286 0
+-1115 1287 -1288 0
+-1115 -1287 1288 0
+1115 1287 -1289 0
+1115 -1287 1289 0
+-1237 1289 -1290 0
+-1237 -1289 1290 0
+1237 1289 -1291 0
+1237 -1289 1291 0
+-529 -1285 0
+-13 -1285 0
+-7 -1285 0
+6 -1285 0
+5 -1285 0
+-1250 -1278 0
+7 13 -1279 -42 -36 1278 0
+-1278 1279 0
+-1007 1279 -1280 0
+-1007 -1279 1280 0
+-89 1007 1279 0
+89 1007 -1279 0
+-1115 1280 -1281 0
+-1115 -1280 1281 0
+1115 1280 -1282 0
+1115 -1280 1282 0
+-1237 1282 -1283 0
+-1237 -1282 1283 0
+1237 1282 -1284 0
+1237 -1282 1284 0
+-13 -1278 0
+-7 -1278 0
+42 -1278 0
+36 -1278 0
+-1250 -1271 0
+7 21 -1272 -26 1271 0
+-1271 1272 0
+-1007 1272 -1273 0
+-1007 -1272 1273 0
+-84 1007 1272 0
+84 1007 -1272 0
+-1115 1273 -1274 0
+-1115 -1273 1274 0
+1115 1273 -1275 0
+1115 -1273 1275 0
+-1237 1275 -1276 0
+-1237 -1275 1276 0
+1237 1275 -1277 0
+1237 -1275 1277 0
+-21 -1271 0
+-7 -1271 0
+26 -1271 0
+-1250 -1264 0
+7 -52 -1265 1264 0
+-1264 1265 0
+-1007 1265 -1266 0
+-1007 -1265 1266 0
+-140 1007 1265 0
+140 1007 -1265 0
+-1115 1266 -1267 0
+-1115 -1266 1267 0
+1115 1266 -1268 0
+1115 -1266 1268 0
+-1237 1268 -1269 0
+-1237 -1268 1269 0
+1237 1268 -1270 0
+1237 -1268 1270 0
+-7 -1264 0
+52 -1264 0
+-1250 -1257 0
+12 -156 -1258 1257 0
+-1257 1258 0
+-1007 1258 -1259 0
+-1007 -1258 1259 0
+-349 1007 1258 0
+349 1007 -1258 0
+-1115 1259 -1260 0
+-1115 -1259 1260 0
+1115 1259 -1261 0
+1115 -1259 1261 0
+-1237 1261 -1262 0
+-1237 -1261 1262 0
+1237 1261 -1263 0
+1237 -1261 1263 0
+-12 -1257 0
+156 -1257 0
+-1250 1251 0
+-1007 1251 -1252 0
+-1007 -1251 1252 0
+-460 1007 1251 0
+460 1007 -1251 0
+-1115 1252 -1253 0
+-1115 -1252 1253 0
+1115 1252 -1254 0
+1115 -1252 1254 0
+-1237 1254 -1255 0
+-1237 -1254 1255 0
+1237 1254 -1256 0
+1237 -1254 1256 0
+-100 -1250 0
+-90 -1250 0
+-85 -1250 0
+-141 -1250 0
+-350 -1250 0
+-452 -1250 0
+458 -1250 0
+149 -1250 0
+148 -1250 0
+-1007 -1248 0
+-30 -1248 0
+-57 -1248 0
+-31 -1248 0
+1240 -1246 0
+1233 -1246 0
+1231 -1232 0
+1232 -1233 1240 0
+-1232 -1240 0
+-1007 1240 -1241 0
+-1007 -1240 1241 0
+-133 1007 1240 0
+133 1007 -1240 0
+-1115 1241 -1242 0
+-1115 -1241 1242 0
+1115 1241 -1243 0
+1115 -1241 1243 0
+-1237 1243 -1244 0
+-1237 -1243 1244 0
+1237 1243 -1245 0
+1237 -1243 1245 0
+-1232 1233 0
+-1007 1233 -1234 0
+-1007 -1233 1234 0
+-135 1007 1233 0
+135 1007 -1233 0
+-1115 1234 -1235 0
+-1115 -1234 1235 0
+1115 1234 -1236 0
+1115 -1234 1236 0
+1236 -1237 -1238 0
+-1236 -1237 1238 0
+1236 1237 -1239 0
+-1236 1237 1239 0
+31 -57 -1089 1237 0
+1089 -1237 0
+57 -1237 0
+-31 -1237 0
+-1225 1226 0
+-101 1226 -1227 0
+-101 -1226 1227 0
+101 1226 -1228 0
+101 -1226 1228 0
+-13 1228 -1229 0
+-13 -1228 1229 0
+13 1228 -1230 0
+13 -1228 1230 0
+10 12 30 31 1230 0
+-30 -1230 0
+-31 -1230 0
+-10 -1230 0
+-12 -1230 0
+10 12 19 30 21 31 1229 0
+-30 -1229 0
+-31 -1229 0
+-19 -1229 0
+-10 -1229 0
+-21 -1229 0
+-12 -1229 0
+91 102 -972 961 1227 0
+-102 -1227 0
+-961 -1227 0
+972 -1227 0
+-91 -1227 0
+-1007 -1225 0
+-934 -1225 0
+-512 -1225 0
+1 -1004 0
+1004 -1005 -1117 -1209 0
+-1004 1209 0
+-1209 1210 1216 1215 1214 1213 1212 1211 1217 1219 0
+1209 -1219 0
+13 101 -526 512 809 -913 714 -1220 1219 0
+-1219 1220 0
+-741 1220 -1221 0
+-741 -1220 1221 0
+741 1220 -1222 0
+741 -1220 1222 0
+-5 7 529 30 83 764 -755 -751 13 -791 824 -65 1222 0
+-824 -1222 0
+791 -1222 0
+-529 -1222 0
+-30 -1222 0
+-83 -1222 0
+-764 -1222 0
+755 -1222 0
+751 -1222 0
+-13 -1222 0
+-7 -1222 0
+5 -1222 0
+65 -1222 0
+31 -57 1192 -1171 -1089 665 615 -1197 1206 -1065 1221 0
+-1206 -1221 0
+1197 -1221 0
+-1192 -1221 0
+1171 -1221 0
+1089 -1221 0
+-665 -1221 0
+-615 -1221 0
+57 -1221 0
+-31 -1221 0
+1065 -1221 0
+-809 -1219 0
+526 -1219 0
+-512 -1219 0
+-101 -1219 0
+913 -1219 0
+-714 -1219 0
+-13 -1219 0
+1209 -1217 0
+-925 1217 -1218 0
+-1217 1218 0
+-741 -1206 1218 0
+-741 1206 -1218 0
+741 -928 1218 0
+741 928 -1218 0
+925 -1217 0
+1209 -1216 0
+-5 7 -641 -825 529 741 -923 13 -653 -837 -65 1216 0
+837 -1216 0
+653 -1216 0
+641 -1216 0
+825 -1216 0
+-529 -1216 0
+-741 -1216 0
+923 -1216 0
+-13 -1216 0
+-7 -1216 0
+5 -1216 0
+65 -1216 0
+1209 -1215 0
+7 13 -318 -305 741 916 912 -331 -747 -36 -35 1215 0
+747 -1215 0
+331 -1215 0
+318 -1215 0
+305 -1215 0
+-741 -1215 0
+-916 -1215 0
+-912 -1215 0
+-13 -1215 0
+-7 -1215 0
+36 -1215 0
+35 -1215 0
+1209 -1214 0
+12 -293 298 741 757 296 294 916 912 299 738 1214 0
+-738 -1214 0
+-299 -1214 0
+-298 -1214 0
+-741 -1214 0
+-757 -1214 0
+-296 -1214 0
+-294 -1214 0
+-916 -1214 0
+-912 -1214 0
+293 -1214 0
+-12 -1214 0
+1209 -1213 0
+7 -295 298 741 757 296 916 912 299 738 1213 0
+-738 -1213 0
+-299 -1213 0
+-298 -1213 0
+-741 -1213 0
+-757 -1213 0
+-296 -1213 0
+-916 -1213 0
+-912 -1213 0
+295 -1213 0
+-7 -1213 0
+1209 -1212 0
+7 21 298 741 757 916 912 299 -297 738 1212 0
+-738 -1212 0
+-299 -1212 0
+-298 -1212 0
+-741 -1212 0
+-757 -1212 0
+-916 -1212 0
+-912 -1212 0
+-21 -1212 0
+297 -1212 0
+-7 -1212 0
+1209 -1211 0
+-291 292 298 741 757 296 294 299 916 912 738 1211 0
+-738 -1211 0
+-299 -1211 0
+-298 -1211 0
+-741 -1211 0
+-757 -1211 0
+-296 -1211 0
+-294 -1211 0
+-292 -1211 0
+-916 -1211 0
+-912 -1211 0
+291 -1211 0
+1209 -1210 0
+291 292 298 741 757 296 294 299 738 916 912 1210 0
+-738 -1210 0
+-299 -1210 0
+-298 -1210 0
+-741 -1210 0
+-757 -1210 0
+-296 -1210 0
+-294 -1210 0
+-292 -1210 0
+-291 -1210 0
+-916 -1210 0
+-912 -1210 0
+-1004 1117 0
+-1117 1118 1168 1157 1135 1134 1133 1132 1131 1130 1129 1128 1127 1126 1125 1124 1123 1122 1121 1120 1194 1208 0
+1117 -1208 0
+845 847 864 863 862 861 856 855 853 851 849 866 1119 1208 0
+-1119 -1208 0
+-866 -1208 0
+-864 -1208 0
+-863 -1208 0
+-862 -1208 0
+-861 -1208 0
+-856 -1208 0
+-855 -1208 0
+-853 -1208 0
+-851 -1208 0
+-849 -1208 0
+-847 -1208 0
+-845 -1208 0
+1117 -1194 0
+13 101 -612 -606 -602 -526 512 809 714 -1195 1194 0
+-1194 1195 0
+-1119 1195 -1196 0
+-1119 -1195 1196 0
+1119 1195 -1207 0
+1119 -1195 1207 0
+-5 -6 -791 529 30 83 764 -755 -751 13 7 -601 824 -22 1207 0
+-824 -1207 0
+601 -1207 0
+791 -1207 0
+-529 -1207 0
+-30 -1207 0
+-83 -1207 0
+-764 -1207 0
+755 -1207 0
+751 -1207 0
+-13 -1207 0
+-7 -1207 0
+6 -1207 0
+5 -1207 0
+22 -1207 0
+31 -57 1192 -1171 -1089 665 615 -1197 1206 -1065 115 -117 -118 1196 0
+-1196 -1206 0
+30 31 366 352 -1160 57 -1138 -1037 -1011 1206 0
+1160 -1206 0
+1138 -1206 0
+-366 -1206 0
+-352 -1206 0
+-30 -1206 0
+-57 -1206 0
+-31 -1206 0
+1037 -1206 0
+1011 -1206 0
+-1196 1197 0
+-1197 1198 1203 1202 1201 1200 1199 1204 1205 0
+1197 -1205 0
+13 101 418 -107 432 -928 -739 1205 0
+739 -1205 0
+-432 -1205 0
+-418 -1205 0
+107 -1205 0
+-101 -1205 0
+928 -1205 0
+-13 -1205 0
+1197 -1204 0
+-5 7 -653 -641 -825 529 13 -837 -749 -65 1204 0
+749 -1204 0
+837 -1204 0
+653 -1204 0
+641 -1204 0
+825 -1204 0
+-529 -1204 0
+-13 -1204 0
+-7 -1204 0
+5 -1204 0
+65 -1204 0
+1197 -1203 0
+7 13 -318 -305 916 -331 -747 -36 -35 1203 0
+747 -1203 0
+331 -1203 0
+318 -1203 0
+305 -1203 0
+-916 -1203 0
+-13 -1203 0
+-7 -1203 0
+36 -1203 0
+35 -1203 0
+1197 -1202 0
+12 -293 298 757 296 294 916 299 738 1202 0
+-738 -1202 0
+-299 -1202 0
+-298 -1202 0
+-757 -1202 0
+-296 -1202 0
+-294 -1202 0
+-916 -1202 0
+293 -1202 0
+-12 -1202 0
+1197 -1201 0
+7 -295 298 757 296 916 299 738 1201 0
+-738 -1201 0
+-299 -1201 0
+-298 -1201 0
+-757 -1201 0
+-296 -1201 0
+-916 -1201 0
+295 -1201 0
+-7 -1201 0
+1197 -1200 0
+7 21 298 757 916 299 -297 738 1200 0
+-738 -1200 0
+-299 -1200 0
+-298 -1200 0
+-757 -1200 0
+-916 -1200 0
+-21 -1200 0
+297 -1200 0
+-7 -1200 0
+1197 -1199 0
+-291 292 298 757 296 294 299 916 738 1199 0
+-738 -1199 0
+-299 -1199 0
+-298 -1199 0
+-757 -1199 0
+-296 -1199 0
+-294 -1199 0
+-292 -1199 0
+-916 -1199 0
+291 -1199 0
+1197 -1198 0
+291 292 298 757 296 294 299 738 916 1198 0
+-738 -1198 0
+-299 -1198 0
+-298 -1198 0
+-757 -1198 0
+-296 -1198 0
+-294 -1198 0
+-292 -1198 0
+-291 -1198 0
+-916 -1198 0
+-1192 -1196 0
+1171 -1196 0
+1089 -1196 0
+-665 -1196 0
+-615 -1196 0
+57 -1196 0
+-31 -1196 0
+1065 -1196 0
+-115 -1196 0
+117 -1196 0
+118 -1196 0
+-809 -1194 0
+612 -1194 0
+606 -1194 0
+602 -1194 0
+526 -1194 0
+-512 -1194 0
+-101 -1194 0
+-714 -1194 0
+-13 -1194 0
+1117 -1168 0
+13 101 615 612 -606 -602 -526 512 665 -1169 1168 0
+-1168 1169 0
+-1119 1169 -1170 0
+-1119 -1169 1170 0
+1119 1169 -1193 0
+1119 -1169 1193 0
+-5 -6 -537 529 30 83 477 -23 22 13 7 -601 640 1193 0
+-640 -1193 0
+601 -1193 0
+537 -1193 0
+-529 -1193 0
+-30 -1193 0
+-83 -1193 0
+-477 -1193 0
+23 -1193 0
+-22 -1193 0
+-13 -1193 0
+-7 -1193 0
+6 -1193 0
+5 -1193 0
+31 -57 -1089 -1171 1192 288 1170 0
+-1170 -1192 0
+30 31 57 -1138 -1037 1192 0
+1138 -1192 0
+-30 -1192 0
+-57 -1192 0
+-31 -1192 0
+1037 -1192 0
+-1170 1171 0
+-1171 1172 1189 1188 1187 1186 1185 1184 1183 1182 1181 1180 1179 1178 1177 1176 1175 1174 1173 1190 1191 0
+1171 -1191 0
+31 -57 457 453 100 90 85 141 350 452 461 -129 1036 1020 1019 1017 1016 1015 1014 1013 118 117 115 1191 0
+129 -1191 0
+-461 -1191 0
+-457 -1191 0
+-453 -1191 0
+-100 -1191 0
+-90 -1191 0
+-85 -1191 0
+-141 -1191 0
+-350 -1191 0
+-452 -1191 0
+57 -1191 0
+-31 -1191 0
+-1036 -1191 0
+-1020 -1191 0
+-1019 -1191 0
+-1017 -1191 0
+-1016 -1191 0
+-1015 -1191 0
+-1014 -1191 0
+-1013 -1191 0
+-118 -1191 0
+-117 -1191 0
+-115 -1191 0
+1171 -1190 0
+31 -57 129 130 1190 0
+-129 -1190 0
+57 -1190 0
+-31 -1190 0
+-130 -1190 0
+1171 -1189 0
+13 101 418 -286 -119 -112 -107 432 -1086 -129 118 117 115 1189 0
+129 -1189 0
+-432 -1189 0
+-418 -1189 0
+286 -1189 0
+119 -1189 0
+112 -1189 0
+107 -1189 0
+-101 -1189 0
+1086 -1189 0
+-13 -1189 0
+-118 -1189 0
+-117 -1189 0
+-115 -1189 0
+1171 -1188 0
+13 101 286 352 -119 -112 -107 366 -1083 -129 118 117 115 1188 0
+129 -1188 0
+-366 -1188 0
+-286 -1188 0
+-352 -1188 0
+119 -1188 0
+112 -1188 0
+107 -1188 0
+-101 -1188 0
+1083 -1188 0
+-13 -1188 0
+-118 -1188 0
+-117 -1188 0
+-115 -1188 0
+1171 -1187 0
+12 85 90 100 141 350 -347 -160 1017 1016 1015 1014 -203 118 117 115 -129 -156 1187 0
+129 -1187 0
+-100 -1187 0
+-90 -1187 0
+-85 -1187 0
+-141 -1187 0
+-350 -1187 0
+347 -1187 0
+160 -1187 0
+-1017 -1187 0
+-1016 -1187 0
+-1015 -1187 0
+-1014 -1187 0
+203 -1187 0
+-118 -1187 0
+-117 -1187 0
+-115 -1187 0
+-12 -1187 0
+156 -1187 0
+1171 -1186 0
+7 -51 90 85 141 -137 -138 1017 1016 1015 118 117 115 -129 -52 100 1186 0
+129 -1186 0
+-100 -1186 0
+-90 -1186 0
+-85 -1186 0
+-141 -1186 0
+137 -1186 0
+138 -1186 0
+-1017 -1186 0
+-1016 -1186 0
+-1015 -1186 0
+-118 -1186 0
+-117 -1186 0
+-115 -1186 0
+-7 -1186 0
+52 -1186 0
+51 -1186 0
+1171 -1185 0
+7 21 90 85 -29 -81 1017 1016 100 118 117 115 -129 -26 -27 1185 0
+129 -1185 0
+-100 -1185 0
+-90 -1185 0
+-85 -1185 0
+29 -1185 0
+81 -1185 0
+-1017 -1185 0
+-1016 -1185 0
+-21 -1185 0
+-118 -1185 0
+-117 -1185 0
+-115 -1185 0
+-7 -1185 0
+26 -1185 0
+27 -1185 0
+1171 -1184 0
+7 13 -318 -305 -144 -87 1017 -331 118 117 115 -129 -42 -36 -48 1184 0
+129 -1184 0
+331 -1184 0
+318 -1184 0
+305 -1184 0
+144 -1184 0
+87 -1184 0
+-1017 -1184 0
+-13 -1184 0
+-118 -1184 0
+-117 -1184 0
+-115 -1184 0
+-7 -1184 0
+42 -1184 0
+36 -1184 0
+48 -1184 0
+1171 -1183 0
+-5 -6 -129 -641 -825 529 -705 -96 13 118 117 115 7 -653 -837 -22 1183 0
+837 -1183 0
+653 -1183 0
+129 -1183 0
+641 -1183 0
+825 -1183 0
+-529 -1183 0
+705 -1183 0
+96 -1183 0
+-13 -1183 0
+-118 -1183 0
+-117 -1183 0
+-115 -1183 0
+-7 -1183 0
+6 -1183 0
+5 -1183 0
+22 -1183 0
+1171 -1182 0
+7 51 90 85 141 -137 -138 1017 1016 1015 100 118 117 115 -129 -52 1182 0
+129 -1182 0
+-100 -1182 0
+-90 -1182 0
+-85 -1182 0
+-141 -1182 0
+137 -1182 0
+138 -1182 0
+-1017 -1182 0
+-1016 -1182 0
+-1015 -1182 0
+-51 -1182 0
+-118 -1182 0
+-117 -1182 0
+-115 -1182 0
+-7 -1182 0
+52 -1182 0
+1171 -1181 0
+7 21 90 85 -29 -81 1017 1016 27 100 118 117 115 -129 -26 1181 0
+129 -1181 0
+-100 -1181 0
+-90 -1181 0
+-85 -1181 0
+29 -1181 0
+81 -1181 0
+-1017 -1181 0
+-1016 -1181 0
+-27 -1181 0
+-21 -1181 0
+-118 -1181 0
+-117 -1181 0
+-115 -1181 0
+-7 -1181 0
+26 -1181 0
+1171 -1180 0
+7 13 -318 -474 -87 1017 48 -331 118 117 115 -129 -42 -36 1180 0
+129 -1180 0
+331 -1180 0
+318 -1180 0
+474 -1180 0
+87 -1180 0
+-1017 -1180 0
+-48 -1180 0
+-13 -1180 0
+-118 -1180 0
+-117 -1180 0
+-115 -1180 0
+-7 -1180 0
+42 -1180 0
+36 -1180 0
+1171 -1179 0
+-5 -6 -641 529 -699 -96 22 13 118 117 115 7 -129 -653 1179 0
+653 -1179 0
+129 -1179 0
+641 -1179 0
+-529 -1179 0
+699 -1179 0
+96 -1179 0
+-22 -1179 0
+-13 -1179 0
+-118 -1179 0
+-117 -1179 0
+-115 -1179 0
+-7 -1179 0
+6 -1179 0
+5 -1179 0
+1171 -1178 0
+12 85 90 100 141 350 -347 -160 1017 1016 1015 1014 203 118 117 115 -129 -156 1178 0
+129 -1178 0
+-100 -1178 0
+-90 -1178 0
+-85 -1178 0
+-141 -1178 0
+-350 -1178 0
+347 -1178 0
+160 -1178 0
+-1017 -1178 0
+-1016 -1178 0
+-1015 -1178 0
+-1014 -1178 0
+-203 -1178 0
+-118 -1178 0
+-117 -1178 0
+-115 -1178 0
+-12 -1178 0
+156 -1178 0
+1171 -1177 0
+85 90 100 -129 141 350 452 -458 -154 1017 1016 1015 1014 1013 149 118 117 115 -148 1177 0
+129 -1177 0
+-100 -1177 0
+-90 -1177 0
+-85 -1177 0
+-141 -1177 0
+-350 -1177 0
+-452 -1177 0
+458 -1177 0
+154 -1177 0
+-1017 -1177 0
+-1016 -1177 0
+-1015 -1177 0
+-1014 -1177 0
+-1013 -1177 0
+-149 -1177 0
+-118 -1177 0
+-117 -1177 0
+-115 -1177 0
+148 -1177 0
+1171 -1176 0
+85 90 100 457 -129 141 350 452 -454 -192 1020 1017 1016 1015 1014 1013 118 117 115 -188 -199 1176 0
+129 -1176 0
+-457 -1176 0
+-100 -1176 0
+-90 -1176 0
+-85 -1176 0
+-141 -1176 0
+-350 -1176 0
+-452 -1176 0
+454 -1176 0
+192 -1176 0
+-1020 -1176 0
+-1017 -1176 0
+-1016 -1176 0
+-1015 -1176 0
+-1014 -1176 0
+-1013 -1176 0
+-118 -1176 0
+-117 -1176 0
+-115 -1176 0
+188 -1176 0
+199 -1176 0
+1171 -1175 0
+85 90 100 457 -129 141 350 452 -454 -192 1020 1017 1016 1015 1014 1013 199 118 117 115 -188 1175 0
+129 -1175 0
+-457 -1175 0
+-100 -1175 0
+-90 -1175 0
+-85 -1175 0
+-141 -1175 0
+-350 -1175 0
+-452 -1175 0
+454 -1175 0
+192 -1175 0
+-1020 -1175 0
+-1017 -1175 0
+-1016 -1175 0
+-1015 -1175 0
+-1014 -1175 0
+-1013 -1175 0
+-199 -1175 0
+-118 -1175 0
+-117 -1175 0
+-115 -1175 0
+188 -1175 0
+1171 -1174 0
+85 90 453 100 457 -129 141 350 452 -462 -186 1020 1019 1017 1016 1015 1014 1013 118 117 115 -180 -181 1174 0
+129 -1174 0
+-457 -1174 0
+-453 -1174 0
+-100 -1174 0
+-90 -1174 0
+-85 -1174 0
+-141 -1174 0
+-350 -1174 0
+-452 -1174 0
+462 -1174 0
+186 -1174 0
+-1020 -1174 0
+-1019 -1174 0
+-1017 -1174 0
+-1016 -1174 0
+-1015 -1174 0
+-1014 -1174 0
+-1013 -1174 0
+-118 -1174 0
+-117 -1174 0
+-115 -1174 0
+180 -1174 0
+181 -1174 0
+1171 -1173 0
+85 90 453 100 457 -129 141 350 452 -462 -186 1020 1019 1017 1016 1015 1014 1013 181 118 117 115 -180 1173 0
+129 -1173 0
+-457 -1173 0
+-453 -1173 0
+-100 -1173 0
+-90 -1173 0
+-85 -1173 0
+-141 -1173 0
+-350 -1173 0
+-452 -1173 0
+462 -1173 0
+186 -1173 0
+-1020 -1173 0
+-1019 -1173 0
+-1017 -1173 0
+-1016 -1173 0
+-1015 -1173 0
+-1014 -1173 0
+-1013 -1173 0
+-181 -1173 0
+-118 -1173 0
+-117 -1173 0
+-115 -1173 0
+180 -1173 0
+1171 -1172 0
+85 90 100 -129 141 350 452 -458 -154 1017 1016 1015 1014 1013 -149 118 117 115 -148 1172 0
+129 -1172 0
+-100 -1172 0
+-90 -1172 0
+-85 -1172 0
+-141 -1172 0
+-350 -1172 0
+-452 -1172 0
+458 -1172 0
+154 -1172 0
+-1017 -1172 0
+-1016 -1172 0
+-1015 -1172 0
+-1014 -1172 0
+-1013 -1172 0
+149 -1172 0
+-118 -1172 0
+-117 -1172 0
+-115 -1172 0
+148 -1172 0
+1089 -1170 0
+57 -1170 0
+-31 -1170 0
+-288 -1170 0
+-665 -1168 0
+-615 -1168 0
+-612 -1168 0
+606 -1168 0
+602 -1168 0
+526 -1168 0
+-512 -1168 0
+-101 -1168 0
+-13 -1168 0
+1117 -1157 0
+-904 1157 -1158 0
+-1157 1158 0
+-1119 1158 -1159 0
+-1119 -1158 1159 0
+-907 1119 1158 0
+907 1119 -1158 0
+30 31 366 352 -1160 57 -1138 -1037 -1011 115 -117 -118 1159 0
+-1159 1160 0
+-1160 1161 1165 1164 1163 1162 1166 1167 0
+1160 -1167 0
+-5 7 -641 -825 529 91 57 31 13 -653 -837 -65 1167 0
+837 -1167 0
+653 -1167 0
+641 -1167 0
+825 -1167 0
+-529 -1167 0
+-91 -1167 0
+-57 -1167 0
+-31 -1167 0
+-13 -1167 0
+-7 -1167 0
+5 -1167 0
+65 -1167 0
+1160 -1166 0
+7 13 -305 299 31 916 -318 -331 -36 -35 1166 0
+331 -1166 0
+318 -1166 0
+305 -1166 0
+-299 -1166 0
+-31 -1166 0
+-916 -1166 0
+-13 -1166 0
+-7 -1166 0
+36 -1166 0
+35 -1166 0
+1160 -1165 0
+12 -293 757 296 294 916 298 299 1165 0
+-299 -1165 0
+-298 -1165 0
+-757 -1165 0
+-296 -1165 0
+-294 -1165 0
+-916 -1165 0
+293 -1165 0
+-12 -1165 0
+1160 -1164 0
+7 -295 757 296 916 298 299 1164 0
+-299 -1164 0
+-298 -1164 0
+-757 -1164 0
+-296 -1164 0
+-916 -1164 0
+295 -1164 0
+-7 -1164 0
+1160 -1163 0
+7 21 757 916 298 -297 299 1163 0
+-299 -1163 0
+-298 -1163 0
+-757 -1163 0
+-916 -1163 0
+-21 -1163 0
+297 -1163 0
+-7 -1163 0
+1160 -1162 0
+-291 292 757 296 294 298 916 299 1162 0
+-299 -1162 0
+-298 -1162 0
+-757 -1162 0
+-296 -1162 0
+-294 -1162 0
+-292 -1162 0
+-916 -1162 0
+291 -1162 0
+1160 -1161 0
+291 292 757 296 294 298 299 916 1161 0
+-299 -1161 0
+-298 -1161 0
+-757 -1161 0
+-296 -1161 0
+-294 -1161 0
+-292 -1161 0
+-291 -1161 0
+-916 -1161 0
+1138 -1159 0
+-366 -1159 0
+-352 -1159 0
+-30 -1159 0
+-57 -1159 0
+-31 -1159 0
+1037 -1159 0
+1011 -1159 0
+-115 -1159 0
+117 -1159 0
+118 -1159 0
+904 -1157 0
+1117 -1135 0
+-897 1135 -1136 0
+-1135 1136 0
+-1119 1136 -1137 0
+-1119 -1136 1137 0
+-900 1119 1136 0
+900 1119 -1136 0
+30 31 57 -1138 288 -1037 1137 0
+-1137 1138 0
+-1138 1139 1154 1153 1152 1151 1150 1149 1148 1147 1146 1145 1144 1143 1142 1141 1140 1155 1156 0
+1138 -1156 0
+30 31 208 194 187 172 168 165 162 155 57 -273 1036 1020 1019 1017 1016 1015 1014 1013 118 117 115 1156 0
+273 -1156 0
+-30 -1156 0
+-208 -1156 0
+-194 -1156 0
+-187 -1156 0
+-172 -1156 0
+-168 -1156 0
+-165 -1156 0
+-162 -1156 0
+-155 -1156 0
+-57 -1156 0
+-31 -1156 0
+-1036 -1156 0
+-1020 -1156 0
+-1019 -1156 0
+-1017 -1156 0
+-1016 -1156 0
+-1015 -1156 0
+-1014 -1156 0
+-1013 -1156 0
+-118 -1156 0
+-117 -1156 0
+-115 -1156 0
+1138 -1155 0
+30 31 57 273 130 1155 0
+-273 -1155 0
+-30 -1155 0
+-57 -1155 0
+-31 -1155 0
+-130 -1155 0
+1138 -1154 0
+12 115 168 165 162 -157 -160 1017 1016 1015 1014 -203 118 117 172 -273 -156 1154 0
+273 -1154 0
+-172 -1154 0
+-168 -1154 0
+-165 -1154 0
+-162 -1154 0
+157 -1154 0
+160 -1154 0
+-1017 -1154 0
+-1016 -1154 0
+-1015 -1154 0
+-1014 -1154 0
+203 -1154 0
+-118 -1154 0
+-117 -1154 0
+-115 -1154 0
+-12 -1154 0
+156 -1154 0
+1138 -1153 0
+7 -51 168 165 -163 -138 1017 1016 1015 118 117 115 -273 -52 172 1153 0
+273 -1153 0
+-172 -1153 0
+-168 -1153 0
+-165 -1153 0
+163 -1153 0
+138 -1153 0
+-1017 -1153 0
+-1016 -1153 0
+-1015 -1153 0
+-118 -1153 0
+-117 -1153 0
+-115 -1153 0
+-7 -1153 0
+52 -1153 0
+51 -1153 0
+1138 -1152 0
+7 21 168 -166 -81 1017 1016 172 118 117 115 -273 -26 -27 1152 0
+273 -1152 0
+-172 -1152 0
+-168 -1152 0
+166 -1152 0
+81 -1152 0
+-1017 -1152 0
+-1016 -1152 0
+-21 -1152 0
+-118 -1152 0
+-117 -1152 0
+-115 -1152 0
+-7 -1152 0
+26 -1152 0
+27 -1152 0
+1138 -1151 0
+7 13 -305 -273 172 -169 -87 31 1017 -318 118 117 115 -331 -42 -36 -48 1151 0
+331 -1151 0
+318 -1151 0
+305 -1151 0
+273 -1151 0
+-172 -1151 0
+169 -1151 0
+87 -1151 0
+-31 -1151 0
+-1017 -1151 0
+-13 -1151 0
+-118 -1151 0
+-117 -1151 0
+-115 -1151 0
+-7 -1151 0
+42 -1151 0
+36 -1151 0
+48 -1151 0
+1138 -1150 0
+-5 -6 -641 -825 529 -273 -173 -96 91 57 31 13 118 117 115 7 -653 -837 -22 1150 0
+837 -1150 0
+653 -1150 0
+641 -1150 0
+825 -1150 0
+-529 -1150 0
+273 -1150 0
+173 -1150 0
+96 -1150 0
+-91 -1150 0
+-57 -1150 0
+-31 -1150 0
+-13 -1150 0
+-118 -1150 0
+-117 -1150 0
+-115 -1150 0
+-7 -1150 0
+6 -1150 0
+5 -1150 0
+22 -1150 0
+1138 -1149 0
+7 51 168 165 -163 -138 1017 1016 1015 172 118 117 115 -273 -52 1149 0
+273 -1149 0
+-172 -1149 0
+-168 -1149 0
+-165 -1149 0
+163 -1149 0
+138 -1149 0
+-1017 -1149 0
+-1016 -1149 0
+-1015 -1149 0
+-51 -1149 0
+-118 -1149 0
+-117 -1149 0
+-115 -1149 0
+-7 -1149 0
+52 -1149 0
+1138 -1148 0
+7 21 168 -166 -81 1017 1016 27 172 118 117 115 -273 -26 1148 0
+273 -1148 0
+-172 -1148 0
+-168 -1148 0
+166 -1148 0
+81 -1148 0
+-1017 -1148 0
+-1016 -1148 0
+-27 -1148 0
+-21 -1148 0
+-118 -1148 0
+-117 -1148 0
+-115 -1148 0
+-7 -1148 0
+26 -1148 0
+1138 -1147 0
+7 13 -273 172 -169 -87 31 1017 48 -318 118 117 115 -331 -42 -36 1147 0
+331 -1147 0
+318 -1147 0
+273 -1147 0
+-172 -1147 0
+169 -1147 0
+87 -1147 0
+-31 -1147 0
+-1017 -1147 0
+-48 -1147 0
+-13 -1147 0
+-118 -1147 0
+-117 -1147 0
+-115 -1147 0
+-7 -1147 0
+42 -1147 0
+36 -1147 0
+1138 -1146 0
+-5 -6 529 -273 -173 -96 91 57 31 22 13 118 117 115 7 -641 -653 1146 0
+653 -1146 0
+641 -1146 0
+-529 -1146 0
+273 -1146 0
+173 -1146 0
+96 -1146 0
+-91 -1146 0
+-57 -1146 0
+-31 -1146 0
+-22 -1146 0
+-13 -1146 0
+-118 -1146 0
+-117 -1146 0
+-115 -1146 0
+-7 -1146 0
+6 -1146 0
+5 -1146 0
+1138 -1145 0
+12 115 168 165 162 -157 -160 1017 1016 1015 1014 203 118 117 172 -273 -156 1145 0
+273 -1145 0
+-172 -1145 0
+-168 -1145 0
+-165 -1145 0
+-162 -1145 0
+157 -1145 0
+160 -1145 0
+-1017 -1145 0
+-1016 -1145 0
+-1015 -1145 0
+-1014 -1145 0
+-203 -1145 0
+-118 -1145 0
+-117 -1145 0
+-115 -1145 0
+-12 -1145 0
+156 -1145 0
+1138 -1144 0
+115 117 168 165 162 155 -151 -154 1017 1016 1015 1014 1013 149 118 172 -273 -148 1144 0
+273 -1144 0
+-172 -1144 0
+-168 -1144 0
+-165 -1144 0
+-162 -1144 0
+-155 -1144 0
+151 -1144 0
+154 -1144 0
+-1017 -1144 0
+-1016 -1144 0
+-1015 -1144 0
+-1014 -1144 0
+-1013 -1144 0
+-149 -1144 0
+-118 -1144 0
+-117 -1144 0
+-115 -1144 0
+148 -1144 0
+1138 -1143 0
+115 117 172 168 165 162 155 -189 -192 1020 1017 1016 1015 1014 1013 118 194 -273 -188 -199 1143 0
+273 -1143 0
+-194 -1143 0
+-172 -1143 0
+-168 -1143 0
+-165 -1143 0
+-162 -1143 0
+-155 -1143 0
+189 -1143 0
+192 -1143 0
+-1020 -1143 0
+-1017 -1143 0
+-1016 -1143 0
+-1015 -1143 0
+-1014 -1143 0
+-1013 -1143 0
+-118 -1143 0
+-117 -1143 0
+-115 -1143 0
+188 -1143 0
+199 -1143 0
+1138 -1142 0
+115 117 172 168 165 162 155 -189 -192 1020 1017 1016 1015 1014 1013 199 118 194 -273 -188 1142 0
+273 -1142 0
+-194 -1142 0
+-172 -1142 0
+-168 -1142 0
+-165 -1142 0
+-162 -1142 0
+-155 -1142 0
+189 -1142 0
+192 -1142 0
+-1020 -1142 0
+-1017 -1142 0
+-1016 -1142 0
+-1015 -1142 0
+-1014 -1142 0
+-1013 -1142 0
+-199 -1142 0
+-118 -1142 0
+-117 -1142 0
+-115 -1142 0
+188 -1142 0
+1138 -1141 0
+115 117 187 172 168 165 162 155 -183 -186 1020 1019 1017 1016 1015 1014 1013 118 194 -273 -180 -181 1141 0
+273 -1141 0
+-194 -1141 0
+-187 -1141 0
+-172 -1141 0
+-168 -1141 0
+-165 -1141 0
+-162 -1141 0
+-155 -1141 0
+183 -1141 0
+186 -1141 0
+-1020 -1141 0
+-1019 -1141 0
+-1017 -1141 0
+-1016 -1141 0
+-1015 -1141 0
+-1014 -1141 0
+-1013 -1141 0
+-118 -1141 0
+-117 -1141 0
+-115 -1141 0
+180 -1141 0
+181 -1141 0
+1138 -1140 0
+115 117 187 172 168 165 162 155 -183 -186 1020 1019 1017 1016 1015 1014 1013 181 118 194 -273 -180 1140 0
+273 -1140 0
+-194 -1140 0
+-187 -1140 0
+-172 -1140 0
+-168 -1140 0
+-165 -1140 0
+-162 -1140 0
+-155 -1140 0
+183 -1140 0
+186 -1140 0
+-1020 -1140 0
+-1019 -1140 0
+-1017 -1140 0
+-1016 -1140 0
+-1015 -1140 0
+-1014 -1140 0
+-1013 -1140 0
+-181 -1140 0
+-118 -1140 0
+-117 -1140 0
+-115 -1140 0
+180 -1140 0
+1138 -1139 0
+115 117 168 165 162 155 -151 -154 1017 1016 1015 1014 1013 -149 118 172 -273 -148 1139 0
+273 -1139 0
+-172 -1139 0
+-168 -1139 0
+-165 -1139 0
+-162 -1139 0
+-155 -1139 0
+151 -1139 0
+154 -1139 0
+-1017 -1139 0
+-1016 -1139 0
+-1015 -1139 0
+-1014 -1139 0
+-1013 -1139 0
+149 -1139 0
+-118 -1139 0
+-117 -1139 0
+-115 -1139 0
+148 -1139 0
+-30 -1137 0
+-57 -1137 0
+-31 -1137 0
+-288 -1137 0
+1037 -1137 0
+897 -1135 0
+1117 -1134 0
+12 -156 862 861 856 855 853 851 849 -848 -203 1119 863 1134 0
+-1119 -1134 0
+-863 -1134 0
+-862 -1134 0
+-861 -1134 0
+-856 -1134 0
+-855 -1134 0
+-853 -1134 0
+-851 -1134 0
+-849 -1134 0
+848 -1134 0
+203 -1134 0
+-12 -1134 0
+156 -1134 0
+1117 -1133 0
+7 -51 862 861 856 855 853 851 -850 1119 -52 863 1133 0
+-1119 -1133 0
+-863 -1133 0
+-862 -1133 0
+-861 -1133 0
+-856 -1133 0
+-855 -1133 0
+-853 -1133 0
+-851 -1133 0
+850 -1133 0
+-7 -1133 0
+52 -1133 0
+51 -1133 0
+1117 -1132 0
+7 21 862 861 856 855 853 -852 863 1119 -26 -27 1132 0
+-1119 -1132 0
+-863 -1132 0
+-862 -1132 0
+-861 -1132 0
+-856 -1132 0
+-855 -1132 0
+-853 -1132 0
+852 -1132 0
+-21 -1132 0
+-7 -1132 0
+26 -1132 0
+27 -1132 0
+1117 -1131 0
+7 13 863 861 -854 -331 -318 -305 -891 1119 -42 -36 -48 1131 0
+-1119 -1131 0
+891 -1131 0
+-863 -1131 0
+-861 -1131 0
+854 -1131 0
+331 -1131 0
+318 -1131 0
+305 -1131 0
+-13 -1131 0
+-7 -1131 0
+42 -1131 0
+36 -1131 0
+48 -1131 0
+1117 -1130 0
+-5 -6 -886 -653 -601 -641 -825 529 13 7 -837 1119 -22 1130 0
+-1119 -1130 0
+837 -1130 0
+886 -1130 0
+653 -1130 0
+601 -1130 0
+641 -1130 0
+825 -1130 0
+-529 -1130 0
+-13 -1130 0
+-7 -1130 0
+6 -1130 0
+5 -1130 0
+22 -1130 0
+1117 -1129 0
+7 51 862 861 856 855 853 851 -850 863 1119 -52 1129 0
+-1119 -1129 0
+-863 -1129 0
+-862 -1129 0
+-861 -1129 0
+-856 -1129 0
+-855 -1129 0
+-853 -1129 0
+-851 -1129 0
+850 -1129 0
+-51 -1129 0
+-7 -1129 0
+52 -1129 0
+1117 -1128 0
+7 21 862 861 856 855 853 -852 27 863 1119 -26 1128 0
+-1119 -1128 0
+-863 -1128 0
+-862 -1128 0
+-861 -1128 0
+-856 -1128 0
+-855 -1128 0
+-853 -1128 0
+852 -1128 0
+-27 -1128 0
+-21 -1128 0
+-7 -1128 0
+26 -1128 0
+1117 -1127 0
+7 13 863 861 -854 -331 -318 48 -881 1119 -42 -36 1127 0
+-1119 -1127 0
+881 -1127 0
+-863 -1127 0
+-861 -1127 0
+854 -1127 0
+331 -1127 0
+318 -1127 0
+-48 -1127 0
+-13 -1127 0
+-7 -1127 0
+42 -1127 0
+36 -1127 0
+1117 -1126 0
+-5 -6 -876 -601 -641 529 22 13 7 -653 1119 1126 0
+-1119 -1126 0
+653 -1126 0
+876 -1126 0
+601 -1126 0
+641 -1126 0
+-529 -1126 0
+-22 -1126 0
+-13 -1126 0
+-7 -1126 0
+6 -1126 0
+5 -1126 0
+1117 -1125 0
+12 -156 862 861 856 855 853 851 849 -848 203 1119 863 1125 0
+-1119 -1125 0
+-863 -1125 0
+-862 -1125 0
+-861 -1125 0
+-856 -1125 0
+-855 -1125 0
+-853 -1125 0
+-851 -1125 0
+-849 -1125 0
+848 -1125 0
+-203 -1125 0
+-12 -1125 0
+156 -1125 0
+1117 -1124 0
+-148 149 862 861 856 855 853 851 849 847 -867 863 1119 1124 0
+-1119 -1124 0
+-863 -1124 0
+-862 -1124 0
+-861 -1124 0
+-856 -1124 0
+-855 -1124 0
+-853 -1124 0
+-851 -1124 0
+-849 -1124 0
+-847 -1124 0
+867 -1124 0
+-149 -1124 0
+148 -1124 0
+1117 -1123 0
+-188 -199 863 862 861 856 855 853 851 849 847 -865 1119 866 1123 0
+-1119 -1123 0
+-866 -1123 0
+-863 -1123 0
+-862 -1123 0
+-861 -1123 0
+-856 -1123 0
+-855 -1123 0
+-853 -1123 0
+-851 -1123 0
+-849 -1123 0
+-847 -1123 0
+865 -1123 0
+188 -1123 0
+199 -1123 0
+1117 -1122 0
+-188 199 863 862 861 856 855 853 851 849 847 -865 866 1119 1122 0
+-1119 -1122 0
+-866 -1122 0
+-863 -1122 0
+-862 -1122 0
+-861 -1122 0
+-856 -1122 0
+-855 -1122 0
+-853 -1122 0
+-851 -1122 0
+-849 -1122 0
+-847 -1122 0
+865 -1122 0
+-199 -1122 0
+188 -1122 0
+1117 -1121 0
+-180 -181 864 863 862 861 856 855 853 851 849 847 -846 1119 866 1121 0
+-1119 -1121 0
+-866 -1121 0
+-864 -1121 0
+-863 -1121 0
+-862 -1121 0
+-861 -1121 0
+-856 -1121 0
+-855 -1121 0
+-853 -1121 0
+-851 -1121 0
+-849 -1121 0
+-847 -1121 0
+846 -1121 0
+180 -1121 0
+181 -1121 0
+1117 -1120 0
+-180 181 864 863 862 861 856 855 853 851 849 847 -846 866 1119 1120 0
+-1119 -1120 0
+-866 -1120 0
+-864 -1120 0
+-863 -1120 0
+-862 -1120 0
+-861 -1120 0
+-856 -1120 0
+-855 -1120 0
+-853 -1120 0
+-851 -1120 0
+-849 -1120 0
+-847 -1120 0
+846 -1120 0
+-181 -1120 0
+180 -1120 0
+1117 -1118 0
+-148 -149 862 861 856 855 853 851 849 847 -867 863 1119 1118 0
+-1118 -1119 0
+115 -116 -609 1119 0
+609 -1119 0
+116 -1119 0
+-115 -1119 0
+-863 -1118 0
+-862 -1118 0
+-861 -1118 0
+-856 -1118 0
+-855 -1118 0
+-853 -1118 0
+-851 -1118 0
+-849 -1118 0
+-847 -1118 0
+867 -1118 0
+149 -1118 0
+148 -1118 0
+-1004 1005 0
+-1005 1006 1114 1116 0
+1005 -1116 0
+30 31 -1007 57 -987 -1037 1116 0
+1007 -1116 0
+987 -1116 0
+-30 -1116 0
+-57 -1116 0
+-31 -1116 0
+1037 -1116 0
+1005 -1114 0
+31 -57 -1089 984 983 -934 -1007 1115 1114 0
+-1114 -1115 0
+30 31 57 -1037 1115 0
+-30 -1115 0
+-57 -1115 0
+-31 -1115 0
+1037 -1115 0
+1007 -1114 0
+1089 -1114 0
+-984 -1114 0
+-983 -1114 0
+934 -1114 0
+57 -1114 0
+-31 -1114 0
+1005 -1006 0
+512 934 -980 1007 1006 0
+-1006 -1007 0
+516 -1007 1008 0
+1007 -1008 0
+-115 -117 -1009 1008 0
+-1008 1009 0
+-525 1009 -1010 0
+525 -1009 -1010 0
+1009 1010 -1063 0
+-1009 1010 1063 0
+-947 1063 -1064 0
+947 -1063 -1064 0
+1063 1064 -1113 0
+-1063 1064 1113 0
+31 -57 -1089 -1065 1064 0
+-1064 1089 0
+-1089 1090 1106 1105 1104 1103 1102 1101 1100 1099 1098 1097 1096 1095 1094 1093 1092 1091 1107 1110 0
+1089 -1110 0
+13 101 418 -286 -563 -112 -107 432 -1111 1110 0
+-1110 1111 0
+-908 -1043 1111 0
+908 -1043 -1111 0
+1043 1111 -1112 0
+1043 -1111 1112 0
+7 13 -419 -289 30 83 -234 -447 450 -42 -36 -48 1112 0
+-450 -1112 0
+447 -1112 0
+419 -1112 0
+289 -1112 0
+-30 -1112 0
+-83 -1112 0
+234 -1112 0
+-13 -1112 0
+-7 -1112 0
+42 -1112 0
+36 -1112 0
+48 -1112 0
+-432 -1110 0
+-418 -1110 0
+286 -1110 0
+563 -1110 0
+112 -1110 0
+107 -1110 0
+-101 -1110 0
+-13 -1110 0
+1089 -1107 0
+13 101 352 -563 -112 -107 286 -1108 366 1107 0
+-366 -1107 0
+-286 -1107 0
+-352 -1107 0
+563 -1107 0
+112 -1107 0
+107 -1107 0
+-101 -1107 0
+-1107 1108 0
+-901 -1043 1108 0
+901 -1043 -1108 0
+1043 1108 -1109 0
+1043 -1108 1109 0
+7 13 -353 30 83 -234 48 -403 416 -42 -36 1109 0
+-416 -1109 0
+403 -1109 0
+353 -1109 0
+-30 -1109 0
+-83 -1109 0
+234 -1109 0
+-48 -1109 0
+-13 -1109 0
+-7 -1109 0
+42 -1109 0
+36 -1109 0
+-13 -1107 0
+1089 -1106 0
+12 -156 554 550 546 -543 -221 1043 1042 1041 1040 -203 562 558 1106 0
+-562 -1106 0
+-558 -1106 0
+-554 -1106 0
+-550 -1106 0
+-546 -1106 0
+543 -1106 0
+221 -1106 0
+-1043 -1106 0
+-1042 -1106 0
+-1041 -1106 0
+-1040 -1106 0
+203 -1106 0
+-12 -1106 0
+156 -1106 0
+1089 -1105 0
+7 -51 554 550 -547 -226 1043 1042 1041 562 -52 558 1105 0
+-562 -1105 0
+-558 -1105 0
+-554 -1105 0
+-550 -1105 0
+547 -1105 0
+226 -1105 0
+-1043 -1105 0
+-1042 -1105 0
+-1041 -1105 0
+-7 -1105 0
+52 -1105 0
+51 -1105 0
+1089 -1104 0
+7 21 554 -551 -230 1043 1042 558 562 -26 -27 1104 0
+-562 -1104 0
+-558 -1104 0
+-554 -1104 0
+551 -1104 0
+230 -1104 0
+-1043 -1104 0
+-1042 -1104 0
+-21 -1104 0
+-7 -1104 0
+26 -1104 0
+27 -1104 0
+1089 -1103 0
+7 13 -305 -594 -234 1043 -318 -331 -42 -36 -48 1103 0
+331 -1103 0
+318 -1103 0
+305 -1103 0
+594 -1103 0
+234 -1103 0
+-1043 -1103 0
+-13 -1103 0
+-7 -1103 0
+42 -1103 0
+36 -1103 0
+48 -1103 0
+1089 -1102 0
+-5 -6 -641 -825 529 -683 -240 13 7 -653 -837 -22 1102 0
+837 -1102 0
+653 -1102 0
+641 -1102 0
+825 -1102 0
+-529 -1102 0
+683 -1102 0
+240 -1102 0
+-13 -1102 0
+-7 -1102 0
+6 -1102 0
+5 -1102 0
+22 -1102 0
+1089 -1101 0
+7 51 554 550 -547 -226 1043 1042 1041 558 562 -52 1101 0
+-562 -1101 0
+-558 -1101 0
+-554 -1101 0
+-550 -1101 0
+547 -1101 0
+226 -1101 0
+-1043 -1101 0
+-1042 -1101 0
+-1041 -1101 0
+-51 -1101 0
+-7 -1101 0
+52 -1101 0
+1089 -1100 0
+7 21 554 -551 -230 1043 1042 27 558 562 -26 1100 0
+-562 -1100 0
+-558 -1100 0
+-554 -1100 0
+551 -1100 0
+230 -1100 0
+-1043 -1100 0
+-1042 -1100 0
+-27 -1100 0
+-21 -1100 0
+-7 -1100 0
+26 -1100 0
+1089 -1099 0
+7 13 -589 -234 1043 48 -318 -331 -42 -36 1099 0
+331 -1099 0
+318 -1099 0
+589 -1099 0
+234 -1099 0
+-1043 -1099 0
+-48 -1099 0
+-13 -1099 0
+-7 -1099 0
+42 -1099 0
+36 -1099 0
+1089 -1098 0
+-5 -6 529 -676 -240 22 13 7 -641 -653 1098 0
+653 -1098 0
+641 -1098 0
+-529 -1098 0
+676 -1098 0
+240 -1098 0
+-22 -1098 0
+-13 -1098 0
+-7 -1098 0
+6 -1098 0
+5 -1098 0
+1089 -1097 0
+12 -156 554 550 546 -543 -221 1043 1042 1041 1040 203 562 558 1097 0
+-562 -1097 0
+-558 -1097 0
+-554 -1097 0
+-550 -1097 0
+-546 -1097 0
+543 -1097 0
+221 -1097 0
+-1043 -1097 0
+-1042 -1097 0
+-1041 -1097 0
+-1040 -1097 0
+-203 -1097 0
+-12 -1097 0
+156 -1097 0
+1089 -1096 0
+-148 149 554 550 546 542 -539 -216 1043 1042 1041 1040 1039 558 562 1096 0
+-562 -1096 0
+-558 -1096 0
+-554 -1096 0
+-550 -1096 0
+-546 -1096 0
+-542 -1096 0
+539 -1096 0
+216 -1096 0
+-1043 -1096 0
+-1042 -1096 0
+-1041 -1096 0
+-1040 -1096 0
+-1039 -1096 0
+-149 -1096 0
+148 -1096 0
+1089 -1095 0
+-188 -199 558 554 550 546 542 -578 -256 1047 1043 1042 1041 1040 1039 581 562 1095 0
+-581 -1095 0
+-562 -1095 0
+-558 -1095 0
+-554 -1095 0
+-550 -1095 0
+-546 -1095 0
+-542 -1095 0
+578 -1095 0
+256 -1095 0
+-1047 -1095 0
+-1043 -1095 0
+-1042 -1095 0
+-1041 -1095 0
+-1040 -1095 0
+-1039 -1095 0
+188 -1095 0
+199 -1095 0
+1089 -1094 0
+-188 199 558 554 550 546 542 -578 -256 1047 1043 1042 1041 1040 1039 562 581 1094 0
+-581 -1094 0
+-562 -1094 0
+-558 -1094 0
+-554 -1094 0
+-550 -1094 0
+-546 -1094 0
+-542 -1094 0
+578 -1094 0
+256 -1094 0
+-1047 -1094 0
+-1043 -1094 0
+-1042 -1094 0
+-1041 -1094 0
+-1040 -1094 0
+-1039 -1094 0
+-199 -1094 0
+188 -1094 0
+1089 -1093 0
+-180 -181 562 558 554 550 546 542 -574 -250 1047 1046 1043 1042 1041 1040 1039 581 577 1093 0
+-581 -1093 0
+-577 -1093 0
+-562 -1093 0
+-558 -1093 0
+-554 -1093 0
+-550 -1093 0
+-546 -1093 0
+-542 -1093 0
+574 -1093 0
+250 -1093 0
+-1047 -1093 0
+-1046 -1093 0
+-1043 -1093 0
+-1042 -1093 0
+-1041 -1093 0
+-1040 -1093 0
+-1039 -1093 0
+180 -1093 0
+181 -1093 0
+1089 -1092 0
+-180 181 562 558 554 550 546 542 -574 -250 1047 1046 1043 1042 1041 1040 1039 577 581 1092 0
+-581 -1092 0
+-577 -1092 0
+-562 -1092 0
+-558 -1092 0
+-554 -1092 0
+-550 -1092 0
+-546 -1092 0
+-542 -1092 0
+574 -1092 0
+250 -1092 0
+-1047 -1092 0
+-1046 -1092 0
+-1043 -1092 0
+-1042 -1092 0
+-1041 -1092 0
+-1040 -1092 0
+-1039 -1092 0
+-181 -1092 0
+180 -1092 0
+1089 -1091 0
+31 -57 573 562 558 554 550 546 542 577 581 1047 1046 1045 1043 1042 1041 1040 1039 1091 0
+-581 -1091 0
+-577 -1091 0
+-573 -1091 0
+-562 -1091 0
+-558 -1091 0
+-554 -1091 0
+-550 -1091 0
+-546 -1091 0
+-542 -1091 0
+57 -1091 0
+-31 -1091 0
+-1047 -1091 0
+-1046 -1091 0
+-1045 -1091 0
+-1043 -1091 0
+-1042 -1091 0
+-1041 -1091 0
+-1040 -1091 0
+-1039 -1091 0
+1089 -1090 0
+-148 -149 554 550 546 542 -539 -216 1043 1042 1041 1040 1039 558 562 1090 0
+-562 -1090 0
+-558 -1090 0
+-554 -1090 0
+-550 -1090 0
+-546 -1090 0
+-542 -1090 0
+539 -1090 0
+216 -1090 0
+-1043 -1090 0
+-1042 -1090 0
+-1041 -1090 0
+-1040 -1090 0
+-1039 -1090 0
+149 -1090 0
+148 -1090 0
+57 -1064 0
+-31 -1064 0
+-1064 1065 0
+-1065 1066 1082 1081 1080 1079 1078 1077 1076 1075 1074 1073 1072 1071 1070 1069 1068 1067 1085 1088 0
+1065 -1088 0
+31 -57 453 100 90 85 141 350 452 457 461 1036 1020 1019 1017 1016 1015 1014 1013 1088 0
+-461 -1088 0
+-457 -1088 0
+-453 -1088 0
+-100 -1088 0
+-90 -1088 0
+-85 -1088 0
+-141 -1088 0
+-350 -1088 0
+-452 -1088 0
+57 -1088 0
+-31 -1088 0
+-1036 -1088 0
+-1020 -1088 0
+-1019 -1088 0
+-1017 -1088 0
+-1016 -1088 0
+-1015 -1088 0
+-1014 -1088 0
+-1013 -1088 0
+1065 -1085 0
+13 101 -286 -119 -112 -107 418 -1086 432 1085 0
+-432 -1085 0
+-418 -1085 0
+286 -1085 0
+119 -1085 0
+112 -1085 0
+107 -1085 0
+-101 -1085 0
+-1085 1086 0
+-908 -1017 1086 0
+908 -1017 -1086 0
+1017 1086 -1087 0
+1017 -1086 1087 0
+7 13 -419 -289 30 83 -87 -447 450 -42 -36 -48 1087 0
+-450 -1087 0
+447 -1087 0
+419 -1087 0
+289 -1087 0
+-30 -1087 0
+-83 -1087 0
+87 -1087 0
+-13 -1087 0
+-7 -1087 0
+42 -1087 0
+36 -1087 0
+48 -1087 0
+-13 -1085 0
+1065 -1082 0
+13 101 352 -119 -112 -107 286 -1083 366 1082 0
+-366 -1082 0
+-286 -1082 0
+-352 -1082 0
+119 -1082 0
+112 -1082 0
+107 -1082 0
+-101 -1082 0
+-1082 1083 0
+-901 -1017 1083 0
+901 -1017 -1083 0
+1017 1083 -1084 0
+1017 -1083 1084 0
+7 13 -353 30 83 -87 48 -403 416 -42 -36 1084 0
+-416 -1084 0
+403 -1084 0
+353 -1084 0
+-30 -1084 0
+-83 -1084 0
+87 -1084 0
+-48 -1084 0
+-13 -1084 0
+-7 -1084 0
+42 -1084 0
+36 -1084 0
+-13 -1082 0
+1065 -1081 0
+12 85 90 141 350 -347 -160 1017 1016 1015 1014 -203 100 -156 1081 0
+-100 -1081 0
+-90 -1081 0
+-85 -1081 0
+-141 -1081 0
+-350 -1081 0
+347 -1081 0
+160 -1081 0
+-1017 -1081 0
+-1016 -1081 0
+-1015 -1081 0
+-1014 -1081 0
+203 -1081 0
+-12 -1081 0
+156 -1081 0
+1065 -1080 0
+7 -51 85 141 -137 -138 1017 1016 1015 100 -52 90 1080 0
+-100 -1080 0
+-90 -1080 0
+-85 -1080 0
+-141 -1080 0
+137 -1080 0
+138 -1080 0
+-1017 -1080 0
+-1016 -1080 0
+-1015 -1080 0
+-7 -1080 0
+52 -1080 0
+51 -1080 0
+1065 -1079 0
+7 21 85 -29 -81 1017 1016 90 100 -26 -27 1079 0
+-100 -1079 0
+-90 -1079 0
+-85 -1079 0
+29 -1079 0
+81 -1079 0
+-1017 -1079 0
+-1016 -1079 0
+-21 -1079 0
+-7 -1079 0
+26 -1079 0
+27 -1079 0
+1065 -1078 0
+7 13 -305 -144 -87 1017 -318 -331 -42 -36 -48 1078 0
+331 -1078 0
+318 -1078 0
+305 -1078 0
+144 -1078 0
+87 -1078 0
+-1017 -1078 0
+-13 -1078 0
+-7 -1078 0
+42 -1078 0
+36 -1078 0
+48 -1078 0
+1065 -1077 0
+-5 -6 -641 -825 529 -705 -96 13 7 -653 -837 -22 1077 0
+837 -1077 0
+653 -1077 0
+641 -1077 0
+825 -1077 0
+-529 -1077 0
+705 -1077 0
+96 -1077 0
+-13 -1077 0
+-7 -1077 0
+6 -1077 0
+5 -1077 0
+22 -1077 0
+1065 -1076 0
+7 51 85 141 -137 -138 1017 1016 1015 90 100 -52 1076 0
+-100 -1076 0
+-90 -1076 0
+-85 -1076 0
+-141 -1076 0
+137 -1076 0
+138 -1076 0
+-1017 -1076 0
+-1016 -1076 0
+-1015 -1076 0
+-51 -1076 0
+-7 -1076 0
+52 -1076 0
+1065 -1075 0
+7 21 85 -29 -81 1017 1016 27 90 100 -26 1075 0
+-100 -1075 0
+-90 -1075 0
+-85 -1075 0
+29 -1075 0
+81 -1075 0
+-1017 -1075 0
+-1016 -1075 0
+-27 -1075 0
+-21 -1075 0
+-7 -1075 0
+26 -1075 0
+1065 -1074 0
+7 13 -474 -87 1017 48 -318 -331 -42 -36 1074 0
+331 -1074 0
+318 -1074 0
+474 -1074 0
+87 -1074 0
+-1017 -1074 0
+-48 -1074 0
+-13 -1074 0
+-7 -1074 0
+42 -1074 0
+36 -1074 0
+1065 -1073 0
+-5 -6 529 -699 -96 22 13 7 -641 -653 1073 0
+653 -1073 0
+641 -1073 0
+-529 -1073 0
+699 -1073 0
+96 -1073 0
+-22 -1073 0
+-13 -1073 0
+-7 -1073 0
+6 -1073 0
+5 -1073 0
+1065 -1072 0
+12 85 90 141 350 -347 -160 1017 1016 1015 1014 203 100 -156 1072 0
+-100 -1072 0
+-90 -1072 0
+-85 -1072 0
+-141 -1072 0
+-350 -1072 0
+347 -1072 0
+160 -1072 0
+-1017 -1072 0
+-1016 -1072 0
+-1015 -1072 0
+-1014 -1072 0
+-203 -1072 0
+-12 -1072 0
+156 -1072 0
+1065 -1071 0
+85 90 100 141 350 452 -458 -154 1017 1016 1015 1014 1013 149 -148 1071 0
+-100 -1071 0
+-90 -1071 0
+-85 -1071 0
+-141 -1071 0
+-350 -1071 0
+-452 -1071 0
+458 -1071 0
+154 -1071 0
+-1017 -1071 0
+-1016 -1071 0
+-1015 -1071 0
+-1014 -1071 0
+-1013 -1071 0
+-149 -1071 0
+148 -1071 0
+1065 -1070 0
+85 90 100 457 141 350 452 -454 -192 1020 1017 1016 1015 1014 1013 -188 -199 1070 0
+-457 -1070 0
+-100 -1070 0
+-90 -1070 0
+-85 -1070 0
+-141 -1070 0
+-350 -1070 0
+-452 -1070 0
+454 -1070 0
+192 -1070 0
+-1020 -1070 0
+-1017 -1070 0
+-1016 -1070 0
+-1015 -1070 0
+-1014 -1070 0
+-1013 -1070 0
+188 -1070 0
+199 -1070 0
+1065 -1069 0
+85 90 100 457 141 350 452 -454 -192 1020 1017 1016 1015 1014 1013 199 -188 1069 0
+-457 -1069 0
+-100 -1069 0
+-90 -1069 0
+-85 -1069 0
+-141 -1069 0
+-350 -1069 0
+-452 -1069 0
+454 -1069 0
+192 -1069 0
+-1020 -1069 0
+-1017 -1069 0
+-1016 -1069 0
+-1015 -1069 0
+-1014 -1069 0
+-1013 -1069 0
+-199 -1069 0
+188 -1069 0
+1065 -1068 0
+85 90 100 453 457 141 350 452 -462 -186 1020 1019 1017 1016 1015 1014 1013 -180 -181 1068 0
+-457 -1068 0
+-453 -1068 0
+-100 -1068 0
+-90 -1068 0
+-85 -1068 0
+-141 -1068 0
+-350 -1068 0
+-452 -1068 0
+462 -1068 0
+186 -1068 0
+-1020 -1068 0
+-1019 -1068 0
+-1017 -1068 0
+-1016 -1068 0
+-1015 -1068 0
+-1014 -1068 0
+-1013 -1068 0
+180 -1068 0
+181 -1068 0
+1065 -1067 0
+85 90 100 453 457 141 350 452 -462 -186 1020 1019 1017 1016 1015 1014 1013 181 -180 1067 0
+-457 -1067 0
+-453 -1067 0
+-100 -1067 0
+-90 -1067 0
+-85 -1067 0
+-141 -1067 0
+-350 -1067 0
+-452 -1067 0
+462 -1067 0
+186 -1067 0
+-1020 -1067 0
+-1019 -1067 0
+-1017 -1067 0
+-1016 -1067 0
+-1015 -1067 0
+-1014 -1067 0
+-1013 -1067 0
+-181 -1067 0
+180 -1067 0
+1065 -1066 0
+85 90 100 141 350 452 -458 -154 1017 1016 1015 1014 1013 -149 -148 1066 0
+-100 -1066 0
+-90 -1066 0
+-85 -1066 0
+-141 -1066 0
+-350 -1066 0
+-452 -1066 0
+458 -1066 0
+154 -1066 0
+-1017 -1066 0
+-1016 -1066 0
+-1015 -1066 0
+-1014 -1066 0
+-1013 -1066 0
+149 -1066 0
+148 -1066 0
+30 31 57 -1037 -1011 1010 0
+-30 -1010 0
+-57 -1010 0
+-31 -1010 0
+-1010 1037 0
+-1037 1038 1060 1059 1058 1057 1056 1055 1054 1053 1052 1051 1050 1049 1048 1044 1061 1062 0
+1037 -1062 0
+12 -156 227 223 -218 -221 1043 1042 1041 1040 -203 236 231 1062 0
+-236 -1062 0
+-231 -1062 0
+-227 -1062 0
+-223 -1062 0
+218 -1062 0
+221 -1062 0
+-1043 -1062 0
+-1042 -1062 0
+-1041 -1062 0
+-1040 -1062 0
+203 -1062 0
+-12 -1062 0
+156 -1062 0
+1037 -1061 0
+7 -51 227 -224 -226 1043 1042 1041 236 -52 231 1061 0
+-236 -1061 0
+-231 -1061 0
+-227 -1061 0
+224 -1061 0
+226 -1061 0
+-1043 -1061 0
+-1042 -1061 0
+-1041 -1061 0
+-7 -1061 0
+52 -1061 0
+51 -1061 0
+1037 -1060 0
+7 21 -228 -230 1043 1042 231 236 -26 -27 1060 0
+-236 -1060 0
+-231 -1060 0
+228 -1060 0
+230 -1060 0
+-1043 -1060 0
+-1042 -1060 0
+-21 -1060 0
+-7 -1060 0
+26 -1060 0
+27 -1060 0
+1037 -1059 0
+7 13 -305 236 -232 -234 31 1043 -318 -331 -42 -36 -48 1059 0
+331 -1059 0
+318 -1059 0
+305 -1059 0
+-236 -1059 0
+232 -1059 0
+234 -1059 0
+-31 -1059 0
+-1043 -1059 0
+-13 -1059 0
+-7 -1059 0
+42 -1059 0
+36 -1059 0
+48 -1059 0
+1037 -1058 0
+-5 -6 -641 -825 529 -237 -240 91 57 31 13 7 -653 -837 -22 1058 0
+837 -1058 0
+653 -1058 0
+641 -1058 0
+825 -1058 0
+-529 -1058 0
+237 -1058 0
+240 -1058 0
+-91 -1058 0
+-57 -1058 0
+-31 -1058 0
+-13 -1058 0
+-7 -1058 0
+6 -1058 0
+5 -1058 0
+22 -1058 0
+1037 -1057 0
+7 51 227 -224 -226 1043 1042 1041 231 236 -52 1057 0
+-236 -1057 0
+-231 -1057 0
+-227 -1057 0
+224 -1057 0
+226 -1057 0
+-1043 -1057 0
+-1042 -1057 0
+-1041 -1057 0
+-51 -1057 0
+-7 -1057 0
+52 -1057 0
+1037 -1056 0
+7 21 -228 -230 1043 1042 27 231 236 -26 1056 0
+-236 -1056 0
+-231 -1056 0
+228 -1056 0
+230 -1056 0
+-1043 -1056 0
+-1042 -1056 0
+-27 -1056 0
+-21 -1056 0
+-7 -1056 0
+26 -1056 0
+1037 -1055 0
+7 13 236 -232 -234 31 1043 48 -318 -331 -42 -36 1055 0
+331 -1055 0
+318 -1055 0
+-236 -1055 0
+232 -1055 0
+234 -1055 0
+-31 -1055 0
+-1043 -1055 0
+-48 -1055 0
+-13 -1055 0
+-7 -1055 0
+42 -1055 0
+36 -1055 0
+1037 -1054 0
+-5 -6 529 -237 -240 91 57 31 22 13 7 -641 -653 1054 0
+653 -1054 0
+641 -1054 0
+-529 -1054 0
+237 -1054 0
+240 -1054 0
+-91 -1054 0
+-57 -1054 0
+-31 -1054 0
+-22 -1054 0
+-13 -1054 0
+-7 -1054 0
+6 -1054 0
+5 -1054 0
+1037 -1053 0
+12 -156 227 223 -218 -221 1043 1042 1041 1040 203 236 231 1053 0
+-236 -1053 0
+-231 -1053 0
+-227 -1053 0
+-223 -1053 0
+218 -1053 0
+221 -1053 0
+-1043 -1053 0
+-1042 -1053 0
+-1041 -1053 0
+-1040 -1053 0
+-203 -1053 0
+-12 -1053 0
+156 -1053 0
+1037 -1052 0
+-148 149 227 223 217 -213 -216 1043 1042 1041 1040 1039 231 236 1052 0
+-236 -1052 0
+-231 -1052 0
+-227 -1052 0
+-223 -1052 0
+-217 -1052 0
+213 -1052 0
+216 -1052 0
+-1043 -1052 0
+-1042 -1052 0
+-1041 -1052 0
+-1040 -1052 0
+-1039 -1052 0
+-149 -1052 0
+148 -1052 0
+1037 -1051 0
+-188 -199 231 227 223 217 -253 -256 1047 1043 1042 1041 1040 1039 258 236 1051 0
+-258 -1051 0
+-236 -1051 0
+-231 -1051 0
+-227 -1051 0
+-223 -1051 0
+-217 -1051 0
+253 -1051 0
+256 -1051 0
+-1047 -1051 0
+-1043 -1051 0
+-1042 -1051 0
+-1041 -1051 0
+-1040 -1051 0
+-1039 -1051 0
+188 -1051 0
+199 -1051 0
+1037 -1050 0
+-188 199 231 227 223 217 -253 -256 1047 1043 1042 1041 1040 1039 236 258 1050 0
+-258 -1050 0
+-236 -1050 0
+-231 -1050 0
+-227 -1050 0
+-223 -1050 0
+-217 -1050 0
+253 -1050 0
+256 -1050 0
+-1047 -1050 0
+-1043 -1050 0
+-1042 -1050 0
+-1041 -1050 0
+-1040 -1050 0
+-1039 -1050 0
+-199 -1050 0
+188 -1050 0
+1037 -1049 0
+-180 -181 236 231 227 223 217 -247 -250 1047 1046 1043 1042 1041 1040 1039 258 252 1049 0
+-258 -1049 0
+-252 -1049 0
+-236 -1049 0
+-231 -1049 0
+-227 -1049 0
+-223 -1049 0
+-217 -1049 0
+247 -1049 0
+250 -1049 0
+-1047 -1049 0
+-1046 -1049 0
+-1043 -1049 0
+-1042 -1049 0
+-1041 -1049 0
+-1040 -1049 0
+-1039 -1049 0
+180 -1049 0
+181 -1049 0
+1037 -1048 0
+-180 181 236 231 227 223 217 -247 -250 1047 1046 1043 1042 1041 1040 1039 252 258 1048 0
+-258 -1048 0
+-252 -1048 0
+-236 -1048 0
+-231 -1048 0
+-227 -1048 0
+-223 -1048 0
+-217 -1048 0
+247 -1048 0
+250 -1048 0
+-1047 -1048 0
+-1046 -1048 0
+-1043 -1048 0
+-1042 -1048 0
+-1041 -1048 0
+-1040 -1048 0
+-1039 -1048 0
+-181 -1048 0
+180 -1048 0
+1037 -1044 0
+30 31 252 246 236 231 227 223 217 57 258 1047 1046 1045 1043 1042 1041 1040 1039 1044 0
+-30 -1044 0
+-258 -1044 0
+-252 -1044 0
+-246 -1044 0
+-236 -1044 0
+-231 -1044 0
+-227 -1044 0
+-223 -1044 0
+-217 -1044 0
+-57 -1044 0
+-31 -1044 0
+-1044 -1047 0
+-148 -216 1047 0
+216 -1047 0
+148 -1047 0
+-1044 -1046 0
+-188 -256 1046 0
+256 -1046 0
+188 -1046 0
+-1044 -1045 0
+-180 -250 1045 0
+250 -1045 0
+180 -1045 0
+-1043 -1044 0
+-1042 -1044 0
+-1041 -1044 0
+-1040 -1044 0
+-1039 -1044 0
+1037 -1038 0
+-148 -149 227 223 217 -213 -216 1043 1042 1041 1040 1039 231 236 1038 0
+-236 -1038 0
+-231 -1038 0
+-227 -1038 0
+-223 -1038 0
+-217 -1038 0
+213 -1038 0
+216 -1038 0
+-1038 -1043 0
+-5 -6 13 7 -240 529 1043 0
+-529 -1043 0
+240 -1043 0
+-13 -1043 0
+-7 -1043 0
+6 -1043 0
+5 -1043 0
+-1038 -1042 0
+7 13 -234 -42 -36 1042 0
+234 -1042 0
+-13 -1042 0
+-7 -1042 0
+42 -1042 0
+36 -1042 0
+-1038 -1041 0
+7 21 -230 -26 1041 0
+230 -1041 0
+-21 -1041 0
+-7 -1041 0
+26 -1041 0
+-1038 -1040 0
+7 -52 -226 1040 0
+226 -1040 0
+-7 -1040 0
+52 -1040 0
+-1038 -1039 0
+12 -156 -221 1039 0
+221 -1039 0
+-12 -1039 0
+156 -1039 0
+149 -1038 0
+148 -1038 0
+-1010 1011 0
+-1011 1012 1033 1032 1031 1030 1029 1028 1027 1026 1025 1024 1023 1022 1021 1018 1034 1035 0
+1011 -1035 0
+30 31 194 187 172 168 165 162 155 57 208 1036 1020 1019 1017 1016 1015 1014 1013 1035 0
+-30 -1035 0
+-208 -1035 0
+-194 -1035 0
+-187 -1035 0
+-172 -1035 0
+-168 -1035 0
+-165 -1035 0
+-162 -1035 0
+-155 -1035 0
+-57 -1035 0
+-31 -1035 0
+-1035 -1036 0
+-180 -186 1036 0
+186 -1036 0
+180 -1036 0
+-1020 -1035 0
+-1019 -1035 0
+-1017 -1035 0
+-1016 -1035 0
+-1015 -1035 0
+-1014 -1035 0
+-1013 -1035 0
+1011 -1034 0
+12 -156 165 162 -157 -160 1017 1016 1015 1014 -203 172 168 1034 0
+-172 -1034 0
+-168 -1034 0
+-165 -1034 0
+-162 -1034 0
+157 -1034 0
+160 -1034 0
+-1017 -1034 0
+-1016 -1034 0
+-1015 -1034 0
+-1014 -1034 0
+203 -1034 0
+-12 -1034 0
+156 -1034 0
+1011 -1033 0
+7 -51 165 -163 -138 1017 1016 1015 172 -52 168 1033 0
+-172 -1033 0
+-168 -1033 0
+-165 -1033 0
+163 -1033 0
+138 -1033 0
+-1017 -1033 0
+-1016 -1033 0
+-1015 -1033 0
+-7 -1033 0
+52 -1033 0
+51 -1033 0
+1011 -1032 0
+7 21 -166 -81 1017 1016 168 172 -26 -27 1032 0
+-172 -1032 0
+-168 -1032 0
+166 -1032 0
+81 -1032 0
+-1017 -1032 0
+-1016 -1032 0
+-21 -1032 0
+-7 -1032 0
+26 -1032 0
+27 -1032 0
+1011 -1031 0
+7 13 -305 172 -169 -87 31 1017 -318 -331 -42 -36 -48 1031 0
+331 -1031 0
+318 -1031 0
+305 -1031 0
+-172 -1031 0
+169 -1031 0
+87 -1031 0
+-31 -1031 0
+-1017 -1031 0
+-13 -1031 0
+-7 -1031 0
+42 -1031 0
+36 -1031 0
+48 -1031 0
+1011 -1030 0
+-5 -6 -641 -825 529 -173 -96 91 57 31 13 7 -653 -837 -22 1030 0
+837 -1030 0
+653 -1030 0
+641 -1030 0
+825 -1030 0
+-529 -1030 0
+173 -1030 0
+96 -1030 0
+-91 -1030 0
+-57 -1030 0
+-31 -1030 0
+-13 -1030 0
+-7 -1030 0
+6 -1030 0
+5 -1030 0
+22 -1030 0
+1011 -1029 0
+7 51 165 -163 -138 1017 1016 1015 168 172 -52 1029 0
+-172 -1029 0
+-168 -1029 0
+-165 -1029 0
+163 -1029 0
+138 -1029 0
+-1017 -1029 0
+-1016 -1029 0
+-1015 -1029 0
+-51 -1029 0
+-7 -1029 0
+52 -1029 0
+1011 -1028 0
+7 21 -166 -81 1017 1016 27 168 172 -26 1028 0
+-172 -1028 0
+-168 -1028 0
+166 -1028 0
+81 -1028 0
+-1017 -1028 0
+-1016 -1028 0
+-27 -1028 0
+-21 -1028 0
+-7 -1028 0
+26 -1028 0
+1011 -1027 0
+7 13 172 -169 -87 31 1017 48 -318 -331 -42 -36 1027 0
+331 -1027 0
+318 -1027 0
+-172 -1027 0
+169 -1027 0
+87 -1027 0
+-31 -1027 0
+-1017 -1027 0
+-48 -1027 0
+-13 -1027 0
+-7 -1027 0
+42 -1027 0
+36 -1027 0
+1011 -1026 0
+-5 -6 529 -173 -96 91 57 31 22 13 7 -641 -653 1026 0
+653 -1026 0
+641 -1026 0
+-529 -1026 0
+173 -1026 0
+96 -1026 0
+-91 -1026 0
+-57 -1026 0
+-31 -1026 0
+-22 -1026 0
+-13 -1026 0
+-7 -1026 0
+6 -1026 0
+5 -1026 0
+1011 -1025 0
+12 -156 165 162 -157 -160 1017 1016 1015 1014 203 172 168 1025 0
+-172 -1025 0
+-168 -1025 0
+-165 -1025 0
+-162 -1025 0
+157 -1025 0
+160 -1025 0
+-1017 -1025 0
+-1016 -1025 0
+-1015 -1025 0
+-1014 -1025 0
+-203 -1025 0
+-12 -1025 0
+156 -1025 0
+1011 -1024 0
+-148 149 165 162 155 -151 -154 1017 1016 1015 1014 1013 168 172 1024 0
+-172 -1024 0
+-168 -1024 0
+-165 -1024 0
+-162 -1024 0
+-155 -1024 0
+151 -1024 0
+154 -1024 0
+-1017 -1024 0
+-1016 -1024 0
+-1015 -1024 0
+-1014 -1024 0
+-1013 -1024 0
+-149 -1024 0
+148 -1024 0
+1011 -1023 0
+155 162 168 165 172 194 -189 -192 1020 1017 1016 1015 1014 1013 -188 -199 1023 0
+-194 -1023 0
+-172 -1023 0
+-168 -1023 0
+-165 -1023 0
+-162 -1023 0
+-155 -1023 0
+189 -1023 0
+192 -1023 0
+-1020 -1023 0
+-1017 -1023 0
+-1016 -1023 0
+-1015 -1023 0
+-1014 -1023 0
+-1013 -1023 0
+188 -1023 0
+199 -1023 0
+1011 -1022 0
+155 162 168 165 172 194 -189 -192 1020 1017 1016 1015 1014 1013 199 -188 1022 0
+-194 -1022 0
+-172 -1022 0
+-168 -1022 0
+-165 -1022 0
+-162 -1022 0
+-155 -1022 0
+189 -1022 0
+192 -1022 0
+-1020 -1022 0
+-1017 -1022 0
+-1016 -1022 0
+-1015 -1022 0
+-1014 -1022 0
+-1013 -1022 0
+-199 -1022 0
+188 -1022 0
+1011 -1021 0
+155 162 172 168 165 187 194 -183 -186 1020 1019 1017 1016 1015 1014 1013 -180 -181 1021 0
+-194 -1021 0
+-187 -1021 0
+-172 -1021 0
+-168 -1021 0
+-165 -1021 0
+-162 -1021 0
+-155 -1021 0
+183 -1021 0
+186 -1021 0
+-1020 -1021 0
+-1019 -1021 0
+-1017 -1021 0
+-1016 -1021 0
+-1015 -1021 0
+-1014 -1021 0
+-1013 -1021 0
+180 -1021 0
+181 -1021 0
+1011 -1018 0
+155 162 172 168 165 187 194 -183 -186 1020 1019 1017 1016 1015 1014 1013 181 -180 1018 0
+-194 -1018 0
+-187 -1018 0
+-172 -1018 0
+-168 -1018 0
+-165 -1018 0
+-162 -1018 0
+-155 -1018 0
+183 -1018 0
+186 -1018 0
+-1018 -1020 0
+-148 -154 1020 0
+154 -1020 0
+148 -1020 0
+-1018 -1019 0
+-188 -192 1019 0
+192 -1019 0
+188 -1019 0
+-1017 -1018 0
+-1016 -1018 0
+-1015 -1018 0
+-1014 -1018 0
+-1013 -1018 0
+-181 -1018 0
+180 -1018 0
+1011 -1012 0
+-148 -149 165 162 155 -151 -154 1017 1016 1015 1014 1013 168 172 1012 0
+-172 -1012 0
+-168 -1012 0
+-165 -1012 0
+-162 -1012 0
+-155 -1012 0
+151 -1012 0
+154 -1012 0
+-1012 -1017 0
+-5 -6 13 7 -96 529 1017 0
+-529 -1017 0
+96 -1017 0
+-13 -1017 0
+-7 -1017 0
+6 -1017 0
+5 -1017 0
+-1012 -1016 0
+7 13 -87 -42 -36 1016 0
+87 -1016 0
+-13 -1016 0
+-7 -1016 0
+42 -1016 0
+36 -1016 0
+-1012 -1015 0
+7 21 -81 -26 1015 0
+81 -1015 0
+-21 -1015 0
+-7 -1015 0
+26 -1015 0
+-1012 -1014 0
+7 -52 -138 1014 0
+138 -1014 0
+-7 -1014 0
+52 -1014 0
+-1012 -1013 0
+12 -156 -160 1013 0
+160 -1013 0
+-12 -1013 0
+156 -1013 0
+149 -1012 0
+148 -1012 0
+115 -1008 0
+117 -1008 0
+-516 1007 0
+980 -1006 0
+-934 -1006 0
+-512 -1006 0
+1 -2 0
+2 -3 -910 -932 0
+-2 932 0
+-932 933 995 986 982 979 971 968 964 958 999 1003 0
+932 -1003 0
+-13 19 934 512 101 529 948 -21 1003 0
+-948 -1003 0
+-529 -1003 0
+-934 -1003 0
+-512 -1003 0
+-101 -1003 0
+-19 -1003 0
+13 -1003 0
+21 -1003 0
+932 -999 0
+-641 -948 -1000 999 0
+-999 1000 0
+-934 -984 1000 0
+-934 984 -1000 0
+934 1000 -1001 0
+934 -1000 1001 0
+-512 -991 1001 0
+-512 991 -1001 0
+512 1001 -1002 0
+512 -1001 1002 0
+91 -101 -103 1002 0
+101 -1002 0
+-91 -1002 0
+103 -1002 0
+948 -999 0
+641 -999 0
+932 -995 0
+-318 -529 948 -996 934 995 0
+-995 996 0
+-512 996 -997 0
+-512 -996 997 0
+512 996 -998 0
+512 -996 998 0
+-91 -101 102 998 0
+-102 -998 0
+101 -998 0
+91 -998 0
+30 83 991 -210 997 0
+-991 -997 0
+210 -997 0
+-30 -997 0
+-83 -997 0
+-948 -995 0
+529 -995 0
+318 -995 0
+-934 -995 0
+932 -986 0
+986 -987 -992 0
+-986 992 0
+-948 992 -993 0
+-948 -992 993 0
+948 992 -994 0
+948 -992 994 0
+30 83 -353 318 -529 994 0
+-318 -994 0
+529 -994 0
+353 -994 0
+-30 -994 0
+-83 -994 0
+31 -57 -478 641 993 0
+-641 -993 0
+478 -993 0
+57 -993 0
+-31 -993 0
+-986 987 0
+-934 987 -988 0
+-934 -987 988 0
+934 987 -989 0
+934 -987 989 0
+-512 989 991 990 0
+-989 -991 0
+31 -57 -367 991 0
+367 -991 0
+57 -991 0
+-31 -991 0
+-989 -990 0
+30 83 -210 990 0
+210 -990 0
+-30 -990 0
+-83 -990 0
+512 -989 0
+30 31 984 83 -57 -666 988 0
+-984 -988 0
+666 -988 0
+-30 -988 0
+-83 -988 0
+57 -988 0
+-31 -988 0
+932 -982 0
+30 83 984 983 -948 -537 -934 641 985 982 0
+-641 -982 0
+-982 -985 0
+31 -57 -478 985 0
+478 -985 0
+57 -985 0
+-31 -985 0
+-982 -984 0
+30 83 -616 984 0
+616 -984 0
+-30 -984 0
+-83 -984 0
+-982 -983 0
+30 31 83 -57 -666 983 0
+666 -983 0
+-30 -983 0
+-83 -983 0
+57 -983 0
+-31 -983 0
+948 -982 0
+537 -982 0
+934 -982 0
+-30 -982 0
+-83 -982 0
+932 -979 0
+-13 19 529 934 512 -959 948 -980 21 979 0
+-979 980 0
+-101 980 -981 0
+-101 -980 981 0
+101 -972 980 0
+101 972 -980 0
+91 102 -961 981 0
+-102 -981 0
+961 -981 0
+-91 -981 0
+-948 -979 0
+-529 -979 0
+-934 -979 0
+-512 -979 0
+959 -979 0
+-19 -979 0
+13 -979 0
+-21 -979 0
+932 -971 0
+-13 19 961 972 948 529 934 512 -101 91 959 102 -975 21 971 0
+-971 975 0
+-975 976 977 978 0
+975 -978 0
+-7 -11 12 -969 978 0
+969 -978 0
+7 -978 0
+-12 -978 0
+11 -978 0
+975 -977 0
+-7 10 -965 -12 977 0
+965 -977 0
+-10 -977 0
+7 -977 0
+12 -977 0
+975 -976 0
+-959 -961 976 0
+961 -976 0
+959 -976 0
+-102 -971 0
+-961 -971 0
+-971 -972 0
+-13 972 -973 0
+-13 -972 973 0
+13 972 -974 0
+13 -972 974 0
+10 12 -57 31 974 0
+57 -974 0
+-31 -974 0
+-10 -974 0
+-12 -974 0
+10 12 19 -57 21 31 973 0
+57 -973 0
+-31 -973 0
+-19 -973 0
+-10 -973 0
+-21 -973 0
+-12 -973 0
+-948 -971 0
+-529 -971 0
+-934 -971 0
+-512 -971 0
+101 -971 0
+-91 -971 0
+-959 -971 0
+-19 -971 0
+13 -971 0
+-21 -971 0
+932 -968 0
+-7 -11 529 934 512 101 13 -969 12 948 968 0
+-968 969 0
+-13 969 -970 0
+-13 -969 970 0
+-10 13 969 0
+10 13 -969 0
+-11 12 21 19 970 0
+-19 -970 0
+-21 -970 0
+-12 -970 0
+11 -970 0
+-948 -968 0
+-529 -968 0
+-934 -968 0
+-512 -968 0
+-101 -968 0
+-13 -968 0
+7 -968 0
+-12 -968 0
+11 -968 0
+932 -964 0
+-7 10 529 934 512 101 948 13 -965 -12 964 0
+-964 965 0
+-13 965 -966 0
+-13 -965 966 0
+13 965 -967 0
+13 -965 967 0
+10 -12 967 0
+-10 -967 0
+12 -967 0
+10 -12 21 19 966 0
+-19 -966 0
+-10 -966 0
+-21 -966 0
+12 -966 0
+-948 -964 0
+-529 -964 0
+-934 -964 0
+-512 -964 0
+-101 -964 0
+-10 -964 0
+-13 -964 0
+7 -964 0
+12 -964 0
+932 -958 0
+13 101 529 934 512 948 -959 -961 958 0
+-958 961 0
+-13 961 -962 0
+-13 -961 962 0
+13 961 -963 0
+13 -961 963 0
+10 12 -31 963 0
+31 -963 0
+-10 -963 0
+-12 -963 0
+10 12 -31 21 19 962 0
+31 -962 0
+-19 -962 0
+-10 -962 0
+-21 -962 0
+-12 -962 0
+-948 -958 0
+-529 -958 0
+-934 -958 0
+-512 -958 0
+-101 -958 0
+-958 959 0
+-7 -959 960 0
+959 -960 0
+10 12 960 0
+-10 -960 0
+-12 -960 0
+7 959 0
+-13 -958 0
+932 -933 0
+-13 -20 934 512 101 948 21 529 933 0
+-933 -948 0
+-948 949 950 0
+948 -950 0
+-5 7 13 529 -951 -63 950 0
+-950 951 0
+-106 951 -952 0
+106 -951 -952 0
+951 952 -953 0
+-951 952 953 0
+-525 953 -954 0
+525 -953 -954 0
+953 954 -955 0
+-953 954 955 0
+-947 955 -956 0
+947 -955 -956 0
+955 956 -957 0
+-955 956 957 0
+30 83 -537 -791 956 0
+537 -956 0
+791 -956 0
+-30 -956 0
+-83 -956 0
+31 -57 -765 -478 954 0
+478 -954 0
+765 -954 0
+57 -954 0
+-31 -954 0
+-641 -825 952 0
+641 -952 0
+825 -952 0
+-529 -950 0
+-13 -950 0
+-7 -950 0
+5 -950 0
+63 -950 0
+948 -949 0
+-5 7 13 529 -61 949 0
+-529 -949 0
+-13 -949 0
+-7 -949 0
+5 -949 0
+61 -949 0
+-529 -933 0
+-933 -934 0
+-934 935 939 0
+934 -939 0
+13 101 -526 512 -940 -943 939 0
+-939 943 0
+-106 943 -944 0
+106 -943 -944 0
+943 944 -945 0
+-943 944 945 0
+-525 945 -946 0
+525 -945 -946 0
+945 946 -947 0
+-945 946 947 0
+30 31 -666 83 -57 -715 946 0
+666 -946 0
+715 -946 0
+-30 -946 0
+-83 -946 0
+57 -946 0
+-31 -946 0
+30 83 -616 -810 944 0
+616 -944 0
+810 -944 0
+-30 -944 0
+-83 -944 0
+-939 940 0
+-30 -520 940 0
+-30 520 -940 0
+30 940 -941 0
+30 -940 941 0
+-83 941 -942 0
+-83 -941 942 0
+-63 83 941 0
+63 83 -941 0
+-133 -135 942 0
+135 -942 0
+133 -942 0
+526 -939 0
+-512 -939 0
+-101 -939 0
+-13 -939 0
+934 -935 0
+13 101 512 -936 -526 935 0
+526 -935 0
+-935 936 0
+-30 -516 936 0
+-30 516 -936 0
+30 936 -937 0
+30 -936 937 0
+-83 937 -938 0
+-83 -937 938 0
+-61 83 937 0
+61 83 -937 0
+133 -135 938 0
+-133 -938 0
+135 -938 0
+-512 -935 0
+-101 -935 0
+-13 -935 0
+-512 -933 0
+-101 -933 0
+13 -933 0
+-21 -933 0
+20 -933 0
+-2 910 0
+-910 911 922 921 920 919 918 917 924 931 0
+910 -931 0
+-5 7 -791 529 -526 512 30 83 101 -913 764 -755 -751 714 13 809 824 -65 931 0
+-824 -931 0
+-809 -931 0
+791 -931 0
+-529 -931 0
+526 -931 0
+-512 -931 0
+-30 -931 0
+-83 -931 0
+-101 -931 0
+913 -931 0
+-764 -931 0
+755 -931 0
+751 -931 0
+-714 -931 0
+-13 -931 0
+-7 -931 0
+5 -931 0
+65 -931 0
+910 -924 0
+924 -925 -928 0
+-924 928 0
+-916 928 -929 0
+-916 -928 929 0
+916 928 -930 0
+916 -928 930 0
+7 13 -419 -289 30 83 -447 450 -36 -35 930 0
+-450 -930 0
+447 -930 0
+419 -930 0
+289 -930 0
+-30 -930 0
+-83 -930 0
+-13 -930 0
+-7 -930 0
+36 -930 0
+35 -930 0
+31 -57 -781 -765 -784 824 929 0
+-824 -929 0
+784 -929 0
+781 -929 0
+765 -929 0
+57 -929 0
+-31 -929 0
+-924 925 0
+-912 925 -926 0
+-912 -925 926 0
+912 925 -927 0
+912 -925 927 0
+13 101 418 -107 432 -739 927 0
+739 -927 0
+-432 -927 0
+-418 -927 0
+107 -927 0
+-101 -927 0
+-13 -927 0
+30 31 -733 -715 809 83 -57 -736 926 0
+-809 -926 0
+736 -926 0
+733 -926 0
+715 -926 0
+-30 -926 0
+-83 -926 0
+57 -926 0
+-31 -926 0
+910 -922 0
+-5 7 -641 -825 529 -923 13 -653 -837 -65 922 0
+837 -922 0
+653 -922 0
+641 -922 0
+825 -922 0
+-529 -922 0
+-922 923 0
+-809 -912 923 0
+809 -912 -923 0
+-749 912 923 0
+749 912 -923 0
+-13 -922 0
+-7 -922 0
+5 -922 0
+65 -922 0
+910 -921 0
+7 13 -318 -305 916 912 -331 -747 -36 -35 921 0
+747 -921 0
+331 -921 0
+318 -921 0
+305 -921 0
+-916 -921 0
+-912 -921 0
+-13 -921 0
+-7 -921 0
+36 -921 0
+35 -921 0
+910 -920 0
+12 -293 298 757 296 294 916 912 299 738 920 0
+-738 -920 0
+-299 -920 0
+-298 -920 0
+-757 -920 0
+-296 -920 0
+-294 -920 0
+-916 -920 0
+-912 -920 0
+293 -920 0
+-12 -920 0
+910 -919 0
+7 -295 298 757 296 916 912 299 738 919 0
+-738 -919 0
+-299 -919 0
+-298 -919 0
+-757 -919 0
+-296 -919 0
+-916 -919 0
+-912 -919 0
+295 -919 0
+-7 -919 0
+910 -918 0
+7 21 298 757 916 912 299 -297 738 918 0
+-738 -918 0
+-299 -918 0
+-298 -918 0
+-757 -918 0
+-916 -918 0
+-912 -918 0
+-21 -918 0
+297 -918 0
+-7 -918 0
+910 -917 0
+-291 292 298 757 296 294 299 916 912 738 917 0
+-738 -917 0
+-299 -917 0
+-298 -917 0
+-757 -917 0
+-296 -917 0
+-294 -917 0
+-292 -917 0
+-916 -917 0
+-912 -917 0
+291 -917 0
+910 -911 0
+291 292 298 757 296 294 299 738 916 912 911 0
+-738 -911 0
+-299 -911 0
+-298 -911 0
+-757 -911 0
+-296 -911 0
+-294 -911 0
+-292 -911 0
+-291 -911 0
+-911 -916 0
+-5 7 13 529 -65 916 0
+-529 -916 0
+-13 -916 0
+-7 -916 0
+5 -916 0
+65 -916 0
+-911 -912 0
+13 101 512 -913 -526 912 0
+526 -912 0
+-512 -912 0
+-101 -912 0
+-912 913 0
+-30 -741 913 0
+-30 741 -913 0
+30 913 -914 0
+30 -913 914 0
+-83 914 -915 0
+-83 -914 915 0
+-65 83 914 0
+65 83 -914 0
+133 -134 135 915 0
+-135 -915 0
+-133 -915 0
+134 -915 0
+-13 -912 0
+-2 3 0
+-3 4 895 894 893 890 885 884 883 880 875 874 873 872 871 870 869 868 844 713 896 903 0
+3 -903 0
+903 -904 -907 0
+-903 907 0
+-863 907 -908 0
+-863 -907 908 0
+863 907 -909 0
+863 -907 909 0
+7 13 -447 -419 -289 30 83 450 -854 -42 -36 -48 909 0
+854 -909 0
+-450 -909 0
+447 -909 0
+419 -909 0
+289 -909 0
+-30 -909 0
+-83 -909 0
+-13 -909 0
+-7 -909 0
+42 -909 0
+36 -909 0
+48 -909 0
+-22 31 -781 -765 -57 -784 824 908 0
+-824 -908 0
+784 -908 0
+781 -908 0
+765 -908 0
+57 -908 0
+-31 -908 0
+22 -908 0
+-903 904 0
+-861 904 -905 0
+-861 -904 905 0
+861 904 -906 0
+861 -904 906 0
+13 101 418 -286 -112 -107 432 -857 906 0
+857 -906 0
+-432 -906 0
+-418 -906 0
+286 -906 0
+112 -906 0
+107 -906 0
+-101 -906 0
+-13 -906 0
+30 31 -733 -612 -715 809 83 -57 -736 905 0
+-809 -905 0
+736 -905 0
+733 -905 0
+612 -905 0
+715 -905 0
+-30 -905 0
+-83 -905 0
+57 -905 0
+-31 -905 0
+3 -896 0
+896 -897 -900 0
+-896 900 0
+-863 900 -901 0
+-863 -900 901 0
+863 900 -902 0
+863 -900 902 0
+7 13 -403 -353 30 83 48 416 -854 -42 -36 902 0
+854 -902 0
+-416 -902 0
+403 -902 0
+353 -902 0
+-30 -902 0
+-83 -902 0
+-48 -902 0
+-13 -902 0
+-7 -902 0
+42 -902 0
+36 -902 0
+22 31 -478 -57 -496 640 901 0
+-640 -901 0
+496 -901 0
+478 -901 0
+57 -901 0
+-31 -901 0
+-22 -901 0
+-896 897 0
+-861 897 -898 0
+-861 -897 898 0
+861 897 -899 0
+861 -897 899 0
+13 101 286 352 -112 -107 366 -857 899 0
+857 -899 0
+-366 -899 0
+-286 -899 0
+-352 -899 0
+112 -899 0
+107 -899 0
+-101 -899 0
+-13 -899 0
+30 31 612 -666 615 83 -57 -690 898 0
+-615 -898 0
+690 -898 0
+-612 -898 0
+666 -898 0
+-30 -898 0
+-83 -898 0
+57 -898 0
+-31 -898 0
+3 -895 0
+12 -156 861 856 855 853 851 849 -848 -203 863 862 895 0
+-863 -895 0
+-862 -895 0
+-861 -895 0
+-856 -895 0
+-855 -895 0
+-853 -895 0
+-851 -895 0
+-849 -895 0
+848 -895 0
+203 -895 0
+-12 -895 0
+156 -895 0
+3 -894 0
+7 -51 861 856 855 853 851 -850 863 -52 862 894 0
+-863 -894 0
+-862 -894 0
+-861 -894 0
+-856 -894 0
+-855 -894 0
+-853 -894 0
+-851 -894 0
+850 -894 0
+-7 -894 0
+52 -894 0
+51 -894 0
+3 -893 0
+7 21 861 856 855 853 -852 862 863 -26 -27 893 0
+-863 -893 0
+-862 -893 0
+-861 -893 0
+-856 -893 0
+-855 -893 0
+-853 -893 0
+852 -893 0
+-21 -893 0
+-7 -893 0
+26 -893 0
+27 -893 0
+3 -890 0
+7 13 861 -854 -331 -318 -305 863 -891 -42 -36 -48 890 0
+-890 891 0
+-145 -856 891 0
+145 -856 -891 0
+856 891 -892 0
+856 -891 892 0
+7 13 31 -854 855 -42 -36 -48 892 0
+-855 -892 0
+854 -892 0
+-31 -892 0
+-13 -892 0
+-7 -892 0
+42 -892 0
+36 -892 0
+48 -892 0
+-863 -890 0
+-861 -890 0
+854 -890 0
+331 -890 0
+318 -890 0
+305 -890 0
+-13 -890 0
+-7 -890 0
+42 -890 0
+36 -890 0
+48 -890 0
+3 -885 0
+-5 -6 -653 -601 -641 -825 529 13 7 -886 -837 -22 885 0
+837 -885 0
+-885 886 0
+-861 886 -887 0
+-861 -886 887 0
+861 886 -888 0
+861 -886 888 0
+-684 -856 888 0
+684 -856 -888 0
+856 888 -889 0
+856 -888 889 0
+-5 -6 57 31 13 7 91 -601 -22 889 0
+601 -889 0
+-91 -889 0
+-57 -889 0
+-31 -889 0
+-13 -889 0
+-7 -889 0
+6 -889 0
+5 -889 0
+22 -889 0
+30 83 -628 -616 -810 -822 -612 887 0
+822 -887 0
+612 -887 0
+628 -887 0
+616 -887 0
+810 -887 0
+-30 -887 0
+-83 -887 0
+653 -885 0
+601 -885 0
+641 -885 0
+825 -885 0
+-529 -885 0
+-13 -885 0
+-7 -885 0
+6 -885 0
+5 -885 0
+22 -885 0
+3 -884 0
+7 51 861 856 855 853 851 -850 862 863 -52 884 0
+-863 -884 0
+-862 -884 0
+-861 -884 0
+-856 -884 0
+-855 -884 0
+-853 -884 0
+-851 -884 0
+850 -884 0
+-51 -884 0
+-7 -884 0
+52 -884 0
+3 -883 0
+7 21 861 856 855 853 -852 27 862 863 -26 883 0
+-863 -883 0
+-862 -883 0
+-861 -883 0
+-856 -883 0
+-855 -883 0
+-853 -883 0
+852 -883 0
+-27 -883 0
+-21 -883 0
+-7 -883 0
+26 -883 0
+3 -880 0
+7 13 861 -854 -331 -318 48 863 -881 -42 -36 880 0
+-880 881 0
+-475 -856 881 0
+475 -856 -881 0
+856 881 -882 0
+856 -881 882 0
+7 13 31 48 -854 855 -42 -36 882 0
+-855 -882 0
+854 -882 0
+-31 -882 0
+-48 -882 0
+-13 -882 0
+-7 -882 0
+42 -882 0
+36 -882 0
+-863 -880 0
+-861 -880 0
+854 -880 0
+331 -880 0
+318 -880 0
+-48 -880 0
+-13 -880 0
+-7 -880 0
+42 -880 0
+36 -880 0
+3 -875 0
+-5 -6 -601 -641 529 22 13 7 -876 -653 875 0
+653 -875 0
+-875 876 0
+-861 876 -877 0
+-861 -876 877 0
+861 876 -878 0
+861 -876 878 0
+-677 -856 878 0
+677 -856 -878 0
+856 878 -879 0
+856 -878 879 0
+-5 -6 57 31 22 13 7 91 -601 879 0
+601 -879 0
+-91 -879 0
+-57 -879 0
+-31 -879 0
+-22 -879 0
+-13 -879 0
+-7 -879 0
+6 -879 0
+5 -879 0
+30 83 -616 612 -628 877 0
+-612 -877 0
+628 -877 0
+616 -877 0
+-30 -877 0
+-83 -877 0
+601 -875 0
+641 -875 0
+-529 -875 0
+-22 -875 0
+-13 -875 0
+-7 -875 0
+6 -875 0
+5 -875 0
+3 -874 0
+12 -156 861 856 855 853 851 849 -848 203 863 862 874 0
+-863 -874 0
+-862 -874 0
+-861 -874 0
+-856 -874 0
+-855 -874 0
+-853 -874 0
+-851 -874 0
+-849 -874 0
+848 -874 0
+-203 -874 0
+-12 -874 0
+156 -874 0
+3 -873 0
+-148 149 861 856 855 853 851 849 847 -867 862 863 873 0
+-863 -873 0
+-862 -873 0
+-861 -873 0
+-856 -873 0
+-855 -873 0
+-853 -873 0
+-851 -873 0
+-849 -873 0
+-847 -873 0
+867 -873 0
+-149 -873 0
+148 -873 0
+3 -872 0
+-188 -199 862 861 856 855 853 851 849 847 -865 866 863 872 0
+-866 -872 0
+-863 -872 0
+-862 -872 0
+-861 -872 0
+-856 -872 0
+-855 -872 0
+-853 -872 0
+-851 -872 0
+-849 -872 0
+-847 -872 0
+865 -872 0
+188 -872 0
+199 -872 0
+3 -871 0
+-188 199 862 861 856 855 853 851 849 847 -865 863 866 871 0
+-866 -871 0
+-863 -871 0
+-862 -871 0
+-861 -871 0
+-856 -871 0
+-855 -871 0
+-853 -871 0
+-851 -871 0
+-849 -871 0
+-847 -871 0
+865 -871 0
+-199 -871 0
+188 -871 0
+3 -870 0
+-180 -181 863 862 861 856 855 853 851 849 847 -846 866 864 870 0
+-866 -870 0
+-864 -870 0
+-863 -870 0
+-862 -870 0
+-861 -870 0
+-856 -870 0
+-855 -870 0
+-853 -870 0
+-851 -870 0
+-849 -870 0
+-847 -870 0
+846 -870 0
+180 -870 0
+181 -870 0
+3 -869 0
+-180 181 863 862 861 856 855 853 851 849 847 -846 864 866 869 0
+-866 -869 0
+-864 -869 0
+-863 -869 0
+-862 -869 0
+-861 -869 0
+-856 -869 0
+-855 -869 0
+-853 -869 0
+-851 -869 0
+-849 -869 0
+-847 -869 0
+846 -869 0
+-181 -869 0
+180 -869 0
+3 -868 0
+-148 -149 861 856 855 853 851 849 847 -867 862 863 868 0
+-863 -868 0
+-862 -868 0
+-861 -868 0
+-856 -868 0
+-855 -868 0
+-853 -868 0
+-851 -868 0
+-849 -868 0
+-847 -868 0
+867 -868 0
+149 -868 0
+148 -868 0
+3 -844 0
+844 845 863 862 861 856 855 853 851 849 847 864 866 0
+-844 -866 0
+-148 866 -867 0
+-866 867 0
+148 -866 0
+-844 -864 0
+-188 864 -865 0
+-864 865 0
+188 -864 0
+-844 -863 0
+-5 -6 13 7 529 -601 863 0
+601 -863 0
+-529 -863 0
+-13 -863 0
+-7 -863 0
+6 -863 0
+5 -863 0
+-844 -862 0
+7 13 -854 -42 -36 862 0
+854 -862 0
+-13 -862 0
+-7 -862 0
+42 -862 0
+36 -862 0
+-844 -861 0
+13 101 -526 512 -602 -606 861 0
+606 -861 0
+602 -861 0
+526 -861 0
+-512 -861 0
+-101 -861 0
+-13 -861 0
+-844 -856 0
+13 101 -107 -112 -857 856 0
+-856 857 0
+-857 858 859 860 0
+857 -860 0
+30 31 57 -609 860 0
+609 -860 0
+-30 -860 0
+-57 -860 0
+-31 -860 0
+857 -859 0
+31 -57 -601 859 0
+601 -859 0
+57 -859 0
+-31 -859 0
+857 -858 0
+30 83 -854 858 0
+854 -858 0
+-30 -858 0
+-83 -858 0
+112 -856 0
+107 -856 0
+-101 -856 0
+-13 -856 0
+-844 -855 0
+-5 -6 57 31 13 7 91 -601 855 0
+601 -855 0
+-91 -855 0
+-57 -855 0
+-31 -855 0
+-13 -855 0
+-7 -855 0
+6 -855 0
+5 -855 0
+-844 -853 0
+7 13 31 -854 -42 -36 853 0
+-853 854 0
+-31 -853 0
+-13 -853 0
+-7 -853 0
+42 -853 0
+36 -853 0
+-844 -851 0
+7 21 -852 -26 851 0
+-851 852 0
+-21 -851 0
+-7 -851 0
+26 -851 0
+-844 -849 0
+7 -52 -850 849 0
+-849 850 0
+-7 -849 0
+52 -849 0
+-844 -847 0
+12 -156 -848 847 0
+-847 848 0
+-12 -847 0
+156 -847 0
+-844 -845 0
+-180 845 -846 0
+-845 846 0
+180 -845 0
+3 -713 0
+-5 -6 -612 -606 -602 -601 -791 529 -526 512 30 83 101 764 -755 -751 714 13 7 809 824 -22 713 0
+-713 -824 0
+-641 -653 -837 -825 824 0
+-824 837 0
+-837 838 841 840 839 842 843 0
+837 -843 0
+7 13 -305 31 -318 -331 -36 -35 843 0
+331 -843 0
+318 -843 0
+305 -843 0
+-31 -843 0
+-13 -843 0
+-7 -843 0
+36 -843 0
+35 -843 0
+837 -842 0
+12 -293 296 294 757 298 842 0
+-298 -842 0
+-757 -842 0
+-296 -842 0
+-294 -842 0
+293 -842 0
+-12 -842 0
+837 -841 0
+7 -295 296 757 298 841 0
+-298 -841 0
+-757 -841 0
+-296 -841 0
+295 -841 0
+-7 -841 0
+837 -840 0
+7 21 757 -297 298 840 0
+-298 -840 0
+-757 -840 0
+-21 -840 0
+297 -840 0
+-7 -840 0
+837 -839 0
+-291 292 296 294 757 298 839 0
+-298 -839 0
+-757 -839 0
+-296 -839 0
+-294 -839 0
+-292 -839 0
+291 -839 0
+837 -838 0
+291 292 296 294 757 298 838 0
+-298 -838 0
+-757 -838 0
+-296 -838 0
+-294 -838 0
+-292 -838 0
+-291 -838 0
+653 -824 0
+641 -824 0
+-824 825 0
+-825 826 834 833 832 831 830 829 828 827 835 836 0
+825 -836 0
+128 142 402 391 390 388 346 387 836 0
+-142 -836 0
+-128 -836 0
+-402 -836 0
+-391 -836 0
+-390 -836 0
+-388 -836 0
+-346 -836 0
+-387 -836 0
+825 -835 0
+12 128 388 346 -158 -203 142 -156 835 0
+-142 -835 0
+-128 -835 0
+-388 -835 0
+-346 -835 0
+158 -835 0
+203 -835 0
+-12 -835 0
+156 -835 0
+825 -834 0
+7 51 388 -76 128 142 -52 834 0
+-142 -834 0
+-128 -834 0
+-388 -834 0
+76 -834 0
+-51 -834 0
+-7 -834 0
+52 -834 0
+825 -833 0
+12 128 388 346 -158 203 142 -156 833 0
+-142 -833 0
+-128 -833 0
+-388 -833 0
+-346 -833 0
+158 -833 0
+-203 -833 0
+-12 -833 0
+156 -833 0
+825 -832 0
+128 142 388 346 387 -152 149 -148 832 0
+-142 -832 0
+-128 -832 0
+-388 -832 0
+-346 -832 0
+-387 -832 0
+152 -832 0
+-149 -832 0
+148 -832 0
+825 -831 0
+128 142 391 388 346 387 -190 -188 -199 831 0
+-142 -831 0
+-128 -831 0
+-391 -831 0
+-388 -831 0
+-346 -831 0
+-387 -831 0
+190 -831 0
+188 -831 0
+199 -831 0
+825 -830 0
+128 142 391 388 346 387 -190 199 -188 830 0
+-142 -830 0
+-128 -830 0
+-391 -830 0
+-388 -830 0
+-346 -830 0
+-387 -830 0
+190 -830 0
+-199 -830 0
+188 -830 0
+825 -829 0
+128 142 391 390 388 346 387 -184 -180 -181 829 0
+-142 -829 0
+-128 -829 0
+-391 -829 0
+-390 -829 0
+-388 -829 0
+-346 -829 0
+-387 -829 0
+184 -829 0
+180 -829 0
+181 -829 0
+825 -828 0
+128 142 391 390 388 346 387 -184 181 -180 828 0
+-142 -828 0
+-128 -828 0
+-391 -828 0
+-390 -828 0
+-388 -828 0
+-346 -828 0
+-387 -828 0
+184 -828 0
+-181 -828 0
+180 -828 0
+825 -827 0
+128 142 388 346 387 -152 -149 -148 827 0
+-142 -827 0
+-128 -827 0
+-388 -827 0
+-346 -827 0
+-387 -827 0
+152 -827 0
+149 -827 0
+148 -827 0
+825 -826 0
+7 21 27 -28 128 -26 826 0
+-128 -826 0
+28 -826 0
+-27 -826 0
+-21 -826 0
+-7 -826 0
+26 -826 0
+-713 -809 0
+30 83 -616 -810 -822 -628 809 0
+-809 822 0
+737 742 744 743 745 823 -822 0
+822 -823 0
+7 13 31 -747 -36 -35 823 0
+747 -823 0
+-31 -823 0
+-13 -823 0
+-7 -823 0
+36 -823 0
+35 -823 0
+-745 822 0
+-744 822 0
+-743 822 0
+-742 822 0
+-737 822 0
+628 -809 0
+616 -809 0
+-809 810 0
+-810 811 819 818 817 816 815 814 813 812 820 821 0
+810 -821 0
+30 83 453 100 90 85 141 350 452 461 457 402 391 390 388 346 387 821 0
+-461 -821 0
+-457 -821 0
+-453 -821 0
+-100 -821 0
+-90 -821 0
+-85 -821 0
+-141 -821 0
+-350 -821 0
+-452 -821 0
+-30 -821 0
+-83 -821 0
+-402 -821 0
+-391 -821 0
+-390 -821 0
+-388 -821 0
+-346 -821 0
+-387 -821 0
+810 -820 0
+12 85 90 141 350 -347 388 346 -158 -203 100 -156 820 0
+-100 -820 0
+-90 -820 0
+-85 -820 0
+-141 -820 0
+-350 -820 0
+347 -820 0
+-388 -820 0
+-346 -820 0
+158 -820 0
+203 -820 0
+-12 -820 0
+156 -820 0
+810 -819 0
+7 51 85 141 -137 388 -76 90 100 -52 819 0
+-100 -819 0
+-90 -819 0
+-85 -819 0
+-141 -819 0
+137 -819 0
+-388 -819 0
+76 -819 0
+-51 -819 0
+-7 -819 0
+52 -819 0
+810 -818 0
+7 21 85 -29 -28 27 90 100 -26 818 0
+-100 -818 0
+-90 -818 0
+-85 -818 0
+29 -818 0
+28 -818 0
+-27 -818 0
+-21 -818 0
+-7 -818 0
+26 -818 0
+810 -817 0
+12 85 90 141 350 -347 388 346 -158 203 100 -156 817 0
+-100 -817 0
+-90 -817 0
+-85 -817 0
+-141 -817 0
+-350 -817 0
+347 -817 0
+-388 -817 0
+-346 -817 0
+158 -817 0
+-203 -817 0
+-12 -817 0
+156 -817 0
+810 -816 0
+85 90 100 141 350 452 -458 388 346 387 -152 149 -148 816 0
+-100 -816 0
+-90 -816 0
+-85 -816 0
+-141 -816 0
+-350 -816 0
+-452 -816 0
+458 -816 0
+-388 -816 0
+-346 -816 0
+-387 -816 0
+152 -816 0
+-149 -816 0
+148 -816 0
+810 -815 0
+85 90 100 457 141 350 452 -454 391 388 346 387 -190 -188 -199 815 0
+-457 -815 0
+-100 -815 0
+-90 -815 0
+-85 -815 0
+-141 -815 0
+-350 -815 0
+-452 -815 0
+454 -815 0
+-391 -815 0
+-388 -815 0
+-346 -815 0
+-387 -815 0
+190 -815 0
+188 -815 0
+199 -815 0
+810 -814 0
+85 90 100 457 141 350 452 -454 391 388 346 387 -190 199 -188 814 0
+-457 -814 0
+-100 -814 0
+-90 -814 0
+-85 -814 0
+-141 -814 0
+-350 -814 0
+-452 -814 0
+454 -814 0
+-391 -814 0
+-388 -814 0
+-346 -814 0
+-387 -814 0
+190 -814 0
+-199 -814 0
+188 -814 0
+810 -813 0
+85 90 100 453 457 141 350 452 -462 391 390 388 346 387 -184 -180 -181 813 0
+-457 -813 0
+-453 -813 0
+-100 -813 0
+-90 -813 0
+-85 -813 0
+-141 -813 0
+-350 -813 0
+-452 -813 0
+462 -813 0
+-391 -813 0
+-390 -813 0
+-388 -813 0
+-346 -813 0
+-387 -813 0
+184 -813 0
+180 -813 0
+181 -813 0
+810 -812 0
+85 90 100 453 457 141 350 452 -462 391 390 388 346 387 -184 181 -180 812 0
+-457 -812 0
+-453 -812 0
+-100 -812 0
+-90 -812 0
+-85 -812 0
+-141 -812 0
+-350 -812 0
+-452 -812 0
+462 -812 0
+-391 -812 0
+-390 -812 0
+-388 -812 0
+-346 -812 0
+-387 -812 0
+184 -812 0
+-181 -812 0
+180 -812 0
+810 -811 0
+85 90 100 141 350 452 -458 388 346 387 -152 -149 -148 811 0
+-100 -811 0
+-90 -811 0
+-85 -811 0
+-141 -811 0
+-350 -811 0
+-452 -811 0
+458 -811 0
+-388 -811 0
+-346 -811 0
+-387 -811 0
+152 -811 0
+149 -811 0
+148 -811 0
+-30 -809 0
+-83 -809 0
+612 -713 0
+606 -713 0
+602 -713 0
+601 -713 0
+-713 791 0
+-791 792 806 805 804 803 802 801 800 799 798 797 796 795 794 793 807 808 0
+791 -808 0
+30 83 461 457 453 100 90 85 141 350 452 142 128 402 391 390 346 387 808 0
+-142 -808 0
+-128 -808 0
+-461 -808 0
+-457 -808 0
+-453 -808 0
+-100 -808 0
+-90 -808 0
+-85 -808 0
+-141 -808 0
+-350 -808 0
+-452 -808 0
+-30 -808 0
+-83 -808 0
+-402 -808 0
+-391 -808 0
+-390 -808 0
+-346 -808 0
+-387 -808 0
+791 -807 0
+7 13 432 -419 418 -289 -286 -119 -112 30 83 -107 101 -71 -447 450 -42 -36 -48 807 0
+-450 -807 0
+447 -807 0
+-432 -807 0
+419 -807 0
+-418 -807 0
+289 -807 0
+286 -807 0
+119 -807 0
+112 -807 0
+-30 -807 0
+-83 -807 0
+107 -807 0
+-101 -807 0
+71 -807 0
+-13 -807 0
+-7 -807 0
+42 -807 0
+36 -807 0
+48 -807 0
+791 -806 0
+7 13 366 -353 286 352 -119 -112 30 83 -107 101 -71 48 -403 416 -42 -36 806 0
+-416 -806 0
+403 -806 0
+-366 -806 0
+353 -806 0
+-286 -806 0
+-352 -806 0
+119 -806 0
+112 -806 0
+-30 -806 0
+-83 -806 0
+107 -806 0
+-101 -806 0
+71 -806 0
+-48 -806 0
+-13 -806 0
+-7 -806 0
+42 -806 0
+36 -806 0
+791 -805 0
+12 85 100 90 128 141 350 -347 346 -158 -203 142 -156 805 0
+-142 -805 0
+-128 -805 0
+-100 -805 0
+-90 -805 0
+-85 -805 0
+-141 -805 0
+-350 -805 0
+347 -805 0
+-346 -805 0
+158 -805 0
+203 -805 0
+-12 -805 0
+156 -805 0
+791 -804 0
+7 -51 100 90 85 141 -137 -76 142 -52 128 804 0
+-142 -804 0
+-128 -804 0
+-100 -804 0
+-90 -804 0
+-85 -804 0
+-141 -804 0
+137 -804 0
+76 -804 0
+-7 -804 0
+52 -804 0
+51 -804 0
+791 -803 0
+7 21 90 85 -29 -28 100 128 -26 -27 803 0
+-128 -803 0
+-100 -803 0
+-90 -803 0
+-85 -803 0
+29 -803 0
+28 -803 0
+-21 -803 0
+-7 -803 0
+26 -803 0
+27 -803 0
+791 -802 0
+7 13 -305 -144 -71 -318 -331 -42 -36 -48 802 0
+331 -802 0
+318 -802 0
+305 -802 0
+144 -802 0
+71 -802 0
+-13 -802 0
+-7 -802 0
+42 -802 0
+36 -802 0
+48 -802 0
+791 -801 0
+7 51 100 90 85 141 -137 -76 128 142 -52 801 0
+-142 -801 0
+-128 -801 0
+-100 -801 0
+-90 -801 0
+-85 -801 0
+-141 -801 0
+137 -801 0
+76 -801 0
+-51 -801 0
+-7 -801 0
+52 -801 0
+791 -800 0
+7 21 90 85 -29 -28 27 100 128 -26 800 0
+-128 -800 0
+-100 -800 0
+-90 -800 0
+-85 -800 0
+29 -800 0
+28 -800 0
+-27 -800 0
+-21 -800 0
+-7 -800 0
+26 -800 0
+791 -799 0
+7 13 -474 -71 48 -318 -331 -42 -36 799 0
+331 -799 0
+318 -799 0
+474 -799 0
+71 -799 0
+-48 -799 0
+-13 -799 0
+-7 -799 0
+42 -799 0
+36 -799 0
+791 -798 0
+12 85 100 90 128 141 350 -347 346 -158 203 142 -156 798 0
+-142 -798 0
+-128 -798 0
+-100 -798 0
+-90 -798 0
+-85 -798 0
+-141 -798 0
+-350 -798 0
+347 -798 0
+-346 -798 0
+158 -798 0
+-203 -798 0
+-12 -798 0
+156 -798 0
+791 -797 0
+85 90 100 128 142 141 350 452 -458 346 387 -152 149 -148 797 0
+-142 -797 0
+-128 -797 0
+-100 -797 0
+-90 -797 0
+-85 -797 0
+-141 -797 0
+-350 -797 0
+-452 -797 0
+458 -797 0
+-346 -797 0
+-387 -797 0
+152 -797 0
+-149 -797 0
+148 -797 0
+791 -796 0
+85 90 457 100 128 142 141 350 452 -454 391 346 387 -190 -188 -199 796 0
+-142 -796 0
+-128 -796 0
+-457 -796 0
+-100 -796 0
+-90 -796 0
+-85 -796 0
+-141 -796 0
+-350 -796 0
+-452 -796 0
+454 -796 0
+-391 -796 0
+-346 -796 0
+-387 -796 0
+190 -796 0
+188 -796 0
+199 -796 0
+791 -795 0
+85 90 457 100 128 142 141 350 452 -454 391 346 387 -190 199 -188 795 0
+-142 -795 0
+-128 -795 0
+-457 -795 0
+-100 -795 0
+-90 -795 0
+-85 -795 0
+-141 -795 0
+-350 -795 0
+-452 -795 0
+454 -795 0
+-391 -795 0
+-346 -795 0
+-387 -795 0
+190 -795 0
+-199 -795 0
+188 -795 0
+791 -794 0
+85 90 457 453 100 128 142 141 350 452 -462 391 390 346 387 -184 -180 -181 794 0
+-142 -794 0
+-128 -794 0
+-457 -794 0
+-453 -794 0
+-100 -794 0
+-90 -794 0
+-85 -794 0
+-141 -794 0
+-350 -794 0
+-452 -794 0
+462 -794 0
+-391 -794 0
+-390 -794 0
+-346 -794 0
+-387 -794 0
+184 -794 0
+180 -794 0
+181 -794 0
+791 -793 0
+85 90 457 453 100 128 142 141 350 452 -462 391 390 346 387 -184 181 -180 793 0
+-142 -793 0
+-128 -793 0
+-457 -793 0
+-453 -793 0
+-100 -793 0
+-90 -793 0
+-85 -793 0
+-141 -793 0
+-350 -793 0
+-452 -793 0
+462 -793 0
+-391 -793 0
+-390 -793 0
+-346 -793 0
+-387 -793 0
+184 -793 0
+-181 -793 0
+180 -793 0
+791 -792 0
+85 90 100 128 142 141 350 452 -458 346 387 -152 -149 -148 792 0
+-142 -792 0
+-128 -792 0
+-100 -792 0
+-90 -792 0
+-85 -792 0
+-141 -792 0
+-350 -792 0
+-452 -792 0
+458 -792 0
+-346 -792 0
+-387 -792 0
+152 -792 0
+149 -792 0
+148 -792 0
+-529 -713 0
+526 -713 0
+-512 -713 0
+-30 -713 0
+-83 -713 0
+-101 -713 0
+-713 -764 0
+31 -57 -765 -781 -784 764 0
+-764 784 0
+-784 785 788 787 786 789 790 0
+784 -790 0
+7 13 -305 299 31 -318 -331 -36 -35 790 0
+331 -790 0
+318 -790 0
+305 -790 0
+-299 -790 0
+-31 -790 0
+-13 -790 0
+-7 -790 0
+36 -790 0
+35 -790 0
+784 -789 0
+12 -293 757 296 294 298 299 789 0
+-299 -789 0
+-298 -789 0
+-757 -789 0
+-296 -789 0
+-294 -789 0
+293 -789 0
+-12 -789 0
+784 -788 0
+7 -295 757 296 298 299 788 0
+-299 -788 0
+-298 -788 0
+-757 -788 0
+-296 -788 0
+295 -788 0
+-7 -788 0
+784 -787 0
+7 21 757 298 -297 299 787 0
+-299 -787 0
+-298 -787 0
+-757 -787 0
+-21 -787 0
+297 -787 0
+-7 -787 0
+784 -786 0
+-291 292 757 296 294 298 299 786 0
+-299 -786 0
+-298 -786 0
+-757 -786 0
+-296 -786 0
+-294 -786 0
+-292 -786 0
+291 -786 0
+784 -785 0
+291 292 757 296 294 298 299 785 0
+-299 -785 0
+-298 -785 0
+-757 -785 0
+-296 -785 0
+-294 -785 0
+-292 -785 0
+-291 -785 0
+-764 781 0
+-781 782 783 0
+781 -783 0
+31 -57 366 -478 352 -496 640 783 0
+-640 -783 0
+496 -783 0
+-366 -783 0
+478 -783 0
+-352 -783 0
+57 -783 0
+-31 -783 0
+781 -782 0
+31 -57 352 -385 -367 -641 -653 782 0
+653 -782 0
+641 -782 0
+-352 -782 0
+385 -782 0
+367 -782 0
+57 -782 0
+-31 -782 0
+-764 765 0
+-765 766 778 777 776 775 774 773 772 771 770 769 768 767 779 780 0
+765 -780 0
+31 -57 208 402 194 187 391 390 172 168 165 162 155 346 387 128 142 780 0
+-142 -780 0
+-128 -780 0
+-208 -780 0
+-402 -780 0
+-194 -780 0
+-187 -780 0
+-391 -780 0
+-390 -780 0
+-172 -780 0
+-168 -780 0
+-165 -780 0
+-162 -780 0
+-155 -780 0
+-346 -780 0
+-387 -780 0
+57 -780 0
+-31 -780 0
+765 -779 0
+12 128 172 168 165 162 -157 346 -158 -203 142 -156 779 0
+-142 -779 0
+-128 -779 0
+-172 -779 0
+-168 -779 0
+-165 -779 0
+-162 -779 0
+157 -779 0
+-346 -779 0
+158 -779 0
+203 -779 0
+-12 -779 0
+156 -779 0
+765 -778 0
+7 -51 172 168 165 -163 -76 142 -52 128 778 0
+-142 -778 0
+-128 -778 0
+-172 -778 0
+-168 -778 0
+-165 -778 0
+163 -778 0
+76 -778 0
+-7 -778 0
+52 -778 0
+51 -778 0
+765 -777 0
+7 21 168 -166 -28 172 128 -26 -27 777 0
+-128 -777 0
+-172 -777 0
+-168 -777 0
+166 -777 0
+28 -777 0
+-21 -777 0
+-7 -777 0
+26 -777 0
+27 -777 0
+765 -776 0
+7 13 -305 172 -169 -71 31 -318 -331 -42 -36 -48 776 0
+331 -776 0
+318 -776 0
+305 -776 0
+-172 -776 0
+169 -776 0
+71 -776 0
+-31 -776 0
+-13 -776 0
+-7 -776 0
+42 -776 0
+36 -776 0
+48 -776 0
+765 -775 0
+7 51 172 168 165 -163 -76 128 142 -52 775 0
+-142 -775 0
+-128 -775 0
+-172 -775 0
+-168 -775 0
+-165 -775 0
+163 -775 0
+76 -775 0
+-51 -775 0
+-7 -775 0
+52 -775 0
+765 -774 0
+7 21 168 -166 -28 27 172 128 -26 774 0
+-128 -774 0
+-172 -774 0
+-168 -774 0
+166 -774 0
+28 -774 0
+-27 -774 0
+-21 -774 0
+-7 -774 0
+26 -774 0
+765 -773 0
+7 13 172 -169 -71 31 48 -318 -331 -42 -36 773 0
+331 -773 0
+318 -773 0
+-172 -773 0
+169 -773 0
+71 -773 0
+-31 -773 0
+-48 -773 0
+-13 -773 0
+-7 -773 0
+42 -773 0
+36 -773 0
+765 -772 0
+12 128 172 168 165 162 -157 346 -158 203 142 -156 772 0
+-142 -772 0
+-128 -772 0
+-172 -772 0
+-168 -772 0
+-165 -772 0
+-162 -772 0
+157 -772 0
+-346 -772 0
+158 -772 0
+-203 -772 0
+-12 -772 0
+156 -772 0
+765 -771 0
+128 142 172 168 165 162 155 -151 346 387 -152 149 -148 771 0
+-142 -771 0
+-128 -771 0
+-172 -771 0
+-168 -771 0
+-165 -771 0
+-162 -771 0
+-155 -771 0
+151 -771 0
+-346 -771 0
+-387 -771 0
+152 -771 0
+-149 -771 0
+148 -771 0
+765 -770 0
+128 142 194 391 172 168 165 162 155 -189 346 387 -190 -188 -199 770 0
+-142 -770 0
+-128 -770 0
+-194 -770 0
+-391 -770 0
+-172 -770 0
+-168 -770 0
+-165 -770 0
+-162 -770 0
+-155 -770 0
+189 -770 0
+-346 -770 0
+-387 -770 0
+190 -770 0
+188 -770 0
+199 -770 0
+765 -769 0
+128 142 194 391 172 168 165 162 155 -189 346 387 -190 199 -188 769 0
+-142 -769 0
+-128 -769 0
+-194 -769 0
+-391 -769 0
+-172 -769 0
+-168 -769 0
+-165 -769 0
+-162 -769 0
+-155 -769 0
+189 -769 0
+-346 -769 0
+-387 -769 0
+190 -769 0
+-199 -769 0
+188 -769 0
+765 -768 0
+128 142 194 187 391 390 172 168 165 162 155 -183 346 387 -184 -180 -181 768 0
+-142 -768 0
+-128 -768 0
+-194 -768 0
+-187 -768 0
+-391 -768 0
+-390 -768 0
+-172 -768 0
+-168 -768 0
+-165 -768 0
+-162 -768 0
+-155 -768 0
+183 -768 0
+-346 -768 0
+-387 -768 0
+184 -768 0
+180 -768 0
+181 -768 0
+765 -767 0
+128 142 194 187 391 390 172 168 165 162 155 -183 346 387 -184 181 -180 767 0
+-142 -767 0
+-128 -767 0
+-194 -767 0
+-187 -767 0
+-391 -767 0
+-390 -767 0
+-172 -767 0
+-168 -767 0
+-165 -767 0
+-162 -767 0
+-155 -767 0
+183 -767 0
+-346 -767 0
+-387 -767 0
+184 -767 0
+-181 -767 0
+180 -767 0
+765 -766 0
+128 142 172 168 165 162 155 -151 346 387 -152 -149 -148 766 0
+-142 -766 0
+-128 -766 0
+-172 -766 0
+-168 -766 0
+-165 -766 0
+-162 -766 0
+-155 -766 0
+151 -766 0
+-346 -766 0
+-387 -766 0
+152 -766 0
+149 -766 0
+148 -766 0
+57 -764 0
+-31 -764 0
+-713 755 0
+-755 756 761 760 759 758 762 763 0
+755 -763 0
+7 13 -447 432 -419 418 -289 30 83 -107 101 450 -739 -36 -35 763 0
+739 -763 0
+-450 -763 0
+447 -763 0
+-432 -763 0
+419 -763 0
+-418 -763 0
+289 -763 0
+-30 -763 0
+-83 -763 0
+107 -763 0
+-101 -763 0
+-13 -763 0
+-7 -763 0
+36 -763 0
+35 -763 0
+755 -762 0
+7 13 -318 -305 -331 -747 -36 -35 762 0
+747 -762 0
+331 -762 0
+318 -762 0
+305 -762 0
+-13 -762 0
+-7 -762 0
+36 -762 0
+35 -762 0
+755 -761 0
+12 -293 298 757 296 294 299 738 761 0
+-738 -761 0
+-299 -761 0
+-298 -761 0
+-757 -761 0
+-296 -761 0
+-294 -761 0
+293 -761 0
+-12 -761 0
+755 -760 0
+7 -295 298 757 296 299 738 760 0
+-738 -760 0
+-299 -760 0
+-298 -760 0
+-757 -760 0
+-296 -760 0
+295 -760 0
+-7 -760 0
+755 -759 0
+7 21 298 757 299 -297 738 759 0
+-738 -759 0
+-299 -759 0
+-298 -759 0
+-757 -759 0
+-21 -759 0
+297 -759 0
+-7 -759 0
+755 -758 0
+-291 292 298 757 296 294 299 738 758 0
+-738 -758 0
+-299 -758 0
+-298 -758 0
+-757 -758 0
+-296 -758 0
+-294 -758 0
+-292 -758 0
+291 -758 0
+755 -756 0
+291 292 298 757 296 294 299 738 756 0
+-738 -756 0
+-299 -756 0
+-298 -756 0
+-756 -757 0
+7 13 -36 -35 757 0
+-13 -757 0
+-7 -757 0
+36 -757 0
+35 -757 0
+-296 -756 0
+-294 -756 0
+-292 -756 0
+-291 -756 0
+-713 751 0
+-751 752 753 754 0
+751 -754 0
+-23 30 615 -537 640 83 477 665 754 0
+-665 -754 0
+-640 -754 0
+-615 -754 0
+537 -754 0
+-30 -754 0
+-83 -754 0
+-477 -754 0
+23 -754 0
+751 -753 0
+30 31 615 -690 -478 -666 640 83 -57 -496 753 0
+-640 -753 0
+496 -753 0
+-615 -753 0
+690 -753 0
+478 -753 0
+666 -753 0
+-30 -753 0
+-83 -753 0
+57 -753 0
+-31 -753 0
+751 -752 0
+30 83 -641 -616 -653 -628 752 0
+653 -752 0
+628 -752 0
+641 -752 0
+616 -752 0
+-30 -752 0
+-83 -752 0
+-713 -714 0
+30 31 -715 -736 83 -57 -733 714 0
+-714 736 0
+-736 737 745 744 743 742 746 748 0
+736 -748 0
+-5 7 57 31 13 91 -749 -65 748 0
+-748 749 0
+-738 749 -750 0
+-738 -749 750 0
+-299 738 749 0
+299 738 -749 0
+31 -57 352 -385 -367 -433 -445 418 750 0
+-418 -750 0
+445 -750 0
+-352 -750 0
+385 -750 0
+367 -750 0
+433 -750 0
+57 -750 0
+-31 -750 0
+-91 -748 0
+-57 -748 0
+-31 -748 0
+-13 -748 0
+-7 -748 0
+5 -748 0
+65 -748 0
+736 -746 0
+7 13 31 299 -747 -36 -35 746 0
+-746 747 0
+-418 -738 747 0
+418 -738 -747 0
+-446 738 747 0
+446 738 -747 0
+-299 -746 0
+-31 -746 0
+-13 -746 0
+-7 -746 0
+36 -746 0
+35 -746 0
+736 -745 0
+12 -293 298 296 294 299 738 745 0
+-738 -745 0
+-299 -745 0
+-298 -745 0
+-296 -745 0
+-294 -745 0
+293 -745 0
+-12 -745 0
+736 -744 0
+7 -295 298 296 299 738 744 0
+-738 -744 0
+-299 -744 0
+-298 -744 0
+-296 -744 0
+295 -744 0
+-7 -744 0
+736 -743 0
+7 21 298 299 -297 738 743 0
+-738 -743 0
+-299 -743 0
+-298 -743 0
+-21 -743 0
+297 -743 0
+-7 -743 0
+736 -742 0
+-291 292 298 296 294 299 738 742 0
+-738 -742 0
+-299 -742 0
+-298 -742 0
+-296 -742 0
+-294 -742 0
+-292 -742 0
+291 -742 0
+736 -737 0
+291 292 298 296 294 299 738 737 0
+-737 -738 0
+13 101 -107 -739 738 0
+-738 739 0
+-30 -65 739 0
+-30 65 -739 0
+30 739 -740 0
+30 -739 740 0
+-83 740 -741 0
+-83 -740 741 0
+-35 83 740 0
+35 83 -740 0
+115 117 -118 741 0
+-117 -741 0
+-115 -741 0
+118 -741 0
+107 -738 0
+-101 -738 0
+-13 -738 0
+-299 -737 0
+-298 -737 0
+-296 -737 0
+-294 -737 0
+-292 -737 0
+-291 -737 0
+-714 733 0
+-733 734 735 0
+733 -735 0
+30 31 366 -666 352 615 83 -57 -690 735 0
+-615 -735 0
+690 -735 0
+-366 -735 0
+666 -735 0
+-352 -735 0
+-30 -735 0
+-83 -735 0
+57 -735 0
+-31 -735 0
+733 -734 0
+30 31 -385 -616 -628 83 -367 -57 352 734 0
+628 -734 0
+-352 -734 0
+385 -734 0
+616 -734 0
+-30 -734 0
+-83 -734 0
+367 -734 0
+57 -734 0
+-31 -734 0
+-714 715 0
+-715 716 730 729 728 727 726 725 724 723 722 721 720 719 718 717 731 732 0
+715 -732 0
+30 31 453 100 90 85 141 350 452 461 83 208 194 187 172 168 165 162 155 -57 457 732 0
+-461 -732 0
+-457 -732 0
+-453 -732 0
+-100 -732 0
+-90 -732 0
+-85 -732 0
+-141 -732 0
+-350 -732 0
+-452 -732 0
+-30 -732 0
+-83 -732 0
+-208 -732 0
+-194 -732 0
+-187 -732 0
+-172 -732 0
+-168 -732 0
+-165 -732 0
+-162 -732 0
+-155 -732 0
+57 -732 0
+-31 -732 0
+715 -731 0
+12 85 90 141 350 -347 172 168 165 162 -157 -203 100 -156 731 0
+-100 -731 0
+-90 -731 0
+-85 -731 0
+-141 -731 0
+-350 -731 0
+347 -731 0
+-172 -731 0
+-168 -731 0
+-165 -731 0
+-162 -731 0
+157 -731 0
+203 -731 0
+-12 -731 0
+156 -731 0
+715 -730 0
+7 -51 85 141 -137 172 168 165 -163 100 -52 90 730 0
+-100 -730 0
+-90 -730 0
+-85 -730 0
+-141 -730 0
+137 -730 0
+-172 -730 0
+-168 -730 0
+-165 -730 0
+163 -730 0
+-7 -730 0
+52 -730 0
+51 -730 0
+715 -729 0
+7 21 85 -29 172 168 -166 90 100 -26 -27 729 0
+-100 -729 0
+-90 -729 0
+-85 -729 0
+29 -729 0
+-172 -729 0
+-168 -729 0
+166 -729 0
+-21 -729 0
+-7 -729 0
+26 -729 0
+27 -729 0
+715 -728 0
+7 13 -169 31 172 -144 -42 -36 -48 728 0
+144 -728 0
+-172 -728 0
+169 -728 0
+-31 -728 0
+-13 -728 0
+-7 -728 0
+42 -728 0
+36 -728 0
+48 -728 0
+715 -727 0
+-5 -6 91 57 31 13 7 -173 -705 -22 727 0
+705 -727 0
+173 -727 0
+-91 -727 0
+-57 -727 0
+-31 -727 0
+-13 -727 0
+-7 -727 0
+6 -727 0
+5 -727 0
+22 -727 0
+715 -726 0
+7 51 85 141 -137 172 168 165 -163 90 100 -52 726 0
+-100 -726 0
+-90 -726 0
+-85 -726 0
+-141 -726 0
+137 -726 0
+-172 -726 0
+-168 -726 0
+-165 -726 0
+163 -726 0
+-51 -726 0
+-7 -726 0
+52 -726 0
+715 -725 0
+7 21 85 -29 172 168 -166 27 90 100 -26 725 0
+-100 -725 0
+-90 -725 0
+-85 -725 0
+29 -725 0
+-172 -725 0
+-168 -725 0
+166 -725 0
+-27 -725 0
+-21 -725 0
+-7 -725 0
+26 -725 0
+715 -724 0
+7 13 -169 31 48 172 -474 -42 -36 724 0
+474 -724 0
+-172 -724 0
+169 -724 0
+-31 -724 0
+-48 -724 0
+-13 -724 0
+-7 -724 0
+42 -724 0
+36 -724 0
+715 -723 0
+-5 -6 91 57 31 22 13 7 -173 -699 723 0
+699 -723 0
+173 -723 0
+-91 -723 0
+-57 -723 0
+-31 -723 0
+-22 -723 0
+-13 -723 0
+-7 -723 0
+6 -723 0
+5 -723 0
+715 -722 0
+12 85 90 141 350 -347 172 168 165 162 -157 203 100 -156 722 0
+-100 -722 0
+-90 -722 0
+-85 -722 0
+-141 -722 0
+-350 -722 0
+347 -722 0
+-172 -722 0
+-168 -722 0
+-165 -722 0
+-162 -722 0
+157 -722 0
+-203 -722 0
+-12 -722 0
+156 -722 0
+715 -721 0
+85 90 100 141 350 452 -458 172 168 165 162 155 -151 149 -148 721 0
+-100 -721 0
+-90 -721 0
+-85 -721 0
+-141 -721 0
+-350 -721 0
+-452 -721 0
+458 -721 0
+-172 -721 0
+-168 -721 0
+-165 -721 0
+-162 -721 0
+-155 -721 0
+151 -721 0
+-149 -721 0
+148 -721 0
+715 -720 0
+85 90 100 457 141 350 452 -454 194 172 168 165 162 155 -189 -188 -199 720 0
+-457 -720 0
+-100 -720 0
+-90 -720 0
+-85 -720 0
+-141 -720 0
+-350 -720 0
+-452 -720 0
+454 -720 0
+-194 -720 0
+-172 -720 0
+-168 -720 0
+-165 -720 0
+-162 -720 0
+-155 -720 0
+189 -720 0
+188 -720 0
+199 -720 0
+715 -719 0
+85 90 100 457 141 350 452 -454 194 172 168 165 162 155 -189 199 -188 719 0
+-457 -719 0
+-100 -719 0
+-90 -719 0
+-85 -719 0
+-141 -719 0
+-350 -719 0
+-452 -719 0
+454 -719 0
+-194 -719 0
+-172 -719 0
+-168 -719 0
+-165 -719 0
+-162 -719 0
+-155 -719 0
+189 -719 0
+-199 -719 0
+188 -719 0
+715 -718 0
+85 90 100 453 457 141 350 452 -462 194 187 172 168 165 162 155 -183 -180 -181 718 0
+-457 -718 0
+-453 -718 0
+-100 -718 0
+-90 -718 0
+-85 -718 0
+-141 -718 0
+-350 -718 0
+-452 -718 0
+462 -718 0
+-194 -718 0
+-187 -718 0
+-172 -718 0
+-168 -718 0
+-165 -718 0
+-162 -718 0
+-155 -718 0
+183 -718 0
+180 -718 0
+181 -718 0
+715 -717 0
+85 90 100 453 457 141 350 452 -462 194 187 172 168 165 162 155 -183 181 -180 717 0
+-457 -717 0
+-453 -717 0
+-100 -717 0
+-90 -717 0
+-85 -717 0
+-141 -717 0
+-350 -717 0
+-452 -717 0
+462 -717 0
+-194 -717 0
+-187 -717 0
+-172 -717 0
+-168 -717 0
+-165 -717 0
+-162 -717 0
+-155 -717 0
+183 -717 0
+-181 -717 0
+180 -717 0
+715 -716 0
+85 90 100 141 350 452 -458 172 168 165 162 155 -151 -149 -148 716 0
+-100 -716 0
+-90 -716 0
+-85 -716 0
+-141 -716 0
+-350 -716 0
+-452 -716 0
+458 -716 0
+-172 -716 0
+-168 -716 0
+-165 -716 0
+-162 -716 0
+-155 -716 0
+151 -716 0
+149 -716 0
+148 -716 0
+-30 -714 0
+-83 -714 0
+57 -714 0
+-31 -714 0
+-13 -713 0
+-7 -713 0
+6 -713 0
+5 -713 0
+22 -713 0
+3 -4 0
+4 -5 615 612 -606 -602 -601 -537 529 -526 512 30 83 101 477 -23 22 13 7 -6 640 665 0
+-4 -665 0
+30 31 -690 83 -57 -666 665 0
+-665 690 0
+-690 691 710 709 708 707 704 703 702 701 698 697 696 695 694 693 692 711 712 0
+690 -712 0
+30 31 461 457 453 100 90 85 141 350 452 -129 83 208 194 187 172 168 165 162 155 -57 -273 712 0
+129 -712 0
+273 -712 0
+-461 -712 0
+-457 -712 0
+-453 -712 0
+-100 -712 0
+-90 -712 0
+-85 -712 0
+-141 -712 0
+-350 -712 0
+-452 -712 0
+-30 -712 0
+-83 -712 0
+-208 -712 0
+-194 -712 0
+-187 -712 0
+-172 -712 0
+-168 -712 0
+-165 -712 0
+-162 -712 0
+-155 -712 0
+57 -712 0
+-31 -712 0
+690 -711 0
+30 31 129 83 -57 273 711 0
+-129 -711 0
+-273 -711 0
+-30 -711 0
+-83 -711 0
+57 -711 0
+-31 -711 0
+690 -710 0
+12 85 100 90 -273 141 350 -347 172 168 165 162 -157 -203 -129 -156 710 0
+129 -710 0
+273 -710 0
+-100 -710 0
+-90 -710 0
+-85 -710 0
+-141 -710 0
+-350 -710 0
+347 -710 0
+-172 -710 0
+-168 -710 0
+-165 -710 0
+-162 -710 0
+157 -710 0
+203 -710 0
+-12 -710 0
+156 -710 0
+690 -709 0
+7 -51 100 90 85 141 -137 172 168 165 -163 -129 -52 -273 709 0
+129 -709 0
+273 -709 0
+-100 -709 0
+-90 -709 0
+-85 -709 0
+-141 -709 0
+137 -709 0
+-172 -709 0
+-168 -709 0
+-165 -709 0
+163 -709 0
+-7 -709 0
+52 -709 0
+51 -709 0
+690 -708 0
+7 21 100 90 85 -29 172 168 -166 -273 -129 -26 -27 708 0
+129 -708 0
+273 -708 0
+-100 -708 0
+-90 -708 0
+-85 -708 0
+29 -708 0
+-172 -708 0
+-168 -708 0
+166 -708 0
+-21 -708 0
+-7 -708 0
+26 -708 0
+27 -708 0
+690 -707 0
+7 13 -273 172 -169 31 -144 -129 -42 -36 -48 707 0
+129 -707 0
+144 -707 0
+273 -707 0
+-172 -707 0
+169 -707 0
+-31 -707 0
+-13 -707 0
+-7 -707 0
+42 -707 0
+36 -707 0
+48 -707 0
+690 -704 0
+-5 -6 -273 -173 91 57 31 13 7 -705 -129 -22 704 0
+129 -704 0
+-704 705 0
+-100 -684 705 0
+-100 684 -705 0
+100 705 -706 0
+100 -705 706 0
+-5 -6 57 31 13 7 91 -95 -22 706 0
+95 -706 0
+-91 -706 0
+-57 -706 0
+-31 -706 0
+-13 -706 0
+-7 -706 0
+6 -706 0
+5 -706 0
+22 -706 0
+273 -704 0
+173 -704 0
+-91 -704 0
+-57 -704 0
+-31 -704 0
+-13 -704 0
+-7 -704 0
+6 -704 0
+5 -704 0
+22 -704 0
+690 -703 0
+7 51 100 90 85 141 -137 172 168 165 -163 -273 -129 -52 703 0
+129 -703 0
+273 -703 0
+-100 -703 0
+-90 -703 0
+-85 -703 0
+-141 -703 0
+137 -703 0
+-172 -703 0
+-168 -703 0
+-165 -703 0
+163 -703 0
+-51 -703 0
+-7 -703 0
+52 -703 0
+690 -702 0
+7 21 100 90 85 -29 172 168 -166 27 -273 -129 -26 702 0
+129 -702 0
+273 -702 0
+-100 -702 0
+-90 -702 0
+-85 -702 0
+29 -702 0
+-172 -702 0
+-168 -702 0
+166 -702 0
+-27 -702 0
+-21 -702 0
+-7 -702 0
+26 -702 0
+690 -701 0
+7 13 -273 172 -169 31 48 -474 -129 -42 -36 701 0
+129 -701 0
+474 -701 0
+273 -701 0
+-172 -701 0
+169 -701 0
+-31 -701 0
+-48 -701 0
+-13 -701 0
+-7 -701 0
+42 -701 0
+36 -701 0
+690 -698 0
+-5 -6 -273 -173 91 57 31 22 13 7 -699 -129 698 0
+129 -698 0
+-698 699 0
+-100 -677 699 0
+-100 677 -699 0
+100 699 -700 0
+100 -699 700 0
+-5 -6 57 31 22 13 7 91 -95 700 0
+95 -700 0
+-91 -700 0
+-57 -700 0
+-31 -700 0
+-22 -700 0
+-13 -700 0
+-7 -700 0
+6 -700 0
+5 -700 0
+273 -698 0
+173 -698 0
+-91 -698 0
+-57 -698 0
+-31 -698 0
+-22 -698 0
+-13 -698 0
+-7 -698 0
+6 -698 0
+5 -698 0
+690 -697 0
+12 85 100 90 -273 141 350 -347 172 168 165 162 -157 203 -129 -156 697 0
+129 -697 0
+273 -697 0
+-100 -697 0
+-90 -697 0
+-85 -697 0
+-141 -697 0
+-350 -697 0
+347 -697 0
+-172 -697 0
+-168 -697 0
+-165 -697 0
+-162 -697 0
+157 -697 0
+-203 -697 0
+-12 -697 0
+156 -697 0
+690 -696 0
+85 90 100 -273 -129 141 350 452 -458 172 168 165 162 155 -151 149 -148 696 0
+129 -696 0
+273 -696 0
+-100 -696 0
+-90 -696 0
+-85 -696 0
+-141 -696 0
+-350 -696 0
+-452 -696 0
+458 -696 0
+-172 -696 0
+-168 -696 0
+-165 -696 0
+-162 -696 0
+-155 -696 0
+151 -696 0
+-149 -696 0
+148 -696 0
+690 -695 0
+85 90 457 100 -273 -129 141 350 452 -454 194 172 168 165 162 155 -189 -188 -199 695 0
+129 -695 0
+273 -695 0
+-457 -695 0
+-100 -695 0
+-90 -695 0
+-85 -695 0
+-141 -695 0
+-350 -695 0
+-452 -695 0
+454 -695 0
+-194 -695 0
+-172 -695 0
+-168 -695 0
+-165 -695 0
+-162 -695 0
+-155 -695 0
+189 -695 0
+188 -695 0
+199 -695 0
+690 -694 0
+85 90 457 100 -273 -129 141 350 452 -454 194 172 168 165 162 155 -189 199 -188 694 0
+129 -694 0
+273 -694 0
+-457 -694 0
+-100 -694 0
+-90 -694 0
+-85 -694 0
+-141 -694 0
+-350 -694 0
+-452 -694 0
+454 -694 0
+-194 -694 0
+-172 -694 0
+-168 -694 0
+-165 -694 0
+-162 -694 0
+-155 -694 0
+189 -694 0
+-199 -694 0
+188 -694 0
+690 -693 0
+85 90 457 453 100 -273 -129 141 350 452 -462 194 187 172 168 165 162 155 -183 -180 -181 693 0
+129 -693 0
+273 -693 0
+-457 -693 0
+-453 -693 0
+-100 -693 0
+-90 -693 0
+-85 -693 0
+-141 -693 0
+-350 -693 0
+-452 -693 0
+462 -693 0
+-194 -693 0
+-187 -693 0
+-172 -693 0
+-168 -693 0
+-165 -693 0
+-162 -693 0
+-155 -693 0
+183 -693 0
+180 -693 0
+181 -693 0
+690 -692 0
+85 90 457 453 100 -273 -129 141 350 452 -462 194 187 172 168 165 162 155 -183 181 -180 692 0
+129 -692 0
+273 -692 0
+-457 -692 0
+-453 -692 0
+-100 -692 0
+-90 -692 0
+-85 -692 0
+-141 -692 0
+-350 -692 0
+-452 -692 0
+462 -692 0
+-194 -692 0
+-187 -692 0
+-172 -692 0
+-168 -692 0
+-165 -692 0
+-162 -692 0
+-155 -692 0
+183 -692 0
+-181 -692 0
+180 -692 0
+690 -691 0
+85 90 100 -273 -129 141 350 452 -458 172 168 165 162 155 -151 -149 -148 691 0
+129 -691 0
+273 -691 0
+-100 -691 0
+-90 -691 0
+-85 -691 0
+-141 -691 0
+-350 -691 0
+-452 -691 0
+458 -691 0
+-172 -691 0
+-168 -691 0
+-165 -691 0
+-162 -691 0
+-155 -691 0
+151 -691 0
+149 -691 0
+148 -691 0
+-665 666 0
+-666 667 687 686 682 681 680 679 675 674 673 672 671 670 669 668 688 689 0
+666 -689 0
+12 -156 554 550 546 -543 236 231 227 223 -218 -203 562 558 689 0
+-562 -689 0
+-558 -689 0
+-554 -689 0
+-550 -689 0
+-546 -689 0
+543 -689 0
+-236 -689 0
+-231 -689 0
+-227 -689 0
+-223 -689 0
+218 -689 0
+203 -689 0
+-12 -689 0
+156 -689 0
+666 -688 0
+7 -51 554 550 -547 236 231 227 -224 562 -52 558 688 0
+-562 -688 0
+-558 -688 0
+-554 -688 0
+-550 -688 0
+547 -688 0
+-236 -688 0
+-231 -688 0
+-227 -688 0
+224 -688 0
+-7 -688 0
+52 -688 0
+51 -688 0
+666 -687 0
+7 21 554 -551 236 231 -228 558 562 -26 -27 687 0
+-562 -687 0
+-558 -687 0
+-554 -687 0
+551 -687 0
+-236 -687 0
+-231 -687 0
+228 -687 0
+-21 -687 0
+-7 -687 0
+26 -687 0
+27 -687 0
+666 -686 0
+7 13 -232 31 236 -594 -42 -36 -48 686 0
+594 -686 0
+-236 -686 0
+232 -686 0
+-31 -686 0
+-13 -686 0
+-7 -686 0
+42 -686 0
+36 -686 0
+48 -686 0
+666 -682 0
+-5 -6 91 57 31 13 7 -237 -683 -22 682 0
+-682 683 0
+-562 683 -684 0
+-562 -683 684 0
+562 683 -685 0
+562 -683 685 0
+-5 -6 57 31 13 7 91 -559 -22 685 0
+559 -685 0
+-91 -685 0
+-57 -685 0
+-31 -685 0
+-13 -685 0
+-7 -685 0
+6 -685 0
+5 -685 0
+22 -685 0
+31 -57 -286 352 -385 -367 -433 -445 418 684 0
+-418 -684 0
+445 -684 0
+286 -684 0
+-352 -684 0
+385 -684 0
+367 -684 0
+433 -684 0
+57 -684 0
+-31 -684 0
+237 -682 0
+-91 -682 0
+-57 -682 0
+-31 -682 0
+-13 -682 0
+-7 -682 0
+6 -682 0
+5 -682 0
+22 -682 0
+666 -681 0
+7 51 554 550 -547 236 231 227 -224 558 562 -52 681 0
+-562 -681 0
+-558 -681 0
+-554 -681 0
+-550 -681 0
+547 -681 0
+-236 -681 0
+-231 -681 0
+-227 -681 0
+224 -681 0
+-51 -681 0
+-7 -681 0
+52 -681 0
+666 -680 0
+7 21 554 -551 236 231 -228 27 558 562 -26 680 0
+-562 -680 0
+-558 -680 0
+-554 -680 0
+551 -680 0
+-236 -680 0
+-231 -680 0
+228 -680 0
+-27 -680 0
+-21 -680 0
+-7 -680 0
+26 -680 0
+666 -679 0
+7 13 -232 31 48 236 -589 -42 -36 679 0
+589 -679 0
+-236 -679 0
+232 -679 0
+-31 -679 0
+-48 -679 0
+-13 -679 0
+-7 -679 0
+42 -679 0
+36 -679 0
+666 -675 0
+-5 -6 91 57 31 22 13 7 -237 -676 675 0
+-675 676 0
+-562 676 -677 0
+-562 -676 677 0
+562 676 -678 0
+562 -676 678 0
+-5 -6 57 31 22 13 7 91 -559 678 0
+559 -678 0
+-91 -678 0
+-57 -678 0
+-31 -678 0
+-22 -678 0
+-13 -678 0
+-7 -678 0
+6 -678 0
+5 -678 0
+31 -57 -385 -367 352 286 677 0
+-286 -677 0
+-352 -677 0
+385 -677 0
+367 -677 0
+57 -677 0
+-31 -677 0
+237 -675 0
+-91 -675 0
+-57 -675 0
+-31 -675 0
+-22 -675 0
+-13 -675 0
+-7 -675 0
+6 -675 0
+5 -675 0
+666 -674 0
+12 -156 554 550 546 -543 236 231 227 223 -218 203 562 558 674 0
+-562 -674 0
+-558 -674 0
+-554 -674 0
+-550 -674 0
+-546 -674 0
+543 -674 0
+-236 -674 0
+-231 -674 0
+-227 -674 0
+-223 -674 0
+218 -674 0
+-203 -674 0
+-12 -674 0
+156 -674 0
+666 -673 0
+-148 149 554 550 546 542 -539 236 231 227 223 217 -213 558 562 673 0
+-562 -673 0
+-558 -673 0
+-554 -673 0
+-550 -673 0
+-546 -673 0
+-542 -673 0
+539 -673 0
+-236 -673 0
+-231 -673 0
+-227 -673 0
+-223 -673 0
+-217 -673 0
+213 -673 0
+-149 -673 0
+148 -673 0
+666 -672 0
+-188 -199 558 554 550 546 542 -578 258 236 231 227 223 217 -253 581 562 672 0
+-581 -672 0
+-562 -672 0
+-558 -672 0
+-554 -672 0
+-550 -672 0
+-546 -672 0
+-542 -672 0
+578 -672 0
+-258 -672 0
+-236 -672 0
+-231 -672 0
+-227 -672 0
+-223 -672 0
+-217 -672 0
+253 -672 0
+188 -672 0
+199 -672 0
+666 -671 0
+-188 199 558 554 550 546 542 -578 258 236 231 227 223 217 -253 562 581 671 0
+-581 -671 0
+-562 -671 0
+-558 -671 0
+-554 -671 0
+-550 -671 0
+-546 -671 0
+-542 -671 0
+578 -671 0
+-258 -671 0
+-236 -671 0
+-231 -671 0
+-227 -671 0
+-223 -671 0
+-217 -671 0
+253 -671 0
+-199 -671 0
+188 -671 0
+666 -670 0
+-180 -181 562 558 554 550 546 542 -574 258 252 236 231 227 223 217 -247 581 577 670 0
+-581 -670 0
+-577 -670 0
+-562 -670 0
+-558 -670 0
+-554 -670 0
+-550 -670 0
+-546 -670 0
+-542 -670 0
+574 -670 0
+-258 -670 0
+-252 -670 0
+-236 -670 0
+-231 -670 0
+-227 -670 0
+-223 -670 0
+-217 -670 0
+247 -670 0
+180 -670 0
+181 -670 0
+666 -669 0
+-180 181 562 558 554 550 546 542 -574 258 252 236 231 227 223 217 -247 577 581 669 0
+-581 -669 0
+-577 -669 0
+-562 -669 0
+-558 -669 0
+-554 -669 0
+-550 -669 0
+-546 -669 0
+-542 -669 0
+574 -669 0
+-258 -669 0
+-252 -669 0
+-236 -669 0
+-231 -669 0
+-227 -669 0
+-223 -669 0
+-217 -669 0
+247 -669 0
+-181 -669 0
+180 -669 0
+666 -668 0
+30 31 573 562 558 554 550 546 542 581 83 258 252 246 236 231 227 223 217 -57 577 668 0
+-581 -668 0
+-577 -668 0
+-573 -668 0
+-562 -668 0
+-558 -668 0
+-554 -668 0
+-550 -668 0
+-546 -668 0
+-542 -668 0
+-30 -668 0
+-83 -668 0
+-258 -668 0
+-252 -668 0
+-246 -668 0
+-236 -668 0
+-231 -668 0
+-227 -668 0
+-223 -668 0
+-217 -668 0
+57 -668 0
+-31 -668 0
+666 -667 0
+-148 -149 554 550 546 542 -539 236 231 227 223 217 -213 558 562 667 0
+-562 -667 0
+-558 -667 0
+-554 -667 0
+-550 -667 0
+-546 -667 0
+-542 -667 0
+539 -667 0
+-236 -667 0
+-231 -667 0
+-227 -667 0
+-223 -667 0
+-217 -667 0
+213 -667 0
+149 -667 0
+148 -667 0
+-30 -665 0
+-83 -665 0
+57 -665 0
+-31 -665 0
+-4 -640 0
+640 -641 -653 0
+-640 653 0
+-25 -653 662 661 660 659 658 657 656 655 654 664 663 0
+653 -664 0
+-25 128 402 391 390 388 346 387 142 664 0
+-142 -664 0
+-128 -664 0
+-402 -664 0
+-391 -664 0
+-390 -664 0
+-388 -664 0
+-346 -664 0
+-387 -664 0
+25 -664 0
+653 -663 0
+12 -25 388 346 -158 -203 142 -156 128 663 0
+-142 -663 0
+-128 -663 0
+-388 -663 0
+-346 -663 0
+158 -663 0
+203 -663 0
+-12 -663 0
+156 -663 0
+25 -663 0
+653 -662 0
+7 -25 388 -76 51 142 -52 128 662 0
+-142 -662 0
+-128 -662 0
+-388 -662 0
+76 -662 0
+-51 -662 0
+-7 -662 0
+52 -662 0
+25 -662 0
+653 -661 0
+12 -25 388 346 -158 203 142 -156 128 661 0
+-142 -661 0
+-128 -661 0
+-388 -661 0
+-346 -661 0
+158 -661 0
+-203 -661 0
+-12 -661 0
+156 -661 0
+25 -661 0
+653 -660 0
+-25 128 388 346 387 -152 149 -148 142 660 0
+-142 -660 0
+-128 -660 0
+-388 -660 0
+-346 -660 0
+-387 -660 0
+152 -660 0
+-149 -660 0
+148 -660 0
+25 -660 0
+653 -659 0
+-25 128 391 388 346 387 -190 -188 142 -199 659 0
+-142 -659 0
+-128 -659 0
+-391 -659 0
+-388 -659 0
+-346 -659 0
+-387 -659 0
+190 -659 0
+188 -659 0
+25 -659 0
+199 -659 0
+653 -658 0
+-25 128 391 388 346 387 -190 199 -188 142 658 0
+-142 -658 0
+-128 -658 0
+-391 -658 0
+-388 -658 0
+-346 -658 0
+-387 -658 0
+190 -658 0
+-199 -658 0
+188 -658 0
+25 -658 0
+653 -657 0
+-25 128 391 390 388 346 387 -184 -180 142 -181 657 0
+-142 -657 0
+-128 -657 0
+-391 -657 0
+-390 -657 0
+-388 -657 0
+-346 -657 0
+-387 -657 0
+184 -657 0
+180 -657 0
+25 -657 0
+181 -657 0
+653 -656 0
+-25 128 391 390 388 346 387 -184 181 -180 142 656 0
+-142 -656 0
+-128 -656 0
+-391 -656 0
+-390 -656 0
+-388 -656 0
+-346 -656 0
+-387 -656 0
+184 -656 0
+-181 -656 0
+180 -656 0
+25 -656 0
+653 -655 0
+-25 128 388 346 387 -152 -149 -148 142 655 0
+-142 -655 0
+-128 -655 0
+-388 -655 0
+-346 -655 0
+-387 -655 0
+152 -655 0
+149 -655 0
+148 -655 0
+25 -655 0
+653 -654 0
+7 21 27 -28 128 -26 -25 654 0
+-128 -654 0
+28 -654 0
+-27 -654 0
+-21 -654 0
+-7 -654 0
+26 -654 0
+25 -654 0
+25 653 0
+-640 641 0
+-641 642 650 649 648 647 646 645 644 643 651 652 0
+641 -652 0
+12 -156 371 370 -219 -203 481 480 652 0
+-481 -652 0
+-480 -652 0
+-371 -652 0
+-370 -652 0
+219 -652 0
+203 -652 0
+-12 -652 0
+156 -652 0
+641 -651 0
+7 51 371 -74 480 481 -52 651 0
+-481 -651 0
+-480 -651 0
+-371 -651 0
+74 -651 0
+-51 -651 0
+-7 -651 0
+52 -651 0
+641 -650 0
+12 -156 371 370 -219 203 481 480 650 0
+-481 -650 0
+-480 -650 0
+-371 -650 0
+-370 -650 0
+219 -650 0
+-203 -650 0
+-12 -650 0
+156 -650 0
+641 -649 0
+-148 149 371 370 369 -214 480 481 649 0
+-481 -649 0
+-480 -649 0
+-371 -649 0
+-370 -649 0
+-369 -649 0
+214 -649 0
+-149 -649 0
+148 -649 0
+641 -648 0
+-188 -199 375 371 370 369 -254 481 480 648 0
+-481 -648 0
+-480 -648 0
+-375 -648 0
+-371 -648 0
+-370 -648 0
+-369 -648 0
+254 -648 0
+188 -648 0
+199 -648 0
+641 -647 0
+-188 199 375 371 370 369 -254 480 481 647 0
+-481 -647 0
+-480 -647 0
+-375 -647 0
+-371 -647 0
+-370 -647 0
+-369 -647 0
+254 -647 0
+-199 -647 0
+188 -647 0
+641 -646 0
+-180 -181 375 374 371 370 369 -248 481 480 646 0
+-481 -646 0
+-480 -646 0
+-375 -646 0
+-374 -646 0
+-371 -646 0
+-370 -646 0
+-369 -646 0
+248 -646 0
+180 -646 0
+181 -646 0
+641 -645 0
+-180 181 375 374 371 370 369 -248 480 481 645 0
+-481 -645 0
+-480 -645 0
+-375 -645 0
+-374 -645 0
+-371 -645 0
+-370 -645 0
+-369 -645 0
+248 -645 0
+-181 -645 0
+180 -645 0
+641 -644 0
+369 370 375 374 373 371 480 481 644 0
+-481 -644 0
+-480 -644 0
+-375 -644 0
+-374 -644 0
+-373 -644 0
+-371 -644 0
+-370 -644 0
+-369 -644 0
+641 -643 0
+-148 -149 371 370 369 -214 480 481 643 0
+-481 -643 0
+-480 -643 0
+-371 -643 0
+-370 -643 0
+-369 -643 0
+214 -643 0
+149 -643 0
+148 -643 0
+641 -642 0
+7 21 27 -79 480 -26 642 0
+-480 -642 0
+79 -642 0
+-27 -642 0
+-21 -642 0
+-7 -642 0
+26 -642 0
+-4 -615 0
+30 83 -628 -616 615 0
+-615 628 0
+465 -628 638 637 636 635 634 633 632 631 630 629 639 0
+628 -639 0
+-25 30 457 453 100 90 85 141 350 452 461 83 402 391 390 388 346 387 -129 639 0
+129 -639 0
+-461 -639 0
+-457 -639 0
+-453 -639 0
+-100 -639 0
+-90 -639 0
+-85 -639 0
+-141 -639 0
+-350 -639 0
+-452 -639 0
+-30 -639 0
+-83 -639 0
+-402 -639 0
+-391 -639 0
+-390 -639 0
+-388 -639 0
+-346 -639 0
+-387 -639 0
+25 -639 0
+-465 628 0
+628 -638 0
+12 -25 90 85 141 350 -347 388 346 -158 -203 -129 -156 100 638 0
+129 -638 0
+-100 -638 0
+-90 -638 0
+-85 -638 0
+-141 -638 0
+-350 -638 0
+347 -638 0
+-388 -638 0
+-346 -638 0
+158 -638 0
+203 -638 0
+-12 -638 0
+156 -638 0
+25 -638 0
+628 -637 0
+7 -25 90 85 141 -137 388 -76 51 -129 -52 100 637 0
+129 -637 0
+-100 -637 0
+-90 -637 0
+-85 -637 0
+-141 -637 0
+137 -637 0
+-388 -637 0
+76 -637 0
+-51 -637 0
+-7 -637 0
+52 -637 0
+25 -637 0
+628 -636 0
+7 21 90 85 -29 -28 27 100 -129 -26 -25 636 0
+129 -636 0
+-100 -636 0
+-90 -636 0
+-85 -636 0
+29 -636 0
+28 -636 0
+-27 -636 0
+-21 -636 0
+-7 -636 0
+26 -636 0
+25 -636 0
+628 -635 0
+12 -25 90 85 141 350 -347 388 346 -158 203 -129 -156 100 635 0
+129 -635 0
+-100 -635 0
+-90 -635 0
+-85 -635 0
+-141 -635 0
+-350 -635 0
+347 -635 0
+-388 -635 0
+-346 -635 0
+158 -635 0
+-203 -635 0
+-12 -635 0
+156 -635 0
+25 -635 0
+628 -634 0
+-25 85 90 100 141 350 452 -458 388 346 387 -152 149 -148 -129 634 0
+129 -634 0
+-100 -634 0
+-90 -634 0
+-85 -634 0
+-141 -634 0
+-350 -634 0
+-452 -634 0
+458 -634 0
+-388 -634 0
+-346 -634 0
+-387 -634 0
+152 -634 0
+-149 -634 0
+148 -634 0
+25 -634 0
+628 -633 0
+-25 85 100 90 457 141 350 452 -454 391 388 346 387 -190 -188 -129 -199 633 0
+129 -633 0
+-457 -633 0
+-100 -633 0
+-90 -633 0
+-85 -633 0
+-141 -633 0
+-350 -633 0
+-452 -633 0
+454 -633 0
+-391 -633 0
+-388 -633 0
+-346 -633 0
+-387 -633 0
+190 -633 0
+188 -633 0
+25 -633 0
+199 -633 0
+628 -632 0
+-25 85 100 90 457 141 350 452 -454 391 388 346 387 -190 199 -188 -129 632 0
+129 -632 0
+-457 -632 0
+-100 -632 0
+-90 -632 0
+-85 -632 0
+-141 -632 0
+-350 -632 0
+-452 -632 0
+454 -632 0
+-391 -632 0
+-388 -632 0
+-346 -632 0
+-387 -632 0
+190 -632 0
+-199 -632 0
+188 -632 0
+25 -632 0
+628 -631 0
+-25 85 453 100 90 457 141 350 452 -462 391 390 388 346 387 -184 -180 -129 -181 631 0
+129 -631 0
+-457 -631 0
+-453 -631 0
+-100 -631 0
+-90 -631 0
+-85 -631 0
+-141 -631 0
+-350 -631 0
+-452 -631 0
+462 -631 0
+-391 -631 0
+-390 -631 0
+-388 -631 0
+-346 -631 0
+-387 -631 0
+184 -631 0
+180 -631 0
+25 -631 0
+181 -631 0
+628 -630 0
+-25 85 453 100 90 457 141 350 452 -462 391 390 388 346 387 -184 181 -180 -129 630 0
+129 -630 0
+-457 -630 0
+-453 -630 0
+-100 -630 0
+-90 -630 0
+-85 -630 0
+-141 -630 0
+-350 -630 0
+-452 -630 0
+462 -630 0
+-391 -630 0
+-390 -630 0
+-388 -630 0
+-346 -630 0
+-387 -630 0
+184 -630 0
+-181 -630 0
+180 -630 0
+25 -630 0
+628 -629 0
+-25 85 90 100 141 350 452 -458 388 346 387 -152 -149 -148 -129 629 0
+129 -629 0
+-100 -629 0
+-90 -629 0
+-85 -629 0
+-141 -629 0
+-350 -629 0
+-452 -629 0
+458 -629 0
+-388 -629 0
+-346 -629 0
+-387 -629 0
+152 -629 0
+149 -629 0
+148 -629 0
+25 -629 0
+-615 616 0
+-616 617 625 624 623 622 621 620 619 618 626 627 0
+616 -627 0
+12 -156 554 550 546 -543 371 370 -219 -203 562 558 627 0
+-562 -627 0
+-558 -627 0
+-554 -627 0
+-550 -627 0
+-546 -627 0
+543 -627 0
+-371 -627 0
+-370 -627 0
+219 -627 0
+203 -627 0
+-12 -627 0
+156 -627 0
+616 -626 0
+7 51 554 550 -547 371 -74 558 562 -52 626 0
+-562 -626 0
+-558 -626 0
+-554 -626 0
+-550 -626 0
+547 -626 0
+-371 -626 0
+74 -626 0
+-51 -626 0
+-7 -626 0
+52 -626 0
+616 -625 0
+7 21 554 -551 -79 27 558 562 -26 625 0
+-562 -625 0
+-558 -625 0
+-554 -625 0
+551 -625 0
+79 -625 0
+-27 -625 0
+-21 -625 0
+-7 -625 0
+26 -625 0
+616 -624 0
+12 -156 554 550 546 -543 371 370 -219 203 562 558 624 0
+-562 -624 0
+-558 -624 0
+-554 -624 0
+-550 -624 0
+-546 -624 0
+543 -624 0
+-371 -624 0
+-370 -624 0
+219 -624 0
+-203 -624 0
+-12 -624 0
+156 -624 0
+616 -623 0
+-148 149 554 550 546 542 -539 371 370 369 -214 558 562 623 0
+-562 -623 0
+-558 -623 0
+-554 -623 0
+-550 -623 0
+-546 -623 0
+-542 -623 0
+539 -623 0
+-371 -623 0
+-370 -623 0
+-369 -623 0
+214 -623 0
+-149 -623 0
+148 -623 0
+616 -622 0
+-188 -199 558 554 550 546 542 -578 375 371 370 369 -254 581 562 622 0
+-581 -622 0
+-562 -622 0
+-558 -622 0
+-554 -622 0
+-550 -622 0
+-546 -622 0
+-542 -622 0
+578 -622 0
+-375 -622 0
+-371 -622 0
+-370 -622 0
+-369 -622 0
+254 -622 0
+188 -622 0
+199 -622 0
+616 -621 0
+-188 199 558 554 550 546 542 -578 375 371 370 369 -254 562 581 621 0
+-581 -621 0
+-562 -621 0
+-558 -621 0
+-554 -621 0
+-550 -621 0
+-546 -621 0
+-542 -621 0
+578 -621 0
+-375 -621 0
+-371 -621 0
+-370 -621 0
+-369 -621 0
+254 -621 0
+-199 -621 0
+188 -621 0
+616 -620 0
+-180 -181 562 558 554 550 546 542 -574 375 374 371 370 369 -248 581 577 620 0
+-581 -620 0
+-577 -620 0
+-562 -620 0
+-558 -620 0
+-554 -620 0
+-550 -620 0
+-546 -620 0
+-542 -620 0
+574 -620 0
+-375 -620 0
+-374 -620 0
+-371 -620 0
+-370 -620 0
+-369 -620 0
+248 -620 0
+180 -620 0
+181 -620 0
+616 -619 0
+-180 181 562 558 554 550 546 542 -574 375 374 371 370 369 -248 577 581 619 0
+-581 -619 0
+-577 -619 0
+-562 -619 0
+-558 -619 0
+-554 -619 0
+-550 -619 0
+-546 -619 0
+-542 -619 0
+574 -619 0
+-375 -619 0
+-374 -619 0
+-371 -619 0
+-370 -619 0
+-369 -619 0
+248 -619 0
+-181 -619 0
+180 -619 0
+616 -618 0
+30 83 573 562 558 554 550 546 542 581 577 375 374 373 371 370 369 618 0
+-581 -618 0
+-577 -618 0
+-573 -618 0
+-562 -618 0
+-558 -618 0
+-554 -618 0
+-550 -618 0
+-546 -618 0
+-542 -618 0
+-30 -618 0
+-83 -618 0
+-375 -618 0
+-374 -618 0
+-373 -618 0
+-371 -618 0
+-370 -618 0
+-369 -618 0
+616 -617 0
+-148 -149 554 550 546 542 -539 371 370 369 -214 558 562 617 0
+-562 -617 0
+-558 -617 0
+-554 -617 0
+-550 -617 0
+-546 -617 0
+-542 -617 0
+539 -617 0
+-371 -617 0
+-370 -617 0
+-369 -617 0
+214 -617 0
+149 -617 0
+148 -617 0
+-30 -615 0
+-83 -615 0
+-4 -612 0
+-30 -288 612 0
+-30 288 -612 0
+30 612 -613 0
+30 -612 613 0
+-83 613 -614 0
+-83 -613 614 0
+-22 83 613 0
+22 83 -613 0
+-133 -134 135 614 0
+-135 -614 0
+133 -614 0
+134 -614 0
+-4 606 0
+-606 607 608 610 0
+606 -610 0
+30 31 57 -611 610 0
+-610 611 0
+-30 -610 0
+-57 -610 0
+-31 -610 0
+606 -608 0
+31 -57 -609 608 0
+-608 609 0
+57 -608 0
+-31 -608 0
+606 -607 0
+30 83 -601 607 0
+601 -607 0
+-30 -607 0
+-83 -607 0
+-4 602 0
+-30 -114 602 0
+-30 114 -602 0
+30 602 -603 0
+30 -602 603 0
+-83 603 -604 0
+-83 -603 604 0
+-6 83 603 0
+6 83 -603 0
+135 604 -605 0
+-604 605 0
+133 -134 -605 0
+134 605 0
+-133 605 0
+-135 -604 0
+-4 601 0
+-4 537 0
+-537 538 598 597 596 593 592 591 588 587 586 585 584 583 582 572 599 600 0
+537 -600 0
+7 13 432 -419 418 -289 -286 -563 -112 30 83 -107 101 -68 -447 450 -42 -36 -48 600 0
+-450 -600 0
+447 -600 0
+-432 -600 0
+419 -600 0
+-418 -600 0
+289 -600 0
+286 -600 0
+563 -600 0
+112 -600 0
+-30 -600 0
+-83 -600 0
+107 -600 0
+-101 -600 0
+68 -600 0
+-13 -600 0
+-7 -600 0
+42 -600 0
+36 -600 0
+48 -600 0
+537 -599 0
+7 13 366 -353 286 352 -563 -112 30 83 -107 101 -68 48 -403 416 -42 -36 599 0
+-416 -599 0
+403 -599 0
+-366 -599 0
+353 -599 0
+-286 -599 0
+-352 -599 0
+563 -599 0
+112 -599 0
+-30 -599 0
+-83 -599 0
+107 -599 0
+-101 -599 0
+68 -599 0
+-48 -599 0
+-13 -599 0
+-7 -599 0
+42 -599 0
+36 -599 0
+537 -598 0
+12 -156 562 558 554 550 546 -543 370 -219 -203 481 480 598 0
+-481 -598 0
+-480 -598 0
+-562 -598 0
+-558 -598 0
+-554 -598 0
+-550 -598 0
+-546 -598 0
+543 -598 0
+-370 -598 0
+219 -598 0
+203 -598 0
+-12 -598 0
+156 -598 0
+537 -597 0
+7 -51 562 558 554 550 -547 -74 481 -52 480 597 0
+-481 -597 0
+-480 -597 0
+-562 -597 0
+-558 -597 0
+-554 -597 0
+-550 -597 0
+547 -597 0
+74 -597 0
+-7 -597 0
+52 -597 0
+51 -597 0
+537 -596 0
+7 21 558 554 -551 -79 562 480 -26 -27 596 0
+-480 -596 0
+-562 -596 0
+-558 -596 0
+-554 -596 0
+551 -596 0
+79 -596 0
+-21 -596 0
+-7 -596 0
+26 -596 0
+27 -596 0
+537 -593 0
+7 13 -305 -594 -68 -318 -331 -42 -36 -48 593 0
+331 -593 0
+318 -593 0
+305 -593 0
+-593 594 0
+-145 -562 594 0
+145 -562 -594 0
+562 594 -595 0
+562 -594 595 0
+7 13 31 -555 558 -42 -36 -48 595 0
+-558 -595 0
+555 -595 0
+-31 -595 0
+-13 -595 0
+-7 -595 0
+42 -595 0
+36 -595 0
+48 -595 0
+68 -593 0
+-13 -593 0
+-7 -593 0
+42 -593 0
+36 -593 0
+48 -593 0
+537 -592 0
+7 51 562 558 554 550 -547 -74 480 481 -52 592 0
+-481 -592 0
+-480 -592 0
+-562 -592 0
+-558 -592 0
+-554 -592 0
+-550 -592 0
+547 -592 0
+74 -592 0
+-51 -592 0
+-7 -592 0
+52 -592 0
+537 -591 0
+7 21 558 554 -551 -79 27 562 480 -26 591 0
+-480 -591 0
+-562 -591 0
+-558 -591 0
+-554 -591 0
+551 -591 0
+79 -591 0
+-27 -591 0
+-21 -591 0
+-7 -591 0
+26 -591 0
+537 -588 0
+7 13 -589 -68 48 -318 -331 -42 -36 588 0
+331 -588 0
+318 -588 0
+-588 589 0
+-475 -562 589 0
+475 -562 -589 0
+562 589 -590 0
+562 -589 590 0
+7 13 31 48 -555 558 -42 -36 590 0
+-558 -590 0
+555 -590 0
+-31 -590 0
+-48 -590 0
+-13 -590 0
+-7 -590 0
+42 -590 0
+36 -590 0
+68 -588 0
+-48 -588 0
+-13 -588 0
+-7 -588 0
+42 -588 0
+36 -588 0
+537 -587 0
+12 -156 562 558 554 550 546 -543 370 -219 203 481 480 587 0
+-481 -587 0
+-480 -587 0
+-562 -587 0
+-558 -587 0
+-554 -587 0
+-550 -587 0
+-546 -587 0
+543 -587 0
+-370 -587 0
+219 -587 0
+-203 -587 0
+-12 -587 0
+156 -587 0
+537 -586 0
+-148 149 562 558 554 550 546 542 -539 370 369 -214 480 481 586 0
+-481 -586 0
+-480 -586 0
+-562 -586 0
+-558 -586 0
+-554 -586 0
+-550 -586 0
+-546 -586 0
+-542 -586 0
+539 -586 0
+-370 -586 0
+-369 -586 0
+214 -586 0
+-149 -586 0
+148 -586 0
+537 -585 0
+-188 -199 581 562 558 554 550 546 542 -578 375 370 369 -254 481 480 585 0
+-481 -585 0
+-480 -585 0
+-581 -585 0
+-562 -585 0
+-558 -585 0
+-554 -585 0
+-550 -585 0
+-546 -585 0
+-542 -585 0
+578 -585 0
+-375 -585 0
+-370 -585 0
+-369 -585 0
+254 -585 0
+188 -585 0
+199 -585 0
+537 -584 0
+-188 199 581 562 558 554 550 546 542 -578 375 370 369 -254 480 481 584 0
+-481 -584 0
+-480 -584 0
+-581 -584 0
+-562 -584 0
+-558 -584 0
+-554 -584 0
+-550 -584 0
+-546 -584 0
+-542 -584 0
+578 -584 0
+-375 -584 0
+-370 -584 0
+-369 -584 0
+254 -584 0
+-199 -584 0
+188 -584 0
+537 -583 0
+-180 -181 581 577 562 558 554 550 546 542 -574 375 374 370 369 -248 481 480 583 0
+-481 -583 0
+-480 -583 0
+-581 -583 0
+-577 -583 0
+-562 -583 0
+-558 -583 0
+-554 -583 0
+-550 -583 0
+-546 -583 0
+-542 -583 0
+574 -583 0
+-375 -583 0
+-374 -583 0
+-370 -583 0
+-369 -583 0
+248 -583 0
+180 -583 0
+181 -583 0
+537 -582 0
+-180 181 581 577 562 558 554 550 546 542 -574 375 374 370 369 -248 480 481 582 0
+-481 -582 0
+-480 -582 0
+-581 -582 0
+-577 -582 0
+-562 -582 0
+-558 -582 0
+-554 -582 0
+-550 -582 0
+-546 -582 0
+-542 -582 0
+574 -582 0
+-375 -582 0
+-374 -582 0
+-370 -582 0
+-369 -582 0
+248 -582 0
+-181 -582 0
+180 -582 0
+537 -572 0
+30 83 581 577 573 562 558 554 550 546 542 481 480 375 374 373 370 369 572 0
+-481 -572 0
+-480 -572 0
+-572 -581 0
+-148 -539 581 0
+539 -581 0
+148 -581 0
+-572 -577 0
+-188 577 -578 0
+-577 578 0
+-30 -256 578 0
+-30 256 -578 0
+30 578 -579 0
+30 -578 579 0
+-83 579 -580 0
+-83 -579 580 0
+83 -254 579 0
+83 254 -579 0
+188 -577 0
+-572 -573 0
+-180 573 -574 0
+-573 574 0
+-30 -250 574 0
+-30 250 -574 0
+30 574 -575 0
+30 -574 575 0
+-83 575 -576 0
+-83 -575 576 0
+83 -248 575 0
+83 248 -575 0
+180 -573 0
+-562 -572 0
+-558 -572 0
+-554 -572 0
+-550 -572 0
+-546 -572 0
+-542 -572 0
+-30 -572 0
+-83 -572 0
+-375 -572 0
+-374 -572 0
+-373 -572 0
+-370 -572 0
+-369 -572 0
+537 -538 0
+-148 -149 562 558 554 550 546 542 -539 370 369 -214 480 481 538 0
+-481 -538 0
+-480 -538 0
+-538 -562 0
+13 101 -107 -112 -563 562 0
+-562 563 0
+-563 564 565 566 0
+563 -566 0
+30 31 57 -567 566 0
+-566 567 0
+-30 567 -568 0
+-30 -567 568 0
+30 567 -569 0
+30 -567 569 0
+-83 569 -570 0
+-83 -569 570 0
+83 569 -571 0
+83 -569 571 0
+-30 -566 0
+-57 -566 0
+-31 -566 0
+563 -565 0
+31 -57 -559 565 0
+559 -565 0
+57 -565 0
+-31 -565 0
+563 -564 0
+30 83 -555 564 0
+555 -564 0
+-30 -564 0
+-83 -564 0
+112 -562 0
+107 -562 0
+-101 -562 0
+-13 -562 0
+-538 -558 0
+-5 -6 57 31 13 7 91 -559 558 0
+-558 559 0
+-30 -240 559 0
+-30 240 -559 0
+30 559 -560 0
+30 -559 560 0
+-83 560 -561 0
+-83 -560 561 0
+83 -238 560 0
+83 238 -560 0
+-91 -558 0
+-57 -558 0
+-31 -558 0
+-13 -558 0
+-7 -558 0
+6 -558 0
+5 -558 0
+-538 -554 0
+7 13 31 -555 -42 -36 554 0
+-554 555 0
+-30 -234 555 0
+-30 234 -555 0
+30 555 -556 0
+30 -555 556 0
+-83 556 -557 0
+-83 -556 557 0
+-68 83 556 0
+68 83 -556 0
+-31 -554 0
+-13 -554 0
+-7 -554 0
+42 -554 0
+36 -554 0
+-538 -550 0
+7 21 -551 -26 550 0
+-550 551 0
+-30 -230 551 0
+-30 230 -551 0
+30 551 -552 0
+30 -551 552 0
+-83 552 -553 0
+-83 -552 553 0
+-79 83 552 0
+79 83 -552 0
+-21 -550 0
+-7 -550 0
+26 -550 0
+-538 -546 0
+7 -52 -547 546 0
+-546 547 0
+-30 -226 547 0
+-30 226 -547 0
+30 547 -548 0
+30 -547 548 0
+-83 548 -549 0
+-83 -548 549 0
+-74 83 548 0
+74 83 -548 0
+-7 -546 0
+52 -546 0
+-538 -542 0
+12 -156 -543 542 0
+-542 543 0
+-30 -221 543 0
+-30 221 -543 0
+30 543 -544 0
+30 -543 544 0
+-83 544 -545 0
+-83 -544 545 0
+83 -219 544 0
+83 219 -544 0
+-12 -542 0
+156 -542 0
+-538 539 0
+-30 -216 539 0
+-30 216 -539 0
+30 539 -540 0
+30 -539 540 0
+-83 540 -541 0
+-83 -540 541 0
+83 -214 540 0
+83 214 -540 0
+-370 -538 0
+-369 -538 0
+214 -538 0
+149 -538 0
+148 -538 0
+-4 -529 0
+-529 530 531 0
+529 -531 0
+7 13 -532 -36 -40 531 0
+-531 532 0
+-94 532 -533 0
+94 -532 -533 0
+532 533 -534 0
+-532 533 534 0
+-525 534 -535 0
+525 -534 -535 0
+534 535 -536 0
+-534 535 536 0
+30 83 -353 -419 535 0
+353 -535 0
+419 -535 0
+-30 -535 0
+-83 -535 0
+-305 -318 533 0
+318 -533 0
+305 -533 0
+-13 -531 0
+-7 -531 0
+36 -531 0
+40 -531 0
+529 -530 0
+7 13 -38 -36 530 0
+-13 -530 0
+-7 -530 0
+38 -530 0
+36 -530 0
+-4 526 0
+-31 -110 526 0
+-31 110 -526 0
+31 526 -527 0
+31 -526 527 0
+7 -30 527 0
+-7 -30 -527 0
+30 527 -528 0
+30 -527 528 0
+7 -83 528 0
+-7 -83 -528 0
+-5 83 528 0
+5 83 -528 0
+-4 -512 0
+-512 513 517 0
+512 -517 0
+13 101 -107 -518 -521 517 0
+-517 521 0
+-106 521 -522 0
+106 -521 -522 0
+521 522 -523 0
+-521 522 523 0
+-94 523 -524 0
+94 -523 -524 0
+523 524 -525 0
+-523 524 525 0
+30 83 -210 -146 524 0
+210 -524 0
+146 -524 0
+-30 -524 0
+-83 -524 0
+31 -57 -433 -367 522 0
+367 -522 0
+433 -522 0
+57 -522 0
+-31 -522 0
+-517 518 0
+-30 -63 518 0
+-30 63 -518 0
+30 518 -519 0
+30 -518 519 0
+-83 519 -520 0
+-83 -519 520 0
+-40 83 519 0
+40 83 -519 0
+-115 -117 520 0
+115 -520 0
+117 -520 0
+107 -517 0
+-101 -517 0
+-13 -517 0
+512 -513 0
+13 101 -514 -107 513 0
+107 -513 0
+-513 514 0
+-30 -61 514 0
+-30 61 -514 0
+30 514 -515 0
+30 -514 515 0
+-83 515 -516 0
+-83 -515 516 0
+-38 83 515 0
+38 83 -515 0
+-115 117 516 0
+-117 -516 0
+115 -516 0
+-101 -513 0
+-13 -513 0
+-4 -30 0
+-4 -83 0
+-4 -101 0
+-4 -477 0
+31 -57 -478 -496 477 0
+-477 496 0
+400 -496 509 508 507 506 505 504 503 502 501 500 499 498 497 511 510 0
+496 -511 0
+-25 31 -273 208 402 194 187 391 390 172 168 165 162 155 346 387 -57 128 142 511 0
+-142 -511 0
+-128 -511 0
+273 -511 0
+-208 -511 0
+-402 -511 0
+-194 -511 0
+-187 -511 0
+-391 -511 0
+-390 -511 0
+-172 -511 0
+-168 -511 0
+-165 -511 0
+-162 -511 0
+-155 -511 0
+-346 -511 0
+-387 -511 0
+57 -511 0
+-31 -511 0
+25 -511 0
+496 -510 0
+12 -25 -273 172 168 165 162 -157 346 -158 -203 142 -156 128 510 0
+-142 -510 0
+-128 -510 0
+273 -510 0
+-172 -510 0
+-168 -510 0
+-165 -510 0
+-162 -510 0
+157 -510 0
+-346 -510 0
+158 -510 0
+203 -510 0
+-12 -510 0
+156 -510 0
+25 -510 0
+496 -509 0
+7 -25 -273 172 168 165 -163 -76 142 -52 -51 128 509 0
+-142 -509 0
+-128 -509 0
+273 -509 0
+-172 -509 0
+-168 -509 0
+-165 -509 0
+163 -509 0
+76 -509 0
+-7 -509 0
+52 -509 0
+51 -509 0
+25 -509 0
+496 -508 0
+7 21 172 168 -166 -28 -273 128 -26 -27 -25 508 0
+-128 -508 0
+273 -508 0
+-172 -508 0
+-168 -508 0
+166 -508 0
+28 -508 0
+-21 -508 0
+-7 -508 0
+26 -508 0
+27 -508 0
+25 -508 0
+496 -507 0
+7 13 -305 -273 172 -169 -71 31 -318 -331 -42 -36 -48 -25 507 0
+331 -507 0
+318 -507 0
+305 -507 0
+273 -507 0
+-172 -507 0
+169 -507 0
+71 -507 0
+-31 -507 0
+-13 -507 0
+-7 -507 0
+42 -507 0
+36 -507 0
+48 -507 0
+25 -507 0
+496 -506 0
+7 -25 -273 172 168 165 -163 -76 51 142 -52 128 506 0
+-142 -506 0
+-128 -506 0
+273 -506 0
+-172 -506 0
+-168 -506 0
+-165 -506 0
+163 -506 0
+76 -506 0
+-51 -506 0
+-7 -506 0
+52 -506 0
+25 -506 0
+496 -505 0
+7 21 172 168 -166 -28 27 -273 128 -26 -25 505 0
+-128 -505 0
+273 -505 0
+-172 -505 0
+-168 -505 0
+166 -505 0
+28 -505 0
+-27 -505 0
+-21 -505 0
+-7 -505 0
+26 -505 0
+25 -505 0
+496 -504 0
+7 13 -273 172 -169 -71 31 48 -318 -331 -42 -36 -25 504 0
+331 -504 0
+318 -504 0
+273 -504 0
+-172 -504 0
+169 -504 0
+71 -504 0
+-31 -504 0
+-48 -504 0
+-13 -504 0
+-7 -504 0
+42 -504 0
+36 -504 0
+25 -504 0
+496 -503 0
+12 -25 -273 172 168 165 162 -157 346 -158 203 142 -156 128 503 0
+-142 -503 0
+-128 -503 0
+273 -503 0
+-172 -503 0
+-168 -503 0
+-165 -503 0
+-162 -503 0
+157 -503 0
+-346 -503 0
+158 -503 0
+-203 -503 0
+-12 -503 0
+156 -503 0
+25 -503 0
+496 -502 0
+-25 128 -273 172 168 165 162 155 -151 346 387 -152 149 -148 142 502 0
+-142 -502 0
+-128 -502 0
+273 -502 0
+-172 -502 0
+-168 -502 0
+-165 -502 0
+-162 -502 0
+-155 -502 0
+151 -502 0
+-346 -502 0
+-387 -502 0
+152 -502 0
+-149 -502 0
+148 -502 0
+25 -502 0
+496 -501 0
+-25 128 -273 194 391 172 168 165 162 155 -189 346 387 -190 -188 142 -199 501 0
+-142 -501 0
+-128 -501 0
+273 -501 0
+-194 -501 0
+-391 -501 0
+-172 -501 0
+-168 -501 0
+-165 -501 0
+-162 -501 0
+-155 -501 0
+189 -501 0
+-346 -501 0
+-387 -501 0
+190 -501 0
+188 -501 0
+25 -501 0
+199 -501 0
+496 -500 0
+-25 128 -273 194 391 172 168 165 162 155 -189 346 387 -190 199 -188 142 500 0
+-142 -500 0
+-128 -500 0
+273 -500 0
+-194 -500 0
+-391 -500 0
+-172 -500 0
+-168 -500 0
+-165 -500 0
+-162 -500 0
+-155 -500 0
+189 -500 0
+-346 -500 0
+-387 -500 0
+190 -500 0
+-199 -500 0
+188 -500 0
+25 -500 0
+496 -499 0
+-25 128 -273 194 187 391 390 172 168 165 162 155 -183 346 387 -184 -180 142 -181 499 0
+-142 -499 0
+-128 -499 0
+273 -499 0
+-194 -499 0
+-187 -499 0
+-391 -499 0
+-390 -499 0
+-172 -499 0
+-168 -499 0
+-165 -499 0
+-162 -499 0
+-155 -499 0
+183 -499 0
+-346 -499 0
+-387 -499 0
+184 -499 0
+180 -499 0
+25 -499 0
+181 -499 0
+496 -498 0
+-25 128 -273 194 187 391 390 172 168 165 162 155 -183 346 387 -184 181 -180 142 498 0
+-142 -498 0
+-128 -498 0
+273 -498 0
+-194 -498 0
+-187 -498 0
+-391 -498 0
+-390 -498 0
+-172 -498 0
+-168 -498 0
+-165 -498 0
+-162 -498 0
+-155 -498 0
+183 -498 0
+-346 -498 0
+-387 -498 0
+184 -498 0
+-181 -498 0
+180 -498 0
+25 -498 0
+496 -497 0
+-25 128 -273 172 168 165 162 155 -151 346 387 -152 -149 -148 142 497 0
+-142 -497 0
+-128 -497 0
+273 -497 0
+-172 -497 0
+-168 -497 0
+-165 -497 0
+-162 -497 0
+-155 -497 0
+151 -497 0
+-346 -497 0
+-387 -497 0
+152 -497 0
+149 -497 0
+148 -497 0
+25 -497 0
+-400 496 0
+-477 478 0
+-478 479 493 492 491 490 489 488 487 486 485 484 483 482 494 495 0
+478 -495 0
+12 -156 236 231 227 223 -218 370 -219 -203 481 480 495 0
+-481 -495 0
+-480 -495 0
+-236 -495 0
+-231 -495 0
+-227 -495 0
+-223 -495 0
+218 -495 0
+-370 -495 0
+219 -495 0
+203 -495 0
+-12 -495 0
+156 -495 0
+478 -494 0
+7 -51 236 231 227 -224 -74 481 -52 480 494 0
+-481 -494 0
+-480 -494 0
+-236 -494 0
+-231 -494 0
+-227 -494 0
+224 -494 0
+74 -494 0
+-7 -494 0
+52 -494 0
+51 -494 0
+478 -493 0
+7 21 231 -228 -79 236 480 -26 -27 493 0
+-480 -493 0
+-236 -493 0
+-231 -493 0
+228 -493 0
+79 -493 0
+-21 -493 0
+-7 -493 0
+26 -493 0
+27 -493 0
+478 -492 0
+7 13 -305 236 -232 -68 31 -318 -331 -42 -36 -48 492 0
+331 -492 0
+318 -492 0
+305 -492 0
+-236 -492 0
+232 -492 0
+68 -492 0
+-31 -492 0
+-13 -492 0
+-7 -492 0
+42 -492 0
+36 -492 0
+48 -492 0
+478 -491 0
+7 51 236 231 227 -224 -74 480 481 -52 491 0
+-481 -491 0
+-480 -491 0
+-236 -491 0
+-231 -491 0
+-227 -491 0
+224 -491 0
+74 -491 0
+-51 -491 0
+-7 -491 0
+52 -491 0
+478 -490 0
+7 21 231 -228 -79 27 236 480 -26 490 0
+-480 -490 0
+-236 -490 0
+-231 -490 0
+228 -490 0
+79 -490 0
+-27 -490 0
+-21 -490 0
+-7 -490 0
+26 -490 0
+478 -489 0
+7 13 236 -232 -68 31 48 -318 -331 -42 -36 489 0
+331 -489 0
+318 -489 0
+-236 -489 0
+232 -489 0
+68 -489 0
+-31 -489 0
+-48 -489 0
+-13 -489 0
+-7 -489 0
+42 -489 0
+36 -489 0
+478 -488 0
+12 -156 236 231 227 223 -218 370 -219 203 481 480 488 0
+-481 -488 0
+-480 -488 0
+-236 -488 0
+-231 -488 0
+-227 -488 0
+-223 -488 0
+218 -488 0
+-370 -488 0
+219 -488 0
+-203 -488 0
+-12 -488 0
+156 -488 0
+478 -487 0
+-148 149 236 231 227 223 217 -213 370 369 -214 480 481 487 0
+-481 -487 0
+-480 -487 0
+-236 -487 0
+-231 -487 0
+-227 -487 0
+-223 -487 0
+-217 -487 0
+213 -487 0
+-370 -487 0
+-369 -487 0
+214 -487 0
+-149 -487 0
+148 -487 0
+478 -486 0
+-188 -199 258 375 236 231 227 223 217 -253 370 369 -254 481 480 486 0
+-481 -486 0
+-480 -486 0
+-258 -486 0
+-375 -486 0
+-236 -486 0
+-231 -486 0
+-227 -486 0
+-223 -486 0
+-217 -486 0
+253 -486 0
+-370 -486 0
+-369 -486 0
+254 -486 0
+188 -486 0
+199 -486 0
+478 -485 0
+-188 199 258 375 236 231 227 223 217 -253 370 369 -254 480 481 485 0
+-481 -485 0
+-480 -485 0
+-258 -485 0
+-375 -485 0
+-236 -485 0
+-231 -485 0
+-227 -485 0
+-223 -485 0
+-217 -485 0
+253 -485 0
+-370 -485 0
+-369 -485 0
+254 -485 0
+-199 -485 0
+188 -485 0
+478 -484 0
+-180 -181 258 252 375 374 236 231 227 223 217 -247 370 369 -248 481 480 484 0
+-481 -484 0
+-480 -484 0
+-258 -484 0
+-252 -484 0
+-375 -484 0
+-374 -484 0
+-236 -484 0
+-231 -484 0
+-227 -484 0
+-223 -484 0
+-217 -484 0
+247 -484 0
+-370 -484 0
+-369 -484 0
+248 -484 0
+180 -484 0
+181 -484 0
+478 -483 0
+-180 181 258 252 375 374 236 231 227 223 217 -247 370 369 -248 480 481 483 0
+-481 -483 0
+-480 -483 0
+-258 -483 0
+-252 -483 0
+-375 -483 0
+-374 -483 0
+-236 -483 0
+-231 -483 0
+-227 -483 0
+-223 -483 0
+-217 -483 0
+247 -483 0
+-370 -483 0
+-369 -483 0
+248 -483 0
+-181 -483 0
+180 -483 0
+478 -482 0
+31 -57 258 252 246 375 374 373 236 231 227 223 217 370 369 480 481 482 0
+-481 -482 0
+-480 -482 0
+-258 -482 0
+-252 -482 0
+-246 -482 0
+-375 -482 0
+-374 -482 0
+-373 -482 0
+-236 -482 0
+-231 -482 0
+-227 -482 0
+-223 -482 0
+-217 -482 0
+-370 -482 0
+-369 -482 0
+57 -482 0
+-31 -482 0
+478 -479 0
+-148 -149 236 231 227 223 217 -213 370 369 -214 480 481 479 0
+-479 -481 0
+7 21 -79 -26 481 0
+79 -481 0
+-21 -481 0
+-7 -481 0
+26 -481 0
+-479 -480 0
+7 13 -68 -42 -36 480 0
+68 -480 0
+-13 -480 0
+-7 -480 0
+42 -480 0
+36 -480 0
+-236 -479 0
+-231 -479 0
+-227 -479 0
+-223 -479 0
+-217 -479 0
+213 -479 0
+-370 -479 0
+-369 -479 0
+214 -479 0
+149 -479 0
+148 -479 0
+57 -477 0
+-31 -477 0
+-4 23 0
+-23 24 471 470 469 468 467 466 465 451 417 351 345 344 343 143 136 472 473 0
+23 -473 0
+7 13 -318 -474 -71 48 -331 -129 -42 -36 -25 473 0
+129 -473 0
+331 -473 0
+318 -473 0
+-473 474 0
+-100 474 -475 0
+-100 -474 475 0
+100 474 -476 0
+100 -474 476 0
+7 13 31 48 -86 90 -42 -36 476 0
+-90 -476 0
+86 -476 0
+-31 -476 0
+-48 -476 0
+-13 -476 0
+-7 -476 0
+42 -476 0
+36 -476 0
+30 83 -210 286 -271 475 0
+-286 -475 0
+271 -475 0
+210 -475 0
+-30 -475 0
+-83 -475 0
+71 -473 0
+-48 -473 0
+-13 -473 0
+-7 -473 0
+42 -473 0
+36 -473 0
+25 -473 0
+23 -472 0
+12 -25 128 100 90 85 141 350 -347 346 -158 203 -129 -156 142 472 0
+129 -472 0
+-142 -472 0
+-128 -472 0
+-100 -472 0
+-90 -472 0
+-85 -472 0
+-141 -472 0
+-350 -472 0
+347 -472 0
+-346 -472 0
+158 -472 0
+-203 -472 0
+-12 -472 0
+156 -472 0
+25 -472 0
+23 -471 0
+-25 85 128 100 90 142 141 350 452 -458 346 387 -152 149 -148 -129 471 0
+129 -471 0
+-142 -471 0
+-128 -471 0
+-100 -471 0
+-90 -471 0
+-85 -471 0
+-141 -471 0
+-350 -471 0
+-452 -471 0
+458 -471 0
+-346 -471 0
+-387 -471 0
+152 -471 0
+-149 -471 0
+148 -471 0
+25 -471 0
+23 -470 0
+-25 85 128 457 100 90 142 141 350 452 -454 391 346 387 -190 -188 -129 -199 470 0
+129 -470 0
+-142 -470 0
+-128 -470 0
+-457 -470 0
+-100 -470 0
+-90 -470 0
+-85 -470 0
+-141 -470 0
+-350 -470 0
+-452 -470 0
+454 -470 0
+-391 -470 0
+-346 -470 0
+-387 -470 0
+190 -470 0
+188 -470 0
+25 -470 0
+199 -470 0
+23 -469 0
+-25 85 128 457 100 90 142 141 350 452 -454 391 346 387 -190 199 -188 -129 469 0
+129 -469 0
+-142 -469 0
+-128 -469 0
+-457 -469 0
+-100 -469 0
+-90 -469 0
+-85 -469 0
+-141 -469 0
+-350 -469 0
+-452 -469 0
+454 -469 0
+-391 -469 0
+-346 -469 0
+-387 -469 0
+190 -469 0
+-199 -469 0
+188 -469 0
+25 -469 0
+23 -468 0
+-25 85 128 457 453 100 90 142 141 350 452 -462 391 390 346 387 -184 -180 -129 -181 468 0
+129 -468 0
+-142 -468 0
+-128 -468 0
+-457 -468 0
+-453 -468 0
+-100 -468 0
+-90 -468 0
+-85 -468 0
+-141 -468 0
+-350 -468 0
+-452 -468 0
+462 -468 0
+-391 -468 0
+-390 -468 0
+-346 -468 0
+-387 -468 0
+184 -468 0
+180 -468 0
+25 -468 0
+181 -468 0
+23 -467 0
+-25 85 128 457 453 100 90 142 141 350 452 -462 391 390 346 387 -184 181 -180 -129 467 0
+129 -467 0
+-142 -467 0
+-128 -467 0
+-457 -467 0
+-453 -467 0
+-100 -467 0
+-90 -467 0
+-85 -467 0
+-141 -467 0
+-350 -467 0
+-452 -467 0
+462 -467 0
+-391 -467 0
+-390 -467 0
+-346 -467 0
+-387 -467 0
+184 -467 0
+-181 -467 0
+180 -467 0
+25 -467 0
+23 -466 0
+-25 85 128 100 90 142 141 350 452 -458 346 387 -152 -149 -148 -129 466 0
+129 -466 0
+-142 -466 0
+-128 -466 0
+-100 -466 0
+-90 -466 0
+-85 -466 0
+-141 -466 0
+-350 -466 0
+-452 -466 0
+458 -466 0
+-346 -466 0
+-387 -466 0
+152 -466 0
+149 -466 0
+148 -466 0
+25 -466 0
+23 -465 0
+25 30 83 129 465 0
+-129 -465 0
+-30 -465 0
+-83 -465 0
+-25 -465 0
+23 -451 0
+-25 30 128 461 457 453 100 90 85 141 350 452 142 83 402 391 390 346 387 -129 451 0
+129 -451 0
+-142 -451 0
+-128 -451 0
+-451 -461 0
+-180 461 -462 0
+-461 462 0
+-30 -186 462 0
+-30 186 -462 0
+30 462 -463 0
+30 -462 463 0
+-83 463 -464 0
+-83 -463 464 0
+83 -184 463 0
+83 184 -463 0
+180 -461 0
+-451 -457 0
+-148 457 -458 0
+-457 458 0
+-30 -154 458 0
+-30 154 -458 0
+30 458 -459 0
+30 -458 459 0
+-83 459 -460 0
+-83 -459 460 0
+83 -152 459 0
+83 152 -459 0
+148 -457 0
+-451 -453 0
+-188 453 -454 0
+-453 454 0
+-30 -192 454 0
+-30 192 -454 0
+30 454 -455 0
+30 -454 455 0
+-83 455 -456 0
+-83 -455 456 0
+83 -190 455 0
+83 190 -455 0
+188 -453 0
+-100 -451 0
+-90 -451 0
+-85 -451 0
+-141 -451 0
+-350 -451 0
+-451 -452 0
+12 -156 -347 452 0
+347 -452 0
+-12 -452 0
+156 -452 0
+-30 -451 0
+-83 -451 0
+-402 -451 0
+-391 -451 0
+-390 -451 0
+-346 -451 0
+-387 -451 0
+25 -451 0
+23 -417 0
+7 13 -447 432 -419 418 -289 -286 -119 -112 30 83 -107 101 -71 450 -129 -42 -36 -48 -25 417 0
+129 -417 0
+-417 -450 0
+-305 -318 -331 450 0
+331 -450 0
+318 -450 0
+305 -450 0
+-417 447 0
+-447 448 449 0
+447 -449 0
+30 83 366 -353 352 416 -403 449 0
+-416 -449 0
+403 -449 0
+-366 -449 0
+353 -449 0
+-352 -449 0
+-30 -449 0
+-83 -449 0
+447 -448 0
+30 83 -271 -210 -331 -318 448 0
+331 -448 0
+318 -448 0
+271 -448 0
+210 -448 0
+-30 -448 0
+-83 -448 0
+-417 -432 0
+31 -57 -385 -367 -433 352 -445 432 0
+-432 445 0
+290 300 302 301 303 446 -445 0
+445 -446 0
+7 13 31 299 -36 -35 446 0
+-299 -446 0
+-31 -446 0
+-13 -446 0
+-7 -446 0
+36 -446 0
+35 -446 0
+-303 445 0
+-302 445 0
+-301 445 0
+-300 445 0
+-290 445 0
+-352 -432 0
+385 -432 0
+367 -432 0
+-432 433 0
+-433 434 442 441 440 439 438 437 436 435 443 444 0
+433 -444 0
+31 -57 194 187 391 390 172 168 165 162 155 388 346 387 402 208 444 0
+-208 -444 0
+-402 -444 0
+-194 -444 0
+-187 -444 0
+-391 -444 0
+-390 -444 0
+-172 -444 0
+-168 -444 0
+-165 -444 0
+-162 -444 0
+-155 -444 0
+-388 -444 0
+-346 -444 0
+-387 -444 0
+57 -444 0
+-31 -444 0
+433 -443 0
+12 -156 165 162 -157 388 346 -158 -203 172 168 443 0
+-172 -443 0
+-168 -443 0
+-165 -443 0
+-162 -443 0
+157 -443 0
+-388 -443 0
+-346 -443 0
+158 -443 0
+203 -443 0
+-12 -443 0
+156 -443 0
+433 -442 0
+7 51 165 -163 388 -76 168 172 -52 442 0
+-172 -442 0
+-168 -442 0
+-165 -442 0
+163 -442 0
+-388 -442 0
+76 -442 0
+-51 -442 0
+-7 -442 0
+52 -442 0
+433 -441 0
+7 21 -166 -28 27 168 172 -26 441 0
+-172 -441 0
+-168 -441 0
+166 -441 0
+28 -441 0
+-27 -441 0
+-21 -441 0
+-7 -441 0
+26 -441 0
+433 -440 0
+12 -156 165 162 -157 388 346 -158 203 172 168 440 0
+-172 -440 0
+-168 -440 0
+-165 -440 0
+-162 -440 0
+157 -440 0
+-388 -440 0
+-346 -440 0
+158 -440 0
+-203 -440 0
+-12 -440 0
+156 -440 0
+433 -439 0
+-148 149 165 162 155 -151 388 346 387 -152 168 172 439 0
+-172 -439 0
+-168 -439 0
+-165 -439 0
+-162 -439 0
+-155 -439 0
+151 -439 0
+-388 -439 0
+-346 -439 0
+-387 -439 0
+152 -439 0
+-149 -439 0
+148 -439 0
+433 -438 0
+155 162 172 168 165 391 194 -189 388 346 387 -190 -188 -199 438 0
+-194 -438 0
+-391 -438 0
+-172 -438 0
+-168 -438 0
+-165 -438 0
+-162 -438 0
+-155 -438 0
+189 -438 0
+-388 -438 0
+-346 -438 0
+-387 -438 0
+190 -438 0
+188 -438 0
+199 -438 0
+433 -437 0
+155 162 172 168 165 391 194 -189 388 346 387 -190 199 -188 437 0
+-194 -437 0
+-391 -437 0
+-172 -437 0
+-168 -437 0
+-165 -437 0
+-162 -437 0
+-155 -437 0
+189 -437 0
+-388 -437 0
+-346 -437 0
+-387 -437 0
+190 -437 0
+-199 -437 0
+188 -437 0
+433 -436 0
+155 162 391 390 172 168 165 187 194 -183 388 346 387 -184 -180 -181 436 0
+-194 -436 0
+-187 -436 0
+-391 -436 0
+-390 -436 0
+-172 -436 0
+-168 -436 0
+-165 -436 0
+-162 -436 0
+-155 -436 0
+183 -436 0
+-388 -436 0
+-346 -436 0
+-387 -436 0
+184 -436 0
+180 -436 0
+181 -436 0
+433 -435 0
+155 162 391 390 172 168 165 187 194 -183 388 346 387 -184 181 -180 435 0
+-194 -435 0
+-187 -435 0
+-391 -435 0
+-390 -435 0
+-172 -435 0
+-168 -435 0
+-165 -435 0
+-162 -435 0
+-155 -435 0
+183 -435 0
+-388 -435 0
+-346 -435 0
+-387 -435 0
+184 -435 0
+-181 -435 0
+180 -435 0
+433 -434 0
+-148 -149 165 162 155 -151 388 346 387 -152 168 172 434 0
+-172 -434 0
+-168 -434 0
+-165 -434 0
+-162 -434 0
+-155 -434 0
+151 -434 0
+-388 -434 0
+-346 -434 0
+-387 -434 0
+152 -434 0
+149 -434 0
+148 -434 0
+57 -432 0
+-31 -432 0
+-417 419 0
+204 -419 429 428 427 426 425 424 423 422 421 420 431 430 0
+419 -431 0
+30 83 196 195 177 176 308 209 208 194 187 172 168 165 162 155 431 0
+-308 -431 0
+-209 -431 0
+-196 -431 0
+-195 -431 0
+-177 -431 0
+-176 -431 0
+-30 -431 0
+-83 -431 0
+-208 -431 0
+-194 -431 0
+-187 -431 0
+-172 -431 0
+-168 -431 0
+-165 -431 0
+-162 -431 0
+-155 -431 0
+419 -430 0
+12 -156 172 168 165 162 -157 -161 -203 308 177 430 0
+-308 -430 0
+-177 -430 0
+-172 -430 0
+-168 -430 0
+-165 -430 0
+-162 -430 0
+157 -430 0
+161 -430 0
+203 -430 0
+-12 -430 0
+156 -430 0
+419 -429 0
+7 -51 168 165 -163 -56 308 -52 172 429 0
+-308 -429 0
+-172 -429 0
+-168 -429 0
+-165 -429 0
+163 -429 0
+56 -429 0
+-7 -429 0
+52 -429 0
+51 -429 0
+419 -428 0
+7 21 -166 -49 168 172 -26 -27 428 0
+-172 -428 0
+-168 -428 0
+166 -428 0
+49 -428 0
+-21 -428 0
+-7 -428 0
+26 -428 0
+27 -428 0
+419 -427 0
+7 51 168 165 -163 -56 172 308 -52 427 0
+-308 -427 0
+-172 -427 0
+-168 -427 0
+-165 -427 0
+163 -427 0
+56 -427 0
+-51 -427 0
+-7 -427 0
+52 -427 0
+419 -426 0
+12 -156 172 168 165 162 -157 -161 203 308 177 426 0
+-308 -426 0
+-177 -426 0
+-172 -426 0
+-168 -426 0
+-165 -426 0
+-162 -426 0
+157 -426 0
+161 -426 0
+-203 -426 0
+-12 -426 0
+156 -426 0
+419 -425 0
+-148 149 176 172 168 165 162 155 -151 -150 177 308 425 0
+-308 -425 0
+-177 -425 0
+-176 -425 0
+-172 -425 0
+-168 -425 0
+-165 -425 0
+-162 -425 0
+-155 -425 0
+151 -425 0
+150 -425 0
+-149 -425 0
+148 -425 0
+419 -424 0
+155 162 177 176 194 172 168 165 196 308 -189 -193 -188 -199 424 0
+-308 -424 0
+-196 -424 0
+-177 -424 0
+-176 -424 0
+-194 -424 0
+-172 -424 0
+-168 -424 0
+-165 -424 0
+-162 -424 0
+-155 -424 0
+189 -424 0
+193 -424 0
+188 -424 0
+199 -424 0
+419 -423 0
+155 162 177 176 194 172 168 165 196 308 -189 -193 199 -188 423 0
+-308 -423 0
+-196 -423 0
+-177 -423 0
+-176 -423 0
+-194 -423 0
+-172 -423 0
+-168 -423 0
+-165 -423 0
+-162 -423 0
+-155 -423 0
+189 -423 0
+193 -423 0
+-199 -423 0
+188 -423 0
+419 -422 0
+155 162 195 177 176 194 187 172 168 165 196 308 -183 -182 -180 -181 422 0
+-308 -422 0
+-196 -422 0
+-195 -422 0
+-177 -422 0
+-176 -422 0
+-194 -422 0
+-187 -422 0
+-172 -422 0
+-168 -422 0
+-165 -422 0
+-162 -422 0
+-155 -422 0
+183 -422 0
+182 -422 0
+180 -422 0
+181 -422 0
+419 -421 0
+155 162 195 177 176 194 187 172 168 165 196 308 -183 -182 181 -180 421 0
+-308 -421 0
+-196 -421 0
+-195 -421 0
+-177 -421 0
+-176 -421 0
+-194 -421 0
+-187 -421 0
+-172 -421 0
+-168 -421 0
+-165 -421 0
+-162 -421 0
+-155 -421 0
+183 -421 0
+182 -421 0
+-181 -421 0
+180 -421 0
+419 -420 0
+-148 -149 176 172 168 165 162 155 -151 -150 177 308 420 0
+-308 -420 0
+-177 -420 0
+-176 -420 0
+-172 -420 0
+-168 -420 0
+-165 -420 0
+-162 -420 0
+-155 -420 0
+151 -420 0
+150 -420 0
+149 -420 0
+148 -420 0
+-204 419 0
+-417 -418 0
+30 83 -210 -146 -289 -271 418 0
+289 -418 0
+271 -418 0
+210 -418 0
+146 -418 0
+-30 -418 0
+-83 -418 0
+289 -417 0
+286 -417 0
+119 -417 0
+112 -417 0
+-30 -417 0
+-83 -417 0
+107 -417 0
+-101 -417 0
+71 -417 0
+-13 -417 0
+-7 -417 0
+42 -417 0
+36 -417 0
+48 -417 0
+25 -417 0
+23 -351 0
+7 13 -403 366 -353 286 352 -119 -112 30 83 -107 101 -71 48 416 -129 -42 -36 -25 351 0
+129 -351 0
+-351 -416 0
+-318 -331 416 0
+331 -416 0
+318 -416 0
+-351 403 0
+281 284 413 412 411 410 409 408 407 406 405 404 414 415 -403 0
+403 -415 0
+30 -47 209 196 195 177 176 308 83 208 194 187 172 168 165 162 155 -273 415 0
+-308 -415 0
+273 -415 0
+-209 -415 0
+-196 -415 0
+-195 -415 0
+-177 -415 0
+-176 -415 0
+-30 -415 0
+-83 -415 0
+-208 -415 0
+-194 -415 0
+-187 -415 0
+-172 -415 0
+-168 -415 0
+-165 -415 0
+-162 -415 0
+-155 -415 0
+47 -415 0
+403 -414 0
+12 -47 177 172 168 165 162 -157 -161 -203 308 -156 -273 414 0
+-308 -414 0
+273 -414 0
+-177 -414 0
+-172 -414 0
+-168 -414 0
+-165 -414 0
+-162 -414 0
+157 -414 0
+161 -414 0
+203 -414 0
+-12 -414 0
+156 -414 0
+47 -414 0
+403 -413 0
+7 -47 172 168 165 -163 -56 308 -52 -51 -273 413 0
+-308 -413 0
+273 -413 0
+-172 -413 0
+-168 -413 0
+-165 -413 0
+163 -413 0
+56 -413 0
+-7 -413 0
+52 -413 0
+51 -413 0
+47 -413 0
+403 -412 0
+7 21 168 -166 -49 172 -273 -26 -27 -47 412 0
+273 -412 0
+-172 -412 0
+-168 -412 0
+166 -412 0
+49 -412 0
+-21 -412 0
+-7 -412 0
+26 -412 0
+27 -412 0
+47 -412 0
+403 -411 0
+7 -47 172 168 165 -163 -56 51 308 -52 -273 411 0
+-308 -411 0
+273 -411 0
+-172 -411 0
+-168 -411 0
+-165 -411 0
+163 -411 0
+56 -411 0
+-51 -411 0
+-7 -411 0
+52 -411 0
+47 -411 0
+403 -410 0
+12 -47 177 172 168 165 162 -157 -161 203 308 -156 -273 410 0
+-308 -410 0
+273 -410 0
+-177 -410 0
+-172 -410 0
+-168 -410 0
+-165 -410 0
+-162 -410 0
+157 -410 0
+161 -410 0
+-203 -410 0
+-12 -410 0
+156 -410 0
+47 -410 0
+403 -409 0
+-47 -148 177 176 172 168 165 162 155 -151 -150 149 -273 308 409 0
+-308 -409 0
+273 -409 0
+-177 -409 0
+-176 -409 0
+-172 -409 0
+-168 -409 0
+-165 -409 0
+-162 -409 0
+-155 -409 0
+151 -409 0
+150 -409 0
+-149 -409 0
+148 -409 0
+47 -409 0
+403 -408 0
+-47 155 196 177 176 194 172 168 165 162 -273 -189 -193 -188 308 -199 408 0
+-308 -408 0
+273 -408 0
+-196 -408 0
+-177 -408 0
+-176 -408 0
+-194 -408 0
+-172 -408 0
+-168 -408 0
+-165 -408 0
+-162 -408 0
+-155 -408 0
+189 -408 0
+193 -408 0
+188 -408 0
+47 -408 0
+199 -408 0
+403 -407 0
+-47 155 196 177 176 194 172 168 165 162 -273 -189 -193 199 -188 308 407 0
+-308 -407 0
+273 -407 0
+-196 -407 0
+-177 -407 0
+-176 -407 0
+-194 -407 0
+-172 -407 0
+-168 -407 0
+-165 -407 0
+-162 -407 0
+-155 -407 0
+189 -407 0
+193 -407 0
+-199 -407 0
+188 -407 0
+47 -407 0
+403 -406 0
+-47 155 196 195 177 176 194 187 172 168 165 162 -273 -183 -182 -180 308 -181 406 0
+-308 -406 0
+273 -406 0
+-196 -406 0
+-195 -406 0
+-177 -406 0
+-176 -406 0
+-194 -406 0
+-187 -406 0
+-172 -406 0
+-168 -406 0
+-165 -406 0
+-162 -406 0
+-155 -406 0
+183 -406 0
+182 -406 0
+180 -406 0
+47 -406 0
+181 -406 0
+403 -405 0
+-47 155 196 195 177 176 194 187 172 168 165 162 -273 -183 -182 181 -180 308 405 0
+-308 -405 0
+273 -405 0
+-196 -405 0
+-195 -405 0
+-177 -405 0
+-176 -405 0
+-194 -405 0
+-187 -405 0
+-172 -405 0
+-168 -405 0
+-165 -405 0
+-162 -405 0
+-155 -405 0
+183 -405 0
+182 -405 0
+-181 -405 0
+180 -405 0
+47 -405 0
+403 -404 0
+-47 -148 177 176 172 168 165 162 155 -151 -150 -149 -273 308 404 0
+-308 -404 0
+273 -404 0
+-177 -404 0
+-176 -404 0
+-172 -404 0
+-168 -404 0
+-165 -404 0
+-162 -404 0
+-155 -404 0
+151 -404 0
+150 -404 0
+149 -404 0
+148 -404 0
+47 -404 0
+-284 403 0
+-281 403 0
+-351 -366 0
+31 -57 -367 -385 366 0
+-366 385 0
+-385 386 399 398 397 396 395 394 393 392 389 400 401 0
+385 -401 0
+-25 31 402 194 187 391 390 172 168 165 162 155 388 346 387 -57 208 -273 401 0
+273 -401 0
+-208 -401 0
+-401 -402 0
+-180 -184 402 0
+184 -402 0
+180 -402 0
+-194 -401 0
+-187 -401 0
+-391 -401 0
+-390 -401 0
+-172 -401 0
+-168 -401 0
+-165 -401 0
+-162 -401 0
+-155 -401 0
+-388 -401 0
+-346 -401 0
+-387 -401 0
+57 -401 0
+-31 -401 0
+25 -401 0
+385 -400 0
+25 31 -57 273 400 0
+-273 -400 0
+57 -400 0
+-31 -400 0
+-25 -400 0
+385 -399 0
+12 -25 168 165 162 -157 388 346 -158 -203 -273 -156 172 399 0
+273 -399 0
+-172 -399 0
+-168 -399 0
+-165 -399 0
+-162 -399 0
+157 -399 0
+-388 -399 0
+-346 -399 0
+158 -399 0
+203 -399 0
+-12 -399 0
+156 -399 0
+25 -399 0
+385 -398 0
+7 -25 168 165 -163 388 -76 51 -273 -52 172 398 0
+273 -398 0
+-172 -398 0
+-168 -398 0
+-165 -398 0
+163 -398 0
+-388 -398 0
+76 -398 0
+-51 -398 0
+-7 -398 0
+52 -398 0
+25 -398 0
+385 -397 0
+7 21 168 -166 -28 27 172 -273 -26 -25 397 0
+273 -397 0
+-172 -397 0
+-168 -397 0
+166 -397 0
+28 -397 0
+-27 -397 0
+-21 -397 0
+-7 -397 0
+26 -397 0
+25 -397 0
+385 -396 0
+12 -25 168 165 162 -157 388 346 -158 203 -273 -156 172 396 0
+273 -396 0
+-172 -396 0
+-168 -396 0
+-165 -396 0
+-162 -396 0
+157 -396 0
+-388 -396 0
+-346 -396 0
+158 -396 0
+-203 -396 0
+-12 -396 0
+156 -396 0
+25 -396 0
+385 -395 0
+-25 -148 168 165 162 155 -151 388 346 387 -152 149 172 -273 395 0
+273 -395 0
+-172 -395 0
+-168 -395 0
+-165 -395 0
+-162 -395 0
+-155 -395 0
+151 -395 0
+-388 -395 0
+-346 -395 0
+-387 -395 0
+152 -395 0
+-149 -395 0
+148 -395 0
+25 -395 0
+385 -394 0
+-25 155 391 172 168 165 162 194 -189 388 346 387 -190 -188 -273 -199 394 0
+273 -394 0
+-194 -394 0
+-391 -394 0
+-172 -394 0
+-168 -394 0
+-165 -394 0
+-162 -394 0
+-155 -394 0
+189 -394 0
+-388 -394 0
+-346 -394 0
+-387 -394 0
+190 -394 0
+188 -394 0
+25 -394 0
+199 -394 0
+385 -393 0
+-25 155 391 172 168 165 162 194 -189 388 346 387 -190 199 -188 -273 393 0
+273 -393 0
+-194 -393 0
+-391 -393 0
+-172 -393 0
+-168 -393 0
+-165 -393 0
+-162 -393 0
+-155 -393 0
+189 -393 0
+-388 -393 0
+-346 -393 0
+-387 -393 0
+190 -393 0
+-199 -393 0
+188 -393 0
+25 -393 0
+385 -392 0
+-25 155 187 391 390 172 168 165 162 194 -183 388 346 387 -184 -180 -273 -181 392 0
+273 -392 0
+-194 -392 0
+-187 -392 0
+-391 -392 0
+-390 -392 0
+-172 -392 0
+-168 -392 0
+-165 -392 0
+-162 -392 0
+-155 -392 0
+183 -392 0
+-388 -392 0
+-346 -392 0
+-387 -392 0
+184 -392 0
+180 -392 0
+25 -392 0
+181 -392 0
+385 -389 0
+-25 155 187 391 390 172 168 165 162 194 -183 388 346 387 -184 181 -180 -273 389 0
+273 -389 0
+-194 -389 0
+-187 -389 0
+-389 -391 0
+-148 -152 391 0
+152 -391 0
+148 -391 0
+-389 -390 0
+-188 -190 390 0
+190 -390 0
+188 -390 0
+-172 -389 0
+-168 -389 0
+-165 -389 0
+-162 -389 0
+-155 -389 0
+183 -389 0
+-388 -389 0
+-346 -389 0
+-387 -389 0
+184 -389 0
+-181 -389 0
+180 -389 0
+25 -389 0
+385 -386 0
+-25 -148 168 165 162 155 -151 388 346 387 -152 -149 172 -273 386 0
+273 -386 0
+-172 -386 0
+-168 -386 0
+-165 -386 0
+-162 -386 0
+-155 -386 0
+151 -386 0
+-386 -388 0
+7 -26 -28 388 0
+28 -388 0
+-7 -388 0
+26 -388 0
+-346 -386 0
+-386 -387 0
+12 -156 -158 387 0
+158 -387 0
+-12 -387 0
+156 -387 0
+152 -386 0
+149 -386 0
+148 -386 0
+25 -386 0
+-366 367 0
+-367 368 382 381 380 379 378 377 376 372 383 384 0
+367 -384 0
+12 -156 227 223 -218 371 370 -219 -203 236 231 384 0
+-236 -384 0
+-231 -384 0
+-227 -384 0
+-223 -384 0
+218 -384 0
+-371 -384 0
+-370 -384 0
+219 -384 0
+203 -384 0
+-12 -384 0
+156 -384 0
+367 -383 0
+7 51 227 -224 371 -74 231 236 -52 383 0
+-236 -383 0
+-231 -383 0
+-227 -383 0
+224 -383 0
+-371 -383 0
+74 -383 0
+-51 -383 0
+-7 -383 0
+52 -383 0
+367 -382 0
+7 21 -228 -79 27 231 236 -26 382 0
+-236 -382 0
+-231 -382 0
+228 -382 0
+79 -382 0
+-27 -382 0
+-21 -382 0
+-7 -382 0
+26 -382 0
+367 -381 0
+12 -156 227 223 -218 371 370 -219 203 236 231 381 0
+-236 -381 0
+-231 -381 0
+-227 -381 0
+-223 -381 0
+218 -381 0
+-371 -381 0
+-370 -381 0
+219 -381 0
+-203 -381 0
+-12 -381 0
+156 -381 0
+367 -380 0
+-148 149 227 223 217 -213 371 370 369 -214 231 236 380 0
+-236 -380 0
+-231 -380 0
+-227 -380 0
+-223 -380 0
+-217 -380 0
+213 -380 0
+-371 -380 0
+-370 -380 0
+-369 -380 0
+214 -380 0
+-149 -380 0
+148 -380 0
+367 -379 0
+-188 -199 236 231 227 223 217 -253 371 370 369 -254 258 375 379 0
+-258 -379 0
+-375 -379 0
+-236 -379 0
+-231 -379 0
+-227 -379 0
+-223 -379 0
+-217 -379 0
+253 -379 0
+-371 -379 0
+-370 -379 0
+-369 -379 0
+254 -379 0
+188 -379 0
+199 -379 0
+367 -378 0
+-188 199 236 231 227 223 217 -253 371 370 369 -254 375 258 378 0
+-258 -378 0
+-375 -378 0
+-236 -378 0
+-231 -378 0
+-227 -378 0
+-223 -378 0
+-217 -378 0
+253 -378 0
+-371 -378 0
+-370 -378 0
+-369 -378 0
+254 -378 0
+-199 -378 0
+188 -378 0
+367 -377 0
+-180 -181 375 374 236 231 227 223 217 -247 371 370 369 -248 258 252 377 0
+-258 -377 0
+-252 -377 0
+-375 -377 0
+-374 -377 0
+-236 -377 0
+-231 -377 0
+-227 -377 0
+-223 -377 0
+-217 -377 0
+247 -377 0
+-371 -377 0
+-370 -377 0
+-369 -377 0
+248 -377 0
+180 -377 0
+181 -377 0
+367 -376 0
+-180 181 375 374 236 231 227 223 217 -247 371 370 369 -248 252 258 376 0
+-258 -376 0
+-252 -376 0
+-375 -376 0
+-374 -376 0
+-236 -376 0
+-231 -376 0
+-227 -376 0
+-223 -376 0
+-217 -376 0
+247 -376 0
+-371 -376 0
+-370 -376 0
+-369 -376 0
+248 -376 0
+-181 -376 0
+180 -376 0
+367 -372 0
+31 -57 246 375 374 373 236 231 227 223 217 371 370 369 252 258 372 0
+-258 -372 0
+-252 -372 0
+-246 -372 0
+-372 -375 0
+-148 -214 375 0
+214 -375 0
+148 -375 0
+-372 -374 0
+-188 -254 374 0
+254 -374 0
+188 -374 0
+-372 -373 0
+-180 -248 373 0
+248 -373 0
+180 -373 0
+-236 -372 0
+-231 -372 0
+-227 -372 0
+-223 -372 0
+-217 -372 0
+-371 -372 0
+-370 -372 0
+-369 -372 0
+57 -372 0
+-31 -372 0
+367 -368 0
+-148 -149 227 223 217 -213 371 370 369 -214 231 236 368 0
+-236 -368 0
+-231 -368 0
+-227 -368 0
+-223 -368 0
+-217 -368 0
+213 -368 0
+-368 -371 0
+7 -26 -79 371 0
+79 -371 0
+-7 -371 0
+26 -371 0
+-368 -370 0
+7 -52 -74 370 0
+74 -370 0
+-7 -370 0
+52 -370 0
+-368 -369 0
+12 -156 -219 369 0
+219 -369 0
+-12 -369 0
+156 -369 0
+214 -368 0
+149 -368 0
+148 -368 0
+57 -366 0
+-31 -366 0
+-351 353 0
+268 -353 363 362 361 360 359 358 357 356 355 354 365 364 0
+353 -365 0
+12 -156 236 231 227 223 -218 -222 -203 321 243 365 0
+-321 -365 0
+-243 -365 0
+-236 -365 0
+-231 -365 0
+-227 -365 0
+-223 -365 0
+218 -365 0
+222 -365 0
+203 -365 0
+-12 -365 0
+156 -365 0
+353 -364 0
+7 -51 231 227 -224 -54 321 -52 236 364 0
+-321 -364 0
+-236 -364 0
+-231 -364 0
+-227 -364 0
+224 -364 0
+54 -364 0
+-7 -364 0
+52 -364 0
+51 -364 0
+353 -363 0
+7 21 -228 -44 231 236 -26 -27 363 0
+-236 -363 0
+-231 -363 0
+228 -363 0
+44 -363 0
+-21 -363 0
+-7 -363 0
+26 -363 0
+27 -363 0
+353 -362 0
+7 51 231 227 -224 -54 236 321 -52 362 0
+-321 -362 0
+-236 -362 0
+-231 -362 0
+-227 -362 0
+224 -362 0
+54 -362 0
+-51 -362 0
+-7 -362 0
+52 -362 0
+353 -361 0
+12 -156 236 231 227 223 -218 -222 203 321 243 361 0
+-321 -361 0
+-243 -361 0
+-236 -361 0
+-231 -361 0
+-227 -361 0
+-223 -361 0
+218 -361 0
+222 -361 0
+-203 -361 0
+-12 -361 0
+156 -361 0
+353 -360 0
+-148 149 242 236 231 227 223 217 -213 -212 243 321 360 0
+-321 -360 0
+-243 -360 0
+-242 -360 0
+-236 -360 0
+-231 -360 0
+-227 -360 0
+-223 -360 0
+-217 -360 0
+213 -360 0
+212 -360 0
+-149 -360 0
+148 -360 0
+353 -359 0
+-188 -199 243 242 258 236 231 227 223 217 -253 -257 321 261 359 0
+-321 -359 0
+-261 -359 0
+-243 -359 0
+-242 -359 0
+-258 -359 0
+-236 -359 0
+-231 -359 0
+-227 -359 0
+-223 -359 0
+-217 -359 0
+253 -359 0
+257 -359 0
+188 -359 0
+199 -359 0
+353 -358 0
+-188 199 243 242 258 236 231 227 223 217 -253 -257 261 321 358 0
+-321 -358 0
+-261 -358 0
+-243 -358 0
+-242 -358 0
+-258 -358 0
+-236 -358 0
+-231 -358 0
+-227 -358 0
+-223 -358 0
+-217 -358 0
+253 -358 0
+257 -358 0
+-199 -358 0
+188 -358 0
+353 -357 0
+-180 -181 260 243 242 258 252 236 231 227 223 217 -247 -251 321 261 357 0
+-321 -357 0
+-261 -357 0
+-260 -357 0
+-243 -357 0
+-242 -357 0
+-258 -357 0
+-252 -357 0
+-236 -357 0
+-231 -357 0
+-227 -357 0
+-223 -357 0
+-217 -357 0
+247 -357 0
+251 -357 0
+180 -357 0
+181 -357 0
+353 -356 0
+-180 181 260 243 242 258 252 236 231 227 223 217 -247 -251 261 321 356 0
+-321 -356 0
+-261 -356 0
+-260 -356 0
+-243 -356 0
+-242 -356 0
+-258 -356 0
+-252 -356 0
+-236 -356 0
+-231 -356 0
+-227 -356 0
+-223 -356 0
+-217 -356 0
+247 -356 0
+251 -356 0
+-181 -356 0
+180 -356 0
+353 -355 0
+30 83 260 259 243 242 321 261 258 252 246 236 231 227 223 217 355 0
+-321 -355 0
+-261 -355 0
+-260 -355 0
+-259 -355 0
+-243 -355 0
+-242 -355 0
+-30 -355 0
+-83 -355 0
+-258 -355 0
+-252 -355 0
+-246 -355 0
+-236 -355 0
+-231 -355 0
+-227 -355 0
+-223 -355 0
+-217 -355 0
+353 -354 0
+-148 -149 242 236 231 227 223 217 -213 -212 243 321 354 0
+-321 -354 0
+-243 -354 0
+-242 -354 0
+-236 -354 0
+-231 -354 0
+-227 -354 0
+-223 -354 0
+-217 -354 0
+213 -354 0
+212 -354 0
+149 -354 0
+148 -354 0
+-268 353 0
+-286 -351 0
+-351 -352 0
+30 83 -271 -210 352 0
+271 -352 0
+210 -352 0
+-30 -352 0
+-83 -352 0
+119 -351 0
+112 -351 0
+-30 -351 0
+-83 -351 0
+107 -351 0
+-101 -351 0
+71 -351 0
+-48 -351 0
+-13 -351 0
+-7 -351 0
+42 -351 0
+36 -351 0
+25 -351 0
+23 -345 0
+12 -25 128 100 90 85 141 350 -347 346 -158 -203 -129 -156 142 345 0
+129 -345 0
+-142 -345 0
+-128 -345 0
+-100 -345 0
+-90 -345 0
+-85 -345 0
+-141 -345 0
+-345 -350 0
+7 -52 -137 350 0
+137 -350 0
+-7 -350 0
+52 -350 0
+-345 347 0
+-30 -160 347 0
+-30 160 -347 0
+30 347 -348 0
+30 -347 348 0
+-83 348 -349 0
+-83 -348 349 0
+83 -158 348 0
+83 158 -348 0
+-345 -346 0
+7 -52 -76 346 0
+76 -346 0
+-7 -346 0
+52 -346 0
+158 -345 0
+203 -345 0
+-12 -345 0
+156 -345 0
+25 -345 0
+23 -344 0
+7 -25 128 100 90 85 141 -137 -76 -129 -52 -51 142 344 0
+129 -344 0
+-142 -344 0
+-128 -344 0
+-100 -344 0
+-90 -344 0
+-85 -344 0
+-141 -344 0
+137 -344 0
+76 -344 0
+-7 -344 0
+52 -344 0
+51 -344 0
+25 -344 0
+23 -343 0
+7 21 100 90 85 -29 -28 128 -129 -26 -27 -25 343 0
+129 -343 0
+-128 -343 0
+-100 -343 0
+-90 -343 0
+-85 -343 0
+29 -343 0
+28 -343 0
+-21 -343 0
+-7 -343 0
+26 -343 0
+27 -343 0
+25 -343 0
+23 -143 0
+7 13 -318 -305 -144 -71 -331 -129 -42 -36 -48 -25 143 0
+129 -143 0
+-143 331 0
+-47 -331 340 339 338 337 336 335 334 333 332 342 341 0
+331 -342 0
+-47 176 196 195 178 177 209 308 342 0
+-308 -342 0
+-209 -342 0
+-196 -342 0
+-195 -342 0
+-178 -342 0
+-177 -342 0
+-176 -342 0
+47 -342 0
+331 -341 0
+12 -47 177 -161 -203 308 -156 178 341 0
+-308 -341 0
+-178 -341 0
+-177 -341 0
+161 -341 0
+203 -341 0
+-12 -341 0
+156 -341 0
+47 -341 0
+331 -340 0
+7 -47 -56 51 308 -52 178 340 0
+-308 -340 0
+-178 -340 0
+56 -340 0
+-51 -340 0
+-7 -340 0
+52 -340 0
+47 -340 0
+331 -339 0
+12 -47 177 -161 203 308 -156 178 339 0
+-308 -339 0
+-178 -339 0
+-177 -339 0
+161 -339 0
+-203 -339 0
+-12 -339 0
+156 -339 0
+47 -339 0
+331 -338 0
+-47 -148 177 176 -150 149 178 308 338 0
+-308 -338 0
+-178 -338 0
+-177 -338 0
+-176 -338 0
+150 -338 0
+-149 -338 0
+148 -338 0
+47 -338 0
+331 -337 0
+-47 176 178 177 196 -193 -188 308 -199 337 0
+-308 -337 0
+-196 -337 0
+-178 -337 0
+-177 -337 0
+-176 -337 0
+193 -337 0
+188 -337 0
+47 -337 0
+199 -337 0
+331 -336 0
+-47 176 178 177 196 -193 199 -188 308 336 0
+-308 -336 0
+-196 -336 0
+-178 -336 0
+-177 -336 0
+-176 -336 0
+193 -336 0
+-199 -336 0
+188 -336 0
+47 -336 0
+331 -335 0
+-47 176 195 178 177 196 -182 -180 308 -181 335 0
+-308 -335 0
+-196 -335 0
+-195 -335 0
+-178 -335 0
+-177 -335 0
+-176 -335 0
+182 -335 0
+180 -335 0
+47 -335 0
+181 -335 0
+331 -334 0
+-47 176 195 178 177 196 -182 181 -180 308 334 0
+-308 -334 0
+-196 -334 0
+-195 -334 0
+-178 -334 0
+-177 -334 0
+-176 -334 0
+182 -334 0
+-181 -334 0
+180 -334 0
+47 -334 0
+331 -333 0
+-47 -148 177 176 -150 -149 178 308 333 0
+-308 -333 0
+-178 -333 0
+-177 -333 0
+-176 -333 0
+150 -333 0
+149 -333 0
+148 -333 0
+47 -333 0
+331 -332 0
+7 21 27 -49 -26 -47 332 0
+49 -332 0
+-27 -332 0
+-21 -332 0
+-7 -332 0
+26 -332 0
+47 -332 0
+47 331 0
+-143 318 0
+-318 319 328 327 326 325 324 323 322 320 329 330 0
+318 -330 0
+12 -156 243 -222 -203 321 244 330 0
+-321 -330 0
+-244 -330 0
+-243 -330 0
+222 -330 0
+203 -330 0
+-12 -330 0
+156 -330 0
+318 -329 0
+7 51 -54 244 321 -52 329 0
+-321 -329 0
+-244 -329 0
+54 -329 0
+-51 -329 0
+-7 -329 0
+52 -329 0
+318 -328 0
+12 -156 243 -222 203 321 244 328 0
+-321 -328 0
+-244 -328 0
+-243 -328 0
+222 -328 0
+-203 -328 0
+-12 -328 0
+156 -328 0
+318 -327 0
+-148 149 243 242 -212 244 321 327 0
+-321 -327 0
+-244 -327 0
+-243 -327 0
+-242 -327 0
+212 -327 0
+-149 -327 0
+148 -327 0
+318 -326 0
+-188 -199 244 243 242 -257 321 261 326 0
+-321 -326 0
+-261 -326 0
+-244 -326 0
+-243 -326 0
+-242 -326 0
+257 -326 0
+188 -326 0
+199 -326 0
+318 -325 0
+-188 199 244 243 242 -257 261 321 325 0
+-321 -325 0
+-261 -325 0
+-244 -325 0
+-243 -325 0
+-242 -325 0
+257 -325 0
+-199 -325 0
+188 -325 0
+318 -324 0
+-180 -181 260 244 243 242 -251 321 261 324 0
+-321 -324 0
+-261 -324 0
+-260 -324 0
+-244 -324 0
+-243 -324 0
+-242 -324 0
+251 -324 0
+180 -324 0
+181 -324 0
+318 -323 0
+-180 181 260 244 243 242 -251 261 321 323 0
+-321 -323 0
+-261 -323 0
+-260 -323 0
+-244 -323 0
+-243 -323 0
+-242 -323 0
+251 -323 0
+-181 -323 0
+180 -323 0
+318 -322 0
+242 243 260 259 244 261 321 322 0
+-321 -322 0
+-261 -322 0
+-260 -322 0
+-259 -322 0
+-244 -322 0
+-243 -322 0
+-242 -322 0
+318 -320 0
+-148 -149 243 242 -212 244 321 320 0
+-320 -321 0
+7 21 -44 -26 321 0
+44 -321 0
+-21 -321 0
+-7 -321 0
+26 -321 0
+-244 -320 0
+-243 -320 0
+-242 -320 0
+212 -320 0
+149 -320 0
+148 -320 0
+318 -319 0
+7 21 27 -44 -26 319 0
+44 -319 0
+-27 -319 0
+-21 -319 0
+-7 -319 0
+26 -319 0
+-143 305 0
+-305 306 315 314 313 312 311 310 309 307 316 317 0
+305 -317 0
+176 177 196 195 178 209 308 317 0
+-308 -317 0
+-209 -317 0
+-196 -317 0
+-195 -317 0
+-178 -317 0
+-177 -317 0
+-176 -317 0
+305 -316 0
+12 -156 177 -161 -203 308 178 316 0
+-308 -316 0
+-178 -316 0
+-177 -316 0
+161 -316 0
+203 -316 0
+-12 -316 0
+156 -316 0
+305 -315 0
+7 51 -56 178 308 -52 315 0
+-308 -315 0
+-178 -315 0
+56 -315 0
+-51 -315 0
+-7 -315 0
+52 -315 0
+305 -314 0
+12 -156 177 -161 203 308 178 314 0
+-308 -314 0
+-178 -314 0
+-177 -314 0
+161 -314 0
+-203 -314 0
+-12 -314 0
+156 -314 0
+305 -313 0
+-148 149 177 176 -150 178 308 313 0
+-308 -313 0
+-178 -313 0
+-177 -313 0
+-176 -313 0
+150 -313 0
+-149 -313 0
+148 -313 0
+305 -312 0
+176 177 178 196 308 -193 -188 -199 312 0
+-308 -312 0
+-196 -312 0
+-178 -312 0
+-177 -312 0
+-176 -312 0
+193 -312 0
+188 -312 0
+199 -312 0
+305 -311 0
+176 177 178 196 308 -193 199 -188 311 0
+-308 -311 0
+-196 -311 0
+-178 -311 0
+-177 -311 0
+-176 -311 0
+193 -311 0
+-199 -311 0
+188 -311 0
+305 -310 0
+176 177 195 178 196 308 -182 -180 -181 310 0
+-308 -310 0
+-196 -310 0
+-195 -310 0
+-178 -310 0
+-177 -310 0
+-176 -310 0
+182 -310 0
+180 -310 0
+181 -310 0
+305 -309 0
+176 177 195 178 196 308 -182 181 -180 309 0
+-308 -309 0
+-196 -309 0
+-195 -309 0
+-178 -309 0
+-177 -309 0
+-176 -309 0
+182 -309 0
+-181 -309 0
+180 -309 0
+305 -307 0
+-148 -149 177 176 -150 178 308 307 0
+-307 -308 0
+7 21 -49 -26 308 0
+49 -308 0
+-21 -308 0
+-7 -308 0
+26 -308 0
+-178 -307 0
+-177 -307 0
+-176 -307 0
+150 -307 0
+149 -307 0
+148 -307 0
+305 -306 0
+7 21 27 -49 -26 306 0
+49 -306 0
+-27 -306 0
+-21 -306 0
+-7 -306 0
+26 -306 0
+-143 144 0
+-100 144 -145 0
+-100 -144 145 0
+100 144 -304 0
+100 -144 304 0
+7 13 31 -86 90 -42 -36 -48 304 0
+-90 -304 0
+86 -304 0
+-31 -304 0
+-13 -304 0
+-7 -304 0
+42 -304 0
+36 -304 0
+48 -304 0
+30 83 -271 -210 -146 -289 -286 145 0
+-145 289 0
+-289 290 301 300 302 303 0
+289 -303 0
+12 -293 296 294 298 299 303 0
+-299 -303 0
+-298 -303 0
+-296 -303 0
+-294 -303 0
+293 -303 0
+-12 -303 0
+289 -302 0
+7 -295 296 298 299 302 0
+-299 -302 0
+-298 -302 0
+-296 -302 0
+295 -302 0
+-7 -302 0
+289 -301 0
+7 21 298 -297 299 301 0
+-299 -301 0
+-298 -301 0
+-21 -301 0
+297 -301 0
+-7 -301 0
+289 -300 0
+-291 292 296 294 298 299 300 0
+-299 -300 0
+-298 -300 0
+-296 -300 0
+-294 -300 0
+-292 -300 0
+291 -300 0
+289 -290 0
+290 291 296 294 292 298 299 0
+-290 -299 0
+-5 7 31 13 57 91 -65 299 0
+-91 -299 0
+-57 -299 0
+-31 -299 0
+-13 -299 0
+-7 -299 0
+5 -299 0
+65 -299 0
+-290 -298 0
+7 13 31 -36 -35 298 0
+-31 -298 0
+-13 -298 0
+-7 -298 0
+36 -298 0
+35 -298 0
+-290 -296 0
+7 21 -297 296 0
+-21 -296 0
+-296 297 0
+-7 -296 0
+-290 -294 0
+7 294 -295 0
+-294 295 0
+-7 -294 0
+-290 -292 0
+12 292 -293 0
+-292 293 0
+-12 -292 0
+-290 -291 0
+-145 286 0
+-22 -30 286 0
+22 -30 -286 0
+30 286 -287 0
+30 -286 287 0
+-83 287 -288 0
+-83 -287 288 0
+-48 83 287 0
+48 83 -287 0
+115 -117 -118 288 0
+-115 -288 0
+117 -288 0
+118 -288 0
+-145 271 0
+-271 272 283 282 281 280 279 278 277 276 275 284 285 0
+271 -285 0
+30 -47 196 195 178 177 176 -273 83 208 194 187 172 168 165 162 155 209 285 0
+273 -285 0
+-209 -285 0
+-196 -285 0
+-195 -285 0
+-178 -285 0
+-177 -285 0
+-176 -285 0
+-30 -285 0
+-83 -285 0
+-208 -285 0
+-194 -285 0
+-187 -285 0
+-172 -285 0
+-168 -285 0
+-165 -285 0
+-162 -285 0
+-155 -285 0
+47 -285 0
+271 -284 0
+30 47 83 273 284 0
+-273 -284 0
+-30 -284 0
+-83 -284 0
+-47 -284 0
+271 -283 0
+12 -47 177 172 168 165 162 -157 -161 -203 -273 -156 178 283 0
+273 -283 0
+-178 -283 0
+-177 -283 0
+-172 -283 0
+-168 -283 0
+-165 -283 0
+-162 -283 0
+157 -283 0
+161 -283 0
+203 -283 0
+-12 -283 0
+156 -283 0
+47 -283 0
+271 -282 0
+7 -47 172 168 165 -163 -56 51 -273 -52 178 282 0
+273 -282 0
+-178 -282 0
+-172 -282 0
+-168 -282 0
+-165 -282 0
+163 -282 0
+56 -282 0
+-51 -282 0
+-7 -282 0
+52 -282 0
+47 -282 0
+271 -281 0
+7 21 168 -166 -49 27 172 -273 -26 -47 281 0
+273 -281 0
+-172 -281 0
+-168 -281 0
+166 -281 0
+49 -281 0
+-27 -281 0
+-21 -281 0
+-7 -281 0
+26 -281 0
+47 -281 0
+271 -280 0
+12 -47 177 172 168 165 162 -157 -161 203 -273 -156 178 280 0
+273 -280 0
+-178 -280 0
+-177 -280 0
+-172 -280 0
+-168 -280 0
+-165 -280 0
+-162 -280 0
+157 -280 0
+161 -280 0
+-203 -280 0
+-12 -280 0
+156 -280 0
+47 -280 0
+271 -279 0
+-47 -148 177 176 172 168 165 162 155 -151 -150 149 178 -273 279 0
+273 -279 0
+-178 -279 0
+-177 -279 0
+-176 -279 0
+-172 -279 0
+-168 -279 0
+-165 -279 0
+-162 -279 0
+-155 -279 0
+151 -279 0
+150 -279 0
+-149 -279 0
+148 -279 0
+47 -279 0
+271 -278 0
+-47 155 178 177 176 194 172 168 165 162 196 -189 -193 -188 -273 -199 278 0
+273 -278 0
+-196 -278 0
+-178 -278 0
+-177 -278 0
+-176 -278 0
+-194 -278 0
+-172 -278 0
+-168 -278 0
+-165 -278 0
+-162 -278 0
+-155 -278 0
+189 -278 0
+193 -278 0
+188 -278 0
+47 -278 0
+199 -278 0
+271 -277 0
+-47 155 178 177 176 194 172 168 165 162 196 -189 -193 199 -188 -273 277 0
+273 -277 0
+-196 -277 0
+-178 -277 0
+-177 -277 0
+-176 -277 0
+-194 -277 0
+-172 -277 0
+-168 -277 0
+-165 -277 0
+-162 -277 0
+-155 -277 0
+189 -277 0
+193 -277 0
+-199 -277 0
+188 -277 0
+47 -277 0
+271 -276 0
+-47 155 195 178 177 176 194 187 172 168 165 162 196 -183 -182 -180 -273 -181 276 0
+273 -276 0
+-196 -276 0
+-195 -276 0
+-178 -276 0
+-177 -276 0
+-176 -276 0
+-194 -276 0
+-187 -276 0
+-172 -276 0
+-168 -276 0
+-165 -276 0
+-162 -276 0
+-155 -276 0
+183 -276 0
+182 -276 0
+180 -276 0
+47 -276 0
+181 -276 0
+271 -275 0
+-47 155 195 178 177 176 194 187 172 168 165 162 196 -183 -182 181 -180 -273 275 0
+273 -275 0
+-196 -275 0
+-195 -275 0
+-178 -275 0
+-177 -275 0
+-176 -275 0
+-194 -275 0
+-187 -275 0
+-172 -275 0
+-168 -275 0
+-165 -275 0
+-162 -275 0
+-155 -275 0
+183 -275 0
+182 -275 0
+-181 -275 0
+180 -275 0
+47 -275 0
+271 -272 0
+-47 -148 177 176 172 168 165 162 155 -151 -150 -149 178 -273 272 0
+-272 273 0
+-25 -30 273 0
+25 -30 -273 0
+30 273 -274 0
+30 -273 274 0
+-83 -130 274 0
+-83 130 -274 0
+-47 83 274 0
+47 83 -274 0
+-178 -272 0
+-177 -272 0
+-176 -272 0
+-172 -272 0
+-168 -272 0
+-165 -272 0
+-162 -272 0
+-155 -272 0
+151 -272 0
+150 -272 0
+149 -272 0
+148 -272 0
+47 -272 0
+-145 210 0
+-210 211 268 267 266 265 264 263 262 245 269 270 0
+210 -270 0
+12 -156 236 231 227 223 -218 -222 -203 244 243 270 0
+-244 -270 0
+-243 -270 0
+-236 -270 0
+-231 -270 0
+-227 -270 0
+-223 -270 0
+218 -270 0
+222 -270 0
+203 -270 0
+-12 -270 0
+156 -270 0
+210 -269 0
+7 51 231 227 -224 -54 236 244 -52 269 0
+-244 -269 0
+-236 -269 0
+-231 -269 0
+-227 -269 0
+224 -269 0
+54 -269 0
+-51 -269 0
+-7 -269 0
+52 -269 0
+210 -268 0
+7 21 -228 -44 27 231 236 -26 268 0
+-236 -268 0
+-231 -268 0
+228 -268 0
+44 -268 0
+-27 -268 0
+-21 -268 0
+-7 -268 0
+26 -268 0
+210 -267 0
+12 -156 236 231 227 223 -218 -222 203 244 243 267 0
+-244 -267 0
+-243 -267 0
+-236 -267 0
+-231 -267 0
+-227 -267 0
+-223 -267 0
+218 -267 0
+222 -267 0
+-203 -267 0
+-12 -267 0
+156 -267 0
+210 -266 0
+-148 149 242 236 231 227 223 217 -213 -212 243 244 266 0
+-244 -266 0
+-243 -266 0
+-242 -266 0
+-236 -266 0
+-231 -266 0
+-227 -266 0
+-223 -266 0
+-217 -266 0
+213 -266 0
+212 -266 0
+-149 -266 0
+148 -266 0
+210 -265 0
+-188 -199 243 242 258 236 231 227 223 217 -253 -257 261 244 265 0
+-261 -265 0
+-244 -265 0
+-243 -265 0
+-242 -265 0
+-258 -265 0
+-236 -265 0
+-231 -265 0
+-227 -265 0
+-223 -265 0
+-217 -265 0
+253 -265 0
+257 -265 0
+188 -265 0
+199 -265 0
+210 -264 0
+-188 199 243 242 258 236 231 227 223 217 -253 -257 244 261 264 0
+-261 -264 0
+-244 -264 0
+-243 -264 0
+-242 -264 0
+-258 -264 0
+-236 -264 0
+-231 -264 0
+-227 -264 0
+-223 -264 0
+-217 -264 0
+253 -264 0
+257 -264 0
+-199 -264 0
+188 -264 0
+210 -263 0
+-180 -181 244 243 242 258 252 236 231 227 223 217 -247 -251 261 260 263 0
+-261 -263 0
+-260 -263 0
+-244 -263 0
+-243 -263 0
+-242 -263 0
+-258 -263 0
+-252 -263 0
+-236 -263 0
+-231 -263 0
+-227 -263 0
+-223 -263 0
+-217 -263 0
+247 -263 0
+251 -263 0
+180 -263 0
+181 -263 0
+210 -262 0
+-180 181 244 243 242 258 252 236 231 227 223 217 -247 -251 260 261 262 0
+-261 -262 0
+-260 -262 0
+-244 -262 0
+-243 -262 0
+-242 -262 0
+-258 -262 0
+-252 -262 0
+-236 -262 0
+-231 -262 0
+-227 -262 0
+-223 -262 0
+-217 -262 0
+247 -262 0
+251 -262 0
+-181 -262 0
+180 -262 0
+210 -245 0
+30 83 259 244 243 242 261 260 258 252 246 236 231 227 223 217 245 0
+-245 -261 0
+-148 -212 261 0
+212 -261 0
+148 -261 0
+-245 -260 0
+-188 -257 260 0
+257 -260 0
+188 -260 0
+-245 -259 0
+-180 -251 259 0
+251 -259 0
+180 -259 0
+-244 -245 0
+-243 -245 0
+-242 -245 0
+-30 -245 0
+-83 -245 0
+-245 -258 0
+-148 -213 258 0
+213 -258 0
+148 -258 0
+-245 -252 0
+-188 252 -253 0
+-252 253 0
+-30 253 -254 0
+-30 -253 254 0
+30 253 -255 0
+30 -253 255 0
+-83 255 -256 0
+-83 -255 256 0
+83 255 -257 0
+83 -255 257 0
+188 -252 0
+-245 -246 0
+-180 246 -247 0
+-246 247 0
+-30 247 -248 0
+-30 -247 248 0
+30 247 -249 0
+30 -247 249 0
+-83 249 -250 0
+-83 -249 250 0
+83 249 -251 0
+83 -249 251 0
+180 -246 0
+-236 -245 0
+-231 -245 0
+-227 -245 0
+-223 -245 0
+-217 -245 0
+210 -211 0
+-148 -149 242 236 231 227 223 217 -213 -212 243 244 211 0
+-211 -244 0
+7 -26 -44 244 0
+44 -244 0
+-7 -244 0
+26 -244 0
+-211 -243 0
+7 -52 -54 243 0
+54 -243 0
+-7 -243 0
+52 -243 0
+-211 -242 0
+12 -156 -222 242 0
+222 -242 0
+-12 -242 0
+156 -242 0
+-211 -236 0
+-5 -6 57 31 13 7 91 -237 236 0
+-236 237 0
+-30 237 -238 0
+-30 -237 238 0
+30 237 -239 0
+30 -237 239 0
+-83 239 -240 0
+-83 -239 240 0
+83 239 -241 0
+83 -239 241 0
+-91 -236 0
+-57 -236 0
+-31 -236 0
+-13 -236 0
+-7 -236 0
+6 -236 0
+5 -236 0
+-211 -231 0
+7 13 31 -232 -42 -36 231 0
+-231 232 0
+-30 -68 232 0
+-30 68 -232 0
+30 232 -233 0
+30 -232 233 0
+-83 233 -234 0
+-83 -233 234 0
+83 233 -235 0
+83 -233 235 0
+-31 -231 0
+-13 -231 0
+-7 -231 0
+42 -231 0
+36 -231 0
+-211 -227 0
+7 21 -228 -26 227 0
+-227 228 0
+-30 -79 228 0
+-30 79 -228 0
+30 228 -229 0
+30 -228 229 0
+-83 229 -230 0
+-83 -229 230 0
+-44 83 229 0
+44 83 -229 0
+-21 -227 0
+-7 -227 0
+26 -227 0
+-211 -223 0
+7 -52 -224 223 0
+-223 224 0
+-30 -74 224 0
+-30 74 -224 0
+30 224 -225 0
+30 -224 225 0
+-83 225 -226 0
+-83 -225 226 0
+-54 83 225 0
+54 83 -225 0
+-7 -223 0
+52 -223 0
+-211 -217 0
+12 -156 -218 217 0
+-217 218 0
+-30 218 -219 0
+-30 -218 219 0
+30 218 -220 0
+30 -218 220 0
+-83 220 -221 0
+-83 -220 221 0
+83 220 -222 0
+83 -220 222 0
+-12 -217 0
+156 -217 0
+-211 213 0
+-30 213 -214 0
+-30 -213 214 0
+30 213 -215 0
+30 -213 215 0
+-83 215 -216 0
+-83 -215 216 0
+83 -212 215 0
+83 212 -215 0
+-211 212 0
+149 -211 0
+148 -211 0
+-145 146 0
+-146 147 205 204 202 201 200 198 197 179 206 207 0
+146 -207 0
+30 83 195 178 177 176 209 196 208 194 187 172 168 165 162 155 207 0
+-207 -209 0
+-180 -182 209 0
+182 -209 0
+180 -209 0
+-196 -207 0
+-195 -207 0
+-178 -207 0
+-177 -207 0
+-176 -207 0
+-30 -207 0
+-83 -207 0
+-207 -208 0
+-180 -183 208 0
+183 -208 0
+180 -208 0
+-194 -207 0
+-187 -207 0
+-172 -207 0
+-168 -207 0
+-165 -207 0
+-162 -207 0
+-155 -207 0
+146 -206 0
+12 -156 172 168 165 162 -157 -161 -203 178 177 206 0
+-178 -206 0
+-177 -206 0
+-172 -206 0
+-168 -206 0
+-165 -206 0
+-162 -206 0
+157 -206 0
+161 -206 0
+203 -206 0
+-12 -206 0
+156 -206 0
+146 -205 0
+7 51 168 165 -163 -56 172 178 -52 205 0
+-178 -205 0
+-172 -205 0
+-168 -205 0
+-165 -205 0
+163 -205 0
+56 -205 0
+-51 -205 0
+-7 -205 0
+52 -205 0
+146 -204 0
+7 21 -166 -49 27 168 172 -26 204 0
+-172 -204 0
+-168 -204 0
+166 -204 0
+49 -204 0
+-27 -204 0
+-21 -204 0
+-7 -204 0
+26 -204 0
+146 -202 0
+12 -156 172 168 165 162 -157 -161 203 178 177 202 0
+-178 -202 0
+-177 -202 0
+-172 -202 0
+-168 -202 0
+-165 -202 0
+-162 -202 0
+157 -202 0
+161 -202 0
+-202 -203 0
+-12 -202 0
+156 -202 0
+146 -201 0
+-148 149 176 172 168 165 162 155 -151 -150 177 178 201 0
+-178 -201 0
+-177 -201 0
+-176 -201 0
+-172 -201 0
+-168 -201 0
+-165 -201 0
+-162 -201 0
+-155 -201 0
+151 -201 0
+150 -201 0
+-149 -201 0
+148 -201 0
+146 -200 0
+155 162 177 176 194 172 168 165 178 196 -189 -193 -188 -199 200 0
+-196 -200 0
+-178 -200 0
+-177 -200 0
+-176 -200 0
+-194 -200 0
+-172 -200 0
+-168 -200 0
+-165 -200 0
+-162 -200 0
+-155 -200 0
+189 -200 0
+193 -200 0
+188 -200 0
+199 -200 0
+146 -198 0
+155 162 177 176 194 172 168 165 178 196 -189 -193 199 -188 198 0
+-196 -198 0
+-178 -198 0
+-177 -198 0
+-176 -198 0
+-194 -198 0
+-172 -198 0
+-168 -198 0
+-165 -198 0
+-162 -198 0
+-155 -198 0
+189 -198 0
+193 -198 0
+-198 -199 0
+188 -198 0
+146 -197 0
+155 162 178 177 176 194 187 172 168 165 195 196 -183 -182 -180 -181 197 0
+-196 -197 0
+-195 -197 0
+-178 -197 0
+-177 -197 0
+-176 -197 0
+-194 -197 0
+-187 -197 0
+-172 -197 0
+-168 -197 0
+-165 -197 0
+-162 -197 0
+-155 -197 0
+183 -197 0
+182 -197 0
+180 -197 0
+181 -197 0
+146 -179 0
+155 162 178 177 176 194 187 172 168 165 195 196 -183 -182 181 -180 179 0
+-179 -196 0
+-148 -150 196 0
+150 -196 0
+148 -196 0
+-179 -195 0
+-188 -193 195 0
+193 -195 0
+188 -195 0
+-178 -179 0
+-177 -179 0
+-176 -179 0
+-179 -194 0
+-148 -151 194 0
+151 -194 0
+148 -194 0
+-179 -187 0
+187 -188 -189 0
+-187 189 0
+-30 189 -190 0
+-30 -189 190 0
+30 189 -191 0
+30 -189 191 0
+-83 191 -192 0
+-83 -191 192 0
+83 191 -193 0
+83 -191 193 0
+-187 188 0
+-172 -179 0
+-168 -179 0
+-165 -179 0
+-162 -179 0
+-155 -179 0
+-179 183 0
+-30 183 -184 0
+-30 -183 184 0
+30 183 -185 0
+30 -183 185 0
+-83 185 -186 0
+-83 -185 186 0
+83 -182 185 0
+83 182 -185 0
+-179 182 0
+-179 -181 0
+-179 180 0
+146 -147 0
+147 -148 176 172 168 165 162 155 -151 -150 -149 177 178 0
+-147 -178 0
+7 -26 -49 178 0
+49 -178 0
+-7 -178 0
+26 -178 0
+-147 -177 0
+7 -52 -56 177 0
+56 -177 0
+-7 -177 0
+52 -177 0
+-147 -176 0
+12 -156 -161 176 0
+161 -176 0
+-12 -176 0
+156 -176 0
+-147 -172 0
+-5 -6 57 31 13 7 91 -173 172 0
+-172 173 0
+-30 -99 173 0
+-30 99 -173 0
+30 173 -174 0
+30 -173 174 0
+-83 -96 174 0
+-83 96 -174 0
+83 174 -175 0
+83 -174 175 0
+-91 -172 0
+-57 -172 0
+-31 -172 0
+-13 -172 0
+-7 -172 0
+6 -172 0
+5 -172 0
+-147 -168 0
+7 13 31 -169 -42 -36 168 0
+-168 169 0
+-30 -71 169 0
+-30 71 -169 0
+30 169 -170 0
+30 -169 170 0
+-83 -87 170 0
+-83 87 -170 0
+83 170 -171 0
+83 -170 171 0
+-31 -168 0
+-13 -168 0
+-7 -168 0
+42 -168 0
+36 -168 0
+-147 -165 0
+7 21 -166 -26 165 0
+-165 166 0
+-28 -30 166 0
+28 -30 -166 0
+30 166 -167 0
+30 -166 167 0
+-81 -83 167 0
+81 -83 -167 0
+-49 83 167 0
+49 83 -167 0
+-21 -165 0
+-7 -165 0
+26 -165 0
+-147 -162 0
+7 -52 -163 162 0
+-162 163 0
+-30 -76 163 0
+-30 76 -163 0
+30 163 -164 0
+30 -163 164 0
+-83 -138 164 0
+-83 138 -164 0
+-56 83 164 0
+56 83 -164 0
+-7 -162 0
+52 -162 0
+-147 -155 0
+12 155 -156 -157 0
+-155 157 0
+-30 157 -158 0
+-30 -157 158 0
+30 157 -159 0
+30 -157 159 0
+-83 159 -160 0
+-83 -159 160 0
+83 159 -161 0
+83 -159 161 0
+-12 -155 0
+-155 156 0
+-147 151 0
+-30 151 -152 0
+-30 -151 152 0
+30 151 -153 0
+30 -151 153 0
+-83 153 -154 0
+-83 -153 154 0
+83 -150 153 0
+83 150 -153 0
+-147 150 0
+-147 149 0
+-147 148 0
+-30 -145 0
+-83 -145 0
+71 -143 0
+-13 -143 0
+-7 -143 0
+42 -143 0
+36 -143 0
+48 -143 0
+25 -143 0
+23 -136 0
+7 -25 128 100 90 85 141 -137 -76 51 -129 -52 142 136 0
+129 -136 0
+-136 -142 0
+7 21 -28 -26 142 0
+28 -142 0
+-21 -142 0
+-7 -142 0
+26 -142 0
+-128 -136 0
+-100 -136 0
+-90 -136 0
+-85 -136 0
+-136 -141 0
+7 21 -29 -26 141 0
+29 -141 0
+-21 -141 0
+-7 -141 0
+26 -141 0
+-136 137 0
+-30 137 -138 0
+-30 -137 138 0
+30 137 -139 0
+30 -137 139 0
+-83 139 -140 0
+-83 -139 140 0
+-76 83 139 0
+76 83 -139 0
+76 -136 0
+-51 -136 0
+-7 -136 0
+52 -136 0
+25 -136 0
+23 -24 0
+7 21 100 90 85 -29 -28 27 128 -129 -26 -25 24 0
+-24 129 0
+-30 129 -130 0
+-30 -129 130 0
+30 129 -131 0
+30 -129 131 0
+-83 131 -132 0
+-83 -131 132 0
+-25 83 131 0
+25 83 -131 0
+132 133 134 135 0
+-132 -135 0
+-132 -134 0
+-132 -133 0
+115 117 118 130 0
+-118 -130 0
+-117 -130 0
+-115 -130 0
+-24 -128 0
+7 13 -71 -42 -36 128 0
+71 -128 0
+-13 -128 0
+-7 -128 0
+42 -128 0
+36 -128 0
+-24 -100 0
+13 100 -107 101 -119 -112 0
+-100 119 0
+-119 120 121 122 0
+119 -122 0
+30 31 57 -123 122 0
+-122 123 0
+-30 123 -124 0
+-30 -123 124 0
+30 123 -125 0
+30 -123 125 0
+-83 125 -126 0
+-83 -125 126 0
+83 125 -127 0
+83 -125 127 0
+-30 -122 0
+-57 -122 0
+-31 -122 0
+119 -121 0
+31 -57 -95 121 0
+95 -121 0
+57 -121 0
+-31 -121 0
+119 -120 0
+30 83 -86 120 0
+86 -120 0
+-30 -120 0
+-83 -120 0
+-100 112 0
+-6 -30 112 0
+6 -30 -112 0
+30 112 -113 0
+30 -112 113 0
+-83 113 -114 0
+-83 -113 114 0
+-42 83 113 0
+42 83 -113 0
+114 115 -116 0
+-114 116 0
+-116 117 -118 0
+116 118 0
+116 -117 0
+-114 -115 0
+-100 107 0
+-31 107 -108 0
+-31 -107 108 0
+31 107 -109 0
+31 -107 109 0
+-30 109 -110 0
+-30 -109 110 0
+30 109 -111 0
+30 -109 111 0
+7 -83 111 0
+-7 -83 -111 0
+-36 83 111 0
+36 83 -111 0
+-5 7 110 0
+-7 -110 0
+5 -110 0
+7 -36 108 0
+-7 -108 0
+36 -108 0
+-100 -101 0
+92 93 102 -101 0
+101 -102 0
+91 102 -103 0
+-91 -102 0
+-102 103 0
+-103 104 105 0
+103 -105 0
+-5 7 13 -106 31 57 -63 105 0
+-57 -105 0
+-31 -105 0
+-13 -105 0
+-105 106 0
+-7 -105 0
+5 -105 0
+63 -105 0
+103 -104 0
+-5 7 13 31 57 -61 104 0
+-57 -104 0
+-31 -104 0
+-13 -104 0
+-7 -104 0
+5 -104 0
+61 -104 0
+-93 101 0
+-92 101 0
+-13 -100 0
+-24 -90 0
+-5 -6 57 31 13 7 91 -95 90 0
+-90 95 0
+-30 95 -96 0
+-30 -95 96 0
+30 95 -97 0
+30 -95 97 0
+-83 97 -98 0
+-83 -97 98 0
+83 97 -99 0
+83 -97 99 0
+-90 -91 0
+-91 92 93 0
+91 -93 0
+7 13 -94 31 -36 -40 93 0
+-31 -93 0
+-13 -93 0
+-93 94 0
+-7 -93 0
+36 -93 0
+40 -93 0
+91 -92 0
+7 13 31 -38 -36 92 0
+-31 -92 0
+-13 -92 0
+-7 -92 0
+38 -92 0
+36 -92 0
+-57 -90 0
+-31 -90 0
+-13 -90 0
+-7 -90 0
+6 -90 0
+5 -90 0
+-24 -85 0
+7 13 31 -86 -42 -36 85 0
+-85 86 0
+-30 86 -87 0
+-30 -86 87 0
+30 86 -88 0
+30 -86 88 0
+-83 88 -89 0
+-83 -88 89 0
+-71 83 88 0
+71 83 -88 0
+-31 -85 0
+-13 -85 0
+-7 -85 0
+42 -85 0
+36 -85 0
+-24 29 0
+29 -30 -81 0
+-29 -30 81 0
+29 30 -82 0
+-29 30 82 0
+82 -83 -84 0
+-82 -83 84 0
+-28 82 83 0
+28 -82 83 0
+31 57 83 0
+-57 -83 0
+-31 -83 0
+30 31 -57 0
+-30 57 0
+-57 58 72 77 0
+57 -77 0
+-26 -27 -78 -59 77 0
+-77 78 0
+-78 79 80 0
+78 -80 0
+-28 -70 80 0
+28 -80 0
+70 -80 0
+78 -79 0
+59 -77 0
+26 -77 0
+27 -77 0
+57 -72 0
+-51 -52 -59 -73 72 0
+-72 73 0
+-73 74 75 0
+73 -75 0
+-70 75 -76 0
+-75 76 0
+70 -75 0
+73 -74 0
+59 -72 0
+52 -72 0
+51 -72 0
+57 -58 0
+-36 -42 -59 -67 58 0
+-58 67 0
+-67 68 69 0
+67 -69 0
+69 -70 -71 0
+-69 71 0
+-69 70 0
+22 25 63 65 -70 0
+-63 70 0
+-65 70 0
+-22 70 0
+-25 70 0
+67 -68 0
+-58 59 0
+-59 60 62 64 66 0
+59 -66 0
+-5 -6 66 0
+6 -66 0
+5 -66 0
+59 -64 0
+-5 64 -65 0
+5 -64 0
+-64 65 0
+59 -62 0
+-5 62 -63 0
+5 -62 0
+-62 63 0
+59 -60 0
+-5 60 -61 0
+5 -60 0
+-60 61 0
+42 -58 0
+36 -58 0
+-30 -31 0
+-31 32 50 0
+31 -50 0
+-33 50 -52 -51 -53 0
+-50 53 0
+-53 54 55 0
+53 -55 0
+-46 55 -56 0
+-55 56 0
+46 -55 0
+53 -54 0
+33 -50 0
+-50 52 0
+-50 51 0
+31 -32 0
+-26 -27 -43 -33 32 0
+-32 43 0
+-43 44 45 0
+43 -45 0
+45 -46 -49 0
+-45 49 0
+-45 46 0
+35 40 48 47 -46 0
+-40 46 0
+-35 46 0
+46 -48 0
+46 -47 0
+43 -44 0
+-32 33 0
+-33 34 37 39 41 0
+33 -41 0
+-36 41 -42 0
+-41 42 0
+36 -41 0
+33 -39 0
+-36 39 -40 0
+36 -39 0
+-39 40 0
+33 -37 0
+-36 37 -38 0
+-37 38 0
+36 -37 0
+33 -34 0
+34 -35 -36 0
+-34 36 0
+-34 35 0
+26 -32 0
+27 -32 0
+-24 28 0
+-24 -27 0
+-21 -24 0
+-7 -24 0
+-24 26 0
+-24 25 0
+-4 -22 0
+-4 -13 0
+-13 14 16 19 0
+13 -19 0
+19 -20 21 0
+-19 -21 0
+14 16 -21 0
+-16 21 0
+-14 21 0
+-19 20 0
+-1 7 20 0
+1 -20 0
+-7 -20 0
+13 -16 0
+7 16 -18 -17 0
+-16 18 0
+-16 17 0
+-7 -16 0
+13 -14 0
+7 14 -15 0
+-14 15 0
+-7 -14 0
+-4 -7 0
+-7 8 9 10 0
+7 -10 0
+10 -11 12 0
+-10 -12 0
+8 9 -12 0
+-9 12 0
+-8 12 0
+-10 11 0
+7 -9 0
+7 -8 0
+-4 6 0
+-4 5 0