From 42b665f2a00643c81b42932fab1441987628c5a5 Mon Sep 17 00:00:00 2001 From: Liana Hadarean Date: Tue, 26 Jan 2016 16:04:26 -0800 Subject: [PATCH] Merged bit-vector and uf proof branch. --- proofs/signatures/Makefile.am | 2 +- proofs/signatures/core_rewrites.plf | 123 + proofs/signatures/ex-mem.plf | 16 +- proofs/signatures/ex_bv.plf | 43 +- proofs/signatures/ex_bv_rewrite.plf | 41 + proofs/signatures/sat.plf | 12 +- proofs/signatures/smt.plf | 94 +- proofs/signatures/th_arrays.plf | 2 +- proofs/signatures/th_bv.plf | 287 ++- proofs/signatures/th_bv_bitblast.plf | 629 +++++ src/Makefile.am | 9 +- src/options/bv_options | 8 +- src/proof/array_proof.h | 78 + src/proof/bitvector_proof.cpp | 602 +++++ src/proof/bitvector_proof.h | 142 ++ src/proof/cnf_proof.cpp | 1049 ++++---- src/proof/cnf_proof.h | 136 +- src/proof/proof.h | 21 +- src/proof/proof_manager.cpp | 546 +++-- src/proof/proof_manager.h | 196 +- src/proof/proof_utils.cpp | 127 + src/proof/proof_utils.h | 178 ++ src/proof/sat_proof.h | 291 ++- src/proof/sat_proof_implementation.h | 1100 +++++++++ src/proof/theory_proof.cpp | 684 ++++-- src/proof/theory_proof.h | 282 ++- src/proof/uf_proof.cpp | 804 ++++++ src/proof/uf_proof.h | 75 + src/prop/bvminisat/bvminisat.cpp | 37 +- src/prop/bvminisat/bvminisat.h | 11 +- src/prop/bvminisat/core/Solver.cc | 407 ++- src/prop/bvminisat/core/Solver.h | 82 +- src/prop/bvminisat/core/SolverTypes.h | 27 +- src/prop/bvminisat/simp/SimpSolver.cc | 20 +- src/prop/bvminisat/simp/SimpSolver.h | 20 +- src/prop/cnf_stream.cpp | 212 +- src/prop/cnf_stream.h | 58 +- src/prop/minisat/core/Solver.cc | 132 +- src/prop/minisat/core/Solver.h | 61 +- src/prop/minisat/core/SolverTypes.h | 37 +- src/prop/minisat/minisat.cpp | 41 +- src/prop/minisat/minisat.h | 5 +- src/prop/minisat/simp/SimpSolver.cc | 12 +- src/prop/minisat/simp/SimpSolver.h | 30 +- src/prop/prop_engine.cpp | 9 +- src/prop/sat_solver.h | 19 +- src/prop/sat_solver_factory.h | 4 +- src/prop/theory_proxy.cpp | 3 + src/smt/smt_engine.cpp | 27 +- src/smt/smt_engine_check_proof.cpp | 5 +- src/smt/smt_engine_scope.h | 3 + src/smt_util/command.cpp | 4 + src/smt_util/command.h | 1 + src/theory/arrays/theory_arrays.cpp | 37 +- src/theory/arrays/theory_arrays.h | 2 +- src/theory/bv/bitblast_strategies_template.h | 57 +- src/theory/bv/bitblast_utils.h | 2 +- src/theory/bv/bitblaster_template.h | 13 +- src/theory/bv/bv_eager_solver.cpp | 11 + src/theory/bv/bv_eager_solver.h | 5 +- src/theory/bv/bv_subtheory.h | 3 + src/theory/bv/bv_subtheory_bitblast.cpp | 45 +- src/theory/bv/bv_subtheory_bitblast.h | 7 +- src/theory/bv/eager_bitblaster.cpp | 52 +- src/theory/bv/lazy_bitblaster.cpp | 37 +- src/theory/bv/theory_bv.cpp | 14 +- src/theory/bv/theory_bv.h | 8 +- src/theory/bv/theory_bv_rewrite_rules_core.h | 3 +- ...ry_bv_rewrite_rules_operator_elimination.h | 3 +- .../theory_bv_rewrite_rules_simplification.h | 6 +- src/theory/bv/theory_bv_utils.h | 10 +- src/theory/output_channel.h | 26 +- src/theory/rewriter.cpp | 10 +- src/theory/theory.cpp | 9 +- src/theory/theory.h | 38 +- src/theory/theory_engine.cpp | 47 +- src/theory/theory_engine.h | 23 +- src/theory/theory_test_utils.h | 7 +- src/theory/uf/equality_engine.cpp | 78 +- src/theory/uf/equality_engine.h | 4 +- src/theory/uf/kinds | 3 + src/theory/uf/symmetry_breaker.cpp | 51 +- src/theory/uf/symmetry_breaker.h | 51 +- src/theory/uf/theory_uf.cpp | 52 +- src/theory/uf/theory_uf.h | 10 +- src/theory/uf/theory_uf_type_rules.h | 8 + test/regress/regress0/bv/Makefile.am | 7 +- test/regress/regress0/bv/bv-proof00.smt | 2176 +++++++++++++++++ test/regress/run_regression | 3 +- test/unit/prop/cnf_stream_white.h | 5 +- test/unit/theory/theory_engine_white.h | 7 +- test/unit/theory/theory_white.h | 18 +- 92 files changed, 9917 insertions(+), 1875 deletions(-) create mode 100644 proofs/signatures/core_rewrites.plf mode change 100755 => 100644 proofs/signatures/ex_bv.plf create mode 100644 proofs/signatures/ex_bv_rewrite.plf mode change 100755 => 100644 proofs/signatures/th_bv.plf create mode 100644 proofs/signatures/th_bv_bitblast.plf create mode 100644 src/proof/array_proof.h create mode 100644 src/proof/bitvector_proof.cpp create mode 100644 src/proof/bitvector_proof.h create mode 100644 src/proof/proof_utils.cpp create mode 100644 src/proof/proof_utils.h create mode 100644 src/proof/sat_proof_implementation.h create mode 100644 src/proof/uf_proof.cpp create mode 100644 src/proof/uf_proof.h create mode 100644 test/regress/regress0/bv/bv-proof00.smt 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 old mode 100755 new mode 100644 index ae585e455..58494e793 --- 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 old mode 100755 new mode 100644 index 0fb50f8cf..c93541085 --- 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& 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& 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(true); + Node false_node = NodeManager::currentNM()->mkConst(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* 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_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"< " << conflict << "\n"; + d_isAssumptionConflict = false; +} + +void BitVectorProof::finalizeConflicts(std::vector& 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().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().repeatAmount; + os << amount <<" _ "; + } + if (term.getKind() == kind::BITVECTOR_SIGN_EXTEND) { + unsigned amount = term.getOperator().getConst().signExtendAmount; + os << amount <<" _ "; + } + + if (term.getKind() == kind::BITVECTOR_ZERO_EXTEND) { + unsigned amount = term.getOperator().getConst().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 "<& 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"<printAssumptionsResolution(lemma_id, os, lemma_paren); + os <= 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_"<().repeatAmount; + os << amount; + } + if (term.getKind() == kind::BITVECTOR_SIGN_EXTEND) { + unsigned amount = term.getOperator().getConst().signExtendAmount; + os << amount; + } + + if (term.getKind() == kind::BITVECTOR_ZERO_EXTEND) { + unsigned amount = term.getOperator().getConst().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 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::const_iterator it = d_bbTerms.begin(); + std::vector::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(); + 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 +#include +#include +#include +#include +#include +#include + +#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 TBitblaster; +} /* namespace CVC4::theory::bv */ +} /* namespace CVC4::theory */ + +class CnfProof; +} /* namespace CVC4 */ + +namespace CVC4 { + +template class TSatProof; +typedef TSatProof< CVC4::BVMinisat::Solver> BVSatProof; + +template class LFSCSatProof; +typedef LFSCSatProof< CVC4::BVMinisat::Solver> LFSCBVSatProof; + +typedef __gnu_cxx::hash_set ExprSet; +typedef __gnu_cxx::hash_map ExprToClauseId; +typedef __gnu_cxx::hash_map ExprToId; +typedef __gnu_cxx::hash_map 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 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* 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* bb); + + BVSatProof* getSatProof(); + CnfProof* getCnfProof() {return d_cnfProof; } + void finalizeConflicts(std::vector& 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& 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, NodeHashFunction >::const_iterator it = ProofManager::currentPM()->begin_deps(); - __gnu_cxx::hash_map< Node, std::vector, 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& childIndex, + std::map& 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 childIndex; + std::map 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 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 +#include #include #include +#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 SatVarToExpr; +typedef __gnu_cxx::hash_map NodeToNode; +typedef __gnu_cxx::hash_set ClauseIdSet; + +typedef context::CDHashMap ClauseIdToNode; +typedef context::CDHashMap 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 d_currentAssertionStack; + + /** Top of stack is top-level fact currently being converted to CNF **/ + std::vector 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& childIndex, + std::map& 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(true); + Node false_node = NodeManager::currentNM()->mkConst(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(true)) || + (n.getKind() == kind::NOT && n[0] == NodeManager::currentNM()->mkConst(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; isecond; - 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::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 v; + v.push_back(NodeManager::currentNM()->integerType()); + if(n.getConst() == kind::SELECT) { + v.push_back(NodeManager::currentNM()->integerType()); + v.push_back(NodeManager::currentNM()->integerType()); + } else if(n.getConst() == 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 TSatProof; +typedef TSatProof< CVC4::Minisat::Solver> CoreSatProof; + class CnfProof; +class RewriterProof; +class TheoryProofEngine; class TheoryProof; +class UFProof; +class ArrayProof; +class BitVectorProof; + +template class LFSCSatProof; +typedef LFSCSatProof< CVC4::Minisat::Solver> LFSCCoreSatProof; -class LFSCSatProof; class LFSCCnfProof; -class LFSCTheoryProof; +class LFSCTheoryProofEngine; +class LFSCUFProof; +class LFSCBitVectorProof; +class LFSCRewriterProof; + +template 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 VarSet; +typedef __gnu_cxx::hash_map < ClauseId, prop::SatClause* > IdToSatClause; typedef __gnu_cxx::hash_set ExprSet; +typedef __gnu_cxx::hash_set NodeSet; +typedef __gnu_cxx::hash_map, NodeHashFunction > NodeToNodes; +typedef std::hash_set 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, 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, NodeHashFunction >::const_iterator begin_deps() const { return d_deps.begin(); } - __gnu_cxx::hash_map< Node, std::vector, 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 d_ops; + std::map 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 +#include +#include +#include "expr/node_manager.h" + +namespace CVC4 { + +typedef __gnu_cxx::hash_set ExprSet; +typedef __gnu_cxx::hash_set NodeSet; + +namespace utils { + +std::string toLFSCKind(Kind kind); + +inline unsigned getExtractHigh(Expr node) { + return node.getOperator().getConst().high; +} + +inline unsigned getExtractLow(Expr node) { + return node.getOperator().getConst().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(true); +} + +inline Expr mkFalse() { + return NodeManager::currentNM()->toExprManager()->mkConst(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& children) { + return NodeManager::currentNM()->toExprManager()->mkExpr(k, children); +} + + +inline Expr mkOnes(unsigned size) { + BitVector val = mkBitVectorOnes(size); + return NodeManager::currentNM()->toExprManager()->mkConst(val); +} + +inline Expr mkConst(unsigned size, unsigned int value) { + BitVector val(size, value); + return NodeManager::currentNM()->toExprManager()->mkConst(val); +} + +inline Expr mkConst(const BitVector& value) { + return NodeManager::currentNM()->toExprManager()->mkConst(value); +} + +inline Expr mkOr(const std::vector& nodes) { + std::set 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::const_iterator it = all.begin(); + std::set::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& conjunctions) { + std::set 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::const_iterator it = all.begin(); + std::set::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& children) { + std::set 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::const_iterator it = all.begin(); + std::set::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().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 - #include #include #include #include #include #include - #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 void printDebug(typename Solver::TLit l); +template 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 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 ResChain { +public: + typedef std::vector< ResStep > 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 IdToSatClause; -typedef std::set < ClauseId > IdSet; -typedef std::vector < Minisat::Lit > LitVector; -typedef __gnu_cxx::hash_map 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 ProofProxy; class CnfProof; -class SatProof { +template +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* > IdResMap; + typedef std::hash_map < ClauseId, uint64_t > IdProofRuleMap; + typedef std::vector < ResChain* > ResStack; + //typedef std::hash_map IdToSatClause; + typedef std::set < ClauseId > IdSet; + typedef std::vector < typename Solver::TLit > LitVector; + typedef __gnu_cxx::hash_map IdToMinisatClause; + typedef __gnu_cxx::hash_map 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* 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* 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* 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* 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* 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 d_glueMap; + struct Statistics { + IntStat d_numLearnedClauses; + IntStat d_numLearnedInProof; + IntStat d_numLemmasInProof; + AverageStat d_avgChainLength; + HistogramStat d_resChainLengths; + HistogramStat d_usedResChainLengths; + HistogramStat d_clauseGlue; + HistogramStat d_usedClauseGlue; + Statistics(const std::string& name); + ~Statistics(); + }; + + Statistics d_statistics; +};/* class TSatProof */ + + +template +class ProofProxy { private: - void printResolution(ClauseId id, std::ostream& out, std::ostream& paren); + TSatProof* d_proof; public: - LFSCSatProof(Minisat::Solver* solver, bool checkRes = false) - : SatProof(solver, checkRes) + ProofProxy(TSatProof* pf); + void updateCRef(typename S::TCRef oldref, typename S::TCRef newref); +};/* class ProofProxy */ + + +template +class LFSCSatProof : public TSatProof { +private: + +public: + LFSCSatProof(SatSolver* solver, const std::string& name, bool checkRes = false) + : TSatProof(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 +prop::SatLiteral toSatLiteral(typename Solver::TLit lit); + + +/** +* Convert from minisat clause to SatClause +* +* @param minisat_cl +* @param sat_cl +*/ +template +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 +void printLit (typename Solver::TLit l) { + Debug("proof:sat") << (sign(l) ? "-" : "") << var(l) + 1; +} + +template +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 +void printClause (std::vector& c) { + for (unsigned i = 0; i < c.size(); i++) { + Debug("proof:sat") << (sign(c[i]) ? "-" : "") << var(c[i]) + 1 << " "; + } +} + + +template +void printLitSet(const std::set& s) { + typename std::set < typename Solver::TLit>::const_iterator it = s.begin(); + for(; it != s.end(); ++it) { + printLit(*it); + Debug("proof:sat") << " "; + } + Debug("proof:sat") << std::endl; +} + +// purely debugging functions +template +void printDebug (typename Solver::TLit l) { + Debug("proof:sat") << (sign(l) ? "-" : "") << var(l) + 1 << std::endl; +} +template +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 +void TSatProof::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 +bool resolve(const typename Solver::TLit v, + std::set& clause1, + std::set& 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(var); + Debug("proof:sat") << std::endl; + } + return false; + } + clause1.erase(var); + clause2.erase(~var); + typename std::set::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(var); + Debug("proof:sat") << std::endl; + } + return false; + } + clause1.erase(~var); + clause2.erase(var); + typename std::set::iterator it = clause2.begin(); + for (; it!= clause2.end(); ++it) { + clause1.insert(*it); + } + } + return true; +} + +/// ResChain +template +ResChain::ResChain(ClauseId start) : + d_start(start), + d_steps(), + d_redundantLits(NULL) + {} +template +void ResChain::addStep(typename Solver::TLit lit, ClauseId id, bool sign) { + ResStep step(lit, id, sign); + d_steps.push_back(step); +} + +template +void ResChain::addRedundantLit(typename Solver::TLit lit) { + if (d_redundantLits) { + d_redundantLits->insert(lit); + } else { + d_redundantLits = new LitSet(); + d_redundantLits->insert(lit); + } +} + + +/// ProxyProof +template +ProofProxy::ProofProxy(TSatProof* proof): + d_proof(proof) +{} + +template +void ProofProxy::updateCRef(typename Solver::TCRef oldref, typename Solver::TCRef newref) { + d_proof->updateCRef(oldref, newref); +} + + +/// SatProof +template +TSatProof::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(this); +} + +template +TSatProof::~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 +void TSatProof::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 +bool TSatProof::checkResolution(ClauseId id) { + if(d_checkRes) { + bool validRes = true; + Assert(d_resChains.find(id) != d_resChains.end()); + ResChain* res = d_resChains[id]; + LitSet clause1; + createLitSet(res->getStart(), clause1); + typename ResChain::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 (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(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(clause1); + Debug("proof:sat") << "proof:checkResolution:: result should be: \n"; + printClause(c); + } + } + return validRes; + + } else { + return true; + } +} + + + + +/// helper methods +template +ClauseId TSatProof::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 +ClauseId TSatProof::getClauseId(typename Solver::TLit lit) { + Assert(d_unitId.find(toInt(lit)) != d_unitId.end()); + return d_unitId[toInt(lit)]; +} +template +typename Solver::TCRef TSatProof::getClauseRef(ClauseId id) { + if (d_idClause.find(id) == d_idClause.end()) { + Debug("proof:sat") << "proof:getClauseRef cannot find clause "< +typename Solver::TClause& TSatProof::getClause(typename Solver::TCRef ref) { + Assert(ref != Solver::TCRef_Undef); + Assert(ref >= 0 && ref < d_solver->ca.size()); + return d_solver->ca[ref]; +} + +template +void TSatProof::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 +typename Solver::TLit TSatProof::getUnit(ClauseId id) { + Assert(d_idUnit.find(id) != d_idUnit.end()); + return d_idUnit[id]; +} +template +bool TSatProof::isUnit(ClauseId id) { + return d_idUnit.find(id) != d_idUnit.end(); +} +template +bool TSatProof::isUnit(typename Solver::TLit lit) { + return d_unitId.find(toInt(lit)) != d_unitId.end(); +} +template +ClauseId TSatProof::getUnitId(typename Solver::TLit lit) { + Assert(isUnit(lit)); + return d_unitId[toInt(lit)]; +} +template +bool TSatProof::hasResolution(ClauseId id) { + return d_resChains.find(id) != d_resChains.end(); +} +template +bool TSatProof::isInputClause(ClauseId id) { + return (d_inputClauses.find(id) != d_inputClauses.end()); +} +template +bool TSatProof::isLemmaClause(ClauseId id) { + return (d_lemmaClauses.find(id) != d_lemmaClauses.end()); +} + +template +bool TSatProof::isAssumptionConflict(ClauseId id) { + return d_assumptionConflicts.find(id) != d_assumptionConflicts.end(); +} + + +template +void TSatProof::print(ClauseId id) { + if (d_deleted.find(id) != d_deleted.end()) { + Debug("proof:sat") << "del"<(getUnit(id)); + } else if (id == d_emptyClauseId) { + Debug("proof:sat") << "empty "<< std::endl; + } + else { + typename Solver::TCRef ref = getClauseRef(id); + printClause(getClause(ref)); + } +} +template +void TSatProof::printRes(ClauseId id) { + Assert(hasResolution(id)); + Debug("proof:sat") << "id "<< id <<": "; + printRes(d_resChains[id]); +} +template +void TSatProof::printRes(ResChain* res) { + ClauseId start_id = res->getStart(); + + if(Debug.isOn("proof:sat")) { + Debug("proof:sat") << "("; + print(start_id); + } + + typename ResChain::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(v); + Debug("proof:sat") << "] "; + print(id); + } + } + Debug("proof:sat") << ") \n"; +} + +/// registration methods +template + ClauseId TSatProof::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 +ClauseId TSatProof::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 +void TSatProof::registerTrueLit(const typename Solver::TLit lit) { + Assert (d_trueLit == ClauseIdUndef); + d_trueLit = registerUnitClause(lit, INPUT); +} + +template +void TSatProof::registerFalseLit(const typename Solver::TLit lit) { + Assert (d_falseLit == ClauseIdUndef); + d_falseLit = registerUnitClause(lit, INPUT); +} + +template +ClauseId TSatProof::getTrueUnit() const { + Assert (d_trueLit != ClauseIdUndef); + return d_trueLit; +} + +template +ClauseId TSatProof::getFalseUnit() const { + Assert (d_falseLit != ClauseIdUndef); + return d_falseLit; +} + + +template +void TSatProof::registerAssumption(const typename Solver::TVar var) { + Assert (d_assumptions.find(var) == d_assumptions.end()); + d_assumptions.insert(var); +} + +template +ClauseId TSatProof::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(*vec_confl); + Debug("proof:sat:detailed") << "\n"; + } + + d_assumptionConflictsDebug[new_id] = vec_confl; + return new_id; +} + + +template +void TSatProof::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 +void TSatProof::removeRedundantFromRes(ResChain* 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 +void TSatProof::registerResolution(ClauseId id, ResChain* 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 +void TSatProof::startResChain(typename Solver::TCRef start) { + ClauseId id = getClauseId(start); + ResChain* res = new ResChain(id); + d_resStack.push_back(res); +} + +template +void TSatProof::startResChain(typename Solver::TLit start) { + ClauseId id = getUnitId(start); + ResChain* res = new ResChain(id); + d_resStack.push_back(res); +} + + +template +void TSatProof::addResolutionStep(typename Solver::TLit lit, + typename Solver::TCRef clause, bool sign) { + ClauseId id = registerClause(clause, LEARNT); + ResChain* res = d_resStack.back(); + res->addStep(lit, id, sign); +} + +template +void TSatProof::endResChain(ClauseId id) { + Debug("proof:sat:detailed") <<"endResChain " << id << "\n"; + Assert(d_resStack.size() > 0); + ResChain* res = d_resStack.back(); + registerResolution(id, res); + d_resStack.pop_back(); +} + + +// template +// void TSatProof::endResChain(typename Solver::TCRef clause) { +// Assert(d_resStack.size() > 0); +// ClauseId id = registerClause(clause, LEARNT); +// ResChain* res = d_resStack.back(); +// registerResolution(id, res); +// d_resStack.pop_back(); +// } + +template +void TSatProof::endResChain(typename Solver::TLit lit) { + Assert(d_resStack.size() > 0); + ClauseId id = registerUnitClause(lit, LEARNT); + Debug("proof:sat:detailed") <<"endResChain unit " << id << "\n"; + ResChain* res = d_resStack.back(); + d_glueMap[id] = 1; + registerResolution(id, res); + d_resStack.pop_back(); +} + + +template +void TSatProof::cancelResChain() { + Assert(d_resStack.size() > 0); + d_resStack.pop_back(); +} + + +template +void TSatProof::storeLitRedundant(typename Solver::TLit lit) { + Assert(d_resStack.size() > 0); + ResChain* res = d_resStack.back(); + res->addRedundantLit(lit); +} + +/// constructing resolutions +template +void TSatProof::resolveOutUnit(typename Solver::TLit lit) { + ClauseId id = resolveUnit(~lit); + ResChain* res = d_resStack.back(); + res->addStep(lit, id, !sign(lit)); +} +template +void TSatProof::storeUnitResolution(typename Solver::TLit lit) { + Debug("cores") << "STORE UNIT RESOLUTION" << std::endl; + resolveUnit(lit); +} +template +ClauseId TSatProof::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* res = new ResChain(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 +void TSatProof::toStream(std::ostream& out) { + Debug("proof:sat") << "TSatProof::printProof\n"; + Unimplemented("native proof printing not supported yet"); +} +template +ClauseId TSatProof::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 +void TSatProof::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* res = new ResChain(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* res = new ResChain(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 +void TSatProof::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 +void TSatProof::finishUpdateCRef() { + d_clauseId.swap(d_temp_clauseId); + d_temp_clauseId.clear(); + + d_idClause.swap(d_temp_idClause); + d_temp_idClause.clear(); +} +template +void TSatProof::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(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 +void TSatProof::constructProof(ClauseId conflict) { + collectClauses(conflict); +} + +template +std::string TSatProof::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 +prop::SatClause* TSatProof::buildClause(ClauseId id) { + if (isUnit(id)) { + typename Solver::TLit lit = getUnit(id); + prop::SatLiteral sat_lit = toSatLiteral(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(minisat_cl, *clause); + return clause; +} + +template +void TSatProof::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* 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::ResSteps steps = res->getSteps(); + for(size_t i = 0; i < steps.size(); i++) { + collectClauses(steps[i].id); + } +} + +template +void TSatProof::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 +void TSatProof::storeClauseGlue(ClauseId clause, int glue) { + Assert (d_glueMap.find(clause) == d_glueMap.end()); + d_glueMap.insert(std::make_pair(clause, glue)); +} + +template +TSatProof::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 +TSatProof::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 +void LFSCSatProof::printResolution(ClauseId id, std::ostream& out, std::ostream& paren) { + out << "(satlem_simplify _ _ _ "; + + ResChain* res = this->d_resChains[id]; + typename ResChain::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) << " "<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 +void LFSCSatProof::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& confl = *(this->d_assumptionConflictsDebug[id]); + + Assert (confl.size()); + + for (unsigned i = 0; i < confl.size(); ++i) { + prop::SatLiteral lit = toSatLiteral(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(confl[i]); + prop::SatVariable v = lit.getSatVariable(); + out << "unit"<< v <<" "; + out << ProofManager::getVarName(v, this->d_name) <<")"; + } + out <<"(\\ e e)\n"; + paren <<")"; +} + + +template +void LFSCSatProof::printResolutions(std::ostream& out, std::ostream& paren) { + Debug("bv-proof") << "; print resolutions" << std::endl; + std::set::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 +void LFSCSatProof::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 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"<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 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 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 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"<= 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() ? "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& 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::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 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() ? "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& 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 #include -#include "expr/expr.h" -#include "util/proof.h" namespace CVC4 { - typedef __gnu_cxx::hash_set SortSet; - typedef __gnu_cxx::hash_set 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 LetMap; +typedef std::vector Bindings; + +class TheoryProof; +typedef unsigned ClauseId; + +typedef __gnu_cxx::hash_set ExprSet; +typedef std::map 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& 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& 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& 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 + +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 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 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 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()); + } 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()); + } 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& 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 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 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& 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 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& 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& 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& minisat_clause); - static void toSatClause (BVMinisat::vec& clause, SatClause& sat_clause); + static void toSatClause (const BVMinisat::Clause& clause, SatClause& sat_clause); void addMarkerLiteral(SatLiteral lit); void explain(SatLiteral lit, std::vector& 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)); @@ -85,6 +76,12 @@ 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_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& ps) +bool Solver::addClause_(vec& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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 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& explanation) { - vec queue; - queue.push(p); - Debug("bvminisat::explain") << OUTPUT_TAG << "starting explain of " << p << std::endl; - __gnu_cxx::hash_set 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 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 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& 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 #include 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 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& ps); // Add a clause to the solver. + bool addClause (const vec& 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& 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& 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& 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& 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& 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 @@ -30,6 +30,15 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "prop/bvminisat/mtl/Alloc.h" namespace CVC4 { +namespace BVMinisat { +class Solver; +} +template class ProofProxy; +typedef ProofProxy BVProofProxy; +} + +namespace CVC4 { + namespace BVMinisat { //================================================================================================= @@ -205,6 +214,8 @@ public: const CRef CRef_Undef = RegionAllocator::Ref_Undef; +const CRef CRef_Lazy = RegionAllocator::Ref_Undef - 1; + class ClauseAllocator : public RegionAllocator { static int clauseWord32Size(int size, bool has_extra){ @@ -245,21 +256,7 @@ class ClauseAllocator : public RegionAllocator RegionAllocator::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& ps) +bool SimpSolver::addClause_(vec& ps, ClauseId& id) { #ifndef NDEBUG for (int i = 0; i < ps.size(); i++) @@ -174,7 +175,7 @@ bool SimpSolver::addClause_(vec& 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& 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& ps); + bool addClause (const vec& 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& 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& 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& 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& 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& 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 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; @@ -116,14 +119,6 @@ protected: return node; } - /** - * 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 @@ -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 @@ -243,13 +244,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. */ @@ -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 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& ps, bool removable, uint64_t proof_id) +bool Solver::addClause_(vec& ps, bool removable, ClauseId& id) { if (!ok) return false; @@ -289,11 +305,13 @@ bool Solver::addClause_(vec& 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& 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& 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& 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& 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& 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& 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 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 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& 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 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; + +public: + static CRef TCRef_Undef; + static CRef TCRef_Lazy; + + typedef Var TVar; + typedef Lit TLit; + typedef Clause TClause; + typedef CRef TCRef; + typedef vec TLitVec; + protected: /** The pointer to the proxy that provides interfaces to the SMT engine */ @@ -85,8 +98,8 @@ protected: /** Is the lemma removable */ vec lemmas_removable; - /** Proof IDs for lemmas */ - vec lemmas_proof_id; + /** Nodes being converted to CNF */ + std::vector< std::pair >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& 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& 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& 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& 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& 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& 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 ProofProxy; +typedef ProofProxy CoreProofProxy; +} namespace CVC4 { namespace Minisat{ @@ -305,27 +307,8 @@ class ClauseAllocator : public RegionAllocator RegionAllocator::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& 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_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_clause); - static void toSatClause (Minisat::vec& 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& ps, bool removable, uint64_t proof_id) +bool SimpSolver::addClause_(vec& ps, bool removable, ClauseId& id) { #ifndef NDEBUG if (use_simplification) { @@ -174,7 +174,7 @@ bool SimpSolver::addClause_(vec& 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& 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& 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& ps, bool removable, uint64_t proof_id); + bool addClause (const vec& 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& 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& 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& 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& bits, TBitblaster* bb) { Assert(node.getKind() == kind::BITVECTOR_AND && bits.size() == 0); - - for(unsigned j = 0; j < utils::getSize(node); ++j) { - std::vector and_j; - for (unsigned i = 0; i < node.getNumChildren(); ++i) { - std::vector 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 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 @@ -272,17 +272,17 @@ void DefaultOrBB (TNode node, std::vector& bits, TBitblaster* bb) { Assert(node.getKind() == kind::BITVECTOR_OR && bits.size() == 0); - - for(unsigned j = 0; j < utils::getSize(node); ++j) { - std::vector or_j; - for (unsigned i = 0; i < node.getNumChildren(); ++i) { - std::vector 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 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 @@ -291,20 +291,17 @@ void DefaultXorBB (TNode node, std::vector& bits, TBitblaster* bb) { Assert(node.getKind() == kind::BITVECTOR_XOR && bits.size() == 0); - - for(unsigned j = 0; j < utils::getSize(node); ++j) { - std::vector first; - bb->bbTerm(node[0], first); - T bitj = first[j]; - - for (unsigned i = 1; i < node.getNumChildren(); ++i) { - std::vector current; - bb->bbTerm(node[i], current); - bitj = mkXor(bitj, current[j]); - Assert(utils::getSize(node) == current.size()); + + bb->bbTerm(node[0], bits); + std::vector 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 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&a, const std::vector&b, s T carry_in = mkFalse(); 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 TBitblaster::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 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& 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& assertions, std::vector& new_assertions); + + bool applyAbstraction(const std::vector& assertions, std::vector& 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::applies(TNode node) { template<> inline Node RewriteRule::apply(TNode node) { Debug("bv-rewrite") << "RewriteRule(" << 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::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::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::applies(TNode node) { template<> inline Node RewriteRule::apply(TNode node) { - Debug("bv-rewrite") << "RewriteRule(" << node << ")" << std::endl; + Debug("bv-rewrite") << "RewriteRule(" << 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().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().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*) 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 @@ -271,6 +270,12 @@ protected: */ Valuation d_valuation; + /** + * Whether proofs are enabled + * + */ + bool d_proofsEnabled; + /** * Returns 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 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(true); d_false = NodeManager::currentNM()->mkConst(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& 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& 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& assertions, std::vector& new_assertions) { @@ -1511,12 +1516,12 @@ void TheoryEngine::ppBvToBool(const std::vector& assertions, std::vector& assertions, std::vector& 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& 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& 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 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& 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::iterator i = d_phi.begin(); i != d_phi.end(); ++i) { @@ -476,12 +480,12 @@ void SymmetryBreaker::apply(std::vector& 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 cts; while(!d_terms.empty() && cts.size() <= n) { @@ -539,11 +543,11 @@ void SymmetryBreaker::apply(std::vector& 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& 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& assumptions) { +void TheoryUF::explain(TNode literal, std::vector& 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 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& assumptions); + void explain(TNode literal, std::vector& 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 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 +#include -#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 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); -- 2.30.2