summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--proofs/signatures/Makefile.am2
-rw-r--r--proofs/signatures/core_rewrites.plf123
-rwxr-xr-xproofs/signatures/ex-mem.plf16
-rw-r--r--[-rwxr-xr-x]proofs/signatures/ex_bv.plf43
-rw-r--r--proofs/signatures/ex_bv_rewrite.plf41
-rwxr-xr-xproofs/signatures/sat.plf12
-rwxr-xr-xproofs/signatures/smt.plf94
-rwxr-xr-xproofs/signatures/th_arrays.plf2
-rw-r--r--[-rwxr-xr-x]proofs/signatures/th_bv.plf287
-rw-r--r--proofs/signatures/th_bv_bitblast.plf629
-rw-r--r--src/Makefile.am9
-rw-r--r--src/options/bv_options8
-rw-r--r--src/proof/array_proof.h78
-rw-r--r--src/proof/bitvector_proof.cpp602
-rw-r--r--src/proof/bitvector_proof.h142
-rw-r--r--src/proof/cnf_proof.cpp1049
-rw-r--r--src/proof/cnf_proof.h136
-rw-r--r--src/proof/proof.h21
-rw-r--r--src/proof/proof_manager.cpp546
-rw-r--r--src/proof/proof_manager.h196
-rw-r--r--src/proof/proof_utils.cpp127
-rw-r--r--src/proof/proof_utils.h178
-rw-r--r--src/proof/sat_proof.h291
-rw-r--r--src/proof/sat_proof_implementation.h1100
-rw-r--r--src/proof/theory_proof.cpp684
-rw-r--r--src/proof/theory_proof.h282
-rw-r--r--src/proof/uf_proof.cpp804
-rw-r--r--src/proof/uf_proof.h75
-rw-r--r--src/prop/bvminisat/bvminisat.cpp37
-rw-r--r--src/prop/bvminisat/bvminisat.h11
-rw-r--r--src/prop/bvminisat/core/Solver.cc407
-rw-r--r--src/prop/bvminisat/core/Solver.h82
-rw-r--r--src/prop/bvminisat/core/SolverTypes.h27
-rw-r--r--src/prop/bvminisat/simp/SimpSolver.cc20
-rw-r--r--src/prop/bvminisat/simp/SimpSolver.h20
-rw-r--r--src/prop/cnf_stream.cpp212
-rw-r--r--src/prop/cnf_stream.h58
-rw-r--r--src/prop/minisat/core/Solver.cc132
-rw-r--r--src/prop/minisat/core/Solver.h61
-rw-r--r--src/prop/minisat/core/SolverTypes.h37
-rw-r--r--src/prop/minisat/minisat.cpp41
-rw-r--r--src/prop/minisat/minisat.h5
-rw-r--r--src/prop/minisat/simp/SimpSolver.cc12
-rw-r--r--src/prop/minisat/simp/SimpSolver.h30
-rw-r--r--src/prop/prop_engine.cpp9
-rw-r--r--src/prop/sat_solver.h19
-rw-r--r--src/prop/sat_solver_factory.h4
-rw-r--r--src/prop/theory_proxy.cpp3
-rw-r--r--src/smt/smt_engine.cpp27
-rw-r--r--src/smt/smt_engine_check_proof.cpp5
-rw-r--r--src/smt/smt_engine_scope.h3
-rw-r--r--src/smt_util/command.cpp4
-rw-r--r--src/smt_util/command.h1
-rw-r--r--src/theory/arrays/theory_arrays.cpp37
-rw-r--r--src/theory/arrays/theory_arrays.h2
-rw-r--r--src/theory/bv/bitblast_strategies_template.h57
-rw-r--r--src/theory/bv/bitblast_utils.h2
-rw-r--r--src/theory/bv/bitblaster_template.h13
-rw-r--r--src/theory/bv/bv_eager_solver.cpp11
-rw-r--r--src/theory/bv/bv_eager_solver.h5
-rw-r--r--src/theory/bv/bv_subtheory.h3
-rw-r--r--src/theory/bv/bv_subtheory_bitblast.cpp45
-rw-r--r--src/theory/bv/bv_subtheory_bitblast.h7
-rw-r--r--src/theory/bv/eager_bitblaster.cpp52
-rw-r--r--src/theory/bv/lazy_bitblaster.cpp37
-rw-r--r--src/theory/bv/theory_bv.cpp14
-rw-r--r--src/theory/bv/theory_bv.h8
-rw-r--r--src/theory/bv/theory_bv_rewrite_rules_core.h3
-rw-r--r--src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h3
-rw-r--r--src/theory/bv/theory_bv_rewrite_rules_simplification.h6
-rw-r--r--src/theory/bv/theory_bv_utils.h10
-rw-r--r--src/theory/output_channel.h26
-rw-r--r--src/theory/rewriter.cpp10
-rw-r--r--src/theory/theory.cpp9
-rw-r--r--src/theory/theory.h38
-rw-r--r--src/theory/theory_engine.cpp47
-rw-r--r--src/theory/theory_engine.h23
-rw-r--r--src/theory/theory_test_utils.h7
-rw-r--r--src/theory/uf/equality_engine.cpp78
-rw-r--r--src/theory/uf/equality_engine.h4
-rw-r--r--src/theory/uf/kinds3
-rw-r--r--src/theory/uf/symmetry_breaker.cpp51
-rw-r--r--src/theory/uf/symmetry_breaker.h51
-rw-r--r--src/theory/uf/theory_uf.cpp52
-rw-r--r--src/theory/uf/theory_uf.h10
-rw-r--r--src/theory/uf/theory_uf_type_rules.h8
-rw-r--r--test/regress/regress0/bv/Makefile.am7
-rw-r--r--test/regress/regress0/bv/bv-proof00.smt2176
-rwxr-xr-xtest/regress/run_regression3
-rw-r--r--test/unit/prop/cnf_stream_white.h5
-rw-r--r--test/unit/theory/theory_engine_white.h7
-rw-r--r--test/unit/theory/theory_white.h18
92 files changed, 9917 insertions, 1875 deletions
diff --git a/proofs/signatures/Makefile.am b/proofs/signatures/Makefile.am
index 9e8063bf2..82d8c2caa 100644
--- a/proofs/signatures/Makefile.am
+++ b/proofs/signatures/Makefile.am
@@ -3,7 +3,7 @@
# add support for more theories, just list them here in the same order
# you would to the LFSC proof-checker binary.
#
-CORE_PLFS = sat.plf smt.plf th_base.plf th_arrays.plf
+CORE_PLFS = sat.plf smt.plf th_base.plf th_arrays.plf th_bv.plf th_bv_bitblast.plf
noinst_LTLIBRARIES = libsignatures.la
diff --git a/proofs/signatures/core_rewrites.plf b/proofs/signatures/core_rewrites.plf
new file mode 100644
index 000000000..ca2c1fa03
--- /dev/null
+++ b/proofs/signatures/core_rewrites.plf
@@ -0,0 +1,123 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;; Rewrite rules
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; t rewrites to t'
+(declare rw_term
+ (! s sort
+ (! t (term s)
+ (! t' (term s)
+ type))))
+
+(declare rw_formula
+ (! f formula
+ (! f' formula
+ type)))
+
+
+(declare apply_rw_formula
+ (! f formula
+ (! f' formula
+ (! rw (rw_formula f f')
+ (! fh (th_holds f)
+ (th_holds f'))))))
+
+
+;; Identity rewrite rules
+(declare rw_term_id
+ (! s sort
+ (! t (term s)
+ (rw_term s t t))))
+
+(declare rw_term_trans
+ (! s sort
+ (! t1 (term s)
+ (! t2 (term s)
+ (! t3 (term s)
+ (! rw12 (rw_term _ t1 t2)
+ (! rw23 (rw_term _ t2 t3)
+ (rw_term s t1 t3))))))))
+
+;; rw_symmetry
+
+(declare rw_formula_trans
+ (! f1 formula
+ (! f2 formula
+ (! f3 formula
+ (! rw1 (rw_formula f1 f2)
+ (! rw2 (rw_formula f2 f3)
+ (rw_formula f1 f3)))))))
+
+
+(declare rw_op1_id
+ (! s sort
+ (! a (term s)
+ (! a' (term s)
+ (! rw (rw_term _ a a')
+ (! op term_op1
+ (rw_term _ (op _ a) (op _ a'))))))))
+
+(declare rw_op2_id
+ (! s sort
+ (! a (term s)
+ (! a' (term s)
+ (! b (term s)
+ (! b' (term s)
+ (! rw (rw_term _ a a')
+ (! rw (rw_term _ b b')
+ (! op term_op2
+ (rw_term _ (op _ a b) (op _ a' b')))))))))))
+
+(declare rw_pred1_id
+ (! s sort
+ (! a (term s)
+ (! a' (term s)
+ (! rw (rw_term _ a a')
+ (! op op_pred1
+ (rw_formula (op _ a) (op _ a'))))))))
+
+(declare rw_pred2_id
+ (! s sort
+ (! a (term s)
+ (! a' (term s)
+ (! b (term s)
+ (! b' (term s)
+ (! rw (rw_term _ a a')
+ (! rw (rw_term _ b b')
+ (! op op_pred2
+ (rw_formula (op _ a b) (op _ a' b')))))))))))
+
+(declare rw_eq_id
+ (! s sort
+ (! a (term s)
+ (! a' (term s)
+ (! b (term s)
+ (! b' (term s)
+ (! rw (rw_term _ a a')
+ (! rw (rw_term _ b b')
+ (rw_formula (= s a b) (= s a' b'))))))))))
+
+(declare rw_formula_op1_id
+ (! f formula
+ (! f' formula
+ (! frw (rw_formula f f')
+ (! op formula_op1
+ (rw_formula (op f) (op f')))))))
+
+(declare rw_formula_op2_id
+ (! f1 formula
+ (! f1' formula
+ (! f2 formula
+ (! f2' formula
+ (! frw1 (rw_formula f1 f1')
+ (! frw2 (rw_formula f2 f2')
+ (! op formula_op2
+ (rw_formula (op f1 f2) (op f1' f2'))))))))))
+
+
+(apply_rw_formula
+ (! f formula
+ (! f' formula
+ (! r (rw_formula f f')
+ (! h (th_holds f)
+ (th_holds f')))))) \ No newline at end of file
diff --git a/proofs/signatures/ex-mem.plf b/proofs/signatures/ex-mem.plf
index 12c4c3e16..7e143c5b6 100755
--- a/proofs/signatures/ex-mem.plf
+++ b/proofs/signatures/ex-mem.plf
@@ -1,5 +1,3 @@
-; AJR : proof used for testing memory use of theory lemmas
-
(check
(% s sort
(% a (term s)
@@ -10,8 +8,8 @@
; -------------------- declaration of input formula -----------------------------------
(% A1 (th_holds (= s a b))
-(% A2 (th_holds (= s b a))
-(% A3 (th_holds (not (= s a a)))
+(% A2 (th_holds (= s b c))
+(% A3 (th_holds (not (= s a c)))
; ------------------- specify that the following is a proof of the empty clause -----------------
@@ -20,15 +18,12 @@
; ---------- use atoms (a1, a2, a3) to map theory literals to boolean literals (v1, v2, v3) ------
(decl_atom (= s a b) (\ v1 (\ a1
-(decl_atom (= s b a) (\ v2 (\ a2
-(decl_atom (= s a a) (\ v3 (\ a3
+(decl_atom (= s b c) (\ v2 (\ a2
+(decl_atom (= s a c) (\ v3 (\ a3
; --------------------------- proof of theory lemma ---------------------------------------------
(satlem _ _ (ast _ _ _ a1 (\ l1 (ast _ _ _ a2 (\ l2 (asf _ _ _ a3 (\ l3 (clausify_false (contra _ (trans _ _ _ _ l1 l2) l3)))))))) (\ CT1
-(satlem _ _ (ast _ _ _ a1 (\ l1 (ast _ _ _ a2 (\ l2 (asf _ _ _ a3 (\ l3 (clausify_false (contra _ (trans _ _ _ _ l1 l2) l3)))))))) (\ CT2
-(satlem _ _ (ast _ _ _ a1 (\ l1 (ast _ _ _ a2 (\ l2 (asf _ _ _ a3 (\ l3 (clausify_false (contra _ (trans _ _ _ _ l1 l2) l3)))))))) (\ CT3
-;...add copies here...
; -------------------- clausification of input formulas -----------------------------------------
@@ -64,5 +59,4 @@
(\ x x))
-)))))))))))))))))))))))))))))
-))
+)))))))))))))))))))))))))))
diff --git a/proofs/signatures/ex_bv.plf b/proofs/signatures/ex_bv.plf
index ae585e455..58494e793 100755..100644
--- a/proofs/signatures/ex_bv.plf
+++ b/proofs/signatures/ex_bv.plf
@@ -1,31 +1,32 @@
-; a = b ^ a = 00000 ^ b = 11111 is UNSAT
+; (a = b) ^ (a = b & 00000) ^ (b = 11111) is UNSAT
(check
(% a var_bv
(% b var_bv
-(% f1 (th_holds (= BitVec (a_var_bv a) (a_var_bv b)))
-(% f2 (th_holds (= BitVec (a_var_bv a) (a_bv (bvc b0 (bvc b0 (bvc b0 (bvc b0 (bvc b0 bvn))))))))
-(% f3 (th_holds (= BitVec (a_var_bv b) (a_bv (bvc b1 (bvc b1 (bvc b1 (bvc b1 (bvc b1 bvn))))))))
+(% f1 (th_holds (= (BitVec 4) (a_var_bv _ a) (a_var_bv _ b)))
+(% f2 (th_holds (= (BitVec 4) (a_var_bv _ a) (bvand 4 (a_var_bv 4 b) (a_bv _ (bvc b0 (bvc b0 (bvc b0 (bvc b0 (bvc b0 bvn)))))))))
+(% f3 (th_holds (= (BitVec 4) (a_var_bv _ b) (a_bv _ (bvc b1 (bvc b1 (bvc b1 (bvc b1 (bvc b1 bvn))))))))
(: (holds cln)
-(decl_bv_atom_var 5 a (\ ba1
-(decl_bv_atom_var 5 b (\ ba2
-(decl_bv_atom_const _ (bvc b0 (bvc b0 (bvc b0 (bvc b0 (bvc b0 bvn))))) (\ c (\ ba3
-(decl_bv_atom_const _ (bvc b1 (bvc b1 (bvc b1 (bvc b1 (bvc b1 bvn))))) (\ d (\ ba4
+;; (decl_bv_term_var 5 a (\ ba1
+;; (decl_bv_term_var 5 b (\ ba2
+;; (decl_bv_term_const _ (bvc b0 (bvc b0 (bvc b0 (bvc b0 (bvc b0 bvn))))) (\ c (\ ba3
+;; (decl_bv_term_const _ (bvc b1 (bvc b1 (bvc b1 (bvc b1 (bvc b1 bvn))))) (\ d (\ ba4
-(decl_atom (bblast a 4) (\ v1 (\ a1
-(decl_atom (bblast b 4) (\ v2 (\ a2
+(decl_atom (bitof a 4) (\ v1 (\ a1
+(decl_atom (bitof b 4) (\ v2 (\ a2
; bitblasting terms
-(th_let_pf _ (bv_bbl_var _ _ _ ba1) (\ bt1
-(th_let_pf _ (bv_bbl_var _ _ _ ba2) (\ bt2
-(th_let_pf _ (bv_bbl_const _ _ _ _ ba3) (\ bt3
-(th_let_pf _ (bv_bbl_const _ _ _ _ ba4) (\ bt4
+(decl_bblast _ _ _ (bv_bbl_var 4 a _ ) (\ bt1
+(decl_bblast _ _ _ (bv_bbl_var 4 b _ ) (\ bt2
+(decl_bblast _ _ _ (bv_bbl_const 4 _ (bvc b0 (bvc b0 (bvc b0 (bvc b0 bvn))))) (\ bt3
+(decl_bblast _ _ _ (bv_bbl_const 4 _ (bvc b1 (bvc b1 (bvc b1 (bvc b1 bvn))))) (\ bt4
+(decl_bblast _ _ _ (bv_bbl_bvand 4 _ _ _ _ _ bt1 bt3) (\ bt5
; bitblasting formulas
-(th_let_pf _ (bv_bbl_eq _ _ _ _ _ bt1 bt2) (\ bf1
-(th_let_pf _ (bv_bbl_eq _ _ _ _ _ bt1 bt3) (\ bf2
-(th_let_pf _ (bv_bbl_eq _ _ _ _ _ bt2 bt4) (\ bf3
+(th_let_pf _ (bv_bbl_eq _ _ _ _ _ _ bt1 bt2) (\ bf1
+(th_let_pf _ (bv_bbl_bvult _ _ _ _ _ _ bt1 bt5) (\ bf2
+(th_let_pf _ (bv_bbl_eq _ _ _ _ _ _ bt2 bt4) (\ bf3
; CNFication
; a.4 V ~b.4
@@ -33,25 +34,25 @@
(asf _ _ _ a1 (\ l1
(ast _ _ _ a2 (\ l2
(clausify_false
- (contra _ (impl_elim _ _ l2 (iff_elim_2 _ _ (and_elim_1 _ _ (impl_elim _ _ f1 bf1)))) l1) ; notice at the intermost we impl_elim, which converts from atom to bit-blasting representation
+ trust
))))) (\ C2
; ~a.4
(satlem _ _
(ast _ _ _ a1 (\ l1
(clausify_false
- (impl_elim _ _ l1 (iff_elim_1 _ _ (and_elim_1 _ _ (impl_elim _ _ f2 bf2))))
+ trust
))) (\ C3
; b.4
(satlem _ _
(asf _ _ _ a2 (\ l2
(clausify_false
- (contra _ (impl_elim _ _ truth (iff_elim_2 _ _ (and_elim_1 _ _ (impl_elim _ _ f3 bf3)))) l2)
+ trust
))) (\ C6
(satlem_simplify _ _ _
(R _ _ (R _ _ C6 C2 v2) C3 v1) (\ x x))
-))))))))))))))))))))))))))))))))))))))))))) \ No newline at end of file
+)))))))))))))))))))))))))))))))))))))))))))))
diff --git a/proofs/signatures/ex_bv_rewrite.plf b/proofs/signatures/ex_bv_rewrite.plf
new file mode 100644
index 000000000..fbe593502
--- /dev/null
+++ b/proofs/signatures/ex_bv_rewrite.plf
@@ -0,0 +1,41 @@
+(check
+(% x var_bv
+(% y var_bv
+(% a var_bv
+(% A0 (th_holds true)
+(% A1 (th_holds
+ (= (BitVec 1) (a_var_bv 1 x)
+ (bvnot 1 (bvxnor 1 (bvxor 1 (a_var_bv 1 a) (a_bv 1 (bvc b1 bvn)))
+ (bvxor 1 (a_var_bv 1 a) (a_bv 1 (bvc b0 bvn))) ))))
+(: (th_holds
+ (= (BitVec 1) (a_var_bv 1 x)
+ (bvxor 1 (bvnot 1 (a_var_bv 1 a)) (a_var_bv 1 a))))
+
+;; print rewritten assertions
+
+(@ ones (a_bv 1 (bvc b1 bvn))
+(@ zero (a_bv 1 (bvc b0 bvn))
+(@ xorone (bvxor 1 (a_var_bv 1 a) ones)
+(@ xorzero (bvxor 1 (a_var_bv 1 a) zero)
+(@ t1 (bvxor 1 xorone xorzero)
+(@ t2 (bvxnor 1 xorone xorzero)
+(@ t3 (bvnot 1 t2)
+(@ t4 (bvnot 1 t1)
+(@ t5 (bvxor 1 (bvnot 1 (a_var_bv 1 a)) (a_var_bv 1 a))
+;; adding identity rewrite proofs
+(@ xor_onerw (rw_term_id 1 xorone)
+(@ xor_zerorw (rw_term_id 1 xorzero)
+(@ rw1 (xnor_elim 1 _ _ _ _ xor_onerw xor_zerorw) ;; bvxnor t1 t2 -> bvnot (bvxor t1 t2)
+(@ rw2 (xor_zero 1 _ _ _ _ (rw_term_id 1 (a_var_bv 1 a)) (rw_term_id 1 zero))
+(@ rw3 (xor_one 1 _ _ _ _ (rw_term_id 1 (a_var_bv 1 a)) (rw_term_id 1 ones))
+(@ rw4 (rw_bvop2_id 1 _ _ _ _ rw3 rw2 bvxor) ;; bvxor t1 t2 -> bvxor t1' t2'
+(@ rw5 (rw_bvop1_id 1 _ _ rw4 bvnot) ;; bvnot (bvxor t1 t2) -> bvnot (bvxor t1' t2')
+(@ rw6 (rw_term_trans 1 _ _ _ rw1 rw5) ;; bvxnor t1 t2 -> bvnot (bvxor t1' t2')
+(@ rw7 (rw_bvop1_id 1 _ _ rw6 bvnot) ;; (bvnot (bvxnor t1 t2)) ->(bvnot (bvnot (bvxor t1' t2')))
+(@ rw8 (not_idemp 1 _ _ (rw_term_id 1 t5)) ;; (bvnot (bvnot (bvxor t1' t2'))) -> bvxor t1' t2'
+(@ rw9 (rw_term_trans 1 _ _ _ rw7 rw8) ;; (bvnot (bvxnor t1 t2)) -> (bvxor t1' t2')
+(@ rw10 (rw_term_id 1 (a_var_bv 1 x))
+(@ rw11 (rw_eq_id 1 _ _ _ _ rw10 rw9) ;; x = t1 => x = t'
+(apply_rw_formula _ _ rw11 A1)
+
+))))))))))))))))))))))))))))) \ No newline at end of file
diff --git a/proofs/signatures/sat.plf b/proofs/signatures/sat.plf
index 5e2f1cc44..b95caa8fd 100755
--- a/proofs/signatures/sat.plf
+++ b/proofs/signatures/sat.plf
@@ -14,7 +14,7 @@
; constructs for general clauses for R, Q, satlem
-(declare concat (! c1 clause (! c2 clause clause)))
+(declare concat_cl (! c1 clause (! c2 clause clause)))
(declare clr (! l lit (! c clause clause)))
; code to check resolutions
@@ -49,7 +49,7 @@
(match m
(tt (do (ifmarked4 v v (markvar4 v)) c'))
(ff (do (ifmarked4 v (markvar4 v) v) (markvar2 v) (clc l c')))))))))
- ((concat c1 c2) (append (simplify_clause c1) (simplify_clause c2)))
+ ((concat_cl c1 c2) (append (simplify_clause c1) (simplify_clause c2)))
((clr l c1)
(match l
; set mark 1 to indicate we should remove v, and fail if
@@ -81,14 +81,14 @@
(! u1 (holds c1)
(! u2 (holds c2)
(! n var
- (holds (concat (clr (pos n) c1)
+ (holds (concat_cl (clr (pos n) c1)
(clr (neg n) c2)))))))))
(declare Q (! c1 clause (! c2 clause
(! u1 (holds c1)
(! u2 (holds c2)
(! n var
- (holds (concat (clr (neg n) c1)
+ (holds (concat_cl (clr (neg n) c1)
(clr (pos n) c2)))))))))
(declare satlem_simplify
@@ -115,13 +115,13 @@
;
; (check
; (% v1 var
-; (% u1 (holds (concat (clr (neg v1) (clr (pos v1) (clc (pos v1) (clr (pos v1) (clc (pos v1) (clc (neg v1) cln))))))
+; (% u1 (holds (concat_cl (clr (neg v1) (clr (pos v1) (clc (pos v1) (clr (pos v1) (clc (pos v1) (clc (neg v1) cln))))))
; (clc (pos v1) (clc (pos v1) cln))))
; (satlem _ _ _ u1 (\ x x))))))
;(check
; (% v1 var
-; (% u1 (holds (clr (neg v1) (concat (clc (neg v1) cln)
+; (% u1 (holds (clr (neg v1) (concat_cl (clc (neg v1) cln)
; (clr (neg v1) (clc (neg v1) cln)))))
; (satlem _ _ _ u1 (\ x x))))))
diff --git a/proofs/signatures/smt.plf b/proofs/signatures/smt.plf
index 62cdf3f94..fa89a457f 100755
--- a/proofs/signatures/smt.plf
+++ b/proofs/signatures/smt.plf
@@ -11,13 +11,29 @@
; standard logic definitions
(declare true formula)
(declare false formula)
-(declare not (! f formula formula))
-(declare and (! f1 formula (! f2 formula formula)))
-(declare or (! f1 formula (! f2 formula formula)))
-(declare impl (! f1 formula (! f2 formula formula)))
-(declare iff (! f1 formula (! f2 formula formula)))
-(declare xor (! f1 formula (! f2 formula formula)))
-(declare ifte (! b formula (! f1 formula (! f2 formula formula))))
+
+(define formula_op1
+ (! f formula
+ formula))
+
+(define formula_op2
+ (! f1 formula
+ (! f2 formula
+ formula)))
+
+(define formula_op3
+ (! f1 formula
+ (! f2 formula
+ (! f3 formula
+ formula))))
+
+(declare not formula_op1)
+(declare and formula_op2)
+(declare or formula_op2)
+(declare impl formula_op2)
+(declare iff formula_op2)
+(declare xor formula_op2)
+(declare ifte formula_op3)
; terms
(declare sort type)
@@ -46,6 +62,19 @@
(declare Bool sort) ; the special sort for predicates
(declare p_app (! x (term Bool) formula)) ; propositional application of term
+; boolean terms
+(declare t_true (term Bool))
+(declare t_false (term Bool))
+(declare t_t_neq_f
+ (th_holds (not (= Bool t_true t_false))))
+(declare pred_eq_t
+ (! x (term Bool)
+ (! u (th_holds (p_app x))
+ (th_holds (= Bool x t_true)))))
+(declare pred_eq_f
+ (! x (term Bool)
+ (! u (th_holds (not (p_app x)))
+ (th_holds (= Bool x t_false)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
@@ -54,8 +83,12 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; binding between an LF var and an (atomic) formula
+
(declare atom (! v var (! p formula type)))
+; binding between two LF vars
+(declare bvatom (! sat_v var (! bv_v var type)))
+
(declare decl_atom
(! f formula
(! u (! v var
@@ -63,6 +96,19 @@
(holds cln)))
(holds cln))))
+;; declare atom enhanced with mapping
+;; between SAT prop variable and BVSAT prop variable
+(declare decl_bvatom
+ (! f formula
+ (! u (! v var
+ (! bv_v var
+ (! a (atom v f)
+ (! bva (atom bv_v f)
+ (! vbv (bvatom v bv_v)
+ (holds cln))))))
+ (holds cln))))
+
+
; clausify a formula directly
(declare clausify_form
(! f formula
@@ -88,13 +134,18 @@
(! u2 (! v (th_holds f) (holds cln))
(holds cln)))))
-
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Natural deduction rules : used for CNF
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; for eager bit-blasting
+(declare iff_symm
+ (! f formula
+ (th_holds (iff f f))))
+
;; contradiction
@@ -291,8 +342,33 @@
(! u (! o (th_holds (not f))
(holds C))
(holds (clc (pos v) C))))))))
-
+;; Bitvector lemma constructors to assume
+;; the unit clause containing the assumptions
+;; it also requires the mapping between bv_v and v
+;; The resolution proof proving false will use bv_v as the definition clauses use bv_v
+;; but the Problem clauses in the main SAT solver will use v so the learned clause is in terms of v
+(declare bv_asf
+ (! v var
+ (! bv_v var
+ (! f formula
+ (! C clause
+ (! r (atom v f) ;; passed in
+ (! x (bvatom v bv_v) ; establishes the equivalence of v to bv_
+ (! u (! o (holds (clc (neg bv_v) cln)) ;; l binding to be used in proof
+ (holds C))
+ (holds (clc (pos v) C))))))))))
+
+(declare bv_ast
+ (! v var
+ (! bv_v var
+ (! f formula
+ (! C clause
+ (! r (atom v f) ; this is specified
+ (! x (bvatom v bv_v) ; establishes the equivalence of v to bv_v
+ (! u (! o (holds (clc (pos bv_v) cln))
+ (holds C))
+ (holds (clc (neg v) C))))))))))
;; Example:
diff --git a/proofs/signatures/th_arrays.plf b/proofs/signatures/th_arrays.plf
index 0c6b16048..8334f51de 100755
--- a/proofs/signatures/th_arrays.plf
+++ b/proofs/signatures/th_arrays.plf
@@ -3,7 +3,7 @@
; Theory of Arrays
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-; depdends on : th_base.plf
+; depends on : th_base.plf
; sorts
diff --git a/proofs/signatures/th_bv.plf b/proofs/signatures/th_bv.plf
index 0fb50f8cf..c93541085 100755..100644
--- a/proofs/signatures/th_bv.plf
+++ b/proofs/signatures/th_bv.plf
@@ -1,145 +1,174 @@
+;;;; TEMPORARY:
+
+(declare trust-bad (th_holds false))
+
+; helper stuff
+(program mpz_sub ((x mpz) (y mpz)) mpz
+ (mp_add x (mp_mul (~1) y)))
+
+(program mp_ispos ((x mpz)) formula
+ (mp_ifneg x false true))
+
+(program mpz_eq ((x mpz) (y mpz)) formula
+ (mp_ifzero (mpz_sub x y) true false))
+
+(program mpz_lt ((x mpz) (y mpz)) formula
+ (mp_ifneg (mpz_sub x y) true false))
+
+(program mpz_lte ((x mpz) (y mpz)) formula
+ (mp_ifneg (mpz_sub x y) true (mpz_eq x y)))
+
+(program mpz_ ((x mpz) (y mpz)) formula
+ (mp_ifzero (mpz_sub x y) true false))
+
+
; "bitvec" is a term of type "sort"
-(declare BitVec sort)
+; (declare BitVec sort)
+(declare BitVec (!n mpz sort))
; bit type
(declare bit type)
(declare b0 bit)
(declare b1 bit)
-; bit vector type
+; bit vector type used for constants
(declare bv type)
(declare bvn bv)
(declare bvc (! b bit (! v bv bv)))
-; a bv constant term
-(declare a_bv (! v bv (term BitVec)))
; calculate the length of a bitvector
-(program bv_len ((v bv)) mpz
- (match v
- (bvn 0)
- ((bvc b v') (mp_add (bv_len v') 1))))
+;; (program bv_len ((v bv)) mpz
+;; (match v
+;; (bvn 0)
+;; ((bvc b v') (mp_add (bv_len v') 1))))
+
+
+; a bv constant term
+(declare a_bv
+ (! n mpz
+ (! v bv
+ (term (BitVec n)))))
+
; a bv variable
(declare var_bv type)
; a bv variable term
-(declare a_var_bv (! v var_bv (term BitVec)))
-
-
-; bit vector operators
-(define bvoper (! x (term BitVec)
- (! y (term BitVec)
- (term BitVec))))
-(declare bvand bvoper)
-(declare bvadd bvoper)
-;....
-
-; all bit-vector terms are mapped with "bv_atom" to:
-; - a simply-typed term of type "var_bv", which is necessary for bit-blasting
-; - a integer size
-(declare bv_atom (! x (term BitVec) (! y var_bv (! n mpz type))))
-
-(declare decl_bv_atom_var (! n mpz ; must be specified
- (! x var_bv
- (! p (! u (bv_atom (a_var_bv x) x n)
- (holds cln))
- (holds cln)))))
-
-(declare decl_bv_atom_const (! n mpz
- (! v bv
- (! s (^ (bv_len v) n)
- (! p (! w var_bv
- (! u (bv_atom (a_bv v) w n)
- (holds cln)))
- (holds cln))))))
-
-
-; other terms here?
-
-
-; bit blasted terms
-(declare bblt type)
-(declare bbltn bblt)
-(declare bbltc (! f formula (! v bblt bblt)))
-
-; (bblast_term x y) means term x corresponds to bit level interpretation y
-(declare bblast_term (! x (term BitVec) (! y bblt formula)))
-
-; a predicate to represent the n^th bit of a bitvector term
-(declare bblast (! x var_bv (! n mpz formula)))
-
-
-; bit blast constant
-(program bblast_const ((v bv) (n mpz)) bblt
- (mp_ifneg n (match v (bvn bbltn)
- (default (fail bblt)))
- (match v ((bvc b v') (bbltc (match b (b0 false) (b1 true)) (bblast_const v' (mp_add n (~ 1)))))
- (default (fail bblt)))))
-
-(declare bv_bbl_const (! n mpz
- (! v bv
- (! x var_bv
- (! f bblt
- (! u (bv_atom (a_bv v) x n)
- (! c (^ (bblast_const v (mp_add n (~ 1))) f)
- (th_holds (bblast_term (a_bv v) f)))))))))
-
-; bit blast variable
-(program bblast_var ((x var_bv) (n mpz)) bblt
- (mp_ifneg n bbltn
- (bbltc (bblast x n) (bblast_var x (mp_add n (~ 1))))))
-
-(declare bv_bbl_var (! n mpz
- (! x var_bv
- (! f bblt
- (! u (bv_atom (a_var_bv x) x n)
- (! c (^ (bblast_var x (mp_add n (~ 1))) f)
- (th_holds (bblast_term (a_var_bv x) f))))))))
-
-; bit blast x = y
-; for x,y of size n, it will return a conjuction (x.{n-1} = y.{n-1} ^ ( ... ^ (x.0 = y.0 ^ true)))
-(program bblast_eq ((x bblt) (y bblt)) formula
- (match x
- (bbltn (match y (bbltn true) (default (fail formula))))
- ((bbltc fx x') (match y
- (bbltn (fail formula))
- ((bbltc fy y') (and (iff fx fy) (bblast_eq x' y')))))))
-
-(declare bv_bbl_eq (! x (term BitVec)
- (! y (term BitVec)
- (! fx bblt
- (! fy bblt
- (! f formula
- (! ux (th_holds (bblast_term x fx))
- (! uy (th_holds (bblast_term y fy))
- (! c (^ (bblast_eq fx fy) f)
- (th_holds (impl (= BitVec x y) f)))))))))))
-
-
-; rewrite rule :
-; x + y = y + x
-(declare bvadd_symm (! x (term BitVec)
- (! y (term BitVec)
- (! x' var_bv
- (! y' var_bv
- (! n mpz
- (! ux (bv_atom x x' n)
- (! uy (bv_atom y y' n)
- (th_holds (= BitVec (bvadd x y) (bvadd y x)))))))))))
-
-
-
-; necessary?
-(program calc_bvand ((a bv) (b bv)) bv
- (match a
- (bvn (match b (bvn bvn) (default (fail bv))))
- ((bvc ba a') (match b
- ((bvc bb b') (bvc (match ba (b0 b0) (b1 bb)) (calc_bvand a' b')))
- (default (fail bv))))))
-
-; rewrite rule (w constants) :
-; a & b = c
-(declare bvand_const (! c bv
- (! a bv
- (! b bv
- (! u (^ (calc_bvand a b) c)
- (th_holds (= BitVec (bvand (a_bv a) (a_bv b)) (a_bv c)))))))) \ No newline at end of file
+(declare a_var_bv
+ (! n mpz
+ (! v var_bv
+ (term (BitVec n)))))
+
+; bit vector binary operators
+(define bvop2
+ (! n mpz
+ (! x (term (BitVec n))
+ (! y (term (BitVec n))
+ (term (BitVec n))))))
+
+(declare bvand bvop2)
+(declare bvor bvop2)
+(declare bvor bvop2)
+(declare bvxor bvop2)
+(declare bvnand bvop2)
+(declare bvnor bvop2)
+(declare bvxnor bvop2)
+(declare bvmul bvop2)
+(declare bvadd bvop2)
+(declare bvsub bvop2)
+(declare bvudiv bvop2)
+(declare bvurem bvop2)
+(declare bvsdiv bvop2)
+(declare bvsrem bvop2)
+(declare bvsmod bvop2)
+(declare bvshl bvop2)
+(declare bvlshr bvop2)
+(declare bvashr bvop2)
+(declare concat bvop2)
+
+; bit vector unary operators
+(define bvop1
+ (! n mpz
+ (! x (term (BitVec n))
+ (term (BitVec n)))))
+
+
+(declare bvneg bvop1)
+(declare bvnot bvop1)
+(declare rotate_left bvop1)
+(declare rotate_right bvop1)
+
+(declare bvcomp
+ (! n mpz
+ (! t1 (term (BitVec n))
+ (! t2 (term (BitVec n))
+ (term (BitVec 1))))))
+
+
+(declare concat
+ (! n mpz
+ (! m mpz
+ (! m' mpz
+ (! t1 (term (BitVec m))
+ (! t2 (term (BitVec m'))
+ (term (BitVec n))))))))
+
+;; side-condition fails in signature only??
+;; (! s (^ (mp_add m m') n)
+
+;; (declare repeat bvopp)
+
+(declare extract
+ (! n mpz
+ (! i mpz
+ (! j mpz
+ (! m mpz
+ (! t2 (term (BitVec m))
+ (term (BitVec n))))))))
+
+(declare zero_extend
+ (! n mpz
+ (! i mpz
+ (! m mpz
+ (! t2 (term (BitVec m))
+ (term (BitVec n)))))))
+
+(declare sign_extend
+ (! n mpz
+ (! i mpz
+ (! m mpz
+ (! t2 (term (BitVec m))
+ (term (BitVec n)))))))
+
+(declare repeat
+ (! n mpz
+ (! i mpz
+ (! m mpz
+ (! t2 (term (BitVec m))
+ (term (BitVec n)))))))
+
+
+
+;; TODO: add checks for valid typing for these operators
+;; (! c1 (^ (mpz_lte i j)
+;; (! c2 (^ (mpz_lt i n) true)
+;; (! c3 (^ (mp_ifneg i false true) true)
+;; (! c4 (^ (mp_ifneg j false true) true)
+;; (! s (^ (mp_add (mpz_sub i j) 1) m)
+
+
+; bit vector predicates
+(define bvpred
+ (! n mpz
+ (! x (term (BitVec n))
+ (! y (term (BitVec n))
+ formula))))
+
+(declare bvult bvpred)
+(declare bvule bvpred)
+(declare bvugt bvpred)
+(declare bvuge bvpred)
+(declare bvslt bvpred)
+(declare bvsle bvpred)
+(declare bvsgt bvpred)
+(declare bvsge bvpred)
+
diff --git a/proofs/signatures/th_bv_bitblast.plf b/proofs/signatures/th_bv_bitblast.plf
new file mode 100644
index 000000000..8e8c51857
--- /dev/null
+++ b/proofs/signatures/th_bv_bitblast.plf
@@ -0,0 +1,629 @@
+; bit blasted terms as list of formulas
+(declare bblt type)
+(declare bbltn bblt)
+(declare bbltc (! f formula (! v bblt bblt)))
+
+; calculate the length of a bit-blasted term
+(program bblt_len ((v bblt)) mpz
+ (match v
+ (bbltn 0)
+ ((bbltc b v') (mp_add (bblt_len v') 1))))
+
+
+; (bblast_term x y) means term y corresponds to bit level interpretation x
+(declare bblast_term
+ (! n mpz
+ (! x (term (BitVec n))
+ (! y bblt
+ type))))
+
+; FIXME: for unsupported bit-blast terms
+(declare trust_bblast_term
+ (! n mpz
+ (! x (term (BitVec n))
+ (! y bblt
+ (bblast_term n x y)))))
+
+
+(declare decl_bblast
+ (! n mpz
+ (! b bblt
+ (! t (term (BitVec n))
+ (! bb (bblast_term n t b)
+ (! s (^ (bblt_len b) n)
+ (! u (! v (bblast_term n t b) (holds cln))
+ (holds cln))))))))
+
+
+; a predicate to represent the n^th bit of a bitvector term
+(declare bitof
+ (! x var_bv
+ (! n mpz formula)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; BITBLASTING RULES
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; BITBLAST CONSTANT
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(program bblast_const ((v bv) (n mpz)) bblt
+ (mp_ifneg n (match v (bvn bbltn)
+ (default (fail bblt)))
+ (match v ((bvc b v') (bbltc (match b (b0 false) (b1 true)) (bblast_const v' (mp_add n (~ 1)))))
+ (default (fail bblt)))))
+
+(declare bv_bbl_const (! n mpz
+ (! f bblt
+ (! v bv
+ (! c (^ (bblast_const v (mp_add n (~ 1))) f)
+ (bblast_term n (a_bv n v) f))))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; BITBLAST VARIABLE
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(program bblast_var ((x var_bv) (n mpz)) bblt
+ (mp_ifneg n bbltn
+ (bbltc (bitof x n) (bblast_var x (mp_add n (~ 1))))))
+
+(declare bv_bbl_var (! n mpz
+ (! x var_bv
+ (! f bblt
+ (! c (^ (bblast_var x (mp_add n (~ 1))) f)
+ (bblast_term n (a_var_bv n x) f))))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; BITBLAST CONCAT
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(program bblast_concat ((x bblt) (y bblt)) bblt
+ (match x
+ (bbltn (match y ((bbltc by y') (bbltc by (bblast_concat x y')))
+ (bbltn bbltn)))
+ ((bbltc bx x') (bbltc bx (bblast_concat x' y)))))
+
+
+(declare bv_bbl_concat (! n mpz
+ (! m mpz
+ (! m1 mpz
+ (! x (term (BitVec m))
+ (! y (term (BitVec m1))
+ (! xb bblt
+ (! yb bblt
+ (! rb bblt
+ (! xbb (bblast_term m x xb)
+ (! ybb (bblast_term m1 y yb)
+ (! c (^ (bblast_concat xb yb ) rb)
+ (bblast_term n (concat n m m1 x y) rb)))))))))))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; BITBLAST EXTRACT
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(program bblast_extract_rec ((x bblt) (i mpz) (j mpz) (n mpz)) bblt
+ (match x
+ ((bbltc bx x') (mp_ifneg (mpz_sub (mpz_sub j n) 1)
+ (mp_ifneg (mpz_sub (mpz_sub n i) 1)
+ (bbltc bx (bblast_extract_rec x' i j (mpz_sub n 1)))
+ (bblast_extract_rec x' i j (mpz_sub n 1)))
+
+ bbltn))
+ (bbltn bbltn)))
+
+(program bblast_extract ((x bblt) (i mpz) (j mpz) (n mpz)) bblt
+ (bblast_extract_rec x i j (mpz_sub n 1)))
+
+(declare bv_bbl_extract (! n mpz
+ (! i mpz
+ (! j mpz
+ (! m mpz
+ (! x (term (BitVec m))
+ (! xb bblt
+ (! rb bblt
+ (! xbb (bblast_term m x xb)
+ (! c ( ^ (bblast_extract xb i j m) rb)
+ (bblast_term n (extract n i j m x) rb)))))))))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; BITBLAST ZERO/SIGN EXTEND
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(program extend_rec ((x bblt) (i mpz) (b formula)) bblt
+ (mp_ifneg i x
+ (bbltc b (extend_rec x (mpz_sub i 1) b)))))
+
+(program bblast_zextend ((x bblt) (i mpz)) bblt
+ (extend_rec x (mpz_sub i 1) false))
+
+(declare bv_bbl_zero_extend (! n mpz
+ (! k mpz
+ (! m mpz
+ (! x (term (BitVec m))
+ (! xb bblt
+ (! rb bblt
+ (! xbb (bblast_term m x xb)
+ (! c ( ^ (bblast_zextend xb k m) rb)
+ (bblast_term n (zero_extend n k m x) rb))))))))))
+
+
+(program bblast_sextend ((x bblt) (i mpz)) bblt
+ (match x (bbltn (fail bblt))
+ ((bbltc xb x') (extend_rec x (mpz_sub i 1) xb))))
+
+(declare bv_bbl_sign_extend (! n mpz
+ (! k mpz
+ (! m mpz
+ (! x (term (BitVec m))
+ (! xb bblt
+ (! rb bblt
+ (! xbb (bblast_term m x xb)
+ (! c ( ^ (bblast_sextend xb k m) rb)
+ (bblast_term n (sign_extend n k m x) rb))))))))))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; BITBLAST BVAND
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(program bblast_bvand ((x bblt) (y bblt)) bblt
+ (match x
+ (bbltn (match y (bbltn bbltn) (default (fail bblt))))
+ ((bbltc bx x') (match y
+ (bbltn (fail bblt))
+ ((bbltc by y') (bbltc (and bx by) (bblast_bvand x' y')))))))
+
+
+(declare bv_bbl_bvand (! n mpz
+ (! x (term (BitVec n))
+ (! y (term (BitVec n))
+ (! xb bblt
+ (! yb bblt
+ (! rb bblt
+ (! xbb (bblast_term n x xb)
+ (! ybb (bblast_term n y yb)
+ (! c (^ (bblast_bvand xb yb ) rb)
+ (bblast_term n (bvand n x y) rb)))))))))))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; BITBLAST BVNOT
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(program bblast_bvnot ((x bblt)) bblt
+ (match x
+ (bbltn bbltn)
+ ((bbltc bx x') (bbltc (not bx) (bblast_bvnot x')))))
+
+
+(declare bv_bbl_bvnot (! n mpz
+ (! x (term (BitVec n))
+ (! xb bblt
+ (! rb bblt
+ (! xbb (bblast_term n x xb)
+ (! c (^ (bblast_bvnot xb ) rb)
+ (bblast_term n (bvnot n x) rb))))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; BITBLAST BVOR
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(program bblast_bvor ((x bblt) (y bblt)) bblt
+ (match x
+ (bbltn (match y (bbltn bbltn) (default (fail bblt))))
+ ((bbltc bx x') (match y
+ (bbltn (fail bblt))
+ ((bbltc by y') (bbltc (or bx by) (bblast_bvor x' y')))))))
+
+
+(declare bv_bbl_bvor (! n mpz
+ (! x (term (BitVec n))
+ (! y (term (BitVec n))
+ (! xb bblt
+ (! yb bblt
+ (! rb bblt
+ (! xbb (bblast_term n x xb)
+ (! ybb (bblast_term n y yb)
+ (! c (^ (bblast_bvor xb yb ) rb)
+ (bblast_term n (bvor n x y) rb)))))))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; BITBLAST BVXOR
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(program bblast_bvxor ((x bblt) (y bblt)) bblt
+ (match x
+ (bbltn (match y (bbltn bbltn) (default (fail bblt))))
+ ((bbltc bx x') (match y
+ (bbltn (fail bblt))
+ ((bbltc by y') (bbltc (xor bx by) (bblast_bvxor x' y')))))))
+
+
+(declare bv_bbl_bvxor (! n mpz
+ (! x (term (BitVec n))
+ (! y (term (BitVec n))
+ (! xb bblt
+ (! yb bblt
+ (! rb bblt
+ (! xbb (bblast_term n x xb)
+ (! ybb (bblast_term n y yb)
+ (! c (^ (bblast_bvxor xb yb ) rb)
+ (bblast_term n (bvxor n x y) rb)))))))))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; BITBLAST BVADD
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; return the carry bit after adding x y
+;; FIXME: not the most efficient thing in the world
+(program bblast_bvadd_carry ((a bblt) (b bblt) (carry formula)) formula
+(match a
+ ( bbltn (match b (bbltn carry) (default (fail formula))))
+ ((bbltc ai a') (match b
+ (bbltn (fail formula))
+ ((bbltc bi b') (or (and ai bi) (and (xor ai bi) (bblast_bvadd_carry a' b' carry))))))))
+
+;; ripple carry adder where carry is the initial carry bit
+(program bblast_bvadd ((a bblt) (b bblt) (carry formula)) bblt
+(match a
+ ( bbltn (match b (bbltn bbltn) (default (fail bblt))))
+ ((bbltc ai a') (match b
+ (bbltn (fail bblt))
+ ((bbltc bi b') (bbltc (xor (xor ai bi) (bblast_bvadd_carry a' b' carry))
+ (bblast_bvadd a' b' carry)))))))
+
+
+(declare bv_bbl_bvadd (! n mpz
+ (! x (term (BitVec n))
+ (! y (term (BitVec n))
+ (! xb bblt
+ (! yb bblt
+ (! rb bblt
+ (! xbb (bblast_term n x xb)
+ (! ybb (bblast_term n y yb)
+ (! c (^ (bblast_bvadd xb yb false) rb)
+ (bblast_term n (bvadd n x y) rb)))))))))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; BITBLAST BVNEG
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(program bblast_zero ((n mpz)) bblt
+(mp_ifzero n bbltn
+ (bbltc false (bblast_zero (mp_add n (~1))))))
+
+(program bblast_bvneg ((x bblt) (n mpz)) bblt
+ (bblast_bvadd (bblast_bvnot x) (bblast_zero n) true))
+
+
+(declare bv_bbl_bvneg (! n mpz
+ (! x (term (BitVec n))
+ (! xb bblt
+ (! rb bblt
+ (! xbb (bblast_term n x xb)
+ (! c (^ (bblast_bvneg xb n) rb)
+ (bblast_term n (bvneg n x) rb))))))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; BITBLAST BVMUL
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+;; shift add multiplier
+
+(program reverse_help ((x bblt) (acc bblt)) bblt
+(match x
+ (bbltn acc)
+ ((bbltc xi x') (reverse_help x' (bbltc xi acc)))))
+
+
+(program reverseb ((x bblt)) bblt
+ (reverse_help x bbltn))
+
+;; (program concat ((a bblt) (b bblt)) bblt
+;; (match a (bbltn b)
+;; ((bbltc ai a') (bbltc ai (concat a' b)))))
+
+
+(program top_k_bits ((a bblt) (k mpz)) bblt
+ (mp_ifzero k bbltn
+ (match a (bbltn (fail bblt))
+ ((bbltc ai a') (bbltc ai (top_k_bits a' (mpz_sub k 1)))))))
+
+(program bottom_k_bits ((a bblt) (k mpz)) bblt
+ (reverseb (top_k_bits (reverseb a) k)))
+
+;; assumes the least signigicant bit is at the beginning of the list
+(program k_bit ((a bblt) (k mpz)) formula
+(mp_ifneg k (fail formula)
+(match a (bbltn (fail formula))
+ ((bbltc ai a') (mp_ifzero k ai (k_bit a' (mpz_sub k 1)))))))
+
+(program and_with_bit ((a bblt) (bt formula)) bblt
+(match a (bbltn bbltn)
+ ((bbltc ai a') (bbltc (and bt ai) (and_with_bit a' bt)))))
+
+;; a is going to be the current result
+;; carry is going to be false initially
+;; b is the and of a and b[k]
+;; res is going to be bbltn initially
+(program mult_step_k_h ((a bblt) (b bblt) (res bblt) (carry formula) (k mpz)) bblt
+(match a
+ (bbltn (match b (bbltn res) (default (fail bblt))))
+ ((bbltc ai a')
+ (match b (bbltn (fail bblt))
+ ((bbltc bi b')
+ (mp_ifneg (mpz_sub k 1)
+ (let carry_out (or (and ai bi) (and (xor ai bi) carry))
+ (let curr (xor (xor ai bi) carry)
+ (mult_step_k_h a' b' (bbltc curr res) carry_out (mpz_sub k 1))))
+ (mult_step_k_h a' b (bbltc ai res) carry (mpz_sub k 1))
+))))))
+
+;; assumes that a, b and res have already been reversed
+(program mult_step ((a bblt) (b bblt) (res bblt) (n mpz) (k mpz)) bblt
+(let k' (mpz_sub n k )
+(let ak (top_k_bits a k')
+(let b' (and_with_bit ak (k_bit b k))
+ (mp_ifzero (mpz_sub k' 1)
+ (mult_step_k_h res b' bbltn false k)
+ (let res' (mult_step_k_h res b' bbltn false k)
+ (mult_step a b (reverseb res') n (mp_add k 1))))))))
+
+
+(program bblast_bvmul ((a bblt) (b bblt) (n mpz)) bblt
+(let ar (reverseb a) ;; reverse a and b so that we can build the circuit
+(let br (reverseb b) ;; from the least significant bit up
+(let res (and_with_bit ar (k_bit br 0))
+ (mp_ifzero (mpz_sub n 1) ;; if multiplying 1 bit numbers no need to call mult_step
+ res
+ (mult_step ar br res n 1))))))
+
+(declare bv_bbl_bvmul (! n mpz
+ (! x (term (BitVec n))
+ (! y (term (BitVec n))
+ (! xb bblt
+ (! yb bblt
+ (! rb bblt
+ (! xbb (bblast_term n x xb)
+ (! ybb (bblast_term n y yb)
+ (! c (^ (bblast_bvmul xb yb n) rb)
+ (bblast_term n (bvmul n x y) rb)))))))))))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; BITBLAST EQUALS
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; bit blast x = y
+; for x,y of size n, it will return a conjuction (x.0 = y.0 ^ ( ... ^ (x.{n-1} = y.{n-1})))
+; f is the accumulator formula that builds the equality in the right order
+(program bblast_eq_rec ((x bblt) (y bblt) (f formula)) formula
+ (match x
+ (bbltn (match y (bbltn f) (default (fail formula))))
+ ((bbltc fx x') (match y
+ (bbltn (fail formula))
+ ((bbltc fy y') (bblast_eq_rec x' y' (and (iff fx fy) f)))))
+ (default (fail formula))))
+
+(program bblast_eq ((x bblt) (y bblt)) formula
+ (match x
+ ((bbltc bx x') (match y ((bbltc by y') (bblast_eq_rec x' y' (iff bx by)))
+ (default (fail formula))))
+ (default (fail formula))))
+
+(declare bv_bbl_=
+ (! n mpz
+ (! x (term (BitVec n))
+ (! y (term (BitVec n))
+ (! bx bblt
+ (! by bblt
+ (! f formula
+ (! bbx (bblast_term n x bx)
+ (! bby (bblast_term n y by)
+ (! c (^ (bblast_eq bx by) f)
+ (th_holds (iff (= (BitVec n) x y) f))))))))))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; BITBLAST BVULT
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(program bblast_bvult ((x bblt) (y bblt) (n mpz)) formula
+(match x
+ ( bbltn (fail formula))
+ ((bbltc xi x') (match y
+ (bbltn (fail formula))
+ ((bbltc yi y') (mp_ifzero n
+ (and (not xi) yi)
+ (or (and (iff xi yi) (bblast_bvult x' y' (mp_add n (~1)))) (and (not xi) yi))))))))
+
+(declare bv_bbl_bvult
+ (! n mpz
+ (! x (term (BitVec n))
+ (! y (term (BitVec n))
+ (! bx bblt
+ (! by bblt
+ (! f formula
+ (! bbx (bblast_term n x bx)
+ (! bby (bblast_term n y by)
+ (! c (^ (bblast_bvult bx by (mp_add n (~1))) f)
+ (th_holds (iff (bvult n x y) f))))))))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; BITBLAST BVSLT
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(program bblast_bvslt ((x bblt) (y bblt) (n mpz)) formula
+(match x
+ ( bbltn (fail formula))
+ ((bbltc xi x') (match y
+ (bbltn (fail formula))
+ ((bbltc yi y') (mp_ifzero (mpz_sub n 1)
+ (and xi (not yi))
+ (or (and (iff xi yi)
+ (bblast_bvult x' y' (mpz_sub n 2)))
+ (and xi (not yi)))))))))
+
+(declare bv_bbl_bvslt
+ (! n mpz
+ (! x (term (BitVec n))
+ (! y (term (BitVec n))
+ (! bx bblt
+ (! by bblt
+ (! f formula
+ (! bbx (bblast_term n x bx)
+ (! bby (bblast_term n y by)
+ (! c (^ (bblast_bvslt bx by n) f)
+ (th_holds (iff (bvslt n x y) f))))))))))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; BITBLASTING CONNECTORS
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+; bit-blasting connections
+
+(declare intro_assump_t
+ (! f formula
+ (! v var
+ (! C clause
+ (! h (th_holds f)
+ (! a (atom v f)
+ (! u (! unit (holds (clc (pos v) cln))
+ (holds C))
+ (holds C))))))))
+
+(declare intro_assump_f
+ (! f formula
+ (! v var
+ (! C clause
+ (! h (th_holds (not f))
+ (! a (atom v f)
+ (! u (! unit (holds (clc (neg v) cln))
+ (holds C))
+ (holds C))))))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; REWRITE RULES
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+; rewrite rule :
+; x + y = y + x
+(declare bvadd_symm
+ (! n mpz
+ (! x (term (BitVec n))
+ (! y (term (BitVec n))
+ (th_holds (= (BitVec n) (bvadd _ x y) (bvadd _ y x)))))))
+
+;; (declare bvcrazy_rewrite
+;; (! n mpz
+;; (! x (term (BitVec n))
+;; (! y (term (BitVec n))
+;; (! xn bv_poly
+;; (! yn bv_poly
+;; (! hxn (bv_normalizes x xn)
+;; (! hyn (bv_normalizes y yn)
+;; (! s (^ (rewrite_scc xn yn) true)
+;; (! u (! x (term (BitVec n)) (holds cln))
+;; (holds cln)))))))))))
+
+;; (th_holds (= (BitVec n) (bvadd x y) (bvadd y x)))))))
+
+
+
+; necessary?
+;; (program calc_bvand ((a bv) (b bv)) bv
+;; (match a
+;; (bvn (match b (bvn bvn) (default (fail bv))))
+;; ((bvc ba a') (match b
+;; ((bvc bb b') (bvc (match ba (b0 b0) (b1 bb)) (calc_bvand a' b')))
+;; (default (fail bv))))))
+
+;; ; rewrite rule (w constants) :
+;; ; a & b = c
+;; (declare bvand_const (! c bv
+;; (! a bv
+;; (! b bv
+;; (! u (^ (calc_bvand a b) c)
+;; (th_holds (= BitVec (bvand (a_bv a) (a_bv b)) (a_bv c))))))))
+
+
+;; making constant bit-vectors
+(program mk_ones ((n mpz)) bv
+ (mp_ifzero n bvn (bvc b1 (mk_ones (mpz_sub n 1)))))
+
+(program mk_zero ((n mpz)) bv
+ (mp_ifzero n bvn (bvc b0 (mk_ones (mpz_sub n 1)))))
+
+
+
+;; (bvxnor a b) => (bvnot (bvxor a b))
+;; (declare bvxnor_elim
+;; (! n mpz
+;; (! a (term (BitVec n))
+;; (! b (term (BitVec n))
+;; (! a' (term (BitVec n))
+;; (! b' (term (BitVec n))
+;; (! rwa (rw_term _ a a')
+;; (! rwb (rw_term _ b b')
+;; (rw_term n (bvxnor _ a b)
+;; (bvnot _ (bvxor _ a' b')))))))))))
+
+
+
+;; ;; (bvxor a 0) => a
+;; (declare bvxor_zero
+;; (! n mpz
+;; (! zero_bits bv
+;; (! sc (^ (mk_zero n) zero_bits)
+;; (! a (term (BitVec n))
+;; (! b (term (BitVec n))
+;; (! a' (term (BitVec n))
+;; (! rwa (rw_term _ a a')
+;; (! rwb (rw_term _ b (a_bv _ zero_bits))
+;; (rw_term _ (bvxor _ a b)
+;; a'))))))))))
+
+;; ;; (bvxor a 11) => (bvnot a)
+;; (declare bvxor_one
+;; (! n mpz
+;; (! one_bits bv
+;; (! sc (^ (mk_ones n) one_bits)
+;; (! a (term (BitVec n))
+;; (! b (term (BitVec n))
+;; (! a' (term (BitVec n))
+;; (! rwa (rw_term _ a a')
+;; (! rwb (rw_term _ b (a_bv _ one_bits))
+;; (rw_term _ (bvxor _ a b)
+;; (bvnot _ a')))))))))))
+
+
+;; ;; (bvnot (bvnot a)) => a
+;; (declare bvnot_idemp
+;; (! n mpz
+;; (! a (term (BitVec n))
+;; (! a' (term (BitVec n))
+;; (! rwa (rw_term _ a a')
+;; (rw_term _ (bvnot _ (bvnot _ a))
+;; a'))))))
+
diff --git a/src/Makefile.am b/src/Makefile.am
index ec6464cdb..c71caea51 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -78,13 +78,20 @@ libcvc4_la_SOURCES = \
printer/tptp/tptp_printer.cpp \
proof/proof.h \
proof/sat_proof.h \
- proof/sat_proof.cpp \
+ proof/sat_proof_implementation.h \
proof/cnf_proof.h \
proof/cnf_proof.cpp \
proof/theory_proof.h \
proof/theory_proof.cpp \
+ proof/uf_proof.h \
+ proof/uf_proof.cpp \
+ proof/array_proof.h \
+ proof/bitvector_proof.h \
+ proof/bitvector_proof.cpp \
proof/proof_manager.h \
proof/proof_manager.cpp \
+ proof/proof_utils.h \
+ proof/proof_utils.cpp \
proof/unsat_core.cpp \
proof/unsat_core.h \
prop/registrar.h \
diff --git a/src/options/bv_options b/src/options/bv_options
index 73790b562..245c56b51 100644
--- a/src/options/bv_options
+++ b/src/options/bv_options
@@ -19,19 +19,19 @@ expert-option bitvectorAigSimplifications --bv-aig-simp=COMMAND std::string :def
# Options for lazy bit-blasting
-option bitvectorPropagate --bv-propagate bool :default true :read-write :link --bitblast=lazy
+option bitvectorPropagate --bv-propagate bool :default true :read-write
use bit-vector propagation in the bit-blaster
-option bitvectorEqualitySolver --bv-eq-solver bool :default true :read-write :link --bitblast=lazy
+option bitvectorEqualitySolver --bv-eq-solver bool :default true :read-write
use the equality engine for the bit-vector theory (only if --bitblast=lazy)
option bitvectorEqualitySlicer --bv-eq-slicer=MODE CVC4::theory::bv::BvSlicerMode :handler CVC4::options::stringToBvSlicerMode :default CVC4::theory::bv::BITVECTOR_SLICER_OFF :read-write :include "options/bv_bitblast_mode.h" :handler-include "options/options_handler_interface.h" :read-write :link --bv-eq-solver
turn on the slicing equality solver for the bit-vector theory (only if --bitblast=lazy)
-option bitvectorInequalitySolver --bv-inequality-solver bool :default true :read-write :link --bitblast=lazy
+option bitvectorInequalitySolver --bv-inequality-solver bool :default true :read-write
turn on the inequality solver for the bit-vector theory (only if --bitblast=lazy)
-option bitvectorAlgebraicSolver --bv-algebraic-solver bool :default true :read-write :link --bitblast=lazy
+option bitvectorAlgebraicSolver --bv-algebraic-solver bool :default true :read-write
turn on the algebraic solver for the bit-vector theory (only if --bitblast=lazy)
expert-option bitvectorAlgebraicBudget --bv-algebraic-budget unsigned :default 1500 :read-write :link --bv-algebraic-solver
diff --git a/src/proof/array_proof.h b/src/proof/array_proof.h
new file mode 100644
index 000000000..beaf5194c
--- /dev/null
+++ b/src/proof/array_proof.h
@@ -0,0 +1,78 @@
+/********************* */
+/*! \file array_proof.h
+ ** \verbatim
+ ** Original author: Liana Hadarean
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2014 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Arrray proof
+ **
+ ** Arrau proof
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__ARRAY__PROOF_H
+#define __CVC4__ARRAY__PROOF_H
+
+#include "expr/expr.h"
+#include "proof/proof_manager.h"
+#include "proof/theory_proof.h"
+#include "theory/arrays/theory_arrays.h"
+
+namespace CVC4 {
+
+namespace theory {
+namespace arrays{
+class TheoryArrays;
+} /* namespace CVC4::theory::arrays */
+} /* namespace CVC4::theory */
+
+class ArrayProof : public TheoryProof {
+ // TODO: whatever goes in this theory
+public:
+ ArrayProof(theory::arrays::TheoryArrays* arrays, TheoryProofEngine* proofEngine)
+ : TheoryProof(arrays, proofEngine)
+ {}
+ virtual void registerTerm(Expr term) {}
+
+ virtual void printTerm(Expr term, std::ostream& os, const LetMap& map) = 0;
+ virtual void printSort(Type type, std::ostream& os) = 0;
+ /**
+ * Print a proof for the theory lemma. Must prove
+ * clause representing lemma to be used in resolution proof.
+ *
+ * @param lemma clausal form of lemma
+ * @param os output stream
+ */
+ virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren) = 0;
+ /**
+ * Print the variable/sorts declarations for this theory.
+ *
+ * @param os
+ * @param paren
+ */
+ virtual void printDeclarations(std::ostream& os, std::ostream& paren) = 0;
+};
+
+class LFSCArrayProof : public ArrayProof {
+public:
+ LFSCArrayProof(theory::arrays::TheoryArrays* uf, TheoryProofEngine* proofEngine)
+ : ArrayProof(uf, proofEngine)
+ {}
+ // TODO implement
+ virtual void printTerm(Expr term, std::ostream& os, const LetMap& map) {}
+ virtual void printSort(Type type, std::ostream& os) {}
+ virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren) {}
+ virtual void printDeclarations(std::ostream& os, std::ostream& paren) {}
+
+};
+
+
+}/* CVC4 namespace */
+
+#endif /* __CVC4__ARRAY__PROOF_H */
diff --git a/src/proof/bitvector_proof.cpp b/src/proof/bitvector_proof.cpp
new file mode 100644
index 000000000..e067f0bce
--- /dev/null
+++ b/src/proof/bitvector_proof.cpp
@@ -0,0 +1,602 @@
+/********************* */
+/*! \file bitvector_proof.cpp
+** \verbatim
+** Original author: Liana Hadarean
+** Major contributors: none
+** Minor contributors (to current version): none
+** This file is part of the CVC4 project.
+** Copyright (c) 2009-2014 New York University and The University of Iowa
+** See the file COPYING in the top-level source directory for licensing
+** information.\endverbatim
+**
+** \brief [[ Add one-line brief description here ]]
+**
+** [[ Add lengthier description here ]]
+** \todo document this file
+**/
+
+
+#include "proof/bitvector_proof.h"
+#include "options/bv_options.h"
+#include "proof/proof_utils.h"
+#include "proof/sat_proof_implementation.h"
+#include "prop/bvminisat/bvminisat.h"
+#include "theory/bv/bitblaster_template.h"
+#include "theory/bv/theory_bv.h"
+
+using namespace CVC4::theory;
+using namespace CVC4::theory::bv;
+
+namespace CVC4 {
+
+BitVectorProof::BitVectorProof(theory::bv::TheoryBV* bv, TheoryProofEngine* proofEngine)
+ : TheoryProof(bv, proofEngine)
+ , d_declarations()
+ , d_seenBBTerms()
+ , d_bbTerms()
+ , d_bbAtoms()
+ , d_resolutionProof(NULL)
+ , d_cnfProof(NULL)
+ , d_bitblaster(NULL)
+{}
+
+void BitVectorProof::initSatProof(CVC4::BVMinisat::Solver* solver) {
+ Assert (d_resolutionProof == NULL);
+ d_resolutionProof = new LFSCBVSatProof(solver, "bb", true);
+}
+
+void BitVectorProof::initCnfProof(prop::CnfStream* cnfStream,
+ context::Context* cnf) {
+ Assert (d_cnfProof == NULL);
+ d_cnfProof = new LFSCCnfProof(cnfStream, cnf, "bb");
+ Assert (d_resolutionProof != NULL);
+ d_resolutionProof->setCnfProof(d_cnfProof);
+
+ // true and false have to be setup in a special way
+ Node true_node = NodeManager::currentNM()->mkConst<bool>(true);
+ Node false_node = NodeManager::currentNM()->mkConst<bool>(false).notNode();
+
+ d_cnfProof->pushCurrentAssertion(true_node);
+ d_cnfProof->pushCurrentDefinition(true_node);
+ d_cnfProof->registerConvertedClause(d_resolutionProof->getTrueUnit());
+ d_cnfProof->popCurrentAssertion();
+ d_cnfProof->popCurrentDefinition();
+
+ d_cnfProof->pushCurrentAssertion(false_node);
+ d_cnfProof->pushCurrentDefinition(false_node);
+ d_cnfProof->registerConvertedClause(d_resolutionProof->getFalseUnit());
+ d_cnfProof->popCurrentAssertion();
+ d_cnfProof->popCurrentDefinition();
+}
+
+void BitVectorProof::setBitblaster(bv::TBitblaster<Node>* bb) {
+ Assert (d_bitblaster == NULL);
+ d_bitblaster = bb;
+}
+
+BVSatProof* BitVectorProof::getSatProof() {
+ Assert (d_resolutionProof != NULL);
+ return d_resolutionProof;
+}
+
+void BitVectorProof::registerTermBB(Expr term) {
+ if (d_seenBBTerms.find(term) != d_seenBBTerms.end())
+ return;
+
+ d_seenBBTerms.insert(term);
+ d_bbTerms.push_back(term);
+}
+
+void BitVectorProof::registerAtomBB(Expr atom, Expr atom_bb) {
+ Expr def = atom.iffExpr(atom_bb);
+ d_bbAtoms.insert(std::make_pair(atom, def));
+ registerTerm(atom);
+}
+
+void BitVectorProof::registerTerm(Expr term) {
+ d_usedBB.insert(term);
+
+ if (Theory::isLeafOf(term, theory::THEORY_BV) &&
+ !term.isConst()) {
+ d_declarations.insert(term);
+ }
+
+ // don't care about parametric operators for bv?
+ for (unsigned i = 0; i < term.getNumChildren(); ++i) {
+ d_proofEngine->registerTerm(term[i]);
+ }
+}
+
+std::string BitVectorProof::getBBTermName(Expr expr) {
+ std::ostringstream os;
+ os << "bt"<< expr.getId();
+ return os.str();
+}
+
+void BitVectorProof::startBVConflict(CVC4::BVMinisat::Solver::TCRef cr) {
+ d_resolutionProof->startResChain(cr);
+}
+
+void BitVectorProof::startBVConflict(CVC4::BVMinisat::Solver::TLit lit) {
+ d_resolutionProof->startResChain(lit);
+}
+
+void BitVectorProof::endBVConflict(const CVC4::BVMinisat::Solver::TLitVec& confl) {
+ std::vector<Expr> expr_confl;
+ for (int i = 0; i < confl.size(); ++i) {
+ prop::SatLiteral lit = prop::BVMinisatSatSolver::toSatLiteral(confl[i]);
+ Expr atom = d_cnfProof->getAtom(lit.getSatVariable()).toExpr();
+ Expr expr_lit = lit.isNegated() ? atom.notExpr() : atom;
+ expr_confl.push_back(expr_lit);
+ }
+ Expr conflict = utils::mkSortedExpr(kind::OR, expr_confl);
+ Debug("bv-proof") << "Make conflict for " << conflict << std::endl;
+
+ if (d_bbConflictMap.find(conflict) != d_bbConflictMap.end()) {
+ Debug("bv-proof") << "Abort...already conflict for " << conflict << std::endl;
+ // This can only happen when we have eager explanations in the bv solver
+ // if we don't get to propagate p before ~p is already asserted
+ d_resolutionProof->cancelResChain();
+ return;
+ }
+
+ // we don't need to check for uniqueness in the sat solver then
+ ClauseId clause_id = d_resolutionProof->registerAssumptionConflict(confl);
+ d_bbConflictMap[conflict] = clause_id;
+ d_resolutionProof->endResChain(clause_id);
+ Debug("bv-proof") << "BitVectorProof::endBVConflict id"<<clause_id<< " => " << conflict << "\n";
+ d_isAssumptionConflict = false;
+}
+
+void BitVectorProof::finalizeConflicts(std::vector<Expr>& conflicts) {
+ if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
+ Debug("bv-proof") << "Construct full proof." << std::endl;
+ d_resolutionProof->constructProof();
+ return;
+ }
+ for(unsigned i = 0; i < conflicts.size(); ++i) {
+ Expr confl = conflicts[i];
+ Debug("bv-proof") << "Finalize conflict " << confl << std::endl;
+ //Assert (d_bbConflictMap.find(confl) != d_bbConflictMap.end());
+ if(d_bbConflictMap.find(confl) != d_bbConflictMap.end()){
+ ClauseId id = d_bbConflictMap[confl];
+ d_resolutionProof->collectClauses(id);
+ }else{
+ Debug("bv-proof") << "Do not collect clauses for " << confl << std::endl;
+ }
+ }
+}
+
+void LFSCBitVectorProof::printTerm(Expr term, std::ostream& os, const LetMap& map) {
+ Assert (Theory::theoryOf(term) == THEORY_BV);
+
+ // peel off eager bit-blasting trick
+ if (term.getKind() == kind::BITVECTOR_EAGER_ATOM) {
+ d_proofEngine->printBoundTerm(term[0], os, map);
+ return;
+ }
+
+ switch (term.getKind()) {
+ case kind::CONST_BITVECTOR : {
+ printConstant(term, os);
+ return;
+ }
+ case kind::BITVECTOR_AND :
+ case kind::BITVECTOR_OR :
+ case kind::BITVECTOR_XOR :
+ case kind::BITVECTOR_NAND :
+ case kind::BITVECTOR_NOR :
+ case kind::BITVECTOR_XNOR :
+ case kind::BITVECTOR_COMP :
+ case kind::BITVECTOR_MULT :
+ case kind::BITVECTOR_PLUS :
+ case kind::BITVECTOR_SUB :
+ case kind::BITVECTOR_UDIV :
+ case kind::BITVECTOR_UREM :
+ case kind::BITVECTOR_UDIV_TOTAL :
+ case kind::BITVECTOR_UREM_TOTAL :
+ case kind::BITVECTOR_SDIV :
+ case kind::BITVECTOR_SREM :
+ case kind::BITVECTOR_SMOD :
+ case kind::BITVECTOR_SHL :
+ case kind::BITVECTOR_LSHR :
+ case kind::BITVECTOR_ASHR :
+ case kind::BITVECTOR_CONCAT : {
+ printOperatorNary(term, os, map);
+ return;
+ }
+ case kind::BITVECTOR_NEG :
+ case kind::BITVECTOR_NOT :
+ case kind::BITVECTOR_ROTATE_LEFT :
+ case kind::BITVECTOR_ROTATE_RIGHT : {
+ printOperatorUnary(term, os, map);
+ return;
+ }
+ case kind::EQUAL :
+ case kind::BITVECTOR_ULT :
+ case kind::BITVECTOR_ULE :
+ case kind::BITVECTOR_UGT :
+ case kind::BITVECTOR_UGE :
+ case kind::BITVECTOR_SLT :
+ case kind::BITVECTOR_SLE :
+ case kind::BITVECTOR_SGT :
+ case kind::BITVECTOR_SGE : {
+ printPredicate(term, os, map);
+ return;
+ }
+ case kind::BITVECTOR_EXTRACT :
+ case kind::BITVECTOR_REPEAT :
+ case kind::BITVECTOR_ZERO_EXTEND :
+ case kind::BITVECTOR_SIGN_EXTEND : {
+ printOperatorParametric(term, os, map);
+ return;
+ }
+ case kind::BITVECTOR_BITOF : {
+ printBitOf(term, os);
+ return;
+ }
+ case kind::VARIABLE:
+ case kind::SKOLEM: {
+ os << "(a_var_bv " << utils::getSize(term)<<" " << ProofManager::sanitize(term) <<")";
+ return;
+ }
+ default:
+ Unreachable();
+ }
+}
+
+void LFSCBitVectorProof::printBitOf(Expr term, std::ostream& os) {
+ Assert (term.getKind() == kind::BITVECTOR_BITOF);
+ unsigned bit = term.getOperator().getConst<BitVectorBitOf>().bitIndex;
+ Expr var = term[0];
+ Assert (var.getKind() == kind::VARIABLE ||
+ var.getKind() == kind::SKOLEM);
+ os << "(bitof " << ProofManager::sanitize(var) <<" " << bit <<")";
+}
+
+void LFSCBitVectorProof::printConstant(Expr term, std::ostream& os) {
+ Assert (term.isConst());
+ os <<"(a_bv " << utils::getSize(term)<<" ";
+ std::ostringstream paren;
+ int size = utils::getSize(term);
+ for (int i = size - 1; i >= 0; --i) {
+ os << "(bvc ";
+ os << (utils::getBit(term, i) ? "b1" : "b0") <<" ";
+ paren << ")";
+ }
+ os << " bvn)";
+ os << paren.str();
+}
+
+void LFSCBitVectorProof::printOperatorNary(Expr term, std::ostream& os, const LetMap& map) {
+ std::string op = utils::toLFSCKind(term.getKind());
+ std::ostringstream paren;
+ std::string holes = term.getKind() == kind::BITVECTOR_CONCAT ? "_ _ " : "";
+ unsigned size = term.getKind() == kind::BITVECTOR_CONCAT? utils::getSize(term) :
+ utils::getSize(term[0]); // cause of COMP
+
+ for (unsigned i = 0; i < term.getNumChildren() - 1; ++i) {
+ os <<"("<< op <<" " << size <<" " << holes;
+ }
+ d_proofEngine->printBoundTerm(term[0], os, map);
+ os <<" ";
+ for (unsigned i = 1; i < term.getNumChildren(); ++i) {
+ d_proofEngine->printBoundTerm(term[i], os, map);
+ os << ")";
+ }
+}
+
+void LFSCBitVectorProof::printOperatorUnary(Expr term, std::ostream& os, const LetMap& map) {
+ os <<"(";
+ os << utils::toLFSCKind(term.getKind()) << " " << utils::getSize(term) <<" ";
+ os << " ";
+ d_proofEngine->printBoundTerm(term[0], os, map);
+ os <<")";
+}
+
+void LFSCBitVectorProof::printPredicate(Expr term, std::ostream& os, const LetMap& map) {
+ os <<"(";
+ os << utils::toLFSCKind(term.getKind()) << " " << utils::getSize(term[0]) <<" ";
+ os << " ";
+ d_proofEngine->printBoundTerm(term[0], os, map);
+ os << " ";
+ d_proofEngine->printBoundTerm(term[1], os, map);
+ os <<")";
+}
+
+void LFSCBitVectorProof::printOperatorParametric(Expr term, std::ostream& os, const LetMap& map) {
+ os <<"(";
+ os << utils::toLFSCKind(term.getKind()) << " " << utils::getSize(term) <<" ";
+ os <<" ";
+ if (term.getKind() == kind::BITVECTOR_REPEAT) {
+ unsigned amount = term.getOperator().getConst<BitVectorRepeat>().repeatAmount;
+ os << amount <<" _ ";
+ }
+ if (term.getKind() == kind::BITVECTOR_SIGN_EXTEND) {
+ unsigned amount = term.getOperator().getConst<BitVectorSignExtend>().signExtendAmount;
+ os << amount <<" _ ";
+ }
+
+ if (term.getKind() == kind::BITVECTOR_ZERO_EXTEND) {
+ unsigned amount = term.getOperator().getConst<BitVectorZeroExtend>().zeroExtendAmount;
+ os << amount<<" _ ";
+ }
+ if (term.getKind() == kind::BITVECTOR_EXTRACT) {
+ unsigned low = utils::getExtractLow(term);
+ unsigned high = utils::getExtractHigh(term);
+ os << high <<" " << low << " " << utils::getSize(term[0]);
+ }
+ os <<" ";
+ Assert (term.getNumChildren() == 1);
+ d_proofEngine->printBoundTerm(term[0], os, map);
+ os <<")";
+}
+
+void LFSCBitVectorProof::printSort(Type type, std::ostream& os) {
+ Assert (type.isBitVector());
+ unsigned width = utils::getSize(type);
+ os << "(BitVec "<<width<<")";
+}
+
+void LFSCBitVectorProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren) {
+ Expr conflict = utils::mkSortedExpr(kind::OR, lemma);
+ if (d_bbConflictMap.find(conflict) != d_bbConflictMap.end()) {
+ std::ostringstream lemma_paren;
+ for (unsigned i = 0; i < lemma.size(); ++i) {
+ Expr lit = lemma[i];
+
+ if (lit.getKind() == kind::NOT) {
+ os << "(intro_assump_t _ _ _ ";
+ } else {
+ os << "(intro_assump_f _ _ _ ";
+ }
+ lemma_paren <<")";
+ // print corresponding literal in main sat solver
+ ProofManager* pm = ProofManager::currentPM();
+ CnfProof* cnf = pm->getCnfProof();
+ prop::SatLiteral main_lit = cnf->getLiteral(lit);
+ os << pm->getLitName(main_lit);
+ os <<" ";
+ // print corresponding literal in bv sat solver
+ prop::SatVariable bb_var = d_cnfProof->getLiteral(lit).getSatVariable();
+ os << pm->getAtomName(bb_var, "bb");
+ os <<"(\\unit"<<bb_var<<"\n";
+ lemma_paren <<")";
+ }
+ Expr lem = utils::mkOr(lemma);
+ Assert (d_bbConflictMap.find(lem) != d_bbConflictMap.end());
+ ClauseId lemma_id = d_bbConflictMap[lem];
+ d_resolutionProof->printAssumptionsResolution(lemma_id, os, lemma_paren);
+ os <<lemma_paren.str();
+ }else{
+ Debug("bv-proof") << std::endl << "; Print non-bitblast theory conflict " << conflict << std::endl;
+ BitVectorProof::printTheoryLemmaProof( lemma, os, paren );
+ }
+}
+void LFSCBitVectorProof::printDeclarations(std::ostream& os, std::ostream& paren) {
+ ExprSet::const_iterator it = d_declarations.begin();
+ ExprSet::const_iterator end = d_declarations.end();
+ for (; it != end; ++it) {
+ os << "(% " << ProofManager::sanitize(*it) <<" var_bv\n";
+ paren <<")";
+ }
+}
+
+
+void LFSCBitVectorProof::printTermBitblasting(Expr term, std::ostream& os) {
+ // TODO: once we have the operator elimination rules remove those that we
+ // eliminated
+ Assert (term.getType().isBitVector());
+ Kind kind = term.getKind();
+
+ if (Theory::isLeafOf(term, theory::THEORY_BV) &&
+ !term.isConst()) {
+ os << "(bv_bbl_var "<<utils::getSize(term) << " " << ProofManager::sanitize(term) <<" _ )";
+ return;
+ }
+
+ switch(kind) {
+ case kind::CONST_BITVECTOR : {
+ os << "(bv_bbl_const "<< utils::getSize(term) <<" _ ";
+ std::ostringstream paren;
+ int size = utils::getSize(term);
+ for (int i = size - 1; i>= 0; --i) {
+ os << "(bvc ";
+ os << (utils::getBit(term, i) ? "b1" : "b0") <<" ";
+ paren << ")";
+ }
+ os << " bvn)";
+ os << paren.str();
+ return;
+ }
+ case kind::BITVECTOR_AND :
+ case kind::BITVECTOR_OR :
+ case kind::BITVECTOR_XOR :
+ case kind::BITVECTOR_NAND :
+ case kind::BITVECTOR_NOR :
+ case kind::BITVECTOR_XNOR :
+ case kind::BITVECTOR_COMP :
+ case kind::BITVECTOR_MULT :
+ case kind::BITVECTOR_PLUS :
+ case kind::BITVECTOR_SUB :
+ case kind::BITVECTOR_CONCAT : {
+ for (unsigned i =0; i < term.getNumChildren() - 1; ++i) {
+ os <<"(bv_bbl_"<< utils::toLFSCKind(kind);
+ if (kind == kind::BITVECTOR_CONCAT) {
+ os << " " << utils::getSize(term) <<" _ ";
+ }
+ os <<" _ _ _ _ _ _ ";
+ }
+ os << getBBTermName(term[0]) <<" ";
+
+ for (unsigned i = 1; i < term.getNumChildren(); ++i) {
+ os << getBBTermName(term[i]);
+ os << ") ";
+ }
+ return;
+ }
+ case kind::BITVECTOR_NEG :
+ case kind::BITVECTOR_NOT :
+ case kind::BITVECTOR_ROTATE_LEFT :
+ case kind::BITVECTOR_ROTATE_RIGHT : {
+ os <<"(bv_bbl_"<<utils::toLFSCKind(kind);
+ os <<" _ _ _ _ ";
+ os << getBBTermName(term[0]);
+ os <<")";
+ return;
+ }
+ case kind::BITVECTOR_EXTRACT : {
+ os <<"(bv_bbl_"<<utils::toLFSCKind(kind) <<" ";
+ os << utils::getSize(term) << " ";
+ os << utils::getExtractHigh(term) << " ";
+ os << utils::getExtractLow(term) << " ";
+ os << " _ _ _ _ ";
+ os << getBBTermName(term[0]);
+ os <<")";
+ return;
+ }
+ case kind::BITVECTOR_REPEAT :
+ case kind::BITVECTOR_ZERO_EXTEND :
+ case kind::BITVECTOR_SIGN_EXTEND : {
+ os <<"(bv_bbl_"<<utils::toLFSCKind(kind) <<" ";
+ os << utils::getSize(term) <<" ";
+ if (term.getKind() == kind::BITVECTOR_REPEAT) {
+ unsigned amount = term.getOperator().getConst<BitVectorRepeat>().repeatAmount;
+ os << amount;
+ }
+ if (term.getKind() == kind::BITVECTOR_SIGN_EXTEND) {
+ unsigned amount = term.getOperator().getConst<BitVectorSignExtend>().signExtendAmount;
+ os << amount;
+ }
+
+ if (term.getKind() == kind::BITVECTOR_ZERO_EXTEND) {
+ unsigned amount = term.getOperator().getConst<BitVectorZeroExtend>().zeroExtendAmount;
+ os << amount;
+ }
+ os <<" _ _ _ _ ";
+ os << getBBTermName(term[0]);
+ os <<")";
+ return;
+ }
+ case kind::BITVECTOR_UDIV :
+ case kind::BITVECTOR_UREM :
+ case kind::BITVECTOR_UDIV_TOTAL :
+ case kind::BITVECTOR_UREM_TOTAL :
+ case kind::BITVECTOR_SDIV :
+ case kind::BITVECTOR_SREM :
+ case kind::BITVECTOR_SMOD :
+ case kind::BITVECTOR_SHL :
+ case kind::BITVECTOR_LSHR :
+ case kind::BITVECTOR_ASHR : {
+ // these are terms for which bit-blasting is not supported yet
+ std::ostringstream paren;
+ os <<"(trust_bblast_term _ ";
+ paren <<")";
+ d_proofEngine->printLetTerm(term, os);
+ os <<" ";
+ std::vector<Node> bits;
+ d_bitblaster->bbTerm(term, bits);
+
+ for (int i = utils::getSize(term) - 1; i >= 0; --i) {
+ os << "(bbltc ";
+ d_proofEngine->printLetTerm((bits[i]).toExpr(), os);
+ paren << ")";
+ }
+ os << "bbltn" << paren.str();
+ return;
+ }
+
+ default:
+ Unreachable("LFSCBitVectorProof Unknown operator");
+ }
+}
+
+void LFSCBitVectorProof::printAtomBitblasting(Expr atom, std::ostream& os) {
+ Kind kind = atom.getKind();
+ switch(kind) {
+ case kind::BITVECTOR_ULT :
+ case kind::BITVECTOR_ULE :
+ case kind::BITVECTOR_UGT :
+ case kind::BITVECTOR_UGE :
+ case kind::BITVECTOR_SLT :
+ case kind::BITVECTOR_SLE :
+ case kind::BITVECTOR_SGT :
+ case kind::BITVECTOR_SGE :
+ case kind::EQUAL:
+ {
+ os <<"(bv_bbl_" << utils::toLFSCKind(atom.getKind());
+ os << " _ _ _ _ _ _ ";
+ os << getBBTermName(atom[0])<<" " << getBBTermName(atom[1]) <<")";
+ return;
+ }
+ default:
+ Unreachable("LFSCBitVectorProof Unknown atom kind");
+ }
+}
+
+
+void LFSCBitVectorProof::printBitblasting(std::ostream& os, std::ostream& paren) {
+ // bit-blast terms
+ std::vector<Expr>::const_iterator it = d_bbTerms.begin();
+ std::vector<Expr>::const_iterator end = d_bbTerms.end();
+ for (; it != end; ++it) {
+ if (d_usedBB.find(*it) == d_usedBB.end() &&
+ options::bitblastMode() != theory::bv::BITBLAST_MODE_EAGER)
+ continue;
+ os <<"(decl_bblast _ _ _ ";
+ printTermBitblasting(*it, os);
+ os << "(\\ "<< getBBTermName(*it);
+ paren <<"\n))";
+ }
+ // bit-blast atoms
+ ExprToExpr::const_iterator ait = d_bbAtoms.begin();
+ ExprToExpr::const_iterator aend = d_bbAtoms.end();
+ for (; ait != aend; ++ait) {
+ if (d_usedBB.find(ait->first) == d_usedBB.end() &&
+ options::bitblastMode() != theory::bv::BITBLAST_MODE_EAGER)
+ continue;
+
+ os << "(th_let_pf _ ";
+ if (ait->first.getKind() == kind::CONST_BOOLEAN) {
+ bool val = ait->first.getConst<bool>();
+ os << "(iff_symm " << (val ? "true" : "false" ) << ")";
+ } else {
+ printAtomBitblasting(ait->first, os);
+ }
+
+ os <<"(\\ " << ProofManager::getPreprocessedAssertionName(ait->second) <<"\n";
+ paren <<"))";
+ }
+}
+
+void LFSCBitVectorProof::printResolutionProof(std::ostream& os,
+ std::ostream& paren) {
+ // collect the input clauses used
+ IdToSatClause used_lemmas;
+ IdToSatClause used_inputs;
+ d_resolutionProof->collectClausesUsed(used_inputs,
+ used_lemmas);
+ Assert (used_lemmas.empty());
+
+ // print mapping between theory atoms and internal SAT variables
+ os << ";; BB atom mapping\n";
+
+ NodeSet atoms;
+ d_cnfProof->collectAtomsForClauses(used_inputs,atoms);
+
+ // first print bit-blasting
+ printBitblasting(os, paren);
+
+ // print CNF conversion proof for bit-blasted facts
+ d_cnfProof->printAtomMapping(atoms, os, paren);
+ os << ";; Bit-blasting definitional clauses \n";
+ for (IdToSatClause::iterator it = used_inputs.begin();
+ it != used_inputs.end(); ++it) {
+ d_cnfProof->printCnfProofForClause(it->first, it->second, os, paren);
+ }
+
+ os << ";; Bit-blasting learned clauses \n";
+ d_resolutionProof->printResolutions(os, paren);
+}
+
+} /* namespace CVC4 */
diff --git a/src/proof/bitvector_proof.h b/src/proof/bitvector_proof.h
new file mode 100644
index 000000000..80d567f7c
--- /dev/null
+++ b/src/proof/bitvector_proof.h
@@ -0,0 +1,142 @@
+/********************* */
+/*! \file bitvector_proof.h
+ ** \verbatim
+ ** Original author: Liana Hadarean
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2014 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Bitvector proof
+ **
+ ** Bitvector proof
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__BITVECTOR__PROOF_H
+#define __CVC4__BITVECTOR__PROOF_H
+
+//#include <cstdint>
+#include <ext/hash_map>
+#include <ext/hash_set>
+#include <iostream>
+#include <set>
+#include <sstream>
+#include <vector>
+
+#include "expr/expr.h"
+#include "proof/theory_proof.h"
+#include "prop/bvminisat/core/Solver.h"
+
+
+namespace CVC4 {
+
+namespace prop {
+class CnfStream;
+} /* namespace CVC4::prop */
+
+namespace theory {
+namespace bv {
+class TheoryBV;
+template <class T> class TBitblaster;
+} /* namespace CVC4::theory::bv */
+} /* namespace CVC4::theory */
+
+class CnfProof;
+} /* namespace CVC4 */
+
+namespace CVC4 {
+
+template <class Solver> class TSatProof;
+typedef TSatProof< CVC4::BVMinisat::Solver> BVSatProof;
+
+template <class Solver> class LFSCSatProof;
+typedef LFSCSatProof< CVC4::BVMinisat::Solver> LFSCBVSatProof;
+
+typedef __gnu_cxx::hash_set<Expr, ExprHashFunction> ExprSet;
+typedef __gnu_cxx::hash_map<Expr, ClauseId, ExprHashFunction> ExprToClauseId;
+typedef __gnu_cxx::hash_map<Expr, unsigned, ExprHashFunction> ExprToId;
+typedef __gnu_cxx::hash_map<Expr, Expr, ExprHashFunction> ExprToExpr;
+
+class BitVectorProof : public TheoryProof {
+protected:
+ ExprSet d_declarations;
+
+ ExprSet d_usedBB; // terms and formulas that are actually relevant to the proof
+
+ ExprSet d_seenBBTerms; // terms that need to be bit-blasted
+ std::vector<Expr> d_bbTerms; // order of bit-blasting
+ ExprToExpr d_bbAtoms; // atoms that need to be bit-blasted
+
+ // map from Expr representing normalized lemma to ClauseId in SAT solver
+ ExprToClauseId d_bbConflictMap;
+ BVSatProof* d_resolutionProof;
+
+ CnfProof* d_cnfProof;
+
+ bool d_isAssumptionConflict;
+ theory::bv::TBitblaster<Node>* d_bitblaster;
+ std::string getBBTermName(Expr expr);
+public:
+ BitVectorProof(theory::bv::TheoryBV* bv, TheoryProofEngine* proofEngine);
+
+ void initSatProof(CVC4::BVMinisat::Solver* solver);
+ void initCnfProof(prop::CnfStream* cnfStream, context::Context* ctx);
+ void setBitblaster(theory::bv::TBitblaster<Node>* bb);
+
+ BVSatProof* getSatProof();
+ CnfProof* getCnfProof() {return d_cnfProof; }
+ void finalizeConflicts(std::vector<Expr>& conflicts);
+
+ void startBVConflict(CVC4::BVMinisat::Solver::TCRef cr);
+ void startBVConflict(CVC4::BVMinisat::Solver::TLit lit);
+ /**
+ * All the
+ *
+ * @param confl an inconsistent set of bv literals
+ */
+ void endBVConflict(const BVMinisat::Solver::TLitVec& confl);
+ void markAssumptionConflict() { d_isAssumptionConflict = true; }
+ bool isAssumptionConflict() { return d_isAssumptionConflict; }
+
+ void registerTermBB(Expr term);
+ void registerAtomBB(Expr atom, Expr atom_bb);
+
+ virtual void registerTerm(Expr term);
+
+ virtual void printTermBitblasting(Expr term, std::ostream& os) = 0;
+ virtual void printAtomBitblasting(Expr term, std::ostream& os) = 0;
+
+ virtual void printBitblasting(std::ostream& os, std::ostream& paren) = 0;
+ virtual void printResolutionProof(std::ostream& os, std::ostream& paren) = 0;
+
+};
+
+class LFSCBitVectorProof: public BitVectorProof {
+
+ void printConstant(Expr term, std::ostream& os);
+ void printOperatorNary(Expr term, std::ostream& os, const LetMap& map);
+ void printOperatorUnary(Expr term, std::ostream& os, const LetMap& map);
+ void printPredicate(Expr term, std::ostream& os, const LetMap& map);
+ void printOperatorParametric(Expr term, std::ostream& os, const LetMap& map);
+ void printBitOf(Expr term, std::ostream& os);
+public:
+ LFSCBitVectorProof(theory::bv::TheoryBV* bv, TheoryProofEngine* proofEngine)
+ :BitVectorProof(bv, proofEngine)
+ {}
+ virtual void printTerm(Expr term, std::ostream& os, const LetMap& map);
+ virtual void printSort(Type type, std::ostream& os);
+ virtual void printTermBitblasting(Expr term, std::ostream& os);
+ virtual void printAtomBitblasting(Expr term, std::ostream& os);
+ virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren);
+ virtual void printDeclarations(std::ostream& os, std::ostream& paren);
+ virtual void printBitblasting(std::ostream& os, std::ostream& paren);
+ virtual void printResolutionProof(std::ostream& os, std::ostream& paren);
+};
+
+}/* CVC4 namespace */
+
+#endif /* __CVC4__BITVECTOR__PROOF_H */
diff --git a/src/proof/cnf_proof.cpp b/src/proof/cnf_proof.cpp
index 263e1fe8c..884a67856 100644
--- a/src/proof/cnf_proof.cpp
+++ b/src/proof/cnf_proof.cpp
@@ -26,518 +26,709 @@ using namespace CVC4::prop;
namespace CVC4 {
-CnfProof::CnfProof(CnfStream* stream)
+CnfProof::CnfProof(CnfStream* stream,
+ context::Context* ctx,
+ const std::string& name)
: d_cnfStream(stream)
-{}
+ , d_clauseToAssertion(ctx)
+ , d_assertionToProofRule(ctx)
+ , d_currentAssertionStack()
+ , d_currentDefinitionStack()
+ , d_clauseToDefinition(ctx)
+ , d_definitions()
+ , d_cnfDeps()
+ , d_name(name)
+{
+ // Setting the proof object for the CnfStream
+ d_cnfStream->setProof(this);
+}
+
+CnfProof::~CnfProof() {}
-CnfProof::~CnfProof() {
+bool CnfProof::isAssertion(Node node) {
+ return d_assertionToProofRule.find(node) !=
+ d_assertionToProofRule.end();
}
-Expr CnfProof::getAtom(prop::SatVariable var) {
- prop::SatLiteral lit (var);
- Node node = d_cnfStream->getNode(lit);
- Expr atom = node.toExpr();
- return atom;
+bool CnfProof::isDefinition(Node node) {
+ return d_definitions.find(node) !=
+ d_definitions.end();
+}
+
+ProofRule CnfProof::getProofRule(Node node) {
+ Assert (isAssertion(node));
+ NodeToProofRule::iterator it = d_assertionToProofRule.find(node);
+ return (*it).second;
+}
+ProofRule CnfProof::getProofRule(ClauseId clause) {
+ TNode assertion = getAssertionForClause(clause);
+ return getProofRule(assertion);
}
-prop::SatLiteral CnfProof::getLiteral(TNode atom) {
- return d_cnfStream->getLiteral(atom);
+Node CnfProof::getAssertionForClause(ClauseId clause) {
+ ClauseIdToNode::const_iterator it = d_clauseToAssertion.find(clause);
+ Assert (it != d_clauseToAssertion.end());
+ return (*it).second;
}
-Expr CnfProof::getAssertion(uint64_t id) {
- return d_cnfStream->getAssertion(id).toExpr();
+Node CnfProof::getDefinitionForClause(ClauseId clause) {
+ ClauseIdToNode::const_iterator it = d_clauseToDefinition.find(clause);
+ Assert (it != d_clauseToDefinition.end());
+ return (*it).second;
}
-void LFSCCnfProof::printAtomMapping(const prop::SatClause* clause, std::ostream& os, std::ostream& paren) {
- for (unsigned i = 0; i < clause->size(); ++i) {
- prop::SatLiteral lit = clause->operator[](i);
- if(d_atomsDeclared.find(lit.getSatVariable()) == d_atomsDeclared.end()) {
- d_atomsDeclared.insert(lit.getSatVariable());
- os << "(decl_atom ";
- if (ProofManager::currentPM()->getLogic().compare("QF_UF") == 0 ||
- ProofManager::currentPM()->getLogic().compare("QF_AX") == 0 ||
- ProofManager::currentPM()->getLogic().compare("QF_SAT") == 0) {
- Expr atom = getAtom(lit.getSatVariable());
- LFSCTheoryProof::printTerm(atom, os);
- } else {
- // print fake atoms for all other logics (for now)
- os << "true ";
- }
+void CnfProof::registerConvertedClause(ClauseId clause, bool explanation) {
+ Assert (clause != ClauseIdUndef &&
+ clause != ClauseIdError &&
+ clause != ClauseIdEmpty);
+
+ // Explanations do not need a CNF conversion proof since they are in CNF
+ // (they will only need a theory proof as they are theory valid)
+ if (explanation) {
+ Debug("proof:cnf") << "CnfProof::registerConvertedClause "
+ << clause << " explanation? " << explanation << std::endl;
+ Assert (d_explanations.find(clause) == d_explanations.end());
+ d_explanations.insert(clause);
+ return;
+ }
- os << " (\\ " << ProofManager::getVarName(lit.getSatVariable()) << " (\\ " << ProofManager::getAtomName(lit.getSatVariable()) << "\n";
- paren << ")))";
- }
+ Node current_assertion = getCurrentAssertion();
+ Node current_expr = getCurrentDefinition();
+
+ Debug("proof:cnf") << "CnfProof::registerConvertedClause "
+ << clause << " assertion = " << current_assertion
+ << clause << " definition = " << current_expr << std::endl;
+
+ setClauseAssertion(clause, current_assertion);
+ setClauseDefinition(clause, current_expr);
+}
+
+void CnfProof::setClauseAssertion(ClauseId clause, Node expr) {
+ Debug("proof:cnf") << "CnfProof::setClauseAssertion "
+ << clause << " assertion " << expr << std::endl;
+ // We can add the same clause from different assertions. In this
+ // case we keep the first assertion. For example asserting a /\ b
+ // and then b /\ c where b is an atom, would assert b twice (note
+ // that since b is top level, it is not cached by the CnfStream)
+ if (d_clauseToAssertion.find(clause) != d_clauseToAssertion.end())
+ return;
+
+ d_clauseToAssertion.insert (clause, expr);
+}
+
+void CnfProof::setClauseDefinition(ClauseId clause, Node definition) {
+ Debug("proof:cnf") << "CnfProof::setClauseDefinition "
+ << clause << " definition " << definition << std::endl;
+ // We keep the first definition
+ if (d_clauseToDefinition.find(clause) != d_clauseToDefinition.end())
+ return;
+
+ d_clauseToDefinition.insert(clause, definition);
+ d_definitions.insert(definition);
+}
+
+void CnfProof::registerAssertion(Node assertion, ProofRule reason) {
+ Debug("proof:cnf") << "CnfProof::registerAssertion "
+ << assertion << " reason " << reason << std::endl;
+ // We can obtain the assertion from different reasons (e.g. if the
+ // assertion is a lemma over shared terms both theories can generate
+ // the same lemma) We only need to prove the lemma in one way, so we
+ // keep the first reason.
+ if (isAssertion(assertion)) {
+ return;
}
+ d_assertionToProofRule.insert(assertion, reason);
}
-void LFSCCnfProof::printClauses(std::ostream& os, std::ostream& paren) {
- printPreprocess(os, paren);
- printInputClauses(os, paren);
- printTheoryLemmas(os, paren);
+void CnfProof::setCnfDependence(Node from, Node to) {
+ Debug("proof:cnf") << "CnfProof::setCnfDependence "
+ << "from " << from << std::endl
+ << " to " << to << std::endl;
+
+ Assert (from != to);
+ d_cnfDeps.insert(std::make_pair(from, to));
}
-void LFSCCnfProof::printPreprocess(std::ostream& os, std::ostream& paren) {
- os << " ;; Preprocessing \n";
- __gnu_cxx::hash_map< Node, std::vector<Node>, NodeHashFunction >::const_iterator it = ProofManager::currentPM()->begin_deps();
- __gnu_cxx::hash_map< Node, std::vector<Node>, NodeHashFunction >::const_iterator end = ProofManager::currentPM()->end_deps();
+void CnfProof::pushCurrentAssertion(Node assertion) {
+ Debug("proof:cnf") << "CnfProof::pushCurrentAssertion "
+ << assertion << std::endl;
- for (; it != end; ++it) {
- if( !it->second.empty() ){
- Expr e = it->first.toExpr();
- os << "(th_let_pf _ ";
+ d_currentAssertionStack.push_back(assertion);
+}
- //TODO
- Trace("cnf-pf-debug") << "; preprocess assertion : " << e << std::endl;
- os << "(trust_f ";
- LFSCTheoryProof::printTerm(e, os);
- os << ") ";
+void CnfProof::popCurrentAssertion() {
+ Assert (d_currentAssertionStack.size());
+
+ Debug("proof:cnf") << "CnfProof::popCurrentAssertion "
+ << d_currentAssertionStack.back() << std::endl;
+
+ d_currentAssertionStack.pop_back();
+}
- os << "(\\ A" << ProofManager::currentPM()->getAssertionCounter() << std::endl;
- ProofManager::currentPM()->setAssertion( e );
- paren << "))";
+Node CnfProof::getCurrentAssertion() {
+ Assert (d_currentAssertionStack.size());
+ return d_currentAssertionStack.back();
+}
+
+void CnfProof::pushCurrentDefinition(Node definition) {
+ Debug("proof:cnf") << "CnfProof::pushCurrentDefinition "
+ << definition << std::endl;
+
+ d_currentDefinitionStack.push_back(definition);
+}
+
+void CnfProof::popCurrentDefinition() {
+ Assert (d_currentDefinitionStack.size());
+
+ Debug("proof:cnf") << "CnfProof::popCurrentDefinition "
+ << d_currentDefinitionStack.back() << std::endl;
+
+ d_currentDefinitionStack.pop_back();
+}
+
+Node CnfProof::getCurrentDefinition() {
+ Assert (d_currentDefinitionStack.size());
+ return d_currentDefinitionStack.back();
+}
+
+
+Node CnfProof::getAtom(prop::SatVariable var) {
+ prop::SatLiteral lit (var);
+ Node node = d_cnfStream->getNode(lit);
+ return node;
+}
+
+
+void CnfProof::collectAtoms(const prop::SatClause* clause,
+ NodeSet& atoms) {
+ for (unsigned i = 0; i < clause->size(); ++i) {
+ SatLiteral lit = clause->operator[](i);
+ SatVariable var = lit.getSatVariable();
+ TNode atom = getAtom(var);
+ if (atoms.find(atom) == atoms.end()) {
+ Assert (atoms.find(atom) == atoms.end());
+ atoms.insert(atom);
+ }
+ }
+}
+
+prop::SatLiteral CnfProof::getLiteral(TNode atom) {
+ return d_cnfStream->getLiteral(atom);
+}
+
+void CnfProof::collectAtomsForClauses(const IdToSatClause& clauses,
+ NodeSet& atom_map) {
+ IdToSatClause::const_iterator it = clauses.begin();
+ for (; it != clauses.end(); ++it) {
+ const prop::SatClause* clause = it->second;
+ collectAtoms(clause, atom_map);
+ }
+
+}
+
+void CnfProof::collectAssertionsForClauses(const IdToSatClause& clauses,
+ NodeSet& assertions) {
+ IdToSatClause::const_iterator it = clauses.begin();
+ for (; it != clauses.end(); ++it) {
+ TNode used_assertion = getAssertionForClause(it->first);
+ assertions.insert(used_assertion);
+ // it can be the case that a definition for a clause is an assertion
+ // but it is not the assertion for the clause
+ // e.g. the assertions [(and a b), a]
+ TNode used_definition = getDefinitionForClause(it->first);
+ if (isAssertion(used_definition)) {
+ assertions.insert(used_definition);
}
}
}
-Expr LFSCCnfProof::clauseToExpr( const prop::SatClause& clause,
- std::map< Expr, unsigned >& childIndex,
- std::map< Expr, bool >& childPol ) {
+void LFSCCnfProof::printAtomMapping(const NodeSet& atoms,
+ std::ostream& os,
+ std::ostream& paren) {
+ NodeSet::const_iterator it = atoms.begin();
+ NodeSet::const_iterator end = atoms.end();
+
+ for (;it != end; ++it) {
+ os << "(decl_atom ";
+ Node atom = *it;
+ prop::SatVariable var = getLiteral(atom).getSatVariable();
+ //FIXME hideous
+ LFSCTheoryProofEngine* pe = (LFSCTheoryProofEngine*)ProofManager::currentPM()->getTheoryProofEngine();
+ pe->printLetTerm(atom.toExpr(), os);
+
+ os << " (\\ " << ProofManager::getVarName(var, d_name)
+ << " (\\ " << ProofManager::getAtomName(var, d_name) << "\n";
+ paren << ")))";
+ }
+}
+
+// maps each expr to the position it had in the clause and the polarity it had
+Node LFSCCnfProof::clauseToNode(const prop::SatClause& clause,
+ std::map<Node, unsigned>& childIndex,
+ std::map<Node, bool>& childPol ) {
std::vector< Node > children;
for (unsigned i = 0; i < clause.size(); ++i) {
prop::SatLiteral lit = clause[i];
prop::SatVariable var = lit.getSatVariable();
- Node atom = Node::fromExpr( getAtom(var) );
+ Node atom = getAtom(var);
children.push_back( lit.isNegated() ? atom.negate() : atom );
- childIndex[atom.toExpr()] = i;
- childPol[atom.toExpr()] = !lit.isNegated();
+ childIndex[atom] = i;
+ childPol[atom] = !lit.isNegated();
}
- return children.size()==1 ? children[0].toExpr() : NodeManager::currentNM()->mkNode( kind::OR, children ).toExpr();
+ return children.size()==1 ? children[0] :
+ NodeManager::currentNM()->mkNode(kind::OR, children );
}
-void LFSCCnfProof::printInputClauses(std::ostream& os, std::ostream& paren) {
- os << " ;; Clauses\n";
- ProofManager::clause_iterator it = ProofManager::currentPM()->begin_input_clauses();
- ProofManager::clause_iterator end = ProofManager::currentPM()->end_input_clauses();
-
-
- for (; it != end; ++it) {
- ClauseId id = it->first;
- const prop::SatClause* clause = it->second;
- printAtomMapping(clause, os, paren);
- os << "(satlem _ _ ";
- std::ostringstream clause_paren;
- printClause(*clause, os, clause_paren);
- os << "(clausify_false ";
-
- Assert( clause->size()>0 );
-
- Expr base_assertion = ProofManager::currentPM()->getFormulaForClauseId( id );
- ProofRule pr = ProofManager::currentPM()->getProofRuleForClauseId( id );
- Trace("cnf-pf") << std::endl;
- Trace("cnf-pf") << "; formula for clause id " << id << " : " << base_assertion << std::endl;
-
- //get the assertion for the clause id
- std::map< Expr, unsigned > childIndex;
- std::map< Expr, bool > childPol;
- Expr assertion = clauseToExpr( *clause, childIndex, childPol );
- //if there is no reason, construct assertion directly. This can happen for unit clauses.
- if( base_assertion.isNull() ){
- base_assertion = assertion;
- }
- //os_base is proof of base_assertion
- std::stringstream os_base;
- bool is_input = ProofManager::currentPM()->isInputAssertion( base_assertion, os_base );
-
- //get base assertion with polarity
- bool base_pol = base_assertion.getKind()!=kind::NOT;
- base_assertion = base_assertion.getKind()==kind::NOT ? base_assertion[0] : base_assertion;
-
- std::map< Expr, unsigned >::iterator itci = childIndex.find( base_assertion );
- bool is_in_clause = itci!=childIndex.end();
- unsigned base_index = is_in_clause ? itci->second : 0;
- Trace("cnf-pf") << "; input = " << is_input << ", is_in_clause = " << is_in_clause << ", id = " << id << ", assertion = " << assertion << ", base assertion = " << base_assertion << std::endl;
- if( !is_input ){
- Assert( is_in_clause );
- prop::SatLiteral blit = (*clause)[ base_index ];
- os_base << ProofManager::getLitName(blit);
- base_pol = !childPol[base_assertion];
+void LFSCCnfProof::printCnfProofForClause(ClauseId id,
+ const prop::SatClause* clause,
+ std::ostream& os,
+ std::ostream& paren) {
+ os << "(satlem _ _ ";
+ std::ostringstream clause_paren;
+ printClause(*clause, os, clause_paren);
+ os << "(clausify_false ";
+
+ // FIXMEEEEEEEEEEEE
+ // os <<"trust)";
+ // os << clause_paren.str()
+ // << " (\\ " << ProofManager::getInputClauseName(id, d_name) << "\n";
+ // paren << "))";
+
+ // return;
+
+ Assert( clause->size()>0 );
+
+ Node base_assertion = getDefinitionForClause(id);
+
+ //get the assertion for the clause id
+ std::map<Node, unsigned > childIndex;
+ std::map<Node, bool > childPol;
+ Node assertion = clauseToNode( *clause, childIndex, childPol );
+ //if there is no reason, construct assertion directly. This can happen for unit clauses.
+ if( base_assertion.isNull() ){
+ base_assertion = assertion;
+ }
+ //os_base is proof of base_assertion
+ std::stringstream os_base;
+
+ // checks if tautological definitional clause or top-level clause
+ // and prints the proof of the top-level formula
+ bool is_input = printProofTopLevel(base_assertion, os_base);
+
+ //get base assertion with polarity
+ bool base_pol = base_assertion.getKind()!=kind::NOT;
+ base_assertion = base_assertion.getKind()==kind::NOT ? base_assertion[0] : base_assertion;
+
+ std::map< Node, unsigned >::iterator itci = childIndex.find( base_assertion );
+ bool is_in_clause = itci!=childIndex.end();
+ unsigned base_index = is_in_clause ? itci->second : 0;
+ Trace("cnf-pf") << std::endl;
+ Trace("cnf-pf") << "; input = " << is_input << ", is_in_clause = " << is_in_clause << ", id = " << id << ", assertion = " << assertion << ", base assertion = " << base_assertion << std::endl;
+ if (!is_input){
+ Assert(is_in_clause);
+ prop::SatLiteral blit = (*clause)[ base_index ];
+ os_base << ProofManager::getLitName(blit, d_name);
+ base_pol = !childPol[base_assertion]; // WHY? if the case is =>
+ }
+ Trace("cnf-pf") << "; polarity of base assertion = " << base_pol << std::endl;
+ Trace("cnf-pf") << "; proof of base : " << os_base.str() << std::endl;
+
+ bool success = false;
+ if( is_input &&
+ is_in_clause &&
+ childPol[base_assertion]==base_pol ){
+ //if both in input and in clause, the proof is trivial. this is the case for unit clauses.
+ Trace("cnf-pf") << "; trivial" << std::endl;
+ os << "(contra _ ";
+ success = true;
+ prop::SatLiteral lit = (*clause)[itci->second];
+ if( base_pol ){
+ os << os_base.str() << " " << ProofManager::getLitName(lit, d_name);
+ }else{
+ os << ProofManager::getLitName(lit, d_name) << " " << os_base.str();
}
- Trace("cnf-pf") << "; polarity of base assertion = " << base_pol << std::endl;
- Trace("cnf-pf") << "; proof of base : " << os_base.str() << std::endl;
-
- bool success = false;
- if( is_input && is_in_clause && childPol[base_assertion]==base_pol ){
- //if both in input and in clause, the proof is trivial. this is the case for unit clauses.
- Trace("cnf-pf") << "; trivial" << std::endl;
- os << "(contra _ ";
- success = true;
- prop::SatLiteral lit = (*clause)[itci->second];
- if( base_pol ){
- os << os_base.str() << " " << ProofManager::getLitName(lit);
- }else{
- os << ProofManager::getLitName(lit) << " " << os_base.str();
+ os << ")";
+ } else if ((base_assertion.getKind()==kind::AND && !base_pol) ||
+ ((base_assertion.getKind()==kind::OR ||
+ base_assertion.getKind()==kind::IMPLIES) && base_pol)) {
+ Trace("cnf-pf") << "; and/or case 1" << std::endl;
+ success = true;
+ std::stringstream os_main;
+ std::stringstream os_paren;
+ //eliminate each one
+ for (int j = base_assertion.getNumChildren()-2; j >= 0; j--) {
+ Node child_base = base_assertion[j].getKind()==kind::NOT ?
+ base_assertion[j][0] : base_assertion[j];
+ bool child_pol = base_assertion[j].getKind()!=kind::NOT;
+
+ if( j==0 && base_assertion.getKind()==kind::IMPLIES ){
+ child_pol = !child_pol;
}
- os << ")";
- }else if( ( base_assertion.getKind()==kind::AND && !base_pol ) || ( ( base_assertion.getKind()==kind::OR || base_assertion.getKind()==kind::IMPLIES ) && base_pol ) ){
- Trace("cnf-pf") << "; and/or case 1" << std::endl;
- success = true;
- std::stringstream os_main;
- std::stringstream os_paren;
- //eliminate each one
- for( int j=base_assertion.getNumChildren()-2; j>=0; j-- ){
- Expr child_base = base_assertion[j].getKind()==kind::NOT ? base_assertion[j][0] : base_assertion[j];
- bool child_pol = base_assertion[j].getKind()!=kind::NOT;
- if( j==0 && base_assertion.getKind()==kind::IMPLIES ){
- child_pol = !child_pol;
+
+ Trace("cnf-pf-debug") << "; child " << j << " "
+ << child_base << " "
+ << child_pol << " "
+ << childPol[child_base] << std::endl;
+
+ std::map< Node, unsigned >::iterator itcic = childIndex.find( child_base );
+
+ if( itcic!=childIndex.end() ){
+ //Assert( child_pol==childPol[child_base] );
+ os_main << "(or_elim_1 _ _ ";
+ prop::SatLiteral lit = (*clause)[itcic->second];
+ // Should be if in the original formula it was negated
+ if( childPol[child_base] && base_pol ){
+ os_main << ProofManager::getLitName(lit, d_name) << " ";
+ }else{
+ os_main << "(not_not_intro _ " << ProofManager::getLitName(lit, d_name) << ") ";
}
- Trace("cnf-pf-debug") << "; child " << j << " " << child_base << " " << child_pol << " " << childPol[child_base] << std::endl;
- std::map< Expr, unsigned >::iterator itcic = childIndex.find( child_base );
- if( itcic!=childIndex.end() ){
- //Assert( child_pol==childPol[child_base] );
- os_main << "(or_elim_1 _ _ ";
- prop::SatLiteral lit = (*clause)[itcic->second];
- if( childPol[child_base] && base_pol ){
- os_main << ProofManager::getLitName(lit) << " ";
- }else{
- os_main << "(not_not_intro _ " << ProofManager::getLitName(lit) << ") ";
- }
- if( base_assertion.getKind()==kind::AND ){
- os_main << "(not_and_elim _ _ ";
- os_paren << ")";
- }
+ if( base_assertion.getKind()==kind::AND ){
+ os_main << "(not_and_elim _ _ ";
os_paren << ")";
- }else{
- success = false;
}
+ os_paren << ")";
+ }else{
+ success = false;
}
- if( success ){
- if( base_assertion.getKind()==kind::IMPLIES ){
- os_main << "(impl_elim _ _ ";
- }
- os_main << os_base.str();
- if( base_assertion.getKind()==kind::IMPLIES ){
- os_main << ")";
- }
- os_main << os_paren.str();
- int last_index = base_assertion.getNumChildren()-1;
- Expr child_base = base_assertion[last_index].getKind()==kind::NOT ? base_assertion[last_index][0] : base_assertion[last_index];
- //bool child_pol = base_assertion[last_index].getKind()!=kind::NOT;
- std::map< Expr, unsigned >::iterator itcic = childIndex.find( child_base );
- if( itcic!=childIndex.end() ){
- os << "(contra _ ";
- prop::SatLiteral lit = (*clause)[itcic->second];
- if( childPol[child_base] && base_pol ){
- os << os_main.str() << " " << ProofManager::getLitName(lit);
- }else{
- os << ProofManager::getLitName(lit) << " " << os_main.str();
- }
- os << ")";
- }else{
- success = false;
- }
+ }
+ if( success ){
+ if( base_assertion.getKind()==kind::IMPLIES ){
+ os_main << "(impl_elim _ _ ";
}
- }else if( ( base_assertion.getKind()==kind::AND && base_pol ) || ( ( base_assertion.getKind()==kind::OR || base_assertion.getKind()==kind::IMPLIES ) && !base_pol ) ){
- std::stringstream os_main;
- Expr iatom;
- if( is_in_clause ){
- Assert( assertion.getNumChildren()==2 );
- iatom = assertion[ base_index==0 ? 1 : 0];
- }else{
- Assert( assertion.getNumChildren()==1 );
- iatom = assertion[0];
+ os_main << os_base.str();
+ if( base_assertion.getKind()==kind::IMPLIES ){
+ os_main << ")";
}
- Trace("cnf-pf") << "; and/or case 2, iatom = " << iatom << std::endl;
- Expr e_base = iatom.getKind()==kind::NOT ? iatom[0] : iatom;
- bool e_pol = iatom.getKind()!=kind::NOT;
- std::map< Expr, unsigned >::iterator itcic = childIndex.find( e_base );
+ os_main << os_paren.str();
+ int last_index = base_assertion.getNumChildren()-1;
+ Node child_base = base_assertion[last_index].getKind()==kind::NOT ? base_assertion[last_index][0] : base_assertion[last_index];
+ //bool child_pol = base_assertion[last_index].getKind()!=kind::NOT;
+ std::map< Node, unsigned >::iterator itcic = childIndex.find( child_base );
if( itcic!=childIndex.end() ){
+ os << "(contra _ ";
prop::SatLiteral lit = (*clause)[itcic->second];
- //eliminate until we find iatom
- for( unsigned j=0; j<base_assertion.getNumChildren(); j++ ){
- Expr child_base = base_assertion[j].getKind()==kind::NOT ? base_assertion[j][0] : base_assertion[j];
- bool child_pol = base_assertion[j].getKind()!=kind::NOT;
- if( j==0 && base_assertion.getKind()==kind::IMPLIES ){
- child_pol = !child_pol;
+ if( childPol[child_base] && base_pol){
+ os << os_main.str() << " " << ProofManager::getLitName(lit, d_name);
+ }else{
+ os << ProofManager::getLitName(lit, d_name) << " " << os_main.str();
+ }
+ os << ")";
+ }else{
+ success = false;
+ }
+ }
+ }else if ((base_assertion.getKind()==kind::AND && base_pol) ||
+ ((base_assertion.getKind()==kind::OR ||
+ base_assertion.getKind()==kind::IMPLIES) && !base_pol)) {
+
+ std::stringstream os_main;
+
+ Node iatom;
+ if (is_in_clause) {
+ Assert( assertion.getNumChildren()==2 );
+ iatom = assertion[ base_index==0 ? 1 : 0];
+ } else {
+ Assert( assertion.getNumChildren()==1 );
+ iatom = assertion[0];
+ }
+
+ Trace("cnf-pf") << "; and/or case 2, iatom = " << iatom << std::endl;
+ Node e_base = iatom.getKind()==kind::NOT ? iatom[0] : iatom;
+ bool e_pol = iatom.getKind()!=kind::NOT;
+ std::map< Node, unsigned >::iterator itcic = childIndex.find( e_base );
+ if( itcic!=childIndex.end() ){
+ prop::SatLiteral lit = (*clause)[itcic->second];
+ //eliminate until we find iatom
+ for( unsigned j=0; j<base_assertion.getNumChildren(); j++ ){
+ Node child_base = base_assertion[j].getKind()==kind::NOT ? base_assertion[j][0] : base_assertion[j];
+ bool child_pol = base_assertion[j].getKind()!=kind::NOT;
+ if( j==0 && base_assertion.getKind()==kind::IMPLIES ){
+ child_pol = !child_pol;
+ }
+ if( e_base==child_base && (e_pol==child_pol)==(base_assertion.getKind()==kind::AND) ){
+ success = true;
+ bool elimNn =( ( base_assertion.getKind()==kind::OR || ( base_assertion.getKind()==kind::IMPLIES && j==1 ) ) && e_pol );
+ if( elimNn ){
+ os_main << "(not_not_elim _ ";
}
- if( e_base==child_base && (e_pol==child_pol)==(base_assertion.getKind()==kind::AND) ){
- success = true;
- bool elimNn =( ( base_assertion.getKind()==kind::OR || ( base_assertion.getKind()==kind::IMPLIES && j==1 ) ) && e_pol );
- if( elimNn ){
- os_main << "(not_not_elim _ ";
- }
- std::stringstream os_paren;
- if( j+1<base_assertion.getNumChildren() ){
- os_main << "(and_elim_1 _ _ ";
- if( base_assertion.getKind()==kind::OR || base_assertion.getKind()==kind::IMPLIES ){
- os_main << "(not_" << ( base_assertion.getKind()==kind::OR ? "or" : "impl" ) << "_elim _ _ ";
- os_paren << ")";
- }
+ std::stringstream os_paren;
+ if( j+1<base_assertion.getNumChildren() ){
+ os_main << "(and_elim_1 _ _ ";
+ if( base_assertion.getKind()==kind::OR || base_assertion.getKind()==kind::IMPLIES ){
+ os_main << "(not_" << ( base_assertion.getKind()==kind::OR ? "or" : "impl" ) << "_elim _ _ ";
os_paren << ")";
}
- for( unsigned k=0; k<j; k++ ){
- os_main << "(and_elim_2 _ _ ";
- if( base_assertion.getKind()==kind::OR || base_assertion.getKind()==kind::IMPLIES ){
- os_main << "(not_" << ( base_assertion.getKind()==kind::OR ? "or" : "impl" ) << "_elim _ _ ";
- os_paren << ")";
- }
+ os_paren << ")";
+ }
+ for( unsigned k=0; k<j; k++ ){
+ os_main << "(and_elim_2 _ _ ";
+ if( base_assertion.getKind()==kind::OR || base_assertion.getKind()==kind::IMPLIES ){
+ os_main << "(not_" << ( base_assertion.getKind()==kind::OR ? "or" : "impl" ) << "_elim _ _ ";
os_paren << ")";
}
- os_main << os_base.str() << os_paren.str();
- if( elimNn ){
- os_main << ")";
- }
- break;
+ os_paren << ")";
}
- }
- if( success ){
- os << "(contra _ ";
- if( !e_pol ){
- os << ProofManager::getLitName(lit) << " " << os_main.str();
- }else{
- os << os_main.str() << " " << ProofManager::getLitName(lit);
+ os_main << os_base.str() << os_paren.str();
+ if( elimNn ){
+ os_main << ")";
}
- os << ")";
- }
- }
- }else if( base_assertion.getKind()==kind::XOR || base_assertion.getKind()==kind::IFF ){
- //eliminate negation
- int num_nots_2 = 0;
- int num_nots_1 = 0;
- Kind k;
- if( !base_pol ){
- if( base_assertion.getKind()==kind::IFF ){
- num_nots_2 = 1;
- }
- k = kind::IFF;
- }else{
- k = base_assertion.getKind();
- }
- std::vector< unsigned > indices;
- std::vector< bool > pols;
- success = true;
- int elimNum = 0;
- for( unsigned i=0; i<2; i++ ){
- Expr child_base = base_assertion[i].getKind()==kind::NOT ? base_assertion[i][0] : base_assertion[i];
- bool child_pol = base_assertion[i].getKind()!=kind::NOT;
- std::map< Expr, unsigned >::iterator itcic = childIndex.find( child_base );
- if( itcic!=childIndex.end() ){
- indices.push_back( itcic->second );
- pols.push_back( childPol[child_base] );
- if( i==0 ){
- //figure out which way to elim
- elimNum = child_pol==childPol[child_base] ? 2 : 1;
- if( (elimNum==2)==(k==kind::IFF) ){
- num_nots_2++;
- }
- if( elimNum==1 ){
- num_nots_1++;
- }
- }
- }else{
- success = false;
break;
}
}
- Trace("cnf-pf") << std::endl << "; num nots = " << num_nots_2 << std::endl;
if( success ){
os << "(contra _ ";
- std::stringstream os_base_n;
- if( num_nots_2==2 ){
- os_base_n << "(not_not_elim _ ";
- }
- os_base_n << "(or_elim_1 _ _ ";
- prop::SatLiteral lit1 = (*clause)[indices[0]];
- if( !pols[0] || num_nots_1==1 ){
- os_base_n << "(not_not_intro _ " << ProofManager::getLitName(lit1) << ") ";
- }else{
- os_base_n << ProofManager::getLitName(lit1) << " ";
- }
- Assert( elimNum!=0 );
- os_base_n << "(" << ( k==kind::IFF ? "iff" : "xor" ) << "_elim_" << elimNum << " _ _ ";
- if( !base_pol ){
- os_base_n << "(not_" << ( base_assertion.getKind()==kind::IFF ? "iff" : "xor" ) << "_elim _ _ " << os_base.str() << ")";
- }else{
- os_base_n << os_base.str();
- }
- os_base_n << "))";
- if( num_nots_2==2 ){
- os_base_n << ")";
- num_nots_2 = 0;
- }
- prop::SatLiteral lit2 = (*clause)[indices[1]];
- if( pols[1]==(num_nots_2==0) ){
- os << os_base_n.str() << " ";
- if( num_nots_2==1 ){
- os << "(not_not_intro _ " << ProofManager::getLitName(lit2) << ")";
- }else{
- os << ProofManager::getLitName(lit2);
- }
+ if( !e_pol ){
+ os << ProofManager::getLitName(lit, d_name) << " " << os_main.str();
}else{
- os << ProofManager::getLitName(lit2) << " " << os_base_n.str();
+ os << os_main.str() << " " << ProofManager::getLitName(lit, d_name);
}
os << ")";
}
- }else if( base_assertion.getKind()==kind::ITE ){
- std::map< unsigned, unsigned > appears;
- std::map< unsigned, Expr > appears_expr;
- unsigned appears_count = 0;
- for( unsigned r=0; r<3; r++ ){
- Expr child_base = base_assertion[r].getKind()==kind::NOT ? base_assertion[r][0] : base_assertion[r];
- std::map< Expr, unsigned >::iterator itcic = childIndex.find( child_base );
- if( itcic!=childIndex.end() ){
- appears[r] = itcic->second;
- appears_expr[r] = child_base;
- appears_count++;
- }
+ }
+ }else if( base_assertion.getKind()==kind::XOR || base_assertion.getKind()==kind::IFF ){
+ //eliminate negation
+ int num_nots_2 = 0;
+ int num_nots_1 = 0;
+ Kind k;
+ if( !base_pol ){
+ if( base_assertion.getKind()==kind::IFF ){
+ num_nots_2 = 1;
}
- if( appears_count==2 ){
- success = true;
- int elimNum = 1;
- unsigned index1 = 0;
- unsigned index2 = 1;
- if( appears.find( 0 )==appears.end() ){
- elimNum = 3;
- index1 = 1;
- index2 = 2;
- }else if( appears.find( 1 )==appears.end() ){
- elimNum = 2;
- index1 = 0;
- index2 = 2;
- }
- std::stringstream os_main;
- os_main << "(or_elim_1 _ _ ";
- prop::SatLiteral lit1 = (*clause)[appears[index1]];
- if( !childPol[appears_expr[index1]] || elimNum==1 || ( elimNum==3 && !base_pol ) ){
- os_main << "(not_not_intro _ " << ProofManager::getLitName(lit1) << ") ";
- }else{
- os_main << ProofManager::getLitName(lit1) << " ";
- }
- os_main << "(" << ( base_pol ? "" : "not_" ) << "ite_elim_" << elimNum << " _ _ _ ";
- os_main << os_base.str() << "))";
- os << "(contra _ ";
- prop::SatLiteral lit2 = (*clause)[appears[index2]];
- if( !childPol[appears_expr[index2]] || !base_pol ){
- os << ProofManager::getLitName(lit2) << " " << os_main.str();
- }else{
- os << os_main.str() << " " << ProofManager::getLitName(lit2);
+ k = kind::IFF;
+ }else{
+ k = base_assertion.getKind();
+ }
+ std::vector< unsigned > indices;
+ std::vector< bool > pols;
+ success = true;
+ int elimNum = 0;
+ for( unsigned i=0; i<2; i++ ){
+ Node child_base = base_assertion[i].getKind()==kind::NOT ? base_assertion[i][0] : base_assertion[i];
+ bool child_pol = base_assertion[i].getKind()!=kind::NOT;
+ std::map< Node, unsigned >::iterator itcic = childIndex.find( child_base );
+ if( itcic!=childIndex.end() ){
+ indices.push_back( itcic->second );
+ pols.push_back( childPol[child_base] );
+ if( i==0 ){
+ //figure out which way to elim
+ elimNum = child_pol==childPol[child_base] ? 2 : 1;
+ if( (elimNum==2)==(k==kind::IFF) ){
+ num_nots_2++;
+ }
+ if( elimNum==1 ){
+ num_nots_1++;
+ }
}
- os << ")";
+ }else{
+ success = false;
+ break;
+ }
+ }
+ Trace("cnf-pf") << std::endl << "; num nots = " << num_nots_2 << std::endl;
+ if( success ){
+ os << "(contra _ ";
+ std::stringstream os_base_n;
+ if( num_nots_2==2 ){
+ os_base_n << "(not_not_elim _ ";
+ }
+ os_base_n << "(or_elim_1 _ _ ";
+ prop::SatLiteral lit1 = (*clause)[indices[0]];
+ if( !pols[0] || num_nots_1==1 ){
+ os_base_n << "(not_not_intro _ " << ProofManager::getLitName(lit1, d_name) << ") ";
+ }else{
+ os_base_n << ProofManager::getLitName(lit1, d_name) << " ";
}
- }else if( base_assertion.isConst() ){
- bool pol = base_assertion==NodeManager::currentNM()->mkConst( true ).toExpr();
- if( pol!=base_pol ){
- success = true;
- if( pol ){
- os << "(contra _ truth " << os_base.str() << ")";
+ Assert( elimNum!=0 );
+ os_base_n << "(" << ( k==kind::IFF ? "iff" : "xor" ) << "_elim_" << elimNum << " _ _ ";
+ if( !base_pol ){
+ os_base_n << "(not_" << ( base_assertion.getKind()==kind::IFF ? "iff" : "xor" ) << "_elim _ _ " << os_base.str() << ")";
+ }else{
+ os_base_n << os_base.str();
+ }
+ os_base_n << "))";
+ if( num_nots_2==2 ){
+ os_base_n << ")";
+ num_nots_2 = 0;
+ }
+ prop::SatLiteral lit2 = (*clause)[indices[1]];
+ if( pols[1]==(num_nots_2==0) ){
+ os << os_base_n.str() << " ";
+ if( num_nots_2==1 ){
+ os << "(not_not_intro _ " << ProofManager::getLitName(lit2, d_name) << ")";
}else{
- os << os_base.str();
+ os << ProofManager::getLitName(lit2, d_name);
}
+ }else{
+ os << ProofManager::getLitName(lit2, d_name) << " " << os_base_n.str();
}
+ os << ")";
}
-
- if( !success ){
- Trace("cnf-pf") << std::endl;
- Trace("cnf-pf") << ";!!!!!!!!! CnfProof : Can't process " << assertion << ", base = " << base_assertion << ", id = " << id << ", proof rule = " << pr << std::endl;
- Trace("cnf-pf") << ";!!!!!!!!! Clause is : ";
- for (unsigned i = 0; i < clause->size(); ++i) {
- Trace("cnf-pf") << (*clause)[i] << " ";
+ }else if( base_assertion.getKind()==kind::ITE ){
+ std::map< unsigned, unsigned > appears;
+ std::map< unsigned, Node > appears_expr;
+ unsigned appears_count = 0;
+ for( unsigned r=0; r<3; r++ ){
+ Node child_base = base_assertion[r].getKind()==kind::NOT ? base_assertion[r][0] : base_assertion[r];
+ std::map< Node, unsigned >::iterator itcic = childIndex.find( child_base );
+ if( itcic!=childIndex.end() ){
+ appears[r] = itcic->second;
+ appears_expr[r] = child_base;
+ appears_count++;
}
- Trace("cnf-pf") << std::endl;
- os << "trust-bad";
- }
-
- os << ")" << clause_paren.str()
- << " (\\ " << ProofManager::getInputClauseName(id) << "\n";
- paren << "))";
- }
-}
-
-void LFSCCnfProof::printTheoryLemmas(std::ostream& os, std::ostream& paren) {
- os << " ;; Theory Lemmas\n";
- ProofManager::ordered_clause_iterator it = ProofManager::currentPM()->begin_lemmas();
- ProofManager::ordered_clause_iterator end = ProofManager::currentPM()->end_lemmas();
-
- for(size_t n = 0; it != end; ++it, ++n) {
- if(n % 100 == 0) {
- Chat() << "proving theory conflicts...(" << n << "/" << ProofManager::currentPM()->num_lemmas() << ")" << std::endl;
}
-
- ClauseId id = it->first;
- const prop::SatClause* clause = it->second;
- NodeBuilder<> c(kind::AND);
- for(unsigned i = 0; i < clause->size(); ++i) {
- prop::SatLiteral lit = (*clause)[i];
- prop::SatVariable var = lit.getSatVariable();
- if(lit.isNegated()) {
- c << Node::fromExpr(getAtom(var));
- } else {
- c << Node::fromExpr(getAtom(var)).notNode();
+ if( appears_count==2 ){
+ success = true;
+ int elimNum = 1;
+ unsigned index1 = 0;
+ unsigned index2 = 1;
+ if( appears.find( 0 )==appears.end() ){
+ elimNum = 3;
+ index1 = 1;
+ index2 = 2;
+ }else if( appears.find( 1 )==appears.end() ){
+ elimNum = 2;
+ index1 = 0;
+ index2 = 2;
}
- }
- Node cl = c;
- if(ProofManager::getSatProof()->d_lemmaClauses.find(id) != ProofManager::getSatProof()->d_lemmaClauses.end()) {
- uint64_t proof_id = ProofManager::getSatProof()->d_lemmaClauses[id];
- TNode orig = d_cnfStream->getAssertion(proof_id & 0xffffffff);
- if(((proof_id >> 32) & 0xffffffff) == RULE_ARRAYS_EXT) {
- Debug("cores") << "; extensional lemma!" << std::endl;
- Assert(cl.getKind() == kind::AND && cl.getNumChildren() == 2 && cl[0].getKind() == kind::EQUAL && cl[0][0].getKind() == kind::SELECT);
- TNode myk = cl[0][0][1];
- Debug("cores") << "; so my skolemized k is " << myk << std::endl;
- os << "(ext _ _ " << orig[0][0] << " " << orig[0][1] << " (\\ " << myk << " (\\ " << ProofManager::getLemmaName(id) << "\n";
- paren << ")))";
+ std::stringstream os_main;
+ os_main << "(or_elim_1 _ _ ";
+ prop::SatLiteral lit1 = (*clause)[appears[index1]];
+ if( !childPol[appears_expr[index1]] || elimNum==1 || ( elimNum==3 && !base_pol ) ){
+ os_main << "(not_not_intro _ " << ProofManager::getLitName(lit1, d_name) << ") ";
+ }else{
+ os_main << ProofManager::getLitName(lit1, d_name) << " ";
+ }
+ os_main << "(" << ( base_pol ? "" : "not_" ) << "ite_elim_" << elimNum << " _ _ _ ";
+ os_main << os_base.str() << "))";
+ os << "(contra _ ";
+ prop::SatLiteral lit2 = (*clause)[appears[index2]];
+ if( !childPol[appears_expr[index2]] || !base_pol ){
+ os << ProofManager::getLitName(lit2, d_name) << " " << os_main.str();
+ }else{
+ os << os_main.str() << " " << ProofManager::getLitName(lit2, d_name);
}
+ os << ")";
}
- printAtomMapping(clause, os, paren);
- os << "(satlem _ _ ";
- std::ostringstream clause_paren;
- printClause(*clause, os, clause_paren);
-
- Debug("cores") << "\n;id is " << id << std::endl;
- if(ProofManager::getSatProof()->d_lemmaClauses.find(id) != ProofManager::getSatProof()->d_lemmaClauses.end()) {
- uint64_t proof_id = ProofManager::getSatProof()->d_lemmaClauses[id];
- Debug("cores") << ";getting id " << int32_t(proof_id & 0xffffffff) << std::endl;
- Assert(int32_t(proof_id & 0xffffffff) != -1);
- TNode orig = d_cnfStream->getAssertion(proof_id & 0xffffffff);
- Debug("cores") << "; ID is " << id << " and that's a lemma with " << ((proof_id >> 32) & 0xffffffff) << " / " << (proof_id & 0xffffffff) << std::endl;
- Debug("cores") << "; that means the lemma was " << orig << std::endl;
- if(((proof_id >> 32) & 0xffffffff) == RULE_ARRAYS_EXT) {
- Debug("cores") << "; extensional" << std::endl;
- os << "(clausify_false trust)\n";
- } else if(proof_id == 0) {
- // theory propagation caused conflict
- //ProofManager::currentPM()->printProof(os, cl);
- os << "(clausify_false trust)\n";
- } else if(((proof_id >> 32) & 0xffffffff) == RULE_CONFLICT) {
- os << "\n;; need to generate a (conflict) proof of " << cl << "\n";
- //ProofManager::currentPM()->printProof(os, cl);
- os << "(clausify_false trust)\n";
- } else {
- os << "\n;; need to generate a (lemma) proof of " << cl;
- os << "\n;; DON'T KNOW HOW !!\n";
- os << "(clausify_false trust)\n";
+ }else if( base_assertion.isConst() ){
+ bool pol = base_assertion==NodeManager::currentNM()->mkConst( true );
+ if( pol!=base_pol ){
+ success = true;
+ if( pol ){
+ os << "(contra _ truth " << os_base.str() << ")";
+ }else{
+ os << os_base.str();
}
- } else {
- os << "\n;; need to generate a (conflict) proof of " << cl << "\n";
- ProofManager::currentPM()->printProof(os, cl);
}
- os << clause_paren.str()
- << " (\\ " << ProofManager::getLemmaClauseName(id) << "\n";
- paren << "))";
}
+
+ if( !success ){
+ Trace("cnf-pf") << std::endl;
+ Trace("cnf-pf") << ";!!!!!!!!! CnfProof : Can't process " << assertion << ", base = " << base_assertion << ", id = " << id << std::endl;
+ Trace("cnf-pf") << ";!!!!!!!!! Clause is : ";
+ for (unsigned i = 0; i < clause->size(); ++i) {
+ Trace("cnf-pf") << (*clause)[i] << " ";
+ }
+ Trace("cnf-pf") << std::endl;
+ os << "trust-bad";
+ }
+
+ os << ")" << clause_paren.str()
+ << " (\\ " << ProofManager::getInputClauseName(id, d_name) << "\n";
+ paren << "))";
}
-void LFSCCnfProof::printClause(const prop::SatClause& clause, std::ostream& os, std::ostream& paren) {
+void LFSCCnfProof::printClause(const prop::SatClause& clause,
+ std::ostream& os,
+ std::ostream& paren) {
for (unsigned i = 0; i < clause.size(); ++i) {
prop::SatLiteral lit = clause[i];
prop::SatVariable var = lit.getSatVariable();
if (lit.isNegated()) {
- os << "(ast _ _ _ " << ProofManager::getAtomName(var) << " (\\ " << ProofManager::getLitName(lit) << " ";
+ os << "(ast _ _ _ " << ProofManager::getAtomName(var, d_name) <<" (\\ " << ProofManager::getLitName(lit, d_name) << " ";
paren << "))";
} else {
- os << "(asf _ _ _ " << ProofManager::getAtomName(var) << " (\\ " << ProofManager::getLitName(lit) << " ";
+ os << "(asf _ _ _ " << ProofManager::getAtomName(var, d_name) <<" (\\ " << ProofManager::getLitName(lit, d_name) << " ";
paren << "))";
}
}
}
+// print a proof of the top-level formula e, based on the input assertions
+bool LFSCCnfProof::printProofTopLevel(Node e, std::ostream& out) {
+ if (!isAssertion(e)) {
+ // check if deduced by CNF
+ // dependence on top level fact i.e. a depends on (a and b)
+ NodeToNode::const_iterator itd = d_cnfDeps.find(e);
+ if (itd != d_cnfDeps.end()) {
+ TNode parent = itd->second;
+ //check if parent is an input assertion
+ std::stringstream out_parent;
+ if (printProofTopLevel(parent, out_parent)) {
+ if(parent.getKind()==kind::AND ||
+ (parent.getKind()==kind::NOT && (parent[0].getKind()==kind::IMPLIES ||
+ parent[0].getKind()==kind::OR))) {
+ Node parent_base = parent.getKind()==kind::NOT ? parent[0] : parent;
+ Node e_base = e.getKind()==kind::NOT ? e[0] : e;
+ bool e_pol = e.getKind()!=kind::NOT;
+ for( unsigned i=0; i<parent_base.getNumChildren(); i++ ){
+ Node child_base = parent_base[i].getKind()==kind::NOT ? parent_base[i][0] : parent_base[i];
+ bool child_pol = parent_base[i].getKind()!=kind::NOT;
+ if( parent_base.getKind()==kind::IMPLIES && i==0 ){
+ child_pol = !child_pol;
+ }
+ if (e_base==child_base &&
+ (e_pol==child_pol)==(parent_base.getKind()==kind::AND)) {
+ bool elimNn = ((parent_base.getKind()==kind::OR ||
+ (parent_base.getKind()==kind::IMPLIES && i==1)) && e_pol);
+ if (elimNn) {
+ out << "(not_not_elim _ ";
+ }
+ std::stringstream out_paren;
+ if (i+1 < parent_base.getNumChildren()) {
+ out << "(and_elim_1 _ _ ";
+ if( parent_base.getKind()==kind::OR ||
+ parent_base.getKind()==kind::IMPLIES ){
+ out << "(not_" << ( parent_base.getKind()==kind::OR ? "or" : "impl" )
+ << "_elim _ _ ";
+ out_paren << ")";
+ }
+ out_paren << ")";
+ }
+ for( unsigned j=0; j<i; j++ ){
+ out << "(and_elim_2 _ _ ";
+ if( parent_base.getKind()==kind::OR || parent_base.getKind()==kind::IMPLIES ){
+ out << "(not_" << ( parent_base.getKind()==kind::OR ? "or" : "impl" ) << "_elim _ _ ";
+ out_paren << ")";
+ }
+ out_paren << ")";
+ }
+ out << out_parent.str();
+ out << out_paren.str();
+ if( elimNn ){
+ out << ")";
+ }
+ return true;
+ }
+ }
+ } else {
+ Trace("cnf-pf-debug") << "; isInputAssertion : parent of " << e
+ << " is not correct type (" << parent << ")" << std::endl;
+ }
+ } else {
+ Trace("cnf-pf-debug") << "; isInputAssertion : parent of " << e
+ << " is not input" << std::endl;
+ }
+ } else {
+ Trace("cnf-pf-debug") << "; isInputAssertion : " << e
+ << " has no parent" << std::endl;
+ }
+ return false;
+ } else {
+ out << ProofManager::getPreprocessedAssertionName(e);
+ return true;
+ }
+}
+
+
+
} /* CVC4 namespace */
diff --git a/src/proof/cnf_proof.h b/src/proof/cnf_proof.h
index d3e59ef93..675bd9b9d 100644
--- a/src/proof/cnf_proof.h
+++ b/src/proof/cnf_proof.h
@@ -21,11 +21,14 @@
#ifndef __CVC4__CNF_PROOF_H
#define __CVC4__CNF_PROOF_H
-#include <ext/hash_map>
+#include <ext/hash_map>
#include <ext/hash_set>
#include <iosfwd>
+#include "context/cdhashmap.h"
#include "proof/sat_proof.h"
+#include "proof/sat_proof.h"
+#include "util/proof.h"
#include "util/proof.h"
namespace CVC4 {
@@ -35,38 +38,131 @@ namespace prop {
class CnfProof;
+typedef __gnu_cxx::hash_map<prop::SatVariable, Expr> SatVarToExpr;
+typedef __gnu_cxx::hash_map<Node, Node, NodeHashFunction> NodeToNode;
+typedef __gnu_cxx::hash_set<ClauseId> ClauseIdSet;
+
+typedef context::CDHashMap<ClauseId, Node> ClauseIdToNode;
+typedef context::CDHashMap<Node, ProofRule, NodeHashFunction> NodeToProofRule;
+
class CnfProof {
protected:
CVC4::prop::CnfStream* d_cnfStream;
- VarSet d_atomsDeclared;
+
+ /** Map from ClauseId to the assertion that lead to adding this clause **/
+ ClauseIdToNode d_clauseToAssertion;
+
+ /** Map from assertion to reason for adding assertion **/
+ NodeToProofRule d_assertionToProofRule;
+
+ /** Top of stack is assertion currently being converted to CNF **/
+ std::vector<Node> d_currentAssertionStack;
+
+ /** Top of stack is top-level fact currently being converted to CNF **/
+ std::vector<Node> d_currentDefinitionStack;
+
+
+ /** Map from ClauseId to the top-level fact that lead to adding this clause **/
+ ClauseIdToNode d_clauseToDefinition;
+
+ /** Top-level facts that follow from assertions during convertAndAssert **/
+ NodeSet d_definitions;
+
+ /** Map from top-level fact to facts/assertion that it follows from **/
+ NodeToNode d_cnfDeps;
+
+ ClauseIdSet d_explanations;
+
+ bool isDefinition(Node node);
+
+ Node getDefinitionForClause(ClauseId clause);
+
+ std::string d_name;
public:
- CnfProof(CVC4::prop::CnfStream* cnfStream);
+ CnfProof(CVC4::prop::CnfStream* cnfStream,
+ context::Context* ctx,
+ const std::string& name);
+
+
+ Node getAtom(prop::SatVariable var);
+ prop::SatLiteral getLiteral(TNode node);
+ void collectAtoms(const prop::SatClause* clause,
+ NodeSet& atoms);
+ void collectAtomsForClauses(const IdToSatClause& clauses,
+ NodeSet& atoms);
+ void collectAssertionsForClauses(const IdToSatClause& clauses,
+ NodeSet& assertions);
+
+ /** Methods for logging what the CnfStream does **/
+ // map the clause back to the current assertion where it came from
+ // if it is an explanation, it does not have a CNF proof since it is
+ // already in CNF
+ void registerConvertedClause(ClauseId clause, bool explanation=false);
+
+ /** Clause is one of the clauses defining the node expression*/
+ void setClauseDefinition(ClauseId clause, Node node);
+
+ /** Clause is one of the clauses defining top-level assertion node*/
+ void setClauseAssertion(ClauseId clause, Node node);
+
+ void registerAssertion(Node assertion, ProofRule reason);
+ void setCnfDependence(Node from, Node to);
+
+ void pushCurrentAssertion(Node assertion); // the current assertion being converted
+ void popCurrentAssertion();
+ Node getCurrentAssertion();
+
+ void pushCurrentDefinition(Node assertion); // the current Tseitin definition being converted
+ void popCurrentDefinition();
+ Node getCurrentDefinition();
+
+
+ // accessors for the leaf assertions that are being converted to CNF
+ bool isAssertion(Node node);
+ ProofRule getProofRule(Node assertion);
+ ProofRule getProofRule(ClauseId clause);
+ Node getAssertionForClause(ClauseId clause);
- Expr getAtom(prop::SatVariable var);
- Expr getAssertion(uint64_t id);
- prop::SatLiteral getLiteral(TNode atom);
+
+ /** Virtual methods for printing things **/
+ virtual void printAtomMapping(const NodeSet& atoms,
+ std::ostream& os,
+ std::ostream& paren) = 0;
- virtual void printClauses(std::ostream& os, std::ostream& paren) = 0;
+ virtual void printClause(const prop::SatClause& clause,
+ std::ostream& os,
+ std::ostream& paren) = 0;
+ virtual void printCnfProofForClause(ClauseId id,
+ const prop::SatClause* clause,
+ std::ostream& os,
+ std::ostream& paren) = 0;
virtual ~CnfProof();
};/* class CnfProof */
class LFSCCnfProof : public CnfProof {
- void printPreprocess(std::ostream& os, std::ostream& paren);
- void printInputClauses(std::ostream& os, std::ostream& paren);
- void printTheoryLemmas(std::ostream& os, std::ostream& paren);
- void printClause(const prop::SatClause& clause, std::ostream& os, std::ostream& paren);
- virtual void printAtomMapping(const prop::SatClause* clause, std::ostream& os, std::ostream& paren);
-
- Expr clauseToExpr( const prop::SatClause& clause,
- std::map< Expr, unsigned >& childIndex,
- std::map< Expr, bool >& childPol );
-
+ Node clauseToNode( const prop::SatClause& clause,
+ std::map<Node, unsigned>& childIndex,
+ std::map<Node, bool>& childPol );
+ bool printProofTopLevel(Node e, std::ostream& out);
public:
- LFSCCnfProof(CVC4::prop::CnfStream* cnfStream)
- : CnfProof(cnfStream)
+ LFSCCnfProof(CVC4::prop::CnfStream* cnfStream,
+ context::Context* ctx,
+ const std::string& name)
+ : CnfProof(cnfStream, ctx, name)
{}
+ ~LFSCCnfProof() {}
- virtual void printClauses(std::ostream& os, std::ostream& paren);
+ void printAtomMapping(const NodeSet& atoms,
+ std::ostream& os,
+ std::ostream& paren);
+
+ void printClause(const prop::SatClause& clause,
+ std::ostream& os,
+ std::ostream& paren);
+ void printCnfProofForClause(ClauseId id,
+ const prop::SatClause* clause,
+ std::ostream& os,
+ std::ostream& paren);
};/* class LFSCCnfProof */
} /* CVC4 namespace */
diff --git a/src/proof/proof.h b/src/proof/proof.h
index ae4c940a0..d69cd6198 100644
--- a/src/proof/proof.h
+++ b/src/proof/proof.h
@@ -9,9 +9,9 @@
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
- ** \brief Proof manager
+ ** \brief Proof macros
**
- ** Proof manager
+ ** Proof macros
**/
#include "cvc4_private.h"
@@ -46,14 +46,25 @@
*/
#ifdef CVC4_PROOF
-# define PROOF(x) if(options::proof() || options::unsatCores()) { x; }
-# define NULLPROOF(x) (options::proof() || options::unsatCores()) ? x : NULL
-# define PROOF_ON() (options::proof() || options::unsatCores())
+# define PROOF(x) if(CVC4::options::proof() || CVC4::options::unsatCores()) { x; }
+# define NULLPROOF(x) (CVC4::options::proof() || CVC4::options::unsatCores()) ? x : NULL
+# define PROOF_ON() (CVC4::options::proof() || CVC4::options::unsatCores())
+# define THEORY_PROOF(x) if(CVC4::options::proof()) { x; }
+# define THEORY_NULLPROOF(x) CVC4::options::proof() ? x : NULL
+# define THEORY_PROOF_ON() CVC4::options::proof()
#else /* CVC4_PROOF */
# define PROOF(x)
# define NULLPROOF(x) NULL
# define PROOF_ON() false
+# define THEORY_PROOF(x)
+# define THEORY_NULLPROOF(x) NULL
+# define THEORY_PROOF_ON() false
#endif /* CVC4_PROOF */
+#ifdef CVC4_PROOF_STATS /* CVC4_PROOF_STATS */
+# define PSTATS(x) { x; }
+#else
+# define PSTATS(x)
+#endif /* CVC4_PROOF_STATS */
#endif /* __CVC4__PROOF__PROOF_H */
diff --git a/src/proof/proof_manager.cpp b/src/proof/proof_manager.cpp
index 88d380c4f..0ae020090 100644
--- a/src/proof/proof_manager.cpp
+++ b/src/proof/proof_manager.cpp
@@ -15,13 +15,20 @@
** \todo document this file
**/
-#include "proof/proof_manager.h"
-
-#include "base/cvc4_assert.h"
#include "context/context.h"
+
+#include "proof/proof_manager.h"
#include "proof/cnf_proof.h"
-#include "proof/sat_proof.h"
#include "proof/theory_proof.h"
+#include "proof/bitvector_proof.h"
+#include "proof/proof_utils.h"
+#include "proof/sat_proof_implementation.h"
+#include "options/bv_options.h"
+
+#include "util/proof.h"
+#include "util/hash.h"
+
+#include "base/cvc4_assert.h"
#include "smt/smt_engine.h"
#include "smt/smt_engine_scope.h"
#include "smt_util/node_visitor.h"
@@ -31,8 +38,7 @@
#include "theory/uf/equality_engine.h"
#include "theory/uf/theory_uf.h"
#include "theory/valuation.h"
-#include "util/hash.h"
-#include "util/proof.h"
+
namespace CVC4 {
@@ -46,17 +52,13 @@ ProofManager::ProofManager(ProofFormat format):
d_satProof(NULL),
d_cnfProof(NULL),
d_theoryProof(NULL),
- d_inputClauses(),
- d_theoryLemmas(),
- d_theoryPropagations(),
d_inputFormulas(),
d_inputCoreFormulas(),
d_outputCoreFormulas(),
d_nextId(0),
d_fullProof(NULL),
d_format(format),
- d_deps(),
- d_assertion_counter(1)
+ d_deps()
{
}
@@ -65,21 +67,6 @@ ProofManager::~ProofManager() {
delete d_cnfProof;
delete d_theoryProof;
delete d_fullProof;
-
- for(IdToClause::iterator it = d_inputClauses.begin();
- it != d_inputClauses.end();
- ++it) {
- delete it->second;
- }
-
- for(OrderedIdToClause::iterator it = d_theoryLemmas.begin();
- it != d_theoryLemmas.end();
- ++it) {
- delete it->second;
- }
-
- // FIXME: memory leak because there are deleted theory lemmas that
- // were not used in the SatProof
}
ProofManager* ProofManager::currentPM() {
@@ -93,13 +80,13 @@ Proof* ProofManager::getProof(SmtEngine* smt) {
Assert (currentPM()->d_format == LFSC);
currentPM()->d_fullProof = new LFSCProof(smt,
- (LFSCSatProof*)getSatProof(),
+ (LFSCCoreSatProof*)getSatProof(),
(LFSCCnfProof*)getCnfProof(),
- (LFSCTheoryProof*)getTheoryProof());
+ (LFSCTheoryProofEngine*)getTheoryProofEngine());
return currentPM()->d_fullProof;
}
-SatProof* ProofManager::getSatProof() {
+CoreSatProof* ProofManager::getSatProof() {
Assert (currentPM()->d_satProof);
return currentPM()->d_satProof;
}
@@ -109,48 +96,135 @@ CnfProof* ProofManager::getCnfProof() {
return currentPM()->d_cnfProof;
}
-TheoryProof* ProofManager::getTheoryProof() {
- //Assert (currentPM()->d_theoryProof);
+TheoryProofEngine* ProofManager::getTheoryProofEngine() {
+ Assert (options::proof());
+ Assert (currentPM()->d_theoryProof != NULL);
return currentPM()->d_theoryProof;
}
+UFProof* ProofManager::getUfProof() {
+ Assert (options::proof());
+ TheoryProof* pf = getTheoryProofEngine()->getTheoryProof(theory::THEORY_UF);
+ return (UFProof*)pf;
+}
+BitVectorProof* ProofManager::getBitVectorProof() {
+ Assert (options::proof());
+ TheoryProof* pf = getTheoryProofEngine()->getTheoryProof(theory::THEORY_BV);
+ return (BitVectorProof*)pf;
+}
+
+ArrayProof* ProofManager::getArrayProof() {
+ Assert (options::proof());
+ TheoryProof* pf = getTheoryProofEngine()->getTheoryProof(theory::THEORY_ARRAY);
+ return (ArrayProof*)pf;
+}
+
void ProofManager::initSatProof(Minisat::Solver* solver) {
Assert (currentPM()->d_satProof == NULL);
Assert(currentPM()->d_format == LFSC);
- currentPM()->d_satProof = new LFSCSatProof(solver);
+ currentPM()->d_satProof = new LFSCCoreSatProof(solver, "");
}
-void ProofManager::initCnfProof(prop::CnfStream* cnfStream) {
- Assert (currentPM()->d_cnfProof == NULL);
- Assert (currentPM()->d_format == LFSC);
- currentPM()->d_cnfProof = new LFSCCnfProof(cnfStream);
+void ProofManager::initCnfProof(prop::CnfStream* cnfStream,
+ context::Context* ctx) {
+ ProofManager* pm = currentPM();
+ Assert (pm->d_cnfProof == NULL);
+ Assert (pm->d_format == LFSC);
+ CnfProof* cnf = new LFSCCnfProof(cnfStream, ctx, "");
+ pm->d_cnfProof = cnf;
+ Assert(pm-> d_satProof != NULL);
+ pm->d_satProof->setCnfProof(cnf);
+
+ // true and false have to be setup in a special way
+ Node true_node = NodeManager::currentNM()->mkConst<bool>(true);
+ Node false_node = NodeManager::currentNM()->mkConst<bool>(false).notNode();
+
+ pm->d_cnfProof->pushCurrentAssertion(true_node);
+ pm->d_cnfProof->pushCurrentDefinition(true_node);
+ pm->d_cnfProof->registerConvertedClause(pm->d_satProof->getTrueUnit());
+ pm->d_cnfProof->popCurrentAssertion();
+ pm->d_cnfProof->popCurrentDefinition();
+
+ pm->d_cnfProof->pushCurrentAssertion(false_node);
+ pm->d_cnfProof->pushCurrentDefinition(false_node);
+ pm->d_cnfProof->registerConvertedClause(pm->d_satProof->getFalseUnit());
+ pm->d_cnfProof->popCurrentAssertion();
+ pm->d_cnfProof->popCurrentDefinition();
+
}
-void ProofManager::initTheoryProof() {
+void ProofManager::initTheoryProofEngine(SmtGlobals* globals) {
Assert (currentPM()->d_theoryProof == NULL);
Assert (currentPM()->d_format == LFSC);
- currentPM()->d_theoryProof = new LFSCTheoryProof();
+ currentPM()->d_theoryProof = new LFSCTheoryProofEngine(globals);
+}
+
+std::string ProofManager::getInputClauseName(ClauseId id,
+ const std::string& prefix) {
+ return append(prefix+".pb", id);
+}
+std::string ProofManager::getLemmaClauseName(ClauseId id,
+ const std::string& prefix) {
+ return append(prefix+".lemc", id);
}
+ std::string ProofManager::getLemmaName(ClauseId id,
+ const std::string& prefix) {
+ return append(prefix+"lem", id);
+}
+
+std::string ProofManager::getLearntClauseName(ClauseId id,
+ const std::string& prefix) {
+ return append(prefix+".cl", id);
+}
+std::string ProofManager::getVarName(prop::SatVariable var,
+ const std::string& prefix) {
+ return append(prefix+".v", var);
+}
+std::string ProofManager::getAtomName(prop::SatVariable var,
+ const std::string& prefix) {
+ return append(prefix+".a", var);
+}
+std::string ProofManager::getLitName(prop::SatLiteral lit,
+ const std::string& prefix) {
+ return append(prefix+".l", lit.toInt());
+}
+
-std::string ProofManager::getInputClauseName(ClauseId id) { return append("pb", id); }
-std::string ProofManager::getLemmaName(ClauseId id) { return append("lem", id); }
-std::string ProofManager::getLemmaClauseName(ClauseId id) { return append("lemc", id); }
-std::string ProofManager::getLearntClauseName(ClauseId id) { return append("cl", id); }
-std::string ProofManager::getVarName(prop::SatVariable var) { return append("var", var); }
-std::string ProofManager::getAtomName(prop::SatVariable var) { return append("atom", var); }
-std::string ProofManager::getLitName(prop::SatLiteral lit) { return append("lit", lit.toInt()); }
+std::string ProofManager::getPreprocessedAssertionName(Node node,
+ const std::string& prefix) {
+ node = node.getKind() == kind::BITVECTOR_EAGER_ATOM ? node[0] : node;
+ return append(prefix+".PA", node.getId());
+}
+std::string ProofManager::getAssertionName(Node node,
+ const std::string& prefix) {
+ return append(prefix+".A", node.getId());
+}
-std::string ProofManager::getAtomName(TNode atom) {
+std::string ProofManager::getAtomName(TNode atom,
+ const std::string& prefix) {
prop::SatLiteral lit = currentPM()->d_cnfProof->getLiteral(atom);
Assert(!lit.isNegated());
- return getAtomName(lit.getSatVariable());
+ return getAtomName(lit.getSatVariable(), prefix);
}
-std::string ProofManager::getLitName(TNode lit) {
- return getLitName(currentPM()->d_cnfProof->getLiteral(lit));
+std::string ProofManager::getLitName(TNode lit,
+ const std::string& prefix) {
+ return getLitName(currentPM()->d_cnfProof->getLiteral(lit), prefix);
+}
+
+std::string ProofManager::sanitize(TNode var) {
+ Assert (var.isVar());
+ std::string name = var.toString();
+ std::replace(name.begin(), name.end(), ' ', '_');
+ return name;
}
+
void ProofManager::traceDeps(TNode n) {
Debug("cores") << "trace deps " << n << std::endl;
+ if ((n.isConst() && n == NodeManager::currentNM()->mkConst<bool>(true)) ||
+ (n.getKind() == kind::NOT && n[0] == NodeManager::currentNM()->mkConst<bool>(false))) {
+ return;
+ }
if(d_inputCoreFormulas.find(n.toExpr()) != d_inputCoreFormulas.end()) {
// originating formula was in core set
Debug("cores") << " -- IN INPUT CORE LIST!" << std::endl;
@@ -171,45 +245,38 @@ void ProofManager::traceDeps(TNode n) {
}
}
-void ProofManager::addClause(ClauseId id, const prop::SatClause* clause, ClauseKind kind) {
- /*for (unsigned i = 0; i < clause->size(); ++i) {
- prop::SatLiteral lit = clause->operator[](i);
- d_propVars.insert(lit.getSatVariable());
- }*/
- if (kind == INPUT) {
- Debug("cores") << "; Add to inputClauses " << id << std::endl;
- d_inputClauses.insert(std::make_pair(id, clause));
- Assert(d_satProof->d_inputClauses.find(id) != d_satProof->d_inputClauses.end());
- Debug("cores") << "; core id is " << d_satProof->d_inputClauses[id] << std::endl;
- if(d_satProof->d_inputClauses[id] == uint64_t(-1)) {
- Debug("cores") << "; + constant unit (true or false)" << std::endl;
- } else if(options::unsatCores()) {
- Expr e = d_cnfProof->getAssertion(d_satProof->d_inputClauses[id] & 0xffffffff);
- Debug("cores") << "; core input assertion from CnfStream is " << e << std::endl;
- Debug("cores") << "; with proof rule " << ((d_satProof->d_inputClauses[id] & 0xffffffff00000000llu) >> 32) << std::endl;
- // Invalid proof rules are currently used for parts of CVC4 that don't
- // support proofs (these are e.g. unproven theory lemmas) or don't need
- // proofs (e.g. split lemmas). We can ignore these safely when
- // constructing unsat cores.
- if(((d_satProof->d_inputClauses[id] & 0xffffffff00000000llu) >> 32) != RULE_INVALID) {
- // trace dependences back to actual assertions
- traceDeps(Node::fromExpr(e));
- }
+void ProofManager::traceUnsatCore() {
+ Assert (options::unsatCores());
+ d_satProof->constructProof();
+ IdToSatClause used_lemmas;
+ IdToSatClause used_inputs;
+ d_satProof->collectClausesUsed(used_inputs,
+ used_lemmas);
+ IdToSatClause::const_iterator it = used_inputs.begin();
+ for(; it != used_inputs.end(); ++it) {
+ Node node = d_cnfProof->getAssertionForClause(it->first);
+ ProofRule rule = d_cnfProof->getProofRule(node);
+
+ Debug("cores") << "core input assertion " << node << std::endl;
+ Debug("cores") << "with proof rule " << rule << std::endl;
+ if (rule == RULE_TSEITIN ||
+ rule == RULE_GIVEN) {
+ // trace dependences back to actual assertions
+ // (this adds them to the unsat core)
+ traceDeps(node);
}
- } else {
- Assert(kind == THEORY_LEMMA);
- d_theoryLemmas.insert(std::make_pair(id, clause));
}
}
-void ProofManager::addAssertion(Expr formula, bool inUnsatCore) {
- Debug("cores") << "assert: " << formula << std::endl;
+void ProofManager::addAssertion(Expr formula) {
+ Debug("proof:pm") << "assert: " << formula << std::endl;
d_inputFormulas.insert(formula);
+}
+
+void ProofManager::addCoreAssertion(Expr formula) {
+ Debug("cores") << "assert: " << formula << std::endl;
d_deps[Node::fromExpr(formula)]; // empty vector of deps
- if(inUnsatCore || options::dumpUnsatCores() || options::checkUnsatCores()) {
- Debug("cores") << "adding to input core forms: " << formula << std::endl;
- d_inputCoreFormulas.insert(formula);
- }
+ d_inputCoreFormulas.insert(formula);
}
void ProofManager::addDependence(TNode n, TNode dep) {
@@ -232,151 +299,210 @@ void ProofManager::setLogic(const LogicInfo& logic) {
d_logic = logic;
}
-void ProofManager::printProof(std::ostream& os, TNode n) {
- // no proofs here yet
-}
-void ProofManager::setCnfDep( Expr child, Expr parent ) {
- Debug("cores") << "CNF dep : " << child << " : " << parent << std::endl;
- d_cnf_dep[child] = parent;
-}
-Expr ProofManager::getFormulaForClauseId( ClauseId id ) {
- std::map< ClauseId, Expr >::const_iterator it = d_clause_id_to_assertion.find( id );
- if( it!=d_clause_id_to_assertion.end() ){
- return it->second;
- }else{
- Node ret;
- return ret.toExpr();
- }
-}
+LFSCProof::LFSCProof(SmtEngine* smtEngine,
+ LFSCCoreSatProof* sat,
+ LFSCCnfProof* cnf,
+ LFSCTheoryProofEngine* theory)
+ : d_satProof(sat)
+ , d_cnfProof(cnf)
+ , d_theoryProof(theory)
+ , d_smtEngine(smtEngine)
+{}
-ProofRule ProofManager::getProofRuleForClauseId( ClauseId id ) {
- std::map< ClauseId, ProofRule >::const_iterator it = d_clause_id_to_rule.find( id );
- if( it!=d_clause_id_to_rule.end() ){
- return it->second;
- }else{
- return RULE_INVALID;
- }
-}
+void LFSCProof::toStream(std::ostream& out) {
+ d_satProof->constructProof();
-void ProofManager::setAssertion( Expr e ) {
- d_assertion_to_id[e] = d_assertion_counter;
- d_assertion_counter++;
-}
-
-// if this function returns true, writes to out a proof of e based on input assertions
-bool ProofManager::isInputAssertion( Expr e, std::ostream& out ) {
- std::map< Expr, unsigned >::iterator itp = d_assertion_to_id.find( e );
- if( itp==d_assertion_to_id.end() ){
- //check if deduced by CNF
- std::map< Expr, Expr >::iterator itd = d_cnf_dep.find( e );
- if( itd!=d_cnf_dep.end() ){
- Expr parent = itd->second;
- //check if parent is an input assertion
- std::stringstream out_parent;
- if( isInputAssertion( parent, out_parent ) ){
- if( parent.getKind()==kind::AND || ( parent.getKind()==kind::NOT && ( parent[0].getKind()==kind::IMPLIES || parent[0].getKind()==kind::OR ) ) ){
- Expr parent_base = parent.getKind()==kind::NOT ? parent[0] : parent;
- Expr e_base = e.getKind()==kind::NOT ? e[0] : e;
- bool e_pol = e.getKind()!=kind::NOT;
- for( unsigned i=0; i<parent_base.getNumChildren(); i++ ){
- Expr child_base = parent_base[i].getKind()==kind::NOT ? parent_base[i][0] : parent_base[i];
- bool child_pol = parent_base[i].getKind()!=kind::NOT;
- if( parent_base.getKind()==kind::IMPLIES && i==0 ){
- child_pol = !child_pol;
- }
- if( e_base==child_base && (e_pol==child_pol)==(parent_base.getKind()==kind::AND) ){
- bool elimNn = ( ( parent_base.getKind()==kind::OR || ( parent_base.getKind()==kind::IMPLIES && i==1 ) ) && e_pol );
- if( elimNn ){
- out << "(not_not_elim _ ";
- }
- std::stringstream out_paren;
- if( i+1<parent_base.getNumChildren() ){
- out << "(and_elim_1 _ _ ";
- if( parent_base.getKind()==kind::OR || parent_base.getKind()==kind::IMPLIES ){
- out << "(not_" << ( parent_base.getKind()==kind::OR ? "or" : "impl" ) << "_elim _ _ ";
- out_paren << ")";
- }
- out_paren << ")";
- }
- for( unsigned j=0; j<i; j++ ){
- out << "(and_elim_2 _ _ ";
- if( parent_base.getKind()==kind::OR || parent_base.getKind()==kind::IMPLIES ){
- out << "(not_" << ( parent_base.getKind()==kind::OR ? "or" : "impl" ) << "_elim _ _ ";
- out_paren << ")";
- }
- out_paren << ")";
- }
- out << out_parent.str();
- out << out_paren.str();
- if( elimNn ){
- out << ")";
- }
- return true;
- }
- }
- }else{
- Trace("cnf-pf-debug") << "; isInputAssertion : parent of " << e << " is not correct type (" << parent << ")" << std::endl;
- }
- }else{
- Trace("cnf-pf-debug") << "; isInputAssertion : parent of " << e << " is not input" << std::endl;
- }
- }else{
- Trace("cnf-pf-debug") << "; isInputAssertion : " << e << " has no parent" << std::endl;
- }
- return false;
- }else{
- out << "A" << itp->second;
- return true;
+ // collecting leaf clauses in resolution proof
+ IdToSatClause used_lemmas;
+ IdToSatClause used_inputs;
+ d_satProof->collectClausesUsed(used_inputs,
+ used_lemmas);
+
+ // collecting assertions that lead to the clauses being asserted
+ NodeSet used_assertions;
+ d_cnfProof->collectAssertionsForClauses(used_inputs, used_assertions);
+
+ NodeSet atoms;
+ // collects the atoms in the clauses
+ d_cnfProof->collectAtomsForClauses(used_inputs, atoms);
+ d_cnfProof->collectAtomsForClauses(used_lemmas, atoms);
+
+ // collects the atoms in the assertions
+ for (NodeSet::const_iterator it = used_assertions.begin();
+ it != used_assertions.end(); ++it) {
+ utils::collectAtoms(*it, atoms);
}
-}
-void ProofManager::setRegisteringFormula( Node n, ProofRule proof_id ) {
- Trace("cnf-pf-debug") << "; set registering formula " << n << " proof rule = " << proof_id << std::endl;
- d_registering_assertion = n;
- d_registering_rule = proof_id;
-}
+ if (Debug.isOn("proof:pm")) {
+ // std::cout << NodeManager::currentNM();
+ Debug("proof:pm") << "LFSCProof::Used assertions: "<< std::endl;
+ for(NodeSet::const_iterator it = used_assertions.begin(); it != used_assertions.end(); ++it) {
+ Debug("proof:pm") << " " << *it << std::endl;
+ }
-void ProofManager::setRegisteredClauseId( ClauseId id ) {
- Trace("cnf-pf-debug") << "; set register clause id " << id << " " << d_registering_assertion << std::endl;
- if( !d_registering_assertion.isNull() ){
- d_clause_id_to_assertion[id] = d_registering_assertion.toExpr();
- d_clause_id_to_rule[id] = d_registering_rule;
- setRegisteringFormula( Node::null(), RULE_INVALID );
+ Debug("proof:pm") << "LFSCProof::Used atoms: "<< std::endl;
+ for(NodeSet::const_iterator it = atoms.begin(); it != atoms.end(); ++it) {
+ Debug("proof:pm") << " " << *it << std::endl;
+ }
}
-}
-LFSCProof::LFSCProof(SmtEngine* smtEngine, LFSCSatProof* sat, LFSCCnfProof* cnf, LFSCTheoryProof* theory)
- : d_satProof(sat)
- , d_cnfProof(cnf)
- , d_theoryProof(theory)
- , d_smtEngine(smtEngine)
-{
- d_satProof->constructProof();
-}
-void LFSCProof::toStream(std::ostream& out) {
+
smt::SmtScope scope(d_smtEngine);
std::ostringstream paren;
out << "(check\n";
out << " ;; Declarations\n";
- if (d_theoryProof == NULL) {
- d_theoryProof = new LFSCTheoryProof();
+
+ // declare the theory atoms
+ NodeSet::const_iterator it = atoms.begin();
+ NodeSet::const_iterator end = atoms.end();
+ for(; it != end; ++it) {
+ d_theoryProof->registerTerm((*it).toExpr());
}
- /*for(LFSCCnfProof::iterator i = d_cnfProof->begin_atom_mapping();
- i != d_cnfProof->end_atom_mapping();
- ++i) {
- d_theoryProof->addDeclaration(*i);
- }*/
+ // print out all the original assertions
d_theoryProof->printAssertions(out, paren);
- out << " ;; Proof of empty clause follows\n";
+
+
out << "(: (holds cln)\n";
- d_cnfProof->printClauses(out, paren);
- d_satProof->printResolutions(out, paren);
- paren <<")))\n;;";
- out << paren.str();
- out << "\n";
+
+ // print trust that input assertions are their preprocessed form
+ printPreprocessedAssertions(used_assertions, out, paren);
+
+ // print mapping between theory atoms and internal SAT variables
+ d_cnfProof->printAtomMapping(atoms, out, paren);
+
+ IdToSatClause::const_iterator cl_it = used_inputs.begin();
+ // print CNF conversion proof for each clause
+ for (; cl_it != used_inputs.end(); ++cl_it) {
+ d_cnfProof->printCnfProofForClause(cl_it->first, cl_it->second, out, paren);
+ }
+
+ // FIXME: for now assume all theory lemmas are in CNF form so
+ // distinguish between them and inputs
+ // print theory lemmas for resolution proof
+ d_theoryProof->printTheoryLemmas(used_lemmas, out, paren);
+
+
+ if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER && ProofManager::getBitVectorProof()) {
+ // print actual resolution proof
+ // d_satProof->printResolutions(out, paren);
+ ProofManager::getBitVectorProof()->getSatProof()->printResolutionEmptyClause(out, paren);
+ paren <<")))\n;;";
+ out << paren.str();
+ out << "\n";
+ } else {
+ // print actual resolution proof
+ d_satProof->printResolutions(out, paren);
+ d_satProof->printResolutionEmptyClause(out, paren);
+ paren <<")))\n;;";
+ out << paren.str();
+ out << "\n";
+ }
+}
+
+void LFSCProof::printPreprocessedAssertions(const NodeSet& assertions,
+ std::ostream& os,
+ std::ostream& paren) {
+ os << " ;; Preprocessing \n";
+ NodeSet::const_iterator it = assertions.begin();
+ NodeSet::const_iterator end = assertions.end();
+
+ for (; it != end; ++it) {
+ os << "(th_let_pf _ ";
+
+ //TODO
+ os << "(trust_f ";
+ ProofManager::currentPM()->getTheoryProofEngine()->printLetTerm((*it).toExpr(), os);
+ os << ") ";
+
+ os << "(\\ "<< ProofManager::getPreprocessedAssertionName(*it, "") << "\n";
+ paren << "))";
+
+ }
}
+
+
+//---from Morgan---
+bool ProofManager::hasOp(TNode n) const {
+ return d_bops.find(n) != d_bops.end();
+}
+
+Node ProofManager::lookupOp(TNode n) const {
+ std::map<Node, Node>::const_iterator i = d_bops.find(n);
+ Assert(i != d_bops.end());
+ return (*i).second;
+}
+
+Node ProofManager::mkOp(TNode n) {
+ if(n.getKind() != kind::BUILTIN) {
+ return n;
+ }
+ Node& op = d_ops[n];
+ if(op.isNull()) {
+ Debug("mgd") << "making an op for " << n << "\n";
+ std::stringstream ss;
+ ss << n;
+ std::string s = ss.str();
+ Debug("mgd") << " : " << s << std::endl;
+ std::vector<TypeNode> v;
+ v.push_back(NodeManager::currentNM()->integerType());
+ if(n.getConst<Kind>() == kind::SELECT) {
+ v.push_back(NodeManager::currentNM()->integerType());
+ v.push_back(NodeManager::currentNM()->integerType());
+ } else if(n.getConst<Kind>() == kind::STORE) {
+ v.push_back(NodeManager::currentNM()->integerType());
+ v.push_back(NodeManager::currentNM()->integerType());
+ v.push_back(NodeManager::currentNM()->integerType());
+ }
+ TypeNode type = NodeManager::currentNM()->mkFunctionType(v);
+ op = NodeManager::currentNM()->mkSkolem(s, type, " ignore", NodeManager::SKOLEM_NO_NOTIFY);
+ d_bops[op] = n;
+ }
+ return op;
+}
+//---end from Morgan---
+
+std::ostream& operator<<(std::ostream& out, CVC4::ProofRule k) {
+ switch(k) {
+ case RULE_GIVEN:
+ out << "RULE_GIVEN";
+ break;
+ case RULE_DERIVED:
+ out << "RULE_DERIVED";
+ break;
+ case RULE_RECONSTRUCT:
+ out << "RULE_RECONSTRUCT";
+ break;
+ case RULE_TRUST:
+ out << "RULE_TRUST";
+ break;
+ case RULE_INVALID:
+ out << "RULE_INVALID";
+ break;
+ case RULE_CONFLICT:
+ out << "RULE_CONFLICT";
+ break;
+ case RULE_TSEITIN:
+ out << "RULE_TSEITIN";
+ break;
+ case RULE_SPLIT:
+ out << "RULE_SPLIT";
+ break;
+ case RULE_ARRAYS_EXT:
+ out << "RULE_ARRAYS";
+ break;
+ case RULE_ARRAYS_ROW:
+ out << "RULE_ARRAYS";
+ break;
+ default:
+ out << "ProofRule Unknown! [" << unsigned(k) << "]";
+ }
+
+ return out;
+}
+
+
} /* CVC4 namespace */
diff --git a/src/proof/proof_manager.h b/src/proof/proof_manager.h
index 6864eca3d..5d8bf3d58 100644
--- a/src/proof/proof_manager.h
+++ b/src/proof/proof_manager.h
@@ -31,27 +31,52 @@
namespace CVC4 {
+class SmtGlobals;
+
// forward declarations
namespace Minisat {
class Solver;
}/* Minisat namespace */
+namespace BVMinisat {
+ class Solver;
+}/* BVMinisat namespace */
+
namespace prop {
class CnfStream;
}/* CVC4::prop namespace */
class SmtEngine;
-typedef int ClauseId;
+typedef unsigned ClauseId;
+const ClauseId ClauseIdEmpty(-1);
+const ClauseId ClauseIdUndef(-2);
+const ClauseId ClauseIdError(-3);
class Proof;
-class SatProof;
+template <class Solver> class TSatProof;
+typedef TSatProof< CVC4::Minisat::Solver> CoreSatProof;
+
class CnfProof;
+class RewriterProof;
+class TheoryProofEngine;
class TheoryProof;
+class UFProof;
+class ArrayProof;
+class BitVectorProof;
+
+template <class Solver> class LFSCSatProof;
+typedef LFSCSatProof< CVC4::Minisat::Solver> LFSCCoreSatProof;
-class LFSCSatProof;
class LFSCCnfProof;
-class LFSCTheoryProof;
+class LFSCTheoryProofEngine;
+class LFSCUFProof;
+class LFSCBitVectorProof;
+class LFSCRewriterProof;
+
+template <class Solver> class ProofProxy;
+typedef ProofProxy< CVC4::Minisat::Solver> CoreProofProxy;
+typedef ProofProxy< CVC4::BVMinisat::Solver> BVProofProxy;
namespace prop {
typedef uint64_t SatVariable;
@@ -67,18 +92,13 @@ enum ProofFormat {
std::string append(const std::string& str, uint64_t num);
-typedef __gnu_cxx::hash_map < ClauseId, const prop::SatClause* > IdToClause;
-typedef std::map < ClauseId, const prop::SatClause* > OrderedIdToClause;
-typedef __gnu_cxx::hash_set<prop::SatVariable > VarSet;
+typedef __gnu_cxx::hash_map < ClauseId, prop::SatClause* > IdToSatClause;
typedef __gnu_cxx::hash_set<Expr, ExprHashFunction > ExprSet;
+typedef __gnu_cxx::hash_set<Node, NodeHashFunction > NodeSet;
+typedef __gnu_cxx::hash_map<Node, std::vector<Node>, NodeHashFunction > NodeToNodes;
+typedef std::hash_set<ClauseId> IdHashSet;
-typedef int ClauseId;
-
-enum ClauseKind {
- INPUT,
- THEORY_LEMMA,
- LEARNT
-};/* enum ClauseKind */
+typedef unsigned ClauseId;
enum ProofRule {
RULE_GIVEN, /* input assertion */
@@ -88,44 +108,31 @@ enum ProofRule {
RULE_INVALID, /* assert-fail if this is ever needed in proof; use e.g. for split lemmas */
RULE_CONFLICT, /* re-construct as a conflict */
RULE_TSEITIN, /* Tseitin CNF transformation */
-
+ RULE_SPLIT, /* A splitting lemma of the form a v ~ a*/
+
RULE_ARRAYS_EXT, /* arrays, extensional */
RULE_ARRAYS_ROW, /* arrays, read-over-write */
};/* enum ProofRules */
class ProofManager {
-
- SatProof* d_satProof;
- CnfProof* d_cnfProof;
- TheoryProof* d_theoryProof;
+ CoreSatProof* d_satProof;
+ CnfProof* d_cnfProof;
+ TheoryProofEngine* d_theoryProof;
// information that will need to be shared across proofs
- IdToClause d_inputClauses;
- OrderedIdToClause d_theoryLemmas;
- IdToClause d_theoryPropagations;
ExprSet d_inputFormulas;
ExprSet d_inputCoreFormulas;
ExprSet d_outputCoreFormulas;
- //VarSet d_propVars;
int d_nextId;
Proof* d_fullProof;
ProofFormat d_format; // used for now only in debug builds
- __gnu_cxx::hash_map< Node, std::vector<Node>, NodeHashFunction > d_deps;
-
+ NodeToNodes d_deps;
// trace dependences back to unsat core
void traceDeps(TNode n);
- Node d_registering_assertion;
- ProofRule d_registering_rule;
- std::map< ClauseId, Expr > d_clause_id_to_assertion;
- std::map< ClauseId, ProofRule > d_clause_id_to_rule;
- std::map< Expr, Expr > d_cnf_dep;
- //LFSC number for assertions
- unsigned d_assertion_counter;
- std::map< Expr, unsigned > d_assertion_to_id;
protected:
LogicInfo d_logic;
@@ -137,93 +144,100 @@ public:
// initialization
static void initSatProof(Minisat::Solver* solver);
- static void initCnfProof(CVC4::prop::CnfStream* cnfStream);
- static void initTheoryProof();
-
- static Proof* getProof(SmtEngine* smt);
- static SatProof* getSatProof();
- static CnfProof* getCnfProof();
- static TheoryProof* getTheoryProof();
-
+ static void initCnfProof(CVC4::prop::CnfStream* cnfStream,
+ context::Context* ctx);
+ static void initTheoryProofEngine(SmtGlobals* globals);
+
+ // getting various proofs
+ static Proof* getProof(SmtEngine* smt);
+ static CoreSatProof* getSatProof();
+ static CnfProof* getCnfProof();
+ static TheoryProofEngine* getTheoryProofEngine();
+ static TheoryProof* getTheoryProof( theory::TheoryId id );
+ static UFProof* getUfProof();
+ static BitVectorProof* getBitVectorProof();
+ static ArrayProof* getArrayProof();
+
// iterators over data shared by proofs
- typedef IdToClause::const_iterator clause_iterator;
- typedef OrderedIdToClause::const_iterator ordered_clause_iterator;
typedef ExprSet::const_iterator assertions_iterator;
- typedef VarSet::const_iterator var_iterator;
-
-
- __gnu_cxx::hash_map< Node, std::vector<Node>, NodeHashFunction >::const_iterator begin_deps() const { return d_deps.begin(); }
- __gnu_cxx::hash_map< Node, std::vector<Node>, NodeHashFunction >::const_iterator end_deps() const { return d_deps.end(); }
-
- clause_iterator begin_input_clauses() const { return d_inputClauses.begin(); }
- clause_iterator end_input_clauses() const { return d_inputClauses.end(); }
- size_t num_input_clauses() const { return d_inputClauses.size(); }
-
- ordered_clause_iterator begin_lemmas() const { return d_theoryLemmas.begin(); }
- ordered_clause_iterator end_lemmas() const { return d_theoryLemmas.end(); }
- size_t num_lemmas() const { return d_theoryLemmas.size(); }
+ // iterate over the assertions (these are arbitrary boolean formulas)
assertions_iterator begin_assertions() const { return d_inputFormulas.begin(); }
assertions_iterator end_assertions() const { return d_inputFormulas.end(); }
size_t num_assertions() const { return d_inputFormulas.size(); }
+
+//---from Morgan---
+ Node mkOp(TNode n);
+ Node lookupOp(TNode n) const;
+ bool hasOp(TNode n) const;
+
+ std::map<Node, Node> d_ops;
+ std::map<Node, Node> d_bops;
+//---end from Morgan---
+
+
+ // variable prefixes
+ static std::string getInputClauseName(ClauseId id, const std::string& prefix = "");
+ static std::string getLemmaClauseName(ClauseId id, const std::string& prefix = "");
+ static std::string getLemmaName(ClauseId id, const std::string& prefix = "");
+ static std::string getLearntClauseName(ClauseId id, const std::string& prefix = "");
+ static std::string getPreprocessedAssertionName(Node node, const std::string& prefix = "");
+ static std::string getAssertionName(Node node, const std::string& prefix = "");
+
+ static std::string getVarName(prop::SatVariable var, const std::string& prefix = "");
+ static std::string getAtomName(prop::SatVariable var, const std::string& prefix = "");
+ static std::string getAtomName(TNode atom, const std::string& prefix = "");
+ static std::string getLitName(prop::SatLiteral lit, const std::string& prefix = "");
+ static std::string getLitName(TNode lit, const std::string& prefix = "");
+
+ // for SMT variable names that have spaces and other things
+ static std::string sanitize(TNode var);
+
- void printProof(std::ostream& os, TNode n);
-
- void addAssertion(Expr formula, bool inUnsatCore);
- void addClause(ClauseId id, const prop::SatClause* clause, ClauseKind kind);
- // note that n depends on dep (for cores)
+ /** Add proof assertion - unlinke addCoreAssertion this is post definition expansion **/
+ void addAssertion(Expr formula);
+
+ /** Public unsat core methods **/
+ void addCoreAssertion(Expr formula);
+
void addDependence(TNode n, TNode dep);
void addUnsatCore(Expr formula);
+ void traceUnsatCore();
assertions_iterator begin_unsat_core() const { return d_outputCoreFormulas.begin(); }
assertions_iterator end_unsat_core() const { return d_outputCoreFormulas.end(); }
size_t size_unsat_core() const { return d_outputCoreFormulas.size(); }
int nextId() { return d_nextId++; }
- // variable prefixes
- static std::string getInputClauseName(ClauseId id);
- static std::string getLemmaName(ClauseId id);
- static std::string getLemmaClauseName(ClauseId id);
- static std::string getLearntClauseName(ClauseId id);
-
- static std::string getVarName(prop::SatVariable var);
- static std::string getAtomName(prop::SatVariable var);
- static std::string getAtomName(TNode atom);
- static std::string getLitName(prop::SatLiteral lit);
- static std::string getLitName(TNode lit);
-
void setLogic(const LogicInfo& logic);
const std::string getLogic() const { return d_logic.getLogicString(); }
+ LogicInfo & getLogicInfo() { return d_logic; }
-
- void setCnfDep( Expr child, Expr parent );
- Expr getFormulaForClauseId( ClauseId id );
- ProofRule getProofRuleForClauseId( ClauseId id );
- unsigned getAssertionCounter() { return d_assertion_counter; }
- void setAssertion( Expr e );
- bool isInputAssertion( Expr e, std::ostream& out );
-
-public: // AJR : FIXME this is hacky
- //currently, to map between ClauseId and Expr, requires:
- // (1) CnfStream::assertClause(...) to call setRegisteringFormula,
- // (2) SatProof::registerClause(...)/registerUnitClause(...) to call setRegisteredClauseId.
- //this is under the assumption that the first call at (2) is invoked for the clause corresponding to the Expr at (1).
- void setRegisteringFormula( Node n, ProofRule proof_id );
- void setRegisteredClauseId( ClauseId id );
};/* class ProofManager */
class LFSCProof : public Proof {
- LFSCSatProof* d_satProof;
+ LFSCCoreSatProof* d_satProof;
LFSCCnfProof* d_cnfProof;
- LFSCTheoryProof* d_theoryProof;
+ LFSCTheoryProofEngine* d_theoryProof;
SmtEngine* d_smtEngine;
+
+ // FIXME: hack until we get preprocessing
+ void printPreprocessedAssertions(const NodeSet& assertions,
+ std::ostream& os,
+ std::ostream& paren);
public:
- LFSCProof(SmtEngine* smtEngine, LFSCSatProof* sat, LFSCCnfProof* cnf, LFSCTheoryProof* theory);
+ LFSCProof(SmtEngine* smtEngine,
+ LFSCCoreSatProof* sat,
+ LFSCCnfProof* cnf,
+ LFSCTheoryProofEngine* theory);
virtual void toStream(std::ostream& out);
virtual ~LFSCProof() {}
};/* class LFSCProof */
+std::ostream& operator<<(std::ostream& out, CVC4::ProofRule k);
}/* CVC4 namespace */
+
+
#endif /* __CVC4__PROOF_MANAGER_H */
diff --git a/src/proof/proof_utils.cpp b/src/proof/proof_utils.cpp
new file mode 100644
index 000000000..47b8a235e
--- /dev/null
+++ b/src/proof/proof_utils.cpp
@@ -0,0 +1,127 @@
+/********************* */
+/*! \file proof_utils.cpp
+** \verbatim
+** Original author: Liana Hadarean
+** Major contributors: none
+** Minor contributors (to current version): none
+** This file is part of the CVC4 project.
+** Copyright (c) 2009-2014 New York University and The University of Iowa
+** See the file COPYING in the top-level source directory for licensing
+** information.\endverbatim
+**
+** \brief [[ Add one-line brief description here ]]
+**
+** [[ Add lengthier description here ]]
+** \todo document this file
+**/
+
+#include "proof/proof_utils.h"
+#include "theory/theory.h"
+
+namespace CVC4 {
+namespace utils {
+
+void collectAtoms(TNode node, CVC4::NodeSet& seen) {
+ if (seen.find(node) != seen.end())
+ return;
+ if (theory::Theory::theoryOf(node) != theory::THEORY_BOOL || node.isVar()) {
+ seen.insert(node);
+ return;
+ }
+
+ for (unsigned i = 0; i < node.getNumChildren(); ++i) {
+ collectAtoms(node[i], seen);
+ }
+}
+
+std::string toLFSCKind(Kind kind) {
+ switch(kind) {
+ // core kinds
+ case kind::OR : return "or";
+ case kind::AND: return "and";
+ case kind::XOR: return "xor";
+ case kind::EQUAL: return "=";
+ case kind::IFF: return "iff";
+ case kind::IMPLIES: return "impl";
+ case kind::NOT: return "not";
+
+ // bit-vector kinds
+ case kind::BITVECTOR_AND :
+ return "bvand";
+ case kind::BITVECTOR_OR :
+ return "bvor";
+ case kind::BITVECTOR_XOR :
+ return "bvxor";
+ case kind::BITVECTOR_NAND :
+ return "bvnand";
+ case kind::BITVECTOR_NOR :
+ return "bvnor";
+ case kind::BITVECTOR_XNOR :
+ return "bvxnor";
+ case kind::BITVECTOR_COMP :
+ return "bvcomp";
+ case kind::BITVECTOR_MULT :
+ return "bvmul";
+ case kind::BITVECTOR_PLUS :
+ return "bvadd";
+ case kind::BITVECTOR_SUB :
+ return "bvsub";
+ case kind::BITVECTOR_UDIV :
+ case kind::BITVECTOR_UDIV_TOTAL :
+ return "bvudiv";
+ case kind::BITVECTOR_UREM :
+ case kind::BITVECTOR_UREM_TOTAL :
+ return "bvurem";
+ case kind::BITVECTOR_SDIV :
+ return "bvsdiv";
+ case kind::BITVECTOR_SREM :
+ return "bvsrem";
+ case kind::BITVECTOR_SMOD :
+ return "bvsmod";
+ case kind::BITVECTOR_SHL :
+ return "bvshl";
+ case kind::BITVECTOR_LSHR :
+ return "bvlshr";
+ case kind::BITVECTOR_ASHR :
+ return "bvashr";
+ case kind::BITVECTOR_CONCAT :
+ return "concat";
+ case kind::BITVECTOR_NEG :
+ return "bvneg";
+ case kind::BITVECTOR_NOT :
+ return "bvnot";
+ case kind::BITVECTOR_ROTATE_LEFT :
+ return "rotate_left";
+ case kind::BITVECTOR_ROTATE_RIGHT :
+ return "rotate_right";
+ case kind::BITVECTOR_ULT :
+ return "bvult";
+ case kind::BITVECTOR_ULE :
+ return "bvule";
+ case kind::BITVECTOR_UGT :
+ return "bvugt";
+ case kind::BITVECTOR_UGE :
+ return "bvuge";
+ case kind::BITVECTOR_SLT :
+ return "bvslt";
+ case kind::BITVECTOR_SLE :
+ return "bvsle";
+ case kind::BITVECTOR_SGT :
+ return "bvsgt";
+ case kind::BITVECTOR_SGE :
+ return "bvsge";
+ case kind::BITVECTOR_EXTRACT :
+ return "extract";
+ case kind::BITVECTOR_REPEAT :
+ return "repeat";
+ case kind::BITVECTOR_ZERO_EXTEND :
+ return "zero_extend";
+ case kind::BITVECTOR_SIGN_EXTEND :
+ return "sign_extend";
+ default:
+ Unreachable();
+ }
+}
+
+} /* namespace CVC4::utils */
+} /* namespace CVC4 */
diff --git a/src/proof/proof_utils.h b/src/proof/proof_utils.h
new file mode 100644
index 000000000..c27fbe5c2
--- /dev/null
+++ b/src/proof/proof_utils.h
@@ -0,0 +1,178 @@
+/********************* */
+/*! \file proof_utils.h
+** \verbatim
+** Original author: Liana Hadarean
+** Major contributors: none
+** Minor contributors (to current version): none
+** This file is part of the CVC4 project.
+** Copyright (c) 2009-2014 New York University and The University of Iowa
+** See the file COPYING in the top-level source directory for licensing
+** information.\endverbatim
+**
+** \brief [[ Add one-line brief description here ]]
+**
+** [[ Add lengthier description here ]]
+** \todo document this file
+**/
+
+#include "cvc4_private.h"
+
+#pragma once
+
+#include <set>
+#include <vector>
+#include <sstream>
+#include "expr/node_manager.h"
+
+namespace CVC4 {
+
+typedef __gnu_cxx::hash_set<Expr, ExprHashFunction> ExprSet;
+typedef __gnu_cxx::hash_set<Node, NodeHashFunction> NodeSet;
+
+namespace utils {
+
+std::string toLFSCKind(Kind kind);
+
+inline unsigned getExtractHigh(Expr node) {
+ return node.getOperator().getConst<BitVectorExtract>().high;
+}
+
+inline unsigned getExtractLow(Expr node) {
+ return node.getOperator().getConst<BitVectorExtract>().low;
+}
+
+inline unsigned getSize(Type type) {
+ BitVectorType bv(type);
+ return bv.getSize();
+}
+
+
+inline unsigned getSize(Expr node) {
+ Assert (node.getType().isBitVector());
+ return getSize(node.getType());
+}
+
+inline Expr mkTrue() {
+ return NodeManager::currentNM()->toExprManager()->mkConst<bool>(true);
+}
+
+inline Expr mkFalse() {
+ return NodeManager::currentNM()->toExprManager()->mkConst<bool>(false);
+}
+inline BitVector mkBitVectorOnes(unsigned size) {
+ Assert(size > 0);
+ return BitVector(1, Integer(1)).signExtend(size - 1);
+}
+
+inline Expr mkExpr(Kind k , Expr expr) {
+ return NodeManager::currentNM()->toExprManager()->mkExpr(k, expr);
+}
+inline Expr mkExpr(Kind k , Expr e1, Expr e2) {
+ return NodeManager::currentNM()->toExprManager()->mkExpr(k, e1, e2);
+}
+inline Expr mkExpr(Kind k , std::vector<Expr>& children) {
+ return NodeManager::currentNM()->toExprManager()->mkExpr(k, children);
+}
+
+
+inline Expr mkOnes(unsigned size) {
+ BitVector val = mkBitVectorOnes(size);
+ return NodeManager::currentNM()->toExprManager()->mkConst<BitVector>(val);
+}
+
+inline Expr mkConst(unsigned size, unsigned int value) {
+ BitVector val(size, value);
+ return NodeManager::currentNM()->toExprManager()->mkConst<BitVector>(val);
+}
+
+inline Expr mkConst(const BitVector& value) {
+ return NodeManager::currentNM()->toExprManager()->mkConst<BitVector>(value);
+}
+
+inline Expr mkOr(const std::vector<Expr>& nodes) {
+ std::set<Expr> all;
+ all.insert(nodes.begin(), nodes.end());
+ Assert(all.size() != 0 );
+
+ if (all.size() == 1) {
+ // All the same, or just one
+ return nodes[0];
+ }
+
+
+ NodeBuilder<> disjunction(kind::OR);
+ std::set<Expr>::const_iterator it = all.begin();
+ std::set<Expr>::const_iterator it_end = all.end();
+ while (it != it_end) {
+ disjunction << Node::fromExpr(*it);
+ ++ it;
+ }
+
+ Node res = disjunction;
+ return res.toExpr();
+}/* mkOr() */
+
+
+inline Expr mkAnd(const std::vector<Expr>& conjunctions) {
+ std::set<Expr> all;
+ all.insert(conjunctions.begin(), conjunctions.end());
+
+ if (all.size() == 0) {
+ return mkTrue();
+ }
+
+ if (all.size() == 1) {
+ // All the same, or just one
+ return conjunctions[0];
+ }
+
+
+ NodeBuilder<> conjunction(kind::AND);
+ std::set<Expr>::const_iterator it = all.begin();
+ std::set<Expr>::const_iterator it_end = all.end();
+ while (it != it_end) {
+ conjunction << Node::fromExpr(*it);
+ ++ it;
+ }
+
+ Node res = conjunction;
+ return res.toExpr();
+}/* mkAnd() */
+
+inline Expr mkSortedExpr(Kind kind, const std::vector<Expr>& children) {
+ std::set<Expr> all;
+ all.insert(children.begin(), children.end());
+
+ if (all.size() == 0) {
+ return mkTrue();
+ }
+
+ if (all.size() == 1) {
+ // All the same, or just one
+ return children[0];
+ }
+
+
+ NodeBuilder<> res(kind);
+ std::set<Expr>::const_iterator it = all.begin();
+ std::set<Expr>::const_iterator it_end = all.end();
+ while (it != it_end) {
+ res << Node::fromExpr(*it);
+ ++ it;
+ }
+
+ return ((Node)res).toExpr();
+}/* mkSortedNode() */
+
+inline const bool getBit(Expr expr, unsigned i) {
+ Assert (i < utils::getSize(expr) &&
+ expr.isConst());
+ Integer bit = expr.getConst<BitVector>().extract(i, i).getValue();
+ return (bit == 1u);
+}
+
+void collectAtoms(TNode node, NodeSet& seen);
+
+
+}
+}
diff --git a/src/proof/sat_proof.h b/src/proof/sat_proof.h
index 52319431c..95a4c8907 100644
--- a/src/proof/sat_proof.h
+++ b/src/proof/sat_proof.h
@@ -20,63 +20,63 @@
#define __CVC4__SAT__PROOF_H
#include <stdint.h>
-
#include <ext/hash_map>
#include <ext/hash_set>
#include <iosfwd>
#include <set>
#include <sstream>
#include <vector>
-
#include "expr/expr.h"
#include "proof/proof_manager.h"
+#include "util/proof.h"
+#include "util/statistics_registry.h"
+
namespace CVC4 {
-namespace Minisat {
- class Solver;
- typedef uint32_t CRef;
-}/* Minisat namespace */
-}
-#include "prop/minisat/core/SolverTypes.h"
-#include "util/proof.h"
-#include "prop/sat_solver_types.h"
-namespace std {
- using namespace __gnu_cxx;
-}/* std namespace */
-namespace CVC4 {
+class CnfProof;
/**
* Helper debugging functions
*/
-void printDebug(Minisat::Lit l);
-void printDebug(Minisat::Clause& c);
+template <class Solver> void printDebug(typename Solver::TLit l);
+template <class Solver> void printDebug(typename Solver::TClause& c);
+
+enum ClauseKind {
+ INPUT,
+ THEORY_LEMMA, // we need to distinguish because we must reprove deleted theory lemmas
+ LEARNT
+};/* enum ClauseKind */
+
+template <class Solver>
struct ResStep {
- Minisat::Lit lit;
+ typename Solver::TLit lit;
ClauseId id;
bool sign;
- ResStep(Minisat::Lit l, ClauseId i, bool s) :
+ ResStep(typename Solver::TLit l, ClauseId i, bool s) :
lit(l),
id(i),
sign(s)
{}
};/* struct ResStep */
-typedef std::vector< ResStep > ResSteps;
-typedef std::set < Minisat::Lit> LitSet;
-
+template <class Solver>
class ResChain {
+public:
+ typedef std::vector< ResStep<Solver> > ResSteps;
+ typedef std::set < typename Solver::TLit> LitSet;
+
private:
ClauseId d_start;
ResSteps d_steps;
LitSet* d_redundantLits;
public:
ResChain(ClauseId start);
- void addStep(Minisat::Lit, ClauseId, bool);
+ void addStep(typename Solver::TLit, ClauseId, bool);
bool redundantRemoved() { return (d_redundantLits == NULL || d_redundantLits->empty()); }
- void addRedundantLit(Minisat::Lit lit);
+ void addRedundantLit(typename Solver::TLit lit);
~ResChain();
// accessor methods
ClauseId getStart() { return d_start; }
@@ -84,35 +84,31 @@ public:
LitSet* getRedundant() { return d_redundantLits; }
};/* class ResChain */
-typedef std::hash_map < ClauseId, Minisat::CRef > IdCRefMap;
-typedef std::hash_map < Minisat::CRef, ClauseId > ClauseIdMap;
-typedef std::hash_map < ClauseId, Minisat::Lit> IdUnitMap;
-typedef std::hash_map < int, ClauseId> UnitIdMap; //FIXME
-typedef std::hash_map < ClauseId, ResChain*> IdResMap;
-typedef std::hash_set < ClauseId > IdHashSet;
-typedef std::hash_map < ClauseId, uint64_t > IdProofRuleMap;
-typedef std::vector < ResChain* > ResStack;
-typedef std::hash_map <ClauseId, prop::SatClause* > IdToSatClause;
-typedef std::set < ClauseId > IdSet;
-typedef std::vector < Minisat::Lit > LitVector;
-typedef __gnu_cxx::hash_map<ClauseId, Minisat::Clause& > IdToMinisatClause;
-
-class SatProof;
-
-class ProofProxy : public ProofProxyAbstract {
-private:
- SatProof* d_proof;
-public:
- ProofProxy(SatProof* pf);
- void updateCRef(Minisat::CRef oldref, Minisat::CRef newref);
-};/* class ProofProxy */
-
+template <class Solver> class ProofProxy;
class CnfProof;
-class SatProof {
+template<class Solver>
+class TSatProof {
protected:
- Minisat::Solver* d_solver;
+ typedef std::set < typename Solver::TLit> LitSet;
+ typedef std::set < typename Solver::TVar> VarSet;
+ typedef std::hash_map < ClauseId, typename Solver::TCRef > IdCRefMap;
+ typedef std::hash_map < typename Solver::TCRef, ClauseId > ClauseIdMap;
+ typedef std::hash_map < ClauseId, typename Solver::TLit> IdUnitMap;
+ typedef std::hash_map < int, ClauseId> UnitIdMap;
+ typedef std::hash_map < ClauseId, ResChain<Solver>* > IdResMap;
+ typedef std::hash_map < ClauseId, uint64_t > IdProofRuleMap;
+ typedef std::vector < ResChain<Solver>* > ResStack;
+ //typedef std::hash_map <ClauseId, prop::SatClause* > IdToSatClause;
+ typedef std::set < ClauseId > IdSet;
+ typedef std::vector < typename Solver::TLit > LitVector;
+ typedef __gnu_cxx::hash_map<ClauseId, typename Solver::TClause& > IdToMinisatClause;
+ typedef __gnu_cxx::hash_map<ClauseId, LitVector* > IdToConflicts;
+
+ typename Solver::Solver* d_solver;
+ CnfProof* d_cnfProof;
+
// clauses
IdCRefMap d_idClause;
ClauseIdMap d_clauseId;
@@ -120,10 +116,14 @@ protected:
UnitIdMap d_unitId;
IdHashSet d_deleted;
IdToSatClause d_deletedTheoryLemmas;
-public:
- IdProofRuleMap d_inputClauses;
- IdProofRuleMap d_lemmaClauses;
+
protected:
+ IdHashSet d_inputClauses;
+ IdHashSet d_lemmaClauses;
+ VarSet d_assumptions; // assumption literals for bv solver
+ IdHashSet d_assumptionConflicts; // assumption conflicts not actually added to SAT solver
+ IdToConflicts d_assumptionConflictsDebug;
+
// resolutions
IdResMap d_resChains;
ResStack d_resStack;
@@ -132,38 +132,45 @@ protected:
const ClauseId d_emptyClauseId;
const ClauseId d_nullId;
// proxy class to break circular dependencies
- ProofProxy* d_proxy;
+ ProofProxy<Solver>* d_proxy;
// temporary map for updating CRefs
ClauseIdMap d_temp_clauseId;
- IdCRefMap d_temp_idClause;
+ IdCRefMap d_temp_idClause;
// unit conflict
ClauseId d_unitConflictId;
bool d_storedUnitConflict;
+
+ ClauseId d_trueLit;
+ ClauseId d_falseLit;
+
+ std::string d_name;
public:
- SatProof(Minisat::Solver* solver, bool checkRes = false);
- virtual ~SatProof();
+ TSatProof(Solver* solver, const std::string& name, bool checkRes = false);
+ virtual ~TSatProof();
+ void setCnfProof(CnfProof* cnf_proof);
protected:
void print(ClauseId id);
void printRes(ClauseId id);
- void printRes(ResChain* res);
+ void printRes(ResChain<Solver>* res);
bool isInputClause(ClauseId id);
- bool isTheoryConflict(ClauseId id);
bool isLemmaClause(ClauseId id);
+ bool isAssumptionConflict(ClauseId id);
bool isUnit(ClauseId id);
- bool isUnit(Minisat::Lit lit);
+ bool isUnit(typename Solver::TLit lit);
bool hasResolution(ClauseId id);
void createLitSet(ClauseId id, LitSet& set);
- void registerResolution(ClauseId id, ResChain* res);
-
- ClauseId getClauseId(Minisat::CRef clause);
- ClauseId getClauseId(Minisat::Lit lit);
- Minisat::CRef getClauseRef(ClauseId id);
- Minisat::Lit getUnit(ClauseId id);
- ClauseId getUnitId(Minisat::Lit lit);
- Minisat::Clause& getClause(Minisat::CRef ref);
+ void registerResolution(ClauseId id, ResChain<Solver>* res);
+
+ ClauseId getClauseId(typename Solver::TCRef clause);
+ ClauseId getClauseId(typename Solver::TLit lit);
+ typename Solver::TCRef getClauseRef(ClauseId id);
+ typename Solver::TLit getUnit(ClauseId id);
+ ClauseId getUnitId(typename Solver::TLit lit);
+ typename Solver::TClause& getClause(typename Solver::TCRef ref);
+ void getLitVec(ClauseId id, LitVector& vec);
virtual void toStream(std::ostream& out);
bool checkResolution(ClauseId id);
@@ -174,7 +181,7 @@ protected:
*
* @return
*/
- ClauseId resolveUnit(Minisat::Lit lit);
+ ClauseId resolveUnit(typename Solver::TLit lit);
/**
* Does a depth first search on removed literals and adds the literals
* to be removed in the proper order to the stack.
@@ -183,27 +190,35 @@ protected:
* @param removedSet the previously computed set of redundant literals
* @param removeStack the stack of literals in reverse order of resolution
*/
- void removedDfs(Minisat::Lit lit, LitSet* removedSet, LitVector& removeStack, LitSet& inClause, LitSet& seen);
- void removeRedundantFromRes(ResChain* res, ClauseId id);
+ void removedDfs(typename Solver::TLit lit, LitSet* removedSet, LitVector& removeStack, LitSet& inClause, LitSet& seen);
+ void removeRedundantFromRes(ResChain<Solver>* res, ClauseId id);
public:
- void startResChain(Minisat::CRef start);
- void addResolutionStep(Minisat::Lit lit, Minisat::CRef clause, bool sign);
+ void startResChain(typename Solver::TLit start);
+ void startResChain(typename Solver::TCRef start);
+ void addResolutionStep(typename Solver::TLit lit, typename Solver::TCRef clause, bool sign);
/**
* Pops the current resolution of the stack and stores it
* in the resolution map. Also registers the 'clause' parameter
* @param clause the clause the resolution is proving
*/
- void endResChain(Minisat::CRef clause);
- void endResChain(Minisat::Lit lit);
+ //void endResChain(typename Solver::TCRef clause);
+ void endResChain(typename Solver::TLit lit);
+ void endResChain(ClauseId id);
+ /**
+ * Pops the current resolution of the stack *without* storing it.
+ *
+ */
+ void cancelResChain();
+
/**
* Stores in the current derivation the redundant literals that were
* eliminated from the conflict clause during conflict clause minimization.
* @param lit the eliminated literal
*/
- void storeLitRedundant(Minisat::Lit lit);
+ void storeLitRedundant(typename Solver::TLit lit);
/// update the CRef Id maps when Minisat does memory reallocation x
- void updateCRef(Minisat::CRef old_ref, Minisat::CRef new_ref);
+ void updateCRef(typename Solver::TCRef old_ref, typename Solver::TCRef new_ref);
void finishUpdateCRef();
/**
@@ -211,66 +226,142 @@ public:
*
* @param conflict
*/
- void finalizeProof(Minisat::CRef conflict);
+ void finalizeProof(typename Solver::TCRef conflict);
/// clause registration methods
- ClauseId registerClause(const Minisat::CRef clause, ClauseKind kind, uint64_t proof_id);
- ClauseId registerUnitClause(const Minisat::Lit lit, ClauseKind kind, uint64_t proof_id);
-
- void storeUnitConflict(Minisat::Lit lit, ClauseKind kind, uint64_t proof_id);
+ ClauseId registerClause(const typename Solver::TCRef clause,
+ ClauseKind kind);
+ ClauseId registerUnitClause(const typename Solver::TLit lit,
+ ClauseKind kind);
+ void registerTrueLit(const typename Solver::TLit lit);
+ void registerFalseLit(const typename Solver::TLit lit);
+
+ ClauseId getTrueUnit() const;
+ ClauseId getFalseUnit() const;
+
+
+ void registerAssumption(const typename Solver::TVar var);
+ ClauseId registerAssumptionConflict(const typename Solver::TLitVec& confl);
+
+ ClauseId storeUnitConflict(typename Solver::TLit lit,
+ ClauseKind kind);
+
/**
* Marks the deleted clauses as deleted. Note we may still use them in the final
* resolution.
* @param clause
*/
- void markDeleted(Minisat::CRef clause);
+ void markDeleted(typename Solver::TCRef clause);
bool isDeleted(ClauseId id) { return d_deleted.find(id) != d_deleted.end(); }
/**
* Constructs the resolution of ~q and resolves it with the current
* resolution thus eliminating q from the current clause
* @param q the literal to be resolved out
*/
- void resolveOutUnit(Minisat::Lit q);
+ void resolveOutUnit(typename Solver::TLit q);
/**
* Constructs the resolution of the literal lit. Called when a clause
* containing lit becomes satisfied and is removed.
* @param lit
*/
- void storeUnitResolution(Minisat::Lit lit);
-
- ProofProxy* getProxy() {return d_proxy; }
+ void storeUnitResolution(typename Solver::TLit lit);
+ ProofProxy<Solver>* getProxy() {return d_proxy; }
/**
- Constructs the SAT proof identifying the needed lemmas
+ * Constructs the SAT proof for the given clause,
+ * by collecting the needed clauses in the d_seen
+ * data-structures, also notifying the proofmanager.
*/
- void constructProof();
-
+ void constructProof(ClauseId id);
+ void constructProof() {
+ constructProof(d_emptyClauseId);
+ }
+ void collectClauses(ClauseId id);
+ prop::SatClause* buildClause(ClauseId id);
protected:
- IdSet d_seenLearnt;
- IdHashSet d_seenInput;
- IdHashSet d_seenTheoryConflicts;
- IdHashSet d_seenLemmas;
+ IdSet d_seenLearnt;
+ IdToSatClause d_seenInputs;
+ IdToSatClause d_seenLemmas;
+
+ std::string varName(typename Solver::TLit lit);
+ std::string clauseName(ClauseId id);
- inline std::string varName(Minisat::Lit lit);
- inline std::string clauseName(ClauseId id);
- void collectClauses(ClauseId id);
void addToProofManager(ClauseId id, ClauseKind kind);
+ void addToCnfProof(ClauseId id);
public:
+ virtual void printResolution(ClauseId id, std::ostream& out, std::ostream& paren) = 0;
virtual void printResolutions(std::ostream& out, std::ostream& paren) = 0;
-};/* class SatProof */
+ virtual void printResolutionEmptyClause(std::ostream& out, std::ostream& paren) = 0;
+ virtual void printAssumptionsResolution(ClauseId id, std::ostream& out, std::ostream& paren) = 0;
+
-class LFSCSatProof : public SatProof {
+ void collectClausesUsed(IdToSatClause& inputs,
+ IdToSatClause& lemmas);
+
+ void storeClauseGlue(ClauseId clause, int glue);
+
+private:
+ __gnu_cxx::hash_map<ClauseId, int> d_glueMap;
+ struct Statistics {
+ IntStat d_numLearnedClauses;
+ IntStat d_numLearnedInProof;
+ IntStat d_numLemmasInProof;
+ AverageStat d_avgChainLength;
+ HistogramStat<uint64_t> d_resChainLengths;
+ HistogramStat<uint64_t> d_usedResChainLengths;
+ HistogramStat<uint64_t> d_clauseGlue;
+ HistogramStat<uint64_t> d_usedClauseGlue;
+ Statistics(const std::string& name);
+ ~Statistics();
+ };
+
+ Statistics d_statistics;
+};/* class TSatProof */
+
+
+template <class S>
+class ProofProxy {
private:
- void printResolution(ClauseId id, std::ostream& out, std::ostream& paren);
+ TSatProof<S>* d_proof;
public:
- LFSCSatProof(Minisat::Solver* solver, bool checkRes = false)
- : SatProof(solver, checkRes)
+ ProofProxy(TSatProof<S>* pf);
+ void updateCRef(typename S::TCRef oldref, typename S::TCRef newref);
+};/* class ProofProxy */
+
+
+template <class SatSolver>
+class LFSCSatProof : public TSatProof<SatSolver> {
+private:
+
+public:
+ LFSCSatProof(SatSolver* solver, const std::string& name, bool checkRes = false)
+ : TSatProof<SatSolver>(solver, name, checkRes)
{}
+ virtual void printResolution(ClauseId id, std::ostream& out, std::ostream& paren);
virtual void printResolutions(std::ostream& out, std::ostream& paren);
+ virtual void printResolutionEmptyClause(std::ostream& out, std::ostream& paren);
+ virtual void printAssumptionsResolution(ClauseId id, std::ostream& out, std::ostream& paren);
};/* class LFSCSatProof */
+
+
+template<class Solver>
+prop::SatLiteral toSatLiteral(typename Solver::TLit lit);
+
+
+/**
+* Convert from minisat clause to SatClause
+*
+* @param minisat_cl
+* @param sat_cl
+*/
+template<class Solver>
+void toSatClause(const typename Solver::TClause& minisat_cl,
+ prop::SatClause& sat_cl);
+
+
}/* CVC4 namespace */
#endif /* __CVC4__SAT__PROOF_H */
diff --git a/src/proof/sat_proof_implementation.h b/src/proof/sat_proof_implementation.h
new file mode 100644
index 000000000..92645e105
--- /dev/null
+++ b/src/proof/sat_proof_implementation.h
@@ -0,0 +1,1100 @@
+/********************* */
+/*! \file sat_proof_implementation.h
+ ** \verbatim
+ ** Original author: Liana Hadarean
+ ** Major contributors: Morgan Deters
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2014 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Resolution proof
+ **
+ ** Resolution proof
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__SAT__PROOF_IMPLEMENTATION_H
+#define __CVC4__SAT__PROOF_IMPLEMENTATION_H
+
+#include "proof/sat_proof.h"
+#include "proof/cnf_proof.h"
+#include "prop/minisat/minisat.h"
+#include "prop/bvminisat/bvminisat.h"
+#include "prop/minisat/core/Solver.h"
+#include "prop/bvminisat/core/Solver.h"
+#include "prop/sat_solver_types.h"
+#include "smt/smt_statistics_registry.h"
+
+namespace CVC4 {
+
+template <class Solver>
+void printLit (typename Solver::TLit l) {
+ Debug("proof:sat") << (sign(l) ? "-" : "") << var(l) + 1;
+}
+
+template <class Solver>
+void printClause (typename Solver::TClause& c) {
+ for (int i = 0; i < c.size(); i++) {
+ Debug("proof:sat") << (sign(c[i]) ? "-" : "") << var(c[i]) + 1 << " ";
+ }
+}
+
+template <class Solver>
+void printClause (std::vector<typename Solver::TLit>& c) {
+ for (unsigned i = 0; i < c.size(); i++) {
+ Debug("proof:sat") << (sign(c[i]) ? "-" : "") << var(c[i]) + 1 << " ";
+ }
+}
+
+
+template <class Solver>
+void printLitSet(const std::set<typename Solver::TLit>& s) {
+ typename std::set < typename Solver::TLit>::const_iterator it = s.begin();
+ for(; it != s.end(); ++it) {
+ printLit<Solver>(*it);
+ Debug("proof:sat") << " ";
+ }
+ Debug("proof:sat") << std::endl;
+}
+
+// purely debugging functions
+template <class Solver>
+void printDebug (typename Solver::TLit l) {
+ Debug("proof:sat") << (sign(l) ? "-" : "") << var(l) + 1 << std::endl;
+}
+template <class Solver>
+void printDebug (typename Solver::TClause& c) {
+ for (int i = 0; i < c.size(); i++) {
+ Debug("proof:sat") << (sign(c[i]) ? "-" : "") << var(c[i]) + 1 << " ";
+ }
+ Debug("proof:sat") << std::endl;
+}
+
+
+/**
+ * Converts the clause associated to id to a set of literals
+ *
+ * @param id the clause id
+ * @param set the clause converted to a set of literals
+ */
+template <class Solver>
+void TSatProof<Solver>::createLitSet(ClauseId id, LitSet& set) {
+ Assert(set.empty());
+ if(isUnit(id)) {
+ set.insert(getUnit(id));
+ return;
+ }
+ if ( id == d_emptyClauseId) {
+ return;
+ }
+ // if it's an assumption
+ if (d_assumptionConflictsDebug.find(id) != d_assumptionConflictsDebug.end()) {
+ LitVector* clause = d_assumptionConflictsDebug[id];
+ for (unsigned i = 0; i < clause->size(); ++i) {
+ set.insert(clause->operator[](i));
+ }
+ return;
+ }
+
+ typename Solver::TCRef ref = getClauseRef(id);
+ typename Solver::TClause& c = getClause(ref);
+ for (int i = 0; i < c.size(); i++) {
+ set.insert(c[i]);
+ }
+}
+
+
+/**
+ * Resolves clause1 and clause2 on variable var and stores the
+ * result in clause1
+ * @param v
+ * @param clause1
+ * @param clause2
+ */
+template <class Solver>
+bool resolve(const typename Solver::TLit v,
+ std::set<typename Solver::TLit>& clause1,
+ std::set<typename Solver::TLit>& clause2, bool s) {
+ Assert(!clause1.empty());
+ Assert(!clause2.empty());
+ typename Solver::TLit var = sign(v) ? ~v : v;
+ if (s) {
+ // literal appears positive in the first clause
+ if( !clause2.count(~var)) {
+ if(Debug.isOn("proof:sat")) {
+ Debug("proof:sat") << "proof:resolve: Missing literal ";
+ printLit<Solver>(var);
+ Debug("proof:sat") << std::endl;
+ }
+ return false;
+ }
+ clause1.erase(var);
+ clause2.erase(~var);
+ typename std::set<typename Solver::TLit>::iterator it = clause2.begin();
+ for (; it!= clause2.end(); ++it) {
+ clause1.insert(*it);
+ }
+ } else {
+ // literal appears negative in the first clause
+ if( !clause1.count(~var) || !clause2.count(var)) {
+ if(Debug.isOn("proof:sat")) {
+ Debug("proof:sat") << "proof:resolve: Missing literal ";
+ printLit<Solver>(var);
+ Debug("proof:sat") << std::endl;
+ }
+ return false;
+ }
+ clause1.erase(~var);
+ clause2.erase(var);
+ typename std::set<typename Solver::TLit>::iterator it = clause2.begin();
+ for (; it!= clause2.end(); ++it) {
+ clause1.insert(*it);
+ }
+ }
+ return true;
+}
+
+/// ResChain
+template <class Solver>
+ResChain<Solver>::ResChain(ClauseId start) :
+ d_start(start),
+ d_steps(),
+ d_redundantLits(NULL)
+ {}
+template <class Solver>
+void ResChain<Solver>::addStep(typename Solver::TLit lit, ClauseId id, bool sign) {
+ ResStep<Solver> step(lit, id, sign);
+ d_steps.push_back(step);
+}
+
+template <class Solver>
+void ResChain<Solver>::addRedundantLit(typename Solver::TLit lit) {
+ if (d_redundantLits) {
+ d_redundantLits->insert(lit);
+ } else {
+ d_redundantLits = new LitSet();
+ d_redundantLits->insert(lit);
+ }
+}
+
+
+/// ProxyProof
+template <class Solver>
+ProofProxy<Solver>::ProofProxy(TSatProof<Solver>* proof):
+ d_proof(proof)
+{}
+
+template <class Solver>
+void ProofProxy<Solver>::updateCRef(typename Solver::TCRef oldref, typename Solver::TCRef newref) {
+ d_proof->updateCRef(oldref, newref);
+}
+
+
+/// SatProof
+template <class Solver>
+TSatProof<Solver>::TSatProof(Solver* solver, const std::string& name, bool checkRes)
+ : d_solver(solver)
+ , d_cnfProof(NULL)
+ , d_idClause()
+ , d_clauseId()
+ , d_idUnit()
+ , d_deleted()
+ , d_inputClauses()
+ , d_lemmaClauses()
+ , d_assumptions()
+ , d_assumptionConflicts()
+ , d_assumptionConflictsDebug()
+ , d_resChains()
+ , d_resStack()
+ , d_checkRes(checkRes)
+ , d_emptyClauseId(ClauseIdEmpty)
+ , d_nullId(-2)
+ , d_temp_clauseId()
+ , d_temp_idClause()
+ , d_unitConflictId()
+ , d_storedUnitConflict(false)
+ , d_trueLit(ClauseIdUndef)
+ , d_falseLit(ClauseIdUndef)
+ , d_name(name)
+ , d_seenLearnt()
+ , d_seenInputs()
+ , d_seenLemmas()
+ , d_statistics(name)
+{
+ d_proxy = new ProofProxy<Solver>(this);
+}
+
+template <class Solver>
+TSatProof<Solver>::~TSatProof() {
+ delete d_proxy;
+
+ // FIXME: double free if deleted clause also appears in d_seenLemmas?
+ IdToSatClause::iterator it = d_deletedTheoryLemmas.begin();
+ IdToSatClause::iterator end = d_deletedTheoryLemmas.end();
+
+ for (; it != end; ++it) {
+ ClauseId id = it->first;
+ // otherwise deleted in next loop
+ if (d_seenLemmas.find(id) == d_seenLemmas.end())
+ delete it->second;
+ }
+
+ IdToSatClause::iterator seen_it = d_seenLemmas.begin();
+ IdToSatClause::iterator seen_end = d_seenLemmas.end();
+
+ for (; seen_it != seen_end; ++seen_it) {
+ delete seen_it->second;
+ }
+
+ seen_it = d_seenInputs.begin();
+ seen_end = d_seenInputs.end();
+
+ for (; seen_it != seen_end; ++seen_it) {
+ delete seen_it->second;
+ }
+}
+
+template <class Solver>
+void TSatProof<Solver>::setCnfProof(CnfProof* cnf_proof) {
+ Assert (d_cnfProof == NULL);
+ d_cnfProof = cnf_proof;
+}
+
+/**
+ * Returns true if the resolution chain corresponding to id
+ * does resolve to the clause associated to id
+ * @param id
+ *
+ * @return
+ */
+template <class Solver>
+bool TSatProof<Solver>::checkResolution(ClauseId id) {
+ if(d_checkRes) {
+ bool validRes = true;
+ Assert(d_resChains.find(id) != d_resChains.end());
+ ResChain<Solver>* res = d_resChains[id];
+ LitSet clause1;
+ createLitSet(res->getStart(), clause1);
+ typename ResChain<Solver>::ResSteps& steps = res->getSteps();
+ for (unsigned i = 0; i < steps.size(); i++) {
+ typename Solver::TLit var = steps[i].lit;
+ LitSet clause2;
+ createLitSet (steps[i].id, clause2);
+ bool res = resolve<Solver> (var, clause1, clause2, steps[i].sign);
+ if(res == false) {
+ validRes = false;
+ break;
+ }
+ }
+ // compare clause we claimed to prove with the resolution result
+ if (isUnit(id)) {
+ // special case if it was a unit clause
+ typename Solver::TLit unit = getUnit(id);
+ validRes = clause1.size() == clause1.count(unit) && !clause1.empty();
+ return validRes;
+ }
+ if (id == d_emptyClauseId) {
+ return clause1.empty();
+ }
+
+ LitVector c;
+ getLitVec(id, c);
+
+ for (unsigned i = 0; i < c.size(); ++i) {
+ int count = clause1.erase(c[i]);
+ if (count == 0) {
+ if(Debug.isOn("proof:sat")) {
+ Debug("proof:sat") << "proof:checkResolution::literal not in computed result ";
+ printLit<Solver>(c[i]);
+ Debug("proof:sat") << "\n";
+ }
+ validRes = false;
+ }
+ }
+ validRes = clause1.empty();
+ if (! validRes) {
+ if(Debug.isOn("proof:sat")) {
+ Debug("proof:sat") << "proof:checkResolution::Invalid Resolution, unremoved literals: \n";
+ printLitSet<Solver>(clause1);
+ Debug("proof:sat") << "proof:checkResolution:: result should be: \n";
+ printClause<Solver>(c);
+ }
+ }
+ return validRes;
+
+ } else {
+ return true;
+ }
+}
+
+
+
+
+/// helper methods
+template <class Solver>
+ClauseId TSatProof<Solver>::getClauseId(typename Solver::TCRef ref) {
+ if(d_clauseId.find(ref) == d_clauseId.end()) {
+ Debug("proof:sat") << "Missing clause \n";
+ }
+ Assert(d_clauseId.find(ref) != d_clauseId.end());
+ return d_clauseId[ref];
+}
+
+template <class Solver>
+ClauseId TSatProof<Solver>::getClauseId(typename Solver::TLit lit) {
+ Assert(d_unitId.find(toInt(lit)) != d_unitId.end());
+ return d_unitId[toInt(lit)];
+}
+template <class Solver>
+typename Solver::TCRef TSatProof<Solver>::getClauseRef(ClauseId id) {
+ if (d_idClause.find(id) == d_idClause.end()) {
+ Debug("proof:sat") << "proof:getClauseRef cannot find clause "<<id<<" "
+ << ((d_deleted.find(id) != d_deleted.end()) ? "deleted" : "")
+ << (isUnit(id)? "Unit" : "") << std::endl;
+ }
+ Assert(d_idClause.find(id) != d_idClause.end());
+ return d_idClause[id];
+}
+
+template <class Solver>
+typename Solver::TClause& TSatProof<Solver>::getClause(typename Solver::TCRef ref) {
+ Assert(ref != Solver::TCRef_Undef);
+ Assert(ref >= 0 && ref < d_solver->ca.size());
+ return d_solver->ca[ref];
+}
+
+template <class Solver>
+void TSatProof<Solver>::getLitVec(ClauseId id, LitVector& vec) {
+ if (isUnit(id)) {
+ typename Solver::TLit lit = getUnit(id);
+ vec.push_back(lit);
+ return;
+ }
+ if (isAssumptionConflict(id)) {
+ vec = *(d_assumptionConflictsDebug[id]);
+ return;
+ }
+ typename Solver::TCRef cref = getClauseRef(id);
+ typename Solver::TClause& cl = getClause(cref);
+ for (int i = 0; i < cl.size(); ++i) {
+ vec.push_back(cl[i]);
+ }
+}
+
+
+template <class Solver>
+typename Solver::TLit TSatProof<Solver>::getUnit(ClauseId id) {
+ Assert(d_idUnit.find(id) != d_idUnit.end());
+ return d_idUnit[id];
+}
+template <class Solver>
+bool TSatProof<Solver>::isUnit(ClauseId id) {
+ return d_idUnit.find(id) != d_idUnit.end();
+}
+template <class Solver>
+bool TSatProof<Solver>::isUnit(typename Solver::TLit lit) {
+ return d_unitId.find(toInt(lit)) != d_unitId.end();
+}
+template <class Solver>
+ClauseId TSatProof<Solver>::getUnitId(typename Solver::TLit lit) {
+ Assert(isUnit(lit));
+ return d_unitId[toInt(lit)];
+}
+template <class Solver>
+bool TSatProof<Solver>::hasResolution(ClauseId id) {
+ return d_resChains.find(id) != d_resChains.end();
+}
+template <class Solver>
+bool TSatProof<Solver>::isInputClause(ClauseId id) {
+ return (d_inputClauses.find(id) != d_inputClauses.end());
+}
+template <class Solver>
+bool TSatProof<Solver>::isLemmaClause(ClauseId id) {
+ return (d_lemmaClauses.find(id) != d_lemmaClauses.end());
+}
+
+template <class Solver>
+bool TSatProof<Solver>::isAssumptionConflict(ClauseId id) {
+ return d_assumptionConflicts.find(id) != d_assumptionConflicts.end();
+}
+
+
+template <class Solver>
+void TSatProof<Solver>::print(ClauseId id) {
+ if (d_deleted.find(id) != d_deleted.end()) {
+ Debug("proof:sat") << "del"<<id;
+ } else if (isUnit(id)) {
+ printLit<Solver>(getUnit(id));
+ } else if (id == d_emptyClauseId) {
+ Debug("proof:sat") << "empty "<< std::endl;
+ }
+ else {
+ typename Solver::TCRef ref = getClauseRef(id);
+ printClause<Solver>(getClause(ref));
+ }
+}
+template <class Solver>
+void TSatProof<Solver>::printRes(ClauseId id) {
+ Assert(hasResolution(id));
+ Debug("proof:sat") << "id "<< id <<": ";
+ printRes(d_resChains[id]);
+}
+template <class Solver>
+void TSatProof<Solver>::printRes(ResChain<Solver>* res) {
+ ClauseId start_id = res->getStart();
+
+ if(Debug.isOn("proof:sat")) {
+ Debug("proof:sat") << "(";
+ print(start_id);
+ }
+
+ typename ResChain<Solver>::ResSteps& steps = res->getSteps();
+ for(unsigned i = 0; i < steps.size(); i++ ) {
+ typename Solver::TLit v = steps[i].lit;
+ ClauseId id = steps[i].id;
+
+ if(Debug.isOn("proof:sat")) {
+ Debug("proof:sat") << "[";
+ printLit<Solver>(v);
+ Debug("proof:sat") << "] ";
+ print(id);
+ }
+ }
+ Debug("proof:sat") << ") \n";
+}
+
+/// registration methods
+template <class Solver>
+ ClauseId TSatProof<Solver>::registerClause(typename Solver::TCRef clause,
+ ClauseKind kind) {
+ Assert(clause != Solver::TCRef_Undef);
+ typename ClauseIdMap::iterator it = d_clauseId.find(clause);
+ if (it == d_clauseId.end()) {
+ ClauseId newId = ProofManager::currentPM()->nextId();
+ d_clauseId.insert(std::make_pair(clause, newId));
+ d_idClause.insert(std::make_pair(newId, clause));
+ if (kind == INPUT) {
+ Assert(d_inputClauses.find(newId) == d_inputClauses.end());
+ d_inputClauses.insert(newId);
+ }
+ if (kind == THEORY_LEMMA) {
+ Assert(d_lemmaClauses.find(newId) == d_lemmaClauses.end());
+ d_lemmaClauses.insert(newId);
+ }
+ }
+
+ ClauseId id = d_clauseId[clause];
+ Assert(kind != INPUT || d_inputClauses.count(id));
+ Assert(kind != THEORY_LEMMA || d_lemmaClauses.count(id));
+
+ Debug("proof:sat:detailed") << "registerClause CRef: " << clause << " id: " << d_clauseId[clause]
+ <<" kind: " << kind << "\n";
+ //ProofManager::currentPM()->setRegisteredClauseId( d_clauseId[clause] );
+ return id;
+}
+
+template <class Solver>
+ClauseId TSatProof<Solver>::registerUnitClause(typename Solver::TLit lit,
+ ClauseKind kind) {
+ Debug("cores") << "registerUnitClause " << kind << std::endl;
+ typename UnitIdMap::iterator it = d_unitId.find(toInt(lit));
+ if (it == d_unitId.end()) {
+ ClauseId newId = ProofManager::currentPM()->nextId();
+ d_unitId.insert(std::make_pair(toInt(lit), newId));
+ d_idUnit.insert(std::make_pair(newId, lit));
+
+ if (kind == INPUT) {
+ Assert(d_inputClauses.find(newId) == d_inputClauses.end());
+ d_inputClauses.insert(newId);
+ }
+ if (kind == THEORY_LEMMA) {
+ Assert(d_lemmaClauses.find(newId) == d_lemmaClauses.end());
+ d_lemmaClauses.insert(newId);
+ }
+ }
+ ClauseId id = d_unitId[toInt(lit)];
+ Assert(kind != INPUT || d_inputClauses.count(id));
+ Assert(kind != THEORY_LEMMA || d_lemmaClauses.count(id));
+ Debug("proof:sat:detailed") << "registerUnitClause id: " << id
+ <<" kind: " << kind << "\n";
+ // ProofManager::currentPM()->setRegisteredClauseId( d_unitId[toInt(lit)] );
+ return id;
+}
+template <class Solver>
+void TSatProof<Solver>::registerTrueLit(const typename Solver::TLit lit) {
+ Assert (d_trueLit == ClauseIdUndef);
+ d_trueLit = registerUnitClause(lit, INPUT);
+}
+
+template <class Solver>
+void TSatProof<Solver>::registerFalseLit(const typename Solver::TLit lit) {
+ Assert (d_falseLit == ClauseIdUndef);
+ d_falseLit = registerUnitClause(lit, INPUT);
+}
+
+template <class Solver>
+ClauseId TSatProof<Solver>::getTrueUnit() const {
+ Assert (d_trueLit != ClauseIdUndef);
+ return d_trueLit;
+}
+
+template <class Solver>
+ClauseId TSatProof<Solver>::getFalseUnit() const {
+ Assert (d_falseLit != ClauseIdUndef);
+ return d_falseLit;
+}
+
+
+template <class Solver>
+void TSatProof<Solver>::registerAssumption(const typename Solver::TVar var) {
+ Assert (d_assumptions.find(var) == d_assumptions.end());
+ d_assumptions.insert(var);
+}
+
+template <class Solver>
+ClauseId TSatProof<Solver>::registerAssumptionConflict(const typename Solver::TLitVec& confl) {
+ Debug("proof:sat:detailed") << "registerAssumptionConflict " << std::endl;
+ // Uniqueness is checked in the bit-vector proof
+ // should be vars
+ for (int i = 0; i < confl.size(); ++i) {
+ Assert (d_assumptions.find(var(confl[i])) != d_assumptions.end());
+ }
+ ClauseId new_id = ProofManager::currentPM()->nextId();
+ d_assumptionConflicts.insert(new_id);
+ LitVector* vec_confl = new LitVector(confl.size());
+ for (int i = 0; i < confl.size(); ++i) {
+ vec_confl->operator[](i) = confl[i];
+ }
+ if (Debug.isOn("proof:sat:detailed")) {
+ printClause<Solver>(*vec_confl);
+ Debug("proof:sat:detailed") << "\n";
+ }
+
+ d_assumptionConflictsDebug[new_id] = vec_confl;
+ return new_id;
+}
+
+
+template <class Solver>
+void TSatProof<Solver>::removedDfs(typename Solver::TLit lit, LitSet* removedSet, LitVector& removeStack, LitSet& inClause, LitSet& seen) {
+ // if we already added the literal return
+ if (seen.count(lit)) {
+ return;
+ }
+
+ typename Solver::TCRef reason_ref = d_solver->reason(var(lit));
+ if (reason_ref == Solver::TCRef_Undef) {
+ seen.insert(lit);
+ removeStack.push_back(lit);
+ return;
+ }
+
+ int size = getClause(reason_ref).size();
+ for (int i = 1; i < size; i++ ) {
+ typename Solver::TLit v = getClause(reason_ref)[i];
+ if(inClause.count(v) == 0 && seen.count(v) == 0) {
+ removedDfs(v, removedSet, removeStack, inClause, seen);
+ }
+ }
+ if(seen.count(lit) == 0) {
+ seen.insert(lit);
+ removeStack.push_back(lit);
+ }
+}
+
+template <class Solver>
+void TSatProof<Solver>::removeRedundantFromRes(ResChain<Solver>* res, ClauseId id) {
+ LitSet* removed = res->getRedundant();
+ if (removed == NULL) {
+ return;
+ }
+
+ LitSet inClause;
+ createLitSet(id, inClause);
+
+ LitVector removeStack;
+ LitSet seen;
+ for (typename LitSet::iterator it = removed->begin(); it != removed->end(); ++it) {
+ removedDfs(*it, removed, removeStack, inClause, seen);
+ }
+
+ for (int i = removeStack.size()-1; i >= 0; --i) {
+ typename Solver::TLit lit = removeStack[i];
+ typename Solver::TCRef reason_ref = d_solver->reason(var(lit));
+ ClauseId reason_id;
+
+ if (reason_ref == Solver::TCRef_Undef) {
+ Assert(isUnit(~lit));
+ reason_id = getUnitId(~lit);
+ } else {
+ reason_id = registerClause(reason_ref, LEARNT);
+ }
+ res->addStep(lit, reason_id, !sign(lit));
+ }
+ removed->clear();
+}
+
+template <class Solver>
+void TSatProof<Solver>::registerResolution(ClauseId id, ResChain<Solver>* res) {
+ Assert(res != NULL);
+
+ removeRedundantFromRes(res, id);
+ Assert(res->redundantRemoved());
+
+ d_resChains[id] = res;
+ if(Debug.isOn("proof:sat")) {
+ printRes(id);
+ }
+ if(d_checkRes) {
+ Assert(checkResolution(id));
+ }
+
+ PSTATS(
+ d_statistics.d_resChainLengths << ((uint64_t)res->getSteps().size());
+ d_statistics.d_avgChainLength.addEntry((uint64_t)res->getSteps().size());
+ ++(d_statistics.d_numLearnedClauses);
+ )
+}
+
+
+/// recording resolutions
+template <class Solver>
+void TSatProof<Solver>::startResChain(typename Solver::TCRef start) {
+ ClauseId id = getClauseId(start);
+ ResChain<Solver>* res = new ResChain<Solver>(id);
+ d_resStack.push_back(res);
+}
+
+template <class Solver>
+void TSatProof<Solver>::startResChain(typename Solver::TLit start) {
+ ClauseId id = getUnitId(start);
+ ResChain<Solver>* res = new ResChain<Solver>(id);
+ d_resStack.push_back(res);
+}
+
+
+template <class Solver>
+void TSatProof<Solver>::addResolutionStep(typename Solver::TLit lit,
+ typename Solver::TCRef clause, bool sign) {
+ ClauseId id = registerClause(clause, LEARNT);
+ ResChain<Solver>* res = d_resStack.back();
+ res->addStep(lit, id, sign);
+}
+
+template <class Solver>
+void TSatProof<Solver>::endResChain(ClauseId id) {
+ Debug("proof:sat:detailed") <<"endResChain " << id << "\n";
+ Assert(d_resStack.size() > 0);
+ ResChain<Solver>* res = d_resStack.back();
+ registerResolution(id, res);
+ d_resStack.pop_back();
+}
+
+
+// template <class Solver>
+// void TSatProof<Solver>::endResChain(typename Solver::TCRef clause) {
+// Assert(d_resStack.size() > 0);
+// ClauseId id = registerClause(clause, LEARNT);
+// ResChain<Solver>* res = d_resStack.back();
+// registerResolution(id, res);
+// d_resStack.pop_back();
+// }
+
+template <class Solver>
+void TSatProof<Solver>::endResChain(typename Solver::TLit lit) {
+ Assert(d_resStack.size() > 0);
+ ClauseId id = registerUnitClause(lit, LEARNT);
+ Debug("proof:sat:detailed") <<"endResChain unit " << id << "\n";
+ ResChain<Solver>* res = d_resStack.back();
+ d_glueMap[id] = 1;
+ registerResolution(id, res);
+ d_resStack.pop_back();
+}
+
+
+template <class Solver>
+void TSatProof<Solver>::cancelResChain() {
+ Assert(d_resStack.size() > 0);
+ d_resStack.pop_back();
+}
+
+
+template <class Solver>
+void TSatProof<Solver>::storeLitRedundant(typename Solver::TLit lit) {
+ Assert(d_resStack.size() > 0);
+ ResChain<Solver>* res = d_resStack.back();
+ res->addRedundantLit(lit);
+}
+
+/// constructing resolutions
+template <class Solver>
+void TSatProof<Solver>::resolveOutUnit(typename Solver::TLit lit) {
+ ClauseId id = resolveUnit(~lit);
+ ResChain<Solver>* res = d_resStack.back();
+ res->addStep(lit, id, !sign(lit));
+}
+template <class Solver>
+void TSatProof<Solver>::storeUnitResolution(typename Solver::TLit lit) {
+ Debug("cores") << "STORE UNIT RESOLUTION" << std::endl;
+ resolveUnit(lit);
+}
+template <class Solver>
+ClauseId TSatProof<Solver>::resolveUnit(typename Solver::TLit lit) {
+ // first check if we already have a resolution for lit
+ if(isUnit(lit)) {
+ ClauseId id = getClauseId(lit);
+ Assert(hasResolution(id) || isInputClause(id) || isLemmaClause(id));
+ return id;
+ }
+ typename Solver::TCRef reason_ref = d_solver->reason(var(lit));
+ Assert(reason_ref != Solver::TCRef_Undef);
+
+ ClauseId reason_id = registerClause(reason_ref, LEARNT);
+
+ ResChain<Solver>* res = new ResChain<Solver>(reason_id);
+ // Here, the call to resolveUnit() can reallocate memory in the
+ // clause allocator. So reload reason ptr each time.
+ typename Solver::TClause* reason = &getClause(reason_ref);
+ for (int i = 0;
+ i < reason->size();
+ i++, reason = &getClause(reason_ref)) {
+ typename Solver::TLit l = (*reason)[i];
+ if(lit != l) {
+ ClauseId res_id = resolveUnit(~l);
+ res->addStep(l, res_id, !sign(l));
+ }
+ }
+ ClauseId unit_id = registerUnitClause(lit, LEARNT);
+ registerResolution(unit_id, res);
+ return unit_id;
+}
+template <class Solver>
+void TSatProof<Solver>::toStream(std::ostream& out) {
+ Debug("proof:sat") << "TSatProof<Solver>::printProof\n";
+ Unimplemented("native proof printing not supported yet");
+}
+template <class Solver>
+ClauseId TSatProof<Solver>::storeUnitConflict(typename Solver::TLit conflict_lit,
+ ClauseKind kind) {
+ Debug("cores") << "STORE UNIT CONFLICT" << std::endl;
+ Assert(!d_storedUnitConflict);
+ d_unitConflictId = registerUnitClause(conflict_lit, kind);
+ d_storedUnitConflict = true;
+ Debug("proof:sat:detailed") <<"storeUnitConflict " << d_unitConflictId << "\n";
+ return d_unitConflictId;
+}
+template <class Solver>
+void TSatProof<Solver>::finalizeProof(typename Solver::TCRef conflict_ref) {
+ Assert(d_resStack.size() == 0);
+ Assert(conflict_ref != Solver::TCRef_Undef);
+ ClauseId conflict_id;
+ if (conflict_ref == Solver::TCRef_Lazy) {
+ Assert(d_storedUnitConflict);
+ conflict_id = d_unitConflictId;
+
+ ResChain<Solver>* res = new ResChain<Solver>(conflict_id);
+ typename Solver::TLit lit = d_idUnit[conflict_id];
+ ClauseId res_id = resolveUnit(~lit);
+ res->addStep(lit, res_id, !sign(lit));
+
+ registerResolution(d_emptyClauseId, res);
+
+ return;
+ } else {
+ Assert(!d_storedUnitConflict);
+ conflict_id = registerClause(conflict_ref, LEARNT); //FIXME
+ }
+
+ if(Debug.isOn("proof:sat")) {
+ Debug("proof:sat") << "proof::finalizeProof Final Conflict ";
+ print(conflict_id);
+ }
+
+ ResChain<Solver>* res = new ResChain<Solver>(conflict_id);
+ // Here, the call to resolveUnit() can reallocate memory in the
+ // clause allocator. So reload conflict ptr each time.
+ typename Solver::TClause* conflict = &getClause(conflict_ref);
+ for (int i = 0;
+ i < conflict->size();
+ ++i, conflict = &getClause(conflict_ref)) {
+ typename Solver::TLit lit = (*conflict)[i];
+ ClauseId res_id = resolveUnit(~lit);
+ res->addStep(lit, res_id, !sign(lit));
+ }
+ registerResolution(d_emptyClauseId, res);
+}
+
+/// CRef manager
+template <class Solver>
+void TSatProof<Solver>::updateCRef(typename Solver::TCRef oldref,
+ typename Solver::TCRef newref) {
+ if (d_clauseId.find(oldref) == d_clauseId.end()) {
+ return;
+ }
+ ClauseId id = getClauseId(oldref);
+ Assert(d_temp_clauseId.find(newref) == d_temp_clauseId.end());
+ Assert(d_temp_idClause.find(id) == d_temp_idClause.end());
+ d_temp_clauseId[newref] = id;
+ d_temp_idClause[id] = newref;
+}
+template <class Solver>
+void TSatProof<Solver>::finishUpdateCRef() {
+ d_clauseId.swap(d_temp_clauseId);
+ d_temp_clauseId.clear();
+
+ d_idClause.swap(d_temp_idClause);
+ d_temp_idClause.clear();
+}
+template <class Solver>
+void TSatProof<Solver>::markDeleted(typename Solver::TCRef clause) {
+ if (d_clauseId.find(clause) != d_clauseId.end()) {
+ ClauseId id = getClauseId(clause);
+ Assert(d_deleted.find(id) == d_deleted.end());
+ d_deleted.insert(id);
+ if (isLemmaClause(id)) {
+ const typename Solver::TClause& minisat_cl = getClause(clause);
+ prop::SatClause* sat_cl = new prop::SatClause();
+ toSatClause<Solver>(minisat_cl, *sat_cl);
+ d_deletedTheoryLemmas.insert(std::make_pair(id, sat_cl));
+ }
+ }
+}
+
+// template<>
+// void toSatClause< ::BVMinisat::Solver> (const BVMinisat::Solver::TClause& minisat_cl,
+// prop::SatClause& sat_cl) {
+
+// prop::BVMinisatSatSolver::toSatClause(minisat_cl, sat_cl);
+// }
+
+
+
+template <class Solver>
+void TSatProof<Solver>::constructProof(ClauseId conflict) {
+ collectClauses(conflict);
+}
+
+template <class Solver>
+std::string TSatProof<Solver>::clauseName(ClauseId id) {
+ std::ostringstream os;
+ if (isInputClause(id)) {
+ os << ProofManager::getInputClauseName(id, d_name);
+ return os.str();
+ } else
+ if (isLemmaClause(id)) {
+ os << ProofManager::getLemmaClauseName(id, d_name);
+ return os.str();
+ }else {
+ os << ProofManager::getLearntClauseName(id, d_name);
+ return os.str();
+ }
+}
+
+template <class Solver>
+prop::SatClause* TSatProof<Solver>::buildClause(ClauseId id) {
+ if (isUnit(id)) {
+ typename Solver::TLit lit = getUnit(id);
+ prop::SatLiteral sat_lit = toSatLiteral<Solver>(lit);
+ prop::SatClause* clause = new prop::SatClause();
+ clause->push_back(sat_lit);
+ return clause;
+ }
+
+ if (isDeleted(id)) {
+ prop::SatClause* clause = d_deletedTheoryLemmas.find(id)->second;
+ return clause;
+ }
+
+ typename Solver::TCRef ref = getClauseRef(id);
+ const typename Solver::TClause& minisat_cl = getClause(ref);
+ prop::SatClause* clause = new prop::SatClause();
+ toSatClause<Solver>(minisat_cl, *clause);
+ return clause;
+}
+
+template <class Solver>
+void TSatProof<Solver>::collectClauses(ClauseId id) {
+ if (d_seenInputs.find(id) != d_seenInputs.end() ||
+ d_seenLemmas.find(id) != d_seenLemmas.end() ||
+ d_seenLearnt.find(id) != d_seenLearnt.end()) {
+ return;
+ }
+
+ if (isInputClause(id)) {
+ d_seenInputs.insert(std::make_pair(id, buildClause(id)));
+ return;
+ } else if (isLemmaClause(id)) {
+ d_seenLemmas.insert(std::make_pair(id, buildClause(id)));
+ return;
+ } else if (!isAssumptionConflict(id)) {
+ d_seenLearnt.insert(id);
+ }
+
+ Assert(d_resChains.find(id) != d_resChains.end());
+ ResChain<Solver>* res = d_resChains[id];
+ PSTATS(
+ d_statistics.d_usedResChainLengths << ((uint64_t)res->getSteps().size());
+ d_statistics.d_usedClauseGlue << ((uint64_t) d_glueMap[id]);
+ );
+ ClauseId start = res->getStart();
+ collectClauses(start);
+
+ typename ResChain<Solver>::ResSteps steps = res->getSteps();
+ for(size_t i = 0; i < steps.size(); i++) {
+ collectClauses(steps[i].id);
+ }
+}
+
+template <class Solver>
+void TSatProof<Solver>::collectClausesUsed(IdToSatClause& inputs,
+ IdToSatClause& lemmas) {
+ inputs = d_seenInputs;
+ lemmas = d_seenLemmas;
+ PSTATS (
+ d_statistics.d_numLearnedInProof.setData(d_seenLearnt.size());
+ d_statistics.d_numLemmasInProof.setData(d_seenLemmas.size());
+ );
+}
+
+template <class Solver>
+void TSatProof<Solver>::storeClauseGlue(ClauseId clause, int glue) {
+ Assert (d_glueMap.find(clause) == d_glueMap.end());
+ d_glueMap.insert(std::make_pair(clause, glue));
+}
+
+template <class Solver>
+TSatProof<Solver>::Statistics::Statistics(const std::string& prefix)
+ : d_numLearnedClauses("satproof::"+prefix+"::NumLearnedClauses", 0)
+ , d_numLearnedInProof("satproof::"+prefix+"::NumLearnedInProof", 0)
+ , d_numLemmasInProof("satproof::"+prefix+"::NumLemmasInProof", 0)
+ , d_avgChainLength("satproof::"+prefix+"::AvgResChainLength")
+ , d_resChainLengths("satproof::"+prefix+"::ResChainLengthsHist")
+ , d_usedResChainLengths("satproof::"+prefix+"::UsedResChainLengthsHist")
+ , d_clauseGlue("satproof::"+prefix+"::ClauseGlueHist")
+ , d_usedClauseGlue("satproof::"+prefix+"::UsedClauseGlueHist") {
+ smtStatisticsRegistry()->registerStat(&d_numLearnedClauses);
+ smtStatisticsRegistry()->registerStat(&d_numLearnedInProof);
+ smtStatisticsRegistry()->registerStat(&d_numLemmasInProof);
+ smtStatisticsRegistry()->registerStat(&d_avgChainLength);
+ smtStatisticsRegistry()->registerStat(&d_resChainLengths);
+ smtStatisticsRegistry()->registerStat(&d_usedResChainLengths);
+ smtStatisticsRegistry()->registerStat(&d_clauseGlue);
+ smtStatisticsRegistry()->registerStat(&d_usedClauseGlue);
+}
+
+template <class Solver>
+TSatProof<Solver>::Statistics::~Statistics() {
+ smtStatisticsRegistry()->unregisterStat(&d_numLearnedClauses);
+ smtStatisticsRegistry()->unregisterStat(&d_numLearnedInProof);
+ smtStatisticsRegistry()->unregisterStat(&d_numLemmasInProof);
+ smtStatisticsRegistry()->unregisterStat(&d_avgChainLength);
+ smtStatisticsRegistry()->unregisterStat(&d_resChainLengths);
+ smtStatisticsRegistry()->unregisterStat(&d_usedResChainLengths);
+ smtStatisticsRegistry()->unregisterStat(&d_clauseGlue);
+ smtStatisticsRegistry()->unregisterStat(&d_usedClauseGlue);
+}
+
+
+/// LFSCSatProof class
+template <class Solver>
+void LFSCSatProof<Solver>::printResolution(ClauseId id, std::ostream& out, std::ostream& paren) {
+ out << "(satlem_simplify _ _ _ ";
+
+ ResChain<Solver>* res = this->d_resChains[id];
+ typename ResChain<Solver>::ResSteps& steps = res->getSteps();
+
+ for (int i = steps.size()-1; i >= 0; i--) {
+ out << "(";
+ out << (steps[i].sign? "R" : "Q") << " _ _ ";
+ }
+
+ ClauseId start_id = res->getStart();
+ out << this->clauseName(start_id) << " ";
+
+ for(unsigned i = 0; i < steps.size(); i++) {
+ prop::SatVariable v = prop::MinisatSatSolver::toSatVariable(var(steps[i].lit));
+ out << this->clauseName(steps[i].id) << " "<<ProofManager::getVarName(v, this->d_name) <<")";
+ }
+
+ if (id == this->d_emptyClauseId) {
+ out <<"(\\empty empty)";
+ return;
+ }
+
+ out << "(\\" << this->clauseName(id) << "\n"; // bind to lemma name
+ paren << "))"; // closing parethesis for lemma binding and satlem
+}
+
+/// LFSCSatProof class
+template <class Solver>
+void LFSCSatProof<Solver>::printAssumptionsResolution(ClauseId id, std::ostream& out, std::ostream& paren) {
+ Assert (this->isAssumptionConflict(id));
+ // print the resolution proving the assumption conflict
+ printResolution(id, out, paren);
+ // resolve out assumptions to prove empty clause
+ out << "(satlem_simplify _ _ _ ";
+ std::vector<typename Solver::TLit>& confl = *(this->d_assumptionConflictsDebug[id]);
+
+ Assert (confl.size());
+
+ for (unsigned i = 0; i < confl.size(); ++i) {
+ prop::SatLiteral lit = toSatLiteral<Solver>(confl[i]);
+ out <<"(";
+ out << (lit.isNegated() ? "Q" : "R") <<" _ _ ";
+ }
+
+ out << this->clauseName(id)<< " ";
+ for (int i = confl.size() - 1; i >= 0; --i) {
+ prop::SatLiteral lit = toSatLiteral<Solver>(confl[i]);
+ prop::SatVariable v = lit.getSatVariable();
+ out << "unit"<< v <<" ";
+ out << ProofManager::getVarName(v, this->d_name) <<")";
+ }
+ out <<"(\\ e e)\n";
+ paren <<")";
+}
+
+
+template <class Solver>
+void LFSCSatProof<Solver>::printResolutions(std::ostream& out, std::ostream& paren) {
+ Debug("bv-proof") << "; print resolutions" << std::endl;
+ std::set<ClauseId>::iterator it = this->d_seenLearnt.begin();
+ for(; it!= this->d_seenLearnt.end(); ++it) {
+ if(*it != this->d_emptyClauseId) {
+ Debug("bv-proof") << "; print resolution for " << *it << std::endl;
+ printResolution(*it, out, paren);
+ }
+ }
+ Debug("bv-proof") << "; done print resolutions" << std::endl;
+}
+
+template <class Solver>
+void LFSCSatProof<Solver>::printResolutionEmptyClause(std::ostream& out, std::ostream& paren) {
+ printResolution(this->d_emptyClauseId, out, paren);
+}
+
+
+inline std::ostream& operator<<(std::ostream& out, CVC4::ClauseKind k) {
+ switch(k) {
+ case CVC4::INPUT:
+ out << "INPUT";
+ break;
+ case CVC4::THEORY_LEMMA:
+ out << "THEORY_LEMMA";
+ break;
+ case CVC4::LEARNT:
+ out << "LEARNT";
+ break;
+ default:
+ out << "ClauseKind Unknown! [" << unsigned(k) << "]";
+ }
+
+ return out;
+}
+
+}/* CVC4 namespace */
+
+#endif /* __CVC4__SAT__PROOF_IMPLEMENTATION_H */
diff --git a/src/proof/theory_proof.cpp b/src/proof/theory_proof.cpp
index 6982509b1..b0d6988a5 100644
--- a/src/proof/theory_proof.cpp
+++ b/src/proof/theory_proof.cpp
@@ -15,145 +15,455 @@
** \todo document this file
**/
-#include "proof/theory_proof.h"
+#include "base/cvc4_assert.h"
+#include "context/context.h"
+#include "options/bv_options.h"
+#include "proof/array_proof.h"
+#include "proof/bitvector_proof.h"
+#include "proof/cnf_proof.h"
+#include "proof/cnf_proof.h"
#include "proof/proof_manager.h"
-using namespace CVC4;
+#include "proof/proof_utils.h"
+#include "proof/sat_proof.h"
+#include "proof/theory_proof.h"
+#include "proof/uf_proof.h"
+#include "prop/sat_solver_types.h"
+#include "smt/smt_engine.h"
+#include "smt/smt_engine_scope.h"
+#include "smt_util/node_visitor.h"
+#include "theory/arrays/theory_arrays.h"
+#include "theory/bv/theory_bv.h"
+#include "theory/output_channel.h"
+#include "theory/term_registration_visitor.h"
+#include "theory/uf/equality_engine.h"
+#include "theory/uf/theory_uf.h"
+#include "theory/valuation.h"
+#include "util/hash.h"
+#include "util/proof.h"
-TheoryProof::TheoryProof()
- : d_termDeclarations()
- , d_sortDeclarations()
- , d_declarationCache()
-{}
-void TheoryProof::addDeclaration(Expr term) {
- if (d_declarationCache.count(term)) {
- return;
- }
+namespace CVC4 {
+
+unsigned CVC4::LetCount::counter = 0;
+static unsigned LET_COUNT = 1;
+
+//for proof replay
+class ProofOutputChannel : public theory::OutputChannel {
+public:
+ Node d_conflict;
+ Proof* d_proof;
+ Node d_lemma;
- Type type = term.getType();
- if (type.isSort())
- d_sortDeclarations.insert(type);
- if (term.getKind() == kind::APPLY_UF) {
- Expr function = term.getOperator();
- d_termDeclarations.insert(function);
- } else if (term.isVariable()) {
- //Assert (type.isSort() || type.isBoolean());
- d_termDeclarations.insert(term);
+ ProofOutputChannel() : d_conflict(), d_proof(NULL) {}
+
+ void conflict(TNode n, Proof* pf) throw() {
+ Trace("theory-proof-debug") << "; CONFLICT: " << n << std::endl;
+ Assert(d_conflict.isNull());
+ Assert(!n.isNull());
+ d_conflict = n;
+ Assert(pf != NULL);
+ d_proof = pf;
}
- // recursively declare all other terms
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- addDeclaration(term[i]);
+ bool propagate(TNode x) throw() {
+ Trace("theory-proof-debug") << "got a propagation: " << x << std::endl;
+ return true;
+ }
+ theory::LemmaStatus lemma(TNode n, ProofRule rule, bool, bool, bool) throw() {
+ Trace("theory-proof-debug") << "new lemma: " << n << std::endl;
+ d_lemma = n;
+ return theory::LemmaStatus(TNode::null(), 0);
+ }
+ theory::LemmaStatus splitLemma(TNode, bool) throw() {
+ AlwaysAssert(false);
+ return theory::LemmaStatus(TNode::null(), 0);
+ }
+ void requirePhase(TNode n, bool b) throw() {
+ Trace("theory-proof-debug") << "requirePhase " << n << " " << b << std::endl;
+ }
+ bool flipDecision() throw() {
+ AlwaysAssert(false);
+ return false;
+ }
+ void setIncomplete() throw() {
+ AlwaysAssert(false);
}
- d_declarationCache.insert(term);
+};/* class ProofOutputChannel */
+
+//for proof replay
+class MyPreRegisterVisitor {
+ theory::Theory* d_theory;
+ __gnu_cxx::hash_set<TNode, TNodeHashFunction> d_visited;
+public:
+ typedef void return_type;
+ MyPreRegisterVisitor(theory::Theory* theory)
+ : d_theory(theory)
+ , d_visited()
+ {}
+ bool alreadyVisited(TNode current, TNode parent) { return d_visited.find(current) != d_visited.end(); }
+ void visit(TNode current, TNode parent) {
+ if(theory::Theory::theoryOf(current) == d_theory->getId()) {
+ //Trace("theory-proof-debug") << "preregister " << current << std::endl;
+ d_theory->preRegisterTerm(current);
+ d_visited.insert(current);
+ }
+ }
+ void start(TNode node) { }
+ void done(TNode node) { }
+}; /* class MyPreRegisterVisitor */
+
+TheoryProofEngine::TheoryProofEngine(SmtGlobals* globals)
+ : d_registrationCache()
+ , d_theoryProofTable()
+ , d_globals(globals)
+{
+ d_theoryProofTable[theory::THEORY_BOOL] = new LFSCBooleanProof(this);
}
-std::string toLFSCKind(Kind kind) {
- switch(kind) {
- case kind::OR : return "or";
- case kind::AND: return "and";
- case kind::XOR: return "xor";
- case kind::EQUAL: return "=";
- case kind::IFF: return "iff";
- case kind::IMPLIES: return "impl";
- case kind::NOT: return "not";
- default:
- Unreachable();
+TheoryProofEngine::~TheoryProofEngine() {
+ TheoryProofTable::iterator it = d_theoryProofTable.begin();
+ TheoryProofTable::iterator end = d_theoryProofTable.end();
+ for (; it != end; ++it) {
+ delete it->second;
}
}
-void LFSCTheoryProof::printTerm(Expr term, std::ostream& os) {
- if (term.isVariable()) {
- if(term.getType().isBoolean()) {
- os << "(p_app " << term << ")";
- } else {
- os << term;
+
+void TheoryProofEngine::registerTheory(theory::Theory* th) {
+ if( th ){
+ theory::TheoryId id = th->getId();
+ if(d_theoryProofTable.find(id) == d_theoryProofTable.end()) {
+
+ Trace("theory-proof-debug") << "; register theory " << id << std::endl;
+
+ if (id == theory::THEORY_UF) {
+ d_theoryProofTable[id] = new LFSCUFProof((theory::uf::TheoryUF*)th, this);
+ return;
+ }
+
+ if (id == theory::THEORY_BV) {
+ BitVectorProof * bvp = new LFSCBitVectorProof((theory::bv::TheoryBV*)th, this);
+ d_theoryProofTable[id] = bvp;
+ ((theory::bv::TheoryBV*)th)->setProofLog( bvp );
+ return;
+ }
+ if (id == theory::THEORY_ARRAY) {
+ d_theoryProofTable[id] = new LFSCArrayProof((theory::arrays::TheoryArrays*)th, this);
+ return;
+ }
+ // TODO other theories
}
+ }
+}
+
+TheoryProof* TheoryProofEngine::getTheoryProof(theory::TheoryId id) {
+ Assert (d_theoryProofTable.find(id) != d_theoryProofTable.end());
+ return d_theoryProofTable[id];
+}
+
+void TheoryProofEngine::registerTerm(Expr term) {
+ if (d_registrationCache.count(term)) {
return;
}
- switch(Kind k = term.getKind()) {
- case kind::APPLY_UF: {
- if(term.getType().isBoolean()) {
- os << "(p_app ";
- }
- Expr func = term.getOperator();
+ theory::TheoryId theory_id = theory::Theory::theoryOf(term);
+
+ // don't need to register boolean terms
+ if (theory_id == theory::THEORY_BUILTIN ||
+ term.getKind() == kind::ITE) {
for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- os << "(apply _ _ ";
+ registerTerm(term[i]);
}
- os << func << " ";
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- printTerm(term[i], os);
- os << ")";
+ d_registrationCache.insert(term);
+ return;
+ }
+
+ if (!supportedTheory(theory_id)) return;
+
+ getTheoryProof(theory_id)->registerTerm(term);
+ d_registrationCache.insert(term);
+}
+
+theory::TheoryId TheoryProofEngine::getTheoryForLemma(ClauseId id) {
+ // TODO: now CNF proof has a map from formula to proof rule
+ // that should be checked to figure out what theory is responsible for this
+ ProofManager* pm = ProofManager::currentPM();
+
+ if (pm->getLogic() == "QF_UF") return theory::THEORY_UF;
+ if (pm->getLogic() == "QF_BV") return theory::THEORY_BV;
+ if (pm->getLogic() == "ALL_SUPPORTED") return theory::THEORY_BV;
+ Unreachable();
+}
+
+void LFSCTheoryProofEngine::bind(Expr term, LetMap& map, Bindings& let_order) {
+ LetMap::iterator it = map.find(term);
+ if (it != map.end()) {
+ LetCount& count = it->second;
+ count.increment();
+ return;
+ }
+ for (unsigned i = 0; i < term.getNumChildren(); ++i) {
+ bind(term[i], map, let_order);
+ }
+ unsigned new_id = LetCount::newId();
+ map[term] = LetCount(new_id);
+ let_order.push_back(LetOrderElement(term, new_id));
+}
+
+void LFSCTheoryProofEngine::printLetTerm(Expr term, std::ostream& os) {
+ LetMap map;
+ Bindings let_order;
+ bind(term, map, let_order);
+ std::ostringstream paren;
+ for (unsigned i = 0; i < let_order.size(); ++i) {
+ Expr current_expr = let_order[i].expr;
+ unsigned let_id = let_order[i].id;
+ LetMap::const_iterator it = map.find(current_expr);
+ Assert (it != map.end());
+ unsigned let_count = it->second.count;
+ Assert(let_count);
+ // skip terms that only appear once
+ if (let_count <= LET_COUNT) {
+ continue;
}
- if(term.getType().isBoolean()) {
- os << ")";
+
+ os << "(@ let"<<let_id << " ";
+ printTheoryTerm(current_expr, os, map);
+ paren <<")";
+ }
+ unsigned last_let_id = let_order.back().id;
+ Expr last = let_order.back().expr;
+ unsigned last_count = map.find(last)->second.count;
+ if (last_count <= LET_COUNT) {
+ printTheoryTerm(last, os, map);
+ }
+ else {
+ os << " let"<< last_let_id;
+ }
+ os << paren.str();
+}
+
+
+void LFSCTheoryProofEngine::printTheoryTerm(Expr term, std::ostream& os, const LetMap& map) {
+ theory::TheoryId theory_id = theory::Theory::theoryOf(term);
+ // boolean terms and ITEs are special because they
+ // are common to all theories
+ if (theory_id == theory::THEORY_BUILTIN ||
+ term.getKind() == kind::ITE ||
+ term.getKind() == kind::EQUAL) {
+ printCoreTerm(term, os, map);
+ return;
+ }
+ // dispatch to proper theory
+ getTheoryProof(theory_id)->printTerm(term, os, map);
+}
+
+void LFSCTheoryProofEngine::printSort(Type type, std::ostream& os) {
+ if (type.isSort()) {
+ getTheoryProof(theory::THEORY_UF)->printSort(type, os);
+ return;
+ }
+ if (type.isBitVector()) {
+ getTheoryProof(theory::THEORY_BV)->printSort(type, os);
+ return;
+ }
+
+ if (type.isArray()) {
+ getTheoryProof(theory::THEORY_ARRAY)->printSort(type, os);
+ return;
+ }
+ Unreachable();
+}
+
+void LFSCTheoryProofEngine::printAssertions(std::ostream& os, std::ostream& paren) {
+ unsigned counter = 0;
+ ProofManager::assertions_iterator it = ProofManager::currentPM()->begin_assertions();
+ ProofManager::assertions_iterator end = ProofManager::currentPM()->end_assertions();
+
+ // collect declarations first
+ for(; it != end; ++it) {
+ registerTerm(*it);
+ }
+ printDeclarations(os, paren);
+
+ it = ProofManager::currentPM()->begin_assertions();
+ for (; it != end; ++it) {
+ // FIXME: merge this with counter
+ os << "(% A" << counter++ << " (th_holds ";
+ printLetTerm(*it, os);
+ os << ")\n";
+ paren << ")";
+ }
+ //store map between assertion and counter
+ // ProofManager::currentPM()->setAssertion( *it );
+}
+
+void LFSCTheoryProofEngine::printDeclarations(std::ostream& os, std::ostream& paren) {
+ TheoryProofTable::const_iterator it = d_theoryProofTable.begin();
+ TheoryProofTable::const_iterator end = d_theoryProofTable.end();
+ for (; it != end; ++it) {
+ it->second->printDeclarations(os, paren);
+ }
+}
+
+void LFSCTheoryProofEngine::printTheoryLemmas(const IdToSatClause& lemmas,
+ std::ostream& os,
+ std::ostream& paren) {
+ os << " ;; Theory Lemmas \n";
+ ProofManager* pm = ProofManager::currentPM();
+ IdToSatClause::const_iterator it = lemmas.begin();
+ IdToSatClause::const_iterator end = lemmas.end();
+
+ // BitVector theory is special case: must know all
+ // conflicts needed ahead of time for resolution
+ // proof lemmas
+ std::vector<Expr> bv_lemmas;
+ for (; it != end; ++it) {
+ ClauseId id = it->first;
+ const prop::SatClause* clause = it->second;
+
+ theory::TheoryId theory_id = getTheoryForLemma(id);
+ if (theory_id != theory::THEORY_BV) continue;
+
+ std::vector<Expr> conflict;
+ for(unsigned i = 0; i < clause->size(); ++i) {
+ prop::SatLiteral lit = (*clause)[i];
+ Expr atom = pm->getCnfProof()->getAtom(lit.getSatVariable()).toExpr();
+ if (atom.isConst()) {
+ Assert (atom == utils::mkTrue() ||
+ (atom == utils::mkFalse() && lit.isNegated()));
+ continue;
+ }
+ Expr expr_lit = lit.isNegated() ? atom.notExpr() : atom;
+ conflict.push_back(expr_lit);
+ }
+ bv_lemmas.push_back(utils::mkSortedExpr(kind::OR, conflict));
+ }
+ // FIXME: ugly, move into bit-vector proof by adding lemma
+ // queue inside each theory_proof
+ BitVectorProof* bv = ProofManager::getBitVectorProof();
+ bv->finalizeConflicts(bv_lemmas);
+
+ bv->printResolutionProof(os, paren);
+
+ if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
+ Assert (lemmas.size() == 1);
+ // nothing more to do (no combination with eager so far)
+ return;
+ }
+
+ it = lemmas.begin();
+
+ for (; it != end; ++it) {
+ ClauseId id = it->first;
+ const prop::SatClause* clause = it->second;
+ // printing clause as it appears in resolution proof
+ os << "(satlem _ _ ";
+ std::ostringstream clause_paren;
+ pm->getCnfProof()->printClause(*clause, os, clause_paren);
+
+ std::vector<Expr> clause_expr;
+ for(unsigned i = 0; i < clause->size(); ++i) {
+ prop::SatLiteral lit = (*clause)[i];
+ Expr atom = pm->getCnfProof()->getAtom(lit.getSatVariable()).toExpr();
+ if (atom.isConst()) {
+ Assert (atom == utils::mkTrue());
+ continue;
+ }
+ Expr expr_lit = lit.isNegated() ? atom.notExpr(): atom;
+ clause_expr.push_back(expr_lit);
}
+
+ // query appropriate theory for proof of clause
+ theory::TheoryId theory_id = getTheoryForLemma(id);
+ Debug("theory-proof-debug") << ";; Get theory lemma from " << theory_id << "..." << std::endl;
+ getTheoryProof(theory_id)->printTheoryLemmaProof(clause_expr, os, paren);
+ // os << " (clausify_false trust)";
+ os << clause_paren.str();
+ os << "( \\ " << pm->getLemmaClauseName(id) <<"\n";
+ paren << "))";
+ }
+}
+
+void LFSCTheoryProofEngine::printBoundTerm(Expr term, std::ostream& os, const LetMap& map) {
+ LetMap::const_iterator it = map.find(term);
+ Assert (it != map.end());
+ unsigned id = it->second.id;
+ unsigned count = it->second.count;
+ if (count > LET_COUNT) {
+ os <<"let"<<id;
+ return;
+ }
+ printTheoryTerm(term, os, map);
+}
+
+void LFSCTheoryProofEngine::printCoreTerm(Expr term, std::ostream& os, const LetMap& map) {
+ if (term.isVariable()) {
+ os << ProofManager::sanitize(term);
return;
}
+ Kind k = term.getKind();
+
+ switch(k) {
case kind::ITE:
- os << (term.getType().isBoolean() ? "(ifte " : "(ite _ ");
- printTerm(term[0], os);
+ os << (term.getType().isBoolean() ? "(ifte ": "(ite _ ");
+
+ printBoundTerm(term[0], os, map);
os << " ";
- printTerm(term[1], os);
+ printBoundTerm(term[1], os, map);
os << " ";
- printTerm(term[2], os);
+ printBoundTerm(term[2], os, map);
os << ")";
return;
case kind::EQUAL:
os << "(";
os << "= ";
- os << term[0].getType() << " ";
- printTerm(term[0], os);
+ printSort(term[0].getType(), os);
+ printBoundTerm(term[0], os, map);
os << " ";
- printTerm(term[1], os);
+ printBoundTerm(term[1], os, map);
os << ")";
return;
case kind::DISTINCT:
- os << "(not (= ";
- os << term[0].getType() << " ";
- printTerm(term[0], os);
- os << " ";
- printTerm(term[1], os);
- os << "))";
- return;
+ // Distinct nodes can have any number of chidlren.
+ Assert (term.getNumChildren() >= 2);
- case kind::OR:
- case kind::AND:
- case kind::XOR:
- case kind::IFF:
- case kind::IMPLIES:
- case kind::NOT:
- // print the Boolean operators
- os << "(" << toLFSCKind(k);
- if(term.getNumChildren() > 2) {
- // LFSC doesn't allow declarations with variable numbers of
- // arguments, so we have to flatten these N-ary versions.
- std::ostringstream paren;
+ if (term.getNumChildren() == 2) {
+ os << "(not (= ";
+ printSort(term[0].getType(), os);
+ printBoundTerm(term[0], os, map);
os << " ";
- for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- printTerm(term[i], os);
- os << " ";
- if(i < term.getNumChildren() - 2) {
- os << "(" << toLFSCKind(k) << " ";
- paren << ")";
- }
- }
- os << paren.str() << ")";
+ printBoundTerm(term[1], os, map);
+ os << "))";
} else {
- // this is for binary and unary operators
+ unsigned numOfPairs = term.getNumChildren() * (term.getNumChildren() - 1) / 2;
+ for (unsigned i = 1; i < numOfPairs; ++i) {
+ os << "(and ";
+ }
+
for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- os << " ";
- printTerm(term[i], os);
+ for (unsigned j = i + 1; j < term.getNumChildren(); ++j) {
+ if ((i != 0) || (j != 1)) {
+ os << "(not (= ";
+ printSort(term[0].getType(), os);
+ printBoundTerm(term[i], os, map);
+ os << " ";
+ printBoundTerm(term[j], os, map);
+ os << ")))";
+ } else {
+ os << "(not (= ";
+ printSort(term[0].getType(), os);
+ printBoundTerm(term[0], os, map);
+ os << " ";
+ printBoundTerm(term[1], os, map);
+ os << "))";
+ }
+ }
}
- os << ")";
}
- return;
- case kind::CONST_BOOLEAN:
- os << (term.getConst<bool>() ? "true" : "false");
return;
case kind::CHAIN: {
@@ -164,13 +474,13 @@ void LFSCTheoryProof::printTerm(Expr term, std::ostream& os) {
std::ostringstream paren;
for(size_t i = 1; i < n; ++i) {
if(i + 1 < n) {
- os << "(" << toLFSCKind(kind::AND) << " ";
+ os << "(" << utils::toLFSCKind(kind::AND) << " ";
paren << ")";
}
- os << "(" << toLFSCKind(op) << " ";
- printTerm(term[i - 1], os);
+ os << "(" << utils::toLFSCKind(op) << " ";
+ printBoundTerm(term[i - 1], os, map);
os << " ";
- printTerm(term[i], os);
+ printBoundTerm(term[i], os, map);
os << ")";
if(i + 1 < n) {
os << " ";
@@ -184,66 +494,144 @@ void LFSCTheoryProof::printTerm(Expr term, std::ostream& os) {
Unhandled(k);
}
- Unreachable();
}
-void LFSCTheoryProof::printAssertions(std::ostream& os, std::ostream& paren) {
- ProofManager::assertions_iterator it = ProofManager::currentPM()->begin_assertions();
- ProofManager::assertions_iterator end = ProofManager::currentPM()->end_assertions();
-
- // collect declarations first
- for(; it != end; ++it) {
- addDeclaration(*it);
+void TheoryProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren) {
+ //default method for replaying proofs: assert (negated) literals back to a fresh copy of the theory
+ Assert( d_theory!=NULL );
+ context::UserContext fakeContext;
+ ProofOutputChannel oc;
+ theory::Valuation v(NULL);
+ //make new copy of theory
+ theory::Theory* th;
+ Trace("theory-proof-debug") << ";; Print theory lemma proof, theory id = " << d_theory->getId() << std::endl;
+ if(d_theory->getId()==theory::THEORY_UF) {
+ th = new theory::uf::TheoryUF(&fakeContext, &fakeContext, oc, v,
+ ProofManager::currentPM()->getLogicInfo(),
+ ProofManager::currentPM()->getTheoryProofEngine()->d_globals,
+ "replay::");
+ } else if(d_theory->getId()==theory::THEORY_ARRAY) {
+ th = new theory::arrays::TheoryArrays(&fakeContext, &fakeContext, oc, v,
+ ProofManager::currentPM()->getLogicInfo(),
+ ProofManager::currentPM()->getTheoryProofEngine()->d_globals,
+ "replay::");
+ } else {
+ InternalError(std::string("can't generate theory-proof for ") + ProofManager::currentPM()->getLogic());
}
- printDeclarations(os, paren);
-
- it = ProofManager::currentPM()->begin_assertions();
- for (; it != end; ++it) {
- os << "(% A" << ProofManager::currentPM()->getAssertionCounter() << " (th_holds ";
- printTerm(*it, os);
- os << ")\n";
- paren << ")";
- //store map between assertion and counter
- ProofManager::currentPM()->setAssertion( *it );
+ th->produceProofs();
+ MyPreRegisterVisitor preRegVisitor(th);
+ for( unsigned i=0; i<lemma.size(); i++ ){
+ Node lit = Node::fromExpr( lemma[i] ).negate();
+ Trace("theory-proof-debug") << "; preregistering and asserting " << lit << std::endl;
+ NodeVisitor<MyPreRegisterVisitor>::run(preRegVisitor, lit);
+ th->assertFact(lit, false);
+ }
+ th->check(theory::Theory::EFFORT_FULL);
+ if(oc.d_conflict.isNull()) {
+ Trace("theory-proof-debug") << "; conflict is null" << std::endl;
+ Assert(!oc.d_lemma.isNull());
+ Trace("theory-proof-debug") << "; ++ but got lemma: " << oc.d_lemma << std::endl;
+ Trace("theory-proof-debug") << "; asserting " << oc.d_lemma[1].negate() << std::endl;
+ th->assertFact(oc.d_lemma[1].negate(), false);
+ th->check(theory::Theory::EFFORT_FULL);
}
+ oc.d_proof->toStream(os);
+ delete th;
}
-void LFSCTheoryProof::printDeclarations(std::ostream& os, std::ostream& paren) {
- // declaring the sorts
- for (SortSet::const_iterator it = d_sortDeclarations.begin(); it != d_sortDeclarations.end(); ++it) {
- os << "(% " << *it << " sort\n";
- paren << ")";
+bool TheoryProofEngine::supportedTheory(theory::TheoryId id) {
+ return (id == theory::THEORY_ARRAY ||
+ id == theory::THEORY_BV ||
+ id == theory::THEORY_UF ||
+ id == theory::THEORY_BOOL);
+}
+
+BooleanProof::BooleanProof(TheoryProofEngine* proofEngine)
+ : TheoryProof(NULL, proofEngine)
+{}
+
+void BooleanProof::registerTerm(Expr term) {
+ Assert (term.getType().isBoolean());
+
+ if (term.isVariable() && d_declarations.find(term) == d_declarations.end()) {
+ d_declarations.insert(term);
+ return;
+ }
+ for (unsigned i = 0; i < term.getNumChildren(); ++i) {
+ d_proofEngine->registerTerm(term[i]);
}
+}
- // declaring the terms
- for (ExprSet::const_iterator it = d_termDeclarations.begin(); it != d_termDeclarations.end(); ++it) {
- Expr term = *it;
+void LFSCBooleanProof::printTerm(Expr term, std::ostream& os, const LetMap& map) {
+ Assert (term.getType().isBoolean());
+ if (term.isVariable()) {
+ os << "(p_app " << ProofManager::sanitize(term) <<")";
+ return;
+ }
- os << "(% " << term << " ";
- os << "(term ";
-
- Type type = term.getType();
- if (type.isFunction()) {
- std::ostringstream fparen;
- FunctionType ftype = (FunctionType)type;
- std::vector<Type> args = ftype.getArgTypes();
- args.push_back(ftype.getRangeType());
- os << "(arrow";
- for (unsigned i = 0; i < args.size(); i++) {
- Type arg_type = args[i];
- //Assert (arg_type.isSort() || arg_type.isBoolean());
- os << " " << arg_type;
- if (i < args.size() - 2) {
- os << " (arrow";
- fparen << ")";
+ Kind k = term.getKind();
+ switch(k) {
+ case kind::OR:
+ case kind::AND:
+ case kind::XOR:
+ case kind::IFF:
+ case kind::IMPLIES:
+ case kind::NOT:
+ // print the Boolean operators
+ os << "(" << utils::toLFSCKind(k);
+ if(term.getNumChildren() > 2) {
+ // LFSC doesn't allow declarations with variable numbers of
+ // arguments, so we have to flatten these N-ary versions.
+ std::ostringstream paren;
+ os << " ";
+ for (unsigned i = 0; i < term.getNumChildren(); ++i) {
+ d_proofEngine->printBoundTerm(term[i], os, map);
+ os << " ";
+ if(i < term.getNumChildren() - 2) {
+ os << "(" << utils::toLFSCKind(k) << " ";
+ paren << ")";
}
}
- os << fparen.str() << "))\n";
+ os << paren.str() << ")";
} else {
- Assert (term.isVariable());
- //Assert (type.isSort() || type.isBoolean());
- os << type << ")\n";
+ // this is for binary and unary operators
+ for (unsigned i = 0; i < term.getNumChildren(); ++i) {
+ os << " ";
+ d_proofEngine->printBoundTerm(term[i], os, map);
+ }
+ os << ")";
}
- paren << ")";
+ return;
+
+ case kind::CONST_BOOLEAN:
+ os << (term.getConst<bool>() ? "true" : "false");
+ return;
+
+ default:
+ Unhandled(k);
}
+
}
+
+void LFSCBooleanProof::printSort(Type type, std::ostream& os) {
+ Assert (type.isBoolean());
+ os << "Bool";
+}
+void LFSCBooleanProof::printDeclarations(std::ostream& os, std::ostream& paren) {
+ for (ExprSet::const_iterator it = d_declarations.begin(); it != d_declarations.end(); ++it) {
+ Expr term = *it;
+
+ os << "(% " << ProofManager::sanitize(term) << " (term ";
+ printSort(term.getType(), os);
+ os <<")\n";
+ paren <<")";
+ }
+}
+
+void LFSCBooleanProof::printTheoryLemmaProof(std::vector<Expr>& lemma,
+ std::ostream& os,
+ std::ostream& paren) {
+ Unreachable("No boolean lemmas yet!");
+}
+
+} /* namespace CVC4 */
diff --git a/src/proof/theory_proof.h b/src/proof/theory_proof.h
index 375ec8205..3d700c388 100644
--- a/src/proof/theory_proof.h
+++ b/src/proof/theory_proof.h
@@ -1,56 +1,260 @@
/********************* */
/*! \file theory_proof.h
- ** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief A manager for UfProofs.
- **
- ** A manager for UfProofs.
- **
- **
- **/
+** \verbatim
+** Original author: Liana Hadarean
+** Major contributors: Morgan Deters
+** Minor contributors (to current version): none
+** This file is part of the CVC4 project.
+** Copyright (c) 2009-2014 New York University and The University of Iowa
+** See the file COPYING in the top-level source directory for licensing
+** information.\endverbatim
+**
+** \brief A manager for UfProofs.
+**
+** A manager for UfProofs.
+**
+**
+**/
#include "cvc4_private.h"
#ifndef __CVC4__THEORY_PROOF_H
#define __CVC4__THEORY_PROOF_H
+#include "util/proof.h"
+#include "expr/expr.h"
+#include "prop/sat_solver_types.h"
#include <ext/hash_set>
#include <iosfwd>
-#include "expr/expr.h"
-#include "util/proof.h"
namespace CVC4 {
- typedef __gnu_cxx::hash_set<Type, TypeHashFunction > SortSet;
- typedef __gnu_cxx::hash_set<Expr, ExprHashFunction > ExprSet;
-
- class TheoryProof {
- protected:
- ExprSet d_termDeclarations;
- SortSet d_sortDeclarations;
- ExprSet d_declarationCache;
-
- public:
- TheoryProof();
- virtual ~TheoryProof() {}
- virtual void printAssertions(std::ostream& os, std::ostream& paren) = 0;
- void addDeclaration(Expr atom);
- };
-
- class LFSCTheoryProof : public TheoryProof {
- void printDeclarations(std::ostream& os, std::ostream& paren);
- public:
- static void printTerm(Expr term, std::ostream& os);
- virtual void printAssertions(std::ostream& os, std::ostream& paren);
- };
+class SmtGlobals;
+
+namespace theory {
+class Theory;
+}
+
+typedef unsigned ClauseId;
+
+struct LetCount {
+ static unsigned counter;
+ static void resetCounter() { counter = 0; }
+ static unsigned newId() { return ++counter; }
+
+ unsigned count;
+ unsigned id;
+ LetCount()
+ : count(0)
+ , id(-1)
+ {}
+
+ void increment() { ++count; }
+ LetCount(unsigned i)
+ : count(1)
+ , id(i)
+ {}
+ LetCount(const LetCount& other)
+ : count(other.count)
+ , id (other.id)
+ {}
+ bool operator==(const LetCount &other) const {
+ return other.id == id && other.count == count;
+ }
+ LetCount& operator=(const LetCount &rhs) {
+ if (&rhs == this) return *this;
+ id = rhs.id;
+ count = rhs.count;
+ return *this;
+ }
+};
+
+struct LetOrderElement {
+ Expr expr;
+ unsigned id;
+ LetOrderElement(Expr e, unsigned i)
+ : expr(e)
+ , id(i)
+ {}
+
+ LetOrderElement()
+ : expr()
+ , id(-1)
+ {}
+};
+
+typedef __gnu_cxx::hash_map < ClauseId, prop::SatClause* > IdToSatClause;
+
+typedef __gnu_cxx::hash_map<Expr, LetCount, ExprHashFunction> LetMap;
+typedef std::vector<LetOrderElement> Bindings;
+
+class TheoryProof;
+typedef unsigned ClauseId;
+
+typedef __gnu_cxx::hash_set<Expr, ExprHashFunction > ExprSet;
+typedef std::map<theory::TheoryId, TheoryProof* > TheoryProofTable;
+
+class TheoryProofEngine {
+protected:
+ ExprSet d_registrationCache;
+ TheoryProofTable d_theoryProofTable;
+
+ /**
+ * Returns whether the theory is currently supported in proof
+ * production mode.
+ */
+ bool supportedTheory(theory::TheoryId id);
+public:
+ SmtGlobals* d_globals;
+
+ TheoryProofEngine(SmtGlobals* globals);
+ virtual ~TheoryProofEngine();
+ /**
+ * Print the theory term (could be atom) by delegating to the
+ * proper theory
+ *
+ * @param term
+ * @param os
+ *
+ * @return
+ */
+ virtual void printLetTerm(Expr term, std::ostream& os) = 0;
+ virtual void printBoundTerm(Expr term, std::ostream& os, const LetMap& map) = 0;
+ /**
+ * Print the proof representation of the given sort.
+ *
+ * @param os
+ */
+ virtual void printSort(Type type, std::ostream& os) = 0;
+ /**
+ * Print the theory assertions (arbitrary formulas over
+ * theory atoms)
+ *
+ * @param os
+ * @param paren closing parenthesis
+ */
+ virtual void printAssertions(std::ostream& os, std::ostream& paren) = 0;
+ /**
+ * Print proofs of all the theory lemmas (must prove
+ * actual clause used in resolution proof).
+ *
+ * @param os
+ * @param paren
+ */
+ virtual void printTheoryLemmas(const IdToSatClause& lemmas,
+ std::ostream& os,
+ std::ostream& paren) = 0;
+ /**
+ * Register theory atom (ensures all terms and atoms are declared).
+ *
+ * @param atom
+ */
+ void registerTerm(Expr atom);
+ /**
+ * Ensures that a theory proof class for the given theory
+ * is created.
+ *
+ * @param theory
+ */
+ void registerTheory(theory::Theory* theory);
+ theory::TheoryId getTheoryForLemma(ClauseId id);
+ TheoryProof* getTheoryProof(theory::TheoryId id);
+};
+
+class LFSCTheoryProofEngine : public TheoryProofEngine {
+ LetMap d_letMap;
+ void printTheoryTerm(Expr term, std::ostream& os, const LetMap& map);
+ void bind(Expr term, LetMap& map, Bindings& let_order);
+public:
+ LFSCTheoryProofEngine(SmtGlobals* globals)
+ : TheoryProofEngine(globals) {}
+
+ void printDeclarations(std::ostream& os, std::ostream& paren);
+ virtual void printCoreTerm(Expr term, std::ostream& os, const LetMap& map);
+ virtual void printLetTerm(Expr term, std::ostream& os);
+ virtual void printBoundTerm(Expr term, std::ostream& os, const LetMap& map);
+ virtual void printAssertions(std::ostream& os, std::ostream& paren);
+ virtual void printTheoryLemmas(const IdToSatClause& lemmas,
+ std::ostream& os,
+ std::ostream& paren);
+ virtual void printSort(Type type, std::ostream& os);
+};
+
+class TheoryProof {
+protected:
+ // Pointer to the theory for this proof
+ theory::Theory* d_theory;
+ TheoryProofEngine* d_proofEngine;
+public:
+ TheoryProof(theory::Theory* th, TheoryProofEngine* proofEngine)
+ : d_theory(th)
+ , d_proofEngine(proofEngine)
+ {}
+ virtual ~TheoryProof() {};
+ /**
+ * Print a term belonging to this theory.
+ *
+ * @param term expresion representing term
+ * @param os output stream
+ */
+ virtual void printTerm(Expr term, std::ostream& os, const LetMap& map) = 0;
+ /**
+ * Print the proof representation of the given type.
+ *
+ * @param type
+ * @param os
+ */
+ virtual void printSort(Type type, std::ostream& os) = 0;
+ /**
+ * Print a proof for the theory lemmas. Must prove
+ * clause representing lemmas to be used in resolution proof.
+ *
+ * @param os output stream
+ */
+ virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren);
+ /**
+ * Print the variable/sorts declarations for this theory.
+ *
+ * @param os
+ * @param paren
+ */
+ virtual void printDeclarations(std::ostream& os, std::ostream& paren) = 0;
+ /**
+ * Register a term of this theory that appears in the proof.
+ *
+ * @param term
+ */
+ virtual void registerTerm(Expr term) = 0;
+};
+
+class BooleanProof : public TheoryProof {
+protected:
+ ExprSet d_declarations; // all the boolean variables
+public:
+ BooleanProof(TheoryProofEngine* proofEngine);
+
+ virtual void registerTerm(Expr term);
+
+ virtual void printTerm(Expr term, std::ostream& os, const LetMap& map) = 0;
+
+ virtual void printSort(Type type, std::ostream& os) = 0;
+ virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren) = 0;
+ virtual void printDeclarations(std::ostream& os, std::ostream& paren) = 0;
+};
+
+class LFSCBooleanProof : public BooleanProof {
+public:
+ LFSCBooleanProof(TheoryProofEngine* proofEngine)
+ : BooleanProof(proofEngine)
+ {}
+ virtual void printTerm(Expr term, std::ostream& os, const LetMap& map);
+ virtual void printSort(Type type, std::ostream& os);
+ virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren);
+ virtual void printDeclarations(std::ostream& os, std::ostream& paren);
+};
+
+
} /* CVC4 namespace */
#endif /* __CVC4__THEORY_PROOF_H */
diff --git a/src/proof/uf_proof.cpp b/src/proof/uf_proof.cpp
new file mode 100644
index 000000000..ec0d90ae7
--- /dev/null
+++ b/src/proof/uf_proof.cpp
@@ -0,0 +1,804 @@
+/********************* */
+/*! \file uf_proof.cpp
+** \verbatim
+** Original author: Liana Hadarean
+** Major contributors: none
+** Minor contributors (to current version): none
+** This file is part of the CVC4 project.
+** Copyright (c) 2009-2014 New York University and The University of Iowa
+** See the file COPYING in the top-level source directory for licensing
+** information.\endverbatim
+**
+** \brief [[ Add one-line brief description here ]]
+**
+** [[ Add lengthier description here ]]
+** \todo document this file
+**/
+
+#include "proof/theory_proof.h"
+#include "proof/proof_manager.h"
+#include "proof/uf_proof.h"
+#include "theory/uf/theory_uf.h"
+#include <stack>
+
+using namespace CVC4;
+using namespace CVC4::theory;
+using namespace CVC4::theory::uf;
+
+
+inline static Node eqNode(TNode n1, TNode n2) {
+ return NodeManager::currentNM()->mkNode(n1.getType().isBoolean() ? kind::IFF : kind::EQUAL, n1, n2);
+}
+
+// congrence matching term helper
+inline static bool match(TNode n1, TNode n2) {
+ Debug("mgd") << "match " << n1 << " " << n2 << std::endl;
+ if(ProofManager::currentPM()->hasOp(n1)) {
+ n1 = ProofManager::currentPM()->lookupOp(n1);
+ }
+ if(ProofManager::currentPM()->hasOp(n2)) {
+ n2 = ProofManager::currentPM()->lookupOp(n2);
+ }
+ Debug("mgd") << "+ match " << n1 << " " << n2 << std::endl;
+ if(n1 == n2) {
+ return true;
+ }
+ if(n1.getType().isFunction() && n2.hasOperator()) {
+ if(ProofManager::currentPM()->hasOp(n2.getOperator())) {
+ return n1 == ProofManager::currentPM()->lookupOp(n2.getOperator());
+ } else {
+ return n1 == n2.getOperator();
+ }
+ }
+ if(n2.getType().isFunction() && n1.hasOperator()) {
+ if(ProofManager::currentPM()->hasOp(n1.getOperator())) {
+ return n2 == ProofManager::currentPM()->lookupOp(n1.getOperator());
+ } else {
+ return n2 == n1.getOperator();
+ }
+ }
+ if(n1.hasOperator() && n2.hasOperator() && n1.getOperator() != n2.getOperator()) {
+ return false;
+ }
+ for(size_t i = 0; i < n1.getNumChildren() && i < n2.getNumChildren(); ++i) {
+ if(n1[i] != n2[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+void ProofUF::toStream(std::ostream& out) {
+ Trace("theory-proof-debug") << "; Print UF proof..." << std::endl;
+ //AJR : carry this further?
+ LetMap map;
+ toStreamLFSC(out, ProofManager::getUfProof(), d_proof, map);
+}
+
+void ProofUF::toStreamLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, const LetMap& map) {
+ Debug("lfsc-uf") << "Printing uf proof in LFSC : " << std::endl;
+ pf->debug_print("lfsc-uf");
+ Debug("lfsc-uf") << std::endl;
+ toStreamRecLFSC( out, tp, pf, 0, map );
+}
+
+Node ProofUF::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, unsigned tb, const LetMap& map) {
+ Debug("gk::proof") << std::endl << std::endl << "toStreamRecLFSC called. tb = " << tb << " . proof:" << std::endl;
+ pf->debug_print("gk::proof");
+ Debug("gk::proof") << std::endl;
+
+ if(tb == 0) {
+ Assert(pf->d_id == eq::MERGED_THROUGH_TRANS);
+ Assert(!pf->d_node.isNull());
+ Assert(pf->d_children.size() >= 2);
+
+ int neg = -1;
+ theory::eq::EqProof subTrans;
+ subTrans.d_id = eq::MERGED_THROUGH_TRANS;
+ subTrans.d_node = pf->d_node;
+
+ size_t i = 0;
+ while (i < pf->d_children.size()) {
+ // Look for the negative clause, with which we will form a contradiction.
+ if(!pf->d_children[i]->d_node.isNull() && pf->d_children[i]->d_node.getKind() == kind::NOT) {
+ Assert(neg < 0);
+ neg = i;
+ ++i;
+ }
+
+ // Handle congruence closures over equalities.
+ else if (pf->d_children[i]->d_id==eq::MERGED_THROUGH_CONGRUENCE && pf->d_children[i]->d_node.isNull()) {
+ Debug("gk::proof") << "Handling congruence over equalities" << std::endl;
+
+ // Gather the sequence of consecutive congruence closures.
+ std::vector<const theory::eq::EqProof *> congruenceClosures;
+ unsigned count;
+ Debug("gk::proof") << "Collecting congruence sequence" << std::endl;
+ for (count = 0;
+ i + count < pf->d_children.size() &&
+ pf->d_children[i + count]->d_id==eq::MERGED_THROUGH_CONGRUENCE &&
+ pf->d_children[i + count]->d_node.isNull();
+ ++count) {
+ Debug("gk::proof") << "Found a congruence: " << std::endl;
+ pf->d_children[i+count]->debug_print("gk::proof");
+ congruenceClosures.push_back(pf->d_children[i+count]);
+ }
+
+ Debug("gk::proof") << "Total number of congruences found: " << congruenceClosures.size() << std::endl;
+
+ // Determine if the "target" of the congruence sequence appears right before or right after the sequence.
+ bool targetAppearsBefore = true;
+ bool targetAppearsAfter = true;
+
+ if ((i == 0) || (i == 1 && neg == 0)) {
+ Debug("gk::proof") << "Target does not appear before" << std::endl;
+ targetAppearsBefore = false;
+ }
+
+ if ((i + count >= pf->d_children.size()) ||
+ (!pf->d_children[i + count]->d_node.isNull() &&
+ pf->d_children[i + count]->d_node.getKind() == kind::NOT)) {
+ Debug("gk::proof") << "Target does not appear after" << std::endl;
+ targetAppearsAfter = false;
+ }
+
+ // Assert that we have precisely one target clause.
+ Assert(targetAppearsBefore != targetAppearsAfter);
+
+ // Begin breaking up the congruences and ordering the equalities correctly.
+ std::vector<theory::eq::EqProof *> orderedEqualities;
+
+
+ // Insert target clause first.
+ if (targetAppearsBefore) {
+ orderedEqualities.push_back(pf->d_children[i - 1]);
+ // The target has already been added to subTrans; remove it.
+ subTrans.d_children.pop_back();
+ } else {
+ orderedEqualities.push_back(pf->d_children[i + count]);
+ }
+
+ // Start with the congruence closure closest to the target clause, and work our way back/forward.
+ if (targetAppearsBefore) {
+ for (unsigned j = 0; j < count; ++j) {
+ if (pf->d_children[i + j]->d_children[0]->d_id != eq::MERGED_THROUGH_REFLEXIVITY)
+ orderedEqualities.insert(orderedEqualities.begin(), pf->d_children[i + j]->d_children[0]);
+ if (pf->d_children[i + j]->d_children[1]->d_id != eq::MERGED_THROUGH_REFLEXIVITY)
+ orderedEqualities.insert(orderedEqualities.end(), pf->d_children[i + j]->d_children[1]);
+ }
+ } else {
+ for (unsigned j = 0; j < count; ++j) {
+ if (pf->d_children[i + count - 1 - j]->d_children[0]->d_id != eq::MERGED_THROUGH_REFLEXIVITY)
+ orderedEqualities.insert(orderedEqualities.begin(), pf->d_children[i + count - 1 - j]->d_children[0]);
+ if (pf->d_children[i + count - 1 - j]->d_children[1]->d_id != eq::MERGED_THROUGH_REFLEXIVITY)
+ orderedEqualities.insert(orderedEqualities.end(), pf->d_children[i + count - 1 - j]->d_children[1]);
+ }
+ }
+
+ // Copy the result into the main transitivity proof.
+ subTrans.d_children.insert(subTrans.d_children.end(), orderedEqualities.begin(), orderedEqualities.end());
+
+ // Increase i to skip over the children that have been processed.
+ i += count;
+ if (targetAppearsAfter) {
+ ++i;
+ }
+ }
+
+ // Else, just copy the child proof as is
+ else {
+ subTrans.d_children.push_back(pf->d_children[i]);
+ ++i;
+ }
+ }
+ Assert(neg >= 0);
+
+ Node n1;
+ std::stringstream ss;
+ //Assert(subTrans.d_children.size() == pf->d_children.size() - 1);
+ Debug("mgdx") << "\nsubtrans has " << subTrans.d_children.size() << " children\n";
+ if(pf->d_children.size() > 2) {
+ n1 = toStreamRecLFSC(ss, tp, &subTrans, 1, map);
+ } else {
+ n1 = toStreamRecLFSC(ss, tp, subTrans.d_children[0], 1, map);
+ Debug("mgdx") << "\nsubTrans unique child " << subTrans.d_children[0]->d_id << " was proven\ngot: " << n1 << std::endl;
+ }
+
+ Node n2 = pf->d_children[neg]->d_node;
+ Assert(n2.getKind() == kind::NOT);
+ out << "(clausify_false (contra _ ";
+ Debug("mgdx") << "\nhave proven: " << n1 << std::endl;
+ Debug("mgdx") << "n2 is " << n2[0] << std::endl;
+
+ if (n2[0].getNumChildren() > 0) { Debug("mgdx") << "\nn2[0]: " << n2[0][0] << std::endl; }
+ if (n1.getNumChildren() > 1) { Debug("mgdx") << "n1[1]: " << n1[1] << std::endl; }
+
+ if(n2[0].getKind() == kind::APPLY_UF) {
+ out << "(trans _ _ _ _ ";
+ out << "(symm _ _ _ ";
+ out << ss.str();
+ out << ") (pred_eq_f _ " << ProofManager::getLitName(n2[0]) << ")) t_t_neq_f))" << std::endl;
+ } else {
+ Assert((n1[0] == n2[0][0] && n1[1] == n2[0][1]) || (n1[1] == n2[0][0] && n1[0] == n2[0][1]));
+ if(n1[1] == n2[0][0]) {
+ out << "(symm _ _ _ " << ss.str() << ")";
+ } else {
+ out << ss.str();
+ }
+ out << " " << ProofManager::getLitName(n2[0]) << "))" << std::endl;
+ }
+ return Node();
+ }
+
+ switch(pf->d_id) {
+ case eq::MERGED_THROUGH_CONGRUENCE: {
+ Debug("mgd") << "\nok, looking at congruence:\n";
+ pf->debug_print("mgd");
+ std::stack<const theory::eq::EqProof*> stk;
+ for(const theory::eq::EqProof* pf2 = pf; pf2->d_id == eq::MERGED_THROUGH_CONGRUENCE; pf2 = pf2->d_children[0]) {
+ Assert(!pf2->d_node.isNull());
+ Assert(pf2->d_node.getKind() == kind::PARTIAL_APPLY_UF || pf2->d_node.getKind() == kind::BUILTIN || pf2->d_node.getKind() == kind::APPLY_UF || pf2->d_node.getKind() == kind::SELECT || pf2->d_node.getKind() == kind::STORE);
+ Assert(pf2->d_children.size() == 2);
+ out << "(cong _ _ _ _ _ _ ";
+ stk.push(pf2);
+ }
+ Assert(stk.top()->d_children[0]->d_id != eq::MERGED_THROUGH_CONGRUENCE);
+ NodeBuilder<> b1(kind::PARTIAL_APPLY_UF), b2(kind::PARTIAL_APPLY_UF);
+ const theory::eq::EqProof* pf2 = stk.top();
+ stk.pop();
+ Assert(pf2->d_id == eq::MERGED_THROUGH_CONGRUENCE);
+ Node n1 = toStreamRecLFSC(out, tp, pf2->d_children[0], tb + 1, map);
+ out << " ";
+ std::stringstream ss;
+ Node n2 = toStreamRecLFSC(ss, tp, pf2->d_children[1], tb + 1, map);
+ Debug("mgd") << "\nok, in FIRST cong[" << stk.size() << "]" << "\n";
+ pf2->debug_print("mgd");
+ Debug("mgd") << "looking at " << pf2->d_node << "\n";
+ Debug("mgd") << " " << n1 << "\n";
+ Debug("mgd") << " " << n2 << "\n";
+ int side = 0;
+ if(match(pf2->d_node, n1[0])) {
+ //if(tb == 1) {
+ Debug("mgd") << "SIDE IS 0\n";
+ //}
+ side = 0;
+ } else {
+ //if(tb == 1) {
+ Debug("mgd") << "SIDE IS 1\n";
+ //}
+ if(!match(pf2->d_node, n1[1])) {
+ Debug("mgd") << "IN BAD CASE, our first subproof is\n";
+ pf2->d_children[0]->debug_print("mgd");
+ }
+ Assert(match(pf2->d_node, n1[1]));
+ side = 1;
+ }
+ if(n1[side].getKind() == kind::APPLY_UF || n1[side].getKind() == kind::PARTIAL_APPLY_UF || n1[side].getKind() == kind::SELECT || n1[side].getKind() == kind::STORE) {
+ if(n1[side].getKind() == kind::APPLY_UF || n1[side].getKind() == kind::PARTIAL_APPLY_UF) {
+ b1 << n1[side].getOperator();
+ } else {
+ b1 << ProofManager::currentPM()->mkOp(n1[side].getOperator());
+ }
+ b1.append(n1[side].begin(), n1[side].end());
+ } else {
+ b1 << n1[side];
+ }
+ if(n1[1-side].getKind() == kind::PARTIAL_APPLY_UF || n1[1-side].getKind() == kind::APPLY_UF || n1[side].getKind() == kind::SELECT || n1[side].getKind() == kind::STORE) {
+ if(n1[1-side].getKind() == kind::PARTIAL_APPLY_UF || n1[1-side].getKind() == kind::APPLY_UF) {
+ b2 << n1[1-side].getOperator();
+ } else {
+ b2 << ProofManager::currentPM()->mkOp(n1[1-side].getOperator());
+ }
+ b2.append(n1[1-side].begin(), n1[1-side].end());
+ } else {
+ b2 << n1[1-side];
+ }
+ Debug("mgd") << "pf2->d_node " << pf2->d_node << std::endl;
+ Debug("mgd") << "b1.getNumChildren() " << b1.getNumChildren() << std::endl;
+ Debug("mgd") << "n1 " << n1 << std::endl;
+ Debug("mgd") << "n2 " << n2 << std::endl;
+ Debug("mgd") << "side " << side << std::endl;
+ if(pf2->d_node[b1.getNumChildren() - (pf2->d_node.getMetaKind() == kind::metakind::PARAMETERIZED ? 0 : 1)] == n2[side]) {
+ b1 << n2[side];
+ b2 << n2[1-side];
+ out << ss.str();
+ } else {
+ Assert(pf2->d_node[b1.getNumChildren() - (pf2->d_node.getMetaKind() == kind::metakind::PARAMETERIZED ? 0 : 1)] == n2[1-side]);
+ b1 << n2[1-side];
+ b2 << n2[side];
+ out << "(symm _ _ _ " << ss.str() << ")";
+ }
+ out << ")";
+ while(!stk.empty()) {
+ if(tb == 1) {
+ Debug("mgd") << "\nMORE TO DO\n";
+ }
+ pf2 = stk.top();
+ stk.pop();
+ Assert(pf2->d_id == eq::MERGED_THROUGH_CONGRUENCE);
+ out << " ";
+ ss.str("");
+ n2 = toStreamRecLFSC(ss, tp, pf2->d_children[1], tb + 1, map);
+ Debug("mgd") << "\nok, in cong[" << stk.size() << "]" << "\n";
+ Debug("mgd") << "looking at " << pf2->d_node << "\n";
+ Debug("mgd") << " " << n1 << "\n";
+ Debug("mgd") << " " << n2 << "\n";
+ Debug("mgd") << " " << b1 << "\n";
+ Debug("mgd") << " " << b2 << "\n";
+ if(pf2->d_node[b1.getNumChildren()] == n2[side]) {
+ b1 << n2[side];
+ b2 << n2[1-side];
+ out << ss.str();
+ } else {
+ Assert(pf2->d_node[b1.getNumChildren()] == n2[1-side]);
+ b1 << n2[1-side];
+ b2 << n2[side];
+ out << "(symm _ _ _ " << ss.str() << ")";
+ }
+ out << ")";
+ }
+ n1 = b1;
+ n2 = b2;
+ Debug("mgd") << "at end assert, got " << pf2->d_node << " and " << n1 << std::endl;
+ if(pf2->d_node.getKind() == kind::PARTIAL_APPLY_UF) {
+ Assert(n1 == pf2->d_node);
+ }
+ if(n1.getOperator().getType().getNumChildren() == n1.getNumChildren() + 1) {
+ if(ProofManager::currentPM()->hasOp(n1.getOperator())) {
+ b1.clear(ProofManager::currentPM()->lookupOp(n2.getOperator()).getConst<Kind>());
+ } else {
+ b1.clear(kind::APPLY_UF);
+ b1 << n1.getOperator();
+ }
+ b1.append(n1.begin(), n1.end());
+ n1 = b1;
+ Debug("mgd") << "at[2] end assert, got " << pf2->d_node << " and " << n1 << std::endl;
+ if(pf2->d_node.getKind() == kind::APPLY_UF) {
+ Assert(n1 == pf2->d_node);
+ }
+ }
+ if(n2.getOperator().getType().getNumChildren() == n2.getNumChildren() + 1) {
+ if(ProofManager::currentPM()->hasOp(n2.getOperator())) {
+ b2.clear(ProofManager::currentPM()->lookupOp(n2.getOperator()).getConst<Kind>());
+ } else {
+ b2.clear(kind::APPLY_UF);
+ b2 << n2.getOperator();
+ }
+ b2.append(n2.begin(), n2.end());
+ n2 = b2;
+ }
+ Node n = (side == 0 ? eqNode(n1, n2) : eqNode(n2, n1));
+ if(tb == 1) {
+ Debug("mgdx") << "\ncong proved: " << n << "\n";
+ }
+ return n;
+ }
+
+ case eq::MERGED_THROUGH_REFLEXIVITY:
+ Assert(!pf->d_node.isNull());
+ Assert(pf->d_children.empty());
+ out << "(refl _ ";
+ tp->printTerm(NodeManager::currentNM()->toExpr(pf->d_node), out, map);
+ out << ")";
+ return eqNode(pf->d_node, pf->d_node);
+
+ case eq::MERGED_THROUGH_EQUALITY:
+ Assert(!pf->d_node.isNull());
+ Assert(pf->d_children.empty());
+ out << ProofManager::getLitName(pf->d_node.negate());
+ return pf->d_node;
+
+ case eq::MERGED_THROUGH_TRANS: {
+ Assert(!pf->d_node.isNull());
+ Assert(pf->d_children.size() >= 2);
+ std::stringstream ss;
+ Debug("mgd") << "\ndoing trans proof[[\n";
+ pf->debug_print("mgd");
+ Debug("mgd") << "\n";
+ Node n1 = toStreamRecLFSC(ss, tp, pf->d_children[0], tb + 1, map);
+ Debug("mgd") << "\ndoing trans proof, got n1 " << n1 << "\n";
+ if(tb == 1) {
+ Debug("mgdx") << "\ntrans proof[0], got n1 " << n1 << "\n";
+ }
+
+ bool identicalEqualities = false;
+ bool evenLengthSequence;
+ Node nodeAfterEqualitySequence;
+
+ for(size_t i = 1; i < pf->d_children.size(); ++i) {
+ std::stringstream ss1(ss.str()), ss2;
+ ss.str("");
+ Node n2 = toStreamRecLFSC(ss2, tp, pf->d_children[i], tb + 1, map);
+
+ // The following branch is dedicated to handling sequences of identical equalities,
+ // i.e. trans[ a=b, a=b, a=b ].
+ //
+ // There are two cases:
+ // 1. The number of equalities is odd. Then, the sequence can be collapsed to just one equality,
+ // i.e. a=b.
+ // 2. The number of equalities is even. Now, we have two options: a=a or b=b. To determine this,
+ // we look at the node after the equality sequence. If it needs a, we go for a=a; and if it needs
+ // b, we go for b=b. If there is no following node, we look at the goal of the transitivity proof,
+ // and use it to determine which option we need.
+ if(n2.getKind() == kind::EQUAL || n2.getKind() == kind::IFF) {
+ if (((n1[0] == n2[0]) && (n1[1] == n2[1])) || ((n1[0] == n2[1]) && (n1[1] == n2[0]))) {
+ // We are in a sequence of identical equalities
+
+ Debug("gk::proof") << "Detected identical equalities: " << std::endl << "\t" << n1 << std::endl;
+
+ if (!identicalEqualities) {
+ // The sequence of identical equalities has started just now
+ identicalEqualities = true;
+
+ Debug("gk::proof") << "The sequence is just beginning. Determining length..." << std::endl;
+
+ // Determine whether the length of this sequence is odd or even.
+ evenLengthSequence = true;
+ bool sequenceOver = false;
+ size_t j = i + 1;
+
+ while (j < pf->d_children.size() && !sequenceOver) {
+ std::stringstream dontCare;
+ nodeAfterEqualitySequence = toStreamRecLFSC(dontCare, tp, pf->d_children[j], tb + 1, map );
+
+ if (((nodeAfterEqualitySequence[0] == n1[0]) && (nodeAfterEqualitySequence[1] == n1[1])) ||
+ ((nodeAfterEqualitySequence[0] == n1[1]) && (nodeAfterEqualitySequence[1] == n1[0]))) {
+ evenLengthSequence = !evenLengthSequence;
+ } else {
+ sequenceOver = true;
+ }
+
+ ++j;
+ }
+
+ if (evenLengthSequence) {
+ // If the length is even, we need to apply transitivity for the "correct" hand of the equality.
+
+ Debug("gk::proof") << "Equality sequence of even length" << std::endl;
+ Debug("gk::proof") << "n1 is: " << n1 << std::endl;
+ Debug("gk::proof") << "n2 is: " << n2 << std::endl;
+ Debug("gk::proof") << "pf-d_node is: " << pf->d_node << std::endl;
+ Debug("gk::proof") << "Next node is: " << nodeAfterEqualitySequence << std::endl;
+
+ ss << "(trans _ _ _ _ ";
+
+ // If the sequence is at the very end of the transitivity proof, use pf->d_node to guide us.
+ if (!sequenceOver) {
+ if (match(n1[0], pf->d_node[0])) {
+ n1 = eqNode(n1[0], n1[0]);
+ ss << ss1.str() << " (symm _ _ _ " << ss1.str() << ")";
+ } else if (match(n1[1], pf->d_node[1])) {
+ n1 = eqNode(n1[1], n1[1]);
+ ss << " (symm _ _ _ " << ss1.str() << ")" << ss1.str();
+ } else {
+ Debug("gk::proof") << "Error: identical equalities over, but hands don't match what we're proving."
+ << std::endl;
+ Assert(false);
+ }
+ } else {
+ // We have a "next node". Use it to guide us.
+
+ Assert(nodeAfterEqualitySequence.getKind() == kind::EQUAL ||
+ nodeAfterEqualitySequence.getKind() == kind::IFF);
+
+ if ((n1[0] == nodeAfterEqualitySequence[0]) || (n1[0] == nodeAfterEqualitySequence[1])) {
+
+ // Eliminate n1[1]
+ ss << ss1.str() << " (symm _ _ _ " << ss1.str() << ")";
+ n1 = eqNode(n1[0], n1[0]);
+
+ } else if ((n1[1] == nodeAfterEqualitySequence[0]) || (n1[1] == nodeAfterEqualitySequence[1])) {
+
+ // Eliminate n1[0]
+ ss << " (symm _ _ _ " << ss1.str() << ")" << ss1.str();
+ n1 = eqNode(n1[1], n1[1]);
+
+ } else {
+ Debug("gk::proof") << "Error: even length sequence, but I don't know which hand to keep!" << std::endl;
+ Assert(false);
+ }
+ }
+
+ ss << ")";
+
+ } else {
+ Debug("gk::proof") << "Equality sequence length is odd!" << std::endl;
+ ss.str(ss1.str());
+ }
+
+ Debug("gk::proof") << "Have proven: " << n1 << std::endl;
+ } else {
+ ss.str(ss1.str());
+ }
+
+ // Ignore the redundancy.
+ continue;
+ }
+ }
+
+ if (identicalEqualities) {
+ // We were in a sequence of identical equalities, but it has now ended. Resume normal operation.
+ identicalEqualities = false;
+ }
+
+ Debug("mgd") << "\ndoing trans proof, got n2 " << n2 << "\n";
+ if(tb == 1) {
+ Debug("mgdx") << "\ntrans proof[" << i << "], got n2 " << n2 << "\n";
+ Debug("mgdx") << (n2.getKind() == kind::EQUAL || n2.getKind() == kind::IFF) << "\n";
+
+ if ((n1.getNumChildren() >= 2) && (n2.getNumChildren() >= 2)) {
+ Debug("mgdx") << n1[0].getId() << " " << n1[1].getId() << " / " << n2[0].getId() << " " << n2[1].getId() << "\n";
+ Debug("mgdx") << n1[0].getId() << " " << n1[0] << "\n";
+ Debug("mgdx") << n1[1].getId() << " " << n1[1] << "\n";
+ Debug("mgdx") << n2[0].getId() << " " << n2[0] << "\n";
+ Debug("mgdx") << n2[1].getId() << " " << n2[1] << "\n";
+ Debug("mgdx") << (n1[0] == n2[0]) << "\n";
+ Debug("mgdx") << (n1[1] == n2[1]) << "\n";
+ Debug("mgdx") << (n1[0] == n2[1]) << "\n";
+ Debug("mgdx") << (n1[1] == n2[0]) << "\n";
+ }
+ }
+ ss << "(trans _ _ _ _ ";
+
+ if((n2.getKind() == kind::EQUAL || n2.getKind() == kind::IFF) &&
+ (n1.getKind() == kind::EQUAL || n1.getKind() == kind::IFF))
+ // Both elements of the transitivity rule are equalities/iffs
+ {
+ if(n1[0] == n2[0]) {
+ if(tb == 1) { Debug("mgdx") << "case 1\n"; }
+ n1 = eqNode(n1[1], n2[1]);
+ ss << "(symm _ _ _ " << ss1.str() << ") " << ss2.str();
+ } else if(n1[1] == n2[1]) {
+ if(tb == 1) { Debug("mgdx") << "case 2\n"; }
+ n1 = eqNode(n1[0], n2[0]);
+ ss << ss1.str() << " (symm _ _ _ " << ss2.str() << ")";
+ } else if(n1[0] == n2[1]) {
+ if(tb == 1) { Debug("mgdx") << "case 3\n"; }
+ n1 = eqNode(n2[0], n1[1]);
+ ss << ss2.str() << " " << ss1.str();
+ if(tb == 1) { Debug("mgdx") << "++ proved " << n1 << "\n"; }
+ } else if(n1[1] == n2[0]) {
+ if(tb == 1) { Debug("mgdx") << "case 4\n"; }
+ n1 = eqNode(n1[0], n2[1]);
+ ss << ss1.str() << " " << ss2.str();
+ } else {
+ Warning() << "\n\ntrans proof failure at step " << i << "\n\n";
+ Warning() << "0 proves " << n1 << "\n";
+ Warning() << "1 proves " << n2 << "\n\n";
+ pf->debug_print("mgdx",0);
+ //toStreamRec(Warning.getStream(), pf, 0);
+ Warning() << "\n\n";
+ Unreachable();
+ }
+ Debug("mgd") << "++ trans proof[" << i << "], now have " << n1 << std::endl;
+ } else if(n1.getKind() == kind::EQUAL || n1.getKind() == kind::IFF) {
+ // n1 is an equality/iff, but n2 is a predicate
+ if(n1[0] == n2) {
+ n1 = n1[1];
+ ss << "(symm _ _ _ " << ss1.str() << ") (pred_eq_t _ " << ss2.str() << ")";
+ } else if(n1[1] == n2) {
+ n1 = n1[0];
+ ss << ss1.str() << " (pred_eq_t _ " << ss2.str() << ")";
+ } else {
+ Unreachable();
+ }
+ } else if(n2.getKind() == kind::EQUAL || n2.getKind() == kind::IFF) {
+ // n2 is an equality/iff, but n1 is a predicate
+ if(n2[0] == n1) {
+ n1 = n2[1];
+ ss << "(symm _ _ _ " << ss2.str() << ") (pred_eq_t _ " << ss1.str() << ")";
+ } else if(n2[1] == n1) {
+ n1 = n2[0];
+ ss << ss2.str() << " (pred_eq_t _ " << ss1.str() << ")";
+ } else {
+ Unreachable();
+ }
+ } else {
+ // Both n1 and n2 are prediacates. Don't know what to do...
+ Unreachable();
+ }
+
+ ss << ")";
+ }
+ out << ss.str();
+ Debug("mgd") << "\n++ trans proof done, have proven " << n1 << std::endl;
+ return n1;
+ }
+
+ case eq::MERGED_ARRAYS_ROW: {
+ Debug("mgd") << "row lemma: " << pf->d_node << std::endl;
+ Assert(pf->d_node.getKind() == kind::EQUAL);
+ TNode t1, t2, t3, t4;
+ Node ret;
+ if(pf->d_node[1].getKind() == kind::SELECT &&
+ pf->d_node[1][0].getKind() == kind::STORE &&
+ pf->d_node[0].getKind() == kind::SELECT &&
+ pf->d_node[0][0] == pf->d_node[1][0][0] &&
+ pf->d_node[0][1] == pf->d_node[1][1]) {
+ t2 = pf->d_node[1][0][1];
+ t3 = pf->d_node[1][1];
+ t1 = pf->d_node[0][0];
+ t4 = pf->d_node[1][0][2];
+ ret = pf->d_node[1].eqNode(pf->d_node[0]);
+ Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\nt4 " << t4 << "\n";
+ } else {
+ Assert(pf->d_node[0].getKind() == kind::SELECT &&
+ pf->d_node[0][0].getKind() == kind::STORE &&
+ pf->d_node[1].getKind() == kind::SELECT &&
+ pf->d_node[1][0] == pf->d_node[0][0][0] &&
+ pf->d_node[1][1] == pf->d_node[0][1]);
+ t2 = pf->d_node[0][0][1];
+ t3 = pf->d_node[0][1];
+ t1 = pf->d_node[1][0];
+ t4 = pf->d_node[0][0][2];
+ ret = pf->d_node;
+ Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\nt4 " << t4 << "\n";
+ }
+ out << "(row _ _ ";
+ tp->printTerm(t2.toExpr(), out, map);
+ out << " ";
+ tp->printTerm(t3.toExpr(), out, map);
+ out << " ";
+ tp->printTerm(t1.toExpr(), out, map);
+ out << " ";
+ tp->printTerm(t4.toExpr(), out, map);
+ out << " " << ProofManager::getLitName(t2.eqNode(t3)) << ")";
+ return ret;
+ }
+
+ case eq::MERGED_ARRAYS_ROW1: {
+ Debug("mgd") << "row1 lemma: " << pf->d_node << std::endl;
+ Assert(pf->d_node.getKind() == kind::EQUAL);
+ TNode t1, t2, t3;
+ Node ret;
+ if(pf->d_node[1].getKind() == kind::SELECT &&
+ pf->d_node[1][0].getKind() == kind::STORE &&
+ pf->d_node[1][0][1] == pf->d_node[1][1] &&
+ pf->d_node[1][0][2] == pf->d_node[0]) {
+ t1 = pf->d_node[1][0][0];
+ t2 = pf->d_node[1][0][1];
+ t3 = pf->d_node[0];
+ ret = pf->d_node[1].eqNode(pf->d_node[0]);
+ Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\n";
+ } else {
+ Assert(pf->d_node[0].getKind() == kind::SELECT &&
+ pf->d_node[0][0].getKind() == kind::STORE &&
+ pf->d_node[0][0][1] == pf->d_node[0][1] &&
+ pf->d_node[0][0][2] == pf->d_node[1]);
+ t1 = pf->d_node[0][0][0];
+ t2 = pf->d_node[0][0][1];
+ t3 = pf->d_node[1];
+ ret = pf->d_node;
+ Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\n";
+ }
+ out << "(row1 _ _ ";
+ tp->printTerm(t1.toExpr(), out, map);
+ out << " ";
+ tp->printTerm(t2.toExpr(), out, map);
+ out << " ";
+ tp->printTerm(t3.toExpr(), out, map);
+ out << ")";
+ return ret;
+ }
+
+ default:
+ Assert(!pf->d_node.isNull());
+ Assert(pf->d_children.empty());
+ Debug("mgd") << "theory proof: " << pf->d_node << " by rule " << int(pf->d_id) << std::endl;
+ AlwaysAssert(false);
+ return pf->d_node;
+ }
+}
+
+UFProof::UFProof(theory::uf::TheoryUF* uf, TheoryProofEngine* pe)
+ : TheoryProof(uf, pe)
+{}
+
+void UFProof::registerTerm(Expr term) {
+ // already registered
+ if (d_declarations.find(term) != d_declarations.end())
+ return;
+
+ Type type = term.getType();
+ if (type.isSort()) {
+ // declare uninterpreted sorts
+ d_sorts.insert(type);
+ }
+
+ if (term.getKind() == kind::APPLY_UF) {
+ Expr function = term.getOperator();
+ d_declarations.insert(function);
+ }
+
+ if (term.isVariable()) {
+ d_declarations.insert(term);
+ }
+
+ // recursively declare all other terms
+ for (unsigned i = 0; i < term.getNumChildren(); ++i) {
+ // could belong to other theories
+ d_proofEngine->registerTerm(term[i]);
+ }
+}
+
+void LFSCUFProof::printTerm(Expr term, std::ostream& os, const LetMap& map) {
+ Assert (Theory::theoryOf(term) == THEORY_UF);
+
+ if (term.getKind() == kind::VARIABLE ||
+ term.getKind() == kind::SKOLEM) {
+ os << term;
+ return;
+ }
+
+ Assert (term.getKind() == kind::APPLY_UF);
+
+ if(term.getType().isBoolean()) {
+ os << "(p_app ";
+ }
+ Expr func = term.getOperator();
+ for (unsigned i = 0; i < term.getNumChildren(); ++i) {
+ os << "(apply _ _ ";
+ }
+ os << func << " ";
+ for (unsigned i = 0; i < term.getNumChildren(); ++i) {
+ printTerm(term[i], os, map);
+ os << ")";
+ }
+ if(term.getType().isBoolean()) {
+ os << ")";
+ }
+}
+
+void LFSCUFProof::printSort(Type type, std::ostream& os) {
+ Assert (type.isSort());
+ os << type <<" ";
+}
+
+void LFSCUFProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren) {
+ os << " ;; UF Theory Lemma \n;;";
+ for (unsigned i = 0; i < lemma.size(); ++i) {
+ os << lemma[i] <<" ";
+ }
+ os <<"\n";
+ //os << " (clausify_false trust)";
+ UFProof::printTheoryLemmaProof( lemma, os, paren );
+}
+
+void LFSCUFProof::printDeclarations(std::ostream& os, std::ostream& paren) {
+ // declaring the sorts
+ for (TypeSet::const_iterator it = d_sorts.begin(); it != d_sorts.end(); ++it) {
+ os << "(% " << *it << " sort\n";
+ paren << ")";
+ }
+
+ // declaring the terms
+ for (ExprSet::const_iterator it = d_declarations.begin(); it != d_declarations.end(); ++it) {
+ Expr term = *it;
+
+ os << "(% " << ProofManager::sanitize(term) << " ";
+ os << "(term ";
+
+ Type type = term.getType();
+ if (type.isFunction()) {
+ std::ostringstream fparen;
+ FunctionType ftype = (FunctionType)type;
+ std::vector<Type> args = ftype.getArgTypes();
+ args.push_back(ftype.getRangeType());
+ os << "(arrow";
+ for (unsigned i = 0; i < args.size(); i++) {
+ Type arg_type = args[i];
+ os << " " << arg_type;
+ if (i < args.size() - 2) {
+ os << " (arrow";
+ fparen << ")";
+ }
+ }
+ os << fparen.str() << "))\n";
+ } else {
+ Assert (term.isVariable());
+ os << type << ")\n";
+ }
+ paren << ")";
+ }
+}
diff --git a/src/proof/uf_proof.h b/src/proof/uf_proof.h
new file mode 100644
index 000000000..121db1fcd
--- /dev/null
+++ b/src/proof/uf_proof.h
@@ -0,0 +1,75 @@
+/********************* */
+/*! \file uf_proof.h
+ ** \verbatim
+ ** Original author: Liana Hadarean
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2014 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief UF proof
+ **
+ ** UF proof
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__UF__PROOF_H
+#define __CVC4__UF__PROOF_H
+
+#include "expr/expr.h"
+#include "proof/proof_manager.h"
+#include "theory/uf/equality_engine.h"
+
+namespace CVC4 {
+
+//proof object outputted by TheoryUF
+class ProofUF : public Proof {
+private:
+ static Node toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, unsigned tb, const LetMap& map);
+public:
+ ProofUF( theory::eq::EqProof * pf ) : d_proof( pf ) {}
+ //it is simply an equality engine proof
+ theory::eq::EqProof * d_proof;
+ void toStream(std::ostream& out);
+ static void toStreamLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, const LetMap& map);
+};
+
+
+namespace theory {
+namespace uf {
+class TheoryUF;
+}
+}
+
+typedef __gnu_cxx::hash_set<Type, TypeHashFunction > TypeSet;
+
+
+class UFProof : public TheoryProof {
+protected:
+ TypeSet d_sorts; // all the uninterpreted sorts in this theory
+ ExprSet d_declarations; // all the variable/function declarations
+
+public:
+ UFProof(theory::uf::TheoryUF* uf, TheoryProofEngine* proofEngine);
+
+ virtual void registerTerm(Expr term);
+};
+
+class LFSCUFProof : public UFProof {
+public:
+ LFSCUFProof(theory::uf::TheoryUF* uf, TheoryProofEngine* proofEngine)
+ : UFProof(uf, proofEngine)
+ {}
+ virtual void printTerm(Expr term, std::ostream& os, const LetMap& map);
+ virtual void printSort(Type type, std::ostream& os);
+ virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren);
+ virtual void printDeclarations(std::ostream& os, std::ostream& paren);
+};
+
+
+}/* CVC4 namespace */
+
+#endif /* __CVC4__UF__PROOF_H */
diff --git a/src/prop/bvminisat/bvminisat.cpp b/src/prop/bvminisat/bvminisat.cpp
index be266b6d8..936778e0d 100644
--- a/src/prop/bvminisat/bvminisat.cpp
+++ b/src/prop/bvminisat/bvminisat.cpp
@@ -19,6 +19,7 @@
#include "prop/bvminisat/bvminisat.h"
#include "prop/bvminisat/simp/SimpSolver.h"
+#include "proof/sat_proof.h"
#include "util/statistics_registry.h"
namespace CVC4 {
@@ -47,14 +48,18 @@ void BVMinisatSatSolver::setNotify(Notify* notify) {
d_minisat->setNotify(d_minisatNotify);
}
-void BVMinisatSatSolver::addClause(SatClause& clause, bool removable, uint64_t proof_id) {
+ClauseId BVMinisatSatSolver::addClause(SatClause& clause,
+ bool removable) {
Debug("sat::minisat") << "Add clause " << clause <<"\n";
BVMinisat::vec<BVMinisat::Lit> minisat_clause;
toMinisatClause(clause, minisat_clause);
// for(unsigned i = 0; i < minisat_clause.size(); ++i) {
// d_minisat->setFrozen(BVMinisat::var(minisat_clause[i]), true);
// }
- d_minisat->addClause(minisat_clause);
+ ClauseId clause_id = ClauseIdError;
+ d_minisat->addClause(minisat_clause, clause_id);
+ THEORY_PROOF(Assert (clause_id != ClauseIdError););
+ return clause_id;
}
SatValue BVMinisatSatSolver::propagate() {
@@ -91,6 +96,10 @@ void BVMinisatSatSolver::popAssumption() {
d_minisat->popAssumption();
}
+void BVMinisatSatSolver::setProofLog( BitVectorProof * bvp ) {
+ d_minisat->setProofLog( bvp );
+}
+
SatVariable BVMinisatSatSolver::newVar(bool isTheoryAtom, bool preRegister, bool canErase){
return d_minisat->newVar(true, true, !canErase);
}
@@ -126,6 +135,10 @@ SatValue BVMinisatSatSolver::solve(long unsigned int& resource){
return result;
}
+bool BVMinisatSatSolver::ok() const {
+ return d_minisat->okay();
+}
+
void BVMinisatSatSolver::getUnsatCore(SatClause& unsatCore) {
// TODO add assertion to check the call was after an unsat call
for (int i = 0; i < d_minisat->conflict.size(); ++i) {
@@ -199,8 +212,8 @@ void BVMinisatSatSolver::toMinisatClause(SatClause& clause,
Assert(clause.size() == (unsigned)minisat_clause.size());
}
-void BVMinisatSatSolver::toSatClause(BVMinisat::vec<BVMinisat::Lit>& clause,
- SatClause& sat_clause) {
+void BVMinisatSatSolver::toSatClause(const BVMinisat::Clause& clause,
+ SatClause& sat_clause) {
for (int i = 0; i < clause.size(); ++i) {
sat_clause.push_back(toSatLiteral(clause[i]));
}
@@ -281,3 +294,19 @@ void BVMinisatSatSolver::Statistics::init(BVMinisat::SimpSolver* minisat){
} /* namespace CVC4::prop */
} /* namespace CVC4 */
+
+namespace CVC4 {
+template<>
+prop::SatLiteral toSatLiteral< BVMinisat::Solver>(BVMinisat::Solver::TLit lit) {
+ return prop::BVMinisatSatSolver::toSatLiteral(lit);
+}
+
+template<>
+void toSatClause< BVMinisat::Solver> (const BVMinisat::Solver::TClause& minisat_cl,
+ prop::SatClause& sat_cl) {
+ prop::BVMinisatSatSolver::toSatClause(minisat_cl, sat_cl);
+}
+
+}
+
+
diff --git a/src/prop/bvminisat/bvminisat.h b/src/prop/bvminisat/bvminisat.h
index 986fbf339..383948e3e 100644
--- a/src/prop/bvminisat/bvminisat.h
+++ b/src/prop/bvminisat/bvminisat.h
@@ -43,7 +43,9 @@ private:
}
void notify(BVMinisat::vec<BVMinisat::Lit>& clause) {
SatClause satClause;
- toSatClause(clause, satClause);
+ for (int i = 0; i < clause.size(); ++i) {
+ satClause.push_back(toSatLiteral(clause[i]));
+ }
d_notify->notify(satClause);
}
@@ -73,7 +75,7 @@ public:
void setNotify(Notify* notify);
- void addClause(SatClause& clause, bool removable, uint64_t proof_id);
+ ClauseId addClause(SatClause& clause, bool removable);
SatValue propagate();
@@ -88,6 +90,7 @@ public:
SatValue solve();
SatValue solve(long unsigned int&);
+ bool ok() const;
void getUnsatCore(SatClause& unsatCore);
SatValue value(SatLiteral l);
@@ -106,7 +109,7 @@ public:
static SatValue toSatLiteralValue(BVMinisat::lbool res);
static void toMinisatClause(SatClause& clause, BVMinisat::vec<BVMinisat::Lit>& minisat_clause);
- static void toSatClause (BVMinisat::vec<BVMinisat::Lit>& clause, SatClause& sat_clause);
+ static void toSatClause (const BVMinisat::Clause& clause, SatClause& sat_clause);
void addMarkerLiteral(SatLiteral lit);
void explain(SatLiteral lit, std::vector<SatLiteral>& explanation);
@@ -114,6 +117,8 @@ public:
SatValue assertAssumption(SatLiteral lit, bool propagate);
void popAssumption();
+
+ void setProofLog( BitVectorProof * bvp );
private:
/* Disable the default constructor. */
diff --git a/src/prop/bvminisat/core/Solver.cc b/src/prop/bvminisat/core/Solver.cc
index 5a37da27c..2100160de 100644
--- a/src/prop/bvminisat/core/Solver.cc
+++ b/src/prop/bvminisat/core/Solver.cc
@@ -31,6 +31,10 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
#include "options/bv_options.h"
#include "options/smt_options.h"
#include "theory/interrupted.h"
+#include "proof/proof_manager.h"
+#include "proof/bitvector_proof.h"
+#include "proof/sat_proof.h"
+#include "proof/sat_proof_implementation.h"
#include "util/utility.h"
namespace CVC4 {
@@ -60,19 +64,6 @@ std::ostream& operator << (std::ostream& out, const BVMinisat::Clause& c) {
static const char* _cat = "CORE";
-// static DoubleOption opt_var_decay (_cat, "var-decay", "The variable activity decay factor", 0.95, DoubleRange(0, false, 1, false));
-// static DoubleOption opt_clause_decay (_cat, "cla-decay", "The clause activity decay factor", 0.999, DoubleRange(0, false, 1, false));
-// static DoubleOption opt_random_var_freq (_cat, "rnd-freq", "The frequency with which the decision heuristic tries to choose a random variable", 0.0, DoubleRange(0, true, 1, true));
-// static DoubleOption opt_random_seed (_cat, "rnd-seed", "Used by the random variable selection", 91648253, DoubleRange(0, false, HUGE_VAL, false));
-// static IntOption opt_ccmin_mode (_cat, "ccmin-mode", "Controls conflict clause minimization (0=none, 1=basic, 2=deep)", 0, IntRange(0, 2));
-// static IntOption opt_phase_saving (_cat, "phase-saving", "Controls the level of phase saving (0=none, 1=limited, 2=full)", 2, IntRange(0, 2));
-// static BoolOption opt_rnd_init_act (_cat, "rnd-init", "Randomize the initial activity", false);
-// static BoolOption opt_luby_restart (_cat, "luby", "Use the Luby restart sequence", true);
-// static IntOption opt_restart_first (_cat, "rfirst", "The base restart interval", 100, IntRange(1, INT32_MAX));
-// static DoubleOption opt_restart_inc (_cat, "rinc", "Restart interval increase factor", 1.5, DoubleRange(1, false, HUGE_VAL, false));
-// static DoubleOption opt_garbage_frac (_cat, "gc-frac", "The fraction of wasted memory allowed before a garbage collection is triggered", 0.20, DoubleRange(0, false, HUGE_VAL, false));
-
-
static DoubleOption opt_var_decay (_cat, "var-decay", "The variable activity decay factor", 0.95, DoubleRange(0, false, 1, false));
static DoubleOption opt_clause_decay (_cat, "cla-decay", "The clause activity decay factor", 0.999, DoubleRange(0, false, 1, false));
static DoubleOption opt_random_var_freq (_cat, "rnd-freq", "The frequency with which the decision heuristic tries to choose a random variable", 0, DoubleRange(0, true, 1, true));
@@ -86,6 +77,12 @@ static DoubleOption opt_restart_inc (_cat, "rinc", "Restart interv
static DoubleOption opt_garbage_frac (_cat, "gc-frac", "The fraction of wasted memory allowed before a garbage collection is triggered", 0.20, DoubleRange(0, false, HUGE_VAL, false));
//=================================================================================================
+// Proof declarations
+CRef Solver::TCRef_Undef = CRef_Undef;
+CRef Solver::TCRef_Lazy = CRef_Undef - 1; // no real lazy ref here
+
+
+//=================================================================================================
// Constructor/Destructor:
@@ -150,6 +147,7 @@ Solver::Solver(CVC4::context::Context* c) :
, conflict_budget (-1)
, propagation_budget (-1)
, asynch_interrupt (false)
+ , d_bvp (NULL)
{
// Create the constant variables
varTrue = newVar(true, false);
@@ -193,37 +191,114 @@ Var Solver::newVar(bool sign, bool dvar)
}
-bool Solver::addClause_(vec<Lit>& ps)
+bool Solver::addClause_(vec<Lit>& ps, ClauseId& id)
{
if (decisionLevel() > 0) {
cancelUntil(0);
}
- if (!ok) return false;
+ if (!ok) {
+ id = ClauseIdUndef;
+ return false;
+ }
// Check if clause is satisfied and remove false/duplicate literals:
+ // TODO proof for duplicate literals removal?
sort(ps);
Lit p; int i, j;
- for (i = j = 0, p = lit_Undef; i < ps.size(); i++)
- if (value(ps[i]) == l_True || ps[i] == ~p)
- return true;
- else if (value(ps[i]) != l_False && ps[i] != p)
- ps[j++] = p = ps[i];
+ int falseLiteralsCount = 0;
+
+ for (i = j = 0, p = lit_Undef; i < ps.size(); i++) {
+ // tautologies are ignored
+ if (value(ps[i]) == l_True || ps[i] == ~p) {
+ id = ClauseIdUndef;
+ return true;
+ }
+
+ // Ignore repeated literals
+ if (ps[i] == p) {
+ continue;
+ }
+
+ if (value(ps[i]) == l_False) {
+ if (!THEORY_PROOF_ON())
+ continue;
+ ++falseLiteralsCount;
+ }
+ ps[j++] = p = ps[i];
+ }
+
ps.shrink(i - j);
clause_added = true;
- if (ps.size() == 0)
+ Assert(falseLiteralsCount == 0 || THEORY_PROOF_ON());
+
+ if(falseLiteralsCount == 0) {
+ if (ps.size() == 0) {
+ Assert (!THEORY_PROOF_ON());
return ok = false;
- else if (ps.size() == 1){
+ }
+ else if (ps.size() == 1){
+ if(d_bvp){ id = d_bvp->getSatProof()->registerUnitClause(ps[0], INPUT);}
uncheckedEnqueue(ps[0]);
- return ok = (propagate() == CRef_Undef);
- } else {
+ CRef confl_ref = propagate();
+ ok = (confl_ref == CRef_Undef);
+ if(d_bvp){ if (!ok) d_bvp->getSatProof()->finalizeProof(confl_ref); }
+ return ok;
+ } else {
CRef cr = ca.alloc(ps, false);
clauses.push(cr);
attachClause(cr);
+ if(d_bvp){ id = d_bvp->getSatProof()->registerClause(cr, INPUT);}
+ }
+ return ok;
}
- return ok;
+
+ if (falseLiteralsCount != 0 && THEORY_PROOF_ON()) {
+ // we are in a conflicting state
+ if (ps.size() == falseLiteralsCount && falseLiteralsCount == 1) {
+ if(d_bvp){ id = d_bvp->getSatProof()->storeUnitConflict(ps[0], INPUT); }
+ if(d_bvp){ d_bvp->getSatProof()->finalizeProof(CVC4::BVMinisat::CRef_Lazy); }
+ return ok = false;
+ }
+
+ assign_lt lt(*this);
+ sort(ps, lt);
+
+ CRef cr = ca.alloc(ps, false);
+ clauses.push(cr);
+ attachClause(cr);
+
+ if(d_bvp){id = d_bvp->getSatProof()->registerClause(cr, INPUT);}
+
+ if(ps.size() == falseLiteralsCount) {
+ if(d_bvp){ d_bvp->getSatProof()->finalizeProof(cr); }
+ return ok = false;
+ }
+
+ // Check if it propagates
+ if (ps.size() == falseLiteralsCount + 1) {
+ Clause& cl = ca[cr];
+
+ Assert (value(cl[0]) == l_Undef);
+ uncheckedEnqueue(cl[0], cr);
+ Assert (cl.size() > 1);
+ CRef confl = propagate();
+ ok = (confl == CRef_Undef);
+ if(!ok) {
+ if(d_bvp){
+ if(ca[confl].size() == 1) {
+ id = d_bvp->getSatProof()->storeUnitConflict(ca[confl][0], LEARNT);
+ d_bvp->getSatProof()->finalizeProof(CVC4::BVMinisat::CRef_Lazy);
+ } else {
+ d_bvp->getSatProof()->finalizeProof(confl);
+ }
+ }
+ }
+ }
+ }
+ return ok;
}
void Solver::attachClause(CRef cr) {
@@ -237,6 +312,8 @@ void Solver::attachClause(CRef cr) {
void Solver::detachClause(CRef cr, bool strict) {
const Clause& c = ca[cr];
+ if(d_bvp){ d_bvp->getSatProof()->markDeleted(cr); }
+
assert(c.size() > 1);
if (strict){
@@ -342,6 +419,9 @@ void Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel, UIP uip
int index = trail.size() - 1;
bool done = false;
+
+ if(d_bvp){ d_bvp->getSatProof()->startResChain(confl); }
+
do{
assert(confl != CRef_Undef); // (otherwise should be UIP)
Clause& c = ca[confl];
@@ -352,7 +432,7 @@ void Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel, UIP uip
for (int j = (p == lit_Undef) ? 0 : 1; j < c.size(); j++){
Lit q = c[j];
- if (!seen[var(q)] && level(var(q)) > 0){
+ if (!seen[var(q)] && level(var(q)) > 0) {
varBumpActivity(var(q));
seen[var(q)] = 1;
if (level(var(q)) >= decisionLevel())
@@ -360,6 +440,10 @@ void Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel, UIP uip
else
out_learnt.push(q);
}
+
+ if (level(var(q)) == 0) {
+ if(d_bvp){ d_bvp->getSatProof()->resolveOutUnit(q); }
+ }
}
// Select next clause to look at:
@@ -369,6 +453,10 @@ void Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel, UIP uip
seen[var(p)] = 0;
pathC--;
+ if ( pathC > 0 && confl != CRef_Undef ) {
+ if(d_bvp){ d_bvp->getSatProof()->addResolutionStep(p, confl, sign(p));}
+ }
+
switch (uip) {
case UIP_FIRST:
done = pathC == 0;
@@ -392,11 +480,22 @@ void Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel, UIP uip
for (i = 1; i < out_learnt.size(); i++)
abstract_level |= abstractLevel(var(out_learnt[i])); // (maintain an abstraction of levels involved in conflict)
- for (i = j = 1; i < out_learnt.size(); i++)
- if (reason(var(out_learnt[i])) == CRef_Undef || !litRedundant(out_learnt[i], abstract_level))
+ for (i = j = 1; i < out_learnt.size(); i++) {
+ if (reason(var(out_learnt[i])) == CRef_Undef) {
+ out_learnt[j++] = out_learnt[i];
+ } else {
+ // Check if the literal is redundant
+ if (!litRedundant(out_learnt[i], abstract_level)) {
+ // Literal is not redundant
out_learnt[j++] = out_learnt[i];
+ } else {
+ if(d_bvp){ d_bvp->getSatProof()->storeLitRedundant(out_learnt[i]); }
+ }
+ }
+ }
}else if (ccmin_mode == 1){
+ Unreachable();
for (i = j = 1; i < out_learnt.size(); i++){
Var x = var(out_learnt[i]);
@@ -452,10 +551,13 @@ bool Solver::litRedundant(Lit p, uint32_t abstract_levels)
analyze_stack.clear(); analyze_stack.push(p);
int top = analyze_toclear.size();
while (analyze_stack.size() > 0){
- assert(reason(var(analyze_stack.last())) != CRef_Undef);
- Clause& c = ca[reason(var(analyze_stack.last()))]; analyze_stack.pop();
+ CRef c_reason = reason(var(analyze_stack.last()));
+ assert(c_reason != CRef_Undef);
+ Clause& c = ca[c_reason];
+ int c_size = c.size();
+ analyze_stack.pop();
- for (int i = 1; i < c.size(); i++){
+ for (int i = 1; i < c_size; i++){
Lit p = c[i];
if (!seen[var(p)] && level(var(p)) > 0){
if (reason(var(p)) != CRef_Undef && (abstractLevel(var(p)) & abstract_levels) != 0){
@@ -495,21 +597,36 @@ void Solver::analyzeFinal2(Lit p, CRef confl_clause, vec<Lit>& out_conflict) {
seen[var(cl[i])] = 1;
}
- for (int i = trail.size() - 1; i >= trail_lim[0]; i--) {
+ int end = options::proof() ? 0 : trail_lim[0];
+ for (int i = trail.size() - 1; i >= end; i--) {
Var x = var(trail[i]);
if (seen[x]) {
if (reason(x) == CRef_Undef) {
// we skip p if was a learnt unit
if (x != var(p)) {
- assert (marker[x] == 2);
- assert (level(x) > 0);
- out_conflict.push(~trail[i]);
+ if (marker[x] == 2) {
+ assert (level(x) > 0);
+ out_conflict.push(~trail[i]);
+ } else {
+ if(d_bvp){d_bvp->getSatProof()->resolveOutUnit(~(trail[i])); }
+ }
+ } else {
+ if(d_bvp){d_bvp->getSatProof()->resolveOutUnit(~p);}
}
} else {
Clause& c = ca[reason(x)];
- for (int j = 1; j < c.size(); j++)
+ if(d_bvp){d_bvp->getSatProof()->addResolutionStep(trail[i],reason(x), sign(trail[i]));}
+
+ for (int j = 1; j < c.size(); j++) {
if (level(var(c[j])) > 0)
seen[var(c[j])] = 1;
+ if(d_bvp){
+ if (level(var(c[j])) == 0) {
+ d_bvp->getSatProof()->resolveOutUnit(c[j]);
+ seen[var(c[j])] = 0; // we don't need to resolve it out again
+ }
+ }
+ }
}
seen[x] = 0;
}
@@ -534,12 +651,23 @@ void Solver::analyzeFinal(Lit p, vec<Lit>& out_conflict)
out_conflict.push(p);
}
- if (decisionLevel() == 0)
- return;
+ if(d_bvp){
+ if (level(var(p)) == 0 && d_bvp->isAssumptionConflict()) {
+ Assert ( marker[var(p)] == 2);
+ if (reason(var(p)) == CRef_Undef) {
+ d_bvp->startBVConflict(p);
+ }
+ }
+ }
+
+ if (decisionLevel() == 0 && !options::proof()) {
+ return;
+ }
seen[var(p)] = 1;
-
- for (int i = trail.size()-1; i >= trail_lim[0]; i--){
+ int end = options::proof() ? 0 : trail_lim[0];
+
+ for (int i = trail.size()-1; i >= end; i--){
Var x = var(trail[i]);
if (seen[x]) {
if (reason(x) == CRef_Undef) {
@@ -548,9 +676,24 @@ void Solver::analyzeFinal(Lit p, vec<Lit>& out_conflict)
out_conflict.push(~trail[i]);
} else {
Clause& c = ca[reason(x)];
- for (int j = 1; j < c.size(); j++)
- if (level(var(c[j])) > 0)
+ if(d_bvp){
+ if (d_bvp->isAssumptionConflict() &&
+ trail[i] == p) {
+ d_bvp->startBVConflict(reason(x));
+ } else {
+ d_bvp->getSatProof()->addResolutionStep(trail[i], reason(x), sign(trail[i]));
+ }
+ }
+ for (int j = 1; j < c.size(); j++) {
+ if (level(var(c[j])) > 0) {
seen[var(c[j])] = 1;
+ }
+ if(d_bvp){
+ if (level(var(c[j])) == 0) {
+ d_bvp->getSatProof()->resolveOutUnit(c[j]);
+ }
+ }
+ }
}
seen[x] = 0;
}
@@ -588,9 +731,12 @@ lbool Solver::propagateAssumptions() {
}
lbool Solver::assertAssumption(Lit p, bool propagate) {
+ // TODO need to somehow mark the assumption as unit in the current context?
+ // it's not always unit though, but this would be useful for debugging
// assert(marker[var(p)] == 1);
+
if (decisionLevel() > assumptions.size()) {
cancelUntil(assumptions.size());
}
@@ -601,7 +747,8 @@ lbool Solver::assertAssumption(Lit p, bool propagate) {
if (c->getLevel() > 0) {
assumptions.push(p);
} else {
- if (!addClause(p)) {
+ ClauseId id;
+ if (!addClause(p, id)) {
conflict.push(~p);
return l_False;
}
@@ -618,6 +765,14 @@ lbool Solver::assertAssumption(Lit p, bool propagate) {
}
}
+void Solver::addMarkerLiteral(Var var) {
+ // make sure it wasn't already marked
+ Assert(marker[var] == 0);
+ marker[var] = 1;
+ if(d_bvp){d_bvp->getSatProof()->registerAssumption(var);}
+}
+
+
/*_________________________________________________________________________________________________
|
| propagate : [void] -> [Clause*]
@@ -730,8 +885,13 @@ void Solver::removeSatisfied(vec<CRef>& cs)
int i, j;
for (i = j = 0; i < cs.size(); i++){
Clause& c = ca[cs[i]];
- if (satisfied(c))
+ if (satisfied(c)) {
+ if (locked(c)) {
+ // store a resolution of the literal c propagated
+ if(d_bvp){ d_bvp->getSatProof()->storeUnitResolution(c[0]); }
+ }
removeClause(cs[i]);
+ }
else
cs[j++] = cs[i];
}
@@ -807,7 +967,12 @@ lbool Solver::search(int nof_conflicts, UIP uip)
if (confl != CRef_Undef){
// CONFLICT
conflicts++; conflictC++;
- if (decisionLevel() == 0) return l_False;
+
+ if (decisionLevel() == 0) {
+ // can this happen for bv?
+ if(d_bvp){ d_bvp->getSatProof()->finalizeProof(confl);}
+ return l_False;
+ }
learnt_clause.clear();
analyze(confl, learnt_clause, backtrack_level, uip);
@@ -821,15 +986,42 @@ lbool Solver::search(int nof_conflicts, UIP uip)
learnts.push(cr);
attachClause(cr);
claBumpActivity(ca[cr]);
+ if(d_bvp){
+ ClauseId id = d_bvp->getSatProof()->registerClause(cr, LEARNT);
+ PSTATS(
+ __gnu_cxx::hash_set<int> cl_levels;
+ for (int i = 0; i < learnt_clause.size(); ++i) {
+ cl_levels.insert(level(var(learnt_clause[i])));
+ }
+ if( d_bvp ){ d_bvp->getSatProof()->storeClauseGlue(id, cl_levels.size()); }
+ )
+ d_bvp->getSatProof()->endResChain(id);
+ }
}
-
+
+ if (learnt_clause.size() == 1) {
+ // learning a unit clause
+ if(d_bvp){ d_bvp->getSatProof()->endResChain(learnt_clause[0]);}
+ }
+
// if the uip was an assumption we are unsat
if (level(var(p)) <= assumptions.size()) {
for (int i = 0; i < learnt_clause.size(); ++i) {
assert (level(var(learnt_clause[i])) <= decisionLevel());
seen[var(learnt_clause[i])] = 1;
}
+
+ // Starting new resolution chain for bit-vector proof
+ if( d_bvp ){
+ if (cr == CRef_Undef) {
+ d_bvp->startBVConflict(learnt_clause[0]);
+ }
+ else {
+ d_bvp->startBVConflict(cr);
+ }
+ }
analyzeFinal(p, conflict);
+ if(d_bvp){ d_bvp->endBVConflict(conflict); }
Debug("bvminisat::search") << OUTPUT_TAG << " conflict on assumptions " << std::endl;
return l_False;
}
@@ -843,7 +1035,10 @@ lbool Solver::search(int nof_conflicts, UIP uip)
CRef new_confl = propagate();
if (new_confl != CRef_Undef) {
// we have a conflict we now need to explain it
- analyzeFinal2(p, new_confl, conflict);
+ // TODO: proof for analyzeFinal2
+ if(d_bvp){ d_bvp->startBVConflict(new_confl); }
+ analyzeFinal2(p, new_confl, conflict);
+ if(d_bvp){ d_bvp->endBVConflict(conflict); }
return l_False;
}
}
@@ -912,7 +1107,10 @@ lbool Solver::search(int nof_conflicts, UIP uip)
newDecisionLevel();
}else if (value(p) == l_False){
marker[var(p)] = 2;
+
+ if(d_bvp){ d_bvp->markAssumptionConflict(); }
analyzeFinal(~p, conflict);
+ if(d_bvp){ d_bvp->endBVConflict(conflict); }
Debug("bvminisat::search") << OUTPUT_TAG << " assumption false, we're unsat" << std::endl;
return l_False;
}else{
@@ -1044,39 +1242,76 @@ lbool Solver::solve_()
//
void Solver::explain(Lit p, std::vector<Lit>& explanation) {
- vec<Lit> queue;
- queue.push(p);
-
Debug("bvminisat::explain") << OUTPUT_TAG << "starting explain of " << p << std::endl;
- __gnu_cxx::hash_set<Var> visited;
- visited.insert(var(p));
+ // top level fact, no explanation necessary
+ if (level(var(p)) == 0) {
+ if(d_bvp){
+ // the only way a marker variable is
+ if (reason(var(p)) == CRef_Undef) {
+ d_bvp->startBVConflict(p);
+ vec<Lit> confl;
+ confl.push(p);
+ d_bvp->endBVConflict(confl);
+ return;
+ }
+ }
+ if (!THEORY_PROOF_ON())
+ return;
+ }
- while(queue.size() > 0) {
- Lit l = queue.last();
-
- Debug("bvminisat::explain") << OUTPUT_TAG << "processing " << l << std::endl;
-
- assert(value(l) == l_True);
- queue.pop();
- if (reason(var(l)) == CRef_Undef) {
- if (level(var(l)) == 0) continue;
- Assert(marker[var(l)] == 2);
- explanation.push_back(l);
- visited.insert(var(l));
- } else {
- Clause& c = ca[reason(var(l))];
- for (int i = 1; i < c.size(); ++i) {
- if (level(var(c[i])) > 0 && visited.count(var(c[i])) == 0) {
- queue.push(~c[i]);
- visited.insert(var(c[i]));
+ seen[var(p)] = 1;
+
+ // if we are called at decisionLevel = 0 trail_lim is empty
+ int bottom = options::proof() ? 0 : trail_lim[0];
+ for (int i = trail.size()-1; i >= bottom; i--){
+ Var x = var(trail[i]);
+ if (seen[x]) {
+ if (reason(x) == CRef_Undef) {
+ if (marker[x] == 2) {
+ assert(level(x) > 0);
+ explanation.push_back(trail[i]);
+ } else {
+ Assert (level(x) == 0);
+ if(d_bvp){ d_bvp->getSatProof()->resolveOutUnit(~(trail[i])); }
+ }
+
+ } else {
+ Clause& c = ca[reason(x)];
+ if(d_bvp){
+ if (p == trail[i]) {
+ d_bvp->startBVConflict(reason(var(p)));
+ } else {
+ d_bvp->getSatProof()->addResolutionStep(trail[i], reason(x), sign(trail[i]));
+ }
+ }
+ for (int j = 1; j < c.size(); j++) {
+ if (level(var(c[j])) > 0 || options::proof()) {
+ seen[var(c[j])] = 1;
+ }
}
}
+ seen[x] = 0;
}
}
+ seen[var(p)] = 0;
+
+ if(d_bvp){
+ vec<Lit> conflict_clause;
+ conflict_clause.push(p);
+ for(unsigned i = 0; i < explanation.size(); ++i) {
+ conflict_clause.push(~explanation[i]);
+ }
+ d_bvp->endBVConflict(conflict_clause);
+ }
}
-
+void Solver::setProofLog( BitVectorProof * bvp ) {
+ d_bvp = bvp;
+ d_bvp->initSatProof(this);
+ d_bvp->getSatProof()->registerTrueLit(mkLit(varTrue, false));
+ d_bvp->getSatProof()->registerFalseLit(mkLit(varFalse, true));
+}
//=================================================================================================
// Writing CNF to DIMACS:
@@ -1171,7 +1406,7 @@ void Solver::relocAll(ClauseAllocator& to)
// printf(" >>> RELOCING: %s%d\n", sign(p)?"-":"", var(p)+1);
vec<Watcher>& ws = watches[p];
for (int j = 0; j < ws.size(); j++)
- ca.reloc(ws[j].cref, to);
+ ca.reloc(ws[j].cref, to, d_bvp ? d_bvp->getSatProof()->getProxy() : NULL);
}
// All reasons:
@@ -1180,18 +1415,20 @@ void Solver::relocAll(ClauseAllocator& to)
Var v = var(trail[i]);
if (reason(v) != CRef_Undef && (ca[reason(v)].reloced() || locked(ca[reason(v)])))
- ca.reloc(vardata[v].reason, to);
+ ca.reloc(vardata[v].reason, to, d_bvp ? d_bvp->getSatProof()->getProxy() : NULL);
}
// All learnt:
//
for (int i = 0; i < learnts.size(); i++)
- ca.reloc(learnts[i], to);
+ ca.reloc(learnts[i], to, d_bvp ? d_bvp->getSatProof()->getProxy() : NULL);
// All original:
//
for (int i = 0; i < clauses.size(); i++)
- ca.reloc(clauses[i], to);
+ ca.reloc(clauses[i], to, d_bvp ? d_bvp->getSatProof()->getProxy() : NULL);
+
+ if(d_bvp){ d_bvp->getSatProof()->finishUpdateCRef(); }
}
@@ -1208,5 +1445,25 @@ void Solver::garbageCollect()
to.moveTo(ca);
}
+void ClauseAllocator::reloc(CRef& cr, ClauseAllocator& to, CVC4::BVProofProxy* proxy)
+{
+ CRef old = cr; // save the old reference
+
+ Clause& c = operator[](cr);
+ if (c.reloced()) { cr = c.relocation(); return; }
+
+ cr = to.alloc(c, c.learnt());
+ c.relocate(cr);
+ if (proxy) {
+ proxy->updateCRef(old, cr);
+ }
+
+ // Copy extra data-fields:
+ // (This could be cleaned-up. Generalize Clause-constructor to be applicable here instead?)
+ to[cr].mark(c.mark());
+ if (to[cr].learnt()) to[cr].activity() = c.activity();
+ else if (to[cr].has_extra()) to[cr].calcAbstraction();
+}
+
} /* CVC4::BVMinisat namespace */
} /* CVC4 namespace */
diff --git a/src/prop/bvminisat/core/Solver.h b/src/prop/bvminisat/core/Solver.h
index 214e425f9..019c09bcd 100644
--- a/src/prop/bvminisat/core/Solver.h
+++ b/src/prop/bvminisat/core/Solver.h
@@ -26,13 +26,21 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
#include "prop/bvminisat/mtl/Heap.h"
#include "prop/bvminisat/mtl/Alg.h"
#include "prop/bvminisat/utils/Options.h"
-
#include "context/cdhashmap.h"
+#include "proof/sat_proof.h"
#include <ext/hash_set>
#include <vector>
namespace CVC4 {
+
+typedef unsigned ClauseId;
+namespace BVMinisat {
+class Solver;
+}
+
+class BitVectorProof;
+
namespace BVMinisat {
/** Interface for minisat callbacks */
@@ -60,7 +68,17 @@ public:
//=================================================================================================
// Solver -- the main class:
class Solver {
-
+ friend class CVC4::TSatProof< CVC4::BVMinisat::Solver>;
+public:
+ typedef Var TVar;
+ typedef Lit TLit;
+ typedef Clause TClause;
+ typedef CRef TCRef;
+ typedef vec<Lit> TLitVec;
+
+ static CRef TCRef_Undef;
+ static CRef TCRef_Lazy;
+private:
/** To notify */
Notify* notify;
@@ -89,12 +107,12 @@ public:
Var falseVar() const { return varFalse; }
- bool addClause (const vec<Lit>& ps); // Add a clause to the solver.
+ bool addClause (const vec<Lit>& ps, ClauseId& id); // Add a clause to the solver.
bool addEmptyClause(); // Add the empty clause, making the solver contradictory.
- bool addClause (Lit p); // Add a unit clause to the solver.
- bool addClause (Lit p, Lit q); // Add a binary clause to the solver.
- bool addClause (Lit p, Lit q, Lit r); // Add a ternary clause to the solver.
- bool addClause_( vec<Lit>& ps); // Add a clause to the solver without making superflous internal copy. Will
+ bool addClause (Lit p, ClauseId& id); // Add a unit clause to the solver.
+ bool addClause (Lit p, Lit q, ClauseId& id); // Add a binary clause to the solver.
+ bool addClause (Lit p, Lit q, Lit r, ClauseId& id); // Add a ternary clause to the solver.
+ bool addClause_( vec<Lit>& ps, ClauseId& id); // Add a clause to the solver without making superflous internal copy. Will
// change the passed vector 'ps'.
// Solving:
@@ -188,16 +206,14 @@ public:
// Bitvector Propagations
//
- void addMarkerLiteral(Var var) {
- // make sure it wasn't already marked
- Assert(marker[var] == 0);
- marker[var] = 1;
- }
+ void addMarkerLiteral(Var var);
bool need_to_propagate; // true if we added new clauses, set to true in propagation
bool only_bcp; // solving mode in which only boolean constraint propagation is done
void setOnlyBCP (bool val) { only_bcp = val;}
void explain(Lit l, std::vector<Lit>& explanation);
+
+ void setProofLog( CVC4::BitVectorProof * bvp );
protected:
@@ -274,6 +290,9 @@ protected:
int64_t conflict_budget; // -1 means no budget.
int64_t propagation_budget; // -1 means no budget.
bool asynch_interrupt;
+
+ //proof log
+ CVC4::BitVectorProof * d_bvp;
// Main internal methods:
//
@@ -340,6 +359,35 @@ protected:
// Returns a random integer 0 <= x < size. Seed must never be 0.
static inline int irand(double& seed, int size) {
return (int)(drand(seed) * size); }
+
+ // Less than for literals in an added clause when proofs are on.
+ struct assign_lt {
+ Solver& solver;
+ assign_lt(Solver& solver) : solver(solver) {}
+ bool operator () (Lit x, Lit y) {
+ lbool x_value = solver.value(x);
+ lbool y_value = solver.value(y);
+ // Two unassigned literals are sorted arbitrarily
+ if (x_value == l_Undef && y_value == l_Undef) {
+ return x < y;
+ }
+ // Unassigned literals are put to front
+ if (x_value == l_Undef) return true;
+ if (y_value == l_Undef) return false;
+ // Literals of the same value are sorted by decreasing levels
+ if (x_value == y_value) {
+ return solver.level(var(x)) > solver.level(var(y));
+ } else {
+ // True literals go up front
+ if (x_value == l_True) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+ };
+
};
@@ -380,11 +428,11 @@ inline void Solver::checkGarbage(double gf){
// NOTE: enqueue does not set the ok flag! (only public methods do)
inline bool Solver::enqueue (Lit p, CRef from) { return value(p) != l_Undef ? value(p) != l_False : (uncheckedEnqueue(p, from), true); }
-inline bool Solver::addClause (const vec<Lit>& ps) { ps.copyTo(add_tmp); return addClause_(add_tmp); }
-inline bool Solver::addEmptyClause () { add_tmp.clear(); return addClause_(add_tmp); }
-inline bool Solver::addClause (Lit p) { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp); }
-inline bool Solver::addClause (Lit p, Lit q) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp); }
-inline bool Solver::addClause (Lit p, Lit q, Lit r) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp); }
+inline bool Solver::addClause (const vec<Lit>& ps, ClauseId& id) { ps.copyTo(add_tmp); return addClause_(add_tmp, id); }
+inline bool Solver::addEmptyClause () { add_tmp.clear(); ClauseId tmp; return addClause_(add_tmp, tmp); }
+inline bool Solver::addClause (Lit p, ClauseId& id) { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp, id); }
+inline bool Solver::addClause (Lit p, Lit q, ClauseId& id) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp, id); }
+inline bool Solver::addClause (Lit p, Lit q, Lit r, ClauseId& id) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp, id); }
inline bool Solver::locked (const Clause& c) const { return value(c[0]) == l_True && reason(var(c[0])) != CRef_Undef && ca.lea(reason(var(c[0]))) == &c; }
inline void Solver::newDecisionLevel() { trail_lim.push(trail.size()); }
diff --git a/src/prop/bvminisat/core/SolverTypes.h b/src/prop/bvminisat/core/SolverTypes.h
index aa0921b78..1fd7ac5a7 100644
--- a/src/prop/bvminisat/core/SolverTypes.h
+++ b/src/prop/bvminisat/core/SolverTypes.h
@@ -31,6 +31,15 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
namespace CVC4 {
namespace BVMinisat {
+class Solver;
+}
+template <class Solver> class ProofProxy;
+typedef ProofProxy<BVMinisat::Solver> BVProofProxy;
+}
+
+namespace CVC4 {
+
+namespace BVMinisat {
//=================================================================================================
// Variables, literals, lifted booleans, clauses:
@@ -205,6 +214,8 @@ public:
const CRef CRef_Undef = RegionAllocator<uint32_t>::Ref_Undef;
+const CRef CRef_Lazy = RegionAllocator<uint32_t>::Ref_Undef - 1;
+
class ClauseAllocator : public RegionAllocator<uint32_t>
{
static int clauseWord32Size(int size, bool has_extra){
@@ -245,21 +256,7 @@ class ClauseAllocator : public RegionAllocator<uint32_t>
RegionAllocator<uint32_t>::free(clauseWord32Size(c.size(), c.has_extra()));
}
- void reloc(CRef& cr, ClauseAllocator& to)
- {
- Clause& c = operator[](cr);
-
- if (c.reloced()) { cr = c.relocation(); return; }
-
- cr = to.alloc(c, c.learnt());
- c.relocate(cr);
-
- // Copy extra data-fields:
- // (This could be cleaned-up. Generalize Clause-constructor to be applicable here instead?)
- to[cr].mark(c.mark());
- if (to[cr].learnt()) to[cr].activity() = c.activity();
- else if (to[cr].has_extra()) to[cr].calcAbstraction();
- }
+ void reloc(CRef& cr, ClauseAllocator& to, CVC4::BVProofProxy* proxy = NULL);
};
diff --git a/src/prop/bvminisat/simp/SimpSolver.cc b/src/prop/bvminisat/simp/SimpSolver.cc
index c5b185c95..311ed1dd1 100644
--- a/src/prop/bvminisat/simp/SimpSolver.cc
+++ b/src/prop/bvminisat/simp/SimpSolver.cc
@@ -24,6 +24,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
#include "options/bv_options.h"
#include "options/smt_options.h"
#include "utils/System.h"
+#include "proof/proof.h"
namespace CVC4 {
namespace BVMinisat {
@@ -62,7 +63,7 @@ SimpSolver::SimpSolver(CVC4::context::Context* c) :
, asymm_lits (0)
, eliminated_vars (0)
, elimorder (1)
- , use_simplification (true)
+ , use_simplification (!PROOF_ON())
, occurs (ClauseDeleted(ca))
, elim_heap (ElimLt(n_occ))
, bwdsub_assigns (0)
@@ -162,7 +163,7 @@ lbool SimpSolver::solve_(bool do_simp, bool turn_off_simp)
-bool SimpSolver::addClause_(vec<Lit>& ps)
+bool SimpSolver::addClause_(vec<Lit>& ps, ClauseId& id)
{
#ifndef NDEBUG
for (int i = 0; i < ps.size(); i++)
@@ -174,7 +175,7 @@ bool SimpSolver::addClause_(vec<Lit>& ps)
if (use_rcheck && implied(ps))
return true;
- if (!Solver::addClause_(ps))
+ if (!Solver::addClause_(ps, id))
return false;
if (use_simplification && clauses.size() == nclauses + 1){
@@ -544,9 +545,12 @@ bool SimpSolver::eliminateVar(Var v)
// Produce clauses in cross product:
vec<Lit>& resolvent = add_tmp;
for (int i = 0; i < pos.size(); i++)
- for (int j = 0; j < neg.size(); j++)
- if (merge(ca[pos[i]], ca[neg[j]], v, resolvent) && !addClause_(resolvent))
- return false;
+ for (int j = 0; j < neg.size(); j++) {
+ ClauseId id = -1;
+ if (merge(ca[pos[i]], ca[neg[j]], v, resolvent) &&
+ !addClause_(resolvent, id))
+ return false;
+ }
// Free occurs list for this variable:
occurs[v].clear(true);
@@ -582,8 +586,8 @@ bool SimpSolver::substitute(Var v, Lit x)
}
removeClause(cls[i]);
-
- if (!addClause_(subst_clause))
+ ClauseId id;
+ if (!addClause_(subst_clause, id))
return ok = false;
}
diff --git a/src/prop/bvminisat/simp/SimpSolver.h b/src/prop/bvminisat/simp/SimpSolver.h
index 85556e935..5f6f46b91 100644
--- a/src/prop/bvminisat/simp/SimpSolver.h
+++ b/src/prop/bvminisat/simp/SimpSolver.h
@@ -42,12 +42,12 @@ class SimpSolver : public Solver {
// Problem specification:
//
Var newVar (bool polarity = true, bool dvar = true, bool freeze = false);
- bool addClause (const vec<Lit>& ps);
+ bool addClause (const vec<Lit>& ps, ClauseId& id);
bool addEmptyClause(); // Add the empty clause to the solver.
- bool addClause (Lit p); // Add a unit clause to the solver.
- bool addClause (Lit p, Lit q); // Add a binary clause to the solver.
- bool addClause (Lit p, Lit q, Lit r); // Add a ternary clause to the solver.
- bool addClause_( vec<Lit>& ps);
+ bool addClause (Lit p, ClauseId& id); // Add a unit clause to the solver.
+ bool addClause (Lit p, Lit q, ClauseId& id); // Add a binary clause to the solver.
+ bool addClause (Lit p, Lit q, Lit r, ClauseId& id); // Add a ternary clause to the solver.
+ bool addClause_( vec<Lit>& ps, ClauseId& id);
bool substitute(Var v, Lit x); // Replace all occurences of v with x (may cause a contradiction).
// Variable mode:
@@ -178,11 +178,11 @@ inline void SimpSolver::updateElimHeap(Var v) {
elim_heap.update(v); }
-inline bool SimpSolver::addClause (const vec<Lit>& ps) { ps.copyTo(add_tmp); return addClause_(add_tmp); }
-inline bool SimpSolver::addEmptyClause() { add_tmp.clear(); return addClause_(add_tmp); }
-inline bool SimpSolver::addClause (Lit p) { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp); }
-inline bool SimpSolver::addClause (Lit p, Lit q) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp); }
-inline bool SimpSolver::addClause (Lit p, Lit q, Lit r) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp); }
+inline bool SimpSolver::addClause (const vec<Lit>& ps, ClauseId& id) { ps.copyTo(add_tmp); return addClause_(add_tmp, id); }
+inline bool SimpSolver::addEmptyClause() { add_tmp.clear(); ClauseId id; return addClause_(add_tmp, id); }
+inline bool SimpSolver::addClause (Lit p, ClauseId& id) { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp, id); }
+inline bool SimpSolver::addClause (Lit p, Lit q, ClauseId& id) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp, id); }
+inline bool SimpSolver::addClause (Lit p, Lit q, Lit r, ClauseId& id) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp, id); }
inline void SimpSolver::setFrozen (Var v, bool b) { frozen[v] = (char)b; if (use_simplification && !b) { updateElimHeap(v); } }
inline lbool SimpSolver::solve ( bool do_simp, bool turn_off_simp) {
diff --git a/src/prop/cnf_stream.cpp b/src/prop/cnf_stream.cpp
index b3666875d..a3d411738 100644
--- a/src/prop/cnf_stream.cpp
+++ b/src/prop/cnf_stream.cpp
@@ -24,6 +24,7 @@
#include "options/bv_options.h"
#include "proof/proof_manager.h"
#include "proof/sat_proof.h"
+#include "proof/cnf_proof.h"
#include "prop/cnf_stream.h"
#include "prop/minisat/minisat.h"
#include "prop/prop_engine.h"
@@ -47,7 +48,7 @@ namespace prop {
CnfStream::CnfStream(SatSolver* satSolver, Registrar* registrar,
context::Context* context, SmtGlobals* globals,
- bool fullLitToNodeMap)
+ bool fullLitToNodeMap, std::string name)
: d_satSolver(satSolver),
d_booleanVariables(context),
d_nodeToLiteralMap(context),
@@ -55,19 +56,21 @@ CnfStream::CnfStream(SatSolver* satSolver, Registrar* registrar,
d_fullLitToNodeMap(fullLitToNodeMap),
d_convertAndAssertCounter(0),
d_registrar(registrar),
- d_assertionTable(context),
+ d_name(name),
+ d_cnfProof(NULL),
d_globals(globals),
d_removable(false) {
}
TseitinCnfStream::TseitinCnfStream(SatSolver* satSolver, Registrar* registrar,
context::Context* context,
- SmtGlobals* globals, bool fullLitToNodeMap)
- : CnfStream(satSolver, registrar, context, globals, fullLitToNodeMap)
+ SmtGlobals* globals, bool fullLitToNodeMap,
+ std::string name)
+ : CnfStream(satSolver, registrar, context, globals, fullLitToNodeMap, name)
{}
-void CnfStream::assertClause(TNode node, SatClause& c, ProofRule proof_id) {
- Debug("cnf") << "Inserting into stream " << c << " node = " << node << ", proof id = " << proof_id << endl;
+void CnfStream::assertClause(TNode node, SatClause& c) {
+ Debug("cnf") << "Inserting into stream " << c << " node = " << node << endl;
if(Dump.isOn("clauses")) {
if(c.size() == 1) {
Dump("clauses") << AssertCommand(Expr(getNode(c[0]).toExpr()));
@@ -81,31 +84,41 @@ void CnfStream::assertClause(TNode node, SatClause& c, ProofRule proof_id) {
Dump("clauses") << AssertCommand(Expr(n.toExpr()));
}
}
- //store map between clause and original formula
- PROOF(ProofManager::currentPM()->setRegisteringFormula( node, proof_id ); );
- d_satSolver->addClause(c, d_removable, d_proofId);
- PROOF(ProofManager::currentPM()->setRegisteringFormula( Node::null(), RULE_INVALID ); );
+
+ PROOF(if (d_cnfProof) d_cnfProof->pushCurrentDefinition(node););
+
+ ClauseId clause_id = d_satSolver->addClause(c, d_removable);
+ if (clause_id == ClauseIdUndef) return; // nothing to store (no clause was added)
+
+ PROOF
+ (
+ if (d_cnfProof) {
+ Assert (clause_id != ClauseIdError);
+ d_cnfProof->registerConvertedClause(clause_id);
+ d_cnfProof->popCurrentDefinition();
+ }
+ );
}
-void CnfStream::assertClause(TNode node, SatLiteral a, ProofRule proof_id) {
+void CnfStream::assertClause(TNode node, SatLiteral a) {
SatClause clause(1);
clause[0] = a;
- assertClause(node, clause, proof_id);
+ assertClause(node, clause);
}
-void CnfStream::assertClause(TNode node, SatLiteral a, SatLiteral b, ProofRule proof_id) {
+void CnfStream::assertClause(TNode node, SatLiteral a, SatLiteral b) {
SatClause clause(2);
clause[0] = a;
clause[1] = b;
- assertClause(node, clause, proof_id);
+ assertClause(node, clause);
}
-void CnfStream::assertClause(TNode node, SatLiteral a, SatLiteral b, SatLiteral c, ProofRule proof_id) {
+void CnfStream::assertClause(TNode node, SatLiteral a, SatLiteral b, SatLiteral c) {
SatClause clause(3);
clause[0] = a;
clause[1] = b;
clause[2] = c;
- assertClause(node, clause, proof_id);
+ assertClause(node, clause);
}
bool CnfStream::hasLiteral(TNode n) const {
@@ -116,7 +129,6 @@ bool CnfStream::hasLiteral(TNode n) const {
void TseitinCnfStream::ensureLiteral(TNode n) {
// These are not removable and have no proof ID
d_removable = false;
- d_proofId = uint64_t(-1);
Debug("cnf") << "ensureLiteral(" << n << ")" << endl;
if(hasLiteral(n)) {
@@ -165,7 +177,7 @@ void TseitinCnfStream::ensureLiteral(TNode n) {
}
SatLiteral CnfStream::newLiteral(TNode node, bool isTheoryAtom, bool preRegister, bool canEliminate) {
- Debug("cnf") << "newLiteral(" << node << ", " << isTheoryAtom << ")" << endl;
+ Debug("cnf") << d_name << "::newLiteral(" << node << ", " << isTheoryAtom << ")" << endl;
Assert(node.getKind() != kind::NOT);
// Get the literal for this node
@@ -200,10 +212,9 @@ SatLiteral CnfStream::newLiteral(TNode node, bool isTheoryAtom, bool preRegister
if (preRegister) {
// In case we are re-entered due to lemmas, save our state
bool backupRemovable = d_removable;
- uint64_t backupProofId= d_proofId;
+ // Should be fine since cnfProof current assertion is stack based.
d_registrar->preRegister(node);
d_removable = backupRemovable;
- d_proofId = backupProofId;
}
// Here, you can have it
@@ -225,6 +236,11 @@ void CnfStream::getBooleanVariables(std::vector<TNode>& outputVariables) const {
}
}
+void CnfStream::setProof(CnfProof* proof) {
+ Assert (d_cnfProof == NULL);
+ d_cnfProof = proof;
+}
+
SatLiteral CnfStream::convertAtom(TNode node) {
Debug("cnf") << "convertAtom(" << node << ")" << endl;
@@ -268,10 +284,10 @@ SatLiteral TseitinCnfStream::handleXor(TNode xorNode) {
SatLiteral xorLit = newLiteral(xorNode);
- assertClause(xorNode.negate(), a, b, ~xorLit, RULE_TSEITIN);
- assertClause(xorNode.negate(), ~a, ~b, ~xorLit, RULE_TSEITIN);
- assertClause(xorNode, a, ~b, xorLit, RULE_TSEITIN);
- assertClause(xorNode, ~a, b, xorLit, RULE_TSEITIN);
+ assertClause(xorNode.negate(), a, b, ~xorLit);
+ assertClause(xorNode.negate(), ~a, ~b, ~xorLit);
+ assertClause(xorNode, a, ~b, xorLit);
+ assertClause(xorNode, ~a, b, xorLit);
return xorLit;
}
@@ -300,14 +316,14 @@ SatLiteral TseitinCnfStream::handleOr(TNode orNode) {
// lit | ~(a_1 | a_2 | a_3 | ... | a_n)
// (lit | ~a_1) & (lit | ~a_2) & (lit & ~a_3) & ... & (lit & ~a_n)
for(unsigned i = 0; i < n_children; ++i) {
- assertClause(orNode, orLit, ~clause[i], RULE_TSEITIN);
+ assertClause(orNode, orLit, ~clause[i]);
}
// lit -> (a_1 | a_2 | a_3 | ... | a_n)
// ~lit | a_1 | a_2 | a_3 | ... | a_n
clause[n_children] = ~orLit;
// This needs to go last, as the clause might get modified by the SAT solver
- assertClause(orNode.negate(), clause, RULE_TSEITIN);
+ assertClause(orNode.negate(), clause);
// Return the literal
return orLit;
@@ -337,7 +353,7 @@ SatLiteral TseitinCnfStream::handleAnd(TNode andNode) {
// ~lit | (a_1 & a_2 & a_3 & ... & a_n)
// (~lit | a_1) & (~lit | a_2) & ... & (~lit | a_n)
for(unsigned i = 0; i < n_children; ++i) {
- assertClause(andNode.negate(), ~andLit, ~clause[i], RULE_TSEITIN);
+ assertClause(andNode.negate(), ~andLit, ~clause[i]);
}
// lit <- (a_1 & a_2 & a_3 & ... a_n)
@@ -345,7 +361,7 @@ SatLiteral TseitinCnfStream::handleAnd(TNode andNode) {
// lit | ~a_1 | ~a_2 | ~a_3 | ... | ~a_n
clause[n_children] = andLit;
// This needs to go last, as the clause might get modified by the SAT solver
- assertClause(andNode, clause, RULE_TSEITIN);
+ assertClause(andNode, clause);
return andLit;
}
@@ -364,13 +380,13 @@ SatLiteral TseitinCnfStream::handleImplies(TNode impliesNode) {
// lit -> (a->b)
// ~lit | ~ a | b
- assertClause(impliesNode.negate(), ~impliesLit, ~a, b, RULE_TSEITIN);
+ assertClause(impliesNode.negate(), ~impliesLit, ~a, b);
// (a->b) -> lit
// ~(~a | b) | lit
// (a | l) & (~b | l)
- assertClause(impliesNode, a, impliesLit, RULE_TSEITIN);
- assertClause(impliesNode, ~b, impliesLit, RULE_TSEITIN);
+ assertClause(impliesNode, a, impliesLit);
+ assertClause(impliesNode, ~b, impliesLit);
return impliesLit;
}
@@ -393,16 +409,16 @@ SatLiteral TseitinCnfStream::handleIff(TNode iffNode) {
// lit -> ((a-> b) & (b->a))
// ~lit | ((~a | b) & (~b | a))
// (~a | b | ~lit) & (~b | a | ~lit)
- assertClause(iffNode.negate(), ~a, b, ~iffLit, RULE_TSEITIN);
- assertClause(iffNode.negate(), a, ~b, ~iffLit, RULE_TSEITIN);
+ assertClause(iffNode.negate(), ~a, b, ~iffLit);
+ assertClause(iffNode.negate(), a, ~b, ~iffLit);
// (a<->b) -> lit
// ~((a & b) | (~a & ~b)) | lit
// (~(a & b)) & (~(~a & ~b)) | lit
// ((~a | ~b) & (a | b)) | lit
// (~a | ~b | lit) & (a | b | lit)
- assertClause(iffNode, ~a, ~b, iffLit, RULE_TSEITIN);
- assertClause(iffNode, a, b, iffLit, RULE_TSEITIN);
+ assertClause(iffNode, ~a, ~b, iffLit);
+ assertClause(iffNode, a, b, iffLit);
return iffLit;
}
@@ -437,9 +453,9 @@ SatLiteral TseitinCnfStream::handleIte(TNode iteNode) {
// lit -> (t | e) & (b -> t) & (!b -> e)
// lit -> (t | e) & (!b | t) & (b | e)
// (!lit | t | e) & (!lit | !b | t) & (!lit | b | e)
- assertClause(iteNode.negate(), ~iteLit, thenLit, elseLit, RULE_TSEITIN);
- assertClause(iteNode.negate(), ~iteLit, ~condLit, thenLit, RULE_TSEITIN);
- assertClause(iteNode.negate(), ~iteLit, condLit, elseLit, RULE_TSEITIN);
+ assertClause(iteNode.negate(), ~iteLit, thenLit, elseLit);
+ assertClause(iteNode.negate(), ~iteLit, ~condLit, thenLit);
+ assertClause(iteNode.negate(), ~iteLit, condLit, elseLit);
// If ITE is false then one of the branches is false and the condition
// implies which one
@@ -447,9 +463,9 @@ SatLiteral TseitinCnfStream::handleIte(TNode iteNode) {
// !lit -> (!t | !e) & (b -> !t) & (!b -> !e)
// !lit -> (!t | !e) & (!b | !t) & (b | !e)
// (lit | !t | !e) & (lit | !b | !t) & (lit | b | !e)
- assertClause(iteNode, iteLit, ~thenLit, ~elseLit, RULE_TSEITIN);
- assertClause(iteNode, iteLit, ~condLit, ~thenLit, RULE_TSEITIN);
- assertClause(iteNode, iteLit, condLit, ~elseLit, RULE_TSEITIN);
+ assertClause(iteNode, iteLit, ~thenLit, ~elseLit);
+ assertClause(iteNode, iteLit, ~condLit, ~thenLit);
+ assertClause(iteNode, iteLit, condLit, ~elseLit);
return iteLit;
}
@@ -514,14 +530,14 @@ SatLiteral TseitinCnfStream::toCNF(TNode node, bool negated) {
else return ~nodeLit;
}
-void TseitinCnfStream::convertAndAssertAnd(TNode node, bool negated, ProofRule proof_id) {
+void TseitinCnfStream::convertAndAssertAnd(TNode node, bool negated) {
Assert(node.getKind() == AND);
if (!negated) {
// If the node is a conjunction, we handle each conjunct separately
for(TNode::const_iterator conjunct = node.begin(), node_end = node.end();
conjunct != node_end; ++conjunct ) {
- PROOF(ProofManager::currentPM()->setCnfDep( (*conjunct).toExpr(), node.toExpr() ) );
- convertAndAssert(*conjunct, false, proof_id);
+ PROOF(if (d_cnfProof) d_cnfProof->setCnfDependence(*conjunct, node););
+ convertAndAssert(*conjunct, false);
}
} else {
// If the node is a disjunction, we construct a clause and assert it
@@ -533,11 +549,11 @@ void TseitinCnfStream::convertAndAssertAnd(TNode node, bool negated, ProofRule p
clause[i] = toCNF(*disjunct, true);
}
Assert(disjunct == node.end());
- assertClause(node.negate(), clause, proof_id);
+ assertClause(node.negate(), clause);
}
}
-void TseitinCnfStream::convertAndAssertOr(TNode node, bool negated, ProofRule proof_id) {
+void TseitinCnfStream::convertAndAssertOr(TNode node, bool negated) {
Assert(node.getKind() == OR);
if (!negated) {
// If the node is a disjunction, we construct a clause and assert it
@@ -549,18 +565,18 @@ void TseitinCnfStream::convertAndAssertOr(TNode node, bool negated, ProofRule pr
clause[i] = toCNF(*disjunct, false);
}
Assert(disjunct == node.end());
- assertClause(node, clause, proof_id);
+ assertClause(node, clause);
} else {
// If the node is a conjunction, we handle each conjunct separately
for(TNode::const_iterator conjunct = node.begin(), node_end = node.end();
conjunct != node_end; ++conjunct ) {
- PROOF(ProofManager::currentPM()->setCnfDep( (*conjunct).negate().toExpr(), node.negate().toExpr() ) );
- convertAndAssert(*conjunct, true, proof_id);
+ PROOF(if (d_cnfProof) d_cnfProof->setCnfDependence((*conjunct).negate(), node.negate()););
+ convertAndAssert(*conjunct, true);
}
}
}
-void TseitinCnfStream::convertAndAssertXor(TNode node, bool negated, ProofRule proof_id) {
+void TseitinCnfStream::convertAndAssertXor(TNode node, bool negated) {
if (!negated) {
// p XOR q
SatLiteral p = toCNF(node[0], false);
@@ -569,11 +585,11 @@ void TseitinCnfStream::convertAndAssertXor(TNode node, bool negated, ProofRule p
SatClause clause1(2);
clause1[0] = ~p;
clause1[1] = ~q;
- assertClause(node, clause1, proof_id);
+ assertClause(node, clause1);
SatClause clause2(2);
clause2[0] = p;
clause2[1] = q;
- assertClause(node, clause2, proof_id);
+ assertClause(node, clause2);
} else {
// !(p XOR q) is the same as p <=> q
SatLiteral p = toCNF(node[0], false);
@@ -582,15 +598,15 @@ void TseitinCnfStream::convertAndAssertXor(TNode node, bool negated, ProofRule p
SatClause clause1(2);
clause1[0] = ~p;
clause1[1] = q;
- assertClause(node.negate(), clause1, proof_id);
+ assertClause(node.negate(), clause1);
SatClause clause2(2);
clause2[0] = p;
clause2[1] = ~q;
- assertClause(node.negate(), clause2, proof_id);
+ assertClause(node.negate(), clause2);
}
}
-void TseitinCnfStream::convertAndAssertIff(TNode node, bool negated, ProofRule proof_id) {
+void TseitinCnfStream::convertAndAssertIff(TNode node, bool negated) {
if (!negated) {
// p <=> q
SatLiteral p = toCNF(node[0], false);
@@ -599,11 +615,11 @@ void TseitinCnfStream::convertAndAssertIff(TNode node, bool negated, ProofRule p
SatClause clause1(2);
clause1[0] = ~p;
clause1[1] = q;
- assertClause(node, clause1, proof_id);
+ assertClause(node, clause1);
SatClause clause2(2);
clause2[0] = p;
clause2[1] = ~q;
- assertClause(node, clause2, proof_id);
+ assertClause(node, clause2);
} else {
// !(p <=> q) is the same as p XOR q
SatLiteral p = toCNF(node[0], false);
@@ -612,15 +628,15 @@ void TseitinCnfStream::convertAndAssertIff(TNode node, bool negated, ProofRule p
SatClause clause1(2);
clause1[0] = ~p;
clause1[1] = ~q;
- assertClause(node.negate(), clause1, proof_id);
+ assertClause(node.negate(), clause1);
SatClause clause2(2);
clause2[0] = p;
clause2[1] = q;
- assertClause(node.negate(), clause2, proof_id);
+ assertClause(node.negate(), clause2);
}
}
-void TseitinCnfStream::convertAndAssertImplies(TNode node, bool negated, ProofRule proof_id) {
+void TseitinCnfStream::convertAndAssertImplies(TNode node, bool negated) {
if (!negated) {
// p => q
SatLiteral p = toCNF(node[0], false);
@@ -629,17 +645,17 @@ void TseitinCnfStream::convertAndAssertImplies(TNode node, bool negated, ProofRu
SatClause clause(2);
clause[0] = ~p;
clause[1] = q;
- assertClause(node, clause, proof_id);
+ assertClause(node, clause);
} else {// Construct the
- PROOF(ProofManager::currentPM()->setCnfDep( node[0].toExpr(), node.negate().toExpr() ) );
- PROOF(ProofManager::currentPM()->setCnfDep( node[1].negate().toExpr(), node.negate().toExpr() ) );
+ PROOF(if (d_cnfProof) d_cnfProof->setCnfDependence(node[0], node.negate()););
+ PROOF(if (d_cnfProof) d_cnfProof->setCnfDependence(node[1].negate(), node.negate()););
// !(p => q) is the same as (p && ~q)
- convertAndAssert(node[0], false, proof_id);
- convertAndAssert(node[1], true, proof_id);
+ convertAndAssert(node[0], false);
+ convertAndAssert(node[1], true);
}
}
-void TseitinCnfStream::convertAndAssertIte(TNode node, bool negated, ProofRule proof_id) {
+void TseitinCnfStream::convertAndAssertIte(TNode node, bool negated) {
// ITE(p, q, r)
SatLiteral p = toCNF(node[0], false);
SatLiteral q = toCNF(node[1], negated);
@@ -653,35 +669,47 @@ void TseitinCnfStream::convertAndAssertIte(TNode node, bool negated, ProofRule p
SatClause clause1(2);
clause1[0] = ~p;
clause1[1] = q;
- assertClause(nnode, clause1, proof_id);
+ assertClause(nnode, clause1);
SatClause clause2(2);
clause2[0] = p;
clause2[1] = r;
- assertClause(nnode, clause2, proof_id);
+ assertClause(nnode, clause2);
}
// At the top level we must ensure that all clauses that are asserted are
// not unit, except for the direct assertions. This allows us to remove the
// clauses later when they are not needed anymore (lemmas for example).
-void TseitinCnfStream::convertAndAssert(TNode node, bool removable, bool negated, ProofRule proof_id, TNode from) {
- Debug("cnf") << "convertAndAssert(" << node << ", removable = " << (removable ? "true" : "false") << ", negated = " << (negated ? "true" : "false") << ")" << endl;
+void TseitinCnfStream::convertAndAssert(TNode node,
+ bool removable,
+ bool negated,
+ ProofRule proof_id,
+ TNode from) {
+ Debug("cnf") << "convertAndAssert(" << node
+ << ", removable = " << (removable ? "true" : "false")
+ << ", negated = " << (negated ? "true" : "false") << ")" << endl;
d_removable = removable;
- if(options::proof() || options::unsatCores()) {
- // Encode the assertion ID in the proof_id to store with generated clauses.
- uint64_t assertionTableIndex = d_assertionTable.size();
- Assert((uint64_t(proof_id) & 0xffffffff00000000llu) == 0 && (assertionTableIndex & 0xffffffff00000000llu) == 0, "proof_id/table_index collision");
- d_proofId = assertionTableIndex | (uint64_t(proof_id) << 32);
- d_assertionTable.push_back(from.isNull() ? node : from);
- Debug("cores") << "; cnf is " << assertionTableIndex << " asst " << node << " proof_id " << proof_id << " from " << from << endl;
- } else {
- // We aren't producing proofs or unsat cores; use an invalid proof id.
- d_proofId = uint64_t(-1);
- }
- convertAndAssert(node, negated, proof_id);
+ PROOF
+ (if (d_cnfProof) {
+ Node assertion = negated ? node.notNode() : (Node)node;
+ Node from_assertion = negated? from.notNode() : (Node) from;
+
+ if (proof_id != RULE_INVALID) {
+ d_cnfProof->pushCurrentAssertion(from.isNull() ? assertion : from_assertion);
+ d_cnfProof->registerAssertion(from.isNull() ? assertion : from_assertion, proof_id);
+ }
+ else {
+ d_cnfProof->pushCurrentAssertion(assertion);
+ d_cnfProof->registerAssertion(assertion, proof_id);
+ }
+ });
+
+ convertAndAssert(node, negated);
+ PROOF(if (d_cnfProof) d_cnfProof->popCurrentAssertion(); );
}
-void TseitinCnfStream::convertAndAssert(TNode node, bool negated, ProofRule proof_id) {
- Debug("cnf") << "convertAndAssert(" << node << ", negated = " << (negated ? "true" : "false") << ")" << endl;
+void TseitinCnfStream::convertAndAssert(TNode node, bool negated) {
+ Debug("cnf") << "convertAndAssert(" << node
+ << ", negated = " << (negated ? "true" : "false") << ")" << endl;
if (d_convertAndAssertCounter % ResourceManager::getFrequencyCount() == 0) {
NodeManager::currentResourceManager()->spendResource(options::cnfStep());
@@ -691,25 +719,25 @@ void TseitinCnfStream::convertAndAssert(TNode node, bool negated, ProofRule proo
switch(node.getKind()) {
case AND:
- convertAndAssertAnd(node, negated, proof_id);
+ convertAndAssertAnd(node, negated);
break;
case OR:
- convertAndAssertOr(node, negated, proof_id);
+ convertAndAssertOr(node, negated);
break;
case IFF:
- convertAndAssertIff(node, negated, proof_id);
+ convertAndAssertIff(node, negated);
break;
case XOR:
- convertAndAssertXor(node, negated, proof_id);
+ convertAndAssertXor(node, negated);
break;
case IMPLIES:
- convertAndAssertImplies(node, negated, proof_id);
+ convertAndAssertImplies(node, negated);
break;
case ITE:
- convertAndAssertIte(node, negated, proof_id);
+ convertAndAssertIte(node, negated);
break;
case NOT:
- convertAndAssert(node[0], !negated, proof_id);
+ convertAndAssert(node[0], !negated);
break;
default:
{
@@ -718,7 +746,7 @@ void TseitinCnfStream::convertAndAssert(TNode node, bool negated, ProofRule proo
nnode = node.negate();
}
// Atoms
- assertClause(nnode, toCNF(node, negated), proof_id);
+ assertClause(nnode, toCNF(node, negated));
}
break;
}
diff --git a/src/prop/cnf_stream.h b/src/prop/cnf_stream.h
index cfab216fe..a07944a58 100644
--- a/src/prop/cnf_stream.h
+++ b/src/prop/cnf_stream.h
@@ -84,8 +84,11 @@ protected:
/** The "registrar" for pre-registration of terms */
Registrar* d_registrar;
- /** A table of assertions, used for regenerating proofs. */
- context::CDList<Node> d_assertionTable;
+ /** The name of this CNF stream*/
+ std::string d_name;
+
+ /** Pointer to the proof corresponding to this CnfStream */
+ CnfProof* d_cnfProof;
/** Container for misc. globals. */
SmtGlobals* d_globals;
@@ -117,14 +120,6 @@ protected:
}
/**
- * A reference into the assertion table, used to map clauses back to
- * their "original" input assertion/lemma. This variable is manipulated
- * by the top-level convertAndAssert(). This is needed in proofs-enabled
- * runs, to justify where the SAT solver's clauses came from.
- */
- uint64_t d_proofId;
-
- /**
* Are we asserting a removable clause (true) or a permanent clause (false).
* This is set at the beginning of convertAndAssert so that it doesn't
* need to be passed on over the stack. Only pure clauses can be asserted
@@ -137,14 +132,14 @@ protected:
* @param node the node giving rise to this clause
* @param clause the clause to assert
*/
- void assertClause(TNode node, SatClause& clause, ProofRule proof_id);
+ void assertClause(TNode node, SatClause& clause);
/**
* Asserts the unit clause to the sat solver.
* @param node the node giving rise to this clause
* @param a the unit literal of the clause
*/
- void assertClause(TNode node, SatLiteral a, ProofRule proof_id);
+ void assertClause(TNode node, SatLiteral a);
/**
* Asserts the binary clause to the sat solver.
@@ -152,7 +147,7 @@ protected:
* @param a the first literal in the clause
* @param b the second literal in the clause
*/
- void assertClause(TNode node, SatLiteral a, SatLiteral b, ProofRule proof_id);
+ void assertClause(TNode node, SatLiteral a, SatLiteral b);
/**
* Asserts the ternary clause to the sat solver.
@@ -161,7 +156,7 @@ protected:
* @param b the second literal in the clause
* @param c the thirs literal in the clause
*/
- void assertClause(TNode node, SatLiteral a, SatLiteral b, SatLiteral c, ProofRule proof_id);
+ void assertClause(TNode node, SatLiteral a, SatLiteral b, SatLiteral c);
/**
* Acquires a new variable from the SAT solver to represent the node
@@ -193,9 +188,15 @@ public:
* @param registrar the entity that takes care of preregistration of Nodes
* @param context the context that the CNF should respect
* @param fullLitToNodeMap maintain a full SAT-literal-to-Node mapping,
+ * @param name string identifier to distinguish between different instances
* even for non-theory literals
*/
- CnfStream(SatSolver* satSolver, Registrar* registrar, context::Context* context, SmtGlobals* globals, bool fullLitToNodeMap = false);
+ CnfStream(SatSolver* satSolver,
+ Registrar* registrar,
+ context::Context* context,
+ SmtGlobals* globals,
+ bool fullLitToNodeMap = false,
+ std::string name="");
/**
* Destructs a CnfStream. This implementation does nothing, but we
@@ -244,13 +245,6 @@ public:
SatLiteral getLiteral(TNode node);
/**
- * Get the assertion with a given ID. (Used for reconstructing proofs.)
- */
- TNode getAssertion(uint64_t id) {
- return d_assertionTable[id];
- }
-
- /**
* Returns the Boolean variables from the input problem.
*/
void getBooleanVariables(std::vector<TNode>& outputVariables) const;
@@ -263,6 +257,7 @@ public:
return d_literalToNodeMap;
}
+ void setProof(CnfProof* proof);
};/* class CnfStream */
@@ -286,7 +281,8 @@ public:
* @param removable is this something that can be erased
* @param negated true if negated
*/
- void convertAndAssert(TNode node, bool removable, bool negated, ProofRule proof_id, TNode from = TNode::null());
+ void convertAndAssert(TNode node, bool removable,
+ bool negated, ProofRule rule, TNode from = TNode::null());
/**
* Constructs the stream to use the given sat solver.
@@ -295,14 +291,14 @@ public:
* @param fullLitToNodeMap maintain a full SAT-literal-to-Node mapping,
* even for non-theory literals
*/
- TseitinCnfStream(SatSolver* satSolver, Registrar* registrar, context::Context* context, SmtGlobals* globals, bool fullLitToNodeMap = false);
+ TseitinCnfStream(SatSolver* satSolver, Registrar* registrar, context::Context* context, SmtGlobals* globals, bool fullLitToNodeMap = false, std::string name = "");
private:
/**
* Same as above, except that removable is remembered.
*/
- void convertAndAssert(TNode node, bool negated, ProofRule proof_id);
+ void convertAndAssert(TNode node, bool negated);
// Each of these formulas handles takes care of a Node of each Kind.
//
@@ -322,12 +318,12 @@ private:
SatLiteral handleAnd(TNode node);
SatLiteral handleOr(TNode node);
- void convertAndAssertAnd(TNode node, bool negated, ProofRule proof_id);
- void convertAndAssertOr(TNode node, bool negated, ProofRule proof_id);
- void convertAndAssertXor(TNode node, bool negated, ProofRule proof_id);
- void convertAndAssertIff(TNode node, bool negated, ProofRule proof_id);
- void convertAndAssertImplies(TNode node, bool negated, ProofRule proof_id);
- void convertAndAssertIte(TNode node, bool negated, ProofRule proof_id);
+ void convertAndAssertAnd(TNode node, bool negated);
+ void convertAndAssertOr(TNode node, bool negated);
+ void convertAndAssertXor(TNode node, bool negated);
+ void convertAndAssertIff(TNode node, bool negated);
+ void convertAndAssertImplies(TNode node, bool negated);
+ void convertAndAssertIte(TNode node, bool negated);
/**
* Transforms the node into CNF recursively.
diff --git a/src/prop/minisat/core/Solver.cc b/src/prop/minisat/core/Solver.cc
index 4c431a9b1..f4489c4be 100644
--- a/src/prop/minisat/core/Solver.cc
+++ b/src/prop/minisat/core/Solver.cc
@@ -25,6 +25,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
#include "base/output.h"
#include "options/prop_options.h"
#include "proof/proof_manager.h"
+#include "proof/sat_proof_implementation.h"
#include "proof/sat_proof.h"
#include "prop/minisat/core/Solver.h"
#include "prop/minisat/minisat.h"
@@ -32,6 +33,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
#include "prop/theory_proxy.h"
#include "smt_util/command.h"
+
using namespace CVC4::prop;
namespace CVC4 {
@@ -40,7 +42,6 @@ namespace Minisat {
//=================================================================================================
// Options:
-
static const char* _cat = "CORE";
static DoubleOption opt_var_decay (_cat, "var-decay", "The variable activity decay factor", 0.95, DoubleRange(0, false, 1, false));
@@ -55,6 +56,10 @@ static IntOption opt_restart_first (_cat, "rfirst", "The base resta
static DoubleOption opt_restart_inc (_cat, "rinc", "Restart interval increase factor", 3, DoubleRange(1, false, HUGE_VAL, false));
static DoubleOption opt_garbage_frac (_cat, "gc-frac", "The fraction of wasted memory allowed before a garbage collection is triggered", 0.20, DoubleRange(0, false, HUGE_VAL, false));
+//=================================================================================================
+// Proof declarations
+CRef Solver::TCRef_Undef = CRef_Undef;
+CRef Solver::TCRef_Lazy = CRef_Lazy;
class ScopedBool {
bool& watch;
@@ -135,8 +140,12 @@ Solver::Solver(CVC4::prop::TheoryProxy* proxy, CVC4::context::Context* context,
// Assert the constants
uncheckedEnqueue(mkLit(varTrue, false));
uncheckedEnqueue(mkLit(varFalse, true));
- PROOF( ProofManager::getSatProof()->registerUnitClause(mkLit(varTrue, false), INPUT, uint64_t(-1)); )
- PROOF( ProofManager::getSatProof()->registerUnitClause(mkLit(varFalse, true), INPUT, uint64_t(-1)); )
+ // FIXME: these should be axioms I believe
+ PROOF
+ (
+ ProofManager::getSatProof()->registerTrueLit(mkLit(varTrue, false));
+ ProofManager::getSatProof()->registerFalseLit(mkLit(varFalse, true));
+ );
}
@@ -217,7 +226,9 @@ CRef Solver::reason(Var x) {
// Get the explanation from the theory
SatClause explanation_cl;
- proxy->explainPropagation(MinisatSatSolver::toSatLiteral(l), explanation_cl);
+ // FIXME: at some point return a tag with the theory that spawned you
+ proxy->explainPropagation(MinisatSatSolver::toSatLiteral(l),
+ explanation_cl);
vec<Lit> explanation;
MinisatSatSolver::toMinisatClause(explanation_cl, explanation);
@@ -263,7 +274,12 @@ CRef Solver::reason(Var x) {
// Construct the reason
CRef real_reason = ca.alloc(explLevel, explanation, true);
- PROOF (ProofManager::getSatProof()->registerClause(real_reason, THEORY_LEMMA, (uint64_t(RULE_CONFLICT) << 32)); );
+ // FIXME: at some point will need more information about where this explanation
+ // came from (ie. the theory/sharing)
+ PROOF (ClauseId id = ProofManager::getSatProof()->registerClause(real_reason, THEORY_LEMMA);
+ ProofManager::getCnfProof()->registerConvertedClause(id, true);
+ // no need to pop current assertion as this is not converted to cnf
+ );
vardata[x] = VarData(real_reason, level(x), user_level(x), intro_level(x), trail_index(x));
clauses_removable.push(real_reason);
attachClause(real_reason);
@@ -271,7 +287,7 @@ CRef Solver::reason(Var x) {
return real_reason;
}
-bool Solver::addClause_(vec<Lit>& ps, bool removable, uint64_t proof_id)
+bool Solver::addClause_(vec<Lit>& ps, bool removable, ClauseId& id)
{
if (!ok) return false;
@@ -289,11 +305,13 @@ bool Solver::addClause_(vec<Lit>& ps, bool removable, uint64_t proof_id)
clauseLevel = std::max(clauseLevel, intro_level(var(ps[i])));
// Tautologies are ignored
if (ps[i] == ~p) {
+ id = ClauseIdUndef;
// Clause can be ignored
return true;
}
// Clauses with 0-level true literals are also ignored
if (value(ps[i]) == l_True && level(var(ps[i])) == 0 && user_level(var(ps[i])) == 0) {
+ id = ClauseIdUndef;
return true;
}
// Ignore repeated literals
@@ -321,8 +339,19 @@ bool Solver::addClause_(vec<Lit>& ps, bool removable, uint64_t proof_id)
lemmas.push();
ps.copyTo(lemmas.last());
lemmas_removable.push(removable);
- Debug("cores") << "lemma push " << proof_id << " " << (proof_id & 0xffffffff) << std::endl;
- lemmas_proof_id.push(proof_id);
+ PROOF(
+ // Store the expression being converted to CNF until
+ // the clause is actually created
+ Node assertion = ProofManager::getCnfProof()->getCurrentAssertion();
+ Node def = ProofManager::getCnfProof()->getCurrentDefinition();
+ lemmas_cnf_assertion.push_back(std::make_pair(assertion, def));
+ id = ClauseIdUndef;
+ );
+ // does it have to always be a lemma?
+ // PROOF(id = ProofManager::getSatProof()->registerUnitClause(ps[0], THEORY_LEMMA););
+ // PROOF(id = ProofManager::getSatProof()->registerTheoryLemma(ps););
+ // Debug("cores") << "lemma push " << proof_id << " " << (proof_id & 0xffffffff) << std::endl;
+ // lemmas_proof_id.push(proof_id);
} else {
// If all false, we're in conflict
if (ps.size() == falseLiteralsCount) {
@@ -331,7 +360,7 @@ bool Solver::addClause_(vec<Lit>& ps, bool removable, uint64_t proof_id)
// construct the clause below to give to the proof manager
// as the final conflict.
if(falseLiteralsCount == 1) {
- PROOF( ProofManager::getSatProof()->storeUnitConflict(ps[0], INPUT, proof_id); )
+ PROOF( id = ProofManager::getSatProof()->storeUnitConflict(ps[0], INPUT); )
PROOF( ProofManager::getSatProof()->finalizeProof(CVC4::Minisat::CRef_Lazy); )
return ok = false;
}
@@ -353,7 +382,9 @@ bool Solver::addClause_(vec<Lit>& ps, bool removable, uint64_t proof_id)
attachClause(cr);
if(PROOF_ON()) {
- PROOF( ProofManager::getSatProof()->registerClause(cr, INPUT, proof_id); )
+ PROOF(
+ id = ProofManager::getSatProof()->registerClause(cr, INPUT);
+ )
if(ps.size() == falseLiteralsCount) {
PROOF( ProofManager::getSatProof()->finalizeProof(cr); )
return ok = false;
@@ -366,12 +397,16 @@ bool Solver::addClause_(vec<Lit>& ps, bool removable, uint64_t proof_id)
if(assigns[var(ps[0])] == l_Undef) {
assert(assigns[var(ps[0])] != l_False);
uncheckedEnqueue(ps[0], cr);
- Debug("cores") << "i'm registering a unit clause, input, proof id " << proof_id << std::endl;
- PROOF( if(ps.size() == 1) { ProofManager::getSatProof()->registerUnitClause(ps[0], INPUT, proof_id); } );
+ Debug("cores") << "i'm registering a unit clause, input" << std::endl;
+ PROOF(
+ if(ps.size() == 1) {
+ id = ProofManager::getSatProof()->registerUnitClause(ps[0], INPUT);
+ }
+ );
CRef confl = propagate(CHECK_WITHOUT_THEORY);
if(! (ok = (confl == CRef_Undef)) ) {
if(ca[confl].size() == 1) {
- PROOF( ProofManager::getSatProof()->storeUnitConflict(ca[confl][0], LEARNT, proof_id); );
+ PROOF( id = ProofManager::getSatProof()->storeUnitConflict(ca[confl][0], LEARNT); );
PROOF( ProofManager::getSatProof()->finalizeProof(CVC4::Minisat::CRef_Lazy); )
} else {
PROOF( ProofManager::getSatProof()->finalizeProof(confl); );
@@ -604,7 +639,7 @@ int Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel)
for (int j = (p == lit_Undef) ? 0 : 1; j < c.size(); j++){
Lit q = c[j];
- if (!seen[var(q)] && level(var(q)) > 0){
+ if (!seen[var(q)] && level(var(q)) > 0) {
varBumpActivity(var(q));
seen[var(q)] = 1;
if (level(var(q)) >= decisionLevel())
@@ -646,7 +681,7 @@ int Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel)
uint32_t abstract_level = 0;
for (i = 1; i < out_learnt.size(); i++)
abstract_level |= abstractLevel(var(out_learnt[i])); // (maintain an abstraction of levels involved in conflict)
-
+
for (i = j = 1; i < out_learnt.size(); i++) {
if (reason(var(out_learnt[i])) == CRef_Undef) {
out_learnt[j++] = out_learnt[i];
@@ -901,7 +936,8 @@ void Solver::propagateTheory() {
proxy->explainPropagation(MinisatSatSolver::toSatLiteral(p), explanation_cl);
vec<Lit> explanation;
MinisatSatSolver::toMinisatClause(explanation_cl, explanation);
- addClause(explanation, true, 0);
+ ClauseId id; // FIXME: mark it as explanation here somehow?
+ addClause(explanation, true, id);
}
}
}
@@ -1159,8 +1195,17 @@ lbool Solver::search(int nof_conflicts)
attachClause(cr);
claBumpActivity(ca[cr]);
uncheckedEnqueue(learnt_clause[0], cr);
-
- PROOF( ProofManager::getSatProof()->endResChain(cr); )
+ PROOF(
+ ClauseId id = ProofManager::getSatProof()->registerClause(cr, LEARNT);
+ PSTATS(
+ __gnu_cxx::hash_set<int> cl_levels;
+ for (int i = 0; i < learnt_clause.size(); ++i) {
+ cl_levels.insert(level(var(learnt_clause[i])));
+ }
+ ProofManager::getSatProof()->storeClauseGlue(id, cl_levels.size());
+ )
+ ProofManager::getSatProof()->endResChain(id);
+ );
}
varDecayActivity();
@@ -1650,14 +1695,14 @@ CRef Solver::updateLemmas() {
// Last index in the trail
int backtrack_index = trail.size();
+ PROOF(Assert (lemmas.size() == (int)lemmas_cnf_assertion.size()););
+
// Attach all the clauses and enqueue all the propagations
for (int i = 0; i < lemmas.size(); ++ i)
{
// The current lemma
vec<Lit>& lemma = lemmas[i];
bool removable = lemmas_removable[i];
- uint64_t proof_id = lemmas_proof_id[i];
- Debug("cores") << "pulled lemma proof id " << proof_id << " " << (proof_id & 0xffffffff) << std::endl;
// Attach it if non-unit
CRef lemma_ref = CRef_Undef;
@@ -1672,7 +1717,15 @@ CRef Solver::updateLemmas() {
}
lemma_ref = ca.alloc(clauseLevel, lemma, removable);
- PROOF( ProofManager::getSatProof()->registerClause(lemma_ref, THEORY_LEMMA, proof_id); );
+ PROOF
+ (
+ TNode cnf_assertion = lemmas_cnf_assertion[i].first;
+ TNode cnf_def = lemmas_cnf_assertion[i].second;
+
+ ClauseId id = ProofManager::getSatProof()->registerClause(lemma_ref, THEORY_LEMMA);
+ ProofManager::getCnfProof()->setClauseAssertion(id, cnf_assertion);
+ ProofManager::getCnfProof()->setClauseDefinition(id, cnf_def);
+ );
if (removable) {
clauses_removable.push(lemma_ref);
} else {
@@ -1680,7 +1733,15 @@ CRef Solver::updateLemmas() {
}
attachClause(lemma_ref);
} else {
- PROOF( ProofManager::getSatProof()->registerUnitClause(lemma[0], THEORY_LEMMA, proof_id); );
+ PROOF
+ (
+ Node cnf_assertion = lemmas_cnf_assertion[i].first;
+ Node cnf_def = lemmas_cnf_assertion[i].second;
+
+ ClauseId id = ProofManager::getSatProof()->registerUnitClause(lemma[0], THEORY_LEMMA);
+ ProofManager::getCnfProof()->setClauseAssertion(id, cnf_assertion);
+ ProofManager::getCnfProof()->setClauseDefinition(id, cnf_def);
+ );
}
// If the lemma is propagating enqueue its literal (or set the conflict)
@@ -1694,7 +1755,7 @@ CRef Solver::updateLemmas() {
} else {
Debug("minisat::lemmas") << "Solver::updateLemmas(): unit conflict or empty clause" << std::endl;
conflict = CRef_Lazy;
- PROOF( ProofManager::getSatProof()->storeUnitConflict(lemma[0], LEARNT, proof_id); );
+ PROOF( ProofManager::getSatProof()->storeUnitConflict(lemma[0], LEARNT); );
}
} else {
Debug("minisat::lemmas") << "lemma size is " << lemma.size() << std::endl;
@@ -1704,10 +1765,11 @@ CRef Solver::updateLemmas() {
}
}
+ PROOF(Assert (lemmas.size() == (int)lemmas_cnf_assertion.size()););
// Clear the lemmas
lemmas.clear();
+ lemmas_cnf_assertion.clear();
lemmas_removable.clear();
- lemmas_proof_id.clear();
if (conflict != CRef_Undef) {
theoryConflict = true;
@@ -1718,6 +1780,28 @@ CRef Solver::updateLemmas() {
return conflict;
}
+void ClauseAllocator::reloc(CRef& cr, ClauseAllocator& to, CVC4::CoreProofProxy* proxy)
+{
+
+ // FIXME what is this CRef_lazy
+ if (cr == CRef_Lazy) return;
+
+ CRef old = cr; // save the old reference
+ Clause& c = operator[](cr);
+ if (c.reloced()) { cr = c.relocation(); return; }
+
+ cr = to.alloc(c.level(), c, c.removable());
+ c.relocate(cr);
+ if (proxy) {
+ proxy->updateCRef(old, cr);
+ }
+ // Copy extra data-fields:
+ // (This could be cleaned-up. Generalize Clause-constructor to be applicable here instead?)
+ to[cr].mark(c.mark());
+ if (to[cr].removable()) to[cr].activity() = c.activity();
+ else if (to[cr].has_extra()) to[cr].calcAbstraction();
+}
+
inline bool Solver::withinBudget(uint64_t ammount) const {
Assert (proxy);
// spendResource sets async_interrupt or throws UnsafeInterruptException
diff --git a/src/prop/minisat/core/Solver.h b/src/prop/minisat/core/Solver.h
index 3be6b1b22..a239eba72 100644
--- a/src/prop/minisat/core/Solver.h
+++ b/src/prop/minisat/core/Solver.h
@@ -37,13 +37,15 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
namespace CVC4 {
- class SatProof;
+template <class Solver> class TSatProof;
- namespace prop {
- class TheoryProxy;
- }/* CVC4::prop namespace */
+namespace prop {
+ class TheoryProxy;
+}/* CVC4::prop namespace */
}/* CVC4 namespace */
+typedef unsigned ClauseId;
+
namespace CVC4 {
namespace Minisat {
@@ -54,7 +56,18 @@ class Solver {
/** The only two CVC4 entry points to the private solver data */
friend class CVC4::prop::TheoryProxy;
- friend class CVC4::SatProof;
+ friend class CVC4::TSatProof<Minisat::Solver>;
+
+public:
+ static CRef TCRef_Undef;
+ static CRef TCRef_Lazy;
+
+ typedef Var TVar;
+ typedef Lit TLit;
+ typedef Clause TClause;
+ typedef CRef TCRef;
+ typedef vec<Lit> TLitVec;
+
protected:
/** The pointer to the proxy that provides interfaces to the SMT engine */
@@ -85,8 +98,8 @@ protected:
/** Is the lemma removable */
vec<bool> lemmas_removable;
- /** Proof IDs for lemmas */
- vec<uint64_t> lemmas_proof_id;
+ /** Nodes being converted to CNF */
+ std::vector< std::pair<CVC4::Node, CVC4::Node > >lemmas_cnf_assertion;
/** Do a another check if FULL_EFFORT was the last one */
bool recheck;
@@ -157,14 +170,14 @@ public:
void push ();
void pop ();
- // CVC4 adds the "proof_id" here to refer to the input assertion/lemma
- // that produced this clause
- bool addClause (const vec<Lit>& ps, bool removable, uint64_t proof_id); // Add a clause to the solver.
- bool addEmptyClause(bool removable); // Add the empty clause, making the solver contradictory.
- bool addClause (Lit p, bool removable, uint64_t proof_id); // Add a unit clause to the solver.
- bool addClause (Lit p, Lit q, bool removable, uint64_t proof_id); // Add a binary clause to the solver.
- bool addClause (Lit p, Lit q, Lit r, bool removable, uint64_t proof_id); // Add a ternary clause to the solver.
- bool addClause_( vec<Lit>& ps, bool removable, uint64_t proof_id); // Add a clause to the solver without making superflous internal copy. Will
+ // addClause returns the ClauseId corresponding to the clause added in the
+ // reference parameter id.
+ bool addClause (const vec<Lit>& ps, bool removable, ClauseId& id); // Add a clause to the solver.
+ bool addEmptyClause(bool removable); // Add the empty clause, making the solver contradictory.
+ bool addClause (Lit p, bool removable, ClauseId& id); // Add a unit clause to the solver.
+ bool addClause (Lit p, Lit q, bool removable, ClauseId& id); // Add a binary clause to the solver.
+ bool addClause (Lit p, Lit q, Lit r, bool removable, ClauseId& id); // Add a ternary clause to the solver.
+ bool addClause_( vec<Lit>& ps, bool removable, ClauseId& id); // Add a clause to the solver without making superflous internal copy. Will
// change the passed vector 'ps'.
// Solving:
@@ -495,15 +508,15 @@ inline void Solver::checkGarbage(double gf){
// NOTE: enqueue does not set the ok flag! (only public methods do)
inline bool Solver::enqueue (Lit p, CRef from) { return value(p) != l_Undef ? value(p) != l_False : (uncheckedEnqueue(p, from), true); }
-inline bool Solver::addClause (const vec<Lit>& ps, bool removable, uint64_t proof_id)
- { ps.copyTo(add_tmp); return addClause_(add_tmp, removable, proof_id); }
-inline bool Solver::addEmptyClause (bool removable) { add_tmp.clear(); return addClause_(add_tmp, removable, uint64_t(-1)); }
-inline bool Solver::addClause (Lit p, bool removable, uint64_t proof_id)
- { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp, removable, proof_id); }
-inline bool Solver::addClause (Lit p, Lit q, bool removable, uint64_t proof_id)
- { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp, removable, proof_id); }
-inline bool Solver::addClause (Lit p, Lit q, Lit r, bool removable, uint64_t proof_id)
- { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp, removable, proof_id); }
+inline bool Solver::addClause (const vec<Lit>& ps, bool removable, ClauseId& id)
+ { ps.copyTo(add_tmp); return addClause_(add_tmp, removable, id); }
+inline bool Solver::addEmptyClause (bool removable) { add_tmp.clear(); ClauseId tmp; return addClause_(add_tmp, removable, tmp); }
+inline bool Solver::addClause (Lit p, bool removable, ClauseId& id)
+ { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp, removable, id); }
+inline bool Solver::addClause (Lit p, Lit q, bool removable, ClauseId& id)
+ { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp, removable, id); }
+inline bool Solver::addClause (Lit p, Lit q, Lit r, bool removable, ClauseId& id)
+ { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp, removable, id); }
inline bool Solver::locked (const Clause& c) const { return value(c[0]) == l_True && isPropagatedBy(var(c[0]), c); }
inline void Solver::newDecisionLevel() { trail_lim.push(trail.size()); flipped.push(false); context->push(); if(Dump.isOn("state")) { Dump("state") << CVC4::PushCommand(); } }
diff --git a/src/prop/minisat/core/SolverTypes.h b/src/prop/minisat/core/SolverTypes.h
index b0d78242c..116a39a49 100644
--- a/src/prop/minisat/core/SolverTypes.h
+++ b/src/prop/minisat/core/SolverTypes.h
@@ -169,20 +169,22 @@ inline std::ostream& operator <<(std::ostream& out, Minisat::lbool val) {
}
-} /* Minisat */
-}
-
+class Solver;
-
-namespace CVC4 {
class ProofProxyAbstract {
public:
virtual ~ProofProxyAbstract() {}
virtual void updateCRef(Minisat::CRef oldref, Minisat::CRef newref) = 0;
};
-}
+
+} /* namespace CVC4::Minisat */
+} /* namespace CVC4 */
+namespace CVC4 {
+template <class Solver> class ProofProxy;
+typedef ProofProxy<CVC4::Minisat::Solver> CoreProofProxy;
+}
namespace CVC4 {
namespace Minisat{
@@ -305,27 +307,8 @@ class ClauseAllocator : public RegionAllocator<uint32_t>
RegionAllocator<uint32_t>::free(clauseWord32Size(c.size(), c.has_extra()));
}
- void reloc(CRef& cr, ClauseAllocator& to, CVC4::ProofProxyAbstract* proxy = NULL)
- {
-
- // FIXME what is this CRef_lazy
- if (cr == CRef_Lazy) return;
-
- CRef old = cr; // save the old reference
- Clause& c = operator[](cr);
- if (c.reloced()) { cr = c.relocation(); return; }
-
- cr = to.alloc(c.level(), c, c.removable());
- c.relocate(cr);
- if (proxy) {
- proxy->updateCRef(old, cr);
- }
- // Copy extra data-fields:
- // (This could be cleaned-up. Generalize Clause-constructor to be applicable here instead?)
- to[cr].mark(c.mark());
- if (to[cr].removable()) to[cr].activity() = c.activity();
- else if (to[cr].has_extra()) to[cr].calcAbstraction();
- }
+ void reloc(CRef& cr, ClauseAllocator& to, CVC4::CoreProofProxy* proxy = NULL);
+ // Implementation moved to Solver.cc.
};
diff --git a/src/prop/minisat/minisat.cpp b/src/prop/minisat/minisat.cpp
index ce5c1eb92..739d9087a 100644
--- a/src/prop/minisat/minisat.cpp
+++ b/src/prop/minisat/minisat.cpp
@@ -23,6 +23,7 @@
#include "options/prop_options.h"
#include "options/smt_options.h"
#include "prop/minisat/simp/SimpSolver.h"
+#include "proof/sat_proof.h"
#include "util/statistics_registry.h"
namespace CVC4 {
@@ -94,14 +95,6 @@ void MinisatSatSolver::toMinisatClause(SatClause& clause,
Assert(clause.size() == (unsigned)minisat_clause.size());
}
-void MinisatSatSolver::toSatClause(Minisat::vec<Minisat::Lit>& clause,
- SatClause& sat_clause) {
- for (int i = 0; i < clause.size(); ++i) {
- sat_clause.push_back(toSatLiteral(clause[i]));
- }
- Assert((unsigned)clause.size() == sat_clause.size());
-}
-
void MinisatSatSolver::toSatClause(const Minisat::Clause& clause,
SatClause& sat_clause) {
for (int i = 0; i < clause.size(); ++i) {
@@ -149,10 +142,18 @@ void MinisatSatSolver::setupOptions() {
d_minisat->restart_inc = options::satRestartInc();
}
-void MinisatSatSolver::addClause(SatClause& clause, bool removable, uint64_t proof_id) {
+ClauseId MinisatSatSolver::addClause(SatClause& clause, bool removable) {
Minisat::vec<Minisat::Lit> minisat_clause;
toMinisatClause(clause, minisat_clause);
- d_minisat->addClause(minisat_clause, removable, proof_id);
+ ClauseId clause_id = ClauseIdError;
+ // FIXME: This relies on the invariant that when ok() is false
+ // the SAT solver does not add the clause (which is what Minisat currently does)
+ if (!ok()) {
+ return ClauseIdUndef;
+ }
+ d_minisat->addClause(minisat_clause, removable, clause_id);
+ PROOF( Assert (clause_id != ClauseIdError););
+ return clause_id;
}
SatVariable MinisatSatSolver::newVar(bool isTheoryAtom, bool preRegister, bool canErase) {
@@ -182,6 +183,9 @@ SatValue MinisatSatSolver::solve() {
return toSatLiteralValue(d_minisat->solve());
}
+bool MinisatSatSolver::ok() const {
+ return d_minisat->okay();
+}
void MinisatSatSolver::interrupt() {
d_minisat->interrupt();
@@ -280,3 +284,20 @@ void MinisatSatSolver::Statistics::init(Minisat::SimpSolver* d_minisat){
} /* namespace CVC4::prop */
} /* namespace CVC4 */
+
+
+namespace CVC4 {
+template<>
+prop::SatLiteral toSatLiteral< CVC4::Minisat::Solver>(Minisat::Solver::TLit lit) {
+ return prop::MinisatSatSolver::toSatLiteral(lit);
+}
+
+template<>
+void toSatClause< CVC4::Minisat::Solver> (const CVC4::Minisat::Solver::TClause& minisat_cl,
+ prop::SatClause& sat_cl) {
+ prop::MinisatSatSolver::toSatClause(minisat_cl, sat_cl);
+}
+
+} /* namespace CVC4 */
+
+
diff --git a/src/prop/minisat/minisat.h b/src/prop/minisat/minisat.h
index f279b3a5b..535ce1a47 100644
--- a/src/prop/minisat/minisat.h
+++ b/src/prop/minisat/minisat.h
@@ -40,11 +40,10 @@ public:
//(Commented because not in use) static bool tobool(SatValue val);
static void toMinisatClause(SatClause& clause, Minisat::vec<Minisat::Lit>& minisat_clause);
- static void toSatClause (Minisat::vec<Minisat::Lit>& clause, SatClause& sat_clause);
static void toSatClause (const Minisat::Clause& clause, SatClause& sat_clause);
void initialize(context::Context* context, TheoryProxy* theoryProxy);
- void addClause(SatClause& clause, bool removable, uint64_t proof_id);
+ ClauseId addClause(SatClause& clause, bool removable);
SatVariable newVar(bool isTheoryAtom, bool preRegister, bool canErase);
SatVariable trueVar() { return d_minisat->trueVar(); }
@@ -53,6 +52,8 @@ public:
SatValue solve();
SatValue solve(long unsigned int&);
+ bool ok() const;
+
void interrupt();
SatValue value(SatLiteral l);
diff --git a/src/prop/minisat/simp/SimpSolver.cc b/src/prop/minisat/simp/SimpSolver.cc
index 235c97e8f..5bdaea950 100644
--- a/src/prop/minisat/simp/SimpSolver.cc
+++ b/src/prop/minisat/simp/SimpSolver.cc
@@ -160,7 +160,7 @@ lbool SimpSolver::solve_(bool do_simp, bool turn_off_simp)
-bool SimpSolver::addClause_(vec<Lit>& ps, bool removable, uint64_t proof_id)
+bool SimpSolver::addClause_(vec<Lit>& ps, bool removable, ClauseId& id)
{
#ifndef NDEBUG
if (use_simplification) {
@@ -174,7 +174,7 @@ bool SimpSolver::addClause_(vec<Lit>& ps, bool removable, uint64_t proof_id)
if (use_rcheck && implied(ps))
return true;
- if (!Solver::addClause_(ps, removable, proof_id))
+ if (!Solver::addClause_(ps, removable, id))
return false;
if (use_simplification && clauses_persistent.size() == nclauses + 1){
@@ -541,12 +541,14 @@ bool SimpSolver::eliminateVar(Var v)
for (int i = 0; i < cls.size(); i++)
removeClause(cls[i]);
+ ClauseId id = ClauseIdUndef;
// Produce clauses in cross product:
vec<Lit>& resolvent = add_tmp;
for (int i = 0; i < pos.size(); i++)
for (int j = 0; j < neg.size(); j++) {
bool removable = ca[pos[i]].removable() && ca[pos[neg[j]]].removable();
- if (merge(ca[pos[i]], ca[neg[j]], v, resolvent) && !addClause_(resolvent, removable, uint64_t(-1))) {
+ if (merge(ca[pos[i]], ca[neg[j]], v, resolvent) &&
+ !addClause_(resolvent, removable, id)) {
return false;
}
}
@@ -585,8 +587,8 @@ bool SimpSolver::substitute(Var v, Lit x)
}
removeClause(cls[i]);
-
- if (!addClause_(subst_clause, c.removable(), uint64_t(-1))) {
+ ClauseId id = ClauseIdUndef;
+ if (!addClause_(subst_clause, c.removable(), id)) {
return ok = false;
}
}
diff --git a/src/prop/minisat/simp/SimpSolver.h b/src/prop/minisat/simp/SimpSolver.h
index 0c5062726..a19bec1ef 100644
--- a/src/prop/minisat/simp/SimpSolver.h
+++ b/src/prop/minisat/simp/SimpSolver.h
@@ -48,12 +48,12 @@ class SimpSolver : public Solver {
// Problem specification:
//
Var newVar (bool polarity = true, bool dvar = true, bool isTheoryAtom = false, bool preRegister = false, bool canErase = true);
- bool addClause (const vec<Lit>& ps, bool removable, uint64_t proof_id);
- bool addEmptyClause(bool removable, uint64_t proof_id); // Add the empty clause to the solver.
- bool addClause (Lit p, bool removable, uint64_t proof_id); // Add a unit clause to the solver.
- bool addClause (Lit p, Lit q, bool removable, uint64_t proof_id); // Add a binary clause to the solver.
- bool addClause (Lit p, Lit q, Lit r, bool removable, uint64_t proof_id); // Add a ternary clause to the solver.
- bool addClause_(vec<Lit>& ps, bool removable, uint64_t proof_id);
+ bool addClause (const vec<Lit>& ps, bool removable, ClauseId& id);
+ bool addEmptyClause(bool removable); // Add the empty clause to the solver.
+ bool addClause (Lit p, bool removable, ClauseId& id); // Add a unit clause to the solver.
+ bool addClause (Lit p, Lit q, bool removable, ClauseId& id); // Add a binary clause to the solver.
+ bool addClause (Lit p, Lit q, Lit r, bool removable, ClauseId& id); // Add a ternary clause to the solver.
+ bool addClause_(vec<Lit>& ps, bool removable, ClauseId& id);
bool substitute(Var v, Lit x); // Replace all occurences of v with x (may cause a contradiction).
// Variable mode:
@@ -183,15 +183,15 @@ inline void SimpSolver::updateElimHeap(Var v) {
elim_heap.update(v); }
-inline bool SimpSolver::addClause (const vec<Lit>& ps, bool removable, uint64_t proof_id)
- { ps.copyTo(add_tmp); return addClause_(add_tmp, removable, proof_id); }
-inline bool SimpSolver::addEmptyClause(bool removable, uint64_t proof_id) { add_tmp.clear(); return addClause_(add_tmp, removable, proof_id); }
-inline bool SimpSolver::addClause (Lit p, bool removable, uint64_t proof_id)
- { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp, removable, proof_id); }
-inline bool SimpSolver::addClause (Lit p, Lit q, bool removable, uint64_t proof_id)
- { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp, removable, proof_id); }
-inline bool SimpSolver::addClause (Lit p, Lit q, Lit r, bool removable, uint64_t proof_id)
- { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp, removable, proof_id); }
+inline bool SimpSolver::addClause(const vec<Lit>& ps, bool removable, ClauseId& id)
+{ ps.copyTo(add_tmp); return addClause_(add_tmp, removable, id); }
+inline bool SimpSolver::addEmptyClause(bool removable) { add_tmp.clear(); ClauseId id=-1; return addClause_(add_tmp, removable, id); }
+inline bool SimpSolver::addClause (Lit p, bool removable, ClauseId& id)
+ { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp, removable, id); }
+inline bool SimpSolver::addClause (Lit p, Lit q, bool removable, ClauseId& id)
+ { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp, removable, id); }
+inline bool SimpSolver::addClause (Lit p, Lit q, Lit r, bool removable, ClauseId& id)
+ { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp, removable, id); }
inline void SimpSolver::setFrozen (Var v, bool b) { frozen[v] = (char)b; if (use_simplification && !b) { updateElimHeap(v); } }
// the solver can always return unknown due to resource limiting
diff --git a/src/prop/prop_engine.cpp b/src/prop/prop_engine.cpp
index 9767ac7c7..593c522a8 100644
--- a/src/prop/prop_engine.cpp
+++ b/src/prop/prop_engine.cpp
@@ -99,7 +99,9 @@ PropEngine::PropEngine(TheoryEngine* te, DecisionEngine *de, Context* satContext
d_decisionEngine->setSatSolver(d_satSolver);
d_decisionEngine->setCnfStream(d_cnfStream);
- PROOF (ProofManager::currentPM()->initCnfProof(d_cnfStream); );
+ PROOF (
+ ProofManager::currentPM()->initCnfProof(d_cnfStream, userContext);
+ );
}
PropEngine::~PropEngine() {
@@ -117,7 +119,10 @@ void PropEngine::assertFormula(TNode node) {
d_cnfStream->convertAndAssert(node, false, false, RULE_GIVEN);
}
-void PropEngine::assertLemma(TNode node, bool negated, bool removable, ProofRule rule, TNode from) {
+void PropEngine::assertLemma(TNode node, bool negated,
+ bool removable,
+ ProofRule rule,
+ TNode from) {
//Assert(d_inCheckSat, "Sat solver should be in solve()!");
Debug("prop::lemmas") << "assertLemma(" << node << ")" << endl;
diff --git a/src/prop/sat_solver.h b/src/prop/sat_solver.h
index 1c1dae410..1383308a3 100644
--- a/src/prop/sat_solver.h
+++ b/src/prop/sat_solver.h
@@ -30,10 +30,15 @@
#include "util/statistics_registry.h"
namespace CVC4 {
+
+class BitVectorProof;
+
namespace prop {
class TheoryProxy;
+typedef unsigned ClauseId;
+
class SatSolver {
public:
@@ -42,7 +47,8 @@ public:
virtual ~SatSolver() throw(AssertionException) { }
/** Assert a clause in the solver. */
- virtual void addClause(SatClause& clause, bool removable, uint64_t proof_id) = 0;
+ virtual ClauseId addClause(SatClause& clause,
+ bool removable) = 0;
/**
* Create a new boolean variable in the solver.
@@ -77,6 +83,10 @@ public:
/** Get the current assertion level */
virtual unsigned getAssertionLevel() const = 0;
+ /** Check if the solver is in an inconsistent state */
+ virtual bool ok() const = 0;
+
+
};/* class SatSolver */
@@ -121,6 +131,10 @@ public:
virtual void popAssumption() = 0;
+ virtual bool ok() const = 0;
+
+ virtual void setProofLog( BitVectorProof * bvp ) {}
+
};/* class BVSatSolverInterface */
@@ -139,7 +153,8 @@ public:
virtual bool flipDecision() = 0;
virtual bool isDecision(SatVariable decn) const = 0;
-
+
+ virtual bool ok() const = 0;
};/* class DPLLSatSolverInterface */
inline std::ostream& operator <<(std::ostream& out, prop::SatLiteral lit) {
diff --git a/src/prop/sat_solver_factory.h b/src/prop/sat_solver_factory.h
index 434bf849d..6a3053a18 100644
--- a/src/prop/sat_solver_factory.h
+++ b/src/prop/sat_solver_factory.h
@@ -31,7 +31,9 @@ namespace prop {
class SatSolverFactory {
public:
- static BVSatSolverInterface* createMinisat(context::Context* mainSatContext, StatisticsRegistry* registry, const std::string& name = "");
+ static BVSatSolverInterface* createMinisat(context::Context* mainSatContext,
+ StatisticsRegistry* registry,
+ const std::string& name = "");
static DPLLSatSolverInterface* createDPLLMinisat(StatisticsRegistry* registry);
};/* class SatSolverFactory */
diff --git a/src/prop/theory_proxy.cpp b/src/prop/theory_proxy.cpp
index e87046ad5..5304691a6 100644
--- a/src/prop/theory_proxy.cpp
+++ b/src/prop/theory_proxy.cpp
@@ -22,6 +22,7 @@
#include "options/decision_options.h"
#include "prop/cnf_stream.h"
#include "prop/prop_engine.h"
+#include "proof/cnf_proof.h"
#include "smt_util/lemma_input_channel.h"
#include "smt_util/lemma_output_channel.h"
#include "smt/smt_statistics_registry.h"
@@ -29,6 +30,7 @@
#include "theory/theory_engine.h"
#include "util/statistics_registry.h"
+
namespace CVC4 {
namespace prop {
@@ -100,6 +102,7 @@ void TheoryProxy::explainPropagation(SatLiteral l, SatClause& explanation) {
TNode lNode = d_cnfStream->getNode(l);
Debug("prop-explain") << "explainPropagation(" << lNode << ")" << std::endl;
Node theoryExplanation = d_theoryEngine->getExplanation(lNode);
+ PROOF(ProofManager::getCnfProof()->pushCurrentAssertion(theoryExplanation); );
Debug("prop-explain") << "explainPropagation() => " << theoryExplanation << std::endl;
if (theoryExplanation.getKind() == kind::AND) {
Node::const_iterator it = theoryExplanation.begin();
diff --git a/src/smt/smt_engine.cpp b/src/smt/smt_engine.cpp
index 1962c6433..c66031265 100644
--- a/src/smt/smt_engine.cpp
+++ b/src/smt/smt_engine.cpp
@@ -788,6 +788,13 @@ SmtEngine::SmtEngine(ExprManager* em) throw() :
d_stats = new SmtEngineStatistics();
d_stats->d_resourceUnitsUsed.setData(
d_private->getResourceManager()->getResourceUsage());
+
+ // The ProofManager is constructed before any other proof objects such as
+ // SatProof and TheoryProofs. The TheoryProofEngine and the SatProof are
+ // initialized in TheoryEngine and PropEngine respectively.
+ Assert(d_proofManager == NULL);
+ PROOF( d_proofManager = new ProofManager(); );
+
// We have mutual dependency here, so we add the prop engine to the theory
// engine later (it is non-essential there)
d_theoryEngine = new TheoryEngine(d_context, d_userContext,
@@ -798,6 +805,8 @@ SmtEngine::SmtEngine(ExprManager* em) throw() :
// Add the theories
for(TheoryId id = theory::THEORY_FIRST; id < theory::THEORY_LAST; ++id) {
TheoryConstructor::addTheory(d_theoryEngine, id);
+ //register with proof engine if applicable
+ THEORY_PROOF(ProofManager::currentPM()->getTheoryProofEngine()->registerTheory(d_theoryEngine->theoryOf(id)); );
}
// global push/pop around everything, to ensure proper destruction
@@ -817,9 +826,6 @@ void SmtEngine::finishInit() {
// ensure that our heuristics are properly set up
setDefaults();
- Assert(d_proofManager == NULL);
- PROOF( d_proofManager = new ProofManager(); );
-
d_decisionEngine = new DecisionEngine(d_context, d_userContext);
d_decisionEngine->init(); // enable appropriate strategies
@@ -857,7 +863,7 @@ void SmtEngine::finishInit() {
}
d_dumpCommands.clear();
- PROOF( ProofManager::currentPM()->setLogic(d_logic.getLogicString()); );
+ PROOF( ProofManager::currentPM()->setLogic(d_logic); );
}
void SmtEngine::finalOptionsAreSet() {
@@ -3515,6 +3521,14 @@ void SmtEnginePrivate::processAssertions() {
Trace("smt-proc") << "SmtEnginePrivate::processAssertions() : post-definition-expansion" << endl;
dumpAssertions("post-definition-expansion", d_assertions);
+ // save the assertions now
+ THEORY_PROOF
+ (
+ for (unsigned i = 0; i < d_assertions.size(); ++i) {
+ ProofManager::currentPM()->addAssertion(d_assertions[i].toExpr());
+ }
+ );
+
Debug("smt") << " d_assertions : " << d_assertions.size() << endl;
if( options::ceGuidedInst() ){
@@ -3936,7 +3950,8 @@ void SmtEnginePrivate::addFormula(TNode n, bool inUnsatCore, bool inInput)
PROOF(
if( inInput ){
// n is an input assertion
- ProofManager::currentPM()->addAssertion(n.toExpr(), inUnsatCore);
+ if (inUnsatCore || options::dumpUnsatCores() || options::checkUnsatCores())
+ ProofManager::currentPM()->addCoreAssertion(n.toExpr());
}else{
// n is the result of an unknown preprocessing step, add it to dependency map to null
ProofManager::currentPM()->addDependence(n, Node::null());
@@ -4724,7 +4739,7 @@ UnsatCore SmtEngine::getUnsatCore() throw(ModalException, UnsafeInterruptExcepti
throw ModalException("Cannot get an unsat core unless immediately preceded by UNSAT/VALID response.");
}
- d_proofManager->getProof(this);// just to trigger core creation
+ d_proofManager->traceUnsatCore();// just to trigger core creation
return UnsatCore(this, d_proofManager->begin_unsat_core(), d_proofManager->end_unsat_core());
#else /* IS_PROOFS_BUILD */
throw ModalException("This build of CVC4 doesn't have proof support (required for unsat cores).");
diff --git a/src/smt/smt_engine_check_proof.cpp b/src/smt/smt_engine_check_proof.cpp
index c4747d724..14adcc536 100644
--- a/src/smt/smt_engine_check_proof.cpp
+++ b/src/smt/smt_engine_check_proof.cpp
@@ -64,11 +64,12 @@ void SmtEngine::checkProof() {
Chat() << "checking proof..." << endl;
if( !(d_logic.isPure(theory::THEORY_BOOL) ||
+ d_logic.isPure(theory::THEORY_BV) ||
(d_logic.isPure(theory::THEORY_UF) &&
! d_logic.hasCardinalityConstraints())) ||
d_logic.isQuantified()) {
// no checking for these yet
- Notice() << "Notice: no proof-checking for non-UF/Bool proofs yet" << endl;
+ Notice() << "Notice: no proof-checking for non-UF/Bool/BV proofs yet" << endl;
return;
}
@@ -91,7 +92,7 @@ void SmtEngine::checkProof() {
a.use_nested_app = false;
a.compile_lib = false;
init();
- check_file(pfFile, args());
+ check_file(pfFile, a);
close(fd);
#else /* IS_PROOFS_BUILD */
diff --git a/src/smt/smt_engine_scope.h b/src/smt/smt_engine_scope.h
index 83da5a159..c4ec15371 100644
--- a/src/smt/smt_engine_scope.h
+++ b/src/smt/smt_engine_scope.h
@@ -23,6 +23,8 @@
#include "base/output.h"
#include "base/tls.h"
#include "expr/node_manager.h"
+#include "proof/proof.h"
+#include "proof/proof_manager.h"
#include "options/smt_options.h"
#include "smt/smt_engine.h"
#include "util/configuration_private.h"
@@ -44,6 +46,7 @@ inline bool smtEngineInScope() {
return s_smtEngine_current != NULL;
}
+// FIXME: Maybe move into SmtScope?
inline ProofManager* currentProofManager() {
#if IS_PROOFS_BUILD
Assert(options::proof() || options::unsatCores());
diff --git a/src/smt_util/command.cpp b/src/smt_util/command.cpp
index 8cc8a421c..83298836f 100644
--- a/src/smt_util/command.cpp
+++ b/src/smt_util/command.cpp
@@ -1110,6 +1110,7 @@ GetProofCommand::GetProofCommand() throw() {
void GetProofCommand::invoke(SmtEngine* smtEngine) throw() {
try {
+ d_smtEngine = smtEngine;
d_result = smtEngine->getProof();
d_commandStatus = CommandSuccess::instance();
} catch(UnsafeInterruptException& e) {
@@ -1127,6 +1128,7 @@ void GetProofCommand::printResult(std::ostream& out, uint32_t verbosity) const t
if(! ok()) {
this->Command::printResult(out, verbosity);
} else {
+ smt::SmtScope scope(d_smtEngine);
d_result->toStream(out);
}
}
@@ -1134,12 +1136,14 @@ void GetProofCommand::printResult(std::ostream& out, uint32_t verbosity) const t
Command* GetProofCommand::exportTo(ExprManager* exprManager, ExprManagerMapCollection& variableMap) {
GetProofCommand* c = new GetProofCommand();
c->d_result = d_result;
+ c->d_smtEngine = d_smtEngine;
return c;
}
Command* GetProofCommand::clone() const {
GetProofCommand* c = new GetProofCommand();
c->d_result = d_result;
+ c->d_smtEngine = d_smtEngine;
return c;
}
diff --git a/src/smt_util/command.h b/src/smt_util/command.h
index d8f9789f5..248e69b0e 100644
--- a/src/smt_util/command.h
+++ b/src/smt_util/command.h
@@ -584,6 +584,7 @@ public:
class CVC4_PUBLIC GetProofCommand : public Command {
protected:
Proof* d_result;
+ SmtEngine* d_smtEngine;
public:
GetProofCommand() throw();
~GetProofCommand() throw() {}
diff --git a/src/theory/arrays/theory_arrays.cpp b/src/theory/arrays/theory_arrays.cpp
index 508a4b323..cbcccd734 100644
--- a/src/theory/arrays/theory_arrays.cpp
+++ b/src/theory/arrays/theory_arrays.cpp
@@ -26,9 +26,10 @@
#include "smt_util/command.h"
#include "theory/rewriter.h"
#include "theory/theory_model.h"
+#include "proof/theory_proof.h"
+#include "proof/proof_manager.h"
#include "theory/valuation.h"
-
using namespace std;
namespace CVC4 {
@@ -54,27 +55,28 @@ const bool d_solveWrite2 = false;
TheoryArrays::TheoryArrays(context::Context* c, context::UserContext* u,
OutputChannel& out, Valuation valuation,
- const LogicInfo& logicInfo, SmtGlobals* globals)
- : Theory(THEORY_ARRAY, c, u, out, valuation, logicInfo, globals),
- d_numRow("theory::arrays::number of Row lemmas", 0),
- d_numExt("theory::arrays::number of Ext lemmas", 0),
- d_numProp("theory::arrays::number of propagations", 0),
- d_numExplain("theory::arrays::number of explanations", 0),
- d_numNonLinear("theory::arrays::number of calls to setNonLinear", 0),
- d_numSharedArrayVarSplits("theory::arrays::number of shared array var splits", 0),
- d_numGetModelValSplits("theory::arrays::number of getModelVal splits", 0),
- d_numGetModelValConflicts("theory::arrays::number of getModelVal conflicts", 0),
- d_numSetModelValSplits("theory::arrays::number of setModelVal splits", 0),
- d_numSetModelValConflicts("theory::arrays::number of setModelVal conflicts", 0),
- d_ppEqualityEngine(u, "theory::arrays::TheoryArraysPP" , true),
+ const LogicInfo& logicInfo, SmtGlobals* globals,
+ std::string name)
+ : Theory(THEORY_ARRAY, c, u, out, valuation, logicInfo, globals, name),
+ d_numRow(name + "theory::arrays::number of Row lemmas", 0),
+ d_numExt(name + "theory::arrays::number of Ext lemmas", 0),
+ d_numProp(name + "theory::arrays::number of propagations", 0),
+ d_numExplain(name + "theory::arrays::number of explanations", 0),
+ d_numNonLinear(name + "theory::arrays::number of calls to setNonLinear", 0),
+ d_numSharedArrayVarSplits(name + "theory::arrays::number of shared array var splits", 0),
+ d_numGetModelValSplits(name + "theory::arrays::number of getModelVal splits", 0),
+ d_numGetModelValConflicts(name + "theory::arrays::number of getModelVal conflicts", 0),
+ d_numSetModelValSplits(name + "theory::arrays::number of setModelVal splits", 0),
+ d_numSetModelValConflicts(name + "theory::arrays::number of setModelVal conflicts", 0),
+ d_ppEqualityEngine(u, name + "theory::arrays::TheoryArraysPP" , true),
d_ppFacts(u),
// d_ppCache(u),
d_literalsToPropagate(c),
d_literalsToPropagateIndex(c, 0),
d_isPreRegistered(c),
- d_mayEqualEqualityEngine(c, "theory::arrays::TheoryArraysMayEqual", true),
+ d_mayEqualEqualityEngine(c, name + "theory::arrays::TheoryArraysMayEqual", true),
d_notify(*this),
- d_equalityEngine(d_notify, c, "theory::arrays::TheoryArrays", true),
+ d_equalityEngine(d_notify, c, name + "theory::arrays::TheoryArrays", true),
d_conflict(c, false),
d_backtracker(c),
d_infoMap(c, &d_backtracker),
@@ -1385,7 +1387,8 @@ void TheoryArrays::check(Effort e) {
weakEquivBuildCond(r[0], r[1], conjunctions);
weakEquivBuildCond(r2[0], r[1], conjunctions);
lemma = mkAnd(conjunctions, true);
- d_out->lemma(lemma, false, false, true);
+ // LSH FIXME: which kind of arrays lemma is this
+ d_out->lemma(lemma, RULE_INVALID, false, false, true);
d_readTableContext->pop();
return;
}
diff --git a/src/theory/arrays/theory_arrays.h b/src/theory/arrays/theory_arrays.h
index f1b02d99e..88d83bfb9 100644
--- a/src/theory/arrays/theory_arrays.h
+++ b/src/theory/arrays/theory_arrays.h
@@ -128,7 +128,7 @@ class TheoryArrays : public Theory {
TheoryArrays(context::Context* c, context::UserContext* u, OutputChannel& out,
Valuation valuation, const LogicInfo& logicInfo,
- SmtGlobals* globals);
+ SmtGlobals* globals, std::string name = "");
~TheoryArrays();
void setMasterEqualityEngine(eq::EqualityEngine* eq);
diff --git a/src/theory/bv/bitblast_strategies_template.h b/src/theory/bv/bitblast_strategies_template.h
index 0990c2f29..bc022a02d 100644
--- a/src/theory/bv/bitblast_strategies_template.h
+++ b/src/theory/bv/bitblast_strategies_template.h
@@ -253,17 +253,17 @@ void DefaultAndBB (TNode node, std::vector<T>& bits, TBitblaster<T>* bb) {
Assert(node.getKind() == kind::BITVECTOR_AND &&
bits.size() == 0);
-
- for(unsigned j = 0; j < utils::getSize(node); ++j) {
- std::vector<T> and_j;
- for (unsigned i = 0; i < node.getNumChildren(); ++i) {
- std::vector<T> current;
- bb->bbTerm(node[i], current);
- and_j.push_back(current[j]);
- Assert(utils::getSize(node) == current.size());
+
+ bb->bbTerm(node[0], bits);
+ std::vector<T> current;
+ for(unsigned j = 1; j < node.getNumChildren(); ++j) {
+ bb->bbTerm(node[j], current);
+ for (unsigned i = 0; i < utils::getSize(node); ++i) {
+ bits[i] = mkAnd(bits[i], current[i]);
}
- bits.push_back(mkAnd(and_j));
+ current.clear();
}
+ Assert (bits.size() == utils::getSize(node));
}
template <class T>
@@ -272,17 +272,17 @@ void DefaultOrBB (TNode node, std::vector<T>& bits, TBitblaster<T>* bb) {
Assert(node.getKind() == kind::BITVECTOR_OR &&
bits.size() == 0);
-
- for(unsigned j = 0; j < utils::getSize(node); ++j) {
- std::vector<T> or_j;
- for (unsigned i = 0; i < node.getNumChildren(); ++i) {
- std::vector<T> current;
- bb->bbTerm(node[i], current);
- or_j.push_back(current[j]);
- Assert(utils::getSize(node) == current.size());
+
+ bb->bbTerm(node[0], bits);
+ std::vector<T> current;
+ for(unsigned j = 1; j < node.getNumChildren(); ++j) {
+ bb->bbTerm(node[j], current);
+ for (unsigned i = 0; i < utils::getSize(node); ++i) {
+ bits[i] = mkOr(bits[i], current[i]);
}
- bits.push_back(mkOr(or_j));
+ current.clear();
}
+ Assert (bits.size() == utils::getSize(node));
}
template <class T>
@@ -291,20 +291,17 @@ void DefaultXorBB (TNode node, std::vector<T>& bits, TBitblaster<T>* bb) {
Assert(node.getKind() == kind::BITVECTOR_XOR &&
bits.size() == 0);
-
- for(unsigned j = 0; j < utils::getSize(node); ++j) {
- std::vector<T> first;
- bb->bbTerm(node[0], first);
- T bitj = first[j];
-
- for (unsigned i = 1; i < node.getNumChildren(); ++i) {
- std::vector<T> current;
- bb->bbTerm(node[i], current);
- bitj = mkXor(bitj, current[j]);
- Assert(utils::getSize(node) == current.size());
+
+ bb->bbTerm(node[0], bits);
+ std::vector<T> current;
+ for(unsigned j = 1; j < node.getNumChildren(); ++j) {
+ bb->bbTerm(node[j], current);
+ for (unsigned i = 0; i < utils::getSize(node); ++i) {
+ bits[i] = mkXor(bits[i], current[i]);
}
- bits.push_back(bitj);
+ current.clear();
}
+ Assert (bits.size() == utils::getSize(node));
}
template <class T>
diff --git a/src/theory/bv/bitblast_utils.h b/src/theory/bv/bitblast_utils.h
index a236c69e8..adaed31c1 100644
--- a/src/theory/bv/bitblast_utils.h
+++ b/src/theory/bv/bitblast_utils.h
@@ -221,7 +221,7 @@ inline void shiftAddMultiplier(const std::vector<T>&a, const std::vector<T>&b, s
T carry_in = mkFalse<T>();
T carry_out;
for(unsigned j = 0; j < res.size() -k; ++j) {
- T aj = mkAnd(a[j], b[k]);
+ T aj = mkAnd(b[k], a[j]);
carry_out = mkOr(mkAnd(res[j+k], aj),
mkAnd( mkXor(res[j+k], aj), carry_in));
res[j+k] = mkXor(mkXor(res[j+k], aj), carry_in);
diff --git a/src/theory/bv/bitblaster_template.h b/src/theory/bv/bitblaster_template.h
index ec76bb4f6..66eea0997 100644
--- a/src/theory/bv/bitblaster_template.h
+++ b/src/theory/bv/bitblaster_template.h
@@ -85,6 +85,8 @@ protected:
TermDefMap d_termCache;
ModelCache d_modelCache;
+ BitVectorProof * d_bvp;
+
void initAtomBBStrategies();
void initTermBBStrategies();
protected:
@@ -105,7 +107,7 @@ public:
bool hasBBTerm(TNode node) const;
void getBBTerm(TNode node, Bits& bits) const;
- void storeBBTerm(TNode term, const Bits& bits);
+ virtual void storeBBTerm(TNode term, const Bits& bits);
/**
* Return a constant representing the value of a in the model.
* If fullModel is true set unconstrained bits to 0. If not return
@@ -171,7 +173,9 @@ public:
void bbAtom(TNode node);
Node getBBAtom(TNode atom) const;
void storeBBAtom(TNode atom, Node atom_bb);
- bool hasBBAtom(TNode atom) const;
+ void storeBBTerm(TNode node, const Bits& bits);
+ bool hasBBAtom(TNode atom) const;
+
TLazyBitblaster(context::Context* c, bv::TheoryBV* bv, const std::string name="", bool emptyNotify = false);
~TLazyBitblaster() throw();
/**
@@ -201,6 +205,7 @@ public:
* constants to equivalence classes that don't already have them
*/
void collectModelInfo(TheoryModel* m, bool fullModel);
+ void setProofLog( BitVectorProof * bvp );
typedef TNodeSet::const_iterator vars_iterator;
vars_iterator beginVars() { return d_variables.begin(); }
@@ -277,9 +282,12 @@ public:
bool hasBBAtom(TNode atom) const;
void bbFormula(TNode formula);
void storeBBAtom(TNode atom, Node atom_bb);
+ void storeBBTerm(TNode node, const Bits& bits);
+
bool assertToSat(TNode node, bool propagate = true);
bool solve();
void collectModelInfo(TheoryModel* m, bool fullModel);
+ void setProofLog( BitVectorProof * bvp );
};
class BitblastingRegistrar: public prop::Registrar {
@@ -406,6 +414,7 @@ template <class T>
TBitblaster<T>::TBitblaster()
: d_termCache()
, d_modelCache()
+ , d_bvp( NULL )
{
initAtomBBStrategies();
initTermBBStrategies();
diff --git a/src/theory/bv/bv_eager_solver.cpp b/src/theory/bv/bv_eager_solver.cpp
index 66b1c4182..2af8d04d6 100644
--- a/src/theory/bv/bv_eager_solver.cpp
+++ b/src/theory/bv/bv_eager_solver.cpp
@@ -16,6 +16,7 @@
#include "options/bv_options.h"
#include "theory/bv/bitblaster_template.h"
+#include "proof/bitvector_proof.h"
#include "theory/bv/bv_eager_solver.h"
using namespace std;
@@ -54,6 +55,12 @@ void EagerBitblastSolver::initialize() {
d_aigBitblaster = new AigBitblaster();
} else {
d_bitblaster = new EagerBitblaster(d_bv);
+ THEORY_PROOF(
+ if( d_bvp ){
+ d_bitblaster->setProofLog( d_bvp );
+ d_bvp->setBitblaster(d_bitblaster);
+ }
+ );
}
}
@@ -112,3 +119,7 @@ void EagerBitblastSolver::collectModelInfo(TheoryModel* m, bool fullModel) {
AlwaysAssert(!d_useAig && d_bitblaster);
d_bitblaster->collectModelInfo(m, fullModel);
}
+
+void EagerBitblastSolver::setProofLog( BitVectorProof * bvp ) {
+ d_bvp = bvp;
+}
diff --git a/src/theory/bv/bv_eager_solver.h b/src/theory/bv/bv_eager_solver.h
index ff13867cc..cfc84dae1 100644
--- a/src/theory/bv/bv_eager_solver.h
+++ b/src/theory/bv/bv_eager_solver.h
@@ -39,7 +39,9 @@ class EagerBitblastSolver {
EagerBitblaster* d_bitblaster;
AigBitblaster* d_aigBitblaster;
bool d_useAig;
- TheoryBV* d_bv;
+
+ TheoryBV* d_bv;
+ BitVectorProof * d_bvp;
public:
EagerBitblastSolver(theory::bv::TheoryBV* bv);
@@ -53,6 +55,7 @@ public:
bool isInitialized();
void initialize();
void collectModelInfo(theory::TheoryModel* m, bool fullModel);
+ void setProofLog( BitVectorProof * bvp );
};
}
diff --git a/src/theory/bv/bv_subtheory.h b/src/theory/bv/bv_subtheory.h
index 9a314fd6a..402dd6be3 100644
--- a/src/theory/bv/bv_subtheory.h
+++ b/src/theory/bv/bv_subtheory.h
@@ -74,6 +74,8 @@ protected:
/** The bit-vector theory */
TheoryBV* d_bv;
+ /** proof log */
+ BitVectorProof * d_bvp;
AssertionQueue d_assertionQueue;
context::CDO<uint32_t> d_assertionIndex;
public:
@@ -102,6 +104,7 @@ public:
return res;
}
virtual void assertFact(TNode fact) { d_assertionQueue.push_back(fact); }
+ virtual void setProofLog( BitVectorProof * bvp ) {}
AssertionQueue::const_iterator assertionsBegin() { return d_assertionQueue.begin(); }
AssertionQueue::const_iterator assertionsEnd() { return d_assertionQueue.end(); }
};
diff --git a/src/theory/bv/bv_subtheory_bitblast.cpp b/src/theory/bv/bv_subtheory_bitblast.cpp
index 9f8cb580c..e7630bb3f 100644
--- a/src/theory/bv/bv_subtheory_bitblast.cpp
+++ b/src/theory/bv/bv_subtheory_bitblast.cpp
@@ -24,6 +24,8 @@
#include "theory/bv/bv_subtheory_bitblast.h"
#include "theory/bv/theory_bv.h"
#include "theory/bv/theory_bv_utils.h"
+#include "proof/proof_manager.h"
+#include "proof/bitvector_proof.h"
using namespace std;
using namespace CVC4::context;
@@ -44,7 +46,8 @@ BitblastSolver::BitblastSolver(context::Context* c, TheoryBV* bv)
d_abstractionModule(NULL),
d_quickCheck(options::bitvectorQuickXplain() ? new BVQuickCheck("bb", bv) : NULL),
d_quickXplain(options::bitvectorQuickXplain() ? new QuickXPlain("bb", d_quickCheck) : NULL)
-{}
+{
+}
BitblastSolver::~BitblastSolver() {
delete d_quickXplain;
@@ -232,40 +235,6 @@ Node BitblastSolver::getModelValue(TNode node)
return val;
}
-// Node BitblastSolver::getModelValueRec(TNode node)
-// {
-// Node val;
-// if (node.isConst()) {
-// return node;
-// }
-// NodeMap::iterator it = d_modelCache.find(node);
-// if (it != d_modelCache.end()) {
-// val = (*it).second;
-// Debug("bitvector-model") << node << " => (cached) " << val <<"\n";
-// return val;
-// }
-// if (d_bv->isLeaf(node)) {
-// val = d_bitblaster->getVarValue(node);
-// if (val == Node()) {
-// // If no value in model, just set to 0
-// val = utils::mkConst(utils::getSize(node), (unsigned)0);
-// }
-// } else {
-// NodeBuilder<> valBuilder(node.getKind());
-// if (node.getMetaKind() == kind::metakind::PARAMETERIZED) {
-// valBuilder << node.getOperator();
-// }
-// for (unsigned i = 0; i < node.getNumChildren(); ++i) {
-// valBuilder << getModelValueRec(node[i]);
-// }
-// val = valBuilder;
-// val = Rewriter::rewrite(val);
-// }
-// Assert(val.isConst());
-// d_modelCache[node] = val;
-// Debug("bitvector-model") << node << " => " << val <<"\n";
-// return val;
-// }
void BitblastSolver::setConflict(TNode conflict) {
@@ -279,6 +248,12 @@ void BitblastSolver::setConflict(TNode conflict) {
d_bv->setConflict(final_conflict);
}
+void BitblastSolver::setProofLog( BitVectorProof * bvp ) {
+ d_bitblaster->setProofLog( bvp );
+ bvp->setBitblaster(d_bitblaster);
+}
+
}/* namespace CVC4::theory::bv */
}/* namespace CVC4::theory */
}/* namespace CVC4 */
+
diff --git a/src/theory/bv/bv_subtheory_bitblast.h b/src/theory/bv/bv_subtheory_bitblast.h
index 0e066eefb..c69069109 100644
--- a/src/theory/bv/bv_subtheory_bitblast.h
+++ b/src/theory/bv/bv_subtheory_bitblast.h
@@ -73,8 +73,9 @@ public:
void bitblastQueue();
void setAbstraction(AbstractionModule* module);
uint64_t computeAtomWeight(TNode atom);
+ void setProofLog( BitVectorProof * bvp );
};
-}
-}
-}
+} /* namespace CVC4::theory::bv */
+} /* namespace CVC4::theory */
+} /* namespace CVC4 */
diff --git a/src/theory/bv/eager_bitblaster.cpp b/src/theory/bv/eager_bitblaster.cpp
index 000abe62b..2e4f06c38 100644
--- a/src/theory/bv/eager_bitblaster.cpp
+++ b/src/theory/bv/eager_bitblaster.cpp
@@ -19,16 +19,13 @@
#include "options/bv_options.h"
#include "prop/cnf_stream.h"
#include "prop/sat_solver_factory.h"
+#include "proof/bitvector_proof.h"
#include "smt/smt_statistics_registry.h"
#include "theory/bv/bitblaster_template.h"
#include "theory/bv/theory_bv.h"
#include "theory/theory_model.h"
-using namespace CVC4;
-using namespace CVC4::theory;
-using namespace CVC4::theory::bv;
-
namespace CVC4 {
namespace theory {
namespace bv {
@@ -46,13 +43,19 @@ EagerBitblaster::EagerBitblaster(TheoryBV* theory_bv)
d_bitblastingRegistrar = new BitblastingRegistrar(this);
d_nullContext = new context::Context();
- d_satSolver = prop::SatSolverFactory::createMinisat(
- d_nullContext, smtStatisticsRegistry(), "EagerBitblaster");
- d_cnfStream = new prop::TseitinCnfStream(d_satSolver, d_bitblastingRegistrar,
- d_nullContext, d_bv->globals());
-
+ d_satSolver = prop::SatSolverFactory::createMinisat(d_nullContext,
+ smtStatisticsRegistry(),
+ "EagerBitblaster");
+ d_cnfStream = new prop::TseitinCnfStream(d_satSolver,
+ d_bitblastingRegistrar,
+ d_nullContext,
+ d_bv->globals(),
+ options::proof(),
+ "EagerBitblaster");
+
MinisatEmptyNotify* notify = new MinisatEmptyNotify();
d_satSolver->setNotify(notify);
+ d_bvp = NULL;
}
EagerBitblaster::~EagerBitblaster() {
@@ -85,21 +88,34 @@ void EagerBitblaster::bbAtom(TNode node) {
// the bitblasted definition of the atom
Node normalized = Rewriter::rewrite(node);
Node atom_bb = normalized.getKind() != kind::CONST_BOOLEAN ?
- Rewriter::rewrite(d_atomBBStrategies[normalized.getKind()](normalized, this)) :
- normalized;
+ d_atomBBStrategies[normalized.getKind()](normalized, this) :
+ normalized;
+
+ if (!options::proof()) {
+ atom_bb = Rewriter::rewrite(atom_bb);
+ }
+
// asserting that the atom is true iff the definition holds
Node atom_definition = utils::mkNode(kind::IFF, node, atom_bb);
- AlwaysAssert (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER);
- storeBBAtom(node, atom_definition);
+ AlwaysAssert (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER);
+ storeBBAtom(node, atom_bb);
d_cnfStream->convertAndAssert(atom_definition, false, false, RULE_INVALID, TNode::null());
}
void EagerBitblaster::storeBBAtom(TNode atom, Node atom_bb) {
- // no need to store the definition for the lazy bit-blaster
- d_bbAtoms.insert(atom);
+ if( d_bvp ){
+ d_bvp->registerAtomBB(atom.toExpr(), atom_bb.toExpr());
+ }
+ d_bbAtoms.insert(atom);
}
+void EagerBitblaster::storeBBTerm(TNode node, const Bits& bits) {
+ if( d_bvp ){ d_bvp->registerTermBB(node.toExpr()); }
+ d_termCache.insert(std::make_pair(node, bits));
+}
+
+
bool EagerBitblaster::hasBBAtom(TNode atom) const {
return d_bbAtoms.find(atom) != d_bbAtoms.end();
}
@@ -211,6 +227,12 @@ void EagerBitblaster::collectModelInfo(TheoryModel* m, bool fullModel) {
}
}
+void EagerBitblaster::setProofLog( BitVectorProof * bvp ) {
+ d_bvp = bvp;
+ d_satSolver->setProofLog(bvp);
+ bvp->initCnfProof(d_cnfStream, d_nullContext);
+}
+
bool EagerBitblaster::isSharedTerm(TNode node) {
return d_bv->d_sharedTermsSet.find(node) != d_bv->d_sharedTermsSet.end();
}
diff --git a/src/theory/bv/lazy_bitblaster.cpp b/src/theory/bv/lazy_bitblaster.cpp
index 34a9418dd..9268e2152 100644
--- a/src/theory/bv/lazy_bitblaster.cpp
+++ b/src/theory/bv/lazy_bitblaster.cpp
@@ -25,7 +25,9 @@
#include "theory/bv/theory_bv.h"
#include "theory/rewriter.h"
#include "theory/theory_model.h"
-#include "theory_bv_utils.h"
+#include "proof/bitvector_proof.h"
+#include "proof/proof_manager.h"
+#include "theory/bv/theory_bv_utils.h"
namespace CVC4 {
namespace theory {
@@ -51,8 +53,12 @@ TLazyBitblaster::TLazyBitblaster(context::Context* c, bv::TheoryBV* bv,
c, smtStatisticsRegistry(), name);
d_nullRegistrar = new prop::NullRegistrar();
d_nullContext = new context::Context();
- d_cnfStream = new prop::TseitinCnfStream(d_satSolver, d_nullRegistrar,
- d_nullContext, d_bv->globals());
+ d_cnfStream = new prop::TseitinCnfStream(d_satSolver,
+ d_nullRegistrar,
+ d_nullContext,
+ d_bv->globals(),
+ options::proof(),
+ "LazyBitblaster");
d_satSolverNotify = d_emptyNotify ?
(prop::BVSatSolverInterface::Notify*) new MinisatEmptyNotify() :
@@ -127,8 +133,12 @@ void TLazyBitblaster::bbAtom(TNode node) {
// the bitblasted definition of the atom
Node normalized = Rewriter::rewrite(node);
Node atom_bb = normalized.getKind() != kind::CONST_BOOLEAN ?
- Rewriter::rewrite(d_atomBBStrategies[normalized.getKind()](normalized, this)) :
- normalized;
+ d_atomBBStrategies[normalized.getKind()](normalized, this) : normalized;
+
+ if (!options::proof()) {
+ atom_bb = Rewriter::rewrite(atom_bb);
+ }
+
// asserting that the atom is true iff the definition holds
Node atom_definition = utils::mkNode(kind::IFF, node, atom_bb);
storeBBAtom(node, atom_bb);
@@ -136,10 +146,19 @@ void TLazyBitblaster::bbAtom(TNode node) {
}
void TLazyBitblaster::storeBBAtom(TNode atom, Node atom_bb) {
- // no need to store the definition for the lazy bit-blaster
+ // No need to store the definition for the lazy bit-blaster (unless proofs are enabled).
+ if( d_bvp != NULL ){
+ d_bvp->registerAtomBB(atom.toExpr(), atom_bb.toExpr());
+ }
d_bbAtoms.insert(atom);
}
+void TLazyBitblaster::storeBBTerm(TNode node, const Bits& bits) {
+ if( d_bvp ){ d_bvp->registerTermBB(node.toExpr()); }
+ d_termCache.insert(std::make_pair(node, bits));
+}
+
+
bool TLazyBitblaster::hasBBAtom(TNode atom) const {
return d_bbAtoms.find(atom) != d_bbAtoms.end();
}
@@ -483,6 +502,12 @@ void TLazyBitblaster::collectModelInfo(TheoryModel* m, bool fullModel) {
}
}
+void TLazyBitblaster::setProofLog( BitVectorProof * bvp ){
+ d_bvp = bvp;
+ d_satSolver->setProofLog( bvp );
+ bvp->initCnfProof(d_cnfStream, d_nullContext);
+}
+
void TLazyBitblaster::clearSolver() {
Assert (d_ctx->getLevel() == 0);
delete d_satSolver;
diff --git a/src/theory/bv/theory_bv.cpp b/src/theory/bv/theory_bv.cpp
index 4acd1b847..8f7e975cd 100644
--- a/src/theory/bv/theory_bv.cpp
+++ b/src/theory/bv/theory_bv.cpp
@@ -30,6 +30,8 @@
#include "theory/bv/theory_bv_rewriter.h"
#include "theory/bv/theory_bv_utils.h"
#include "theory/theory_model.h"
+#include "proof/theory_proof.h"
+#include "proof/proof_manager.h"
#include "theory/valuation.h"
using namespace CVC4::context;
@@ -363,7 +365,6 @@ void TheoryBV::checkForLemma(TNode fact) {
}
}
-
void TheoryBV::check(Effort e)
{
if (done() && !fullEffort(e)) {
@@ -706,6 +707,7 @@ Node TheoryBV::explain(TNode node) {
// return the explanation
Node explanation = utils::mkAnd(assumptions);
Debug("bitvector::explain") << "TheoryBV::explain(" << node << ") => " << explanation << std::endl;
+ Debug("bitvector::explain") << "TheoryBV::explain done. \n";
return explanation;
}
@@ -796,6 +798,16 @@ bool TheoryBV::applyAbstraction(const std::vector<Node>& assertions, std::vector
return changed;
}
+void TheoryBV::setProofLog( BitVectorProof * bvp ) {
+ if( options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER ){
+ d_eagerSolver->setProofLog( bvp );
+ }else{
+ for( unsigned i=0; i< d_subtheories.size(); i++ ){
+ d_subtheories[i]->setProofLog( bvp );
+ }
+ }
+}
+
void TheoryBV::setConflict(Node conflict) {
if (options::bvAbstraction()) {
Node new_conflict = d_abstractionModule->simplifyConflict(conflict);
diff --git a/src/theory/bv/theory_bv.h b/src/theory/bv/theory_bv.h
index e7e4d464f..27138abfc 100644
--- a/src/theory/bv/theory_bv.h
+++ b/src/theory/bv/theory_bv.h
@@ -87,7 +87,10 @@ public:
void ppStaticLearn(TNode in, NodeBuilder<>& learned);
void presolve();
- bool applyAbstraction(const std::vector<Node>& assertions, std::vector<Node>& new_assertions);
+
+ bool applyAbstraction(const std::vector<Node>& assertions, std::vector<Node>& new_assertions);
+
+ void setProofLog( BitVectorProof * bvp );
private:
@@ -209,11 +212,10 @@ private:
void sendConflict();
- void lemma(TNode node) { d_out->lemma(node); d_lemmasAdded = true; }
+ void lemma(TNode node) { d_out->lemma(node, RULE_CONFLICT); d_lemmasAdded = true; }
void checkForLemma(TNode node);
-
friend class LazyBitblaster;
friend class TLazyBitblaster;
friend class EagerBitblaster;
diff --git a/src/theory/bv/theory_bv_rewrite_rules_core.h b/src/theory/bv/theory_bv_rewrite_rules_core.h
index 676df5dde..185985b3b 100644
--- a/src/theory/bv/theory_bv_rewrite_rules_core.h
+++ b/src/theory/bv/theory_bv_rewrite_rules_core.h
@@ -276,7 +276,8 @@ bool RewriteRule<ReflexivityEq>::applies(TNode node) {
template<> inline
Node RewriteRule<ReflexivityEq>::apply(TNode node) {
Debug("bv-rewrite") << "RewriteRule<ReflexivityEq>(" << node << ")" << std::endl;
- return node[1].eqNode(node[0]);
+ Node res = node[1].eqNode(node[0]);
+ return res;
}
}
diff --git a/src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h b/src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h
index cd173a6dd..d5d6c39dd 100644
--- a/src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h
+++ b/src/theory/bv/theory_bv_rewrite_rules_operator_elimination.h
@@ -325,7 +325,8 @@ Node RewriteRule<XnorEliminate>::apply(TNode node) {
TNode a = node[0];
TNode b = node[1];
Node xorNode = utils::mkNode(kind::BITVECTOR_XOR, a, b);
- return utils::mkNode(kind::BITVECTOR_NOT, xorNode);
+ Node result = utils::mkNode(kind::BITVECTOR_NOT, xorNode);
+ return result;
}
diff --git a/src/theory/bv/theory_bv_rewrite_rules_simplification.h b/src/theory/bv/theory_bv_rewrite_rules_simplification.h
index 3bf390ded..4d3b676c9 100644
--- a/src/theory/bv/theory_bv_rewrite_rules_simplification.h
+++ b/src/theory/bv/theory_bv_rewrite_rules_simplification.h
@@ -379,8 +379,8 @@ Node RewriteRule<XorZero>::apply(TNode node) {
children.push_back(node[i]);
}
}
-
- return utils::mkNode(kind::BITVECTOR_XOR, children);
+ Node res = utils::mkNode(kind::BITVECTOR_XOR, children);
+ return res;
}
@@ -488,7 +488,7 @@ bool RewriteRule<NotIdemp>::applies(TNode node) {
template<> inline
Node RewriteRule<NotIdemp>::apply(TNode node) {
- Debug("bv-rewrite") << "RewriteRule<XorIdemp>(" << node << ")" << std::endl;
+ Debug("bv-rewrite") << "RewriteRule<NotIdemp>(" << node << ")" << std::endl;
return node[0][0];
}
diff --git a/src/theory/bv/theory_bv_utils.h b/src/theory/bv/theory_bv_utils.h
index ba8074fbb..993be309b 100644
--- a/src/theory/bv/theory_bv_utils.h
+++ b/src/theory/bv/theory_bv_utils.h
@@ -51,11 +51,11 @@ inline unsigned getSize(TNode node) {
return node.getType().getBitVectorSize();
}
-// this seems to behave strangely
-inline const Integer& getBit(TNode node, unsigned i) {
- Assert (0);
- Assert (node.getKind() == kind::CONST_BITVECTOR);
- return node.getConst<BitVector>().extract(i, i).getValue();
+inline const bool getBit(TNode node, unsigned i) {
+ Assert (i < utils::getSize(node) &&
+ node.getKind() == kind::CONST_BITVECTOR);
+ Integer bit = node.getConst<BitVector>().extract(i, i).getValue();
+ return (bit == 1u);
}
inline Node mkTrue() {
diff --git a/src/theory/output_channel.h b/src/theory/output_channel.h
index 2491aef3a..d5c12457a 100644
--- a/src/theory/output_channel.h
+++ b/src/theory/output_channel.h
@@ -22,6 +22,7 @@
#include "base/cvc4_assert.h"
#include "smt/logic_exception.h"
#include "theory/interrupted.h"
+#include "proof/proof_manager.h"
#include "util/resource_manager.h"
namespace CVC4 {
@@ -99,8 +100,10 @@ public:
* assigned false), or else a literal by itself (in the case of a
* unit conflict) which is assigned TRUE (and T-conflicting) in the
* current assignment.
+ * @param pf - a proof of the conflict. This is only non-null if proofs
+ * are enabled.
*/
- virtual void conflict(TNode n) throw(AssertionException, UnsafeInterruptException) = 0;
+ virtual void conflict(TNode n, Proof* pf = NULL) throw(AssertionException, UnsafeInterruptException) = 0;
/**
* Propagate a theory literal.
@@ -115,16 +118,31 @@ public:
* been detected. (This requests a split.)
*
* @param n - a theory lemma valid at decision level 0
+ * @param rule - the proof rule for this lemma
* @param removable - whether the lemma can be removed at any point
* @param preprocess - whether to apply more aggressive preprocessing
* @param sendAtoms - whether to ensure atoms are sent to the theory
* @return the "status" of the lemma, including user level at which
* the lemma resides; the lemma will be removed when this user level pops
*/
- virtual LemmaStatus lemma(TNode n, bool removable = false,
- bool preprocess = false, bool sendAtoms = false)
- throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException, LogicException) = 0;
+ virtual LemmaStatus lemma(TNode n, ProofRule rule,
+ bool removable = false,
+ bool preprocess = false,
+ bool sendAtoms = false)
+ throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException) = 0;
+
+ /**
+ * Variant of the lemma function that does not require providing a proof rule.
+ */
+ virtual LemmaStatus lemma(TNode n,
+ bool removable = false,
+ bool preprocess = false,
+ bool sendAtoms = false)
+ throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException) {
+ return lemma(n, RULE_INVALID, removable, preprocess, sendAtoms);
+ }
+
/**
* Request a split on a new theory atom. This is equivalent to
* calling lemma({OR n (NOT n)}).
diff --git a/src/theory/rewriter.cpp b/src/theory/rewriter.cpp
index c98429dd2..d89724cbd 100644
--- a/src/theory/rewriter.cpp
+++ b/src/theory/rewriter.cpp
@@ -40,7 +40,9 @@ static CVC4_THREADLOCAL(std::hash_set<Node, NodeHashFunction>*) s_rewriteStack =
class RewriterInitializer {
static RewriterInitializer s_rewriterInitializer;
- RewriterInitializer() { Rewriter::init(); }
+ RewriterInitializer() {
+ Rewriter::init();
+ }
~RewriterInitializer() { Rewriter::shutdown(); }
};/* class RewriterInitializer */
@@ -190,7 +192,8 @@ Node Rewriter::rewriteTo(theory::TheoryId theoryId, Node node) {
// Incorporate the children if necessary
if (rewriteStackTop.node.getNumChildren() > 0) {
- rewriteStackTop.node = rewriteStackTop.builder;
+ Node rewritten = rewriteStackTop.builder;
+ rewriteStackTop.node = rewritten;
rewriteStackTop.theoryId = theoryOf(rewriteStackTop.node);
}
@@ -208,7 +211,8 @@ Node Rewriter::rewriteTo(theory::TheoryId theoryId, Node node) {
Assert(s_rewriteStack->find(response.node) == s_rewriteStack->end());
s_rewriteStack->insert(response.node);
#endif
- rewriteStackTop.node = rewriteTo(newTheoryId, response.node);
+ Node rewritten = rewriteTo(newTheoryId, response.node);
+ rewriteStackTop.node = rewritten;
#ifdef CVC4_ASSERTIONS
s_rewriteStack->erase(response.node);
#endif
diff --git a/src/theory/theory.cpp b/src/theory/theory.cpp
index 9e946f8d7..45c9b1936 100644
--- a/src/theory/theory.cpp
+++ b/src/theory/theory.cpp
@@ -50,8 +50,9 @@ std::ostream& operator<<(std::ostream& os, Theory::Effort level){
Theory::Theory(TheoryId id, context::Context* satContext, context::UserContext* userContext,
OutputChannel& out, Valuation valuation, const LogicInfo& logicInfo,
- SmtGlobals* globals) throw()
+ SmtGlobals* globals, std::string name) throw()
: d_id(id)
+ , d_instanceName(name)
, d_satContext(satContext)
, d_userContext(userContext)
, d_logicInfo(logicInfo)
@@ -60,12 +61,12 @@ Theory::Theory(TheoryId id, context::Context* satContext, context::UserContext*
, d_sharedTermsIndex(satContext, 0)
, d_careGraph(NULL)
, d_quantEngine(NULL)
- , d_checkTime(statName(id, "checkTime"))
- , d_computeCareGraphTime(statName(id, "computeCareGraphTime"))
+ , d_checkTime(getFullInstanceName() + "::checkTime")
+ , d_computeCareGraphTime(getFullInstanceName() + "::computeCareGraphTime")
, d_sharedTerms(satContext)
, d_out(&out)
, d_valuation(valuation)
- , d_proofEnabled(false)
+ , d_proofsEnabled(false)
, d_globals(globals)
{
smtStatisticsRegistry()->registerStat(&d_checkTime);
diff --git a/src/theory/theory.h b/src/theory/theory.h
index f7d9ee6a0..2c3c66d8b 100644
--- a/src/theory/theory.h
+++ b/src/theory/theory.h
@@ -149,6 +149,11 @@ private:
*/
TheoryId d_id;
+ /** Name of this theory instance. Along with the TheoryId this should provide
+ * an unique string identifier for each instance of a Theory class. We need
+ * this to ensure unique statistics names over multiple theory instances. */
+ std::string d_instanceName;
+
/**
* The SAT search context for the Theory.
*/
@@ -204,12 +209,6 @@ protected:
/** time spent in theory combination */
TimerStat d_computeCareGraphTime;
- static std::string statName(TheoryId id, const char* statName) {
- std::stringstream ss;
- ss << "theory<" << id << ">::" << statName;
- return ss.str();
- }
-
/**
* The only method to add suff to the care graph.
*/
@@ -247,7 +246,7 @@ protected:
*/
Theory(TheoryId id, context::Context* satContext, context::UserContext* userContext,
OutputChannel& out, Valuation valuation, const LogicInfo& logicInfo,
- SmtGlobals* globals) throw();
+ SmtGlobals* globals, std::string name = "") throw(); // taking : No default.
/**
* This is called at shutdown time by the TheoryEngine, just before
@@ -272,6 +271,12 @@ protected:
Valuation d_valuation;
/**
+ * Whether proofs are enabled
+ *
+ */
+ bool d_proofsEnabled;
+
+ /**
* Returns the next assertion in the assertFact() queue.
*
* @return the next assertion in the assertFact() queue
@@ -290,12 +295,6 @@ protected:
void printFacts(std::ostream& os) const;
void debugPrintFacts() const;
- /**
- * Whether proofs are enabled
- *
- */
- bool d_proofEnabled;
-
SmtGlobals* d_globals;
public:
@@ -416,6 +415,13 @@ public:
return d_id;
}
+ std::string getFullInstanceName() const {
+ std::stringstream ss;
+ ss << "theory<" << d_id << ">" << d_instanceName;
+ return ss.str();
+ }
+
+
/**
* Get the SAT context associated to this Theory.
*/
@@ -855,7 +861,11 @@ public:
*/
virtual std::pair<bool, Node> entailmentCheck(TNode lit, const EntailmentCheckParameters* params = NULL, EntailmentCheckSideEffects* out = NULL);
-
+ /**
+ * Turn on proof-production mode.
+ */
+ void produceProofs() { d_proofsEnabled = true; }
+
/** Returns a pointer to the globals copy the theory is using. */
SmtGlobals* globals() { return d_globals; }
diff --git a/src/theory/theory_engine.cpp b/src/theory/theory_engine.cpp
index 25eac2ed4..be2a89dbc 100644
--- a/src/theory/theory_engine.cpp
+++ b/src/theory/theory_engine.cpp
@@ -27,7 +27,7 @@
#include "options/options.h"
#include "options/quantifiers_options.h"
#include "proof/proof_manager.h"
-#include "proof/proof_manager.h"
+#include "proof/theory_proof.h"
#include "smt/logic_exception.h"
#include "smt_util/ite_removal.h"
#include "smt_util/lemma_output_channel.h"
@@ -54,8 +54,6 @@ using namespace CVC4::theory;
namespace CVC4 {
void TheoryEngine::finishInit() {
- PROOF (ProofManager::initTheoryProof(); );
-
// initialize the quantifiers engine
d_quantEngine = new QuantifiersEngine(d_context, d_userContext, this);
@@ -157,6 +155,8 @@ TheoryEngine::TheoryEngine(context::Context* context,
d_true = NodeManager::currentNM()->mkConst<bool>(true);
d_false = NodeManager::currentNM()->mkConst<bool>(false);
+ PROOF (ProofManager::currentPM()->initTheoryProofEngine(d_globals); );
+
d_iteUtilities = new ITEUtilities(d_iteRemover.getContainsVisitor());
smtStatisticsRegistry()->registerStat(&d_arithSubstitutionsAdded);
@@ -377,7 +377,7 @@ void TheoryEngine::check(Theory::Effort effort) {
printAssertions("theory::assertions::fulleffort");
}
}
-
+
// Note that we've discharged all the facts
d_factsAsserted = false;
@@ -414,7 +414,7 @@ void TheoryEngine::check(Theory::Effort effort) {
// must build model at this point
d_curr_model_builder->buildModel(d_curr_model, true);
}
- Trace("theory::assertions-model") << endl;
+ Trace("theory::assertions-model") << endl;
if (Trace.isOn("theory::assertions-model")) {
printAssertions("theory::assertions-model");
}
@@ -486,7 +486,7 @@ void TheoryEngine::combineTheories() {
// We need to split on it
Debug("combineTheories") << "TheoryEngine::combineTheories(): requesting a split " << endl;
- lemma(equality.orNode(equality.notNode()), false, false, false, carePair.theory);
+ lemma(equality.orNode(equality.notNode()), RULE_INVALID, false, false, false, carePair.theory);
// This code is supposed to force preference to follow what the theory models already have
// but it doesn't seem to make a big difference - need to explore more -Clark
// if (true) {
@@ -1371,7 +1371,12 @@ void TheoryEngine::ensureLemmaAtoms(const std::vector<TNode>& atoms, theory::The
}
}
-theory::LemmaStatus TheoryEngine::lemma(TNode node, bool negated, bool removable, bool preprocess, theory::TheoryId atomsTo) {
+theory::LemmaStatus TheoryEngine::lemma(TNode node,
+ ProofRule rule,
+ bool negated,
+ bool removable,
+ bool preprocess,
+ theory::TheoryId atomsTo) {
// For resource-limiting (also does a time check).
// spendResource();
@@ -1420,10 +1425,10 @@ theory::LemmaStatus TheoryEngine::lemma(TNode node, bool negated, bool removable
}
// assert to prop engine
- d_propEngine->assertLemma(additionalLemmas[0], negated, removable, RULE_INVALID, node);
+ d_propEngine->assertLemma(additionalLemmas[0], negated, removable, rule, node);
for (unsigned i = 1; i < additionalLemmas.size(); ++ i) {
additionalLemmas[i] = theory::Rewriter::rewrite(additionalLemmas[i]);
- d_propEngine->assertLemma(additionalLemmas[i], false, removable, RULE_INVALID, node);
+ d_propEngine->assertLemma(additionalLemmas[i], false, removable, rule, node);
}
// WARNING: Below this point don't assume additionalLemmas[0] to be not negated.
@@ -1467,11 +1472,11 @@ void TheoryEngine::conflict(TNode conflict, TheoryId theoryId) {
Node fullConflict = mkExplanation(explanationVector);
Debug("theory::conflict") << "TheoryEngine::conflict(" << conflict << ", " << theoryId << "): full = " << fullConflict << endl;
Assert(properConflict(fullConflict));
- lemma(fullConflict, true, true, false, THEORY_LAST);
+ lemma(fullConflict, RULE_CONFLICT, true, true, false, THEORY_LAST);
} else {
// When only one theory, the conflict should need no processing
Assert(properConflict(conflict));
- lemma(conflict, true, true, false, THEORY_LAST);
+ lemma(conflict, RULE_CONFLICT, true, true, false, THEORY_LAST);
}
}
@@ -1483,27 +1488,27 @@ void TheoryEngine::staticInitializeBVOptions(const std::vector<Node>& assertions
if (options::produceModels())
throw ModalException("Slicer does not currently support model generation. Use --bv-eq-slicer=off");
useSlicer = true;
-
+
} else if (options::bitvectorEqualitySlicer() == bv::BITVECTOR_SLICER_OFF) {
return;
-
+
} else if (options::bitvectorEqualitySlicer() == bv::BITVECTOR_SLICER_AUTO) {
if (options::incrementalSolving() ||
options::produceModels())
return;
- useSlicer = true;
+ useSlicer = true;
bv::utils::TNodeBoolMap cache;
for (unsigned i = 0; i < assertions.size(); ++i) {
- useSlicer = useSlicer && bv::utils::isCoreTerm(assertions[i], cache);
+ useSlicer = useSlicer && bv::utils::isCoreTerm(assertions[i], cache);
}
}
-
+
if (useSlicer) {
- bv::TheoryBV* bv_theory = (bv::TheoryBV*)d_theoryTable[THEORY_BV];
+ bv::TheoryBV* bv_theory = (bv::TheoryBV*)d_theoryTable[THEORY_BV];
bv_theory->enableCoreTheorySlicer();
}
-
+
}
void TheoryEngine::ppBvToBool(const std::vector<Node>& assertions, std::vector<Node>& new_assertions) {
@@ -1511,12 +1516,12 @@ void TheoryEngine::ppBvToBool(const std::vector<Node>& assertions, std::vector<N
}
bool TheoryEngine::ppBvAbstraction(const std::vector<Node>& assertions, std::vector<Node>& new_assertions) {
- bv::TheoryBV* bv_theory = (bv::TheoryBV*)d_theoryTable[THEORY_BV];
- return bv_theory->applyAbstraction(assertions, new_assertions);
+ bv::TheoryBV* bv_theory = (bv::TheoryBV*)d_theoryTable[THEORY_BV];
+ return bv_theory->applyAbstraction(assertions, new_assertions);
}
void TheoryEngine::mkAckermanizationAsssertions(std::vector<Node>& assertions) {
- bv::TheoryBV* bv_theory = (bv::TheoryBV*)d_theoryTable[THEORY_BV];
+ bv::TheoryBV* bv_theory = (bv::TheoryBV*)d_theoryTable[THEORY_BV];
bv_theory->mkAckermanizationAsssertions(assertions);
}
diff --git a/src/theory/theory_engine.h b/src/theory/theory_engine.h
index 7cb15ca97..0bf00c079 100644
--- a/src/theory/theory_engine.h
+++ b/src/theory/theory_engine.h
@@ -269,8 +269,9 @@ class TheoryEngine {
}
}
- void conflict(TNode conflictNode) throw(AssertionException, UnsafeInterruptException) {
+ void conflict(TNode conflictNode, Proof* pf = NULL) throw(AssertionException, UnsafeInterruptException) {
Trace("theory::conflict") << "EngineOutputChannel<" << d_theory << ">::conflict(" << conflictNode << ")" << std::endl;
+ Assert(pf == NULL); // theory shouldn't be producing proofs yet
++ d_statistics.conflicts;
d_engine->d_outputChannelUsed = true;
d_engine->conflict(conflictNode, d_theory);
@@ -283,18 +284,23 @@ class TheoryEngine {
return d_engine->propagate(literal, d_theory);
}
- theory::LemmaStatus lemma(TNode lemma, bool removable = false, bool preprocess = false, bool sendAtoms = false) throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException, LogicException) {
+ theory::LemmaStatus lemma(TNode lemma,
+ ProofRule rule,
+ bool removable = false,
+ bool preprocess = false,
+ bool sendAtoms = false)
+ throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException) {
Trace("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::lemma(" << lemma << ")" << std::endl;
++ d_statistics.lemmas;
d_engine->d_outputChannelUsed = true;
- return d_engine->lemma(lemma, false, removable, preprocess, sendAtoms ? d_theory : theory::THEORY_LAST);
+ return d_engine->lemma(lemma, rule, false, removable, preprocess, sendAtoms ? d_theory: theory::THEORY_LAST);
}
theory::LemmaStatus splitLemma(TNode lemma, bool removable = false) throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException) {
Trace("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::lemma(" << lemma << ")" << std::endl;
++ d_statistics.lemmas;
d_engine->d_outputChannelUsed = true;
- return d_engine->lemma(lemma, false, removable, false, d_theory);
+ return d_engine->lemma(lemma, RULE_SPLIT, false, removable, false, d_theory);
}
void demandRestart() throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException) {
@@ -304,7 +310,7 @@ class TheoryEngine {
"A boolean variable asserted to be true to force a restart");
Trace("theory::restart") << "EngineOutputChannel<" << d_theory << ">::restart(" << restartVar << ")" << std::endl;
++ d_statistics.restartDemands;
- lemma(restartVar, true);
+ lemma(restartVar, RULE_INVALID, true);
}
void requirePhase(TNode n, bool phase)
@@ -436,7 +442,12 @@ class TheoryEngine {
* @param removable can the lemma be remove (restrictions apply)
* @param needAtoms if not THEORY_LAST, then
*/
- theory::LemmaStatus lemma(TNode node, bool negated, bool removable, bool preprocess, theory::TheoryId atomsTo);
+ theory::LemmaStatus lemma(TNode node,
+ ProofRule rule,
+ bool negated,
+ bool removable,
+ bool preprocess,
+ theory::TheoryId atomsTo);
/** Enusre that the given atoms are send to the given theory */
void ensureLemmaAtoms(const std::vector<TNode>& atoms, theory::TheoryId theory);
diff --git a/src/theory/theory_test_utils.h b/src/theory/theory_test_utils.h
index f0b616d62..6247833f8 100644
--- a/src/theory/theory_test_utils.h
+++ b/src/theory/theory_test_utils.h
@@ -71,7 +71,7 @@ public:
void safePoint(uint64_t ammount) throw(Interrupted, AssertionException) {}
- void conflict(TNode n)
+ void conflict(TNode n, Proof* pf = NULL)
throw(AssertionException, UnsafeInterruptException) {
push(CONFLICT, n);
}
@@ -87,7 +87,10 @@ public:
push(PROPAGATE_AS_DECISION, n);
}
- LemmaStatus lemma(TNode n, bool removable, bool preprocess, bool sendAtoms) throw(AssertionException, UnsafeInterruptException) {
+ LemmaStatus lemma(TNode n, ProofRule rule,
+ bool removable = false,
+ bool preprocess = false,
+ bool sendAtoms = false) throw(AssertionException, UnsafeInterruptException) {
push(LEMMA, n);
return LemmaStatus(Node::null(), 0);
}
diff --git a/src/theory/uf/equality_engine.cpp b/src/theory/uf/equality_engine.cpp
index 828d53144..8df323992 100644
--- a/src/theory/uf/equality_engine.cpp
+++ b/src/theory/uf/equality_engine.cpp
@@ -314,10 +314,10 @@ void EqualityEngine::addTermInternal(TNode t, bool isOperator) {
// How many children are not constants yet
d_subtermsToEvaluate[result] = t.getNumChildren();
for (unsigned i = 0; i < t.getNumChildren(); ++ i) {
- if (isConstant(getNodeId(t[i]))) {
- Debug("equality::evaluation") << d_name << "::eq::addTermInternal(" << t << "): evaluates " << t[i] << std::endl;
- subtermEvaluates(result);
- }
+ if (isConstant(getNodeId(t[i]))) {
+ Debug("equality::evaluation") << d_name << "::eq::addTermInternal(" << t << "): evaluates " << t[i] << std::endl;
+ subtermEvaluates(result);
+ }
}
}
} else {
@@ -335,7 +335,7 @@ void EqualityEngine::addTermInternal(TNode t, bool isOperator) {
} else if (d_constantsAreTriggers && d_isConstant[result]) {
// Non-Boolean constants are trigger terms for all tags
EqualityNodeId tId = getNodeId(t);
- // Setup the new set
+ // Setup the new set
Theory::Set newSetTags = 0;
EqualityNodeId newSetTriggers[THEORY_LAST];
unsigned newSetTriggersSize = THEORY_LAST;
@@ -629,12 +629,12 @@ bool EqualityEngine::merge(EqualityNode& class1, EqualityNode& class2, std::vect
Debug("equality") << d_name << "::eq::merge(" << class1.getFind() << "," << class2.getFind() << "): " << d_nodes[currentId] << " in " << d_nodes[funId] << std::endl;
const FunctionApplication& fun = d_applications[useNode.getApplicationId()].normalized;
// If it's interpreted and we can interpret
- if (fun.isInterpreted() && class1isConstant && !d_isInternal[currentId]) {
- // Get the actual term id
- TNode term = d_nodes[funId];
- subtermEvaluates(getNodeId(term));
- }
- // Check if there is an application with find arguments
+ if (fun.isInterpreted() && class1isConstant && !d_isInternal[currentId]) {
+ // Get the actual term id
+ TNode term = d_nodes[funId];
+ subtermEvaluates(getNodeId(term));
+ }
+ // Check if there is an application with find arguments
EqualityNodeId aNormalized = getEqualityNode(fun.a).getFind();
EqualityNodeId bNormalized = getEqualityNode(fun.b).getFind();
FunctionApplication funNormalized(fun.type, aNormalized, bNormalized);
@@ -972,7 +972,7 @@ void EqualityEngine::getExplanation(EqualityNodeId t1Id, EqualityNodeId t2Id, st
// If the nodes are the same, we're done
if (t1Id == t2Id){
if( eqp ) {
- eqp->d_node = d_nodes[t1Id];
+ eqp->d_node = ProofManager::currentPM()->mkOp(d_nodes[t1Id]);
}
return;
}
@@ -1029,6 +1029,7 @@ void EqualityEngine::getExplanation(EqualityNodeId t1Id, EqualityNodeId t2Id, st
MergeReasonType reasonType = d_equalityEdges[currentEdge].getReasonType();
Debug("equality") << d_name << "::eq::getExplanation(): currentEdge = " << currentEdge << ", currentNode = " << currentNode << std::endl;
+ Debug("equality") << d_name << " in currentEdge = (" << d_nodes[currentNode] << "," << d_nodes[edge.getNodeId()] << ")" << std::endl;
EqProof * eqpc = NULL;
//make child proof if a proof is being constructed
@@ -1051,6 +1052,20 @@ void EqualityEngine::getExplanation(EqualityNodeId t1Id, EqualityNodeId t2Id, st
if( eqpc ){
eqpc->d_children.push_back( eqpc1 );
eqpc->d_children.push_back( eqpc2 );
+ Debug("equality-pf") << "Congruence : " << d_nodes[currentNode] << " " << d_nodes[edgeNode] << std::endl;
+ if( d_nodes[currentNode].getKind()==kind::EQUAL ){
+ //leave node null for now
+ eqpc->d_node = Node::null();
+ }else{
+ Debug("equality-pf") << d_nodes[f1.a] << " / " << d_nodes[f2.a] << ", " << d_nodes[f1.b] << " / " << d_nodes[f2.b] << std::endl;
+ if(d_nodes[f1.a].getKind() == kind::APPLY_UF ||
+ d_nodes[f1.a].getKind() == kind::SELECT ||
+ d_nodes[f1.a].getKind() == kind::STORE) {
+ eqpc->d_node = d_nodes[f1.a];
+ } else {
+ eqpc->d_node = NodeManager::currentNM()->mkNode(kind::PARTIAL_APPLY_UF, ProofManager::currentPM()->mkOp(d_nodes[f1.a]), d_nodes[f1.b]);
+ }
+ }
}
Debug("equality") << pop;
break;
@@ -1103,13 +1118,14 @@ void EqualityEngine::getExplanation(EqualityNodeId t1Id, EqualityNodeId t2Id, st
// Construct the equality
Debug("equality") << d_name << "::eq::getExplanation(): adding: " << d_equalityEdges[currentEdge].getReason() << std::endl;
if( eqpc ){
- if( reasonType==MERGED_THROUGH_EQUALITY ){
+ if(reasonType == MERGED_THROUGH_EQUALITY) {
eqpc->d_node = d_equalityEdges[currentEdge].getReason();
- }else{
- //theory-specific proof rule : TODO
- eqpc->d_id = reasonType;
- //eqpc->d_node = d_equalityEdges[currentEdge].getNodeId();
+ } else {
+ // theory-specific proof rule
+ eqpc->d_node = d_nodes[d_equalityEdges[currentEdge].getNodeId()].eqNode(d_nodes[currentNode]);
+ Debug("equality-pf") << "theory eq : " << eqpc->d_node << std::endl;
}
+ eqpc->d_id = reasonType;
}
equalities.push_back(d_equalityEdges[currentEdge].getReason());
break;
@@ -1120,13 +1136,32 @@ void EqualityEngine::getExplanation(EqualityNodeId t1Id, EqualityNodeId t2Id, st
currentEdge = bfsQueue[currentIndex].edgeId;
currentIndex = bfsQueue[currentIndex].previousIndex;
+ //---from Morgan---
+ if(eqpc != NULL && eqpc->d_id == MERGED_THROUGH_REFLEXIVITY) {
+ if(eqpc->d_node.isNull()) {
+ Assert(eqpc->d_children.size() == 1);
+ EqProof *p = eqpc;
+ eqpc = p->d_children[0];
+ delete p;
+ } else {
+ Assert(eqpc->d_children.empty());
+ }
+ }
+ //---end from Morgan---
+
eqp_trans.push_back( eqpc );
} while (currentEdge != null_id);
- if( eqp ){
- eqp->d_id = MERGED_THROUGH_TRANS;
- eqp->d_children.insert( eqp->d_children.end(), eqp_trans.begin(), eqp_trans.end() );
+ if(eqp) {
+ if(eqp_trans.size() == 1) {
+ *eqp = *eqp_trans[0];
+ delete eqp_trans[0];
+ } else {
+ eqp->d_id = MERGED_THROUGH_TRANS;
+ eqp->d_children.insert( eqp->d_children.end(), eqp_trans.begin(), eqp_trans.end() );
+ eqp->d_node = NodeManager::currentNM()->mkNode(d_nodes[t1Id].getType().isBoolean() ? kind::IFF : kind::EQUAL, d_nodes[t1Id], d_nodes[t2Id]);
+ }
}
// Done
@@ -2057,8 +2092,7 @@ bool EqClassIterator::isFinished() const {
return d_current == null_id;
}
-
-void EqProof::debug_print( const char * c, unsigned tb ){
+void EqProof::debug_print( const char * c, unsigned tb ) const{
for( unsigned i=0; i<tb; i++ ) { Debug( c ) << " "; }
Debug( c ) << d_id << "(";
if( !d_children.empty() || !d_node.isNull() ){
diff --git a/src/theory/uf/equality_engine.h b/src/theory/uf/equality_engine.h
index 87074aebc..9cfa16adf 100644
--- a/src/theory/uf/equality_engine.h
+++ b/src/theory/uf/equality_engine.h
@@ -879,8 +879,8 @@ public:
MergeReasonType d_id;
Node d_node;
std::vector< EqProof * > d_children;
- void debug_print( const char * c, unsigned tb = 0 );
-};
+ void debug_print( const char * c, unsigned tb = 0 ) const;
+};/* class EqProof */
} // Namespace eq
} // Namespace theory
diff --git a/src/theory/uf/kinds b/src/theory/uf/kinds
index f0b50b778..888fa140f 100644
--- a/src/theory/uf/kinds
+++ b/src/theory/uf/kinds
@@ -21,6 +21,9 @@ typerule CARDINALITY_CONSTRAINT ::CVC4::theory::uf::CardinalityConstraintTypeRul
operator COMBINED_CARDINALITY_CONSTRAINT 1 "combined cardinality constraint; parameter is a positive integer constant k that bounds the sum of the cardinalities of all sorts in the signature"
typerule COMBINED_CARDINALITY_CONSTRAINT ::CVC4::theory::uf::CombinedCardinalityConstraintTypeRule
+parameterized PARTIAL_APPLY_UF APPLY_UF 1: "partial uninterpreted function application"
+typerule PARTIAL_APPLY_UF ::CVC4::theory::uf::PartialTypeRule
+
operator CARDINALITY_VALUE 1 "cardinality value of sort S: first parameter is (any) term of sort S"
typerule CARDINALITY_VALUE ::CVC4::theory::uf::CardinalityValueTypeRule
diff --git a/src/theory/uf/symmetry_breaker.cpp b/src/theory/uf/symmetry_breaker.cpp
index d5e18ed14..4f7a2667c 100644
--- a/src/theory/uf/symmetry_breaker.cpp
+++ b/src/theory/uf/symmetry_breaker.cpp
@@ -167,7 +167,8 @@ void SymmetryBreaker::Template::reset() {
d_reps.clear();
}
-SymmetryBreaker::SymmetryBreaker(context::Context* context) :
+SymmetryBreaker::SymmetryBreaker(context::Context* context,
+ std::string name) :
ContextNotifyObj(context),
d_assertionsToRerun(context),
d_rerunningAssertions(false),
@@ -178,7 +179,10 @@ SymmetryBreaker::SymmetryBreaker(context::Context* context) :
d_template(),
d_normalizationCache(),
d_termEqs(),
- d_termEqsOnly() {
+ d_termEqsOnly(),
+ d_name(name),
+ d_stats(d_name)
+{
}
class SBGuard {
@@ -461,7 +465,7 @@ void SymmetryBreaker::apply(std::vector<Node>& newClauses) {
Debug("ufsymm") << "UFSYMM =====================================================" << endl
<< "UFSYMM have " << d_permutations.size() << " permutation sets" << endl;
if(!d_permutations.empty()) {
- { TimerStat::CodeTimer codeTimer(d_initNormalizationTimer);
+ { TimerStat::CodeTimer codeTimer(d_stats.d_initNormalizationTimer);
// normalize d_phi
for(vector<Node>::iterator i = d_phi.begin(); i != d_phi.end(); ++i) {
@@ -476,12 +480,12 @@ void SymmetryBreaker::apply(std::vector<Node>& newClauses) {
for(Permutations::iterator i = d_permutations.begin();
i != d_permutations.end();
++i) {
- ++d_permutationSetsConsidered;
+ ++(d_stats.d_permutationSetsConsidered);
const Permutation& p = *i;
Debug("ufsymm") << "UFSYMM looking at permutation: " << p << endl;
size_t n = p.size() - 1;
if(invariantByPermutations(p)) {
- ++d_permutationSetsInvariant;
+ ++(d_stats.d_permutationSetsInvariant);
selectTerms(p);
set<Node> cts;
while(!d_terms.empty() && cts.size() <= n) {
@@ -539,11 +543,11 @@ void SymmetryBreaker::apply(std::vector<Node>& newClauses) {
Node d;
if(disj.getNumChildren() > 1) {
d = disj;
- ++d_clauses;
+ ++(d_stats.d_clauses);
} else {
d = disj[0];
disj.clear();
- ++d_units;
+ ++(d_stats.d_units);
}
if(Debug.isOn("ufsymm")) {
Debug("ufsymm") << "UFSYMM symmetry-breaking clause: " << d << endl;
@@ -569,7 +573,7 @@ void SymmetryBreaker::guessPermutations() {
}
bool SymmetryBreaker::invariantByPermutations(const Permutation& p) {
- TimerStat::CodeTimer codeTimer(d_invariantByPermutationsTimer);
+ TimerStat::CodeTimer codeTimer(d_stats.d_invariantByPermutationsTimer);
// use d_phi
Debug("ufsymm") << "UFSYMM invariantByPermutations()? " << p << endl;
@@ -681,7 +685,7 @@ static bool isSubset(const T1& s, const T2& t) {
}
void SymmetryBreaker::selectTerms(const Permutation& p) {
- TimerStat::CodeTimer codeTimer(d_selectTermsTimer);
+ TimerStat::CodeTimer codeTimer(d_stats.d_selectTermsTimer);
// use d_phi, put into d_terms
Debug("ufsymm") << "UFSYMM selectTerms(): " << p << endl;
@@ -733,6 +737,35 @@ void SymmetryBreaker::selectTerms(const Permutation& p) {
}
}
+SymmetryBreaker::Statistics::Statistics(std::string name)
+ : d_clauses(name + "theory::uf::symmetry_breaker::clauses", 0)
+ , d_units(name + "theory::uf::symmetry_breaker::units", 0)
+ , d_permutationSetsConsidered(name + "theory::uf::symmetry_breaker::permutationSetsConsidered", 0)
+ , d_permutationSetsInvariant(name + "theory::uf::symmetry_breaker::permutationSetsInvariant", 0)
+ , d_invariantByPermutationsTimer(name + "theory::uf::symmetry_breaker::timers::invariantByPermutations")
+ , d_selectTermsTimer(name + "theory::uf::symmetry_breaker::timers::selectTerms")
+ , d_initNormalizationTimer(name + "theory::uf::symmetry_breaker::timers::initNormalization")
+{
+ smtStatisticsRegistry()->registerStat(&d_clauses);
+ smtStatisticsRegistry()->registerStat(&d_units);
+ smtStatisticsRegistry()->registerStat(&d_permutationSetsConsidered);
+ smtStatisticsRegistry()->registerStat(&d_permutationSetsInvariant);
+ smtStatisticsRegistry()->registerStat(&d_invariantByPermutationsTimer);
+ smtStatisticsRegistry()->registerStat(&d_selectTermsTimer);
+ smtStatisticsRegistry()->registerStat(&d_initNormalizationTimer);
+}
+
+SymmetryBreaker::Statistics::~Statistics()
+{
+ smtStatisticsRegistry()->unregisterStat(&d_clauses);
+ smtStatisticsRegistry()->unregisterStat(&d_units);
+ smtStatisticsRegistry()->unregisterStat(&d_permutationSetsConsidered);
+ smtStatisticsRegistry()->unregisterStat(&d_permutationSetsInvariant);
+ smtStatisticsRegistry()->unregisterStat(&d_invariantByPermutationsTimer);
+ smtStatisticsRegistry()->unregisterStat(&d_selectTermsTimer);
+ smtStatisticsRegistry()->unregisterStat(&d_initNormalizationTimer);
+}
+
SymmetryBreaker::Terms::iterator
SymmetryBreaker::selectMostPromisingTerm(Terms& terms) {
// use d_phi
diff --git a/src/theory/uf/symmetry_breaker.h b/src/theory/uf/symmetry_breaker.h
index 763ced650..5523c1c0d 100644
--- a/src/theory/uf/symmetry_breaker.h
+++ b/src/theory/uf/symmetry_breaker.h
@@ -128,35 +128,30 @@ private:
Node normInternal(TNode phi, size_t level);
Node norm(TNode n);
+ std::string d_name;
+
// === STATISTICS ===
/** number of new clauses that come from the SymmetryBreaker */
- KEEP_STATISTIC(IntStat,
- d_clauses,
- "theory::uf::symmetry_breaker::clauses", 0);
- /** number of new clauses that come from the SymmetryBreaker */
- KEEP_STATISTIC(IntStat,
- d_units,
- "theory::uf::symmetry_breaker::units", 0);
- /** number of potential permutation sets we found */
- KEEP_STATISTIC(IntStat,
- d_permutationSetsConsidered,
- "theory::uf::symmetry_breaker::permutationSetsConsidered", 0);
- /** number of invariant permutation sets we found */
- KEEP_STATISTIC(IntStat,
- d_permutationSetsInvariant,
- "theory::uf::symmetry_breaker::permutationSetsInvariant", 0);
- /** time spent in invariantByPermutations() */
- KEEP_STATISTIC(TimerStat,
- d_invariantByPermutationsTimer,
- "theory::uf::symmetry_breaker::timers::invariantByPermutations");
- /** time spent in selectTerms() */
- KEEP_STATISTIC(TimerStat,
- d_selectTermsTimer,
- "theory::uf::symmetry_breaker::timers::selectTerms");
- /** time spent in initial round of normalization */
- KEEP_STATISTIC(TimerStat,
- d_initNormalizationTimer,
- "theory::uf::symmetry_breaker::timers::initNormalization");
+ struct Statistics {
+ /** number of new clauses that come from the SymmetryBreaker */
+ IntStat d_clauses;
+ IntStat d_units;
+ /** number of potential permutation sets we found */
+ IntStat d_permutationSetsConsidered;
+ /** number of invariant permutation sets we found */
+ IntStat d_permutationSetsInvariant;
+ /** time spent in invariantByPermutations() */
+ TimerStat d_invariantByPermutationsTimer;
+ /** time spent in selectTerms() */
+ TimerStat d_selectTermsTimer;
+ /** time spent in initial round of normalization */
+ TimerStat d_initNormalizationTimer;
+
+ Statistics(std::string name);
+ ~Statistics();
+ };
+
+ Statistics d_stats;
protected:
@@ -167,7 +162,7 @@ protected:
public:
- SymmetryBreaker(context::Context* context);
+ SymmetryBreaker(context::Context* context, std::string name = "");
~SymmetryBreaker() throw() {}
void assertFormula(TNode phi);
void apply(std::vector<Node>& newClauses);
diff --git a/src/theory/uf/theory_uf.cpp b/src/theory/uf/theory_uf.cpp
index e21b7ef7d..93a920f82 100644
--- a/src/theory/uf/theory_uf.cpp
+++ b/src/theory/uf/theory_uf.cpp
@@ -20,30 +20,34 @@
#include "options/quantifiers_options.h"
#include "options/smt_options.h"
#include "options/uf_options.h"
+#include "proof/proof_manager.h"
+#include "proof/theory_proof.h"
+#include "proof/uf_proof.h"
#include "theory/theory_model.h"
#include "theory/type_enumerator.h"
#include "theory/uf/theory_uf_strong_solver.h"
using namespace std;
-using namespace CVC4;
-using namespace CVC4::theory;
-using namespace CVC4::theory::uf;
+
+namespace CVC4 {
+namespace theory {
+namespace uf {
/** Constructs a new instance of TheoryUF w.r.t. the provided context.*/
TheoryUF::TheoryUF(context::Context* c, context::UserContext* u,
OutputChannel& out, Valuation valuation,
- const LogicInfo& logicInfo, SmtGlobals* globals)
- : Theory(THEORY_UF, c, u, out, valuation, logicInfo, globals),
+ const LogicInfo& logicInfo, SmtGlobals* globals, std::string name)
+ : Theory(THEORY_UF, c, u, out, valuation, logicInfo, globals, name),
d_notify(*this),
/* The strong theory solver can be notified by EqualityEngine::init(),
* so make sure it's initialized first. */
d_thss(NULL),
- d_equalityEngine(d_notify, c, "theory::uf::TheoryUF", true),
+ d_equalityEngine(d_notify, c, name + "theory::uf::TheoryUF", true),
d_conflict(c, false),
d_literalsToPropagate(c),
d_literalsToPropagateIndex(c, 0),
d_functionsTerms(c),
- d_symb(u)
+ d_symb(u, name)
{
// The kinds we are treating as function application in congruence
d_equalityEngine.addFunctionKind(kind::APPLY_UF);
@@ -204,27 +208,29 @@ Node TheoryUF::getNextDecisionRequest(){
}
}
-void TheoryUF::explain(TNode literal, std::vector<TNode>& assumptions) {
+void TheoryUF::explain(TNode literal, std::vector<TNode>& assumptions, eq::EqProof* pf) {
// Do the work
bool polarity = literal.getKind() != kind::NOT;
TNode atom = polarity ? literal : literal[0];
- eq::EqProof * eqp = d_proofEnabled ? new eq::EqProof : NULL;
if (atom.getKind() == kind::EQUAL || atom.getKind() == kind::IFF) {
- d_equalityEngine.explainEquality(atom[0], atom[1], polarity, assumptions, eqp);
+ d_equalityEngine.explainEquality(atom[0], atom[1], polarity, assumptions, pf);
} else {
- d_equalityEngine.explainPredicate(atom, polarity, assumptions, eqp);
+ d_equalityEngine.explainPredicate(atom, polarity, assumptions, pf);
}
- //for now, just print debug
- //TODO : send the proof outwards : d_out->conflict( lem, eqp );
- if( eqp ){
- eqp->debug_print("uf-pf");
+ if( pf ){
+ Debug("uf-pf") << std::endl;
+ pf->debug_print("uf-pf");
}
}
Node TheoryUF::explain(TNode literal) {
+ return explain(literal, NULL);
+}
+
+Node TheoryUF::explain(TNode literal, eq::EqProof* pf) {
Debug("uf") << "TheoryUF::explain(" << literal << ")" << std::endl;
std::vector<TNode> assumptions;
- explain(literal, assumptions);
+ explain(literal, assumptions, pf);
return mkAnd(assumptions);
}
@@ -508,13 +514,14 @@ void TheoryUF::computeCareGraph() {
}/* TheoryUF::computeCareGraph() */
void TheoryUF::conflict(TNode a, TNode b) {
- //TODO: create EqProof at this level if d_proofEnabled = true
+ eq::EqProof* pf = d_proofsEnabled ? new eq::EqProof() : NULL;
if (a.getKind() == kind::CONST_BOOLEAN) {
- d_conflictNode = explain(a.iffNode(b));
+ d_conflictNode = explain(a.iffNode(b),pf);
} else {
- d_conflictNode = explain(a.eqNode(b));
+ d_conflictNode = explain(a.eqNode(b),pf);
}
- d_out->conflict(d_conflictNode);
+ ProofUF * puf = d_proofsEnabled ? new ProofUF( pf ) : NULL;
+ d_out->conflict(d_conflictNode, puf);
d_conflict = true;
}
@@ -541,3 +548,8 @@ void TheoryUF::eqNotifyDisequal(TNode t1, TNode t2, TNode reason) {
d_thss->assertDisequal(t1, t2, reason);
}
}
+
+
+} /* namespace CVC4::theory::uf */
+} /* namespace CVC4::theory */
+} /* namespace CVC4 */
diff --git a/src/theory/uf/theory_uf.h b/src/theory/uf/theory_uf.h
index aff78f53d..bd0016be7 100644
--- a/src/theory/uf/theory_uf.h
+++ b/src/theory/uf/theory_uf.h
@@ -128,9 +128,15 @@ private:
/**
* Explain why this literal is true by adding assumptions
+ * with proof (if "pf" is non-NULL).
*/
- void explain(TNode literal, std::vector<TNode>& assumptions);
+ void explain(TNode literal, std::vector<TNode>& assumptions, eq::EqProof* pf);
+ /**
+ * Explain a literal, with proof (if "pf" is non-NULL).
+ */
+ Node explain(TNode literal, eq::EqProof* pf);
+
/** Literals to propagate */
context::CDList<Node> d_literalsToPropagate;
@@ -163,7 +169,7 @@ public:
/** Constructs a new instance of TheoryUF w.r.t. the provided context.*/
TheoryUF(context::Context* c, context::UserContext* u, OutputChannel& out,
Valuation valuation, const LogicInfo& logicInfo,
- SmtGlobals* globals);
+ SmtGlobals* globals, std::string name = "");
~TheoryUF();
diff --git a/src/theory/uf/theory_uf_type_rules.h b/src/theory/uf/theory_uf_type_rules.h
index 6faab8517..05b95e9e1 100644
--- a/src/theory/uf/theory_uf_type_rules.h
+++ b/src/theory/uf/theory_uf_type_rules.h
@@ -107,6 +107,14 @@ public:
}
};/* class CardinalityConstraintTypeRule */
+class PartialTypeRule {
+public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
+ throw (TypeCheckingExceptionPrivate, AssertionException) {
+ return n.getOperator().getType().getRangeType();
+ }
+};/* class PartialTypeRule */
+
class CardinalityValueTypeRule {
public:
inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
diff --git a/test/regress/regress0/bv/Makefile.am b/test/regress/regress0/bv/Makefile.am
index fa9ee41a1..d85b3d109 100644
--- a/test/regress/regress0/bv/Makefile.am
+++ b/test/regress/regress0/bv/Makefile.am
@@ -21,6 +21,9 @@ MAKEFLAGS = -k
# If a test shouldn't be run in e.g. competition mode,
# put it below in "TESTS +="
+# FIXME: Proof checking takes too long. Add this back.
+# fuzz15.delta01.smt
+
# Regression tests for SMT inputs
SMT_TESTS = \
fuzz01.smt \
@@ -38,7 +41,6 @@ SMT_TESTS = \
fuzz12.smt \
fuzz13.smt \
fuzz14.smt \
- fuzz15.delta01.smt \
fuzz16.delta01.smt \
fuzz17.delta01.smt \
fuzz18.delta01.smt \
@@ -93,7 +95,8 @@ SMT_TESTS = \
calc2_sec2_shifter_mult_bmc15.atlas.delta01.smt \
smtcompbug.smt \
unsound1.smt2 \
- unsound1-reduced.smt2
+ unsound1-reduced.smt2 \
+ bv-proof00.smt
# Regression tests for SMT2 inputs
SMT2_TESTS = divtest.smt2
diff --git a/test/regress/regress0/bv/bv-proof00.smt b/test/regress/regress0/bv/bv-proof00.smt
new file mode 100644
index 000000000..adfebf58e
--- /dev/null
+++ b/test/regress/regress0/bv/bv-proof00.smt
@@ -0,0 +1,2176 @@
+(benchmark fuzzsmt
+:logic QF_BV
+:status unsat
+:extrafuns ((v0 BitVec[7]))
+:extrafuns ((v1 BitVec[1]))
+:extrafuns ((v2 BitVec[7]))
+:extrafuns ((v3 BitVec[5]))
+:formula
+(let (?e4 bv9[4])
+(let (?e5 bv1[3])
+(let (?e6 bv15[5])
+(let (?e7 (ite (bvuge (sign_extend[2] v3) v2) bv1[1] bv0[1]))
+(let (?e8 (ite (distinct ?e7 v1) bv1[1] bv0[1]))
+(let (?e9 (bvxor (zero_extend[2] ?e6) v2))
+(let (?e10 (bvcomp ?e9 v2))
+(let (?e11 (bvnot ?e6))
+(let (?e12 (bvsub (sign_extend[6] ?e10) v2))
+(let (?e13 (bvneg v3))
+(let (?e14 (extract[0:0] ?e5))
+(let (?e15 (ite (bvugt ?e6 (sign_extend[4] ?e14)) bv1[1] bv0[1]))
+(let (?e16 (bvcomp ?e4 (sign_extend[1] ?e5)))
+(let (?e17 (bvnot ?e5))
+(let (?e18 (ite (= bv1[1] (extract[3:3] v0)) v2 v2))
+(let (?e19 (bvadd (sign_extend[4] ?e5) ?e12))
+(let (?e20 (bvnor (sign_extend[6] ?e15) ?e18))
+(let (?e21 (bvnor v0 (zero_extend[2] ?e11)))
+(let (?e22 (bvadd (zero_extend[4] ?e7) ?e13))
+(let (?e23 (ite (bvslt ?e18 v0) bv1[1] bv0[1]))
+(let (?e24 (zero_extend[0] ?e18))
+(let (?e25 (bvxnor ?e18 v0))
+(let (?e26 (ite (bvsge (zero_extend[6] ?e14) v0) bv1[1] bv0[1]))
+(let (?e27 (bvneg ?e13))
+(let (?e28 (bvxnor ?e13 ?e13))
+(let (?e29 (bvneg ?e12))
+(let (?e30 (zero_extend[3] v1))
+(let (?e31 (ite (bvsgt ?e29 ?e19) bv1[1] bv0[1]))
+(let (?e32 (ite (= bv1[1] (extract[5:5] ?e9)) ?e28 (sign_extend[2] ?e5)))
+(let (?e33 (bvcomp ?e14 ?e31))
+(let (?e34 (repeat[1] ?e25))
+(let (?e35 (ite (distinct ?e34 ?e21) bv1[1] bv0[1]))
+(let (?e36 (bvneg v0))
+(let (?e37 (ite (bvugt (sign_extend[2] ?e13) ?e19) bv1[1] bv0[1]))
+(let (?e38 (ite (distinct (sign_extend[4] ?e17) ?e24) bv1[1] bv0[1]))
+(let (?e39 (bvsub ?e29 (zero_extend[2] ?e13)))
+(let (?e40 (ite (bvule (sign_extend[2] ?e6) ?e21) bv1[1] bv0[1]))
+(let (?e41 (bvneg ?e9))
+(let (?e42 (ite (bvsle ?e29 ?e39) bv1[1] bv0[1]))
+(let (?e43 (bvneg ?e16))
+(let (?e44 (bvand v0 ?e41))
+(let (?e45 (bvnand ?e16 ?e15))
+(let (?e46 (bvand ?e13 (sign_extend[4] ?e43)))
+(let (?e47 (concat ?e31 ?e37))
+(let (?e48 (sign_extend[7] ?e43))
+(let (?e49 (bvnor ?e12 (sign_extend[6] ?e16)))
+(let (?e50 (bvmul v2 (sign_extend[2] ?e22)))
+(let (?e51 (ite (bvugt ?e34 ?e25) bv1[1] bv0[1]))
+(let (?e52 (sign_extend[1] ?e20))
+(let (?e53 (ite (bvslt ?e7 ?e51) bv1[1] bv0[1]))
+(let (?e54 (bvnand (sign_extend[6] ?e53) ?e36))
+(let (?e55 (extract[0:0] ?e43))
+(let (?e56 (bvnor v3 (sign_extend[4] ?e15)))
+(let (?e57 (zero_extend[5] ?e42))
+(let (?e58 (ite (bvult ?e37 ?e40) bv1[1] bv0[1]))
+(let (?e59 (bvashr ?e39 ?e18))
+(let (?e60 (ite (bvuge (zero_extend[4] ?e17) ?e39) bv1[1] bv0[1]))
+(let (?e61 (bvashr (sign_extend[7] ?e38) ?e52))
+(let (?e62 (bvashr (sign_extend[1] v2) ?e52))
+(let (?e63 (ite (= bv1[1] (extract[2:2] v2)) (zero_extend[3] ?e30) ?e25))
+(let (?e64 (ite (bvslt ?e23 ?e51) bv1[1] bv0[1]))
+(let (?e65 (ite (bvsgt ?e41 (sign_extend[6] ?e7)) bv1[1] bv0[1]))
+(let (?e66 (extract[0:0] ?e54))
+(let (?e67 (bvsub (zero_extend[4] ?e5) ?e63))
+(let (?e68 (ite (bvsle ?e33 ?e53) bv1[1] bv0[1]))
+(let (?e69 (bvnor v0 (sign_extend[4] ?e17)))
+(let (?e70 (ite (bvugt (zero_extend[6] v1) ?e67) bv1[1] bv0[1]))
+(let (?e71 (bvor ?e12 ?e49))
+(let (?e72 (ite (bvuge ?e34 (zero_extend[6] ?e16)) bv1[1] bv0[1]))
+(let (?e73 (ite (bvugt ?e63 (zero_extend[2] v3)) bv1[1] bv0[1]))
+(let (?e74 (bvnot v0))
+(let (?e75 (ite (bvsge ?e18 (sign_extend[4] ?e17)) bv1[1] bv0[1]))
+(let (?e76 (bvcomp (sign_extend[5] ?e7) ?e57))
+(let (?e77 (ite (bvsgt (zero_extend[7] ?e66) ?e62) bv1[1] bv0[1]))
+(let (?e78 (concat ?e39 ?e42))
+(let (?e79 (bvnor ?e67 v0))
+(let (?e80 (bvnor ?e32 v3))
+(let (?e81 (ite (= bv1[1] (extract[0:0] ?e5)) ?e57 (sign_extend[5] ?e37)))
+(let (?e82 (rotate_left[1] ?e5))
+(let (?e83 (bvcomp (sign_extend[2] ?e27) ?e69))
+(let (?e84 (bvshl (zero_extend[2] ?e32) ?e41))
+(let (?e85 (bvashr ?e51 ?e68))
+(let (?e86 (bvnand ?e8 ?e76))
+(let (?e87 (ite (bvsge (sign_extend[4] ?e23) ?e27) bv1[1] bv0[1]))
+(let (?e88 (ite (= bv1[1] (extract[0:0] ?e73)) ?e22 (zero_extend[4] ?e35)))
+(let (?e89 (bvnot ?e46))
+(let (?e90 (bvxnor ?e19 (zero_extend[1] ?e81)))
+(let (?e91 (repeat[1] ?e27))
+(let (?e92 (bvneg ?e31))
+(let (?e93 (ite (distinct ?e52 (sign_extend[7] ?e92)) bv1[1] bv0[1]))
+(let (?e94 (bvmul (sign_extend[6] ?e70) ?e90))
+(let (?e95 (bvneg ?e54))
+(let (?e96 (ite (bvsge (zero_extend[4] ?e33) ?e56) bv1[1] bv0[1]))
+(let (?e97 (ite (bvule ?e69 ?e50) bv1[1] bv0[1]))
+(let (?e98 (bvshl (sign_extend[7] ?e70) ?e48))
+(let (?e99 (zero_extend[2] ?e70))
+(let (?e100 (rotate_left[0] ?e17))
+(let (?e101 (ite (= bv1[1] (extract[0:0] ?e70)) ?e95 (zero_extend[2] ?e80)))
+(let (?e102 (ite (bvule (sign_extend[1] ?e100) ?e30) bv1[1] bv0[1]))
+(let (?e103 (bvnor (sign_extend[6] ?e58) ?e71))
+(let (?e104 (bvashr ?e25 (zero_extend[2] ?e11)))
+(let (?e105 (ite (bvule ?e59 ?e63) bv1[1] bv0[1]))
+(let (?e106 (ite (= bv1[1] (extract[1:1] ?e11)) (sign_extend[2] ?e56) ?e9))
+(let (?e107 (bvor ?e90 (zero_extend[6] ?e42)))
+(let (?e108 (bvnot ?e18))
+(let (?e109 (ite (bvult (sign_extend[6] ?e10) ?e41) bv1[1] bv0[1]))
+(let (?e110 (bvxnor (sign_extend[6] ?e86) ?e20))
+(let (?e111 (concat ?e42 ?e105))
+(let (?e112 (ite (bvsle (zero_extend[1] ?e104) ?e98) bv1[1] bv0[1]))
+(let (?e113 (bvashr ?e20 ?e39))
+(let (?e114 (bvnand ?e63 ?e94))
+(let (?e115 (bvxor ?e110 (zero_extend[6] ?e85)))
+(let (?e116 (bvxor (sign_extend[1] ?e12) ?e48))
+(let (?e117 (bvxor (zero_extend[6] ?e77) ?e67))
+(let (?e118 (rotate_right[0] ?e51))
+(let (?e119 (bvnot ?e73))
+(let (?e120 (ite (bvuge ?e89 (sign_extend[4] ?e65)) bv1[1] bv0[1]))
+(let (?e121 (bvashr (sign_extend[6] ?e83) ?e18))
+(let (?e122 (rotate_right[0] ?e68))
+(let (?e123 (rotate_left[0] ?e87))
+(let (?e124 (bvand ?e19 (zero_extend[1] ?e57)))
+(let (?e125 (ite (bvsge (sign_extend[6] ?e93) ?e74) bv1[1] bv0[1]))
+(let (?e126 (bvshl (zero_extend[6] ?e97) ?e103))
+(let (?e127 (bvor ?e29 (sign_extend[6] ?e65)))
+(let (?e128 (bvnor ?e62 (sign_extend[1] ?e24)))
+(let (?e129 (ite (bvult ?e94 (sign_extend[6] ?e76)) bv1[1] bv0[1]))
+(let (?e130 (rotate_right[0] ?e10))
+(let (?e131 (sign_extend[1] ?e71))
+(let (?e132 (ite (bvuge ?e5 (sign_extend[2] ?e66)) bv1[1] bv0[1]))
+(let (?e133 (ite (= ?e55 ?e26) bv1[1] bv0[1]))
+(let (?e134 (ite (bvslt (sign_extend[2] ?e32) ?e127) bv1[1] bv0[1]))
+(let (?e135 (sign_extend[6] ?e102))
+(let (?e136 (bvxnor ?e101 (sign_extend[2] ?e13)))
+(let (?e137 (ite (bvslt (sign_extend[7] ?e83) ?e98) bv1[1] bv0[1]))
+(let (?e138 (ite (bvugt ?e79 ?e67) bv1[1] bv0[1]))
+(let (?e139 (bvsub (zero_extend[6] ?e73) ?e9))
+(let (?e140 (bvxor (zero_extend[6] ?e137) ?e21))
+(let (?e141 (bvnand ?e90 (zero_extend[2] ?e80)))
+(let (?e142 (ite (bvugt ?e90 (zero_extend[6] ?e38)) bv1[1] bv0[1]))
+(let (?e143 (repeat[2] ?e30))
+(let (?e144 (ite (bvuge ?e135 (sign_extend[2] v3)) bv1[1] bv0[1]))
+(let (?e145 (bvxnor (zero_extend[4] ?e82) ?e113))
+(let (?e146 (sign_extend[0] ?e140))
+(let (?e147 (bvmul ?e146 (zero_extend[2] ?e27)))
+(let (?e148 (ite (bvult ?e84 (sign_extend[1] ?e81)) bv1[1] bv0[1]))
+(let (?e149 (bvshl ?e135 (sign_extend[6] ?e26)))
+(let (?e150 (bvmul ?e71 ?e20))
+(let (?e151 (bvshl ?e125 ?e37))
+(let (?e152 (ite (bvult ?e36 (zero_extend[6] ?e53)) bv1[1] bv0[1]))
+(let (?e153 (bvneg ?e106))
+(let (?e154 (ite (bvsgt ?e143 ?e131) bv1[1] bv0[1]))
+(let (?e155 (zero_extend[0] ?e47))
+(let (?e156 (bvadd ?e120 ?e138))
+(let (?e157 (bvxnor ?e138 v1))
+(let (?e158 (rotate_left[0] ?e70))
+(let (?e159 (ite (bvsle ?e30 (zero_extend[3] ?e8)) bv1[1] bv0[1]))
+(let (?e160 (bvnot ?e134))
+(let (?e161 (ite (bvslt ?e71 (zero_extend[6] ?e66)) bv1[1] bv0[1]))
+(let (?e162 (extract[0:0] ?e79))
+(let (?e163 (bvnand (sign_extend[4] ?e137) ?e80))
+(let (?e164 (ite (bvult (sign_extend[6] ?e154) ?e135) bv1[1] bv0[1]))
+(let (?e165 (sign_extend[1] ?e156))
+(let (?e166 (ite (bvugt ?e149 (zero_extend[6] ?e55)) bv1[1] bv0[1]))
+(let (?e167 (ite (= bv1[1] (extract[0:0] ?e164)) (sign_extend[2] ?e31) ?e5))
+(let (?e168 (zero_extend[5] ?e73))
+(let (?e169 (bvand ?e39 (zero_extend[2] ?e13)))
+(let (?e170 (ite (bvsgt (zero_extend[6] ?e66) ?e44) bv1[1] bv0[1]))
+(let (?e171 (ite (bvsle ?e114 (zero_extend[6] ?e26)) bv1[1] bv0[1]))
+(let (?e172 (ite (bvult ?e52 (sign_extend[7] ?e171)) bv1[1] bv0[1]))
+(let (?e173 (ite (bvugt (sign_extend[4] ?e30) ?e78) bv1[1] bv0[1]))
+(let (?e174 (bvadd ?e121 (sign_extend[6] ?e151)))
+(let (?e175 (ite (bvult (sign_extend[6] ?e130) ?e34) bv1[1] bv0[1]))
+(let (?e176 (bvand ?e135 v2))
+(let (?e177 (bvneg ?e152))
+(let (?e178 (ite (distinct ?e42 ?e35) bv1[1] bv0[1]))
+(let (?e179 (bvadd (sign_extend[2] ?e89) ?e39))
+(let (?e180 (bvnor ?e10 ?e118))
+(let (?e181 (ite (bvugt ?e134 ?e148) bv1[1] bv0[1]))
+(let (?e182 (ite (= ?e36 ?e108) bv1[1] bv0[1]))
+(let (?e183 (bvxor v1 ?e86))
+(let (?e184 (bvsub (sign_extend[6] ?e181) ?e59))
+(let (?e185 (bvor (sign_extend[2] ?e33) ?e5))
+(let (?e186 (rotate_right[0] ?e161))
+(let (?e187 (bvcomp ?e29 (zero_extend[6] ?e87)))
+(let (?e188 (bvmul (zero_extend[1] ?e69) ?e62))
+(let (?e189 (bvor ?e150 (zero_extend[6] ?e170)))
+(let (?e190 (repeat[6] ?e26))
+(let (?e191 (bvnot ?e75))
+(let (?e192 (bvnand ?e182 ?e35))
+(let (?e193 (ite (= bv1[1] (extract[0:0] ?e123)) ?e7 ?e73))
+(let (?e194 (bvneg ?e60))
+(let (?e195 (bvshl ?e62 (zero_extend[6] ?e165)))
+(let (?e196 (bvneg ?e95))
+(let (?e197 (bvnot ?e58))
+(let (?e198 (bvneg ?e56))
+(let (?e199 (bvashr ?e170 ?e138))
+(let (?e200 (bvcomp (zero_extend[6] ?e35) ?e139))
+(let (?e201 (sign_extend[0] ?e157))
+(let (?e202 (extract[0:0] ?e7))
+(let (?e203 (ite (bvule ?e18 ?e107) bv1[1] bv0[1]))
+(let (?e204 (bvxor ?e54 ?e150))
+(let (?e205 (bvxor ?e107 ?e114))
+(let (?e206 (ite (bvule ?e62 (zero_extend[1] ?e153)) bv1[1] bv0[1]))
+(let (?e207 (bvneg ?e112))
+(let (?e208 (rotate_left[0] ?e64))
+(let (?e209 (bvcomp (sign_extend[6] ?e122) ?e34))
+(let (?e210 (bvor ?e39 ?e126))
+(let (?e211 (sign_extend[3] ?e96))
+(let (?e212 (bvnor (sign_extend[1] ?e166) ?e47))
+(let (?e213 (rotate_left[0] ?e117))
+(let (?e214 (ite (= (zero_extend[6] ?e199) ?e74) bv1[1] bv0[1]))
+(let (?e215 (concat ?e142 ?e160))
+(let (?e216 (bvor ?e54 (sign_extend[4] ?e17)))
+(let (?e217 (ite (distinct (sign_extend[6] ?e55) ?e41) bv1[1] bv0[1]))
+(let (?e218 (ite (distinct ?e206 ?e203) bv1[1] bv0[1]))
+(let (?e219 (ite (bvsle ?e207 ?e105) bv1[1] bv0[1]))
+(let (?e220 (ite (bvsle ?e139 ?e9) bv1[1] bv0[1]))
+(let (?e221 (bvneg ?e180))
+(let (?e222 (ite (bvslt (sign_extend[5] ?e155) ?e141) bv1[1] bv0[1]))
+(let (?e223 (ite (bvult ?e179 (zero_extend[6] ?e218)) bv1[1] bv0[1]))
+(let (?e224 (ite (bvugt ?e180 ?e83) bv1[1] bv0[1]))
+(let (?e225 (ite (bvsge ?e150 (zero_extend[6] ?e70)) bv1[1] bv0[1]))
+(let (?e226 (repeat[1] ?e15))
+(let (?e227 (bvneg ?e67))
+(let (?e228 (ite (bvuge ?e177 ?e65) bv1[1] bv0[1]))
+(let (?e229 (ite (bvule ?e141 ?e101) bv1[1] bv0[1]))
+(let (?e230 (ite (= ?e140 (sign_extend[6] ?e125)) bv1[1] bv0[1]))
+(let (?e231 (bvor (zero_extend[6] ?e221) ?e104))
+(let (?e232 (zero_extend[1] ?e149))
+(let (?e233 (ite (bvult v0 (zero_extend[6] ?e10)) bv1[1] bv0[1]))
+(let (?e234 (bvadd ?e194 ?e7))
+(let (?e235 (bvmul (sign_extend[6] ?e164) ?e44))
+(let (?e236 (bvnor ?e147 (zero_extend[6] ?e223)))
+(let (?e237 (concat ?e40 ?e184))
+(let (?e238 (bvsub (sign_extend[2] ?e55) ?e167))
+(let (?e239 (ite (bvule (sign_extend[4] ?e138) ?e28) bv1[1] bv0[1]))
+(let (?e240 (bvashr ?e110 (zero_extend[6] ?e180)))
+(let (?e241 (ite (bvslt ?e163 (sign_extend[4] ?e197)) bv1[1] bv0[1]))
+(let (?e242 (bvadd (sign_extend[7] ?e123) ?e131))
+(let (?e243 (bvxor ?e126 (zero_extend[6] ?e83)))
+(let (?e244 (ite (bvuge ?e168 (sign_extend[5] ?e26)) bv1[1] bv0[1]))
+(let (?e245 (ite (distinct ?e143 (zero_extend[1] ?e205)) bv1[1] bv0[1]))
+(let (?e246 (bvsub ?e29 (sign_extend[6] ?e132)))
+(let (?e247 (bvashr ?e24 (sign_extend[6] ?e192)))
+(let (?e248 (bvxnor (zero_extend[6] ?e162) ?e140))
+(let (?e249 (bvnor ?e76 ?e10))
+(let (?e250 (bvnor ?e175 ?e214))
+(let (?e251 (bvnand (zero_extend[6] ?e40) ?e21))
+(let (?e252 (bvsub ?e121 (zero_extend[2] ?e80)))
+(let (?e253 (ite (bvsgt (zero_extend[3] ?e4) ?e139) bv1[1] bv0[1]))
+(flet ($e254 (bvsle ?e82 (zero_extend[2] ?e133)))
+(flet ($e255 (bvult ?e246 (sign_extend[2] ?e11)))
+(flet ($e256 (bvsgt ?e117 ?e94))
+(flet ($e257 (distinct (zero_extend[7] ?e132) ?e52))
+(flet ($e258 (= ?e83 ?e177))
+(flet ($e259 (bvugt ?e115 (sign_extend[6] ?e138)))
+(flet ($e260 (bvsle (zero_extend[6] ?e35) ?e179))
+(flet ($e261 (bvult ?e239 ?e208))
+(flet ($e262 (bvule ?e244 ?e219))
+(flet ($e263 (bvule ?e165 (zero_extend[1] ?e226)))
+(flet ($e264 (distinct ?e81 ?e57))
+(flet ($e265 (bvsgt ?e27 (sign_extend[4] ?e180)))
+(flet ($e266 (bvuge ?e147 (zero_extend[6] ?e76)))
+(flet ($e267 (bvsle ?e114 ?e147))
+(flet ($e268 (bvslt ?e143 (zero_extend[1] ?e141)))
+(flet ($e269 (bvsge (zero_extend[4] ?e4) ?e52))
+(flet ($e270 (bvsge ?e142 ?e223))
+(flet ($e271 (bvule (zero_extend[2] ?e27) ?e205))
+(flet ($e272 (bvult ?e235 (sign_extend[2] ?e56)))
+(flet ($e273 (bvule ?e189 (zero_extend[6] ?e92)))
+(flet ($e274 (bvsge ?e68 ?e42))
+(flet ($e275 (distinct ?e77 ?e228))
+(flet ($e276 (= ?e81 (sign_extend[5] ?e193)))
+(flet ($e277 (bvugt (sign_extend[4] ?e185) ?e117))
+(flet ($e278 (bvult v2 ?e84))
+(flet ($e279 (bvsle (zero_extend[6] ?e239) ?e140))
+(flet ($e280 (= ?e80 (zero_extend[4] ?e217)))
+(flet ($e281 (bvuge (sign_extend[1] ?e12) ?e61))
+(flet ($e282 (bvugt ?e48 (sign_extend[7] ?e7)))
+(flet ($e283 (bvult ?e68 ?e241))
+(flet ($e284 (bvsgt ?e235 (zero_extend[6] ?e203)))
+(flet ($e285 (distinct ?e147 (sign_extend[6] ?e102)))
+(flet ($e286 (= (sign_extend[1] ?e190) ?e174))
+(flet ($e287 (bvslt ?e21 ?e107))
+(flet ($e288 (bvugt ?e201 ?e122))
+(flet ($e289 (bvule (zero_extend[6] ?e92) ?e136))
+(flet ($e290 (bvult (zero_extend[6] ?e137) ?e176))
+(flet ($e291 (= (zero_extend[5] ?e212) ?e24))
+(flet ($e292 (distinct ?e157 ?e225))
+(flet ($e293 (= (sign_extend[5] ?e47) ?e252))
+(flet ($e294 (bvugt ?e50 (zero_extend[6] ?e130)))
+(flet ($e295 (= ?e158 ?e14))
+(flet ($e296 (bvsge (sign_extend[1] ?e138) ?e47))
+(flet ($e297 (bvsgt (sign_extend[3] ?e11) ?e188))
+(flet ($e298 (bvult ?e242 (sign_extend[1] ?e121)))
+(flet ($e299 (bvsge ?e94 ?e74))
+(flet ($e300 (bvsge ?e231 (zero_extend[6] ?e225)))
+(flet ($e301 (bvule (sign_extend[1] ?e152) ?e111))
+(flet ($e302 (bvsgt ?e155 (zero_extend[1] ?e160)))
+(flet ($e303 (distinct ?e140 (sign_extend[4] ?e82)))
+(flet ($e304 (bvugt ?e55 ?e158))
+(flet ($e305 (bvule ?e58 ?e180))
+(flet ($e306 (bvule ?e198 (sign_extend[4] ?e182)))
+(flet ($e307 (= ?e71 ?e36))
+(flet ($e308 (bvsle ?e235 ?e136))
+(flet ($e309 (bvugt ?e90 (sign_extend[6] ?e97)))
+(flet ($e310 (bvslt ?e201 ?e172))
+(flet ($e311 (= ?e6 (zero_extend[4] ?e177)))
+(flet ($e312 (bvslt ?e134 ?e186))
+(flet ($e313 (bvugt ?e205 (zero_extend[6] ?e249)))
+(flet ($e314 (bvsgt (sign_extend[6] ?e70) ?e205))
+(flet ($e315 (bvule ?e17 (zero_extend[2] ?e144)))
+(flet ($e316 (distinct (sign_extend[6] ?e161) v0))
+(flet ($e317 (bvule (zero_extend[6] ?e109) ?e252))
+(flet ($e318 (distinct ?e238 (sign_extend[2] ?e142)))
+(flet ($e319 (bvsgt ?e38 ?e137))
+(flet ($e320 (distinct (zero_extend[4] ?e202) ?e11))
+(flet ($e321 (bvsle ?e5 (sign_extend[2] ?e55)))
+(flet ($e322 (bvugt ?e154 ?e239))
+(flet ($e323 (bvule ?e147 ?e104))
+(flet ($e324 (bvuge ?e213 ?e146))
+(flet ($e325 (bvult ?e108 ?e189))
+(flet ($e326 (distinct ?e50 (sign_extend[6] ?e68)))
+(flet ($e327 (bvsge (zero_extend[1] ?e150) ?e61))
+(flet ($e328 (bvule ?e198 (zero_extend[4] ?e170)))
+(flet ($e329 (bvuge (sign_extend[6] ?e148) ?e79))
+(flet ($e330 (= ?e69 ?e49))
+(flet ($e331 (= (sign_extend[4] ?e167) ?e25))
+(flet ($e332 (distinct ?e190 (sign_extend[1] ?e46)))
+(flet ($e333 (bvsle (sign_extend[6] ?e118) ?e139))
+(flet ($e334 (bvugt ?e117 (sign_extend[6] ?e172)))
+(flet ($e335 (bvugt ?e138 ?e218))
+(flet ($e336 (bvsle ?e176 (zero_extend[6] ?e170)))
+(flet ($e337 (bvule ?e252 (sign_extend[6] ?e138)))
+(flet ($e338 (bvsle ?e194 ?e158))
+(flet ($e339 (bvsle (zero_extend[5] ?e111) ?e25))
+(flet ($e340 (bvslt ?e40 ?e220))
+(flet ($e341 (bvuge ?e79 ?e140))
+(flet ($e342 (bvugt ?e173 ?e72))
+(flet ($e343 (bvslt ?e156 ?e208))
+(flet ($e344 (bvugt ?e196 (zero_extend[6] ?e37)))
+(flet ($e345 (= (zero_extend[4] ?e130) ?e88))
+(flet ($e346 (= ?e41 ?e213))
+(flet ($e347 (bvule (sign_extend[4] ?e93) ?e13))
+(flet ($e348 (distinct ?e204 ?e29))
+(flet ($e349 (bvult (zero_extend[6] ?e165) ?e143))
+(flet ($e350 (bvult (sign_extend[6] ?e72) ?e204))
+(flet ($e351 (bvult ?e118 ?e144))
+(flet ($e352 (bvsle ?e138 ?e138))
+(flet ($e353 (distinct ?e145 ?e113))
+(flet ($e354 (bvugt (sign_extend[6] ?e157) ?e251))
+(flet ($e355 (bvule ?e227 ?e150))
+(flet ($e356 (= ?e25 (sign_extend[6] ?e42)))
+(flet ($e357 (bvsle (zero_extend[1] ?e146) ?e98))
+(flet ($e358 (distinct ?e215 (sign_extend[1] ?e158)))
+(flet ($e359 (= ?e55 ?e133))
+(flet ($e360 (= ?e19 (sign_extend[6] ?e175)))
+(flet ($e361 (distinct ?e125 ?e151))
+(flet ($e362 (bvuge ?e54 ?e24))
+(flet ($e363 (bvuge ?e249 ?e152))
+(flet ($e364 (bvsge (sign_extend[1] ?e190) ?e39))
+(flet ($e365 (bvsgt ?e27 (zero_extend[4] ?e214)))
+(flet ($e366 (= ?e19 (sign_extend[6] ?e73)))
+(flet ($e367 (distinct ?e210 ?e216))
+(flet ($e368 (distinct ?e19 (zero_extend[6] ?e68)))
+(flet ($e369 (bvsle ?e102 ?e51))
+(flet ($e370 (bvugt ?e205 (zero_extend[6] ?e119)))
+(flet ($e371 (bvslt ?e140 (zero_extend[6] ?e133)))
+(flet ($e372 (bvugt ?e91 (sign_extend[4] ?e209)))
+(flet ($e373 (bvslt ?e174 ?e127))
+(flet ($e374 (bvsgt ?e9 (zero_extend[2] ?e13)))
+(flet ($e375 (bvule (sign_extend[4] ?e241) ?e13))
+(flet ($e376 (bvsle (sign_extend[6] ?e160) ?e114))
+(flet ($e377 (distinct ?e236 ?e103))
+(flet ($e378 (bvsle ?e103 (zero_extend[2] ?e28)))
+(flet ($e379 (= (sign_extend[6] ?e96) ?e169))
+(flet ($e380 (bvule ?e68 ?e249))
+(flet ($e381 (bvuge ?e147 (zero_extend[6] ?e156)))
+(flet ($e382 (bvuge ?e187 ?e31))
+(flet ($e383 (bvsgt ?e118 ?e130))
+(flet ($e384 (bvsle (sign_extend[1] ?e165) ?e17))
+(flet ($e385 (bvuge (zero_extend[7] ?e118) ?e48))
+(flet ($e386 (bvult (sign_extend[6] ?e197) ?e124))
+(flet ($e387 (bvsgt ?e211 (zero_extend[3] ?e31)))
+(flet ($e388 (bvslt ?e52 (sign_extend[7] ?e8)))
+(flet ($e389 (bvsle (sign_extend[3] ?e211) ?e49))
+(flet ($e390 (bvsgt (sign_extend[2] ?e151) ?e82))
+(flet ($e391 (bvult ?e23 ?e228))
+(flet ($e392 (bvule (zero_extend[4] ?e17) ?e246))
+(flet ($e393 (bvugt ?e191 ?e191))
+(flet ($e394 (bvult ?e160 ?e92))
+(flet ($e395 (bvuge ?e51 ?e65))
+(flet ($e396 (bvuge (zero_extend[1] ?e190) ?e108))
+(flet ($e397 (bvuge ?e69 (sign_extend[6] ?e65)))
+(flet ($e398 (bvult ?e200 ?e123))
+(flet ($e399 (= (zero_extend[7] ?e76) ?e78))
+(flet ($e400 (bvsgt (zero_extend[2] ?e118) ?e5))
+(flet ($e401 (bvugt (zero_extend[4] ?e82) ?e248))
+(flet ($e402 (bvsle ?e227 ?e127))
+(flet ($e403 (= ?e213 ?e95))
+(flet ($e404 (bvugt ?e54 (zero_extend[6] ?e109)))
+(flet ($e405 (bvsge ?e25 ?e139))
+(flet ($e406 (bvule ?e98 (zero_extend[7] ?e192)))
+(flet ($e407 (bvugt (sign_extend[7] ?e26) ?e98))
+(flet ($e408 (bvsgt ?e140 ?e95))
+(flet ($e409 (bvugt ?e112 ?e221))
+(flet ($e410 (bvugt (sign_extend[2] ?e46) ?e189))
+(flet ($e411 (bvuge (sign_extend[6] ?e142) ?e184))
+(flet ($e412 (bvslt (zero_extend[6] ?e200) ?e63))
+(flet ($e413 (bvsge ?e72 ?e40))
+(flet ($e414 (bvule ?e152 ?e151))
+(flet ($e415 (bvsge ?e59 (zero_extend[2] ?e22)))
+(flet ($e416 (bvsge ?e188 (sign_extend[7] ?e173)))
+(flet ($e417 (bvsgt ?e98 (zero_extend[1] ?e63)))
+(flet ($e418 (bvult ?e29 (zero_extend[2] ?e80)))
+(flet ($e419 (bvsgt ?e59 (zero_extend[6] ?e87)))
+(flet ($e420 (bvuge (sign_extend[2] ?e156) ?e99))
+(flet ($e421 (bvsgt ?e77 ?e118))
+(flet ($e422 (bvugt ?e74 (sign_extend[5] ?e111)))
+(flet ($e423 (bvult ?e180 ?e181))
+(flet ($e424 (bvsle ?e90 (sign_extend[6] ?e148)))
+(flet ($e425 (distinct ?e160 ?e194))
+(flet ($e426 (bvsle ?e184 (sign_extend[6] ?e45)))
+(flet ($e427 (= ?e252 (sign_extend[2] ?e11)))
+(flet ($e428 (bvsge ?e24 (zero_extend[6] ?e134)))
+(flet ($e429 (bvsgt ?e160 ?e206))
+(flet ($e430 (bvugt (zero_extend[2] ?e22) ?e240))
+(flet ($e431 (bvsge ?e95 ?e19))
+(flet ($e432 (bvsge ?e201 ?e87))
+(flet ($e433 (bvsle ?e34 ?e145))
+(flet ($e434 (bvuge ?e117 (zero_extend[6] ?e51)))
+(flet ($e435 (bvule ?e216 ?e145))
+(flet ($e436 (bvslt ?e52 (zero_extend[7] ?e191)))
+(flet ($e437 (bvslt ?e16 ?e129))
+(flet ($e438 (bvsge (zero_extend[7] ?e249) ?e188))
+(flet ($e439 (bvsle ?e138 ?e33))
+(flet ($e440 (distinct ?e103 (sign_extend[6] ?e186)))
+(flet ($e441 (bvuge ?e145 (sign_extend[6] ?e118)))
+(flet ($e442 (bvsgt ?e183 ?e102))
+(flet ($e443 (bvuge (zero_extend[6] ?e233) ?e49))
+(flet ($e444 (= ?e105 ?e160))
+(flet ($e445 (bvsgt ?e145 ?e104))
+(flet ($e446 (bvslt (zero_extend[2] ?e185) ?e32))
+(flet ($e447 (bvugt ?e122 ?e162))
+(flet ($e448 (= (sign_extend[6] ?e156) ?e240))
+(flet ($e449 (bvsge ?e83 ?e197))
+(flet ($e450 (bvsgt ?e89 (zero_extend[4] ?e70)))
+(flet ($e451 (bvsle (zero_extend[6] ?e202) ?e251))
+(flet ($e452 (bvslt ?e203 ?e229))
+(flet ($e453 (bvsge (sign_extend[6] ?e201) ?e63))
+(flet ($e454 (bvslt ?e33 ?e70))
+(flet ($e455 (bvuge ?e119 ?e173))
+(flet ($e456 (distinct ?e205 ?e210))
+(flet ($e457 (bvslt ?e230 ?e38))
+(flet ($e458 (bvsgt ?e45 ?e159))
+(flet ($e459 (bvuge ?e231 ?e115))
+(flet ($e460 (bvslt (sign_extend[5] ?e16) ?e81))
+(flet ($e461 (bvugt (sign_extend[6] ?e15) ?e126))
+(flet ($e462 (bvsgt ?e108 ?e106))
+(flet ($e463 (bvsgt ?e41 ?e252))
+(flet ($e464 (bvsge ?e56 (sign_extend[4] ?e233)))
+(flet ($e465 (bvult ?e76 ?e23))
+(flet ($e466 (bvuge ?e20 ?e126))
+(flet ($e467 (bvslt ?e85 ?e86))
+(flet ($e468 (bvuge ?e11 (zero_extend[4] ?e70)))
+(flet ($e469 (bvsgt (sign_extend[7] ?e87) ?e188))
+(flet ($e470 (bvsge (zero_extend[5] ?e199) ?e190))
+(flet ($e471 (= ?e146 ?e205))
+(flet ($e472 (distinct (sign_extend[4] ?e75) ?e32))
+(flet ($e473 (bvult (zero_extend[6] ?e222) ?e54))
+(flet ($e474 (bvult (zero_extend[6] ?e162) ?e149))
+(flet ($e475 (bvsge ?e50 (sign_extend[4] ?e99)))
+(flet ($e476 (bvult (sign_extend[1] ?e217) ?e165))
+(flet ($e477 (= ?e36 ?e117))
+(flet ($e478 (bvuge ?e80 (zero_extend[4] ?e87)))
+(flet ($e479 (= (sign_extend[6] ?e161) ?e204))
+(flet ($e480 (bvuge ?e227 (sign_extend[2] ?e89)))
+(flet ($e481 (bvslt (zero_extend[5] ?e5) ?e128))
+(flet ($e482 (bvuge (sign_extend[4] ?e99) ?e213))
+(flet ($e483 (bvsle (sign_extend[3] ?e138) ?e4))
+(flet ($e484 (distinct (sign_extend[7] ?e105) ?e195))
+(flet ($e485 (bvult ?e189 (sign_extend[6] ?e65)))
+(flet ($e486 (bvugt (zero_extend[6] ?e66) ?e20))
+(flet ($e487 (bvslt ?e76 ?e26))
+(flet ($e488 (bvsle ?e109 ?e68))
+(flet ($e489 (bvuge ?e56 (zero_extend[4] ?e250)))
+(flet ($e490 (bvule ?e61 (zero_extend[7] ?e156)))
+(flet ($e491 (bvsle (sign_extend[6] ?e144) ?e18))
+(flet ($e492 (bvsle (zero_extend[6] ?e26) ?e139))
+(flet ($e493 (bvslt (zero_extend[4] ?e200) ?e32))
+(flet ($e494 (bvslt (sign_extend[6] ?e218) ?e94))
+(flet ($e495 (bvslt ?e104 (zero_extend[6] ?e239)))
+(flet ($e496 (= (sign_extend[4] ?e211) ?e116))
+(flet ($e497 (distinct (sign_extend[3] ?e97) ?e211))
+(flet ($e498 (= ?e50 ?e210))
+(flet ($e499 (distinct (zero_extend[6] ?e192) ?e205))
+(flet ($e500 (bvsle ?e84 (sign_extend[6] ?e250)))
+(flet ($e501 (bvslt (zero_extend[4] ?e222) ?e13))
+(flet ($e502 (bvule ?e124 (zero_extend[6] ?e112)))
+(flet ($e503 (= ?e8 ?e177))
+(flet ($e504 (bvuge ?e200 ?e158))
+(flet ($e505 (bvugt (zero_extend[6] ?e77) ?e126))
+(flet ($e506 (= ?e148 ?e60))
+(flet ($e507 (bvuge (zero_extend[6] ?e132) ?e121))
+(flet ($e508 (bvule (sign_extend[5] ?e148) ?e81))
+(flet ($e509 (bvsle (sign_extend[5] ?e38) ?e81))
+(flet ($e510 (bvsge (zero_extend[4] ?e238) ?e36))
+(flet ($e511 (bvuge ?e231 (sign_extend[4] ?e99)))
+(flet ($e512 (bvsgt ?e46 (sign_extend[4] ?e225)))
+(flet ($e513 (bvsgt ?e29 (sign_extend[6] ?e245)))
+(flet ($e514 (bvsle ?e116 (zero_extend[7] ?e199)))
+(flet ($e515 (= ?e207 ?e16))
+(flet ($e516 (distinct ?e211 (zero_extend[3] ?e177)))
+(flet ($e517 (bvsgt ?e78 (sign_extend[7] ?e229)))
+(flet ($e518 (bvsge ?e88 (zero_extend[4] ?e119)))
+(flet ($e519 (bvult ?e128 (zero_extend[7] ?e120)))
+(flet ($e520 (bvugt ?e118 ?e225))
+(flet ($e521 (bvuge (sign_extend[6] ?e181) ?e49))
+(flet ($e522 (bvugt ?e115 (zero_extend[6] ?e222)))
+(flet ($e523 (bvult (zero_extend[6] ?e250) ?e94))
+(flet ($e524 (bvsle ?e60 ?e120))
+(flet ($e525 (bvugt ?e146 ?e236))
+(flet ($e526 (distinct ?e16 ?e123))
+(flet ($e527 (bvugt ?e124 ?e248))
+(flet ($e528 (bvult ?e189 ?e29))
+(flet ($e529 (bvult ?e154 ?e118))
+(flet ($e530 (= (sign_extend[7] ?e154) ?e143))
+(flet ($e531 (bvugt (sign_extend[1] ?e34) ?e131))
+(flet ($e532 (bvule ?e115 (zero_extend[6] ?e199)))
+(flet ($e533 (bvuge (zero_extend[6] ?e132) ?e110))
+(flet ($e534 (bvsgt ?e240 ?e227))
+(flet ($e535 (bvsle ?e246 ?e19))
+(flet ($e536 (bvsle ?e55 ?e207))
+(flet ($e537 (bvsge (zero_extend[5] ?e164) ?e190))
+(flet ($e538 (distinct (sign_extend[6] ?e183) ?e71))
+(flet ($e539 (bvslt (zero_extend[7] ?e197) ?e195))
+(flet ($e540 (bvslt ?e14 ?e233))
+(flet ($e541 (bvugt (sign_extend[6] ?e239) ?e44))
+(flet ($e542 (bvugt (sign_extend[6] ?e220) ?e36))
+(flet ($e543 (= ?e41 ?e127))
+(flet ($e544 (bvsle ?e139 ?e127))
+(flet ($e545 (bvsle ?e28 (sign_extend[4] ?e129)))
+(flet ($e546 (bvugt ?e106 ?e18))
+(flet ($e547 (= ?e224 ?e96))
+(flet ($e548 (bvugt ?e237 (zero_extend[7] ?e223)))
+(flet ($e549 (bvslt (zero_extend[6] ?e202) ?e204))
+(flet ($e550 (distinct (sign_extend[1] ?e79) ?e78))
+(flet ($e551 (bvsgt (zero_extend[7] ?e160) ?e78))
+(flet ($e552 (bvsge (sign_extend[7] ?e137) ?e232))
+(flet ($e553 (bvsge (zero_extend[7] ?e193) ?e128))
+(flet ($e554 (bvsge (zero_extend[4] ?e76) ?e22))
+(flet ($e555 (bvsgt (zero_extend[6] ?e96) ?e150))
+(flet ($e556 (bvugt ?e204 (zero_extend[2] ?e89)))
+(flet ($e557 (bvule (zero_extend[6] ?e43) ?e149))
+(flet ($e558 (bvuge ?e59 (zero_extend[4] ?e100)))
+(flet ($e559 (distinct ?e37 ?e37))
+(flet ($e560 (distinct ?e43 ?e233))
+(flet ($e561 (bvsgt ?e220 ?e221))
+(flet ($e562 (bvsge (zero_extend[6] ?e125) ?e126))
+(flet ($e563 (bvslt ?e117 (sign_extend[6] ?e51)))
+(flet ($e564 (bvsge (sign_extend[2] ?e89) ?e149))
+(flet ($e565 (bvsle ?e93 ?e35))
+(flet ($e566 (bvugt ?e127 (zero_extend[6] ?e60)))
+(flet ($e567 (bvule ?e20 (sign_extend[6] ?e218)))
+(flet ($e568 (bvugt (zero_extend[4] ?e100) ?e94))
+(flet ($e569 (bvslt ?e39 (sign_extend[6] ?e73)))
+(flet ($e570 (distinct ?e136 (sign_extend[6] ?e60)))
+(flet ($e571 (distinct ?e230 ?e40))
+(flet ($e572 (bvslt ?e111 (sign_extend[1] ?e93)))
+(flet ($e573 (bvuge v2 ?e54))
+(flet ($e574 (bvsle ?e44 (sign_extend[6] ?e97)))
+(flet ($e575 (distinct ?e226 ?e250))
+(flet ($e576 (bvsgt ?e227 (sign_extend[1] ?e81)))
+(flet ($e577 (bvsge (sign_extend[2] ?e123) ?e17))
+(flet ($e578 (bvsle ?e71 ?e135))
+(flet ($e579 (distinct ?e161 ?e159))
+(flet ($e580 (bvsge (zero_extend[7] ?e226) ?e128))
+(flet ($e581 (= (zero_extend[2] ?e56) ?e19))
+(flet ($e582 (bvuge (zero_extend[6] ?e86) ?e196))
+(flet ($e583 (bvugt (sign_extend[6] ?e181) ?e49))
+(flet ($e584 (bvugt (sign_extend[4] ?e167) ?e141))
+(flet ($e585 (bvule ?e177 ?e175))
+(flet ($e586 (bvsgt (sign_extend[6] ?e155) ?e188))
+(flet ($e587 (bvult (sign_extend[1] ?e72) ?e155))
+(flet ($e588 (distinct ?e114 ?e41))
+(flet ($e589 (bvule ?e153 (sign_extend[6] ?e178)))
+(flet ($e590 (distinct ?e63 ?e54))
+(flet ($e591 (bvslt ?e237 (sign_extend[1] ?e115)))
+(flet ($e592 (bvugt (zero_extend[7] ?e217) ?e116))
+(flet ($e593 (bvule ?e176 ?e21))
+(flet ($e594 (bvugt ?e232 (sign_extend[1] ?e36)))
+(flet ($e595 (= ?e169 (zero_extend[6] ?e226)))
+(flet ($e596 (distinct ?e113 (sign_extend[6] ?e234)))
+(flet ($e597 (bvugt ?e146 ?e39))
+(flet ($e598 (= ?e212 (sign_extend[1] ?e109)))
+(flet ($e599 (distinct ?e173 ?e129))
+(flet ($e600 (distinct ?e175 ?e97))
+(flet ($e601 (bvule ?e107 ?e29))
+(flet ($e602 (bvugt ?e30 (sign_extend[3] ?e93)))
+(flet ($e603 (distinct ?e67 (sign_extend[6] ?e187)))
+(flet ($e604 (bvsle ?e203 ?e249))
+(flet ($e605 (bvult ?e228 ?e119))
+(flet ($e606 (bvugt ?e132 v1))
+(flet ($e607 (bvsge (zero_extend[6] ?e218) ?e117))
+(flet ($e608 (bvsgt ?e227 (sign_extend[6] ?e228)))
+(flet ($e609 (bvuge (sign_extend[6] ?e206) ?e204))
+(flet ($e610 (distinct ?e10 ?e157))
+(flet ($e611 (= ?e221 ?e86))
+(flet ($e612 (bvslt ?e92 ?e245))
+(flet ($e613 (bvule ?e29 (sign_extend[6] ?e180)))
+(flet ($e614 (bvsle ?e45 ?e93))
+(flet ($e615 (= ?e150 (sign_extend[2] ?e22)))
+(flet ($e616 (bvult ?e76 ?e180))
+(flet ($e617 (bvult ?e20 (sign_extend[6] ?e171)))
+(flet ($e618 (bvule ?e141 ?e146))
+(flet ($e619 (= (zero_extend[1] ?e227) ?e242))
+(flet ($e620 (distinct ?e213 ?e114))
+(flet ($e621 (distinct ?e216 (sign_extend[6] ?e160)))
+(flet ($e622 (bvsle ?e9 ?e121))
+(flet ($e623 (distinct (zero_extend[6] ?e229) ?e95))
+(flet ($e624 (bvslt (sign_extend[1] ?e135) ?e78))
+(flet ($e625 (bvslt v3 ?e56))
+(flet ($e626 (bvslt (sign_extend[4] ?e123) ?e89))
+(flet ($e627 (bvule ?e183 ?e92))
+(flet ($e628 (bvslt (zero_extend[4] ?e112) ?e91))
+(flet ($e629 (bvult (sign_extend[6] ?e53) ?e117))
+(flet ($e630 (bvsgt ?e58 ?e249))
+(flet ($e631 (= ?e169 (sign_extend[6] ?e87)))
+(flet ($e632 (= ?e19 ?e103))
+(flet ($e633 (bvsgt ?e82 (zero_extend[2] ?e86)))
+(flet ($e634 (bvslt ?e198 (sign_extend[4] ?e15)))
+(flet ($e635 (bvsle ?e225 ?e193))
+(flet ($e636 (bvsge (sign_extend[2] ?e27) ?e149))
+(flet ($e637 (bvsle ?e91 (sign_extend[4] ?e194)))
+(flet ($e638 (bvugt (sign_extend[6] ?e14) ?e140))
+(flet ($e639 (bvsle ?e132 ?e118))
+(flet ($e640 (bvugt ?e82 (zero_extend[2] ?e85)))
+(flet ($e641 (bvuge (zero_extend[2] ?e163) ?e169))
+(flet ($e642 (bvsge ?e21 (sign_extend[2] ?e32)))
+(flet ($e643 (bvsle ?e232 (sign_extend[1] ?e20)))
+(flet ($e644 (bvslt ?e141 (zero_extend[4] ?e82)))
+(flet ($e645 (bvsle ?e215 (zero_extend[1] ?e134)))
+(flet ($e646 (bvsge ?e130 ?e152))
+(flet ($e647 (bvugt (sign_extend[7] ?e129) ?e98))
+(flet ($e648 (bvsgt ?e59 (zero_extend[6] ?e148)))
+(flet ($e649 (= (zero_extend[7] ?e253) ?e128))
+(flet ($e650 (distinct ?e231 (zero_extend[6] ?e193)))
+(flet ($e651 (bvsle ?e180 ?e31))
+(flet ($e652 (bvuge ?e220 ?e193))
+(flet ($e653 (= ?e110 ?e227))
+(flet ($e654 (bvuge ?e162 ?e186))
+(flet ($e655 (= ?e80 (zero_extend[4] ?e201)))
+(flet ($e656 (= ?e239 ?e220))
+(flet ($e657 (distinct ?e58 ?e233))
+(flet ($e658 (bvsge ?e35 ?e14))
+(flet ($e659 (bvsgt ?e99 (sign_extend[2] ?e159)))
+(flet ($e660 (bvsle (zero_extend[6] ?e43) ?e251))
+(flet ($e661 (= ?e132 ?e45))
+(flet ($e662 (bvugt (zero_extend[6] ?e96) v2))
+(flet ($e663 (bvsgt ?e207 ?e77))
+(flet ($e664 (bvslt (zero_extend[6] ?e109) ?e54))
+(flet ($e665 (bvugt (sign_extend[6] ?e14) ?e136))
+(flet ($e666 (bvsle (sign_extend[6] ?e33) ?e74))
+(flet ($e667 (bvuge (sign_extend[6] ?e64) ?e54))
+(flet ($e668 (bvult (sign_extend[4] ?e172) ?e56))
+(flet ($e669 (bvslt (sign_extend[6] ?e234) ?e149))
+(flet ($e670 (bvule ?e75 ?e250))
+(flet ($e671 (bvugt ?e101 ?e231))
+(flet ($e672 (bvslt (sign_extend[7] ?e186) ?e143))
+(flet ($e673 (= ?e186 ?e187))
+(flet ($e674 (bvsgt ?e106 ?e12))
+(flet ($e675 (bvugt ?e62 (zero_extend[7] ?e166)))
+(flet ($e676 (bvuge ?e210 ?e216))
+(flet ($e677 (bvult ?e144 ?e64))
+(flet ($e678 (distinct ?e240 (sign_extend[6] ?e23)))
+(flet ($e679 (bvsge ?e237 (zero_extend[7] ?e7)))
+(flet ($e680 (distinct (zero_extend[5] ?e134) ?e168))
+(flet ($e681 (= (sign_extend[6] ?e241) ?e235))
+(flet ($e682 (bvslt ?e45 ?e43))
+(flet ($e683 (bvuge ?e193 ?e225))
+(flet ($e684 (bvslt (zero_extend[6] ?e207) ?e174))
+(flet ($e685 (bvugt (sign_extend[6] ?e42) ?e216))
+(flet ($e686 (distinct (sign_extend[6] ?e225) ?e145))
+(flet ($e687 (bvugt ?e144 ?e60))
+(flet ($e688 (bvslt ?e199 ?e10))
+(flet ($e689 (bvsgt ?e81 (zero_extend[5] ?e192)))
+(flet ($e690 (bvsge ?e213 (zero_extend[6] ?e8)))
+(flet ($e691 (= ?e98 ?e78))
+(flet ($e692 (bvuge ?e138 ?e130))
+(flet ($e693 (bvule ?e97 ?e239))
+(flet ($e694 (bvslt (sign_extend[1] ?e190) ?e44))
+(flet ($e695 (bvugt ?e62 (sign_extend[7] ?e193)))
+(flet ($e696 (bvule ?e167 (zero_extend[2] ?e230)))
+(flet ($e697 (bvsge ?e179 ?e69))
+(flet ($e698 (distinct ?e74 ?e84))
+(flet ($e699 (bvugt ?e227 (sign_extend[6] ?e119)))
+(flet ($e700 (= ?e111 (zero_extend[1] ?e85)))
+(flet ($e701 (= ?e133 ?e35))
+(flet ($e702 (bvult ?e217 ?e226))
+(flet ($e703 (bvslt ?e70 ?e160))
+(flet ($e704 (bvslt ?e127 ?e49))
+(flet ($e705 (bvsge ?e116 (zero_extend[2] ?e168)))
+(flet ($e706 (= ?e193 ?e10))
+(flet ($e707 (bvugt ?e216 (zero_extend[6] ?e65)))
+(flet ($e708 (bvugt ?e80 (sign_extend[4] ?e250)))
+(flet ($e709 (bvsle ?e108 (sign_extend[6] ?e55)))
+(flet ($e710 (= ?e13 (zero_extend[4] ?e217)))
+(flet ($e711 (bvugt ?e234 ?e58))
+(flet ($e712 (= ?e127 ?e49))
+(flet ($e713 (bvugt ?e147 (sign_extend[6] ?e83)))
+(flet ($e714 (distinct ?e4 (sign_extend[3] ?e245)))
+(flet ($e715 (bvslt (sign_extend[4] ?e82) ?e149))
+(flet ($e716 (bvult (sign_extend[2] ?e6) ?e240))
+(flet ($e717 (bvsgt ?e128 ?e78))
+(flet ($e718 (bvsge ?e189 (sign_extend[6] ?e134)))
+(flet ($e719 (bvugt ?e14 ?e239))
+(flet ($e720 (bvsgt (zero_extend[5] ?e212) ?e29))
+(flet ($e721 (bvsgt (zero_extend[6] ?e203) ?e106))
+(flet ($e722 (bvsle (sign_extend[6] ?e225) ?e213))
+(flet ($e723 (bvuge (zero_extend[6] ?e171) ?e117))
+(flet ($e724 (bvsge ?e124 ?e251))
+(flet ($e725 (= ?e140 ?e231))
+(flet ($e726 (bvsge ?e89 (zero_extend[4] ?e183)))
+(flet ($e727 (= (sign_extend[4] ?e171) ?e22))
+(flet ($e728 (= ?e94 (zero_extend[2] ?e80)))
+(flet ($e729 (bvsle (zero_extend[6] ?e175) ?e240))
+(flet ($e730 (bvult ?e13 (zero_extend[4] ?e191)))
+(flet ($e731 (bvsgt (sign_extend[2] ?e162) ?e185))
+(flet ($e732 (bvsle (sign_extend[6] ?e250) ?e213))
+(flet ($e733 (bvult ?e53 ?e200))
+(flet ($e734 (bvsle (zero_extend[2] ?e28) ?e101))
+(flet ($e735 (bvslt ?e175 ?e53))
+(flet ($e736 (bvult ?e120 ?e234))
+(flet ($e737 (bvuge ?e116 (sign_extend[7] ?e253)))
+(flet ($e738 (bvsgt ?e116 (sign_extend[7] ?e83)))
+(flet ($e739 (bvugt ?e76 ?e31))
+(flet ($e740 (bvugt (sign_extend[1] ?e193) ?e212))
+(flet ($e741 (bvult (sign_extend[5] ?e111) ?e251))
+(flet ($e742 (bvult (zero_extend[6] ?e191) ?e184))
+(flet ($e743 (= ?e235 (zero_extend[6] ?e156)))
+(flet ($e744 (distinct ?e178 ?e86))
+(flet ($e745 (bvsgt ?e252 (sign_extend[6] ?e77)))
+(flet ($e746 (bvule ?e122 ?e15))
+(flet ($e747 (bvslt ?e21 (sign_extend[6] ?e207)))
+(flet ($e748 (bvult (sign_extend[2] ?e93) ?e82))
+(flet ($e749 (distinct ?e90 ?e115))
+(flet ($e750 (bvugt ?e243 (sign_extend[2] ?e28)))
+(flet ($e751 (bvsgt ?e146 ?e71))
+(flet ($e752 (bvule ?e106 (sign_extend[6] ?e241)))
+(flet ($e753 (distinct ?e88 (sign_extend[4] ?e96)))
+(flet ($e754 (bvsle ?e23 ?e180))
+(flet ($e755 (bvule ?e27 (sign_extend[4] ?e123)))
+(flet ($e756 (= (zero_extend[7] ?e229) ?e61))
+(flet ($e757 (bvuge ?e210 (sign_extend[5] ?e212)))
+(flet ($e758 (bvsge ?e180 ?e96))
+(flet ($e759 (bvsle ?e247 (zero_extend[6] ?e31)))
+(flet ($e760 (bvsle (zero_extend[5] ?e16) ?e168))
+(flet ($e761 (bvsgt ?e138 ?e200))
+(flet ($e762 (bvsgt ?e239 ?e209))
+(flet ($e763 (bvslt ?e197 ?e197))
+(flet ($e764 (bvugt ?e34 ?e29))
+(flet ($e765 (= ?e26 ?e217))
+(flet ($e766 (bvule (zero_extend[6] ?e221) ?e25))
+(flet ($e767 (bvsge ?e189 (zero_extend[5] ?e215)))
+(flet ($e768 (bvult ?e78 (zero_extend[1] ?e67)))
+(flet ($e769 (bvuge (zero_extend[5] ?e215) ?e240))
+(flet ($e770 (= (sign_extend[6] ?e133) ?e235))
+(flet ($e771 (bvsgt ?e27 (zero_extend[4] ?e253)))
+(flet ($e772 (bvsgt ?e18 ?e248))
+(flet ($e773 (bvult ?e78 (sign_extend[7] ?e200)))
+(flet ($e774 (bvult (zero_extend[6] ?e134) ?e251))
+(flet ($e775 (bvule ?e48 (sign_extend[7] ?e68)))
+(flet ($e776 (bvugt ?e6 (zero_extend[4] ?e191)))
+(flet ($e777 (bvult ?e89 (sign_extend[4] ?e162)))
+(flet ($e778 (bvsle ?e39 (sign_extend[6] ?e120)))
+(flet ($e779 (bvule ?e106 (zero_extend[6] ?e194)))
+(flet ($e780 (distinct ?e101 ?e50))
+(flet ($e781 (bvslt ?e91 (sign_extend[4] ?e92)))
+(flet ($e782 (distinct ?e96 ?e16))
+(flet ($e783 (bvugt ?e159 ?e253))
+(flet ($e784 (bvult ?e218 ?e142))
+(flet ($e785 (= (zero_extend[6] ?e133) ?e115))
+(flet ($e786 (bvsgt ?e131 (zero_extend[7] ?e191)))
+(flet ($e787 (bvugt ?e200 ?e87))
+(flet ($e788 (bvugt ?e139 (sign_extend[6] ?e144)))
+(flet ($e789 (bvsgt (zero_extend[1] ?e243) ?e195))
+(flet ($e790 (bvsge ?e71 (sign_extend[2] ?e6)))
+(flet ($e791 (bvule (sign_extend[5] ?e72) ?e168))
+(flet ($e792 (bvsgt ?e21 (sign_extend[6] ?e43)))
+(flet ($e793 (= (zero_extend[1] ?e168) ?e136))
+(flet ($e794 (bvsgt ?e113 ?e153))
+(flet ($e795 (bvult (sign_extend[6] ?e233) ?e251))
+(flet ($e796 (bvugt ?e124 (zero_extend[6] ?e178)))
+(flet ($e797 (distinct ?e242 (zero_extend[1] ?e127)))
+(flet ($e798 (= (sign_extend[4] ?e43) ?e91))
+(flet ($e799 (bvule ?e241 ?e119))
+(flet ($e800 (distinct ?e127 ?e101))
+(flet ($e801 (= (sign_extend[6] ?e197) ?e20))
+(flet ($e802 (bvsgt (sign_extend[6] ?e244) ?e236))
+(flet ($e803 (= ?e61 (zero_extend[1] ?e107)))
+(flet ($e804 (bvsgt ?e227 (sign_extend[3] ?e4)))
+(flet ($e805 (bvuge (sign_extend[1] ?e172) ?e47))
+(flet ($e806 (bvuge ?e201 ?e83))
+(flet ($e807 (bvsge ?e227 ?e196))
+(flet ($e808 (bvsle ?e215 (zero_extend[1] ?e171)))
+(flet ($e809 (bvsgt ?e247 (zero_extend[4] ?e17)))
+(flet ($e810 (bvult ?e62 (sign_extend[7] ?e172)))
+(flet ($e811 (= ?e38 ?e87))
+(flet ($e812 (= ?e58 ?e144))
+(flet ($e813 (bvuge ?e234 ?e40))
+(flet ($e814 (bvsge ?e229 ?e249))
+(flet ($e815 (bvsge ?e134 ?e221))
+(flet ($e816 (bvugt (zero_extend[6] ?e38) ?e34))
+(flet ($e817 (bvsle ?e42 ?e64))
+(flet ($e818 (bvule ?e174 ?e243))
+(flet ($e819 (bvugt ?e115 (sign_extend[6] ?e241)))
+(flet ($e820 (bvslt (zero_extend[2] ?e28) ?e227))
+(flet ($e821 (bvult (sign_extend[6] ?e159) ?e29))
+(flet ($e822 (bvuge ?e62 (sign_extend[7] ?e186)))
+(flet ($e823 (bvult ?e224 ?e253))
+(flet ($e824 (bvule ?e170 ?e55))
+(flet ($e825 (bvsge ?e235 ?e121))
+(flet ($e826 (bvsgt (zero_extend[6] ?e31) ?e126))
+(flet ($e827 (bvslt ?e51 ?e183))
+(flet ($e828 (bvult (zero_extend[4] ?e219) ?e13))
+(flet ($e829 (bvsge ?e108 (zero_extend[6] ?e226)))
+(flet ($e830 (bvslt ?e104 ?e252))
+(flet ($e831 (bvsgt (zero_extend[2] ?e23) ?e5))
+(flet ($e832 (= ?e171 v1))
+(flet ($e833 (bvsgt (sign_extend[6] v1) ?e184))
+(flet ($e834 (distinct ?e192 ?e166))
+(flet ($e835 (distinct ?e110 (zero_extend[6] ?e172)))
+(flet ($e836 (bvugt ?e182 ?e228))
+(flet ($e837 (bvuge ?e28 (sign_extend[4] ?e187)))
+(flet ($e838 (bvsle ?e236 ?e135))
+(flet ($e839 (bvule ?e71 (sign_extend[4] ?e185)))
+(flet ($e840 (bvslt ?e82 (zero_extend[2] ?e148)))
+(flet ($e841 (= (sign_extend[6] ?e249) ?e54))
+(flet ($e842 (bvugt ?e209 ?e93))
+(flet ($e843 (bvuge ?e158 ?e177))
+(flet ($e844 (bvsle (sign_extend[4] ?e96) ?e27))
+(flet ($e845 (distinct ?e219 ?e214))
+(flet ($e846 (bvsge ?e141 (sign_extend[6] ?e161)))
+(flet ($e847 (bvugt ?e62 (zero_extend[7] ?e151)))
+(flet ($e848 (bvule ?e146 (sign_extend[6] ?e55)))
+(flet ($e849 (bvult ?e67 (sign_extend[6] ?e171)))
+(flet ($e850 (bvsle ?e60 ?e209))
+(flet ($e851 (bvugt ?e82 (zero_extend[2] ?e224)))
+(flet ($e852 (bvsgt ?e80 ?e11))
+(flet ($e853 (bvule (zero_extend[6] ?e193) ?e213))
+(flet ($e854 (bvslt ?e158 ?e154))
+(flet ($e855 (distinct (sign_extend[4] ?e167) ?e113))
+(flet ($e856 (bvsle ?e235 (zero_extend[6] ?e160)))
+(flet ($e857 (bvsgt ?e143 (zero_extend[1] ?e139)))
+(flet ($e858 (bvult ?e227 ?e210))
+(flet ($e859 (bvule ?e135 ?e216))
+(flet ($e860 (bvsge (sign_extend[1] ?e106) ?e48))
+(flet ($e861 (= ?e50 (sign_extend[6] ?e137)))
+(flet ($e862 (distinct ?e150 (zero_extend[6] ?e42)))
+(flet ($e863 (bvsge ?e124 (zero_extend[6] ?e23)))
+(flet ($e864 (= ?e194 ?e161))
+(flet ($e865 (bvuge ?e24 (sign_extend[6] ?e214)))
+(flet ($e866 (bvsle (sign_extend[6] ?e92) ?e179))
+(flet ($e867 (bvule ?e141 (sign_extend[6] ?e16)))
+(flet ($e868 (bvule ?e165 (zero_extend[1] ?e199)))
+(flet ($e869 (bvsle (zero_extend[6] ?e105) ?e19))
+(flet ($e870 (bvult ?e233 ?e166))
+(flet ($e871 (bvuge ?e10 ?e183))
+(flet ($e872 (distinct ?e228 ?e206))
+(flet ($e873 (bvult ?e184 (sign_extend[6] ?e33)))
+(flet ($e874 (bvsgt ?e108 (zero_extend[6] ?e51)))
+(flet ($e875 (bvsge ?e53 ?e96))
+(flet ($e876 (distinct (sign_extend[6] v1) ?e71))
+(flet ($e877 (bvslt ?e64 ?e105))
+(flet ($e878 (bvsgt ?e213 (sign_extend[2] ?e32)))
+(flet ($e879 (bvugt (sign_extend[6] v1) ?e69))
+(flet ($e880 (distinct ?e250 ?e225))
+(flet ($e881 (bvsle ?e92 ?e23))
+(flet ($e882 (= (sign_extend[4] ?e161) v3))
+(flet ($e883 (bvslt ?e46 ?e89))
+(flet ($e884 (bvuge (sign_extend[6] ?e23) ?e54))
+(flet ($e885 (bvsle ?e55 ?e60))
+(flet ($e886 (bvsgt ?e197 ?e102))
+(flet ($e887 (bvsle ?e101 ?e41))
+(flet ($e888 (bvule ?e41 (zero_extend[6] ?e138)))
+(flet ($e889 (= (zero_extend[1] ?e205) ?e242))
+(flet ($e890 (distinct ?e24 ?e246))
+(flet ($e891 (bvsge (zero_extend[7] ?e92) ?e131))
+(flet ($e892 (bvule ?e9 (sign_extend[6] ?e109)))
+(flet ($e893 (bvsle (sign_extend[6] ?e182) ?e108))
+(flet ($e894 (bvsge ?e186 ?e166))
+(flet ($e895 (bvuge ?e146 ?e71))
+(flet ($e896 (bvsge ?e121 (sign_extend[6] v1)))
+(flet ($e897 (bvslt (zero_extend[1] ?e69) ?e61))
+(flet ($e898 (bvugt (sign_extend[6] ?e119) ?e44))
+(flet ($e899 (bvsgt (zero_extend[6] ?e154) ?e216))
+(flet ($e900 (bvugt ?e156 ?e202))
+(flet ($e901 (bvugt ?e251 (zero_extend[6] ?e151)))
+(flet ($e902 (bvule ?e235 (zero_extend[6] ?e187)))
+(flet ($e903 (bvslt ?e44 ?e84))
+(flet ($e904 (distinct ?e152 ?e10))
+(flet ($e905 (bvsge (sign_extend[6] ?e142) ?e204))
+(flet ($e906 (bvslt ?e54 (zero_extend[6] ?e16)))
+(flet ($e907 (bvule (zero_extend[2] ?e6) ?e67))
+(flet ($e908 (bvuge ?e43 ?e217))
+(flet ($e909 (bvsgt ?e91 (zero_extend[1] ?e30)))
+(flet ($e910 (bvule ?e167 (zero_extend[2] ?e55)))
+(flet ($e911 (= (zero_extend[2] ?e203) ?e82))
+(flet ($e912 (bvult ?e20 (zero_extend[6] ?e7)))
+(flet ($e913 (bvslt ?e195 (zero_extend[7] ?e42)))
+(flet ($e914 (bvule ?e123 ?e37))
+(flet ($e915 (bvule ?e188 (zero_extend[7] ?e214)))
+(flet ($e916 (bvsgt ?e30 (zero_extend[3] ?e175)))
+(flet ($e917 (= (zero_extend[4] ?e142) ?e88))
+(flet ($e918 (bvsle ?e232 (sign_extend[7] ?e228)))
+(flet ($e919 (distinct ?e136 (sign_extend[6] ?e132)))
+(flet ($e920 (bvuge ?e143 (sign_extend[7] ?e122)))
+(flet ($e921 (bvslt ?e17 (zero_extend[2] ?e42)))
+(flet ($e922 (bvslt ?e116 (zero_extend[7] ?e73)))
+(flet ($e923 (bvsge ?e127 ?e227))
+(flet ($e924 (bvslt (zero_extend[6] ?e180) v0))
+(flet ($e925 (distinct ?e47 (zero_extend[1] ?e226)))
+(flet ($e926 (= ?e69 (zero_extend[6] ?e250)))
+(flet ($e927 (bvult ?e247 ?e29))
+(flet ($e928 (bvuge (sign_extend[5] ?e217) ?e81))
+(flet ($e929 (distinct ?e48 (zero_extend[1] ?e141)))
+(flet ($e930 (bvugt ?e95 (zero_extend[6] ?e217)))
+(flet ($e931 (bvsle ?e246 (zero_extend[6] ?e40)))
+(flet ($e932 (bvslt (sign_extend[2] ?e82) ?e91))
+(flet ($e933 (bvsge ?e238 (sign_extend[2] ?e191)))
+(flet ($e934 (bvuge ?e252 (sign_extend[6] ?e193)))
+(flet ($e935 (bvugt (sign_extend[6] ?e14) ?e216))
+(flet ($e936 (bvsle ?e15 ?e206))
+(flet ($e937 (distinct (sign_extend[1] v2) ?e61))
+(flet ($e938 (bvslt (zero_extend[1] ?e19) ?e232))
+(flet ($e939 (= ?e98 (sign_extend[4] ?e30)))
+(flet ($e940 (bvsgt ?e71 (zero_extend[1] ?e168)))
+(flet ($e941 (bvult (sign_extend[5] ?e155) ?e71))
+(flet ($e942 (bvsle (sign_extend[7] ?e60) ?e232))
+(flet ($e943 (bvsle ?e139 ?e59))
+(flet ($e944 (distinct (sign_extend[6] ?e86) ?e74))
+(flet ($e945 (distinct (sign_extend[6] ?e209) v2))
+(flet ($e946 (bvule (zero_extend[6] ?e122) ?e101))
+(flet ($e947 (bvsgt ?e124 (zero_extend[6] ?e10)))
+(flet ($e948 (bvult ?e48 (zero_extend[3] ?e198)))
+(flet ($e949 (bvule ?e57 (zero_extend[1] ?e56)))
+(flet ($e950 (bvsgt ?e48 (zero_extend[7] ?e250)))
+(flet ($e951 (bvsgt ?e153 (zero_extend[6] ?e162)))
+(flet ($e952 (bvsle ?e138 ?e193))
+(flet ($e953 (bvsgt ?e235 ?e63))
+(flet ($e954 (bvule ?e93 ?e45))
+(flet ($e955 (bvule ?e32 (sign_extend[4] ?e220)))
+(flet ($e956 (bvslt ?e227 ?e149))
+(flet ($e957 (bvule (zero_extend[6] ?e64) ?e252))
+(flet ($e958 (= ?e7 ?e222))
+(flet ($e959 (= ?e118 ?e125))
+(flet ($e960 (bvuge ?e164 ?e157))
+(flet ($e961 (bvsle ?e227 ?e41))
+(flet ($e962 (bvugt ?e188 (zero_extend[7] ?e75)))
+(flet ($e963 (bvugt ?e130 ?e164))
+(flet ($e964 (bvuge ?e244 ?e194))
+(flet ($e965 (bvslt (zero_extend[6] ?e202) ?e189))
+(flet ($e966 (bvslt ?e229 ?e53))
+(flet ($e967 (bvslt ?e185 (sign_extend[2] ?e86)))
+(flet ($e968 (bvuge ?e231 ?e39))
+(flet ($e969 (= ?e26 ?e134))
+(flet ($e970 (bvule (sign_extend[4] ?e211) ?e188))
+(flet ($e971 (bvuge (sign_extend[2] ?e56) ?e114))
+(flet ($e972 (distinct ?e170 ?e209))
+(flet ($e973 (bvule ?e61 (sign_extend[1] ?e110)))
+(flet ($e974 (bvsle ?e218 ?e239))
+(flet ($e975 (bvuge ?e158 ?e37))
+(flet ($e976 (bvsgt ?e206 ?e148))
+(flet ($e977 (distinct ?e18 (zero_extend[6] ?e26)))
+(flet ($e978 (distinct ?e117 (sign_extend[6] ?e239)))
+(flet ($e979 (bvuge ?e82 (zero_extend[2] ?e197)))
+(flet ($e980 (bvsle ?e55 ?e118))
+(flet ($e981 (= ?e181 ?e152))
+(flet ($e982 (bvugt (sign_extend[2] ?e151) ?e99))
+(flet ($e983 (bvult (zero_extend[3] ?e202) ?e4))
+(flet ($e984 (bvugt ?e224 ?e55))
+(flet ($e985 (distinct (sign_extend[6] ?e97) ?e71))
+(flet ($e986 (bvsge ?e108 ?e106))
+(flet ($e987 (bvsle ?e59 (zero_extend[6] ?e222)))
+(flet ($e988 (distinct ?e138 ?e148))
+(flet ($e989 (bvuge (zero_extend[5] ?e155) ?e174))
+(flet ($e990 (bvsle ?e48 (sign_extend[7] ?e175)))
+(flet ($e991 (bvult (zero_extend[2] ?e125) ?e82))
+(flet ($e992 (bvsle ?e141 (zero_extend[6] ?e234)))
+(flet ($e993 (bvsle ?e43 ?e178))
+(flet ($e994 (distinct (sign_extend[7] ?e118) ?e98))
+(flet ($e995 (bvugt ?e9 (sign_extend[1] ?e190)))
+(flet ($e996 (bvult ?e20 ?e104))
+(flet ($e997 (bvsgt (sign_extend[6] ?e60) ?e84))
+(flet ($e998 (bvsgt (zero_extend[6] ?e223) ?e79))
+(flet ($e999 (bvuge ?e41 (sign_extend[2] ?e11)))
+(flet ($e1000 (distinct (zero_extend[6] ?e183) ?e127))
+(flet ($e1001 (bvule ?e135 ?e205))
+(flet ($e1002 (bvule ?e129 ?e142))
+(flet ($e1003 (bvult ?e97 ?e209))
+(flet ($e1004 (distinct (sign_extend[6] ?e199) ?e196))
+(flet ($e1005 (bvsge (sign_extend[1] ?e166) ?e111))
+(flet ($e1006 (= ?e198 (zero_extend[4] ?e134)))
+(flet ($e1007 (bvult (zero_extend[6] ?e129) ?e36))
+(flet ($e1008 (bvsge ?e241 ?e202))
+(flet ($e1009 (bvuge (sign_extend[6] ?e186) ?e106))
+(flet ($e1010 (bvslt ?e118 ?e26))
+(flet ($e1011 (bvult ?e135 ?e115))
+(flet ($e1012 (bvule ?e88 (zero_extend[4] ?e217)))
+(flet ($e1013 (bvsle ?e14 ?e137))
+(flet ($e1014 (distinct (zero_extend[6] ?e223) ?e71))
+(flet ($e1015 (bvsgt (sign_extend[6] ?e166) ?e196))
+(flet ($e1016 (bvule (zero_extend[6] ?e224) ?e127))
+(flet ($e1017 (bvugt ?e21 v0))
+(flet ($e1018 (bvsgt ?e174 (sign_extend[6] ?e220)))
+(flet ($e1019 (bvsge ?e74 (zero_extend[6] ?e105)))
+(flet ($e1020 (bvsge ?e188 (sign_extend[7] ?e66)))
+(flet ($e1021 (bvuge (zero_extend[6] ?e191) ?e115))
+(flet ($e1022 (bvult v3 (zero_extend[4] ?e164)))
+(flet ($e1023 (= ?e225 ?e97))
+(flet ($e1024 (bvult ?e120 ?e224))
+(flet ($e1025 (bvugt (sign_extend[1] ?e236) ?e78))
+(flet ($e1026 (bvule (sign_extend[6] ?e7) ?e136))
+(flet ($e1027 (= ?e147 ?e127))
+(flet ($e1028 (distinct ?e169 (zero_extend[6] ?e85)))
+(flet ($e1029 (bvsle ?e113 (zero_extend[5] ?e165)))
+(flet ($e1030 (bvult (zero_extend[4] ?e185) ?e36))
+(flet ($e1031 (bvuge ?e69 ?e115))
+(flet ($e1032 (= ?e132 ?e233))
+(flet ($e1033 (bvugt ?e45 ?e201))
+(flet ($e1034 (bvult ?e16 ?e10))
+(flet ($e1035 (bvugt ?e175 ?e72))
+(flet ($e1036 (bvuge ?e19 (sign_extend[6] ?e16)))
+(flet ($e1037 (bvule ?e158 ?e173))
+(flet ($e1038 (bvuge (sign_extend[1] ?e93) ?e111))
+(flet ($e1039 (= ?e227 ?e41))
+(flet ($e1040 (bvugt ?e165 (zero_extend[1] ?e130)))
+(flet ($e1041 (bvuge (zero_extend[2] ?e53) ?e99))
+(flet ($e1042 (bvsgt ?e236 (zero_extend[6] ?e53)))
+(flet ($e1043 (bvsle ?e135 ?e110))
+(flet ($e1044 (distinct (sign_extend[2] ?e206) ?e185))
+(flet ($e1045 (bvsgt (sign_extend[6] ?e239) ?e9))
+(flet ($e1046 (bvslt ?e91 (zero_extend[4] ?e160)))
+(flet ($e1047 (bvule ?e171 ?e172))
+(flet ($e1048 (bvsle ?e102 ?e162))
+(flet ($e1049 (bvsle ?e116 (sign_extend[7] ?e10)))
+(flet ($e1050 (bvugt ?e27 (zero_extend[3] ?e165)))
+(flet ($e1051 (= ?e68 ?e214))
+(flet ($e1052 (bvule ?e106 ?e74))
+(flet ($e1053 (bvule ?e217 ?e175))
+(flet ($e1054 (= ?e231 (sign_extend[6] ?e118)))
+(flet ($e1055 (bvsge ?e143 (sign_extend[7] ?e102)))
+(flet ($e1056 (bvult (sign_extend[1] ?e158) ?e215))
+(flet ($e1057 (bvslt (zero_extend[6] ?e87) ?e136))
+(flet ($e1058 (distinct ?e110 ?e25))
+(flet ($e1059 (= ?e155 (sign_extend[1] ?e223)))
+(flet ($e1060 (bvsle ?e242 (zero_extend[7] ?e208)))
+(flet ($e1061 (bvsgt (zero_extend[7] ?e66) ?e128))
+(flet ($e1062 (bvsgt (sign_extend[7] ?e156) ?e48))
+(flet ($e1063 (bvule ?e36 (zero_extend[6] ?e42)))
+(flet ($e1064 (= ?e246 ?e59))
+(flet ($e1065 (bvugt ?e4 (sign_extend[3] ?e33)))
+(flet ($e1066 (bvult ?e26 ?e221))
+(flet ($e1067 (bvuge (sign_extend[6] ?e203) ?e216))
+(flet ($e1068 (bvsle ?e64 ?e244))
+(flet ($e1069 (bvsgt (zero_extend[2] ?e28) ?e49))
+(flet ($e1070 (bvult (sign_extend[6] ?e156) ?e145))
+(flet ($e1071 (bvule (sign_extend[4] ?e53) ?e28))
+(flet ($e1072 (bvsge ?e54 (zero_extend[6] ?e87)))
+(flet ($e1073 (bvslt ?e145 (sign_extend[6] ?e191)))
+(flet ($e1074 (= ?e62 (sign_extend[6] ?e212)))
+(flet ($e1075 (bvslt (sign_extend[4] ?e26) v3))
+(flet ($e1076 (bvsgt ?e136 ?e210))
+(flet ($e1077 (distinct ?e229 ?e68))
+(flet ($e1078 (bvsle (sign_extend[6] ?e249) ?e110))
+(flet ($e1079 (bvule (sign_extend[6] ?e177) ?e59))
+(flet ($e1080 (bvule ?e201 ?e183))
+(flet ($e1081 (bvuge ?e44 (zero_extend[6] ?e122)))
+(flet ($e1082 (bvsge (zero_extend[1] ?e81) ?e117))
+(flet ($e1083 (bvugt (zero_extend[5] ?e239) ?e57))
+(flet ($e1084 (distinct ?e101 (sign_extend[4] ?e5)))
+(flet ($e1085 (bvule (zero_extend[3] ?e212) ?e46))
+(flet ($e1086 (bvslt (sign_extend[6] ?e130) ?e231))
+(flet ($e1087 (bvsgt (zero_extend[6] ?e217) ?e50))
+(flet ($e1088 (bvslt ?e104 v0))
+(flet ($e1089 (bvugt ?e232 (zero_extend[7] ?e87)))
+(flet ($e1090 (bvsge ?e14 ?e132))
+(flet ($e1091 (bvugt (zero_extend[6] ?e214) ?e247))
+(flet ($e1092 (bvult ?e174 (zero_extend[6] ?e66)))
+(flet ($e1093 (bvslt ?e116 (zero_extend[7] ?e233)))
+(flet ($e1094 (bvsle ?e94 (zero_extend[6] ?e31)))
+(flet ($e1095 (bvsge (zero_extend[7] ?e86) ?e52))
+(flet ($e1096 (bvsge (zero_extend[1] v3) ?e168))
+(flet ($e1097 (bvult (zero_extend[6] ?e68) ?e136))
+(flet ($e1098 (bvslt ?e50 (zero_extend[4] ?e82)))
+(flet ($e1099 (bvsge ?e141 ?e126))
+(flet ($e1100 (bvsgt ?e227 (sign_extend[6] ?e180)))
+(flet ($e1101 (bvsle (sign_extend[6] ?e43) ?e12))
+(flet ($e1102 (bvslt ?e178 ?e148))
+(flet ($e1103 (bvuge ?e126 ?e176))
+(flet ($e1104 (distinct (sign_extend[5] ?e230) ?e190))
+(flet ($e1105 (bvslt ?e130 ?e162))
+(flet ($e1106 (bvsgt (sign_extend[7] ?e220) ?e131))
+(flet ($e1107 (bvule ?e205 (zero_extend[2] ?e27)))
+(flet ($e1108 (bvsgt (zero_extend[5] ?e212) ?e94))
+(flet ($e1109 (bvugt ?e198 ?e91))
+(flet ($e1110 (bvuge ?e135 (zero_extend[6] ?e234)))
+(flet ($e1111 (bvuge (zero_extend[3] ?e208) ?e30))
+(flet ($e1112 (bvult ?e179 ?e84))
+(flet ($e1113 (bvsgt (sign_extend[3] ?e28) ?e242))
+(flet ($e1114 (bvugt ?e123 ?e151))
+(flet ($e1115 (bvule ?e20 (zero_extend[6] ?e218)))
+(flet ($e1116 (bvult ?e35 ?e228))
+(flet ($e1117 (bvsgt ?e174 (zero_extend[6] ?e102)))
+(flet ($e1118 (bvule (zero_extend[4] ?e5) ?e24))
+(flet ($e1119 (bvsge ?e206 ?e102))
+(flet ($e1120 (bvsle (zero_extend[5] ?e187) ?e57))
+(flet ($e1121 (bvslt (sign_extend[3] ?e155) v3))
+(flet ($e1122 (bvugt (sign_extend[6] ?e142) ?e12))
+(flet ($e1123 (bvult ?e204 (zero_extend[4] ?e17)))
+(flet ($e1124 (bvule ?e14 ?e220))
+(flet ($e1125 (= ?e18 (zero_extend[6] ?e229)))
+(flet ($e1126 (bvsgt (zero_extend[5] ?e175) ?e168))
+(flet ($e1127 (bvugt ?e184 (zero_extend[6] ?e162)))
+(flet ($e1128 (bvslt (sign_extend[1] ?e166) ?e47))
+(flet ($e1129 (bvslt (zero_extend[6] ?e64) ?e54))
+(flet ($e1130 (bvslt ?e221 ?e186))
+(flet ($e1131 (bvugt (zero_extend[6] ?e133) ?e36))
+(flet ($e1132 (bvslt (sign_extend[6] ?e214) ?e12))
+(flet ($e1133 (bvuge ?e247 (sign_extend[6] ?e42)))
+(flet ($e1134 (bvslt (sign_extend[6] ?e75) v0))
+(flet ($e1135 (bvsgt (zero_extend[5] ?e154) ?e81))
+(flet ($e1136 (bvsle (sign_extend[4] ?e250) ?e46))
+(flet ($e1137 (bvult ?e164 ?e130))
+(flet ($e1138 (distinct (sign_extend[1] ?e57) ?e71))
+(flet ($e1139 (bvsle ?e18 ?e29))
+(flet ($e1140 (bvugt (sign_extend[1] ?e81) ?e140))
+(flet ($e1141 (bvsge ?e21 (sign_extend[6] ?e105)))
+(flet ($e1142 (bvsge (zero_extend[6] ?e138) ?e210))
+(flet ($e1143 (bvsgt ?e141 (zero_extend[2] ?e13)))
+(flet ($e1144 (bvsgt ?e179 (sign_extend[6] ?e102)))
+(flet ($e1145 (bvult (zero_extend[6] ?e51) ?e179))
+(flet ($e1146 (bvslt (sign_extend[6] ?e183) ?e9))
+(flet ($e1147 (bvuge (zero_extend[6] ?e187) ?e136))
+(flet ($e1148 (bvsgt (sign_extend[7] ?e77) ?e131))
+(flet ($e1149 (bvsge (sign_extend[6] ?e26) ?e41))
+(flet ($e1150 (bvuge (zero_extend[4] ?e219) ?e6))
+(flet ($e1151 (bvugt ?e70 ?e87))
+(flet ($e1152 (bvult ?e114 (zero_extend[6] ?e159)))
+(flet ($e1153 (bvsgt ?e216 (zero_extend[6] ?e158)))
+(flet ($e1154 (bvsge ?e41 (zero_extend[2] ?e13)))
+(flet ($e1155 (bvsge (zero_extend[6] ?e218) ?e141))
+(flet ($e1156 (bvsle ?e47 ?e212))
+(flet ($e1157 (bvule ?e104 (zero_extend[6] ?e134)))
+(flet ($e1158 (bvslt ?e33 ?e244))
+(flet ($e1159 (= (sign_extend[3] ?e212) ?e89))
+(flet ($e1160 (bvsgt (sign_extend[6] ?e162) ?e69))
+(flet ($e1161 (bvsge ?e90 (zero_extend[6] ?e234)))
+(flet ($e1162 (bvslt ?e81 (sign_extend[5] ?e245)))
+(flet ($e1163 (= ?e19 ?e25))
+(flet ($e1164 (bvuge ?e25 ?e153))
+(flet ($e1165 (= (zero_extend[6] ?e175) ?e145))
+(flet ($e1166 (bvule ?e139 (zero_extend[6] ?e178)))
+(flet ($e1167 (bvule ?e226 ?e120))
+(flet ($e1168 (bvsgt ?e5 (zero_extend[2] ?e245)))
+(flet ($e1169 (bvsgt ?e195 (zero_extend[7] ?e148)))
+(flet ($e1170 (= ?e114 (sign_extend[6] ?e175)))
+(flet ($e1171 (distinct ?e74 ?e141))
+(flet ($e1172 (bvuge (zero_extend[2] ?e93) ?e238))
+(flet ($e1173 (bvult ?e242 (sign_extend[7] ?e93)))
+(flet ($e1174 (bvslt (sign_extend[2] ?e183) ?e5))
+(flet ($e1175 (bvuge ?e175 ?e151))
+(flet ($e1176 (bvugt ?e32 (zero_extend[4] ?e201)))
+(flet ($e1177 (= ?e55 ?e221))
+(flet ($e1178 (bvugt ?e159 ?e197))
+(flet ($e1179 (bvsgt ?e164 ?e224))
+(flet ($e1180 (bvuge (zero_extend[2] ?e11) ?e49))
+(flet ($e1181 (bvult v0 (zero_extend[6] ?e183)))
+(flet ($e1182 (bvsgt (sign_extend[6] ?e45) ?e18))
+(flet ($e1183 (bvult (sign_extend[6] ?e250) ?e127))
+(flet ($e1184 (bvugt v0 (sign_extend[6] ?e230)))
+(flet ($e1185 (bvule ?e221 ?e96))
+(flet ($e1186 (bvult ?e97 ?e43))
+(flet ($e1187 (bvsge (sign_extend[2] ?e253) ?e185))
+(flet ($e1188 (bvult (sign_extend[6] ?e58) v0))
+(flet ($e1189 (= (zero_extend[6] ?e157) ?e54))
+(flet ($e1190 (bvslt ?e204 ?e74))
+(flet ($e1191 (bvuge ?e70 ?e166))
+(flet ($e1192 (distinct (sign_extend[6] ?e65) ?e140))
+(flet ($e1193 (= (sign_extend[5] ?e35) ?e81))
+(flet ($e1194 (bvule (zero_extend[2] ?e85) ?e17))
+(flet ($e1195 (distinct (sign_extend[1] ?e231) ?e52))
+(flet ($e1196 (bvuge ?e35 ?e8))
+(flet ($e1197 (bvsgt (sign_extend[4] ?e151) ?e91))
+(flet ($e1198 (bvugt ?e10 ?e159))
+(flet ($e1199 (bvult (zero_extend[6] ?e35) ?e21))
+(flet ($e1200 (bvsge ?e56 (sign_extend[4] ?e245)))
+(flet ($e1201 (= (sign_extend[6] ?e102) ?e174))
+(flet ($e1202 (bvule ?e83 ?e77))
+(flet ($e1203 (bvugt (zero_extend[6] ?e97) ?e34))
+(flet ($e1204 (bvsle ?e99 (sign_extend[2] ?e250)))
+(flet ($e1205 (bvslt ?e38 ?e33))
+(flet ($e1206 (distinct ?e242 (zero_extend[7] ?e119)))
+(flet ($e1207 (distinct ?e114 ?e216))
+(flet ($e1208 (bvsge (sign_extend[7] ?e87) ?e52))
+(flet ($e1209 (bvsge (zero_extend[6] ?e96) ?e94))
+(flet ($e1210 (distinct (zero_extend[6] ?e148) ?e25))
+(flet ($e1211 (bvuge ?e245 ?e60))
+(flet ($e1212 (bvslt (sign_extend[6] ?e86) ?e29))
+(flet ($e1213 (bvsle ?e197 ?e40))
+(flet ($e1214 (bvuge ?e32 (sign_extend[4] ?e160)))
+(flet ($e1215 (distinct (zero_extend[7] ?e154) ?e62))
+(flet ($e1216 (bvugt v3 (zero_extend[4] ?e31)))
+(flet ($e1217 (bvugt (sign_extend[2] ?e163) ?e9))
+(flet ($e1218 (not $e570))
+(flet ($e1219 (implies $e343 $e915))
+(flet ($e1220 (iff $e1109 $e928))
+(flet ($e1221 (xor $e318 $e1181))
+(flet ($e1222 (or $e386 $e386))
+(flet ($e1223 (if_then_else $e287 $e479 $e1132))
+(flet ($e1224 (iff $e546 $e1071))
+(flet ($e1225 (xor $e1138 $e640))
+(flet ($e1226 (or $e555 $e522))
+(flet ($e1227 (implies $e269 $e1033))
+(flet ($e1228 (if_then_else $e981 $e606 $e696))
+(flet ($e1229 (not $e796))
+(flet ($e1230 (implies $e332 $e1188))
+(flet ($e1231 (implies $e360 $e576))
+(flet ($e1232 (xor $e440 $e729))
+(flet ($e1233 (not $e540))
+(flet ($e1234 (implies $e1161 $e423))
+(flet ($e1235 (or $e309 $e963))
+(flet ($e1236 (iff $e357 $e602))
+(flet ($e1237 (and $e1108 $e516))
+(flet ($e1238 (implies $e453 $e842))
+(flet ($e1239 (not $e632))
+(flet ($e1240 (xor $e1115 $e272))
+(flet ($e1241 (not $e1153))
+(flet ($e1242 (or $e944 $e1035))
+(flet ($e1243 (iff $e740 $e398))
+(flet ($e1244 (iff $e674 $e652))
+(flet ($e1245 (and $e312 $e741))
+(flet ($e1246 (and $e584 $e1226))
+(flet ($e1247 (not $e715))
+(flet ($e1248 (not $e284))
+(flet ($e1249 (and $e1220 $e472))
+(flet ($e1250 (if_then_else $e388 $e1232 $e636))
+(flet ($e1251 (not $e411))
+(flet ($e1252 (if_then_else $e642 $e975 $e503))
+(flet ($e1253 (and $e1189 $e560))
+(flet ($e1254 (if_then_else $e1125 $e395 $e416))
+(flet ($e1255 (and $e1148 $e477))
+(flet ($e1256 (and $e840 $e488))
+(flet ($e1257 (or $e953 $e1074))
+(flet ($e1258 (xor $e268 $e389))
+(flet ($e1259 (xor $e1019 $e562))
+(flet ($e1260 (xor $e610 $e1195))
+(flet ($e1261 (if_then_else $e533 $e965 $e419))
+(flet ($e1262 (not $e1037))
+(flet ($e1263 (if_then_else $e1219 $e1257 $e649))
+(flet ($e1264 (xor $e836 $e368))
+(flet ($e1265 (implies $e539 $e713))
+(flet ($e1266 (xor $e364 $e710))
+(flet ($e1267 (xor $e671 $e255))
+(flet ($e1268 (and $e1081 $e1158))
+(flet ($e1269 (xor $e960 $e656))
+(flet ($e1270 (and $e918 $e1256))
+(flet ($e1271 (or $e1112 $e431))
+(flet ($e1272 (implies $e254 $e777))
+(flet ($e1273 (xor $e718 $e1116))
+(flet ($e1274 (not $e1000))
+(flet ($e1275 (not $e554))
+(flet ($e1276 (xor $e1090 $e509))
+(flet ($e1277 (implies $e393 $e1180))
+(flet ($e1278 (or $e443 $e489))
+(flet ($e1279 (iff $e280 $e820))
+(flet ($e1280 (not $e1207))
+(flet ($e1281 (not $e1171))
+(flet ($e1282 (if_then_else $e979 $e936 $e392))
+(flet ($e1283 (and $e525 $e899))
+(flet ($e1284 (xor $e947 $e959))
+(flet ($e1285 (xor $e1049 $e638))
+(flet ($e1286 (iff $e531 $e779))
+(flet ($e1287 (implies $e1229 $e912))
+(flet ($e1288 (implies $e946 $e987))
+(flet ($e1289 (if_then_else $e747 $e893 $e856))
+(flet ($e1290 (iff $e801 $e303))
+(flet ($e1291 (or $e1093 $e901))
+(flet ($e1292 (and $e728 $e646))
+(flet ($e1293 (and $e684 $e1099))
+(flet ($e1294 (or $e369 $e484))
+(flet ($e1295 (xor $e621 $e837))
+(flet ($e1296 (xor $e653 $e745))
+(flet ($e1297 (implies $e624 $e1296))
+(flet ($e1298 (xor $e1203 $e882))
+(flet ($e1299 (and $e1022 $e1103))
+(flet ($e1300 (implies $e306 $e524))
+(flet ($e1301 (xor $e1204 $e1227))
+(flet ($e1302 (or $e1216 $e978))
+(flet ($e1303 (implies $e1039 $e816))
+(flet ($e1304 (implies $e1102 $e698))
+(flet ($e1305 (xor $e607 $e945))
+(flet ($e1306 (iff $e1206 $e336))
+(flet ($e1307 (not $e1048))
+(flet ($e1308 (or $e574 $e1014))
+(flet ($e1309 (if_then_else $e870 $e276 $e857))
+(flet ($e1310 (if_then_else $e299 $e1185 $e697))
+(flet ($e1311 (or $e799 $e457))
+(flet ($e1312 (not $e1278))
+(flet ($e1313 (and $e1027 $e449))
+(flet ($e1314 (implies $e337 $e467))
+(flet ($e1315 (xor $e827 $e1058))
+(flet ($e1316 (xor $e1015 $e1222))
+(flet ($e1317 (not $e1178))
+(flet ($e1318 (or $e717 $e790))
+(flet ($e1319 (if_then_else $e473 $e871 $e474))
+(flet ($e1320 (and $e353 $e1133))
+(flet ($e1321 (not $e1287))
+(flet ($e1322 (iff $e1265 $e390))
+(flet ($e1323 (iff $e753 $e427))
+(flet ($e1324 (and $e365 $e660))
+(flet ($e1325 (if_then_else $e275 $e571 $e798))
+(flet ($e1326 (or $e345 $e803))
+(flet ($e1327 (and $e418 $e406))
+(flet ($e1328 (if_then_else $e1079 $e435 $e865))
+(flet ($e1329 (if_then_else $e608 $e685 $e704))
+(flet ($e1330 (xor $e1020 $e352))
+(flet ($e1331 (xor $e828 $e578))
+(flet ($e1332 (xor $e491 $e811))
+(flet ($e1333 (or $e669 $e680))
+(flet ($e1334 (iff $e1191 $e1053))
+(flet ($e1335 (not $e881))
+(flet ($e1336 (iff $e722 $e397))
+(flet ($e1337 (implies $e256 $e672))
+(flet ($e1338 (iff $e916 $e1248))
+(flet ($e1339 (if_then_else $e1122 $e1038 $e785))
+(flet ($e1340 (or $e1302 $e736))
+(flet ($e1341 (and $e512 $e1041))
+(flet ($e1342 (and $e1044 $e377))
+(flet ($e1343 (iff $e744 $e471))
+(flet ($e1344 (not $e1249))
+(flet ($e1345 (and $e405 $e616))
+(flet ($e1346 (iff $e767 $e756))
+(flet ($e1347 (and $e334 $e1241))
+(flet ($e1348 (not $e1131))
+(flet ($e1349 (implies $e623 $e339))
+(flet ($e1350 (xor $e310 $e812))
+(flet ($e1351 (or $e451 $e1314))
+(flet ($e1352 (if_then_else $e1082 $e986 $e600))
+(flet ($e1353 (iff $e663 $e1332))
+(flet ($e1354 (xor $e1344 $e895))
+(flet ($e1355 (iff $e705 $e629))
+(flet ($e1356 (implies $e1340 $e924))
+(flet ($e1357 (or $e1096 $e750))
+(flet ($e1358 (iff $e1231 $e743))
+(flet ($e1359 (iff $e317 $e805))
+(flet ($e1360 (iff $e782 $e373))
+(flet ($e1361 (not $e657))
+(flet ($e1362 (and $e541 $e586))
+(flet ($e1363 (implies $e1043 $e1312))
+(flet ($e1364 (not $e1061))
+(flet ($e1365 (if_then_else $e1168 $e590 $e791))
+(flet ($e1366 (not $e1127))
+(flet ($e1367 (xor $e935 $e943))
+(flet ($e1368 (if_then_else $e844 $e413 $e834))
+(flet ($e1369 (and $e458 $e402))
+(flet ($e1370 (if_then_else $e695 $e407 $e500))
+(flet ($e1371 (not $e832))
+(flet ($e1372 (and $e283 $e1085))
+(flet ($e1373 (or $e483 $e889))
+(flet ($e1374 (if_then_else $e641 $e581 $e1201))
+(flet ($e1375 (and $e282 $e880))
+(flet ($e1376 (xor $e650 $e1008))
+(flet ($e1377 (and $e1311 $e1253))
+(flet ($e1378 (if_then_else $e504 $e367 $e428))
+(flet ($e1379 (if_then_else $e1321 $e949 $e1199))
+(flet ($e1380 (xor $e1007 $e1259))
+(flet ($e1381 (iff $e1130 $e1349))
+(flet ($e1382 (if_then_else $e366 $e267 $e279))
+(flet ($e1383 (not $e838))
+(flet ($e1384 (not $e1087))
+(flet ($e1385 (or $e1380 $e922))
+(flet ($e1386 (implies $e618 $e1172))
+(flet ($e1387 (implies $e1306 $e1331))
+(flet ($e1388 (and $e1239 $e507))
+(flet ($e1389 (not $e931))
+(flet ($e1390 (or $e967 $e1075))
+(flet ($e1391 (or $e934 $e982))
+(flet ($e1392 (if_then_else $e725 $e1165 $e985))
+(flet ($e1393 (xor $e1145 $e464))
+(flet ($e1394 (if_then_else $e295 $e964 $e1293))
+(flet ($e1395 (not $e1062))
+(flet ($e1396 (and $e1264 $e1368))
+(flet ($e1397 (xor $e1258 $e813))
+(flet ($e1398 (not $e690))
+(flet ($e1399 (if_then_else $e1328 $e1078 $e528))
+(flet ($e1400 (iff $e1070 $e742))
+(flet ($e1401 (iff $e911 $e1144))
+(flet ($e1402 (or $e781 $e662))
+(flet ($e1403 (if_then_else $e1101 $e530 $e378))
+(flet ($e1404 (and $e788 $e593))
+(flet ($e1405 (implies $e738 $e1160))
+(flet ($e1406 (if_then_else $e591 $e456 $e439))
+(flet ($e1407 (or $e1313 $e622))
+(flet ($e1408 (xor $e892 $e1362))
+(flet ($e1409 (iff $e1288 $e682))
+(flet ($e1410 (or $e1031 $e321))
+(flet ($e1411 (not $e1281))
+(flet ($e1412 (and $e1263 $e387))
+(flet ($e1413 (or $e939 $e543))
+(flet ($e1414 (xor $e1012 $e886))
+(flet ($e1415 (not $e716))
+(flet ($e1416 (implies $e536 $e385))
+(flet ($e1417 (implies $e775 $e598))
+(flet ($e1418 (if_then_else $e534 $e519 $e454))
+(flet ($e1419 (and $e643 $e826))
+(flet ($e1420 (not $e1001))
+(flet ($e1421 (implies $e647 $e515))
+(flet ($e1422 (not $e1179))
+(flet ($e1423 (or $e1254 $e1234))
+(flet ($e1424 (if_then_else $e877 $e679 $e465))
+(flet ($e1425 (if_then_else $e940 $e1384 $e670))
+(flet ($e1426 (and $e914 $e401))
+(flet ($e1427 (not $e676))
+(flet ($e1428 (xor $e1119 $e764))
+(flet ($e1429 (xor $e634 $e1386))
+(flet ($e1430 (xor $e1324 $e549))
+(flet ($e1431 (implies $e999 $e347))
+(flet ($e1432 (if_then_else $e1426 $e495 $e761))
+(flet ($e1433 (xor $e1367 $e1224))
+(flet ($e1434 (and $e1414 $e1054))
+(flet ($e1435 (iff $e951 $e724))
+(flet ($e1436 (iff $e759 $e637))
+(flet ($e1437 (not $e561))
+(flet ($e1438 (not $e988))
+(flet ($e1439 (if_then_else $e1182 $e1366 $e1334))
+(flet ($e1440 (or $e869 $e448))
+(flet ($e1441 (xor $e375 $e1213))
+(flet ($e1442 (or $e830 $e1403))
+(flet ($e1443 (xor $e1299 $e1104))
+(flet ($e1444 (or $e355 $e383))
+(flet ($e1445 (xor $e1016 $e1357))
+(flet ($e1446 (and $e765 $e1040))
+(flet ($e1447 (or $e1396 $e329))
+(flet ($e1448 (xor $e497 $e1305))
+(flet ($e1449 (or $e731 $e547))
+(flet ($e1450 (if_then_else $e789 $e1301 $e579))
+(flet ($e1451 (iff $e1443 $e969))
+(flet ($e1452 (implies $e260 $e1200))
+(flet ($e1453 (not $e585))
+(flet ($e1454 (iff $e270 $e1294))
+(flet ($e1455 (if_then_else $e604 $e1167 $e308))
+(flet ($e1456 (and $e919 $e766))
+(flet ($e1457 (implies $e362 $e1142))
+(flet ($e1458 (if_then_else $e1450 $e1353 $e1091))
+(flet ($e1459 (not $e1084))
+(flet ($e1460 (xor $e535 $e1032))
+(flet ($e1461 (xor $e1237 $e681))
+(flet ($e1462 (xor $e661 $e1444))
+(flet ($e1463 (if_then_else $e859 $e445 $e1350))
+(flet ($e1464 (iff $e566 $e686))
+(flet ($e1465 (or $e1137 $e1273))
+(flet ($e1466 (xor $e396 $e923))
+(flet ($e1467 (iff $e890 $e437))
+(flet ($e1468 (and $e490 $e475))
+(flet ($e1469 (and $e297 $e1003))
+(flet ($e1470 (not $e1286))
+(flet ($e1471 (if_then_else $e1369 $e552 $e1415))
+(flet ($e1472 (if_then_else $e1373 $e699 $e1266))
+(flet ($e1473 (and $e1361 $e1251))
+(flet ($e1474 (or $e773 $e703))
+(flet ($e1475 (implies $e1410 $e1089))
+(flet ($e1476 (not $e417))
+(flet ($e1477 (if_then_else $e1392 $e330 $e1359))
+(flet ($e1478 (not $e833))
+(flet ($e1479 (xor $e917 $e1151))
+(flet ($e1480 (not $e447))
+(flet ($e1481 (not $e573))
+(flet ($e1482 (or $e301 $e596))
+(flet ($e1483 (implies $e927 $e887))
+(flet ($e1484 (and $e1342 $e867))
+(flet ($e1485 (and $e1280 $e952))
+(flet ($e1486 (implies $e1005 $e537))
+(flet ($e1487 (and $e776 $e1110))
+(flet ($e1488 (and $e442 $e902))
+(flet ($e1489 (and $e1470 $e433))
+(flet ($e1490 (if_then_else $e1069 $e499 $e1050))
+(flet ($e1491 (or $e854 $e1208))
+(flet ($e1492 (xor $e463 $e1437))
+(flet ($e1493 (not $e274))
+(flet ($e1494 (iff $e772 $e861))
+(flet ($e1495 (iff $e1404 $e313))
+(flet ($e1496 (implies $e1230 $e1467))
+(flet ($e1497 (iff $e992 $e817))
+(flet ($e1498 (xor $e1387 $e1047))
+(flet ($e1499 (or $e675 $e292))
+(flet ($e1500 (xor $e974 $e1250))
+(flet ($e1501 (implies $e1067 $e415))
+(flet ($e1502 (implies $e1282 $e627))
+(flet ($e1503 (or $e712 $e1336))
+(flet ($e1504 (if_then_else $e615 $e1445 $e1503))
+(flet ($e1505 (implies $e1135 $e494))
+(flet ($e1506 (xor $e1325 $e529))
+(flet ($e1507 (not $e1430))
+(flet ($e1508 (iff $e1462 $e980))
+(flet ($e1509 (implies $e461 $e1024))
+(flet ($e1510 (xor $e961 $e263))
+(flet ($e1511 (implies $e654 $e1128))
+(flet ($e1512 (xor $e644 $e1491))
+(flet ($e1513 (implies $e1184 $e469))
+(flet ($e1514 (and $e1059 $e391))
+(flet ($e1515 (if_then_else $e1326 $e734 $e719))
+(flet ($e1516 (and $e665 $e932))
+(flet ($e1517 (and $e422 $e1433))
+(flet ($e1518 (if_then_else $e325 $e1120 $e1272))
+(flet ($e1519 (implies $e829 $e1329))
+(flet ($e1520 (xor $e1086 $e1113))
+(flet ($e1521 (not $e701))
+(flet ($e1522 (or $e506 $e614))
+(flet ($e1523 (and $e976 $e1235))
+(flet ($e1524 (implies $e1238 $e814))
+(flet ($e1525 (implies $e408 $e1453))
+(flet ($e1526 (xor $e1522 $e1274))
+(flet ($e1527 (implies $e1341 $e956))
+(flet ($e1528 (xor $e430 $e847))
+(flet ($e1529 (implies $e1358 $e1117))
+(flet ($e1530 (and $e436 $e550))
+(flet ($e1531 (not $e1408))
+(flet ($e1532 (and $e1289 $e1337))
+(flet ($e1533 (xor $e487 $e906))
+(flet ($e1534 (implies $e315 $e1196))
+(flet ($e1535 (if_then_else $e635 $e1401 $e403))
+(flet ($e1536 (if_then_else $e1307 $e1402 $e286))
+(flet ($e1537 (xor $e1330 $e768))
+(flet ($e1538 (or $e1481 $e466))
+(flet ($e1539 (and $e1283 $e290))
+(flet ($e1540 (if_then_else $e333 $e770 $e1255))
+(flet ($e1541 (or $e808 $e800))
+(flet ($e1542 (xor $e806 $e1013))
+(flet ($e1543 (iff $e1379 $e1395))
+(flet ($e1544 (if_then_else $e1492 $e1460 $e958))
+(flet ($e1545 (iff $e692 $e481))
+(flet ($e1546 (iff $e1493 $e346))
+(flet ($e1547 (iff $e1418 $e802))
+(flet ($e1548 (and $e714 $e1532))
+(flet ($e1549 (or $e1215 $e1412))
+(flet ($e1550 (iff $e1487 $e327))
+(flet ($e1551 (and $e1002 $e941))
+(flet ($e1552 (or $e771 $e1405))
+(flet ($e1553 (not $e1194))
+(flet ($e1554 (not $e432))
+(flet ($e1555 (and $e1279 $e264))
+(flet ($e1556 (not $e1500))
+(flet ($e1557 (iff $e1545 $e883))
+(flet ($e1558 (not $e658))
+(flet ($e1559 (iff $e735 $e486))
+(flet ($e1560 (or $e1124 $e977))
+(flet ($e1561 (and $e1246 $e441))
+(flet ($e1562 (not $e1497))
+(flet ($e1563 (and $e1385 $e508))
+(flet ($e1564 (or $e1542 $e1536))
+(flet ($e1565 (if_then_else $e1169 $e774 $e612))
+(flet ($e1566 (if_then_else $e1454 $e314 $e730))
+(flet ($e1567 (xor $e1316 $e930))
+(flet ($e1568 (or $e1042 $e1221))
+(flet ($e1569 (and $e1187 $e720))
+(flet ($e1570 (and $e1440 $e628))
+(flet ($e1571 (if_then_else $e311 $e639 $e1018))
+(flet ($e1572 (if_then_else $e501 $e322 $e950))
+(flet ($e1573 (if_then_else $e1292 $e1017 $e620))
+(flet ($e1574 (if_then_else $e523 $e1088 $e532))
+(flet ($e1575 (implies $e1434 $e1538))
+(flet ($e1576 (not $e783))
+(flet ($e1577 (if_then_else $e1134 $e323 $e860))
+(flet ($e1578 (or $e693 $e594))
+(flet ($e1579 (if_then_else $e380 $e1546 $e973))
+(flet ($e1580 (implies $e444 $e1290))
+(flet ($e1581 (or $e1136 $e1508))
+(flet ($e1582 (iff $e645 $e462))
+(flet ($e1583 (implies $e625 $e762))
+(flet ($e1584 (if_then_else $e575 $e261 $e1198))
+(flet ($e1585 (or $e1557 $e1371))
+(flet ($e1586 (if_then_else $e809 $e909 $e592))
+(flet ($e1587 (iff $e1320 $e1252))
+(flet ($e1588 (implies $e277 $e896))
+(flet ($e1589 (xor $e340 $e687))
+(flet ($e1590 (if_then_else $e319 $e1173 $e913))
+(flet ($e1591 (implies $e1393 $e1461))
+(flet ($e1592 (implies $e1126 $e1092))
+(flet ($e1593 (xor $e298 $e831))
+(flet ($e1594 (not $e1076))
+(flet ($e1595 (xor $e850 $e438))
+(flet ($e1596 (xor $e1511 $e1389))
+(flet ($e1597 (xor $e804 $e737))
+(flet ($e1598 (iff $e1597 $e993))
+(flet ($e1599 (iff $e1343 $e1065))
+(flet ($e1600 (if_then_else $e1319 $e907 $e1559))
+(flet ($e1601 (iff $e631 $e709))
+(flet ($e1602 (if_then_else $e876 $e1190 $e721))
+(flet ($e1603 (implies $e1466 $e700))
+(flet ($e1604 (if_then_else $e822 $e1052 $e1025))
+(flet ($e1605 (xor $e410 $e376))
+(flet ($e1606 (iff $e583 $e746))
+(flet ($e1607 (or $e792 $e1095))
+(flet ($e1608 (if_then_else $e1009 $e707 $e1245))
+(flet ($e1609 (xor $e1267 $e455))
+(flet ($e1610 (iff $e673 $e259))
+(flet ($e1611 (not $e307))
+(flet ($e1612 (not $e1567))
+(flet ($e1613 (not $e1327))
+(flet ($e1614 (iff $e910 $e1428))
+(flet ($e1615 (and $e1217 $e1576))
+(flet ($e1616 (not $e258))
+(flet ($e1617 (iff $e1333 $e1562))
+(flet ($e1618 (not $e1543))
+(flet ($e1619 (not $e1479))
+(flet ($e1620 (iff $e1504 $e1399))
+(flet ($e1621 (xor $e835 $e1614))
+(flet ($e1622 (if_then_else $e1262 $e302 $e1247))
+(flet ($e1623 (xor $e1519 $e1583))
+(flet ($e1624 (iff $e450 $e1591))
+(flet ($e1625 (and $e399 $e412))
+(flet ($e1626 (not $e968))
+(flet ($e1627 (implies $e601 $e1464))
+(flet ($e1628 (or $e1377 $e1394))
+(flet ($e1629 (or $e1442 $e1147))
+(flet ($e1630 (not $e900))
+(flet ($e1631 (not $e884))
+(flet ($e1632 (not $e1587))
+(flet ($e1633 (or $e1534 $e502))
+(flet ($e1634 (implies $e1080 $e1620))
+(flet ($e1635 (if_then_else $e1550 $e1495 $e485))
+(flet ($e1636 (not $e358))
+(flet ($e1637 (or $e1554 $e1607))
+(flet ($e1638 (not $e1525))
+(flet ($e1639 (xor $e818 $e1436))
+(flet ($e1640 (or $e891 $e1605))
+(flet ($e1641 (xor $e1588 $e1465))
+(flet ($e1642 (not $e288))
+(flet ($e1643 (implies $e824 $e459))
+(flet ($e1644 (if_then_else $e404 $e879 $e1458))
+(flet ($e1645 (not $e1594))
+(flet ($e1646 (implies $e1291 $e513))
+(flet ($e1647 (iff $e1139 $e688))
+(flet ($e1648 (and $e1612 $e1193))
+(flet ($e1649 (implies $e1212 $e300))
+(flet ($e1650 (and $e424 $e858))
+(flet ($e1651 (not $e1593))
+(flet ($e1652 (implies $e1177 $e1480))
+(flet ($e1653 (and $e421 $e1407))
+(flet ($e1654 (xor $e1526 $e429))
+(flet ($e1655 (not $e1372))
+(flet ($e1656 (or $e1154 $e1322))
+(flet ($e1657 (xor $e1129 $e648))
+(flet ($e1658 (and $e553 $e1556))
+(flet ($e1659 (and $e1261 $e825))
+(flet ($e1660 (implies $e1308 $e666))
+(flet ($e1661 (if_then_else $e1610 $e784 $e493))
+(flet ($e1662 (iff $e470 $e897))
+(flet ($e1663 (and $e1218 $e1449))
+(flet ($e1664 (and $e1164 $e551))
+(flet ($e1665 (and $e1627 $e1244))
+(flet ($e1666 (iff $e1570 $e1516))
+(flet ($e1667 (xor $e1575 $e1174))
+(flet ($e1668 (implies $e1236 $e1309))
+(flet ($e1669 (not $e1658))
+(flet ($e1670 (if_then_else $e933 $e400 $e855))
+(flet ($e1671 (implies $e587 $e1537))
+(flet ($e1672 (if_then_else $e1030 $e1323 $e492))
+(flet ($e1673 (or $e1530 $e864))
+(flet ($e1674 (xor $e1060 $e874))
+(flet ($e1675 (xor $e1448 $e755))
+(flet ($e1676 (or $e1529 $e1586))
+(flet ($e1677 (implies $e1565 $e1675))
+(flet ($e1678 (and $e655 $e1417))
+(flet ($e1679 (iff $e281 $e1636))
+(flet ($e1680 (if_then_else $e1622 $e667 $e1618))
+(flet ($e1681 (not $e1513))
+(flet ($e1682 (xor $e925 $e350))
+(flet ($e1683 (not $e1469))
+(flet ($e1684 (or $e1370 $e971))
+(flet ($e1685 (implies $e733 $e1240))
+(flet ($e1686 (if_then_else $e599 $e955 $e296))
+(flet ($e1687 (iff $e1064 $e848))
+(flet ($e1688 (iff $e538 $e1637))
+(flet ($e1689 (or $e1411 $e1411))
+(flet ($e1690 (and $e1625 $e1100))
+(flet ($e1691 (xor $e1004 $e966))
+(flet ($e1692 (xor $e678 $e1652))
+(flet ($e1693 (or $e556 $e348))
+(flet ($e1694 (implies $e1360 $e1685))
+(flet ($e1695 (if_then_else $e1400 $e595 $e1564))
+(flet ($e1696 (iff $e468 $e1572))
+(flet ($e1697 (implies $e1315 $e460))
+(flet ($e1698 (iff $e521 $e316))
+(flet ($e1699 (xor $e1468 $e1592))
+(flet ($e1700 (iff $e1143 $e569))
+(flet ($e1701 (or $e823 $e1383))
+(flet ($e1702 (or $e995 $e1317))
+(flet ($e1703 (implies $e984 $e285))
+(flet ($e1704 (if_then_else $e1429 $e335 $e1141))
+(flet ($e1705 (not $e1549))
+(flet ($e1706 (not $e1640))
+(flet ($e1707 (xor $e1140 $e1435))
+(flet ($e1708 (not $e597))
+(flet ($e1709 (xor $e1621 $e1505))
+(flet ($e1710 (and $e1021 $e331))
+(flet ($e1711 (and $e1375 $e1056))
+(flet ($e1712 (and $e1023 $e1555))
+(flet ($e1713 (xor $e510 $e1531))
+(flet ($e1714 (not $e434))
+(flet ($e1715 (or $e1528 $e1077))
+(flet ($e1716 (and $e1676 $e1228))
+(flet ($e1717 (xor $e1496 $e603))
+(flet ($e1718 (iff $e1552 $e1541))
+(flet ($e1719 (if_then_else $e1527 $e557 $e1558))
+(flet ($e1720 (if_then_else $e1310 $e1600 $e994))
+(flet ($e1721 (or $e548 $e1391))
+(flet ($e1722 (and $e1684 $e787))
+(flet ($e1723 (iff $e1441 $e1582))
+(flet ($e1724 (not $e452))
+(flet ($e1725 (if_then_else $e359 $e278 $e1233))
+(flet ($e1726 (not $e749))
+(flet ($e1727 (xor $e1608 $e293))
+(flet ($e1728 (if_then_else $e1431 $e1205 $e514))
+(flet ($e1729 (xor $e1284 $e1716))
+(flet ($e1730 (not $e1721))
+(flet ($e1731 (or $e1714 $e1566))
+(flet ($e1732 (if_then_else $e1339 $e1682 $e1668))
+(flet ($e1733 (implies $e1390 $e381))
+(flet ($e1734 (implies $e1553 $e1374))
+(flet ($e1735 (or $e1705 $e1494))
+(flet ($e1736 (or $e1197 $e903))
+(flet ($e1737 (if_then_else $e875 $e1735 $e1482))
+(flet ($e1738 (or $e1506 $e1709))
+(flet ($e1739 (xor $e372 $e1698))
+(flet ($e1740 (not $e1691))
+(flet ($e1741 (if_then_else $e863 $e589 $e1298))
+(flet ($e1742 (if_then_else $e1540 $e1712 $e1560))
+(flet ($e1743 (implies $e1351 $e1724))
+(flet ($e1744 (if_then_else $e1738 $e819 $e1717))
+(flet ($e1745 (and $e1661 $e1509))
+(flet ($e1746 (or $e1711 $e505))
+(flet ($e1747 (if_then_else $e1548 $e265 $e257))
+(flet ($e1748 (or $e1746 $e1303))
+(flet ($e1749 (implies $e341 $e425))
+(flet ($e1750 (xor $e1577 $e1518))
+(flet ($e1751 (xor $e1269 $e1424))
+(flet ($e1752 (and $e1679 $e1363))
+(flet ($e1753 (implies $e1463 $e1271))
+(flet ($e1754 (xor $e1681 $e1159))
+(flet ($e1755 (if_then_else $e1670 $e852 $e1388))
+(flet ($e1756 (if_then_else $e795 $e1729 $e1146))
+(flet ($e1757 (not $e1423))
+(flet ($e1758 (and $e304 $e266))
+(flet ($e1759 (if_then_else $e1209 $e1632 $e1590))
+(flet ($e1760 (not $e1149))
+(flet ($e1761 (or $e780 $e1474))
+(flet ($e1762 (or $e1118 $e605))
+(flet ($e1763 (and $e1006 $e841))
+(flet ($e1764 (if_then_else $e1631 $e1581 $e1121))
+(flet ($e1765 (iff $e1150 $e1764))
+(flet ($e1766 (xor $e356 $e1753))
+(flet ($e1767 (if_then_else $e558 $e1364 $e1688))
+(flet ($e1768 (iff $e1097 $e1285))
+(flet ($e1769 (implies $e1606 $e1107))
+(flet ($e1770 (implies $e962 $e1690))
+(flet ($e1771 (and $e1707 $e545))
+(flet ($e1772 (not $e1485))
+(flet ($e1773 (and $e1381 $e1745))
+(flet ($e1774 (or $e1499 $e1752))
+(flet ($e1775 (implies $e1769 $e1268))
+(flet ($e1776 (and $e511 $e1276))
+(flet ($e1777 (and $e559 $e1578))
+(flet ($e1778 (xor $e1447 $e908))
+(flet ($e1779 (implies $e1352 $e972))
+(flet ($e1780 (if_then_else $e426 $e1520 $e1657))
+(flet ($e1781 (xor $e1699 $e1378))
+(flet ($e1782 (implies $e991 $e1662))
+(flet ($e1783 (or $e328 $e1775))
+(flet ($e1784 (or $e894 $e1446))
+(flet ($e1785 (iff $e1297 $e794))
+(flet ($e1786 (or $e1782 $e996))
+(flet ($e1787 (if_then_else $e1175 $e989 $e1783))
+(flet ($e1788 (xor $e294 $e1098))
+(flet ($e1789 (iff $e1629 $e1397))
+(flet ($e1790 (iff $e727 $e1626))
+(flet ($e1791 (or $e626 $e942))
+(flet ($e1792 (if_then_else $e990 $e1166 $e1028))
+(flet ($e1793 (and $e619 $e1398))
+(flet ($e1794 (iff $e1478 $e1515))
+(flet ($e1795 (and $e1596 $e1210))
+(flet ($e1796 (implies $e723 $e1768))
+(flet ($e1797 (implies $e1571 $e1490))
+(flet ($e1798 (if_then_else $e1521 $e1335 $e1643))
+(flet ($e1799 (iff $e1539 $e1451))
+(flet ($e1800 (implies $e1740 $e1762))
+(flet ($e1801 (iff $e1687 $e1152))
+(flet ($e1802 (and $e1354 $e1653))
+(flet ($e1803 (xor $e446 $e1585))
+(flet ($e1804 (iff $e394 $e1766))
+(flet ($e1805 (iff $e1801 $e846))
+(flet ($e1806 (implies $e1105 $e588))
+(flet ($e1807 (and $e1318 $e1045))
+(flet ($e1808 (or $e1771 $e1700))
+(flet ($e1809 (xor $e1476 $e1073))
+(flet ($e1810 (iff $e810 $e1727))
+(flet ($e1811 (iff $e1780 $e609))
+(flet ($e1812 (iff $e1438 $e1456))
+(flet ($e1813 (iff $e1533 $e1800))
+(flet ($e1814 (iff $e659 $e1595))
+(flet ($e1815 (implies $e1489 $e1654))
+(flet ($e1816 (implies $e1427 $e1755))
+(flet ($e1817 (if_then_else $e1615 $e1733 $e1811))
+(flet ($e1818 (or $e1066 $e1817))
+(flet ($e1819 (implies $e1584 $e1694))
+(flet ($e1820 (implies $e544 $e1759))
+(flet ($e1821 (xor $e1225 $e1345))
+(flet ($e1822 (and $e633 $e1544))
+(flet ($e1823 (iff $e1162 $e1680))
+(flet ($e1824 (if_then_else $e1416 $e754 $e1214))
+(flet ($e1825 (xor $e1779 $e815))
+(flet ($e1826 (if_then_else $e1765 $e1807 $e1517))
+(flet ($e1827 (implies $e1692 $e305))
+(flet ($e1828 (and $e1677 $e683))
+(flet ($e1829 (and $e1270 $e1589))
+(flet ($e1830 (implies $e920 $e711))
+(flet ($e1831 (iff $e542 $e898))
+(flet ($e1832 (or $e527 $e324))
+(flet ($e1833 (implies $e1823 $e878))
+(flet ($e1834 (iff $e518 $e568))
+(flet ($e1835 (implies $e1659 $e1617))
+(flet ($e1836 (and $e326 $e496))
+(flet ($e1837 (and $e617 $e1649))
+(flet ($e1838 (xor $e1641 $e853))
+(flet ($e1839 (not $e1580))
+(flet ($e1840 (iff $e1835 $e763))
+(flet ($e1841 (implies $e1211 $e1072))
+(flet ($e1842 (xor $e1106 $e409))
+(flet ($e1843 (and $e1439 $e1704))
+(flet ($e1844 (xor $e1192 $e1731))
+(flet ($e1845 (xor $e382 $e1036))
+(flet ($e1846 (and $e1660 $e1825))
+(flet ($e1847 (or $e1702 $e1624))
+(flet ($e1848 (or $e793 $e1794))
+(flet ($e1849 (xor $e1665 $e708))
+(flet ($e1850 (implies $e1455 $e739))
+(flet ($e1851 (and $e752 $e1356))
+(flet ($e1852 (implies $e291 $e1609))
+(flet ($e1853 (or $e1833 $e370))
+(flet ($e1854 (or $e1810 $e845))
+(flet ($e1855 (not $e1613))
+(flet ($e1856 (xor $e797 $e998))
+(flet ($e1857 (xor $e1535 $e1741))
+(flet ($e1858 (if_then_else $e1300 $e1365 $e1843))
+(flet ($e1859 (not $e374))
+(flet ($e1860 (iff $e1819 $e938))
+(flet ($e1861 (not $e1850))
+(flet ($e1862 (xor $e1382 $e1834))
+(flet ($e1863 (if_then_else $e1706 $e1802 $e1277))
+(flet ($e1864 (xor $e611 $e757))
+(flet ($e1865 (xor $e1406 $e1602))
+(flet ($e1866 (if_then_else $e1848 $e1421 $e1776))
+(flet ($e1867 (implies $e1788 $e1853))
+(flet ($e1868 (not $e1484))
+(flet ($e1869 (and $e1851 $e344))
+(flet ($e1870 (implies $e1726 $e371))
+(flet ($e1871 (and $e1673 $e748))
+(flet ($e1872 (and $e1355 $e1599))
+(flet ($e1873 (iff $e1774 $e769))
+(flet ($e1874 (if_then_else $e1547 $e1639 $e1695))
+(flet ($e1875 (xor $e1787 $e1822))
+(flet ($e1876 (or $e1473 $e1604))
+(flet ($e1877 (implies $e873 $e1655))
+(flet ($e1878 (not $e1483))
+(flet ($e1879 (if_then_else $e1763 $e1725 $e1816))
+(flet ($e1880 (iff $e1475 $e1840))
+(flet ($e1881 (xor $e1761 $e1758))
+(flet ($e1882 (and $e1242 $e1856))
+(flet ($e1883 (xor $e478 $e414))
+(flet ($e1884 (or $e1757 $e1701))
+(flet ($e1885 (implies $e1806 $e526))
+(flet ($e1886 (if_then_else $e1877 $e851 $e1818))
+(flet ($e1887 (if_then_else $e668 $e1409 $e1871))
+(flet ($e1888 (and $e582 $e577))
+(flet ($e1889 (if_then_else $e1686 $e1846 $e1498))
+(flet ($e1890 (not $e1422))
+(flet ($e1891 (not $e379))
+(flet ($e1892 (implies $e1874 $e349))
+(flet ($e1893 (and $e1719 $e1512))
+(flet ($e1894 (and $e1664 $e786))
+(flet ($e1895 (iff $e482 $e1894))
+(flet ($e1896 (not $e1630))
+(flet ($e1897 (if_then_else $e1892 $e1510 $e1646))
+(flet ($e1898 (or $e1814 $e983))
+(flet ($e1899 (or $e1884 $e1821))
+(flet ($e1900 (xor $e565 $e1888))
+(flet ($e1901 (and $e1472 $e694))
+(flet ($e1902 (xor $e970 $e1875))
+(flet ($e1903 (xor $e1029 $e706))
+(flet ($e1904 (xor $e1666 $e904))
+(flet ($e1905 (xor $e954 $e1703))
+(flet ($e1906 (if_then_else $e1900 $e1748 $e1760))
+(flet ($e1907 (not $e1638))
+(flet ($e1908 (if_then_else $e1157 $e1619 $e1804))
+(flet ($e1909 (xor $e1011 $e1663))
+(flet ($e1910 (or $e1488 $e1743))
+(flet ($e1911 (if_then_else $e726 $e1650 $e1831))
+(flet ($e1912 (xor $e1730 $e1857))
+(flet ($e1913 (and $e567 $e1459))
+(flet ($e1914 (iff $e1772 $e1770))
+(flet ($e1915 (or $e1671 $e1786))
+(flet ($e1916 (implies $e1865 $e778))
+(flet ($e1917 (if_then_else $e1346 $e1693 $e1163))
+(flet ($e1918 (iff $e1809 $e1912))
+(flet ($e1919 (and $e1905 $e1420))
+(flet ($e1920 (or $e1176 $e1849))
+(flet ($e1921 (or $e1906 $e1413))
+(flet ($e1922 (xor $e1457 $e1882))
+(flet ($e1923 (and $e862 $e1869))
+(flet ($e1924 (and $e1083 $e1858))
+(flet ($e1925 (xor $e1778 $e1803))
+(flet ($e1926 (not $e760))
+(flet ($e1927 (implies $e1904 $e1672))
+(flet ($e1928 (iff $e702 $e520))
+(flet ($e1929 (if_then_else $e677 $e1598 $e563))
+(flet ($e1930 (or $e1523 $e1295))
+(flet ($e1931 (or $e1304 $e1926))
+(flet ($e1932 (implies $e1574 $e1057))
+(flet ($e1933 (iff $e1911 $e1886))
+(flet ($e1934 (iff $e630 $e1756))
+(flet ($e1935 (iff $e1737 $e1914))
+(flet ($e1936 (or $e1603 $e1805))
+(flet ($e1937 (xor $e1713 $e1898))
+(flet ($e1938 (xor $e1452 $e1744))
+(flet ($e1939 (and $e1551 $e1915))
+(flet ($e1940 (and $e1501 $e262))
+(flet ($e1941 (or $e1929 $e1872))
+(flet ($e1942 (and $e1573 $e363))
+(flet ($e1943 (or $e1847 $e1642))
+(flet ($e1944 (or $e1941 $e1866))
+(flet ($e1945 (iff $e1094 $e613))
+(flet ($e1946 (xor $e1837 $e1524))
+(flet ($e1947 (or $e1635 $e1051))
+(flet ($e1948 (implies $e905 $e1747))
+(flet ($e1949 (iff $e751 $e1921))
+(flet ($e1950 (or $e1948 $e1916))
+(flet ($e1951 (if_then_else $e1656 $e1924 $e843))
+(flet ($e1952 (not $e1903))
+(flet ($e1953 (and $e384 $e1842))
+(flet ($e1954 (xor $e1678 $e1734))
+(flet ($e1955 (if_then_else $e1859 $e1944 $e1861))
+(flet ($e1956 (if_then_else $e1155 $e1867 $e1891))
+(flet ($e1957 (if_then_else $e1949 $e1860 $e1928))
+(flet ($e1958 (if_then_else $e1633 $e1909 $e1829))
+(flet ($e1959 (if_then_else $e1920 $e1471 $e1881))
+(flet ($e1960 (or $e1715 $e1732))
+(flet ($e1961 (or $e1939 $e476))
+(flet ($e1962 (or $e1879 $e1918))
+(flet ($e1963 (and $e1797 $e1844))
+(flet ($e1964 (and $e1243 $e1432))
+(flet ($e1965 (iff $e691 $e1784))
+(flet ($e1966 (and $e1937 $e1896))
+(flet ($e1967 (if_then_else $e1812 $e1736 $e732))
+(flet ($e1968 (not $e1568))
+(flet ($e1969 (and $e1789 $e1935))
+(flet ($e1970 (if_then_else $e1925 $e1795 $e1931))
+(flet ($e1971 (if_then_else $e929 $e1845 $e1739))
+(flet ($e1972 (or $e1616 $e273))
+(flet ($e1973 (iff $e1026 $e1962))
+(flet ($e1974 (if_then_else $e1964 $e1718 $e1922))
+(flet ($e1975 (or $e1971 $e1477))
+(flet ($e1976 (xor $e926 $e1799))
+(flet ($e1977 (and $e957 $e821))
+(flet ($e1978 (xor $e1669 $e1796))
+(flet ($e1979 (if_then_else $e1063 $e1936 $e1838))
+(flet ($e1980 (if_then_else $e1963 $e1338 $e1954))
+(flet ($e1981 (or $e1068 $e1697))
+(flet ($e1982 (xor $e1183 $e1824))
+(flet ($e1983 (not $e866))
+(flet ($e1984 (implies $e1956 $e354))
+(flet ($e1985 (implies $e1965 $e1579))
+(flet ($e1986 (iff $e580 $e1750))
+(flet ($e1987 (or $e1114 $e1897))
+(flet ($e1988 (if_then_else $e1919 $e1966 $e1275))
+(flet ($e1989 (if_then_else $e807 $e1899 $e1722))
+(flet ($e1990 (not $e1793))
+(flet ($e1991 (implies $e1961 $e1855))
+(flet ($e1992 (iff $e921 $e1773))
+(flet ($e1993 (xor $e1742 $e1696))
+(flet ($e1994 (iff $e689 $e937))
+(flet ($e1995 (iff $e1689 $e1947))
+(flet ($e1996 (xor $e1913 $e1815))
+(flet ($e1997 (iff $e1514 $e1628))
+(flet ($e1998 (implies $e1836 $e1123))
+(flet ($e1999 (or $e1930 $e1878))
+(flet ($e2000 (implies $e1889 $e1728))
+(flet ($e2001 (and $e1873 $e1202))
+(flet ($e2002 (and $e1973 $e1958))
+(flet ($e2003 (iff $e1993 $e1987))
+(flet ($e2004 (and $e872 $e1260))
+(flet ($e2005 (implies $e1880 $e1885))
+(flet ($e2006 (and $e1977 $e1985))
+(flet ($e2007 (iff $e1854 $e1723))
+(flet ($e2008 (or $e1901 $e1827))
+(flet ($e2009 (or $e2008 $e758))
+(flet ($e2010 (implies $e1997 $e1419))
+(flet ($e2011 (not $e1563))
+(flet ($e2012 (iff $e1647 $e1932))
+(flet ($e2013 (iff $e1798 $e1902))
+(flet ($e2014 (not $e564))
+(flet ($e2015 (iff $e1945 $e1938))
+(flet ($e2016 (if_then_else $e1852 $e1781 $e338))
+(flet ($e2017 (and $e1751 $e1507))
+(flet ($e2018 (not $e1170))
+(flet ($e2019 (implies $e1156 $e2000))
+(flet ($e2020 (xor $e1708 $e1634))
+(flet ($e2021 (or $e2009 $e1813))
+(flet ($e2022 (not $e1910))
+(flet ($e2023 (iff $e2010 $e1820))
+(flet ($e2024 (if_then_else $e1934 $e498 $e1983))
+(flet ($e2025 (not $e1785))
+(flet ($e2026 (xor $e1864 $e1791))
+(flet ($e2027 (or $e2011 $e572))
+(flet ($e2028 (implies $e997 $e1486))
+(flet ($e2029 (not $e1974))
+(flet ($e2030 (not $e342))
+(flet ($e2031 (if_then_else $e1988 $e1034 $e1890))
+(flet ($e2032 (or $e1876 $e2024))
+(flet ($e2033 (or $e2027 $e1868))
+(flet ($e2034 (not $e2019))
+(flet ($e2035 (not $e1348))
+(flet ($e2036 (not $e517))
+(flet ($e2037 (implies $e1976 $e2003))
+(flet ($e2038 (if_then_else $e2006 $e1645 $e1754))
+(flet ($e2039 (if_then_else $e1972 $e2013 $e1996))
+(flet ($e2040 (or $e1862 $e2022))
+(flet ($e2041 (xor $e1611 $e849))
+(flet ($e2042 (xor $e1883 $e1623))
+(flet ($e2043 (if_then_else $e1425 $e1951 $e1832))
+(flet ($e2044 (iff $e1957 $e885))
+(flet ($e2045 (or $e2004 $e2033))
+(flet ($e2046 (or $e289 $e1927))
+(flet ($e2047 (or $e868 $e2014))
+(flet ($e2048 (iff $e1839 $e2023))
+(flet ($e2049 (if_then_else $e351 $e1502 $e1790))
+(flet ($e2050 (implies $e1808 $e2015))
+(flet ($e2051 (not $e320))
+(flet ($e2052 (not $e2036))
+(flet ($e2053 (and $e1644 $e1569))
+(flet ($e2054 (if_then_else $e1970 $e2047 $e1942))
+(flet ($e2055 (xor $e1960 $e1992))
+(flet ($e2056 (or $e2035 $e1975))
+(flet ($e2057 (implies $e1830 $e1933))
+(flet ($e2058 (iff $e948 $e1991))
+(flet ($e2059 (iff $e1952 $e1953))
+(flet ($e2060 (and $e2057 $e1923))
+(flet ($e2061 (and $e2041 $e1989))
+(flet ($e2062 (or $e1978 $e1055))
+(flet ($e2063 (xor $e1347 $e2020))
+(flet ($e2064 (implies $e1887 $e2034))
+(flet ($e2065 (if_then_else $e1950 $e1946 $e1990))
+(flet ($e2066 (xor $e1601 $e888))
+(flet ($e2067 (iff $e1826 $e1674))
+(flet ($e2068 (if_then_else $e1986 $e1984 $e1981))
+(flet ($e2069 (if_then_else $e1940 $e2044 $e1907))
+(flet ($e2070 (or $e1968 $e2051))
+(flet ($e2071 (if_then_else $e2052 $e2029 $e2016))
+(flet ($e2072 (iff $e2031 $e1995))
+(flet ($e2073 (or $e2070 $e271))
+(flet ($e2074 (iff $e2017 $e2042))
+(flet ($e2075 (implies $e2065 $e2037))
+(flet ($e2076 (or $e1186 $e1998))
+(flet ($e2077 (not $e2026))
+(flet ($e2078 (xor $e2040 $e1767))
+(flet ($e2079 (and $e1893 $e1749))
+(flet ($e2080 (or $e2075 $e1982))
+(flet ($e2081 (or $e2001 $e1828))
+(flet ($e2082 (and $e2056 $e1046))
+(flet ($e2083 (not $e2043))
+(flet ($e2084 (not $e839))
+(flet ($e2085 (and $e1967 $e2066))
+(flet ($e2086 (not $e2067))
+(flet ($e2087 (if_then_else $e2064 $e1908 $e1980))
+(flet ($e2088 (if_then_else $e2087 $e2071 $e1010))
+(flet ($e2089 (not $e1999))
+(flet ($e2090 (not $e2045))
+(flet ($e2091 (xor $e361 $e2088))
+(flet ($e2092 (implies $e1777 $e1955))
+(flet ($e2093 (if_then_else $e2091 $e2062 $e2032))
+(flet ($e2094 (not $e2073))
+(flet ($e2095 (not $e1863))
+(flet ($e2096 (implies $e1895 $e2039))
+(flet ($e2097 (if_then_else $e1917 $e1792 $e1870))
+(flet ($e2098 (xor $e1651 $e2061))
+(flet ($e2099 (if_then_else $e2081 $e2081 $e2089))
+(flet ($e2100 (if_then_else $e2097 $e2049 $e2092))
+(flet ($e2101 (implies $e1667 $e480))
+(flet ($e2102 (if_then_else $e2077 $e1223 $e2072))
+(flet ($e2103 (xor $e2055 $e2025))
+(flet ($e2104 (not $e2086))
+(flet ($e2105 (and $e2103 $e2005))
+(flet ($e2106 (iff $e2060 $e2079))
+(flet ($e2107 (and $e2058 $e2053))
+(flet ($e2108 (not $e1979))
+(flet ($e2109 (and $e2046 $e1648))
+(flet ($e2110 (xor $e2105 $e664))
+(flet ($e2111 (if_then_else $e2021 $e2095 $e420))
+(flet ($e2112 (iff $e2101 $e2012))
+(flet ($e2113 (or $e2100 $e1943))
+(flet ($e2114 (xor $e2038 $e2107))
+(flet ($e2115 (if_then_else $e2002 $e2074 $e1376))
+(flet ($e2116 (xor $e2098 $e2094))
+(flet ($e2117 (iff $e2050 $e2059))
+(flet ($e2118 (or $e2104 $e2090))
+(flet ($e2119 (xor $e2063 $e1959))
+(flet ($e2120 (and $e2110 $e1841))
+(flet ($e2121 (implies $e2068 $e2114))
+(flet ($e2122 (xor $e2007 $e2082))
+(flet ($e2123 (or $e2096 $e2108))
+(flet ($e2124 (implies $e2084 $e2076))
+(flet ($e2125 (implies $e2085 $e2099))
+(flet ($e2126 (iff $e2117 $e2120))
+(flet ($e2127 (or $e2028 $e2030))
+(flet ($e2128 (iff $e2121 $e1561))
+(flet ($e2129 (xor $e2048 $e2116))
+(flet ($e2130 (and $e2118 $e2126))
+(flet ($e2131 (iff $e2054 $e2080))
+(flet ($e2132 (xor $e2129 $e1683))
+(flet ($e2133 (implies $e2106 $e2122))
+(flet ($e2134 (not $e2119))
+(flet ($e2135 (if_then_else $e1969 $e651 $e2083))
+(flet ($e2136 (if_then_else $e1994 $e2133 $e2134))
+(flet ($e2137 (iff $e2132 $e2132))
+(flet ($e2138 (or $e1720 $e1111))
+(flet ($e2139 (and $e2078 $e2128))
+(flet ($e2140 (iff $e1710 $e2093))
+(flet ($e2141 (or $e2124 $e2130))
+(flet ($e2142 (not $e2131))
+(flet ($e2143 (if_then_else $e2111 $e2018 $e2069))
+(flet ($e2144 (iff $e2125 $e2143))
+(flet ($e2145 (implies $e2137 $e2127))
+(flet ($e2146 (xor $e2123 $e2112))
+(flet ($e2147 (not $e2135))
+(flet ($e2148 (or $e2136 $e2102))
+(flet ($e2149 (or $e2115 $e2141))
+(flet ($e2150 (or $e2148 $e2145))
+(flet ($e2151 (not $e2113))
+(flet ($e2152 (and $e2149 $e2149))
+(flet ($e2153 (if_then_else $e2140 $e2150 $e2140))
+(flet ($e2154 (not $e2153))
+(flet ($e2155 (or $e2138 $e2152))
+(flet ($e2156 (and $e2139 $e2154))
+(flet ($e2157 (and $e2144 $e2146))
+(flet ($e2158 (xor $e2156 $e2147))
+(flet ($e2159 (and $e2157 $e2142))
+(flet ($e2160 (implies $e2109 $e2159))
+(flet ($e2161 (not $e2158))
+(flet ($e2162 (if_then_else $e2151 $e2160 $e2151))
+(flet ($e2163 (or $e2161 $e2162))
+(flet ($e2164 (iff $e2163 $e2163))
+(flet ($e2165 (and $e2164 $e2164))
+(flet ($e2166 (or $e2165 $e2165))
+(flet ($e2167 (not $e2166))
+(flet ($e2168 (iff $e2167 $e2155))
+$e2168
+))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+
diff --git a/test/regress/run_regression b/test/regress/run_regression
index 9204fe33c..868a69116 100755
--- a/test/regress/run_regression
+++ b/test/regress/run_regression
@@ -335,7 +335,8 @@ if $check_models || $check_proofs || $check_unsat_cores; then
check_cmdline="$check_cmdline --check-models"
fi
if $check_proofs; then
- check_cmdline="$check_cmdline --check-proofs"
+ # taking: Make the extra flags part of --check-proofs.
+ check_cmdline="$check_cmdline --check-proofs --no-bv-eq --no-bv-ineq --no-bv-algebraic"
fi
if $check_unsat_cores; then
check_cmdline="$check_cmdline --check-unsat-cores"
diff --git a/test/unit/prop/cnf_stream_white.h b/test/unit/prop/cnf_stream_white.h
index bab71d8b2..0736ec052 100644
--- a/test/unit/prop/cnf_stream_white.h
+++ b/test/unit/prop/cnf_stream_white.h
@@ -64,8 +64,9 @@ public:
return d_nextVar++;
}
- void addClause(SatClause& c, bool lemma, uint64_t) {
+ ClauseId addClause(SatClause& c, bool lemma) {
d_addClauseCalled = true;
+ return ClauseIdUndef;
}
void reset() {
@@ -117,6 +118,8 @@ public:
return true;
}
+ bool ok() const { return true; }
+
};/* class FakeSatSolver */
class CnfStreamWhite : public CxxTest::TestSuite {
diff --git a/test/unit/theory/theory_engine_white.h b/test/unit/theory/theory_engine_white.h
index 2ecb4e225..62ed96900 100644
--- a/test/unit/theory/theory_engine_white.h
+++ b/test/unit/theory/theory_engine_white.h
@@ -49,7 +49,7 @@ using namespace CVC4::smt;
using namespace std;
class FakeOutputChannel : public OutputChannel {
- void conflict(TNode n) throw(AssertionException) {
+ void conflict(TNode n, Proof* pf = NULL) throw(AssertionException) {
Unimplemented();
}
bool propagate(TNode n) throw(AssertionException) {
@@ -58,7 +58,10 @@ class FakeOutputChannel : public OutputChannel {
void propagateAsDecision(TNode n) throw(AssertionException) {
Unimplemented();
}
- LemmaStatus lemma(TNode n, bool removable, bool preprocess, bool sendAtoms) throw(AssertionException) {
+ LemmaStatus lemma(TNode n, ProofRule rule,
+ bool removable,
+ bool preprocess,
+ bool sendAtoms) throw(AssertionException) {
Unimplemented();
}
void requirePhase(TNode, bool) throw(AssertionException) {
diff --git a/test/unit/theory/theory_white.h b/test/unit/theory/theory_white.h
index 429e72fc6..daa98855a 100644
--- a/test/unit/theory/theory_white.h
+++ b/test/unit/theory/theory_white.h
@@ -15,16 +15,17 @@
**/
#include <cxxtest/TestSuite.h>
+#include <vector>
-#include "theory/theory.h"
-#include "theory/theory_engine.h"
+// taking: Add include for Proof*.
+#include "context/context.h"
#include "expr/node.h"
#include "expr/node_manager.h"
-#include "context/context.h"
#include "smt/smt_engine.h"
#include "smt/smt_engine_scope.h"
+#include "theory/theory.h"
+#include "theory/theory_engine.h"
-#include <vector>
using namespace CVC4;
using namespace CVC4::theory;
@@ -56,7 +57,7 @@ public:
throw(Interrupted, UnsafeInterruptException, AssertionException)
{}
- void conflict(TNode n)
+ void conflict(TNode n, Proof* pf = NULL)
throw(AssertionException) {
push(CONFLICT, n);
}
@@ -72,7 +73,10 @@ public:
// ignore
}
- LemmaStatus lemma(TNode n, bool removable = false, bool preprocess = false, bool sendAtoms = false)
+ LemmaStatus lemma(TNode n, ProofRule rule,
+ bool removable = false,
+ bool preprocess = false,
+ bool sendAtoms = false)
throw(AssertionException) {
push(LEMMA, n);
return LemmaStatus(Node::null(), 0);
@@ -305,7 +309,7 @@ public:
void testOutputChannel() {
Node n = atom0.orNode(atom1);
- d_outputChannel.lemma(n);
+ d_outputChannel.lemma(n, RULE_INVALID);
d_outputChannel.split(atom0);
Node s = atom0.orNode(atom0.notNode());
TS_ASSERT_EQUALS(d_outputChannel.d_callHistory.size(), 2u);
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback