# 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 th_bv.plf th_bv_bitblast.plf
+CORE_PLFS = sat.plf smt.plf th_base.plf th_arrays.plf th_bv.plf th_bv_bitblast.plf th_real.plf th_int.plf
noinst_LTLIBRARIES = libsignatures.la
; input :
; ~L1
-; (extenstionality) lemma :
+; (extenstionality) lemma :
; L1 or ~L2
; theory conflicts :
(check
(% I sort
(% E sort
-(% a (term (array I E))
+(% a (term (Array I E))
(% i (term I)
; (1) -------------------- input formula -----------------------------------
-(% A1 (th_holds (not (= (array I E) a (apply _ _ (apply _ _ (apply _ _ (write I E) a) i) (apply _ _ (apply _ _ (read I E) a) i)))))
+(% A1 (th_holds (not (= (Array I E) a (apply _ _ (apply _ _ (apply _ _ (write I E) a) i) (apply _ _ (apply _ _ (read I E) a) i)))))
; (4) -------------------- map theory literals to boolean variables
; --- maps all theory literals involved in proof to boolean literals
-(decl_atom (= (array I E) a (apply _ _ (apply _ _ (apply _ _ (write I E) a) i) (apply _ _ (apply _ _ (read I E) a) i))) (\ v1 (\ a1
+(decl_atom (= (Array I E) a (apply _ _ (apply _ _ (apply _ _ (write I E) a) i) (apply _ _ (apply _ _ (read I E) a) i))) (\ v1 (\ a1
(decl_atom (= E (apply _ _ (apply _ _ (read I E) a) k) (apply _ _ (apply _ _ (read I E) (apply _ _ (apply _ _ (apply _ _ (write I E) a) i) (apply _ _ (apply _ _ (read I E) a) i))) k)) (\ v2 (\ a2
(decl_atom (= I i k) (\ v3 (\ a3
; use read over write rule "row"
(contra _ (symm _ _ _ (row _ _ _ _ a (apply _ _ (apply _ _ (read I E) a) i) l3)) l2)
-
+
))))) (\ CT1
; CT1 is the clause ( v2 V v3 )
(clausify_false
; use read over write rule "row1"
- (contra _ (symm _ _ _
- (trans _ _ _ _
- (symm _ _ _ (cong _ _ _ _ _ _
+ (contra _ (symm _ _ _
+ (trans _ _ _ _
+ (symm _ _ _ (cong _ _ _ _ _ _
(refl _ (apply _ _ (read I E) (apply _ _ (apply _ _ (apply _ _ (write I E) a) i) (apply _ _ (apply _ _ (read I E) a) i))))
l3))
(trans _ _ _ _
(cong _ _ _ _ _ _ (refl _ (apply _ _ (read I E) a)) l3)
)))
l2)
-
+
))))) (\ CT2
; CT2 is the clause ( v2 V ~v3 )
; sorts
-(declare array (! s1 sort (! s2 sort sort))) ; s1 is index, s2 is element
+(declare Array (! s1 sort (! s2 sort sort))) ; s1 is index, s2 is element
; functions
(declare write (! s1 sort
(! s2 sort
- (term (arrow (array s1 s2)
+ (term (arrow (Array s1 s2)
(arrow s1
- (arrow s2 (array s1 s2))))))))
+ (arrow s2 (Array s1 s2))))))))
(declare read (! s1 sort
(! s2 sort
- (term (arrow (array s1 s2)
+ (term (arrow (Array s1 s2)
(arrow s1 s2))))))
; inference rules
+
+; read( a[i] = b, i ) == b
(declare row1 (! s1 sort
(! s2 sort
- (! t1 (term (array s1 s2))
+ (! t1 (term (Array s1 s2))
(! t2 (term s1)
(! t3 (term s2)
- (th_holds (= _ (apply _ _ (apply _ _ (read s1 s2) (apply _ _ (apply _ _ (apply _ _ (write s1 s2) t1) t2) t3)) t2)
- t3))))))))
-
+ (th_holds (= _
+ (apply _ _ (apply _ _ (read s1 s2) (apply _ _ (apply _ _ (apply _ _ (write s1 s2) t1) t2) t3)) t2) t3))))))))
(declare row (! s1 sort
(! s2 sort
(! t2 (term s1)
(! t3 (term s1)
- (! t1 (term (array s1 s2))
+ (! t1 (term (Array s1 s2))
(! t4 (term s2)
(! u (th_holds (not (= _ t2 t3)))
(th_holds (= _ (apply _ _ (apply _ _ (read s1 s2) (apply _ _ (apply _ _ (apply _ _ (write s1 s2) t1) t2) t4)) t3)
(apply _ _ (apply _ _ (read s1 s2) t1) t3)))))))))))
+(declare negativerow (! s1 sort
+ (! s2 sort
+ (! t2 (term s1)
+ (! t3 (term s1)
+ (! t1 (term (Array s1 s2))
+ (! t4 (term s2)
+ (! u (th_holds (not (= _
+ (apply _ _ (apply _ _ (read s1 s2) (apply _ _ (apply _ _ (apply _ _ (write s1 s2) t1) t2) t4)) t3)
+ (apply _ _ (apply _ _ (read s1 s2) t1) t3))))
+ (th_holds (= _ t2 t3))))))))))
+
(declare ext (! s1 sort
(! s2 sort
- (! t1 (term (array s1 s2))
- (! t2 (term (array s1 s2))
+ (! t1 (term (Array s1 s2))
+ (! t2 (term (Array s1 s2))
(! u1 (! k (term s1)
(! u2 (th_holds (or (= _ t1 t2) (not (= _ (apply _ _ (apply _ _ (read s1 s2) t1) k) (apply _ _ (apply _ _ (read s1 s2) t2) k)))))
(holds cln)))
(! t1 (term (arrow s1 s2))
(! t2 (term s1)
(term s2))))))
-
-
+
+
; inference rules :
(declare trust (th_holds false)) ; temporary
(! u (th_holds (= _ y z))
(th_holds (= _ x z)))))))))
+(declare negsymm (! s sort
+ (! x (term s)
+ (! y (term s)
+ (! u (th_holds (not (= _ x y)))
+ (th_holds (not (= _ y x))))))))
+
+(declare negtrans1 (! s sort
+ (! x (term s)
+ (! y (term s)
+ (! z (term s)
+ (! u (th_holds (not (= _ x y)))
+ (! u (th_holds (= _ y z))
+ (th_holds (not (= _ x z))))))))))
+
+(declare negtrans2 (! s sort
+ (! x (term s)
+ (! y (term s)
+ (! z (term s)
+ (! u (th_holds (= _ x y))
+ (! u (th_holds (not (= _ y z)))
+ (th_holds (not (= _ x z))))))))))
+
(declare cong (! s1 sort
(! s2 sort
(! a1 (term (arrow s1 s2))
--- /dev/null
+(declare Int sort)
+
+(define arithpred_Int (! x (term Int)
+ (! y (term Int)
+ formula)))
+
+(declare >_Int arithpred_Int)
+(declare >=_Int arithpred_Int)
+(declare <_Int arithpred_Int)
+(declare <=_Int arithpred_Int)
+
+(define arithterm_Int (! x (term Int)
+ (! y (term Int)
+ (term Int))))
+
+(declare +_Int arithterm_Int)
+(declare -_Int arithterm_Int)
+(declare *_Int arithterm_Int) ; is * ok to use?
+(declare /_Int arithterm_Int) ; is / ok to use?
+
+; a constant term
+(declare a_int (! x mpz (term Int)))
+
+; unary negation
+(declare u-_Int (! t (term Int) (term Int)))
--- /dev/null
+; 59 loc in side conditions\r
+\r
+(program mpq_ifpos ((x mpq)) bool\r
+ (mp_ifneg x ff (mp_ifzero x ff tt)))\r
+\r
+; a real variable\r
+(declare var_real type)\r
+; a real variable term\r
+(declare a_var_real (! v var_real (term Real)))\r
+\r
+;; linear polynomials in the form a_1*x_1 + a_2*x_2 .... + a_n*x_n\r
+\r
+(declare lmon type)\r
+(declare lmonn lmon)\r
+(declare lmonc (! c mpq (! v var_real (! l lmon lmon))))\r
+\r
+(program lmon_neg ((l lmon)) lmon \r
+ (match l\r
+ (lmonn l)\r
+ ((lmonc c' v' l') (lmonc (mp_neg c') v' (lmon_neg l')))))\r
+\r
+(program lmon_add ((l1 lmon) (l2 lmon)) lmon\r
+ (match l1\r
+ (lmonn l2)\r
+ ((lmonc c' v' l') \r
+ (match l2\r
+ (lmonn l1)\r
+ ((lmonc c'' v'' l'')\r
+ (compare v' v'' \r
+ (lmonc c' v' (lmon_add l' l2))\r
+ (lmonc c'' v'' (lmon_add l1 l''))))))))\r
+\r
+(program lmon_mul_c ((l lmon) (c mpq)) lmon\r
+ (match l\r
+ (lmonn l)\r
+ ((lmonc c' v' l') (lmonc (mp_mul c c') v' (lmon_mul_c l' c)))))\r
+\r
+;; linear polynomials in the form (a_1*x_1 + a_2*x_2 .... + a_n*x_n) + c \r
+\r
+(declare poly type)\r
+(declare polyc (! c mpq (! l lmon poly)))\r
+\r
+(program poly_neg ((p poly)) poly\r
+ (match p\r
+ ((polyc m' p') (polyc (mp_neg m') (lmon_neg p')))))\r
+\r
+(program poly_add ((p1 poly) (p2 poly)) poly\r
+ (match p1\r
+ ((polyc c1 l1)\r
+ (match p2\r
+ ((polyc c2 l2) (polyc (mp_add c1 c2) (lmon_add l1 l2)))))))\r
+\r
+(program poly_sub ((p1 poly) (p2 poly)) poly\r
+ (poly_add p1 (poly_neg p2)))\r
+ \r
+(program poly_mul_c ((p poly) (c mpq)) poly\r
+ (match p\r
+ ((polyc c' l') (polyc (mp_mul c' c) (lmon_mul_c l' c)))))\r
+ \r
+;; code to isolate a variable from a term\r
+;; if (isolate v l) returns (c,l'), this means l = c*v + l', where v is not in FV(t').\r
+\r
+(declare isol type)\r
+(declare isolc (! r mpq (! l lmon isol)))\r
+\r
+(program isolate_h ((v var_real) (l lmon) (e bool)) isol\r
+ (match l\r
+ (lmonn (isolc 0/1 l))\r
+ ((lmonc c' v' l') \r
+ (ifmarked v'\r
+ (match (isolate_h v l' tt) \r
+ ((isolc ci li) (isolc (mp_add c' ci) li)))\r
+ (match e \r
+ (tt (isolc 0/1 l))\r
+ (ff (match (isolate_h v l' ff) \r
+ ((isolc ci li) (isolc ci (lmonc c' v' li))))))))))\r
+\r
+(program isolate ((v var_real) (l lmon)) isol\r
+ (do (markvar v)\r
+ (let i (isolate_h v l ff)\r
+ (do (markvar v) i))))\r
+\r
+;; determine if a monomial list is constant\r
+\r
+(program is_lmon_zero ((l lmon)) bool\r
+ (match l\r
+ (lmonn tt)\r
+ ((lmonc c v l')\r
+ (match (isolate v l)\r
+ ((isolc ci li) \r
+ (mp_ifzero ci (is_lmon_zero li) ff))))))\r
+ \r
+;; return the constant that p is equal to. If p is not constant, fail.\r
+ \r
+(program is_poly_const ((p poly)) mpq\r
+ (match p\r
+ ((polyc c' l')\r
+ (match (is_lmon_zero l')\r
+ (tt c')\r
+ (ff (fail mpq))))))\r
+\r
+;; conversion to use polynomials in term formulas\r
+\r
+(declare poly_term (! p poly (term Real)))\r
+ \r
+;; create new equality out of inequality\r
+\r
+(declare lra_>=_>=_to_=\r
+ (! p1 poly\r
+ (! p2 poly\r
+ (! f1 (th_holds (>=0_Real (poly_term p1)))\r
+ (! f2 (th_holds (>=0_Real (poly_term p2)))\r
+ (! i2 (^ (mp_ifzero (is_poly_const (poly_add p1 p2)) tt ff) tt)\r
+ (th_holds (=0_Real (poly_term p2))))))))))\r
+ \r
+;; axioms\r
+\r
+(declare lra_axiom_=\r
+ (th_holds (=0_Real (poly_term (polyc 0/1 lmonn)))))\r
+ \r
+(declare lra_axiom_>\r
+ (! c mpq \r
+ (! i (^ (mpq_ifpos c) tt)\r
+ (th_holds (>0_Real (poly_term (polyc c lmonn)))))))\r
+ \r
+(declare lra_axiom_>=\r
+ (! c mpq \r
+ (! i (^ (mp_ifneg c tt ff) ff)\r
+ (th_holds (>=0_Real (poly_term (polyc c lmonn)))))))\r
+ \r
+(declare lra_axiom_distinct\r
+ (! c mpq \r
+ (! i (^ (mp_ifzero c tt ff) ff)\r
+ (th_holds (distinct0_Real (poly_term (polyc c lmonn)))))))\r
+\r
+;; contradiction rules\r
+\r
+(declare lra_contra_=\r
+ (! p poly\r
+ (! f (th_holds (=0_Real (poly_term p)))\r
+ (! i (^ (mp_ifzero (is_poly_const p) tt ff) ff)\r
+ (holds cln)))))\r
+ \r
+(declare lra_contra_>\r
+ (! p poly\r
+ (! f (th_holds (>0_Real (poly_term p)))\r
+ (! i2 (^ (mpq_ifpos (is_poly_const p)) ff)\r
+ (holds cln)))))\r
+ \r
+(declare lra_contra_>=\r
+ (! p poly\r
+ (! f (th_holds (>=0_Real (poly_term p)))\r
+ (! i2 (^ (mp_ifneg (is_poly_const p) tt ff) tt)\r
+ (holds cln)))))\r
+ \r
+(declare lra_contra_distinct\r
+ (! p poly\r
+ (! f (th_holds (distinct0_Real (poly_term p)))\r
+ (! i2 (^ (mp_ifzero (is_poly_const p) tt ff) tt)\r
+ (holds cln)))))\r
+\r
+;; muliplication by a constant\r
+\r
+(declare lra_mul_c_=\r
+ (! p poly\r
+ (! p' poly\r
+ (! c mpq\r
+ (! f (th_holds (=0_Real (poly_term p)))\r
+ (! i (^ (poly_mul_c p c) p')\r
+ (th_holds (=0_Real (poly_term p')))))))))\r
+\r
+(declare lra_mul_c_>\r
+ (! p poly\r
+ (! p' poly\r
+ (! c mpq\r
+ (! f (th_holds (>0_Real (poly_term p)))\r
+ (! i (^ (mp_ifneg c (fail poly) (mp_ifzero c (fail poly) (poly_mul_c p c))) p')\r
+ (th_holds (>0_Real (poly_term p')))))))));)\r
+ \r
+(declare lra_mul_c_>=\r
+ (! p poly\r
+ (! p' poly\r
+ (! c mpq\r
+ (! f (th_holds (>=0_Real (poly_term p)))\r
+ (! i (^ (mp_ifneg c (fail poly) (poly_mul_c p c)) p')\r
+ (th_holds (>=0_Real (poly_term p')))))))));)\r
+ \r
+(declare lra_mul_c_distinct\r
+ (! p poly\r
+ (! p' poly\r
+ (! c mpq\r
+ (! f (th_holds (distinct0_Real (poly_term p)))\r
+ (! i (^ (mp_ifzero c (fail poly) (poly_mul_c p c)) p')\r
+ (th_holds (distinct0_Real (poly_term p')))))))));)\r
+\r
+;; adding equations\r
+\r
+(declare lra_add_=_=\r
+ (! p1 poly\r
+ (! p2 poly\r
+ (! p3 poly\r
+ (! f1 (th_holds (=0_Real (poly_term p1)))\r
+ (! f2 (th_holds (=0_Real (poly_term p2)))\r
+ (! i (^ (poly_add p1 p2) p3)\r
+ (th_holds (=0_Real (poly_term p3)))))))))))\r
+ \r
+(declare lra_add_>_>\r
+ (! p1 poly\r
+ (! p2 poly\r
+ (! p3 poly\r
+ (! f1 (th_holds (>0_Real (poly_term p1)))\r
+ (! f2 (th_holds (>0_Real (poly_term p2)))\r
+ (! i (^ (poly_add p1 p2) p3)\r
+ (th_holds (>0_Real (poly_term p3))))))))))\r
+ \r
+(declare lra_add_>=_>=\r
+ (! p1 poly\r
+ (! p2 poly\r
+ (! p3 poly\r
+ (! f1 (th_holds (>=0_Real (poly_term p1)))\r
+ (! f2 (th_holds (>=0_Real (poly_term p2)))\r
+ (! i (^ (poly_add p1 p2) p3)\r
+ (th_holds (>=0_Real (poly_term p3))))))))))\r
+\r
+(declare lra_add_=_>\r
+ (! p1 poly\r
+ (! p2 poly\r
+ (! p3 poly\r
+ (! f1 (th_holds (=0_Real (poly_term p1)))\r
+ (! f2 (th_holds (>0_Real (poly_term p2)))\r
+ (! i (^ (poly_add p1 p2) p3)\r
+ (th_holds (>0_Real (poly_term p3))))))))))\r
+ \r
+(declare lra_add_=_>=\r
+ (! p1 poly\r
+ (! p2 poly\r
+ (! p3 poly\r
+ (! f1 (th_holds (=0_Real (poly_term p1)))\r
+ (! f2 (th_holds (>=0_Real (poly_term p2)))\r
+ (! i (^ (poly_add p1 p2) p3)\r
+ (th_holds (>=0_Real (poly_term p3))))))))))\r
+\r
+(declare lra_add_>_>=\r
+ (! p1 poly\r
+ (! p2 poly\r
+ (! p3 poly\r
+ (! f1 (th_holds (>0_Real (poly_term p1)))\r
+ (! f2 (th_holds (>=0_Real (poly_term p2)))\r
+ (! i (^ (poly_add p1 p2) p3)\r
+ (th_holds (>0_Real (poly_term p3))))))))))\r
+ \r
+(declare lra_add_=_distinct\r
+ (! p1 poly\r
+ (! p2 poly\r
+ (! p3 poly\r
+ (! f1 (th_holds (=0_Real (poly_term p1)))\r
+ (! f2 (th_holds (distinct0_Real (poly_term p2)))\r
+ (! i (^ (poly_add p1 p2) p3)\r
+ (th_holds (distinct0_Real (poly_term p3)))))))))))\r
+ \r
+;; substracting equations\r
+\r
+(declare lra_sub_=_=\r
+ (! p1 poly\r
+ (! p2 poly\r
+ (! p3 poly\r
+ (! f1 (th_holds (=0_Real (poly_term p1)))\r
+ (! f2 (th_holds (=0_Real (poly_term p2)))\r
+ (! i (^ (poly_sub p1 p2) p3)\r
+ (th_holds (=0_Real (poly_term p3)))))))))))\r
+ \r
+(declare lra_sub_>_=\r
+ (! p1 poly\r
+ (! p2 poly\r
+ (! p3 poly\r
+ (! f1 (th_holds (>0_Real (poly_term p1)))\r
+ (! f2 (th_holds (=0_Real (poly_term p2)))\r
+ (! i (^ (poly_sub p1 p2) p3)\r
+ (th_holds (>0_Real (poly_term p3))))))))))\r
+ \r
+(declare lra_sub_>=_=\r
+ (! p1 poly\r
+ (! p2 poly\r
+ (! p3 poly\r
+ (! f1 (th_holds (>=0_Real (poly_term p1)))\r
+ (! f2 (th_holds (=0_Real (poly_term p2)))\r
+ (! i (^ (poly_sub p1 p2) p3)\r
+ (th_holds (>=0_Real (poly_term p3))))))))))\r
+ \r
+(declare lra_sub_distinct_=\r
+ (! p1 poly\r
+ (! p2 poly\r
+ (! p3 poly\r
+ (! f1 (th_holds (distinct0_Real (poly_term p1)))\r
+ (! f2 (th_holds (=0_Real (poly_term p2)))\r
+ (! i (^ (poly_sub p1 p2) p3)\r
+ (th_holds (distinct0_Real (poly_term p3)))))))))))\r
+\r
+ ;; converting between terms and polynomials\r
+\r
+(declare poly_norm (! t (term Real) (! p poly type))) \r
+\r
+(declare pn_let \r
+ (! t (term Real)\r
+ (! p poly\r
+ (! pn (poly_norm t p)\r
+\r
+ (! u (! pnt (poly_norm t p)\r
+ (holds cln))\r
+ (holds cln))))))\r
+\r
+(declare pn_const\r
+ (! x mpq\r
+ (poly_norm (a_real x) (polyc x lmonn))))\r
+ \r
+(declare pn_var\r
+ (! v var_real\r
+ (poly_norm (a_var_real v) (polyc 0/1 (lmonc 1/1 v lmonn)))))\r
+\r
+\r
+(declare pn_+\r
+ (! x (term Real)\r
+ (! px poly\r
+ (! y (term Real)\r
+ (! py poly\r
+ (! pz poly\r
+ (! pnx (poly_norm x px)\r
+ (! pny (poly_norm y py)\r
+ (! a (^ (poly_add px py) pz)\r
+ (poly_norm (+_Real x y) pz))))))))))\r
+ \r
+(declare pn_-\r
+ (! x (term Real)\r
+ (! px poly\r
+ (! y (term Real)\r
+ (! py poly\r
+ (! pz poly\r
+ (! pnx (poly_norm x px)\r
+ (! pny (poly_norm y py)\r
+ (! a (^ (poly_sub px py) pz)\r
+ (poly_norm (-_Real x y) pz))))))))))\r
+ \r
+(declare pn_mul_c_L\r
+ (! y (term Real)\r
+ (! py poly\r
+ (! pz poly\r
+ (! x mpq\r
+ (! pny (poly_norm y py)\r
+ (! a (^ (poly_mul_c py x) pz)\r
+ (poly_norm (*_Real (a_real x) y) pz))))))))\r
+ \r
+(declare pn_mul_c_R\r
+ (! y (term Real)\r
+ (! py poly\r
+ (! pz poly\r
+ (! x mpq\r
+ (! pny (poly_norm y py)\r
+ (! a (^ (poly_mul_c py x) pz)\r
+ (poly_norm (*_Real y (a_real x)) pz))))))))\r
+\r
+;; for polynomializing other terms, in particular ite's\r
+\r
+(declare term_atom (! v var_real (! t (term Real) type)))\r
+\r
+(declare decl_term_atom\r
+ (! t (term Real)\r
+ (! u (! v var_real\r
+ (! a (term_atom v t)\r
+ (holds cln)))\r
+ (holds cln))))\r
+ \r
+(declare pn_var_atom\r
+ (! v var_real\r
+ (! t (term Real)\r
+ (! a (term_atom v t)\r
+ (poly_norm t (polyc 0/1 (lmonc 1/1 v lmonn)))))))\r
+\r
+\r
+;; conversion between term formulas and polynomial formulas\r
+\r
+(declare poly_formula_norm (! ft formula (! fp formula type))) \r
+\r
+; convert between term formulas and polynomial formulas\r
+\r
+(declare poly_form\r
+ (! ft formula\r
+ (! fp formula\r
+ (! p (poly_formula_norm ft fp)\r
+ (! u (th_holds ft)\r
+ (th_holds fp))))))\r
+ \r
+(declare poly_form_not\r
+ (! ft formula\r
+ (! fp formula\r
+ (! p (poly_formula_norm ft fp)\r
+ (! u (th_holds (not ft))\r
+ (th_holds (not fp)))))))\r
+ \r
+; form equivalence between term formula and polynomial formula \r
+ \r
+(declare poly_norm_=\r
+ (! x (term Real)\r
+ (! y (term Real)\r
+ (! p poly\r
+ (! h (th_holds (= Real x y))\r
+ (! n (poly_norm (-_Real x y) p)\r
+ (! u (! pn (th_holds (=0_Real (poly_term p)))\r
+ (holds cln))\r
+ (holds cln))))))))\r
+ \r
+(declare poly_norm_>\r
+ (! x (term Real)\r
+ (! y (term Real)\r
+ (! p poly\r
+ (! h (th_holds (>_Real x y))\r
+ (! n (poly_norm (-_Real x y) p)\r
+ (! u (! pn (th_holds (>0_Real (poly_term p)))\r
+ (holds cln))\r
+ (holds cln))))))))\r
+ \r
+(declare poly_norm_<\r
+ (! x (term Real)\r
+ (! y (term Real)\r
+ (! p poly\r
+ (! h (th_holds (<_Real x y))\r
+ (! n (poly_norm (-_Real y x) p)\r
+ (! u (! pn (th_holds (>0_Real (poly_term p)))\r
+ (holds cln))\r
+ (holds cln))))))))\r
+ \r
+(declare poly_norm_>=\r
+ (! x (term Real)\r
+ (! y (term Real)\r
+ (! p poly\r
+ (! h (th_holds (>=_Real x y))\r
+ (! n (poly_norm (-_Real x y) p)\r
+ (! u (! pn (th_holds (>=0_Real (poly_term p)))\r
+ (holds cln))\r
+ (holds cln))))))))\r
+ \r
+(declare poly_norm_<=\r
+ (! x (term Real)\r
+ (! y (term Real)\r
+ (! p poly\r
+ (! h (th_holds (<=_Real x y))\r
+ (! n (poly_norm (-_Real y x) p)\r
+ (! u (! pn (th_holds (>=0_Real (poly_term p)))\r
+ (holds cln))\r
+ (holds cln))))))))\r
+ \r
+ \r
--- /dev/null
+(declare Real sort)
+
+(define arithpred_Real (! x (term Real)
+ (! y (term Real)
+ formula)))
+
+(declare >_Real arithpred_Real)
+(declare >=_Real arithpred_Real)
+(declare <_Real arithpred_Real)
+(declare <=_Real arithpred_Real)
+
+(define arithterm_Real (! x (term Real)
+ (! y (term Real)
+ (term Real))))
+
+(declare +_Real arithterm_Real)
+(declare -_Real arithterm_Real)
+(declare *_Real arithterm_Real) ; is * ok to use?
+(declare /_Real arithterm_Real) ; is / ok to use?
+
+; a constant term
+(declare a_real (! x mpq (term Real)))
+
+; unary negation
+(declare u-_Real (! t (term Real) (term Real)))
printer/cvc/cvc_printer.cpp \
printer/tptp/tptp_printer.h \
printer/tptp/tptp_printer.cpp \
+ proof/arith_proof.cpp \
+ proof/arith_proof.h \
+ proof/array_proof.cpp \
proof/array_proof.h \
proof/bitvector_proof.cpp \
proof/bitvector_proof.h \
proof/proof_utils.h \
proof/sat_proof.h \
proof/sat_proof_implementation.h \
+ proof/skolemization_manager.cpp \
+ proof/skolemization_manager.h \
proof/theory_proof.cpp \
proof/theory_proof.h \
proof/uf_proof.cpp \
choose bitblasting mode, see --bitblast=help
# Options for eager bit-blasting
-
+
option bitvectorAig --bitblast-aig bool :default false :predicate abcEnabledBuild setBitblastAig :read-write
bitblast by first converting to AIG (implies --bitblast=eager)
expert-option bitvectorAigSimplifications --bv-aig-simp=COMMAND std::string :default "" :predicate abcEnabledBuild :read-write :link --bitblast-aig :link-smt bitblast-aig
abc command to run AIG simplifications (implies --bitblast-aig, default is "balance;drw")
# Options for lazy bit-blasting
-option bitvectorPropagate --bv-propagate bool :default true :read-write
+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
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
+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
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 :link-smt bv-algebraic-solver
the budget allowed for the algebraic solver in number of SAT conflicts
# General options
-option bitvectorToBool --bv-to-bool bool :default false :read-write
+option bitvectorToBool --bv-to-bool bool :default false :read-write
lift bit-vectors of size 1 to booleans when possible
option bitvectorDivByZeroConst --bv-div-zero-const bool :default false :read-write
expert-option bvExtractArithRewrite --bv-extract-arith bool :default false :read-write
enable rewrite pushing extract [i:0] over arithmetic operations (can blow up)
-
+
expert-option bvAbstraction --bv-abstraction bool :default false :read-write
- mcm benchmark abstraction
+ mcm benchmark abstraction
-expert-option skolemizeArguments --bv-skolemize bool :default false :read-write
+expert-option skolemizeArguments --bv-skolemize bool :default false :read-write
skolemize arguments for bv abstraction (only does something if --bv-abstraction is on)
expert-option bvNumFunc --bv-num-func=NUM unsigned :default 1
expert-option bitvectorQuickXplain --bv-quick-xplain bool :default false
minimize bv conflicts using the QuickXplain algorithm
-
+
expert-option bvIntroducePow2 --bv-intro-pow2 bool :default false
introduce bitvector powers of two as a preprocessing pass
-
+
endmodule
// arrays theory
case kind::SELECT:
case kind::STORE:
+ case kind::PARTIAL_SELECT_0:
+ case kind::PARTIAL_SELECT_1:
case kind::ARRAY_TYPE: out << smtKindString(k) << " "; break;
// string theory
case kind::CARDINALITY_CONSTRAINT: out << "fmf.card "; break;
case kind::CARDINALITY_VALUE: out << "fmf.card.val "; break;
-
+
// bv theory
case kind::BITVECTOR_CONCAT: out << "concat "; forceBinary = true; break;
case kind::BITVECTOR_AND: out << "bvand "; forceBinary = true; break;
case kind::SELECT: return "select";
case kind::STORE: return "store";
case kind::ARRAY_TYPE: return "Array";
+ case kind::PARTIAL_SELECT_0: return "partial_select_0";
+ case kind::PARTIAL_SELECT_1: return "partial_select_1";
// bv theory
case kind::BITVECTOR_CONCAT: return "concat";
--- /dev/null
+/********************* */
+/*! \file arith_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/arith_proof.h"
+#include "theory/arith/theory_arith.h"
+#include <stack>
+
+namespace CVC4 {
+
+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("pf::arith") << "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("pf::arith") << "+ 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 ProofArith::toStream(std::ostream& out) {
+ Trace("theory-proof-debug") << "; Print Arith proof..." << std::endl;
+ //AJR : carry this further?
+ LetMap map;
+ toStreamLFSC(out, ProofManager::getArithProof(), d_proof, map);
+}
+
+void ProofArith::toStreamLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, const LetMap& map) {
+ Debug("lfsc-arith") << "Printing arith proof in LFSC : " << std::endl;
+ pf->debug_print("lfsc-arith");
+ Debug("lfsc-arith") << std::endl;
+ toStreamRecLFSC( out, tp, pf, 0, map );
+}
+
+Node ProofArith::toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, unsigned tb, const LetMap& map) {
+ Debug("pf::arith") << std::endl << std::endl << "toStreamRecLFSC called. tb = " << tb << " . proof:" << std::endl;
+ pf->debug_print("pf::arith");
+ Debug("pf::arith") << std::endl;
+
+ if(tb == 0) {
+ Assert(pf->d_id == theory::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 = theory::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==theory::eq::MERGED_THROUGH_CONGRUENCE && pf->d_children[i]->d_node.isNull()) {
+ Debug("pf::arith") << "Handling congruence over equalities" << std::endl;
+
+ // Gather the sequence of consecutive congruence closures.
+ std::vector<const theory::eq::EqProof *> congruenceClosures;
+ unsigned count;
+ Debug("pf::arith") << "Collecting congruence sequence" << std::endl;
+ for (count = 0;
+ i + count < pf->d_children.size() &&
+ pf->d_children[i + count]->d_id==theory::eq::MERGED_THROUGH_CONGRUENCE &&
+ pf->d_children[i + count]->d_node.isNull();
+ ++count) {
+ Debug("pf::arith") << "Found a congruence: " << std::endl;
+ pf->d_children[i+count]->debug_print("pf::arith");
+ congruenceClosures.push_back(pf->d_children[i+count]);
+ }
+
+ Debug("pf::arith") << "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("pf::arith") << "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("pf::arith") << "Target does not appear after" << std::endl;
+ targetAppearsAfter = false;
+ }
+
+ // Assert that we have precisely one target clause.
+ Assert(targetAppearsBefore != targetAppearsAfter);
+
+ // Begin breaking up the congruences and ordering the equalities correctly.
+ std::vector<theory::eq::EqProof *> orderedEqualities;
+
+
+ // Insert target clause first.
+ if (targetAppearsBefore) {
+ orderedEqualities.push_back(pf->d_children[i - 1]);
+ // The target has already been added to subTrans; remove it.
+ subTrans.d_children.pop_back();
+ } else {
+ orderedEqualities.push_back(pf->d_children[i + count]);
+ }
+
+ // Start with the congruence closure closest to the target clause, and work our way back/forward.
+ if (targetAppearsBefore) {
+ for (unsigned j = 0; j < count; ++j) {
+ if (pf->d_children[i + j]->d_children[0]->d_id != theory::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 != theory::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 != theory::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 != theory::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("pf::arith") << "\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("pf::arith") << "\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("pf::arith") << "\nhave proven: " << n1 << std::endl;
+ Debug("pf::arith") << "n2 is " << n2[0] << std::endl;
+
+ if (n2[0].getNumChildren() > 0) { Debug("pf::arith") << "\nn2[0]: " << n2[0][0] << std::endl; }
+ if (n1.getNumChildren() > 1) { Debug("pf::arith") << "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 theory::eq::MERGED_THROUGH_CONGRUENCE: {
+ Debug("pf::arith") << "\nok, looking at congruence:\n";
+ pf->debug_print("pf::arith");
+ std::stack<const theory::eq::EqProof*> stk;
+ for(const theory::eq::EqProof* pf2 = pf; pf2->d_id == theory::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 != theory::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 == theory::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("pf::arith") << "\nok, in FIRST cong[" << stk.size() << "]" << "\n";
+ pf2->debug_print("pf::arith");
+ Debug("pf::arith") << "looking at " << pf2->d_node << "\n";
+ Debug("pf::arith") << " " << n1 << "\n";
+ Debug("pf::arith") << " " << n2 << "\n";
+ int side = 0;
+ if(match(pf2->d_node, n1[0])) {
+ //if(tb == 1) {
+ Debug("pf::arith") << "SIDE IS 0\n";
+ //}
+ side = 0;
+ } else {
+ //if(tb == 1) {
+ Debug("pf::arith") << "SIDE IS 1\n";
+ //}
+ if(!match(pf2->d_node, n1[1])) {
+ Debug("pf::arith") << "IN BAD CASE, our first subproof is\n";
+ pf2->d_children[0]->debug_print("pf::arith");
+ }
+ 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("pf::arith") << "pf2->d_node " << pf2->d_node << std::endl;
+ Debug("pf::arith") << "b1.getNumChildren() " << b1.getNumChildren() << std::endl;
+ Debug("pf::arith") << "n1 " << n1 << std::endl;
+ Debug("pf::arith") << "n2 " << n2 << std::endl;
+ Debug("pf::arith") << "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("pf::arith") << "\nMORE TO DO\n";
+ }
+ pf2 = stk.top();
+ stk.pop();
+ Assert(pf2->d_id == theory::eq::MERGED_THROUGH_CONGRUENCE);
+ out << " ";
+ ss.str("");
+ n2 = toStreamRecLFSC(ss, tp, pf2->d_children[1], tb + 1, map);
+ Debug("pf::arith") << "\nok, in cong[" << stk.size() << "]" << "\n";
+ Debug("pf::arith") << "looking at " << pf2->d_node << "\n";
+ Debug("pf::arith") << " " << n1 << "\n";
+ Debug("pf::arith") << " " << n2 << "\n";
+ Debug("pf::arith") << " " << b1 << "\n";
+ Debug("pf::arith") << " " << 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("pf::arith") << "at end assert, got " << pf2->d_node << " and " << n1 << std::endl;
+ if(pf2->d_node.getKind() == kind::PARTIAL_APPLY_UF) {
+ Assert(n1 == pf2->d_node);
+ }
+ if(n1.getOperator().getType().getNumChildren() == n1.getNumChildren() + 1) {
+ if(ProofManager::currentPM()->hasOp(n1.getOperator())) {
+ b1.clear(ProofManager::currentPM()->lookupOp(n2.getOperator()).getConst<Kind>());
+ } else {
+ b1.clear(kind::APPLY_UF);
+ b1 << n1.getOperator();
+ }
+ b1.append(n1.begin(), n1.end());
+ n1 = b1;
+ Debug("pf::arith") << "at[2] end assert, got " << pf2->d_node << " and " << n1 << std::endl;
+ if(pf2->d_node.getKind() == kind::APPLY_UF) {
+ Assert(n1 == pf2->d_node);
+ }
+ }
+ if(n2.getOperator().getType().getNumChildren() == n2.getNumChildren() + 1) {
+ if(ProofManager::currentPM()->hasOp(n2.getOperator())) {
+ b2.clear(ProofManager::currentPM()->lookupOp(n2.getOperator()).getConst<Kind>());
+ } else {
+ b2.clear(kind::APPLY_UF);
+ b2 << n2.getOperator();
+ }
+ b2.append(n2.begin(), n2.end());
+ n2 = b2;
+ }
+ Node n = (side == 0 ? eqNode(n1, n2) : eqNode(n2, n1));
+ if(tb == 1) {
+ Debug("pf::arith") << "\ncong proved: " << n << "\n";
+ }
+ return n;
+ }
+
+ case theory::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 theory::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 theory::eq::MERGED_THROUGH_TRANS: {
+ Assert(!pf->d_node.isNull());
+ Assert(pf->d_children.size() >= 2);
+ std::stringstream ss;
+ Debug("pf::arith") << "\ndoing trans proof[[\n";
+ pf->debug_print("pf::arith");
+ Debug("pf::arith") << "\n";
+ Node n1 = toStreamRecLFSC(ss, tp, pf->d_children[0], tb + 1, map);
+ Debug("pf::arith") << "\ndoing trans proof, got n1 " << n1 << "\n";
+ if(tb == 1) {
+ Debug("pf::arith") << "\ntrans proof[0], got n1 " << n1 << "\n";
+ }
+
+ bool identicalEqualities = false;
+ bool evenLengthSequence;
+ Node nodeAfterEqualitySequence;
+
+ std::map<size_t, Node> childToStream;
+
+ for(size_t i = 1; i < pf->d_children.size(); ++i) {
+ std::stringstream ss1(ss.str()), ss2;
+ ss.str("");
+
+ // It is possible that we've already converted the i'th child to stream. If so,
+ // use previously stored result. Otherwise, convert and store.
+ Node n2;
+ if (childToStream.find(i) != childToStream.end())
+ n2 = childToStream[i];
+ else {
+ n2 = toStreamRecLFSC(ss2, tp, pf->d_children[i], tb + 1, map);
+ childToStream[i] = n2;
+ }
+
+ // 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("pf::arith") << "Detected identical equalities: " << std::endl << "\t" << n1 << std::endl;
+
+ if (!identicalEqualities) {
+ // The sequence of identical equalities has started just now
+ identicalEqualities = true;
+
+ Debug("pf::arith") << "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("pf::arith") << "Equality sequence of even length" << std::endl;
+ Debug("pf::arith") << "n1 is: " << n1 << std::endl;
+ Debug("pf::arith") << "n2 is: " << n2 << std::endl;
+ Debug("pf::arith") << "pf-d_node is: " << pf->d_node << std::endl;
+ Debug("pf::arith") << "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("pf::arith") << "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("pf::arith") << "Error: even length sequence, but I don't know which hand to keep!" << std::endl;
+ Assert(false);
+ }
+ }
+
+ ss << ")";
+
+ } else {
+ Debug("pf::arith") << "Equality sequence length is odd!" << std::endl;
+ ss.str(ss1.str());
+ }
+
+ Debug("pf::arith") << "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("pf::arith") << "\ndoing trans proof, got n2 " << n2 << "\n";
+ if(tb == 1) {
+ Debug("pf::arith") << "\ntrans proof[" << i << "], got n2 " << n2 << "\n";
+ Debug("pf::arith") << (n2.getKind() == kind::EQUAL || n2.getKind() == kind::IFF) << "\n";
+
+ if ((n1.getNumChildren() >= 2) && (n2.getNumChildren() >= 2)) {
+ Debug("pf::arith") << n1[0].getId() << " " << n1[1].getId() << " / " << n2[0].getId() << " " << n2[1].getId() << "\n";
+ Debug("pf::arith") << n1[0].getId() << " " << n1[0] << "\n";
+ Debug("pf::arith") << n1[1].getId() << " " << n1[1] << "\n";
+ Debug("pf::arith") << n2[0].getId() << " " << n2[0] << "\n";
+ Debug("pf::arith") << n2[1].getId() << " " << n2[1] << "\n";
+ Debug("pf::arith") << (n1[0] == n2[0]) << "\n";
+ Debug("pf::arith") << (n1[1] == n2[1]) << "\n";
+ Debug("pf::arith") << (n1[0] == n2[1]) << "\n";
+ Debug("pf::arith") << (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("pf::arith") << "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("pf::arith") << "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("pf::arith") << "case 3\n"; }
+ n1 = eqNode(n2[0], n1[1]);
+ ss << ss2.str() << " " << ss1.str();
+ if(tb == 1) { Debug("pf::arith") << "++ proved " << n1 << "\n"; }
+ } else if(n1[1] == n2[0]) {
+ if(tb == 1) { Debug("pf::arith") << "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("pf::arith",0);
+ //toStreamRec(Warning.getStream(), pf, 0);
+ Warning() << "\n\n";
+ Unreachable();
+ }
+ Debug("pf::arith") << "++ 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("pf::arith") << "\n++ trans proof done, have proven " << n1 << std::endl;
+ return n1;
+ }
+
+ default:
+ Assert(!pf->d_node.isNull());
+ Assert(pf->d_children.empty());
+ Debug("pf::arith") << "theory proof: " << pf->d_node << " by rule " << int(pf->d_id) << std::endl;
+ AlwaysAssert(false);
+ return pf->d_node;
+ }
+}
+
+ArithProof::ArithProof(theory::arith::TheoryArith* arith, TheoryProofEngine* pe)
+ : TheoryProof(arith, pe), d_realMode(false)
+{}
+
+void ArithProof::registerTerm(Expr term) {
+ Debug("pf::arith") << "Arith register term: " << term << ". Kind: " << term.getKind()
+ << ". Type: " << term.getType() << std::endl;
+
+ if (term.getType().isReal() && !term.getType().isInteger()) {
+ Debug("pf::arith") << "Entering real mode" << std::endl;
+ d_realMode = true;
+ }
+
+ // recursively declare all other terms
+ for (unsigned i = 0; i < term.getNumChildren(); ++i) {
+ // could belong to other theories
+ d_proofEngine->registerTerm(term[i]);
+ }
+}
+
+void LFSCArithProof::printOwnedTerm(Expr term, std::ostream& os, const LetMap& map) {
+ Debug("pf::arith") << "Arith print term: " << term << ". Kind: " << term.getKind()
+ << ". Type: " << term.getType()
+ << ". Number of children: " << term.getNumChildren() << std::endl;
+
+ // !d_realMode <--> term.getType().isInteger()
+
+ Assert (theory::Theory::theoryOf(term) == theory::THEORY_ARITH);
+ switch (term.getKind()) {
+
+ case kind::CONST_RATIONAL: {
+ Assert (term.getNumChildren() == 0);
+ Assert (term.getType().isInteger() || term.getType().isReal());
+
+ const Rational& r = term.getConst<Rational>();
+ bool neg = (r < 0);
+
+ os << (!d_realMode ? "(a_int " : "(a_real ");
+
+ if (neg) {
+ os << "(~ ";
+ }
+
+ if (!d_realMode) {
+ os << r.abs();
+ } else {
+ os << r.abs().getNumerator();
+ os << "/";
+ os << r.getDenominator();
+ }
+
+ if (neg) {
+ os << ") ";
+ }
+
+ os << ") ";
+ return;
+ }
+
+ case kind::UMINUS: {
+ Assert (term.getNumChildren() == 1);
+ Assert (term.getType().isInteger() || term.getType().isReal());
+ os << (!d_realMode ? "(u-_Int " : "(u-_Real ");
+ d_proofEngine->printBoundTerm(term[0], os, map);
+ os << ") ";
+ return;
+ }
+
+ case kind::PLUS: {
+ Assert (term.getNumChildren() >= 2);
+
+ std::stringstream paren;
+ for (unsigned i = 0; i < term.getNumChildren() - 1; ++i) {
+ os << (!d_realMode ? "(+_Int " : "(+_Real ");
+ d_proofEngine->printBoundTerm(term[i], os, map);
+ os << " ";
+ paren << ") ";
+ }
+
+ d_proofEngine->printBoundTerm(term[term.getNumChildren() - 1], os, map);
+ os << paren.str();
+ return;
+ }
+
+ case kind::MINUS: {
+ Assert (term.getNumChildren() >= 2);
+
+ std::stringstream paren;
+ for (unsigned i = 0; i < term.getNumChildren() - 1; ++i) {
+ os << (!d_realMode ? "(-_Int " : "(-_Real ");
+ d_proofEngine->printBoundTerm(term[i], os, map);
+ os << " ";
+ paren << ") ";
+ }
+
+ d_proofEngine->printBoundTerm(term[term.getNumChildren() - 1], os, map);
+ os << paren.str();
+ return;
+ }
+
+ case kind::MULT: {
+ Assert (term.getNumChildren() >= 2);
+
+ std::stringstream paren;
+ for (unsigned i = 0; i < term.getNumChildren() - 1; ++i) {
+ os << (!d_realMode ? "(*_Int " : "(*_Real ");
+ d_proofEngine->printBoundTerm(term[i], os, map);
+ os << " ";
+ paren << ") ";
+ }
+
+ d_proofEngine->printBoundTerm(term[term.getNumChildren() - 1], os, map);
+ os << paren.str();
+ return;
+ }
+
+ case kind::DIVISION:
+ case kind::DIVISION_TOTAL: {
+ Assert (term.getNumChildren() >= 2);
+
+ std::stringstream paren;
+ for (unsigned i = 0; i < term.getNumChildren() - 1; ++i) {
+ os << (!d_realMode ? "(/_Int " : "(/_Real ");
+ d_proofEngine->printBoundTerm(term[i], os, map);
+ os << " ";
+ paren << ") ";
+ }
+
+ d_proofEngine->printBoundTerm(term[term.getNumChildren() - 1], os, map);
+ os << paren.str();
+ return;
+ }
+
+ case kind::GT:
+ Assert (term.getNumChildren() == 2);
+ os << (!d_realMode ? "(>_Int " : "(>_Real ");
+ d_proofEngine->printBoundTerm(term[0], os, map);
+ os << " ";
+ d_proofEngine->printBoundTerm(term[1], os, map);
+ os << ") ";
+ return;
+
+ case kind::GEQ:
+ Assert (term.getNumChildren() == 2);
+ os << (!d_realMode ? "(>=_Int " : "(>=_Real ");
+ d_proofEngine->printBoundTerm(term[0], os, map);
+ os << " ";
+ d_proofEngine->printBoundTerm(term[1], os, map);
+ os << ") ";
+ return;
+
+ case kind::LT:
+ Assert (term.getNumChildren() == 2);
+ os << (!d_realMode ? "(<_Int " : "(<_Real ");
+ d_proofEngine->printBoundTerm(term[0], os, map);
+ os << " ";
+ d_proofEngine->printBoundTerm(term[1], os, map);
+ os << ") ";
+ return;
+
+ case kind::LEQ:
+ Assert (term.getNumChildren() == 2);
+ os << (!d_realMode ? "(<=_Int " : "(<=_Real ");
+ d_proofEngine->printBoundTerm(term[0], os, map);
+ os << " ";
+ d_proofEngine->printBoundTerm(term[1], os, map);
+ os << ") ";
+ return;
+
+ default:
+ Debug("pf::arith") << "Default printing of term: " << term << std::endl;
+ os << term;
+ return;
+ }
+}
+
+void LFSCArithProof::printOwnedSort(Type type, std::ostream& os) {
+ Debug("pf::arith") << "Arith print sort: " << type << std::endl;
+
+ if (type.isInteger() && d_realMode) {
+ // If in "real mode", don't use type Int for, e.g., equality.
+ os << "Real ";
+ } else {
+ os << type << " ";
+ }
+}
+
+void LFSCArithProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren) {
+ os << " ;; Arith Theory Lemma \n;;";
+ for (unsigned i = 0; i < lemma.size(); ++i) {
+ os << lemma[i] <<" ";
+ }
+ os <<"\n";
+ //os << " (clausify_false trust)";
+ ArithProof::printTheoryLemmaProof( lemma, os, paren );
+}
+
+void LFSCArithProof::printSortDeclarations(std::ostream& os, std::ostream& paren) {
+}
+
+void LFSCArithProof::printTermDeclarations(std::ostream& os, std::ostream& paren) {
+}
+
+void LFSCArithProof::printDeferredDeclarations(std::ostream& os, std::ostream& paren) {
+ // Nothing to do here at this point.
+}
+
+} /* CVC4 namespace */
--- /dev/null
+/********************* */
+/*! \file arith_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 Arith proof
+ **
+ ** Arith proof
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__ARITH__PROOF_H
+#define __CVC4__ARITH__PROOF_H
+
+#include "expr/expr.h"
+#include "proof/proof_manager.h"
+#include "proof/theory_proof.h"
+#include "theory/uf/equality_engine.h"
+
+namespace CVC4 {
+
+//proof object outputted by TheoryArith
+class ProofArith : public Proof {
+private:
+ static Node toStreamRecLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, unsigned tb, const LetMap& map);
+public:
+ ProofArith( 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 arith {
+class TheoryArith;
+}
+}
+
+typedef __gnu_cxx::hash_set<Type, TypeHashFunction > TypeSet;
+
+
+class ArithProof : public TheoryProof {
+protected:
+ // std::map<Expr, std::string> d_constRationalString; // all the variable/function declarations
+
+ // TypeSet d_sorts; // all the uninterpreted sorts in this theory
+ // ExprSet d_declarations; // all the variable/function declarations
+
+ bool d_realMode;
+
+public:
+ ArithProof(theory::arith::TheoryArith* arith, TheoryProofEngine* proofEngine);
+
+ virtual void registerTerm(Expr term);
+};
+
+class LFSCArithProof : public ArithProof {
+public:
+ LFSCArithProof(theory::arith::TheoryArith* arith, TheoryProofEngine* proofEngine)
+ : ArithProof(arith, proofEngine)
+ {}
+ virtual void printOwnedTerm(Expr term, std::ostream& os, const LetMap& map);
+ virtual void printOwnedSort(Type type, std::ostream& os);
+ virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren);
+ virtual void printSortDeclarations(std::ostream& os, std::ostream& paren);
+ virtual void printTermDeclarations(std::ostream& os, std::ostream& paren);
+ virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren);
+};
+
+
+}/* CVC4 namespace */
+
+#endif /* __CVC4__ARITH__PROOF_H */
--- /dev/null
+/********************* */
+/*! \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/array_proof.h"
+#include "theory/arrays/theory_arrays.h"
+#include <stack>
+
+namespace CVC4 {
+
+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;
+ Debug("pf::array") << "+ match: step 1" << 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()) {
+ if (!((n1.getKind() == kind::SELECT && n2.getKind() == kind::PARTIAL_SELECT_0) ||
+ (n1.getKind() == kind::SELECT && n2.getKind() == kind::PARTIAL_SELECT_1) ||
+ (n1.getKind() == kind::PARTIAL_SELECT_1 && n2.getKind() == kind::SELECT) ||
+ (n1.getKind() == kind::PARTIAL_SELECT_1 && n2.getKind() == kind::PARTIAL_SELECT_0) ||
+ (n1.getKind() == kind::PARTIAL_SELECT_0 && n2.getKind() == kind::SELECT) ||
+ (n1.getKind() == kind::PARTIAL_SELECT_0 && n2.getKind() == kind::PARTIAL_SELECT_1)
+ )) {
+ return false;
+ }
+ }
+
+ for(size_t i = 0; i < n1.getNumChildren() && i < n2.getNumChildren(); ++i) {
+ if(n1[i] != n2[i]) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void ProofArray::toStream(std::ostream& out) {
+ Trace("pf::array") << "; Print Array proof..." << std::endl;
+ //AJR : carry this further?
+ LetMap map;
+ toStreamLFSC(out, ProofManager::getArrayProof(), d_proof, map);
+ Debug("pf::array") << "; Print Array proof done!" << std::endl;
+}
+
+void ProofArray::toStreamLFSC(std::ostream& out, TheoryProof* tp, theory::eq::EqProof* pf, const LetMap& map) {
+ Debug("pf::array") << "Printing array proof in LFSC : " << std::endl;
+ pf->debug_print("pf::array");
+ Debug("pf::array") << std::endl;
+ toStreamRecLFSC( out, tp, pf, 0, map );
+ Debug("pf::array") << "Printing array proof in LFSC DONE" << std::endl;
+}
+
+void ProofArray::registerSkolem(Node equality, Node skolem) {
+ d_nodeToSkolem[equality] = skolem;
+}
+
+Node ProofArray::toStreamRecLFSC(std::ostream& out,
+ TheoryProof* tp,
+ theory::eq::EqProof* pf,
+ unsigned tb,
+ const LetMap& map) {
+
+ Debug("pf::array") << std::endl << std::endl << "toStreamRecLFSC called. tb = " << tb << " . proof:" << std::endl;
+ pf->debug_print("pf::array");
+ Debug("pf::array") << std::endl;
+
+ if(tb == 0) {
+ Assert(pf->d_id == theory::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 = theory::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==theory::eq::MERGED_THROUGH_CONGRUENCE && pf->d_children[i]->d_node.isNull()) {
+ Debug("pf::array") << "Handling congruence over equalities" << std::endl;
+
+ // Gather the sequence of consecutive congruence closures.
+ std::vector<const theory::eq::EqProof *> congruenceClosures;
+ unsigned count;
+ Debug("pf::array") << "Collecting congruence sequence" << std::endl;
+ for (count = 0;
+ i + count < pf->d_children.size() &&
+ pf->d_children[i + count]->d_id==theory::eq::MERGED_THROUGH_CONGRUENCE &&
+ pf->d_children[i + count]->d_node.isNull();
+ ++count) {
+ Debug("pf::array") << "Found a congruence: " << std::endl;
+ pf->d_children[i+count]->debug_print("pf::array");
+ congruenceClosures.push_back(pf->d_children[i+count]);
+ }
+
+ Debug("pf::array") << "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("pf::array") << "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("pf::array") << "Target does not appear after" << std::endl;
+ targetAppearsAfter = false;
+ }
+
+ // Assert that we have precisely one target clause.
+ Assert(targetAppearsBefore != targetAppearsAfter);
+
+ // Begin breaking up the congruences and ordering the equalities correctly.
+ std::vector<theory::eq::EqProof *> orderedEqualities;
+
+ // Insert target clause first.
+ if (targetAppearsBefore) {
+ orderedEqualities.push_back(pf->d_children[i - 1]);
+ // The target has already been added to subTrans; remove it.
+ subTrans.d_children.pop_back();
+ } else {
+ orderedEqualities.push_back(pf->d_children[i + count]);
+ }
+
+ // Start with the congruence closure closest to the target clause, and work our way back/forward.
+ if (targetAppearsBefore) {
+ for (unsigned j = 0; j < count; ++j) {
+ if (pf->d_children[i + j]->d_children[0]->d_id != theory::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 != theory::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 != theory::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 != theory::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, ss2;
+ //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);
+ Debug("mgdx") << "\nhave proven: " << n1 << std::endl;
+ Debug("mgdx") << "n2 is " << n2 << std::endl;
+ Debug("mgdx") << "n2->d_id is " << pf->d_children[neg]->d_id << std::endl;
+ Debug("mgdx") << "n2[0] 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 (pf->d_children[neg]->d_id == theory::eq::MERGED_ARRAYS_EXT) {
+ // The negative node was created by an EXT rule; e.g. it is a[k]!=b[k], due to a!=b.
+
+ // (clausify_false (contra _ .gl2 (or_elim_1 _ _ .gl1 FIXME))))))) (\ .glemc6
+
+ out << "(clausify_false (contra _ ";
+ out << ss.str();
+
+ toStreamRecLFSC(ss2, tp, pf->d_children[neg], 1, map);
+
+ out << " ";
+ out << ss2.str();
+ out << "))";
+
+ } else {
+ // The negative node is, e.g., a pure equality
+ out << "(clausify_false (contra _ ";
+
+ 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();
+ }
+ Debug("pf::array") << "ArrayProof::toStream: getLitName( " << n2[0] << " ) = " <<
+ ProofManager::getLitName(n2[0]) << std::endl;
+
+ out << " " << ProofManager::getLitName(n2[0]) << "))" << std::endl;
+ }
+ }
+
+ return Node();
+ }
+
+ switch(pf->d_id) {
+ case theory::eq::MERGED_THROUGH_CONGRUENCE: {
+ Debug("mgd") << "\nok, looking at congruence:\n";
+ pf->debug_print("mgd");
+ std::stack<const theory::eq::EqProof*> stk;
+ for(const theory::eq::EqProof* pf2 = pf; pf2->d_id == theory::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::PARTIAL_SELECT_0 ||
+ pf2->d_node.getKind() == kind::PARTIAL_SELECT_1 ||
+ 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 != theory::eq::MERGED_THROUGH_CONGRUENCE);
+ // NodeBuilder<> b1(kind::PARTIAL_APPLY_UF), b2(kind::PARTIAL_APPLY_UF);
+ NodeBuilder<> b1, b2;
+
+ const theory::eq::EqProof* pf2 = stk.top();
+ stk.pop();
+ Assert(pf2->d_id == theory::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");
+ // Temp
+ Debug("mgd") << "n1 is a proof for: " << pf2->d_children[0]->d_node << ". It is: " << n1 << std::endl;
+ Debug("mgd") << "n2 is a proof for: " << pf2->d_children[1]->d_node << ". It is: " << n2 << std::endl;
+ //
+ 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])) {
+ Debug("mgd") << "SIDE IS 0\n";
+ side = 0;
+ } else {
+ 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::PARTIAL_SELECT_1 ||
+ n1[side].getKind() == kind::STORE) {
+ if(n1[side].getKind() == kind::APPLY_UF || n1[side].getKind() == kind::PARTIAL_APPLY_UF) {
+ b1 << kind::PARTIAL_APPLY_UF;
+ b1 << n1[side].getOperator();
+ } else if (n1[side].getKind() == kind::SELECT || n1[side].getKind() == kind::PARTIAL_SELECT_1) {
+ // b1 << n1[side].getKind();
+ b1 << kind::SELECT;
+ } else {
+ b1 << kind::PARTIAL_APPLY_UF;
+ b1 << ProofManager::currentPM()->mkOp(n1[side].getOperator());
+ }
+ b1.append(n1[side].begin(), n1[side].end());
+ }
+ else if (n1[side].getKind() == kind::PARTIAL_SELECT_0) {
+ b1 << kind::PARTIAL_SELECT_1;
+ } else {
+ b1 << n1[side];
+ }
+
+ if(n1[1-side].getKind() == kind::PARTIAL_APPLY_UF ||
+ n1[1-side].getKind() == kind::APPLY_UF ||
+ n1[1-side].getKind() == kind::SELECT ||
+ n1[1-side].getKind() == kind::PARTIAL_SELECT_1 ||
+ n1[1-side].getKind() == kind::STORE) {
+ if(n1[1-side].getKind() == kind::APPLY_UF ||
+ n1[1-side].getKind() == kind::PARTIAL_APPLY_UF) {
+ b2 << kind::PARTIAL_APPLY_UF;
+ b2 << n1[1-side].getOperator();
+ } else if (n1[1-side].getKind() == kind::SELECT || n1[1-side].getKind() == kind::PARTIAL_SELECT_1) {
+ // b2 << n1[1-side].getKind();
+ b2 << kind::SELECT;
+ } else {
+ b2 << kind::PARTIAL_APPLY_UF;
+ b2 << ProofManager::currentPM()->mkOp(n1[1-side].getOperator());
+ }
+ b2.append(n1[1-side].begin(), n1[1-side].end());
+ } else if (n1[1-side].getKind() == kind::PARTIAL_SELECT_0) {
+ b2 << kind::PARTIAL_SELECT_1;
+ } 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;
+ // These debug prints can cause a problem if we're constructing a SELECT node and it doesn't have enough
+ // children yet.
+ // Debug("mgd") << "b1 " << b1 << std::endl;
+ // Debug("mgd") << "b2 " << b2 << std::endl;
+ Debug("mgd") << "side " << side << std::endl;
+ Debug("mgd") << "pf2->d_node's number of children: " << pf2->d_node.getNumChildren() << std::endl;
+ Debug("mgd") << "pf2->d_node's meta kind: " << pf2->d_node.getMetaKind() << std::endl;
+ Debug("mgd") << "Is this meta kind considered parameterized? " << (pf2->d_node.getMetaKind() == kind::metakind::PARAMETERIZED) << std::endl;
+
+ if(pf2->d_node[b1.getNumChildren() +
+ (n1[side].getKind() == kind::PARTIAL_SELECT_0 ? 1 : 0) +
+ (n1[side].getKind() == kind::PARTIAL_SELECT_1 ? 1 : 0) -
+ (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() +
+ (n1[side].getKind() == kind::PARTIAL_SELECT_0 ? 1 : 0) +
+ (n1[side].getKind() == kind::PARTIAL_SELECT_1 ? 1 : 0) -
+ (pf2->d_node.getMetaKind() == kind::metakind::PARAMETERIZED ? 0 : 1)] == n2[1-side]);
+ b1 << n2[1-side];
+ b2 << n2[side];
+ out << "(symm _ _ _ " << ss.str() << ")";
+ }
+
+ Debug("mgd") << "After first insertion:" << std::endl;
+ Debug("mgd") << "b1 " << b1 << std::endl;
+ Debug("mgd") << "b2 " << b2 << std::endl;
+
+ out << ")";
+ while(!stk.empty()) {
+
+ Debug("mgd") << "\nMORE TO DO\n";
+
+ pf2 = stk.top();
+ stk.pop();
+ Assert(pf2->d_id == theory::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!" << std::endl
+ << "pf2->d_node = " << pf2->d_node << std::endl
+ << "n1 (assigned from b1) = " << n1 << std::endl
+ << "n2 (assigned from b2) = " << n2 << std::endl;
+
+ if(pf2->d_node.getKind() == kind::PARTIAL_APPLY_UF) {
+ Assert(n1 == pf2->d_node);
+ }
+
+ Debug("mgd") << "n1.getOperator().getType().getNumChildren() = "
+ << n1.getOperator().getType().getNumChildren() << std::endl;
+ Debug("mgd") << "n1.getNumChildren() + 1 = "
+ << n1.getNumChildren() + 1 << std::endl;
+
+ Assert(!((n1.getKind() == kind::PARTIAL_SELECT_0 && n1.getNumChildren() == 2)));
+ if (n1.getKind() == kind::PARTIAL_SELECT_1 && n1.getNumChildren() == 2) {
+ Debug("mgd") << "Finished a SELECT. Updating.." << std::endl;
+ b1.clear(kind::SELECT);
+ b1.append(n1.begin(), n1.end());
+ n1 = b1;
+ Debug("mgd") << "New n1: " << n1 << std::endl;
+ // } else if (n1.getKind() == kind::PARTIAL_SELECT_0 && n1.getNumChildren() == 1) {
+ // Debug("mgd") << "Finished a PARTIAL_SELECT_1. Updating.." << std::endl;
+ // b1.clear(kind::PARTIAL_SELECT_1);
+ // b1.append(n1.begin(), n1.end());
+ // n1 = b1;
+ // Debug("mgd") << "New n1: " << n1 << std::endl;
+ // } else
+ } else if(n1.getOperator().getType().getNumChildren() == n1.getNumChildren() + 1) {
+ if(ProofManager::currentPM()->hasOp(n1.getOperator())) {
+ b1.clear(ProofManager::currentPM()->lookupOp(n2.getOperator()).getConst<Kind>());
+ } else {
+ b1.clear(kind::APPLY_UF);
+ b1 << n1.getOperator();
+ }
+ b1.append(n1.begin(), n1.end());
+ n1 = b1;
+ Debug("mgd") << "at[2] end assert, got " << pf2->d_node << " and " << n1 << std::endl;
+ if(pf2->d_node.getKind() == kind::APPLY_UF) {
+ Assert(n1 == pf2->d_node);
+ }
+ }
+
+ Debug("mgd") << "n2.getOperator().getType().getNumChildren() = "
+ << n2.getOperator().getType().getNumChildren() << std::endl;
+ Debug("mgd") << "n2.getNumChildren() + 1 = "
+ << n2.getNumChildren() + 1 << std::endl;
+
+ Assert(!((n2.getKind() == kind::PARTIAL_SELECT_0 && n2.getNumChildren() == 2)));
+ if (n2.getKind() == kind::PARTIAL_SELECT_1 && n2.getNumChildren() == 2) {
+ Debug("mgd") << "Finished a SELECT. Updating.." << std::endl;
+ b2.clear(kind::SELECT);
+ b2.append(n2.begin(), n2.end());
+ n2 = b2;
+ Debug("mgd") << "New n2: " << n2 << std::endl;
+ // } else if (n2.getKind() == kind::PARTIAL_SELECT_0 && n2.getNumChildren() == 1) {
+ // Debug("mgd") << "Finished a PARTIAL_SELECT_1. Updating.." << std::endl;
+ // b2.clear(kind::PARTIAL_SELECT_1);
+ // b2.append(n2.begin(), n2.end());
+ // n2 = b2;
+ // Debug("mgd") << "New n2: " << n2 << std::endl;
+ // } else
+ } else if(n2.getOperator().getType().getNumChildren() == n2.getNumChildren() + 1) {
+ if(ProofManager::currentPM()->hasOp(n2.getOperator())) {
+ b2.clear(ProofManager::currentPM()->lookupOp(n2.getOperator()).getConst<Kind>());
+ } else {
+ b2.clear(kind::APPLY_UF);
+ b2 << n2.getOperator();
+ }
+ b2.append(n2.begin(), n2.end());
+ n2 = b2;
+ }
+ Node n = (side == 0 ? eqNode(n1, n2) : eqNode(n2, n1));
+
+ Debug("mgdx") << "\ncong proved: " << n << "\n";
+ return n;
+ }
+
+ case theory::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 theory::eq::MERGED_THROUGH_EQUALITY:
+ Assert(!pf->d_node.isNull());
+ Assert(pf->d_children.empty());
+ Debug("pf::array") << "ArrayProof::toStream: getLitName( " << pf->d_node.negate() << " ) = " <<
+ ProofManager::getLitName(pf->d_node.negate()) << std::endl;
+ out << ProofManager::getLitName(pf->d_node.negate());
+ return pf->d_node;
+
+ case theory::eq::MERGED_THROUGH_TRANS: {
+ bool firstNeg = false;
+ bool secondNeg = false;
+
+ 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;
+
+ std::map<size_t, Node> childToStream;
+
+ for(size_t i = 1; i < pf->d_children.size(); ++i) {
+ std::stringstream ss1(ss.str()), ss2;
+ ss.str("");
+
+ // It is possible that we've already converted the i'th child to stream. If so,
+ // use previously stored result. Otherwise, convert and store.
+ Node n2;
+ if (childToStream.find(i) != childToStream.end())
+ n2 = childToStream[i];
+ else {
+ n2 = toStreamRecLFSC(ss2, tp, pf->d_children[i], tb + 1, map);
+ childToStream[i] = n2;
+ }
+
+ Debug("mgd") << "\ndoing trans proof, got (first) n2 " << n2 << "\n";
+
+ // 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("pf::array") << "Detected identical equalities: " << std::endl << "\t" << n1 << std::endl;
+
+ if (!identicalEqualities) {
+ // The sequence of identical equalities has started just now
+ identicalEqualities = true;
+
+ Debug("pf::array") << "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("pf::array") << "Equality sequence of even length" << std::endl;
+ Debug("pf::array") << "n1 is: " << n1 << std::endl;
+ Debug("pf::array") << "n2 is: " << n2 << std::endl;
+ Debug("pf::array") << "pf-d_node is: " << pf->d_node << std::endl;
+ Debug("pf::array") << "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("pf::array") << "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.
+ if (nodeAfterEqualitySequence.getKind() == kind::NOT) {
+ nodeAfterEqualitySequence = nodeAfterEqualitySequence[0];
+ }
+
+ 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("pf::array") << "Error: even length sequence, but I don't know which hand to keep!" << std::endl;
+ Assert(false);
+ }
+ }
+
+ ss << ")";
+
+ } else {
+ Debug("pf::array") << "Equality sequence length is odd!" << std::endl;
+ ss.str(ss1.str());
+ }
+
+ Debug("pf::array") << "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";
+ }
+ }
+
+ // We can hadnle one of the equalities being negative, but not both
+ Assert((n1.getKind() != kind::NOT) || (n2.getKind() != kind::NOT));
+
+ firstNeg = false;
+ secondNeg = false;
+
+ if (n1.getKind() == kind::NOT) {
+ Debug("mgdx") << "n1 is negative" << std::endl;
+ Debug("pf::array") << "n1 = " << n1 << ", n2 = " << n2 << std::endl;
+ firstNeg = true;
+ ss << "(negtrans1 _ _ _ _ ";
+ n1 = n1[0];
+ } else if (n2.getKind() == kind::NOT) {
+ Debug("mgdx") << "n2 is negative" << std::endl;
+ Debug("pf::array") << "n1 = " << n1 << ", n2 = " << n2 << std::endl;
+ secondNeg = true;
+ ss << "(negtrans2 _ _ _ _ ";
+ n2 = n2[0];
+ } else {
+ 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 << (firstNeg ? "(negsymm _ _ _ " : "(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() << (secondNeg ? " (negsymm _ _ _ " : " (symm _ _ _ " ) << ss2.str() << ")";
+ } else if(n1[0] == n2[1]) {
+ if(tb == 1) { Debug("mgdx") << "case 3\n"; }
+ if(!firstNeg && !secondNeg) {
+ n1 = eqNode(n2[0], n1[1]);
+ ss << ss2.str() << " " << ss1.str();
+ } else if (firstNeg) {
+ n1 = eqNode(n1[1], n2[0]);
+ ss << " (negsymm _ _ _ " << ss1.str() << ") (symm _ _ _ " << ss2.str() << ")";
+ } else {
+ Assert(secondNeg);
+ n1 = eqNode(n1[1], n2[0]);
+ ss << " (symm _ _ _ " << ss1.str() << ") (negsymm _ _ _ " << ss2.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 << (firstNeg ? "(negsymm _ _ _ " : "(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 << (secondNeg ? "(negsymm _ _ _ " : "(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 << ")";
+
+ if (firstNeg || secondNeg) {
+ n1 = (n1.getKind() == kind::NOT) ? n1[0] : n1.notNode();
+ }
+ }
+
+ out << ss.str();
+ Debug("mgd") << "\n++ trans proof done, have proven " << n1 << std::endl;
+ //return (firstNeg || secondNeg) ? n1.notNode() : n1;
+ return n1;
+ }
+
+ case theory::eq::MERGED_ARRAYS_ROW: {
+ Debug("mgd") << "row lemma: " << pf->d_node << std::endl;
+ Assert(pf->d_node.getKind() == kind::EQUAL);
+
+
+ if (pf->d_node[1].getKind() == kind::SELECT) {
+ // This is the case where ((a[i]:=t)[k] == a[k]), and the sub-proof explains why (i != k).
+ 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";
+ }
+
+ // inner index != outer index
+ // t3 is the outer index
+
+
+ Assert(pf->d_children.size() == 1);
+ std::stringstream ss;
+ Node subproof = toStreamRecLFSC(ss, tp, pf->d_children[0], tb + 1, map);
+
+ 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 << " ";
+
+ Debug("pf::array") << "pf->d_children[0]->d_node is: " << pf->d_children[0]->d_node
+ << ". t3 is: " << t3 << std::endl
+ << "subproof is: " << subproof << std::endl;
+
+ Debug("pf::array") << "Subproof is: " << ss.str() << std::endl;
+
+ if (subproof[0][1] == t3) {
+ Debug("pf::array") << "Dont need symmetry!" << std::endl;
+ out << ss.str();
+ } else {
+ Debug("pf::array") << "Need symmetry!" << std::endl;
+ out << "(negsymm _ _ _ " << ss.str() << ")";
+ }
+
+ out << ")";
+
+ return ret;
+ } else {
+ Debug("pf::array") << "In the case of NEGATIVE ROW" << std::endl;
+
+ Debug("pf::array") << "pf->d_children[0]->d_node is: " << pf->d_children[0]->d_node << std::endl;
+
+ // This is the case where (i == k), and the sub-proof explains why ((a[i]:=t)[k] != a[k])
+
+ // If we wanted to remove the need for "negativerow", we would need to prove i==k using a new satlem. We would:
+ // 1. Create a new satlem.
+ // 2. Assume that i != k
+ // 3. Apply ROW to show that ((a[i]:=t)[k] == a[k])
+ // 4. Contradict this with the fact that ((a[i]:=t)[k] != a[k]), obtaining our contradiction
+
+ TNode t1, t2, t3, t4;
+ Node ret;
+
+ // pf->d_node is an equality, i==k.
+ t1 = pf->d_node[0];
+ t2 = pf->d_node[1];
+
+ // pf->d_children[0]->d_node will have the form: (not (= (select (store a_565 i7 e_566) i1) (select a_565 i1))),
+ // or its symmetrical version.
+
+ unsigned side;
+ if (pf->d_children[0]->d_node[0][0].getKind() == kind::SELECT &&
+ pf->d_children[0]->d_node[0][0][0].getKind() == kind::STORE) {
+ side = 0;
+ } else if (pf->d_children[0]->d_node[0][1].getKind() == kind::SELECT &&
+ pf->d_children[0]->d_node[0][1][0].getKind() == kind::STORE) {
+ side = 1;
+ }
+ else {
+ Unreachable();
+ }
+
+ Debug("pf::array") << "Side is: " << side << std::endl;
+
+ // The array's index and element types will come from the subproof...
+ t3 = pf->d_children[0]->d_node[0][side][0][0];
+ t4 = pf->d_children[0]->d_node[0][side][0][2];
+ ret = pf->d_node;
+
+ Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\nt4 " << t4 << "\n";
+
+ Assert(pf->d_children.size() == 1);
+ std::stringstream ss;
+ Node subproof = toStreamRecLFSC(ss, tp, pf->d_children[0], tb + 1, map);
+
+ Debug("pf::array") << "Subproof is: " << ss.str() << std::endl;
+
+ out << "(negativerow _ _ ";
+ tp->printTerm(t1.toExpr(), out, map);
+ out << " ";
+ tp->printTerm(t2.toExpr(), out, map);
+ out << " ";
+ tp->printTerm(t3.toExpr(), out, map);
+ out << " ";
+ tp->printTerm(t4.toExpr(), out, map);
+ out << " ";
+
+
+ // if (subproof[0][1] == t3) {
+ Debug("pf::array") << "Dont need symmetry!" << std::endl;
+ out << ss.str();
+ // } else {
+ // Debug("pf::array") << "Need symmetry!" << std::endl;
+ // out << "(negsymm _ _ _ " << ss.str() << ")";
+ // }
+
+ out << ")";
+
+ // Unreachable();
+
+ return ret;
+ }
+ }
+
+ case theory::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;
+ }
+
+ case theory::eq::MERGED_ARRAYS_EXT: {
+ theory::eq::EqProof *child_proof;
+
+ Assert(pf->d_node.getKind() == kind::NOT);
+ Assert(pf->d_node[0].getKind() == kind::EQUAL);
+ Assert(pf->d_children.size() == 1);
+
+ child_proof = pf->d_children[0];
+ Assert(child_proof->d_node.getKind() == kind::NOT);
+ Assert(child_proof->d_node[0].getKind() == kind::EQUAL);
+
+ Debug("mgd") << "EXT lemma: " << pf->d_node << std::endl;
+
+ TNode t1, t2, t3;
+ t1 = child_proof->d_node[0][0];
+ t2 = child_proof->d_node[0][1];
+ t3 = pf->d_node[0][0][1];
+
+ Debug("mgd") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\n";
+
+ out << "(or_elim_1 _ _ ";
+ out << ProofManager::getLitName(child_proof->d_node[0]);
+ out << " ";
+ out << ProofManager::getArrayProof()->skolemToLiteral(t3.toExpr());
+ out << ")";
+
+ return pf->d_node;
+ }
+
+ 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;
+ }
+}
+
+ArrayProof::ArrayProof(theory::arrays::TheoryArrays* arrays, TheoryProofEngine* pe)
+ : TheoryProof(arrays, pe)
+{}
+
+void ArrayProof::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]);
+ }
+}
+
+std::string ArrayProof::skolemToLiteral(Expr skolem) {
+ Assert(d_skolemToLiteral.find(skolem) != d_skolemToLiteral.end());
+ return d_skolemToLiteral[skolem];
+}
+
+void LFSCArrayProof::printOwnedTerm(Expr term, std::ostream& os, const LetMap& map) {
+ Debug("pf::array") << std::endl << "(pf::array) LFSCArrayProof::printOwnedTerm: term = " << term << std::endl;
+
+ Assert (theory::Theory::theoryOf(term) == theory::THEORY_ARRAY);
+
+ if (theory::Theory::theoryOf(term) != theory::THEORY_ARRAY) {
+ // We can get here, for instance, if there's a (select ite ...), e.g. a non-array term
+ // hiding as a subterm of an array term. In that case, send it back to the dispatcher.
+ d_proofEngine->printBoundTerm(term, os, map);
+ return;
+ }
+
+ if (term.getKind() == kind::VARIABLE || term.getKind() == kind::SKOLEM) {
+ os << term;
+ return;
+ }
+
+ Assert ((term.getKind() == kind::SELECT) || (term.getKind() == kind::PARTIAL_SELECT_0) || (term.getKind() == kind::PARTIAL_SELECT_1) || (term.getKind() == kind::STORE));
+
+ switch (term.getKind()) {
+ case kind::SELECT:
+ Assert(term.getNumChildren() == 2);
+ os << "(apply _ _ (apply _ _ (read ";
+ printSort(ArrayType(term[0].getType()).getIndexType(), os);
+ os << " ";
+ printSort(ArrayType(term[0].getType()).getConstituentType(), os);
+ os << ") ";
+ printTerm(term[0], os, map);
+ os << ") ";
+ printTerm(term[1], os, map);
+ os << ") ";
+ return;
+
+ case kind::PARTIAL_SELECT_0:
+ Assert(term.getNumChildren() == 1);
+ os << "(read ";
+ printSort(ArrayType(term[0].getType()).getIndexType(), os);
+ os << " ";
+ printSort(ArrayType(term[0].getType()).getConstituentType(), os);
+ os << ") ";
+ return;
+
+ case kind::PARTIAL_SELECT_1:
+ Debug("pf::array") << "This branch has not beed tested yet." << std::endl;
+ Unreachable();
+
+ Assert(term.getNumChildren() == 1);
+ os << "(apply _ _ (read ";
+ printSort(ArrayType(term[0].getType()).getIndexType(), os);
+ os << " ";
+ printSort(ArrayType(term[0].getType()).getConstituentType(), os);
+ os << ") ";
+ printTerm(term[0], os, map);
+ os << ") ";
+ return;
+
+ case kind::STORE:
+ os << "(apply _ _ (apply _ _ (apply _ _ (write ";
+ printSort(ArrayType(term[0].getType()).getIndexType(), os);
+ os << " ";
+ printSort(ArrayType(term[0].getType()).getConstituentType(), os);
+ os << ") ";
+ printTerm(term[0], os, map);
+ os << ") ";
+ printTerm(term[1], os, map);
+ os << ") ";
+ printTerm(term[2], os, map);
+ os << ") ";
+ return;
+
+ default:
+ Unreachable();
+ return;
+ }
+}
+
+void LFSCArrayProof::printOwnedSort(Type type, std::ostream& os) {
+ Debug("pf::array") << std::endl << "(pf::array) LFSCArrayProof::printOwnedSort: type is: " << type << std::endl;
+ Assert (type.isArray() || type.isSort());
+ os << type <<" ";
+}
+
+void LFSCArrayProof::printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren) {
+ os << " ;; Array Theory Lemma \n;;";
+ for (unsigned i = 0; i < lemma.size(); ++i) {
+ os << lemma[i] <<" ";
+ }
+ os <<"\n";
+ //os << " (clausify_false trust)";
+ ArrayProof::printTheoryLemmaProof(lemma, os, paren);
+}
+
+void LFSCArrayProof::printSortDeclarations(std::ostream& os, std::ostream& paren) {
+ // declaring the sorts
+ Debug("pf::array") << "Arrays declaring sorts..." << std::endl;
+
+ for (TypeSet::const_iterator it = d_sorts.begin(); it != d_sorts.end(); ++it) {
+ if (!ProofManager::currentPM()->wasPrinted(*it)) {
+ os << "(% " << *it << " sort\n";
+ paren << ")";
+ ProofManager::currentPM()->markPrinted(*it);
+ }
+ }
+}
+
+void LFSCArrayProof::printTermDeclarations(std::ostream& os, std::ostream& paren) {
+ Debug("pf::array") << "Arrays declaring terms..." << std::endl;
+
+ for (ExprSet::const_iterator it = d_declarations.begin(); it != d_declarations.end(); ++it) {
+ Expr term = *it;
+
+ Assert(term.getType().isArray() || term.isVariable());
+
+ Debug("pf::array") << "LFSCArrayProof::printDeclarations: term is: " << term
+ << ". It's type is: " << term.getType()
+ << std::endl;
+
+ if (term.getType().isArray()){
+ ArrayType array_type(term.getType());
+
+ Debug("pf::array") << "LFSCArrayProof::printDeclarations: term is an array. Index type: "
+ << array_type.getIndexType()
+ << ", element type: " << array_type.getConstituentType() << std::endl;
+
+ os << "(% " << ProofManager::sanitize(term) << " ";
+ os << "(term ";
+ os << "(Array ";
+
+ printSort(array_type.getIndexType(), os);
+ os << " ";
+ printSort(array_type.getConstituentType(), os);
+
+ os << "))\n";
+ } else {
+ Assert(term.isVariable());
+ if (ProofManager::getSkolemizationManager()->isSkolem(*it)) {
+ Debug("pf::array") << "This term is a skoelm!" << std::endl;
+ d_skolemDeclarations.insert(*it);
+ } else {
+ os << "(% " << ProofManager::sanitize(term) << " ";
+ os << "(term ";
+ os << term.getType() << ")\n";
+ }
+ }
+
+ paren << ")";
+ }
+
+ Debug("pf::array") << "Declaring terms done!" << std::endl;
+}
+
+void LFSCArrayProof::printDeferredDeclarations(std::ostream& os, std::ostream& paren) {
+ Debug("pf::array") << "Array: print deferred declarations called" << std::endl;
+
+ for (ExprSet::const_iterator it = d_skolemDeclarations.begin(); it != d_skolemDeclarations.end(); ++it) {
+ Expr term = *it;
+ Node equality = ProofManager::getSkolemizationManager()->getDisequality(*it);
+
+ Debug("pf::array") << "LFSCArrayProof::printDeferredDeclarations: term is: " << *it << std::endl
+ << "It is a witness for: " << equality << std::endl;
+
+ std::ostringstream newSkolemLiteral;
+ newSkolemLiteral << ".sl" << d_skolemToLiteral.size();
+ std::string skolemLiteral = newSkolemLiteral.str();
+
+ d_skolemToLiteral[*it] = skolemLiteral;
+
+ Debug("pf::array") << "LFSCArrayProof::printDeferredDeclarations: new skolem literal is: " << skolemLiteral << std::endl;
+
+ Assert(equality.getKind() == kind::NOT);
+ Assert(equality[0].getKind() == kind::EQUAL);
+
+ Node array_one = equality[0][0];
+ Node array_two = equality[0][1];
+
+ LetMap map;
+
+ os << "(ext _ _ ";
+ printTerm(array_one.toExpr(), os, map);
+ os << " ";
+ printTerm(array_two.toExpr(), os, map);
+ os << " (\\ ";
+ printTerm(*it, os, map);
+ os << " (\\ ";
+ os << skolemLiteral.c_str();
+ os << "\n";
+
+ paren << ")))";
+ }
+}
+
+} /* CVC4 namespace */
#include "proof/proof_manager.h"
#include "proof/theory_proof.h"
#include "theory/arrays/theory_arrays.h"
+#include "theory/uf/equality_engine.h"
namespace CVC4 {
+//proof object outputted by TheoryARRAY
+class ProofArray : public Proof {
+private:
+ static Node toStreamRecLFSC(std::ostream& out, TheoryProof* tp,
+ theory::eq::EqProof* pf,
+ unsigned tb,
+ const LetMap& map);
+
+ std::hash_map<Node, Node, NodeHashFunction> d_nodeToSkolem;
+public:
+ ProofArray(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);
+
+ void registerSkolem(Node equality, Node skolem);
+};
+
namespace theory {
namespace arrays{
class TheoryArrays;
} /* namespace CVC4::theory::arrays */
} /* namespace CVC4::theory */
+typedef __gnu_cxx::hash_set<Type, TypeHashFunction > TypeSet;
+
class ArrayProof : public TheoryProof {
// TODO: whatever goes in this theory
+protected:
+ TypeSet d_sorts; // all the uninterpreted sorts in this theory
+ ExprSet d_declarations; // all the variable/function declarations
+ ExprSet d_skolemDeclarations; // all the skolem variable declarations
+ std::map<Expr, std::string> d_skolemToLiteral;
+
public:
- ArrayProof(theory::arrays::TheoryArrays* arrays, TheoryProofEngine* proofEngine)
- : TheoryProof(arrays, proofEngine)
- {}
- virtual void registerTerm(Expr term) {}
-
- virtual void printTerm(Expr term, std::ostream& os, const LetMap& map) = 0;
- virtual void printSort(Type type, std::ostream& os) = 0;
- /**
- * Print a proof for the theory lemma. Must prove
- * clause representing lemma to be used in resolution proof.
- *
- * @param lemma clausal form of lemma
- * @param os output stream
- */
- virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren) = 0;
- /**
- * Print the variable/sorts declarations for this theory.
- *
- * @param os
- * @param paren
- */
- virtual void printDeclarations(std::ostream& os, std::ostream& paren) = 0;
+ ArrayProof(theory::arrays::TheoryArrays* arrays, TheoryProofEngine* proofEngine);
+
+ std::string skolemToLiteral(Expr skolem);
+
+ virtual void registerTerm(Expr term);
};
class LFSCArrayProof : public ArrayProof {
public:
- LFSCArrayProof(theory::arrays::TheoryArrays* uf, TheoryProofEngine* proofEngine)
- : ArrayProof(uf, proofEngine)
+ LFSCArrayProof(theory::arrays::TheoryArrays* arrays, TheoryProofEngine* proofEngine)
+ : ArrayProof(arrays, proofEngine)
{}
- // TODO implement
- virtual void printTerm(Expr term, std::ostream& os, const LetMap& map) {}
- virtual void printSort(Type type, std::ostream& os) {}
- virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren) {}
- virtual void printDeclarations(std::ostream& os, std::ostream& paren) {}
+ virtual void printOwnedTerm(Expr term, std::ostream& os, const LetMap& map);
+ virtual void printOwnedSort(Type type, std::ostream& os);
+ virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren);
+ virtual void printSortDeclarations(std::ostream& os, std::ostream& paren);
+ virtual void printTermDeclarations(std::ostream& os, std::ostream& paren);
+ virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren);
};
** \todo document this file
**/
-#include "proof/bitvector_proof.h"
-
+#include "proof/bitvector_proof.h"
#include "options/bv_options.h"
#include "proof/clause_id.h"
#include "proof/proof_utils.h"
expr_confl.push_back(expr_lit);
}
Expr conflict = utils::mkSortedExpr(kind::OR, expr_confl);
- Debug("bv-proof") << "Make conflict for " << conflict << std::endl;
+ Debug("pf::bv") << "Make conflict for " << conflict << std::endl;
if (d_bbConflictMap.find(conflict) != d_bbConflictMap.end()) {
- Debug("bv-proof") << "Abort...already conflict for " << conflict << std::endl;
+ Debug("pf::bv") << "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();
ClauseId clause_id = d_resolutionProof->registerAssumptionConflict(confl);
d_bbConflictMap[conflict] = clause_id;
d_resolutionProof->endResChain(clause_id);
- Debug("bv-proof") << "BitVectorProof::endBVConflict id"<<clause_id<< " => " << conflict << "\n";
+ Debug("pf::bv") << "BitVectorProof::endBVConflict id"<<clause_id<< " => " << conflict << "\n";
d_isAssumptionConflict = false;
}
void BitVectorProof::finalizeConflicts(std::vector<Expr>& conflicts) {
if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER) {
- Debug("bv-proof") << "Construct full proof." << std::endl;
+ Debug("pf::bv") << "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;
+ Debug("pf::bv") << "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;
+ Debug("pf::bv") << "Do not collect clauses for " << confl << std::endl;
}
}
}
-void LFSCBitVectorProof::printTerm(Expr term, std::ostream& os, const LetMap& map) {
+void LFSCBitVectorProof::printOwnedTerm(Expr term, std::ostream& os, const LetMap& map) {
+ Debug("pf::bv") << std::endl << "(pf::bv) LFSCBitVectorProof::printOwnedTerm( " << term << " ), theory is: "
+ << Theory::theoryOf(term) << std::endl;
+
Assert (Theory::theoryOf(term) == THEORY_BV);
// peel off eager bit-blasting trick
return;
}
case kind::BITVECTOR_BITOF : {
- printBitOf(term, os);
+ printBitOf(term, os, map);
return;
}
case kind::VARIABLE:
}
}
-void LFSCBitVectorProof::printBitOf(Expr term, std::ostream& os) {
+void LFSCBitVectorProof::printBitOf(Expr term, std::ostream& os, const LetMap& map) {
Assert (term.getKind() == kind::BITVECTOR_BITOF);
unsigned bit = term.getOperator().getConst<BitVectorBitOf>().bitIndex;
Expr var = term[0];
- Assert (var.getKind() == kind::VARIABLE ||
- var.getKind() == kind::SKOLEM);
- os << "(bitof " << ProofManager::sanitize(var) <<" " << bit <<")";
+
+ Debug("pf::bv") << "LFSCBitVectorProof::printBitOf( " << term << " ), "
+ << "bit = " << bit
+ << ", var = " << var << std::endl;
+
+ os << "(bitof ";
+ if (var.getKind() == kind::VARIABLE || var.getKind() == kind::SKOLEM) {
+ // If var is "simple", we can just sanitize and print
+ os << ProofManager::sanitize(var);
+ } else {
+ // If var is "complex", it can belong to another theory. Therefore, dispatch again.
+ d_proofEngine->printBoundTerm(var, os, map);
+ }
+
+ os << " " << bit << ")";
}
void LFSCBitVectorProof::printConstant(Expr term, std::ostream& os) {
os <<")";
}
-void LFSCBitVectorProof::printSort(Type type, std::ostream& os) {
+void LFSCBitVectorProof::printOwnedSort(Type type, std::ostream& os) {
+ Debug("pf::bv") << std::endl << "(pf::bv) LFSCBitVectorProof::printOwnedSort( " << type << " )" << std::endl;
+
Assert (type.isBitVector());
unsigned width = utils::getSize(type);
os << "(BitVec "<<width<<")";
ClauseId lemma_id = d_bbConflictMap[lem];
d_resolutionProof->printAssumptionsResolution(lemma_id, os, lemma_paren);
os <<lemma_paren.str();
- }else{
- Debug("bv-proof") << std::endl << "; Print non-bitblast theory conflict " << conflict << std::endl;
+ } else {
+ Unreachable(); // If we were to reach here, we would crash because BV replay is currently not supported
+ // in TheoryProof::printTheoryLemmaProof()
+
+ Debug("pf::bv") << std::endl << "; Print non-bitblast theory conflict " << conflict << std::endl;
BitVectorProof::printTheoryLemmaProof( lemma, os, paren );
}
}
-void LFSCBitVectorProof::printDeclarations(std::ostream& os, std::ostream& paren) {
+
+void LFSCBitVectorProof::printSortDeclarations(std::ostream& os, std::ostream& paren) {
+ // Nothing to do here at this point.
+}
+
+void LFSCBitVectorProof::printTermDeclarations(std::ostream& os, std::ostream& paren) {
ExprSet::const_iterator it = d_declarations.begin();
ExprSet::const_iterator end = d_declarations.end();
for (; it != end; ++it) {
}
}
+void LFSCBitVectorProof::printDeferredDeclarations(std::ostream& os, std::ostream& paren) {
+ // Nothing to do here at this point.
+}
void LFSCBitVectorProof::printTermBitblasting(Expr term, std::ostream& os) {
// TODO: once we have the operator elimination rules remove those that we
os <<" _ _ _ _ _ _ ";
}
os << getBBTermName(term[0]) <<" ";
-
+
for (unsigned i = 1; i < term.getNumChildren(); ++i) {
os << getBBTermName(term[i]);
os << ") ";
case kind::BITVECTOR_SHL :
case kind::BITVECTOR_LSHR :
case kind::BITVECTOR_ASHR : {
- // these are terms for which bit-blasting is not supported yet
+ // these are terms for which bit-blasting is not supported yet
std::ostringstream paren;
os <<"(trust_bblast_term _ ";
paren <<")";
#ifndef __CVC4__BITVECTOR__PROOF_H
#define __CVC4__BITVECTOR__PROOF_H
-//#include <cstdint>
+//#include <cstdint>
#include <ext/hash_map>
#include <ext/hash_set>
#include <iostream>
} /* namespace CVC4::theory::bv */
} /* namespace CVC4::theory */
-class CnfProof;
+class CnfProof;
} /* namespace CVC4 */
namespace CVC4 {
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;
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);
+ void printBitOf(Expr term, std::ostream& os, const LetMap& map);
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 printOwnedTerm(Expr term, std::ostream& os, const LetMap& map);
+ virtual void printOwnedSort(Type type, std::ostream& os);
virtual void printTermBitblasting(Expr term, std::ostream& os);
virtual void printAtomBitblasting(Expr term, std::ostream& os);
virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren);
- virtual void printDeclarations(std::ostream& os, std::ostream& paren);
+ virtual void printSortDeclarations(std::ostream& os, std::ostream& paren);
+ virtual void printTermDeclarations(std::ostream& os, std::ostream& paren);
+ virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren);
virtual void printBitblasting(std::ostream& os, std::ostream& paren);
virtual void printResolutionProof(std::ostream& os, std::ostream& paren);
};
#include "prop/minisat/minisat.h"
#include "prop/sat_solver_types.h"
-using namespace CVC4::prop;
-
namespace CVC4 {
-CnfProof::CnfProof(CnfStream* stream,
+CnfProof::CnfProof(prop::CnfStream* stream,
context::Context* ctx,
const std::string& name)
: d_cnfStream(stream)
, d_clauseToAssertion(ctx)
, d_assertionToProofRule(ctx)
+ , d_clauseIdToOwnerTheory(ctx)
, d_currentAssertionStack()
, d_currentDefinitionStack()
, d_clauseToDefinition(ctx)
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);
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);
+ registerExplanationLemma(clause);
}
void CnfProof::setClauseAssertion(ClauseId clause, Node expr) {
// 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);
}
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;
d_assertionToProofRule.insert(assertion, reason);
}
+void CnfProof::registerExplanationLemma(ClauseId clauseId) {
+ d_clauseIdToOwnerTheory.insert(clauseId, getExplainerTheory());
+}
+
+theory::TheoryId CnfProof::getOwnerTheory(ClauseId clause) {
+ Assert(d_clauseIdToOwnerTheory.find(clause) != d_clauseIdToOwnerTheory.end());
+ return d_clauseIdToOwnerTheory[clause];
+}
+
+
void CnfProof::setCnfDependence(Node from, Node to) {
Debug("proof:cnf") << "CnfProof::setCnfDependence "
<< "from " << from << std::endl
void CnfProof::popCurrentAssertion() {
Assert (d_currentAssertionStack.size());
-
+
Debug("proof:cnf") << "CnfProof::popCurrentAssertion "
<< d_currentAssertionStack.back() << std::endl;
-
+
d_currentAssertionStack.pop_back();
}
return d_currentAssertionStack.back();
}
+void CnfProof::setExplainerTheory(theory::TheoryId theory) {
+ d_explainerTheory = theory;
+}
+
+theory::TheoryId CnfProof::getExplainerTheory() {
+ return d_explainerTheory;
+}
+
void CnfProof::pushCurrentDefinition(Node definition) {
Debug("proof:cnf") << "CnfProof::pushCurrentDefinition "
<< definition << std::endl;
void CnfProof::popCurrentDefinition() {
Assert (d_currentDefinitionStack.size());
-
+
Debug("proof:cnf") << "CnfProof::popCurrentDefinition "
<< d_currentDefinitionStack.back() << std::endl;
-
+
d_currentDefinitionStack.pop_back();
}
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();
+ prop::SatLiteral lit = clause->operator[](i);
+ prop::SatVariable var = lit.getSatVariable();
TNode atom = getAtom(var);
if (atoms.find(atom) == atoms.end()) {
Assert (atoms.find(atom) == atoms.end());
void LFSCCnfProof::printAtomMapping(const NodeSet& atoms,
std::ostream& os,
std::ostream& paren) {
- NodeSet::const_iterator it = atoms.begin();
- NodeSet::const_iterator end = atoms.end();
+ NodeSet::const_iterator it = atoms.begin();
+ NodeSet::const_iterator end = atoms.end();
for (;it != end; ++it) {
os << "(decl_atom ";
//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 << ")))";
// paren << "))";
// return;
-
+
Assert( clause->size()>0 );
-
+
Node base_assertion = getDefinitionForClause(id);
//get the assertion for the clause id
std::stringstream os_paren;
//eliminate each one
for (int j = base_assertion.getNumChildren()-2; j >= 0; j--) {
+ Trace("cnf-pf-debug") << "; base_assertion[" << j << "] is: " << base_assertion[j]
+ << ", and its kind is: " << base_assertion[j].getKind() << std::endl ;
+
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;
- }
-
+
Trace("cnf-pf-debug") << "; child " << j << " "
- << child_base << " "
- << child_pol << " "
- << childPol[child_base] << std::endl;
-
+ << ", child base: " << child_base
+ << ", child pol: " << child_pol
+ << ", childPol[child_base] "
+ << childPol[child_base] << ", base pol: " << base_pol << std::endl;
+
std::map< Node, unsigned >::iterator itcic = childIndex.find( child_base );
if( itcic!=childIndex.end() ){
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 ){
+ // if( childPol[child_base] && base_pol ){
+
+ // Adding the below to catch a specific case where the first child of an IMPLIES is negative,
+ // in which case we need not_not introduction.
+ if (base_assertion.getKind() == kind::IMPLIES && !child_pol && base_pol) {
+ os_main << "(not_not_intro _ " << ProofManager::getLitName(lit, d_name) << ") ";
+ } else if (childPol[child_base] && base_pol) {
os_main << ProofManager::getLitName(lit, d_name) << " ";
}else{
os_main << "(not_not_intro _ " << ProofManager::getLitName(lit, d_name) << ") ";
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;
Node iatom;
Assert( assertion.getNumChildren()==1 );
iatom = assertion[0];
}
-
+
Trace("cnf-pf") << "; and/or case 2, iatom = " << iatom << std::endl;
Node e_base = iatom.getKind()==kind::NOT ? iatom[0] : iatom;
bool e_pol = iatom.getKind()!=kind::NOT;
}
}
-
-
} /* CVC4 namespace */
#ifndef __CVC4__CNF_PROOF_H
#define __CVC4__CNF_PROOF_H
-#include <ext/hash_map>
+#include <ext/hash_map>
#include <ext/hash_set>
#include <iosfwd>
typedef context::CDHashMap<ClauseId, Node> ClauseIdToNode;
typedef context::CDHashMap<Node, ProofRule, NodeHashFunction> NodeToProofRule;
+typedef context::CDHashMap<ClauseId, theory::TheoryId> ClauseIdToTheory;
class CnfProof {
protected:
/** Map from assertion to reason for adding assertion **/
NodeToProofRule d_assertionToProofRule;
+ /** Map from assertion to the theory that added this assertion **/
+ ClauseIdToTheory d_clauseIdToOwnerTheory;
+
+ /** The last theory to explain a lemma **/
+ theory::TheoryId d_explainerTheory;
+
/** Top of stack is assertion currently being converted to CNF **/
std::vector<Node> d_currentAssertionStack;
/** Top of stack is top-level fact currently being converted to CNF **/
std::vector<Node> d_currentDefinitionStack;
-
/** Map from ClauseId to the top-level fact that lead to adding this clause **/
ClauseIdToNode d_clauseToDefinition;
/** Top-level facts that follow from assertions during convertAndAssert **/
NodeSet d_definitions;
-
+
/** Map from top-level fact to facts/assertion that it follows from **/
NodeToNode d_cnfDeps;
ClauseIdSet d_explanations;
-
+
bool isDefinition(Node node);
Node getDefinitionForClause(ClauseId clause);
-
+
std::string d_name;
public:
CnfProof(CVC4::prop::CnfStream* cnfStream,
/** 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 popCurrentDefinition();
Node getCurrentDefinition();
-
+ void setExplainerTheory(theory::TheoryId theory);
+ theory::TheoryId getExplainerTheory();
+ theory::TheoryId getOwnerTheory(ClauseId clause);
+
+ void registerExplanationLemma(ClauseId clauseId);
+
// 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);
-
/** Virtual methods for printing things **/
virtual void printAtomMapping(const NodeSet& atoms,
std::ostream& os,
void printAtomMapping(const NodeSet& atoms,
std::ostream& os,
std::ostream& paren);
-
+
void printClause(const prop::SatClause& clause,
std::ostream& os,
std::ostream& paren);
/********************* */
/*! \file proof_manager.cpp
- ** \verbatim
- ** Original author: Liana Hadarean
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): Andrew Reynolds
- ** 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
- **/
+** \verbatim
+** Original author: Liana Hadarean
+** Major contributors: Morgan Deters
+** Minor contributors (to current version): Andrew Reynolds
+** 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_manager.h"
TheoryProof* pf = getTheoryProofEngine()->getTheoryProof(theory::THEORY_UF);
return (UFProof*)pf;
}
+
BitVectorProof* ProofManager::getBitVectorProof() {
Assert (options::proof());
TheoryProof* pf = getTheoryProofEngine()->getTheoryProof(theory::THEORY_BV);
return (ArrayProof*)pf;
}
+ArithProof* ProofManager::getArithProof() {
+ Assert (options::proof());
+ TheoryProof* pf = getTheoryProofEngine()->getTheoryProof(theory::THEORY_ARITH);
+ return (ArithProof*)pf;
+}
+
+SkolemizationManager* ProofManager::getSkolemizationManager() {
+ Assert (options::proof());
+ return &(currentPM()->d_skolemizationManager);
+}
+
void ProofManager::initSatProof(Minisat::Solver* solver) {
Assert (currentPM()->d_satProof == NULL);
Assert(currentPM()->d_format == LFSC);
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(), ' ', '_');
+std::string ProofManager::sanitize(TNode node) {
+ Assert (node.isVar() || node.isConst());
+
+ std::string name = node.toString();
+ if (node.isVar()) {
+ std::replace(name.begin(), name.end(), ' ', '_');
+ } else if (node.isConst()) {
+ name.erase(std::remove(name.begin(), name.end(), '('), name.end());
+ name.erase(std::remove(name.begin(), name.end(), ')'), name.end());
+ name.erase(std::remove(name.begin(), name.end(), ' '), name.end());
+ name = "const" + name;
+ }
+
return name;
}
-
void ProofManager::traceDeps(TNode n) {
Debug("cores") << "trace deps " << n << std::endl;
if ((n.isConst() && n == NodeManager::currentNM()->mkConst<bool>(true)) ||
d_satProof->collectClausesUsed(used_inputs,
used_lemmas);
+ IdToSatClause::iterator it2;
+ Debug("pf::pm") << std::endl << "Used inputs: " << std::endl;
+ for (it2 = used_inputs.begin(); it2 != used_inputs.end(); ++it2) {
+ Debug("pf::pm") << "\t input = " << *(it2->second) << std::endl;
+ }
+ Debug("pf::pm") << std::endl;
+
+ // Debug("pf::pm") << std::endl << "Used lemmas: " << std::endl;
+ // for (it2 = used_lemmas.begin(); it2 != used_lemmas.end(); ++it2) {
+ // Debug("pf::pm") << "\t lemma = " << *(it2->second) << std::endl;
+ // }
+ // Debug("pf::pm") << std::endl;
+ Debug("pf::pm") << std::endl << "Used lemmas: " << std::endl;
+ for (it2 = used_lemmas.begin(); it2 != used_lemmas.end(); ++it2) {
+
+ std::vector<Expr> clause_expr;
+ for(unsigned i = 0; i < it2->second->size(); ++i) {
+ prop::SatLiteral lit = (*(it2->second))[i];
+ Expr atom = d_cnfProof->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);
+ }
+
+ Debug("pf::pm") << "\t lemma " << it2->first << " = " << *(it2->second) << std::endl;
+ Debug("pf::pm") << "\t";
+ for (unsigned i = 0; i < clause_expr.size(); ++i) {
+ Debug("pf::pm") << clause_expr[i] << " ";
+ }
+ Debug("pf::pm") << std::endl;
+ }
+ Debug("pf::pm") << std::endl;
+
// collecting assertions that lead to the clauses being asserted
NodeSet used_assertions;
d_cnfProof->collectAssertionsForClauses(used_inputs, used_assertions);
+ NodeSet::iterator it3;
+ Debug("pf::pm") << std::endl << "Used assertions: " << std::endl;
+ for (it3 = used_assertions.begin(); it3 != used_assertions.end(); ++it3)
+ Debug("pf::pm") << "\t assertion = " << *it3 << std::endl;
+
NodeSet atoms;
// collects the atoms in the clauses
d_cnfProof->collectAtomsForClauses(used_inputs, atoms);
utils::collectAtoms(*it, atoms);
}
- 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;
- }
+ NodeSet::iterator atomIt;
+ Debug("pf::pm") << std::endl << "Dumping atoms from lemmas, inputs and assertions: " << std::endl << std::endl;
+ for (atomIt = atoms.begin(); atomIt != atoms.end(); ++atomIt) {
+ Debug("pf::pm") << "\tAtom: " << *atomIt << std::endl;
- 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;
+ 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;
+ }
+
+ 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;
+ }
}
}
-
-
smt::SmtScope scope(d_smtEngine);
std::ostringstream paren;
out << "(check\n";
// declare the theory atoms
NodeSet::const_iterator it = atoms.begin();
NodeSet::const_iterator end = atoms.end();
+
+ Debug("pf::pm") << "LFSCProof::toStream: registering terms:" << std::endl;
for(; it != end; ++it) {
+ Debug("pf::pm") << "\tTerm: " << (*it).toExpr() << std::endl;
d_theoryProof->registerTerm((*it).toExpr());
}
+
+ Debug("pf::pm") << std::endl << "Term registration done!" << std::endl << std::endl;
+
+ Debug("pf::pm") << std::endl << "LFSCProof::toStream: starting to print assertions" << std::endl;
+
// print out all the original assertions
+ d_theoryProof->registerTermsFromAssertions();
+ d_theoryProof->printSortDeclarations(out, paren);
+ d_theoryProof->printTermDeclarations(out, paren);
d_theoryProof->printAssertions(out, paren);
+ Debug("pf::pm") << std::endl << "LFSCProof::toStream: print assertions DONE" << std::endl;
- out << "(: (holds cln)\n";
+ out << "(: (holds cln)\n\n";
+
+ // Have the theory proofs print deferred declarations, e.g. for skolem variables.
+ out << " ;; Printing deferred declarations \n";
+ d_theoryProof->printDeferredDeclarations(out, paren);
// print trust that input assertions are their preprocessed form
printPreprocessedAssertions(used_assertions, out, paren);
// print mapping between theory atoms and internal SAT variables
+ out << ";; Printing mapping from preprocessed assertions into atoms \n";
d_cnfProof->printAtomMapping(atoms, out, paren);
+ Debug("pf::pm") << std::endl << "Printing cnf proof for clauses" << std::endl;
+
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);
}
+ Debug("pf::pm") << std::endl << "Printing cnf proof for clauses DONE" << std::endl;
+
// 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);
+ Debug("pf::pm") << "Proof manager: printing theory lemmas" << std::endl;
+ d_theoryProof->printTheoryLemmas(used_lemmas, out, paren);
+ Debug("pf::pm") << "Proof manager: printing theory lemmas DONE!" << std::endl;
if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER && ProofManager::getBitVectorProof()) {
// print actual resolution proof
void LFSCProof::printPreprocessedAssertions(const NodeSet& assertions,
std::ostream& os,
std::ostream& paren) {
- os << " ;; Preprocessing \n";
+ os << "\n ;; In the preprocessor we trust \n";
NodeSet::const_iterator it = assertions.begin();
NodeSet::const_iterator end = assertions.end();
paren << "))";
}
-}
-
+ os << "\n";
+}
//---from Morgan---
+
bool ProofManager::hasOp(TNode n) const {
return d_bops.find(n) != d_bops.end();
}
}
Node ProofManager::mkOp(TNode n) {
+ Trace("mgd-pm-mkop") << "MkOp : " << n << " " << n.getKind() << std::endl;
if(n.getKind() != kind::BUILTIN) {
return n;
}
+
Node& op = d_ops[n];
if(op.isNull()) {
- Debug("mgd") << "making an op for " << n << "\n";
+ Assert((n.getConst<Kind>() == kind::SELECT) || (n.getConst<Kind>() == kind::STORE));
+
+ Debug("mgd-pm-mkop") << "making an op for " << n << "\n";
+
std::stringstream ss;
ss << n;
std::string s = ss.str();
- Debug("mgd") << " : " << s << std::endl;
+ Debug("mgd-pm-mkop") << " : " << s << std::endl;
std::vector<TypeNode> v;
v.push_back(NodeManager::currentNM()->integerType());
if(n.getConst<Kind>() == kind::SELECT) {
v.push_back(NodeManager::currentNM()->integerType());
}
TypeNode type = NodeManager::currentNM()->mkFunctionType(v);
+ Debug("mgd-pm-mkop") << "typenode is: " << type << "\n";
op = NodeManager::currentNM()->mkSkolem(s, type, " ignore", NodeManager::SKOLEM_NO_NOTIFY);
d_bops[op] = n;
}
+ Debug("mgd-pm-mkop") << "returning the op: " << op << "\n";
return op;
}
//---end from Morgan---
+bool ProofManager::wasPrinted(const Type& type) const {
+ return d_printedTypes.find(type) != d_printedTypes.end();
+}
+
+void ProofManager::markPrinted(const Type& type) {
+ d_printedTypes.insert(type);
+}
+
std::ostream& operator<<(std::ostream& out, CVC4::ProofRule k) {
switch(k) {
case RULE_GIVEN:
- out << "RULE_GIVEN";
+ out << "RULE_GIVEN";
break;
case RULE_DERIVED:
- out << "RULE_DERIVED";
+ out << "RULE_DERIVED";
break;
case RULE_RECONSTRUCT:
- out << "RULE_RECONSTRUCT";
+ out << "RULE_RECONSTRUCT";
break;
case RULE_TRUST:
- out << "RULE_TRUST";
+ out << "RULE_TRUST";
break;
case RULE_INVALID:
- out << "RULE_INVALID";
+ out << "RULE_INVALID";
break;
case RULE_CONFLICT:
- out << "RULE_CONFLICT";
+ out << "RULE_CONFLICT";
break;
case RULE_TSEITIN:
- out << "RULE_TSEITIN";
+ out << "RULE_TSEITIN";
break;
case RULE_SPLIT:
- out << "RULE_SPLIT";
+ out << "RULE_SPLIT";
break;
case RULE_ARRAYS_EXT:
- out << "RULE_ARRAYS";
+ out << "RULE_ARRAYS";
break;
case RULE_ARRAYS_ROW:
- out << "RULE_ARRAYS";
+ out << "RULE_ARRAYS";
break;
default:
out << "ProofRule Unknown! [" << unsigned(k) << "]";
#include <iosfwd>
#include <map>
-
+#include "proof/proof.h"
+#include "proof/skolemization_manager.h"
+#include "util/proof.h"
#include "expr/node.h"
#include "proof/clause_id.h"
#include "proof/proof.h"
class SmtEngine;
const ClauseId ClauseIdEmpty(-1);
-const ClauseId ClauseIdUndef(-2);
+const ClauseId ClauseIdUndef(-2);
const ClauseId ClauseIdError(-3);
class Proof;
-template <class Solver> class TSatProof;
+template <class Solver> class TSatProof;
typedef TSatProof< CVC4::Minisat::Solver> CoreSatProof;
class CnfProof;
class TheoryProofEngine;
class TheoryProof;
class UFProof;
+class ArithProof;
class ArrayProof;
class BitVectorProof;
-template <class Solver> class LFSCSatProof;
+template <class Solver> class LFSCSatProof;
typedef LFSCSatProof< CVC4::Minisat::Solver> LFSCCoreSatProof;
class LFSCCnfProof;
template <class Solver> class ProofProxy;
typedef ProofProxy< CVC4::Minisat::Solver> CoreProofProxy;
-typedef ProofProxy< CVC4::BVMinisat::Solver> BVProofProxy;
+typedef ProofProxy< CVC4::BVMinisat::Solver> BVProofProxy;
namespace prop {
typedef uint64_t SatVariable;
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 */
ExprSet d_inputCoreFormulas;
ExprSet d_outputCoreFormulas;
+ SkolemizationManager d_skolemizationManager;
+
int d_nextId;
Proof* d_fullProof;
// trace dependences back to unsat core
void traceDeps(TNode n);
+ std::set<Type> d_printedTypes;
+
protected:
LogicInfo d_logic;
static UFProof* getUfProof();
static BitVectorProof* getBitVectorProof();
static ArrayProof* getArrayProof();
+ static ArithProof* getArithProof();
+
+ static SkolemizationManager *getSkolemizationManager();
// iterators over data shared by proofs
typedef ExprSet::const_iterator assertions_iterator;
}
assertions_iterator end_assertions() const { return d_inputFormulas.end(); }
size_t num_assertions() const { return d_inputFormulas.size(); }
-
+
//---from Morgan---
Node mkOp(TNode n);
Node lookupOp(TNode n) const;
bool hasOp(TNode n) const;
-
+
std::map<Node, Node> d_ops;
std::map<Node, Node> d_bops;
//---end from Morgan---
-
-
+
+
// variable prefixes
static std::string getInputClauseName(ClauseId id, const std::string& prefix = "");
static std::string getLemmaClauseName(ClauseId id, const std::string& prefix = "");
static std::string 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 = "");
// for SMT variable names that have spaces and other things
static std::string sanitize(TNode var);
-
- /** Add proof assertion - unlinke addCoreAssertion this is post definition expansion **/
+ /** Add proof assertion - unlike 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);
const std::string getLogic() const { return d_logic.getLogicString(); }
LogicInfo & getLogicInfo() { return d_logic; }
+ void markPrinted(const Type& type);
+ bool wasPrinted(const Type& type) const;
+
};/* class ProofManager */
class LFSCProof : public Proof {
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;
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.
virtual void printResolutionEmptyClause(std::ostream& out, std::ostream& paren) = 0;
virtual void printAssumptionsResolution(ClauseId id, std::ostream& out, std::ostream& paren) = 0;
-
void collectClausesUsed(IdToSatClause& inputs,
IdToSatClause& lemmas);
void storeClauseGlue(ClauseId clause, int glue);
+
+
private:
__gnu_cxx::hash_map<ClauseId, int> d_glueMap;
struct Statistics {
Statistics d_statistics;
};/* class TSatProof */
-
template <class S>
class ProofProxy {
private:
namespace CVC4 {
-template <class Solver>
+template <class Solver>
void printLit (typename Solver::TLit l) {
Debug("proof:sat") << (sign(l) ? "-" : "") << var(l) + 1;
}
-template <class Solver>
+template <class Solver>
void printClause (typename Solver::TClause& c) {
for (int i = 0; i < c.size(); i++) {
Debug("proof:sat") << (sign(c[i]) ? "-" : "") << var(c[i]) + 1 << " ";
}
}
-template <class Solver>
+template <class Solver>
void printClause (std::vector<typename Solver::TLit>& c) {
for (unsigned i = 0; i < c.size(); i++) {
Debug("proof:sat") << (sign(c[i]) ? "-" : "") << var(c[i]) + 1 << " ";
}
-template <class Solver>
+template <class Solver>
void printLitSet(const std::set<typename Solver::TLit>& s) {
typename std::set < typename Solver::TLit>::const_iterator it = s.begin();
for(; it != s.end(); ++it) {
}
// purely debugging functions
-template <class Solver>
+template <class Solver>
void printDebug (typename Solver::TLit l) {
Debug("proof:sat") << (sign(l) ? "-" : "") << var(l) + 1 << std::endl;
}
-template <class Solver>
+template <class Solver>
void printDebug (typename Solver::TClause& c) {
for (int i = 0; i < c.size(); i++) {
Debug("proof:sat") << (sign(c[i]) ? "-" : "") << var(c[i]) + 1 << " ";
* @param id the clause id
* @param set the clause converted to a set of literals
*/
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::createLitSet(ClauseId id, LitSet& set) {
Assert(set.empty());
if(isUnit(id)) {
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));
+ 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++) {
* @param clause1
* @param clause2
*/
-template <class Solver>
+template <class Solver>
bool resolve(const typename Solver::TLit v,
std::set<typename Solver::TLit>& clause1,
std::set<typename Solver::TLit>& clause2, bool s) {
}
clause1.erase(var);
clause2.erase(~var);
- typename std::set<typename Solver::TLit>::iterator it = clause2.begin();
+ typename std::set<typename Solver::TLit>::iterator it = clause2.begin();
for (; it!= clause2.end(); ++it) {
clause1.insert(*it);
}
}
clause1.erase(~var);
clause2.erase(var);
- typename std::set<typename Solver::TLit>::iterator it = clause2.begin();
+ typename std::set<typename Solver::TLit>::iterator it = clause2.begin();
for (; it!= clause2.end(); ++it) {
clause1.insert(*it);
}
}
/// ResChain
-template <class Solver>
+template <class Solver>
ResChain<Solver>::ResChain(ClauseId start) :
d_start(start),
d_steps(),
d_redundantLits(NULL)
{}
-template <class Solver>
+template <class Solver>
void ResChain<Solver>::addStep(typename Solver::TLit lit, ClauseId id, bool sign) {
ResStep<Solver> step(lit, id, sign);
d_steps.push_back(step);
}
-template <class Solver>
+template <class Solver>
void ResChain<Solver>::addRedundantLit(typename Solver::TLit lit) {
if (d_redundantLits) {
d_redundantLits->insert(lit);
/// ProxyProof
-template <class Solver>
+template <class Solver>
ProofProxy<Solver>::ProofProxy(TSatProof<Solver>* proof):
d_proof(proof)
{}
-template <class Solver>
+template <class Solver>
void ProofProxy<Solver>::updateCRef(typename Solver::TCRef oldref, typename Solver::TCRef newref) {
d_proof->updateCRef(oldref, newref);
}
/// SatProof
-template <class Solver>
+template <class Solver>
TSatProof<Solver>::TSatProof(Solver* solver, const std::string& name, bool checkRes)
: d_solver(solver)
, d_cnfProof(NULL)
, d_unitConflictId()
, d_storedUnitConflict(false)
, d_trueLit(ClauseIdUndef)
- , d_falseLit(ClauseIdUndef)
+ , d_falseLit(ClauseIdUndef)
, d_name(name)
, d_seenLearnt()
, d_seenInputs()
d_proxy = new ProofProxy<Solver>(this);
}
-template <class Solver>
+template <class Solver>
TSatProof<Solver>::~TSatProof() {
delete d_proxy;
-
+
// FIXME: double free if deleted clause also appears in d_seenLemmas?
IdToSatClause::iterator it = d_deletedTheoryLemmas.begin();
IdToSatClause::iterator end = d_deletedTheoryLemmas.end();
delete seen_it->second;
}
}
-
-template <class Solver>
+
+template <class Solver>
void TSatProof<Solver>::setCnfProof(CnfProof* cnf_proof) {
Assert (d_cnfProof == NULL);
d_cnfProof = cnf_proof;
*
* @return
*/
-template <class Solver>
+template <class Solver>
bool TSatProof<Solver>::checkResolution(ClauseId id) {
if(d_checkRes) {
bool validRes = true;
if (id == d_emptyClauseId) {
return clause1.empty();
}
-
+
LitVector c;
- getLitVec(id, c);
+ getLitVec(id, c);
for (unsigned i = 0; i < c.size(); ++i) {
int count = clause1.erase(c[i]);
/// helper methods
-template <class Solver>
+template <class Solver>
ClauseId TSatProof<Solver>::getClauseId(typename Solver::TCRef ref) {
if(d_clauseId.find(ref) == d_clauseId.end()) {
Debug("proof:sat") << "Missing clause \n";
return d_clauseId[ref];
}
-template <class Solver>
+template <class Solver>
ClauseId TSatProof<Solver>::getClauseId(typename Solver::TLit lit) {
Assert(d_unitId.find(toInt(lit)) != d_unitId.end());
return d_unitId[toInt(lit)];
}
-template <class Solver>
+template <class Solver>
typename Solver::TCRef TSatProof<Solver>::getClauseRef(ClauseId id) {
if (d_idClause.find(id) == d_idClause.end()) {
Debug("proof:sat") << "proof:getClauseRef cannot find clause "<<id<<" "
return d_idClause[id];
}
-template <class Solver>
+template <class Solver>
typename Solver::TClause& TSatProof<Solver>::getClause(typename Solver::TCRef ref) {
Assert(ref != Solver::TCRef_Undef);
Assert(ref >= 0 && ref < d_solver->ca.size());
return d_solver->ca[ref];
}
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::getLitVec(ClauseId id, LitVector& vec) {
if (isUnit(id)) {
typename Solver::TLit lit = getUnit(id);
vec.push_back(lit);
- return;
+ return;
}
if (isAssumptionConflict(id)) {
vec = *(d_assumptionConflictsDebug[id]);
}
-template <class Solver>
+template <class Solver>
typename Solver::TLit TSatProof<Solver>::getUnit(ClauseId id) {
Assert(d_idUnit.find(id) != d_idUnit.end());
return d_idUnit[id];
}
-template <class Solver>
+template <class Solver>
bool TSatProof<Solver>::isUnit(ClauseId id) {
return d_idUnit.find(id) != d_idUnit.end();
}
-template <class Solver>
+template <class Solver>
bool TSatProof<Solver>::isUnit(typename Solver::TLit lit) {
return d_unitId.find(toInt(lit)) != d_unitId.end();
}
-template <class Solver>
+template <class Solver>
ClauseId TSatProof<Solver>::getUnitId(typename Solver::TLit lit) {
Assert(isUnit(lit));
return d_unitId[toInt(lit)];
}
-template <class Solver>
+template <class Solver>
bool TSatProof<Solver>::hasResolution(ClauseId id) {
return d_resChains.find(id) != d_resChains.end();
}
-template <class Solver>
+template <class Solver>
bool TSatProof<Solver>::isInputClause(ClauseId id) {
return (d_inputClauses.find(id) != d_inputClauses.end());
}
-template <class Solver>
+template <class Solver>
bool TSatProof<Solver>::isLemmaClause(ClauseId id) {
return (d_lemmaClauses.find(id) != d_lemmaClauses.end());
}
-template <class Solver>
+template <class Solver>
bool TSatProof<Solver>::isAssumptionConflict(ClauseId id) {
return d_assumptionConflicts.find(id) != d_assumptionConflicts.end();
}
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::print(ClauseId id) {
if (d_deleted.find(id) != d_deleted.end()) {
Debug("proof:sat") << "del"<<id;
printClause<Solver>(getClause(ref));
}
}
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::printRes(ClauseId id) {
Assert(hasResolution(id));
Debug("proof:sat") << "id "<< id <<": ";
printRes(d_resChains[id]);
}
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::printRes(ResChain<Solver>* res) {
ClauseId start_id = res->getStart();
}
/// registration methods
-template <class Solver>
+template <class Solver>
ClauseId TSatProof<Solver>::registerClause(typename Solver::TCRef clause,
ClauseKind kind) {
Assert(clause != Solver::TCRef_Undef);
typename ClauseIdMap::iterator it = d_clauseId.find(clause);
if (it == d_clauseId.end()) {
ClauseId newId = ProofManager::currentPM()->nextId();
- d_clauseId.insert(std::make_pair(clause, newId));
+ d_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());
if (kind == THEORY_LEMMA) {
Assert(d_lemmaClauses.find(newId) == d_lemmaClauses.end());
d_lemmaClauses.insert(newId);
+ Debug("pf::sat") << "TSatProof::registerClause registering a new lemma clause: "
+ << newId << " = " << *buildClause(newId)
+ << ". Explainer theory: " << d_cnfProof->getExplainerTheory()
+ << std::endl;
+ d_cnfProof->registerExplanationLemma(newId);
}
}
return id;
}
-template <class Solver>
+template <class Solver>
ClauseId TSatProof<Solver>::registerUnitClause(typename Solver::TLit lit,
ClauseKind kind) {
Debug("cores") << "registerUnitClause " << kind << std::endl;
}
if (kind == THEORY_LEMMA) {
Assert(d_lemmaClauses.find(newId) == d_lemmaClauses.end());
+ Debug("pf::sat") << "TSatProof::registerUnitClause: registering a new lemma (UNIT CLAUSE): "
+ << lit
+ << ". Explainer theory: " << d_cnfProof->getExplainerTheory()
+ << std::endl;
d_lemmaClauses.insert(newId);
+ d_cnfProof->registerExplanationLemma(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
+ Debug("proof:sat:detailed") << "registerUnitClause id: " << id
<<" kind: " << kind << "\n";
// ProofManager::currentPM()->setRegisteredClauseId( d_unitId[toInt(lit)] );
return id;
}
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::registerTrueLit(const typename Solver::TLit lit) {
Assert (d_trueLit == ClauseIdUndef);
d_trueLit = registerUnitClause(lit, INPUT);
}
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::registerFalseLit(const typename Solver::TLit lit) {
Assert (d_falseLit == ClauseIdUndef);
d_falseLit = registerUnitClause(lit, INPUT);
}
-template <class Solver>
+template <class Solver>
ClauseId TSatProof<Solver>::getTrueUnit() const {
Assert (d_trueLit != ClauseIdUndef);
return d_trueLit;
}
-template <class Solver>
+template <class Solver>
ClauseId TSatProof<Solver>::getFalseUnit() const {
Assert (d_falseLit != ClauseIdUndef);
return d_falseLit;
}
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::registerAssumption(const typename Solver::TVar var) {
Assert (d_assumptions.find(var) == d_assumptions.end());
d_assumptions.insert(var);
}
-template <class Solver>
+template <class Solver>
ClauseId TSatProof<Solver>::registerAssumptionConflict(const typename Solver::TLitVec& confl) {
Debug("proof:sat:detailed") << "registerAssumptionConflict " << std::endl;
// Uniqueness is checked in the bit-vector proof
}
ClauseId new_id = ProofManager::currentPM()->nextId();
d_assumptionConflicts.insert(new_id);
- LitVector* vec_confl = new LitVector(confl.size());
+ LitVector* vec_confl = new LitVector(confl.size());
for (int i = 0; i < confl.size(); ++i) {
vec_confl->operator[](i) = confl[i];
}
if (Debug.isOn("proof:sat:detailed")) {
printClause<Solver>(*vec_confl);
- Debug("proof:sat:detailed") << "\n";
+ Debug("proof:sat:detailed") << "\n";
}
d_assumptionConflictsDebug[new_id] = vec_confl;
}
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::removedDfs(typename Solver::TLit lit, LitSet* removedSet, LitVector& removeStack, LitSet& inClause, LitSet& seen) {
// if we already added the literal return
if (seen.count(lit)) {
}
}
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::removeRedundantFromRes(ResChain<Solver>* res, ClauseId id) {
LitSet* removed = res->getRedundant();
if (removed == NULL) {
}
removed->clear();
}
-
-template <class Solver>
+
+template <class Solver>
void TSatProof<Solver>::registerResolution(ClauseId id, ResChain<Solver>* res) {
Assert(res != NULL);
/// recording resolutions
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::startResChain(typename Solver::TCRef start) {
ClauseId id = getClauseId(start);
ResChain<Solver>* res = new ResChain<Solver>(id);
d_resStack.push_back(res);
}
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::startResChain(typename Solver::TLit start) {
ClauseId id = getUnitId(start);
ResChain<Solver>* res = new ResChain<Solver>(id);
}
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::addResolutionStep(typename Solver::TLit lit,
typename Solver::TCRef clause, bool sign) {
ClauseId id = registerClause(clause, LEARNT);
res->addStep(lit, id, sign);
}
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::endResChain(ClauseId id) {
Debug("proof:sat:detailed") <<"endResChain " << id << "\n";
Assert(d_resStack.size() > 0);
}
-// template <class Solver>
+// template <class Solver>
// void TSatProof<Solver>::endResChain(typename Solver::TCRef clause) {
// Assert(d_resStack.size() > 0);
// ClauseId id = registerClause(clause, LEARNT);
// d_resStack.pop_back();
// }
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::endResChain(typename Solver::TLit lit) {
Assert(d_resStack.size() > 0);
ClauseId id = registerUnitClause(lit, LEARNT);
}
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::cancelResChain() {
Assert(d_resStack.size() > 0);
d_resStack.pop_back();
}
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::storeLitRedundant(typename Solver::TLit lit) {
Assert(d_resStack.size() > 0);
ResChain<Solver>* res = d_resStack.back();
}
/// constructing resolutions
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::resolveOutUnit(typename Solver::TLit lit) {
ClauseId id = resolveUnit(~lit);
ResChain<Solver>* res = d_resStack.back();
res->addStep(lit, id, !sign(lit));
}
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::storeUnitResolution(typename Solver::TLit lit) {
Debug("cores") << "STORE UNIT RESOLUTION" << std::endl;
resolveUnit(lit);
}
-template <class Solver>
+template <class Solver>
ClauseId TSatProof<Solver>::resolveUnit(typename Solver::TLit lit) {
// first check if we already have a resolution for lit
if(isUnit(lit)) {
registerResolution(unit_id, res);
return unit_id;
}
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::toStream(std::ostream& out) {
Debug("proof:sat") << "TSatProof<Solver>::printProof\n";
Unimplemented("native proof printing not supported yet");
}
-template <class Solver>
+template <class Solver>
ClauseId TSatProof<Solver>::storeUnitConflict(typename Solver::TLit conflict_lit,
ClauseKind kind) {
Debug("cores") << "STORE UNIT CONFLICT" << std::endl;
Debug("proof:sat:detailed") <<"storeUnitConflict " << d_unitConflictId << "\n";
return d_unitConflictId;
}
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::finalizeProof(typename Solver::TCRef conflict_ref) {
Assert(d_resStack.size() == 0);
Assert(conflict_ref != Solver::TCRef_Undef);
}
/// CRef manager
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::updateCRef(typename Solver::TCRef oldref,
typename Solver::TCRef newref) {
if (d_clauseId.find(oldref) == d_clauseId.end()) {
d_temp_clauseId[newref] = id;
d_temp_idClause[id] = newref;
}
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::finishUpdateCRef() {
d_clauseId.swap(d_temp_clauseId);
d_temp_clauseId.clear();
d_idClause.swap(d_temp_idClause);
d_temp_idClause.clear();
}
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::markDeleted(typename Solver::TCRef clause) {
if (d_clauseId.find(clause) != d_clauseId.end()) {
ClauseId id = getClauseId(clause);
// template<>
// void toSatClause< ::BVMinisat::Solver> (const BVMinisat::Solver::TClause& minisat_cl,
// prop::SatClause& sat_cl) {
-
+
// prop::BVMinisatSatSolver::toSatClause(minisat_cl, sat_cl);
// }
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::constructProof(ClauseId conflict) {
collectClauses(conflict);
}
-template <class Solver>
+template <class Solver>
std::string TSatProof<Solver>::clauseName(ClauseId id) {
std::ostringstream os;
if (isInputClause(id)) {
}
}
-template <class Solver>
+template <class Solver>
prop::SatClause* TSatProof<Solver>::buildClause(ClauseId id) {
if (isUnit(id)) {
typename Solver::TLit lit = getUnit(id);
return clause;
}
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::collectClauses(ClauseId id) {
if (d_seenInputs.find(id) != d_seenInputs.end() ||
d_seenLemmas.find(id) != d_seenLemmas.end() ||
}
}
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::collectClausesUsed(IdToSatClause& inputs,
IdToSatClause& lemmas) {
inputs = d_seenInputs;
);
}
-template <class Solver>
+template <class Solver>
void TSatProof<Solver>::storeClauseGlue(ClauseId clause, int glue) {
Assert (d_glueMap.find(clause) == d_glueMap.end());
d_glueMap.insert(std::make_pair(clause, glue));
}
-template <class Solver>
+template <class Solver>
TSatProof<Solver>::Statistics::Statistics(const std::string& prefix)
: d_numLearnedClauses("satproof::"+prefix+"::NumLearnedClauses", 0)
, d_numLearnedInProof("satproof::"+prefix+"::NumLearnedInProof", 0)
smtStatisticsRegistry()->registerStat(&d_usedClauseGlue);
}
-template <class Solver>
+template <class Solver>
TSatProof<Solver>::Statistics::~Statistics() {
smtStatisticsRegistry()->unregisterStat(&d_numLearnedClauses);
smtStatisticsRegistry()->unregisterStat(&d_numLearnedInProof);
/// LFSCSatProof class
-template <class Solver>
+template <class Solver>
void LFSCSatProof<Solver>::printResolution(ClauseId id, std::ostream& out, std::ostream& paren) {
out << "(satlem_simplify _ _ _ ";
}
/// LFSCSatProof class
-template <class Solver>
+template <class Solver>
void LFSCSatProof<Solver>::printAssumptionsResolution(ClauseId id, std::ostream& out, std::ostream& paren) {
Assert (this->isAssumptionConflict(id));
// print the resolution proving the assumption conflict
// resolve out assumptions to prove empty clause
out << "(satlem_simplify _ _ _ ";
std::vector<typename Solver::TLit>& confl = *(this->d_assumptionConflictsDebug[id]);
-
+
Assert (confl.size());
for (unsigned i = 0; i < confl.size(); ++i) {
out <<"(";
out << (lit.isNegated() ? "Q" : "R") <<" _ _ ";
}
-
- out << this->clauseName(id)<< " ";
+
+ out << this->clauseName(id)<< " ";
for (int i = confl.size() - 1; i >= 0; --i) {
prop::SatLiteral lit = toSatLiteral<Solver>(confl[i]);
prop::SatVariable v = lit.getSatVariable();
template <class Solver>
void LFSCSatProof<Solver>::printResolutionEmptyClause(std::ostream& out, std::ostream& paren) {
- printResolution(this->d_emptyClauseId, out, paren);
+ printResolution(this->d_emptyClauseId, out, paren);
}
inline std::ostream& operator<<(std::ostream& out, CVC4::ClauseKind k) {
switch(k) {
case CVC4::INPUT:
- out << "INPUT";
+ out << "INPUT";
break;
case CVC4::THEORY_LEMMA:
- out << "THEORY_LEMMA";
+ out << "THEORY_LEMMA";
break;
case CVC4::LEARNT:
- out << "LEARNT";
+ out << "LEARNT";
break;
default:
out << "ClauseKind Unknown! [" << unsigned(k) << "]";
--- /dev/null
+/********************* */
+/*! \file skolemization_manager.cpp
+ **/
+
+#include "proof/skolemization_manager.h"
+
+namespace CVC4 {
+
+void SkolemizationManager::registerSkolem(Node disequality, Node skolem) {
+ Debug("pf::pm") << "SkolemizationManager: registerSkolem: disequality = " << disequality << ", skolem = " << skolem << std::endl;
+
+ if (isSkolem(skolem)) {
+ Assert(d_skolemToDisequality[skolem] == disequality);
+ return;
+ }
+
+ d_disequalityToSkolem[disequality] = skolem;
+ d_skolemToDisequality[skolem] = disequality;
+}
+
+bool SkolemizationManager::hasSkolem(Node disequality) {
+ return (d_disequalityToSkolem.find(disequality) != d_disequalityToSkolem.end());
+}
+
+Node SkolemizationManager::getSkolem(Node disequality) {
+ Debug("pf::pm") << "SkolemizationManager: getSkolem( ";
+ Assert (d_disequalityToSkolem.find(disequality) != d_disequalityToSkolem.end());
+ Debug("pf::pm") << disequality << " ) = " << d_disequalityToSkolem[disequality] << std::endl;
+ return d_disequalityToSkolem[disequality];
+}
+
+Node SkolemizationManager::getDisequality(Node skolem) {
+ Assert (d_skolemToDisequality.find(skolem) != d_skolemToDisequality.end());
+ return d_skolemToDisequality[skolem];
+}
+
+bool SkolemizationManager::isSkolem(Node skolem) {
+ return (d_skolemToDisequality.find(skolem) != d_skolemToDisequality.end());
+}
+
+void SkolemizationManager::clear() {
+ Debug("pf::pm") << "SkolemizationManager: clear" << std::endl;
+ d_disequalityToSkolem.clear();
+ d_skolemToDisequality.clear();
+}
+
+std::hash_map<Node, Node, NodeHashFunction>::const_iterator SkolemizationManager::begin() {
+ return d_disequalityToSkolem.begin();
+}
+
+std::hash_map<Node, Node, NodeHashFunction>::const_iterator SkolemizationManager::end() {
+ return d_disequalityToSkolem.end();
+}
+
+} /* CVC4 namespace */
--- /dev/null
+/********************* */
+/*! \file skolemization_manager.h
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef __CVC4__SKOLEMIZATION_MANAGER_H
+#define __CVC4__SKOLEMIZATION_MANAGER_H
+
+#include <iostream>
+#include <map>
+#include "proof/proof.h"
+#include "util/proof.h"
+#include "expr/node.h"
+#include "theory/logic_info.h"
+#include "theory/substitutions.h"
+
+namespace CVC4 {
+
+class SkolemizationManager {
+public:
+ void registerSkolem(Node disequality, Node skolem);
+ bool hasSkolem(Node disequality);
+ Node getSkolem(Node disequality);
+ Node getDisequality(Node skolem);
+ bool isSkolem(Node skolem);
+
+ void clear();
+
+ std::hash_map<Node, Node, NodeHashFunction>::const_iterator begin();
+ std::hash_map<Node, Node, NodeHashFunction>::const_iterator end();
+
+private:
+ std::hash_map<Node, Node, NodeHashFunction> d_disequalityToSkolem;
+ std::hash_map<Node, Node, NodeHashFunction> d_skolemToDisequality;
+};
+
+}/* CVC4 namespace */
+
+
+
+#endif /* __CVC4__SKOLEMIZATION_MANAGER_H */
#include "base/cvc4_assert.h"
#include "context/context.h"
#include "options/bv_options.h"
+#include "proof/arith_proof.h"
#include "proof/array_proof.h"
#include "proof/bitvector_proof.h"
#include "proof/clause_id.h"
return theory::LemmaStatus(TNode::null(), 0);
}
void requirePhase(TNode n, bool b) throw() {
+ Debug("theory-proof-debug") << "ProofOutputChannel::requirePhase called" << std::endl;
Trace("theory-proof-debug") << "requirePhase " << n << " " << b << std::endl;
}
bool flipDecision() throw() {
+ Debug("theory-proof-debug") << "ProofOutputChannel::flipDecision called" << std::endl;
AlwaysAssert(false);
return false;
}
void setIncomplete() throw() {
+ Debug("theory-proof-debug") << "ProofOutputChannel::setIncomplete called" << std::endl;
AlwaysAssert(false);
}
};/* class ProofOutputChannel */
((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
+
+ if (id == theory::THEORY_ARITH) {
+ d_theoryProofTable[id] = new LFSCArithProof((theory::arith::TheoryArith*)th, this);
+ return;
+ }
+
+ // TODO other theories
}
}
}
if (d_registrationCache.count(term)) {
return;
}
+ Debug("pf::tp") << "TheoryProofEngine::registerTerm: registering new term: " << term << std::endl;
theory::TheoryId theory_id = theory::Theory::theoryOf(term);
+ Debug("pf::tp") << "Term's theory: " << theory_id << std::endl;
+
// don't need to register boolean terms
if (theory_id == theory::THEORY_BUILTIN ||
term.getKind() == kind::ITE) {
}
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();
+ Debug("pf::tp") << "TheoryProofEngine::getTheoryForLemma( " << id << " )"
+ << " = " << pm->getCnfProof()->getOwnerTheory(id) << std::endl;
+
+ if ((pm->getLogic() == "QF_UFLIA") || (pm->getLogic() == "QF_UFLRA")) {
+ Debug("pf::tp") << "TheoryProofEngine::getTheoryForLemma: special hack for Arithmetic-with-holes support. "
+ << "Returning THEORY_ARITH" << std::endl;
+ return theory::THEORY_ARITH;
+ }
+
+ return pm->getCnfProof()->getOwnerTheory(id);
+
+ // if (pm->getLogic() == "QF_UF") return theory::THEORY_UF;
+ // if (pm->getLogic() == "QF_BV") return theory::THEORY_BV;
+ // if (pm->getLogic() == "QF_AX") return theory::THEORY_ARRAY;
+ // if (pm->getLogic() == "ALL_SUPPORTED") return theory::THEORY_BV;
+
+ // Debug("pf::tp") << "Unsupported logic (" << pm->getLogic() << ")" << std::endl;
+
+ // Unreachable();
}
void LFSCTheoryProofEngine::bind(Expr term, LetMap& map, Bindings& let_order) {
void LFSCTheoryProofEngine::printTheoryTerm(Expr term, std::ostream& os, const LetMap& map) {
theory::TheoryId theory_id = theory::Theory::theoryOf(term);
+ Debug("pf::tp") << std::endl << "LFSCTheoryProofEngine::printTheoryTerm: term = " << term
+ << ", theory_id = " << theory_id << std::endl;
+
// boolean terms and ITEs are special because they
// are common to all theories
if (theory_id == theory::THEORY_BUILTIN ||
return;
}
// dispatch to proper theory
- getTheoryProof(theory_id)->printTerm(term, os, map);
+ getTheoryProof(theory_id)->printOwnedTerm(term, os, map);
}
void LFSCTheoryProofEngine::printSort(Type type, std::ostream& os) {
if (type.isSort()) {
- getTheoryProof(theory::THEORY_UF)->printSort(type, os);
+ getTheoryProof(theory::THEORY_UF)->printOwnedSort(type, os);
return;
}
if (type.isBitVector()) {
- getTheoryProof(theory::THEORY_BV)->printSort(type, os);
+ getTheoryProof(theory::THEORY_BV)->printOwnedSort(type, os);
return;
}
if (type.isArray()) {
- getTheoryProof(theory::THEORY_ARRAY)->printSort(type, os);
+ getTheoryProof(theory::THEORY_ARRAY)->printOwnedSort(type, os);
return;
}
+
+ if (type.isInteger() || type.isReal()) {
+ getTheoryProof(theory::THEORY_ARITH)->printOwnedSort(type, os);
+ return;
+ }
+
+ if (type.isBoolean()) {
+ getTheoryProof(theory::THEORY_BOOL)->printOwnedSort(type, os);
+ return;
+ }
+
Unreachable();
}
-void LFSCTheoryProofEngine::printAssertions(std::ostream& os, std::ostream& paren) {
- unsigned counter = 0;
+void LFSCTheoryProofEngine::registerTermsFromAssertions() {
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);
+}
+
+void LFSCTheoryProofEngine::printAssertions(std::ostream& os, std::ostream& paren) {
+ Debug("pf::tp") << "LFSCTheoryProofEngine::printAssertions called" << std::endl << std::endl;
+
+ unsigned counter = 0;
+ ProofManager::assertions_iterator it = ProofManager::currentPM()->begin_assertions();
+ ProofManager::assertions_iterator end = ProofManager::currentPM()->end_assertions();
- it = ProofManager::currentPM()->begin_assertions();
for (; it != end; ++it) {
+ Debug("pf::tp") << "printAssertions: assertion is: " << *it << std::endl;
// FIXME: merge this with counter
os << "(% A" << counter++ << " (th_holds ";
printLetTerm(*it, os);
}
//store map between assertion and counter
// ProofManager::currentPM()->setAssertion( *it );
+ Debug("pf::tp") << "LFSCTheoryProofEngine::printAssertions done" << std::endl << std::endl;
}
-void LFSCTheoryProofEngine::printDeclarations(std::ostream& os, std::ostream& paren) {
+void LFSCTheoryProofEngine::printSortDeclarations(std::ostream& os, std::ostream& paren) {
+ Debug("pf::tp") << "LFSCTheoryProofEngine::printSortDeclarations called" << std::endl << std::endl;
+
TheoryProofTable::const_iterator it = d_theoryProofTable.begin();
TheoryProofTable::const_iterator end = d_theoryProofTable.end();
for (; it != end; ++it) {
- it->second->printDeclarations(os, paren);
+ it->second->printSortDeclarations(os, paren);
+ }
+
+ Debug("pf::tp") << "LFSCTheoryProofEngine::printSortDeclarations done" << std::endl << std::endl;
+}
+
+void LFSCTheoryProofEngine::printTermDeclarations(std::ostream& os, std::ostream& paren) {
+ Debug("pf::tp") << "LFSCTheoryProofEngine::printTermDeclarations called" << std::endl << std::endl;
+
+ TheoryProofTable::const_iterator it = d_theoryProofTable.begin();
+ TheoryProofTable::const_iterator end = d_theoryProofTable.end();
+ for (; it != end; ++it) {
+ it->second->printTermDeclarations(os, paren);
+ }
+
+ Debug("pf::tp") << "LFSCTheoryProofEngine::printTermDeclarations done" << std::endl << std::endl;
+}
+
+void LFSCTheoryProofEngine::printDeferredDeclarations(std::ostream& os, std::ostream& paren) {
+ Debug("pf::tp") << "LFSCTheoryProofEngine::printDeferredDeclarations called" << std::endl;
+
+ TheoryProofTable::const_iterator it = d_theoryProofTable.begin();
+ TheoryProofTable::const_iterator end = d_theoryProofTable.end();
+ for (; it != end; ++it) {
+ it->second->printDeferredDeclarations(os, paren);
}
}
IdToSatClause::const_iterator it = lemmas.begin();
IdToSatClause::const_iterator end = lemmas.end();
+ Debug("pf::tp") << "LFSCTheoryProofEngine::printTheoryLemmas: checking lemma owners..." << std::endl;
+
+ for (; it != end; ++it) {
+ Debug("pf::tp") << "LFSCTheoryProofEngine::printTheoryLemmas: new lemma" << std::endl;
+ ClauseId id = it->first;
+ Debug("pf::tp") << "\tLemma = " << id
+ << ". Owner theory: " << pm->getCnfProof()->getOwnerTheory(id) << std::endl;
+ }
+ it = lemmas.begin();
+
// BitVector theory is special case: must know all
// conflicts needed ahead of time for resolution
// proof lemmas
it = lemmas.begin();
+ Debug("pf::tp") << "LFSCTheoryProofEngine::printTheoryLemmas: printing lemmas..." << std::endl;
+
for (; it != end; ++it) {
+ Debug("pf::tp") << "LFSCTheoryProofEngine::printTheoryLemmas: printing a new lemma!" << std::endl;
+
+ // Debug("pf::tp") << "\tLemma = " << it->first << ", " << *(it->second) << std::endl;
ClauseId id = it->first;
+ Debug("pf::tp") << "Owner theory:" << pm->getCnfProof()->getOwnerTheory(id) << std::endl;
const prop::SatClause* clause = it->second;
// printing clause as it appears in resolution proof
os << "(satlem _ _ ";
std::ostringstream clause_paren;
+
+ Debug("pf::tp") << "CnfProof printing clause..." << std::endl;
pm->getCnfProof()->printClause(*clause, os, clause_paren);
+ Debug("pf::tp") << "CnfProof printing clause - Done!" << std::endl;
std::vector<Expr> clause_expr;
for(unsigned i = 0; i < clause->size(); ++i) {
clause_expr.push_back(expr_lit);
}
+ Debug("pf::tp") << "Expression printing done!" << std::endl;
+
// query appropriate theory for proof of clause
theory::TheoryId theory_id = getTheoryForLemma(id);
+ Debug("pf::tp") << "Get theory lemma from " << theory_id << "..." << std::endl;
Debug("theory-proof-debug") << ";; Get theory lemma from " << theory_id << "..." << std::endl;
getTheoryProof(theory_id)->printTheoryLemmaProof(clause_expr, os, paren);
+ Debug("pf::tp") << "Get theory lemma from " << theory_id << "... DONE!" << std::endl;
// os << " (clausify_false trust)";
os << clause_paren.str();
os << "( \\ " << pm->getLemmaClauseName(id) <<"\n";
}
void LFSCTheoryProofEngine::printBoundTerm(Expr term, std::ostream& os, const LetMap& map) {
+ // Debug("pf::tp") << "LFSCTheoryProofEngine::printBoundTerm( " << term << " ) " << std::endl;
+
LetMap::const_iterator it = map.find(term);
- Assert (it != map.end());
- unsigned id = it->second.id;
- unsigned count = it->second.count;
- if (count > LET_COUNT) {
- os <<"let"<<id;
- return;
+ if (it != map.end()) {
+ unsigned id = it->second.id;
+ unsigned count = it->second.count;
+ if (count > LET_COUNT) {
+ os <<"let"<<id;
+ return;
+ }
}
- printTheoryTerm(term, os, map);
+
+ printTheoryTerm(term, os, map);
}
void LFSCTheoryProofEngine::printCoreTerm(Expr term, std::ostream& os, const LetMap& map) {
th = new theory::arrays::TheoryArrays(&fakeContext, &fakeContext, oc, v,
ProofManager::currentPM()->getLogicInfo(),
"replay::");
+ } else if (d_theory->getId() == theory::THEORY_ARITH) {
+ Trace("theory-proof-debug") << "Arith proofs currently not supported. Use 'trust'" << std::endl;
+ os << " (clausify_false trust)";
+ return;
} else {
InternalError(std::string("can't generate theory-proof for ") + ProofManager::currentPM()->getLogic());
}
+
+ Debug("pf::tp") << "TheoryProof::printTheoryLemmaProof - calling th->ProduceProofs()" << std::endl;
th->produceProofs();
+ Debug("pf::tp") << "TheoryProof::printTheoryLemmaProof - th->ProduceProofs() DONE" << std::endl;
+
MyPreRegisterVisitor preRegVisitor(th);
for( unsigned i=0; i<lemma.size(); i++ ){
Node lit = Node::fromExpr( lemma[i] ).negate();
- Trace("theory-proof-debug") << "; preregistering and asserting " << lit << std::endl;
+ Trace("pf::tp") << "; preregistering and asserting " << lit << std::endl;
NodeVisitor<MyPreRegisterVisitor>::run(preRegVisitor, lit);
th->assertFact(lit, false);
}
+
+ Debug("pf::tp") << "TheoryProof::printTheoryLemmaProof - calling th->check()" << std::endl;
th->check(theory::Theory::EFFORT_FULL);
+ Debug("pf::tp") << "TheoryProof::printTheoryLemmaProof - th->check() DONE" << std::endl;
+
if(oc.d_conflict.isNull()) {
- Trace("theory-proof-debug") << "; conflict is null" << std::endl;
+ Trace("pf::tp") << "; 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);
+ Trace("pf::tp") << "; ++ but got lemma: " << oc.d_lemma << std::endl;
+
+ // Original, as in Liana's branch
+ // Trace("pf::tp") << "; asserting " << oc.d_lemma[1].negate() << std::endl;
+ // th->assertFact(oc.d_lemma[1].negate(), false);
+ // th->check(theory::Theory::EFFORT_FULL);
+
+ // Altered version, to handle OR lemmas
+
+ if (oc.d_lemma.getKind() == kind::OR) {
+ Debug("pf::tp") << "OR lemma. Negating each child separately" << std::endl;
+ for (unsigned i = 0; i < oc.d_lemma.getNumChildren(); ++i) {
+ if (oc.d_lemma[i].getKind() == kind::NOT) {
+ Trace("pf::tp") << "; asserting fact: " << oc.d_lemma[i][0] << std::endl;
+ th->assertFact(oc.d_lemma[i][0], false);
+ }
+ else {
+ Trace("pf::tp") << "; asserting fact: " << oc.d_lemma[i].notNode() << std::endl;
+ th->assertFact(oc.d_lemma[i].notNode(), false);
+ }
+ }
+ }
+ else {
+ Unreachable();
+
+ Assert(oc.d_lemma.getKind() == kind::NOT);
+ Debug("pf::tp") << "NOT lemma" << std::endl;
+ Trace("pf::tp") << "; asserting fact: " << oc.d_lemma[0] << std::endl;
+ th->assertFact(oc.d_lemma[0], false);
+ }
+
+ // Trace("pf::tp") << "; ++ but got lemma: " << oc.d_lemma << std::endl;
+ // Trace("pf::tp") << "; asserting " << oc.d_lemma[1].negate() << std::endl;
+ // th->assertFact(oc.d_lemma[1].negate(), false);
+
+ //
th->check(theory::Theory::EFFORT_FULL);
}
+ Debug("pf::tp") << "Calling oc.d_proof->toStream(os)" << std::endl;
oc.d_proof->toStream(os);
+ Debug("pf::tp") << "Calling oc.d_proof->toStream(os) -- DONE!" << std::endl;
+
+ Debug("pf::tp") << "About to delete the theory solver used for proving the lemma... " << std::endl;
delete th;
+ Debug("pf::tp") << "About to delete the theory solver used for proving the lemma: DONE! " << std::endl;
}
bool TheoryProofEngine::supportedTheory(theory::TheoryId id) {
return (id == theory::THEORY_ARRAY ||
+ id == theory::THEORY_ARITH ||
id == theory::THEORY_BV ||
id == theory::THEORY_UF ||
id == theory::THEORY_BOOL);
}
}
-void LFSCBooleanProof::printTerm(Expr term, std::ostream& os, const LetMap& map) {
+void LFSCBooleanProof::printOwnedTerm(Expr term, std::ostream& os, const LetMap& map) {
Assert (term.getType().isBoolean());
if (term.isVariable()) {
os << "(p_app " << ProofManager::sanitize(term) <<")";
}
-void LFSCBooleanProof::printSort(Type type, std::ostream& os) {
+void LFSCBooleanProof::printOwnedSort(Type type, std::ostream& os) {
Assert (type.isBoolean());
os << "Bool";
}
-void LFSCBooleanProof::printDeclarations(std::ostream& os, std::ostream& paren) {
+
+void LFSCBooleanProof::printSortDeclarations(std::ostream& os, std::ostream& paren) {
+ // Nothing to do here at this point.
+}
+
+void LFSCBooleanProof::printTermDeclarations(std::ostream& os, std::ostream& paren) {
for (ExprSet::const_iterator it = d_declarations.begin(); it != d_declarations.end(); ++it) {
Expr term = *it;
}
}
+void LFSCBooleanProof::printDeferredDeclarations(std::ostream& os, std::ostream& paren) {
+ // Nothing to do here at this point.
+}
+
void LFSCBooleanProof::printTheoryLemmaProof(std::vector<Expr>& lemma,
std::ostream& os,
std::ostream& paren) {
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)
count = rhs.count;
return *this;
}
-};
+};
struct LetOrderElement {
Expr expr;
typedef __gnu_cxx::hash_map < ClauseId, prop::SatClause* > IdToSatClause;
typedef __gnu_cxx::hash_map<Expr, LetCount, ExprHashFunction> LetMap;
-typedef std::vector<LetOrderElement> Bindings;
+typedef std::vector<LetOrderElement> Bindings;
class TheoryProof;
*/
virtual void printSort(Type type, std::ostream& os) = 0;
+ /**
+ * Go over the assertions and register all terms with the theories.
+ *
+ * @param os
+ * @param paren closing parenthesis
+ */
+ virtual void registerTermsFromAssertions() = 0;
+
/**
* Print the theory assertions (arbitrary formulas over
* theory atoms)
* @param paren closing parenthesis
*/
virtual void printAssertions(std::ostream& os, std::ostream& paren) = 0;
+ /**
+ * Print variable declarations that need to appear within the proof,
+ * e.g. skolemized variables.
+ *
+ * @param os
+ * @param paren closing parenthesis
+ */
+ virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren) = 0;
/**
* Print proofs of all the theory lemmas (must prove
LFSCTheoryProofEngine()
: TheoryProofEngine() {}
- void printDeclarations(std::ostream& os, std::ostream& paren);
+ void registerTermsFromAssertions();
+ void printSortDeclarations(std::ostream& os, std::ostream& paren);
+ void printTermDeclarations(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 printDeferredDeclarations(std::ostream& os, std::ostream& paren);
virtual void printTheoryLemmas(const IdToSatClause& lemmas,
std::ostream& os,
std::ostream& paren);
: d_theory(th)
, d_proofEngine(proofEngine)
{}
- virtual ~TheoryProof() {};
- /**
- * Print a term belonging to this theory.
- *
+ virtual ~TheoryProof() {};
+ /**
+ * Print a term belonging some theory, not neccessarily this one.
+ *
* @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
+ void printTerm(Expr term, std::ostream& os, const LetMap& map) {
+ d_proofEngine->printBoundTerm(term, os, map);
+ }
+ /**
+ * Print a term belonging to THIS theory.
+ *
+ * @param term expresion representing term
+ * @param os output stream
+ */
+ virtual void printOwnedTerm(Expr term, std::ostream& os, const LetMap& map) = 0;
+ /**
+ * Print the proof representation of the given type that belongs to some theory.
+ *
+ * @param type
+ * @param os
*/
- virtual void printSort(Type type, std::ostream& os) = 0;
- /**
+ void printSort(Type type, std::ostream& os) {
+ d_proofEngine->printSort(type, os);
+ }
+ /**
+ * Print the proof representation of the given type that belongs to THIS theory.
+ *
+ * @param type
+ * @param os
+ */
+ virtual void printOwnedSort(Type type, std::ostream& os) = 0;
+ /**
* Print a proof for the theory lemmas. Must prove
* clause representing lemmas to be used in resolution proof.
- *
+ *
* @param os output stream
*/
virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren);
- /**
- * Print the variable/sorts declarations for this theory.
- *
- * @param os
- * @param paren
+ /**
+ * Print the sorts declarations for this theory.
+ *
+ * @param os
+ * @param paren
*/
- virtual void printDeclarations(std::ostream& os, std::ostream& paren) = 0;
- /**
+ virtual void printSortDeclarations(std::ostream& os, std::ostream& paren) = 0;
+ /**
+ * Print the term declarations for this theory.
+ *
+ * @param os
+ * @param paren
+ */
+ virtual void printTermDeclarations(std::ostream& os, std::ostream& paren) = 0;
+ /**
+ * Print any deferred variable/sorts declarations for this theory
+ * (those that need to appear inside the actual proof).
+ *
+ * @param os
+ * @param paren
+ */
+ virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren) = 0;
+ /**
* Register a term of this theory that appears in the proof.
- *
- * @param term
+ *
+ * @param term
*/
- virtual void registerTerm(Expr term) = 0;
+ virtual void registerTerm(Expr term) = 0;
};
class BooleanProof : public TheoryProof {
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 printOwnedTerm(Expr term, std::ostream& os, const LetMap& map) = 0;
+
+ virtual void printOwnedSort(Type type, std::ostream& os) = 0;
virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren) = 0;
- virtual void printDeclarations(std::ostream& os, std::ostream& paren) = 0;
+ virtual void printSortDeclarations(std::ostream& os, std::ostream& paren) = 0;
+ virtual void printTermDeclarations(std::ostream& os, std::ostream& paren) = 0;
+ virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren) = 0;
};
class LFSCBooleanProof : public BooleanProof {
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 printOwnedTerm(Expr term, std::ostream& os, const LetMap& map);
+ virtual void printOwnedSort(Type type, std::ostream& os);
virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren);
- virtual void printDeclarations(std::ostream& os, std::ostream& paren);
+ virtual void printSortDeclarations(std::ostream& os, std::ostream& paren);
+ virtual void printTermDeclarations(std::ostream& os, std::ostream& paren);
+ virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren);
};
-
} /* CVC4 namespace */
#endif /* __CVC4__THEORY_PROOF_H */
#include "theory/uf/theory_uf.h"
#include <stack>
-using namespace CVC4;
-using namespace CVC4::theory;
-using namespace CVC4::theory::uf;
-
+namespace CVC4 {
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;
+ Debug("pf::uf") << "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;
+ Debug("pf::uf") << "+ match " << n1 << " " << n2 << std::endl;
if(n1 == n2) {
return true;
}
}
void ProofUF::toStreamLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, const LetMap& map) {
+ Debug("pf::uf") << "ProofUF::toStreamLFSC starting" << std::endl;
Debug("lfsc-uf") << "Printing uf proof in LFSC : " << std::endl;
pf->debug_print("lfsc-uf");
Debug("lfsc-uf") << std::endl;
}
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;
+ Debug("pf::uf") << std::endl << std::endl << "toStreamRecLFSC called. tb = " << tb << " . proof:" << std::endl;
+ pf->debug_print("pf::uf");
+ Debug("pf::uf") << std::endl;
if(tb == 0) {
- Assert(pf->d_id == eq::MERGED_THROUGH_TRANS);
+ Assert(pf->d_id == theory::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_id = theory::eq::MERGED_THROUGH_TRANS;
subTrans.d_node = pf->d_node;
size_t i = 0;
}
// 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;
+ else if (pf->d_children[i]->d_id==theory::eq::MERGED_THROUGH_CONGRUENCE && pf->d_children[i]->d_node.isNull()) {
+ Debug("pf::uf") << "Handling congruence over equalities" << std::endl;
// Gather the sequence of consecutive congruence closures.
std::vector<const theory::eq::EqProof *> congruenceClosures;
unsigned count;
- Debug("gk::proof") << "Collecting congruence sequence" << std::endl;
+ Debug("pf::uf") << "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_id==theory::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");
+ Debug("pf::uf") << "Found a congruence: " << std::endl;
+ pf->d_children[i+count]->debug_print("pf::uf");
congruenceClosures.push_back(pf->d_children[i+count]);
}
- Debug("gk::proof") << "Total number of congruences found: " << congruenceClosures.size() << std::endl;
+ Debug("pf::uf") << "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;
+ Debug("pf::uf") << "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;
+ Debug("pf::uf") << "Target does not appear after" << std::endl;
targetAppearsAfter = false;
}
// 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)
+ if (pf->d_children[i + j]->d_children[0]->d_id != theory::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)
+ if (pf->d_children[i + j]->d_children[1]->d_id != theory::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)
+ if (pf->d_children[i + count - 1 - j]->d_children[0]->d_id != theory::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)
+ if (pf->d_children[i + count - 1 - j]->d_children[1]->d_id != theory::eq::MERGED_THROUGH_REFLEXIVITY)
orderedEqualities.insert(orderedEqualities.end(), pf->d_children[i + count - 1 - j]->d_children[1]);
}
}
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";
+ Debug("pf::uf") << "\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;
+ Debug("pf::uf") << "\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;
+ Debug("pf::uf") << "\nhave proven: " << n1 << std::endl;
+ Debug("pf::uf") << "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].getNumChildren() > 0) { Debug("pf::uf") << "\nn2[0]: " << n2[0][0] << std::endl; }
+ if (n1.getNumChildren() > 1) { Debug("pf::uf") << "n1[1]: " << n1[1] << std::endl; }
if(n2[0].getKind() == kind::APPLY_UF) {
out << "(trans _ _ _ _ ";
}
switch(pf->d_id) {
- case eq::MERGED_THROUGH_CONGRUENCE: {
- Debug("mgd") << "\nok, looking at congruence:\n";
- pf->debug_print("mgd");
+ case theory::eq::MERGED_THROUGH_CONGRUENCE: {
+ Debug("pf::uf") << "\nok, looking at congruence:\n";
+ pf->debug_print("pf::uf");
std::stack<const theory::eq::EqProof*> stk;
- for(const theory::eq::EqProof* pf2 = pf; pf2->d_id == eq::MERGED_THROUGH_CONGRUENCE; pf2 = pf2->d_children[0]) {
+ for(const theory::eq::EqProof* pf2 = pf; pf2->d_id == theory::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);
+ Assert(stk.top()->d_children[0]->d_id != theory::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);
+ Assert(pf2->d_id == theory::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";
+ Debug("pf::uf") << "\nok, in FIRST cong[" << stk.size() << "]" << "\n";
+ pf2->debug_print("pf::uf");
+ Debug("pf::uf") << "looking at " << pf2->d_node << "\n";
+ Debug("pf::uf") << " " << n1 << "\n";
+ Debug("pf::uf") << " " << n2 << "\n";
int side = 0;
if(match(pf2->d_node, n1[0])) {
//if(tb == 1) {
- Debug("mgd") << "SIDE IS 0\n";
+ Debug("pf::uf") << "SIDE IS 0\n";
//}
side = 0;
} else {
//if(tb == 1) {
- Debug("mgd") << "SIDE IS 1\n";
+ Debug("pf::uf") << "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");
+ Debug("pf::uf") << "IN BAD CASE, our first subproof is\n";
+ pf2->d_children[0]->debug_print("pf::uf");
}
Assert(match(pf2->d_node, n1[1]));
side = 1;
} 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;
+ Debug("pf::uf") << "pf2->d_node " << pf2->d_node << std::endl;
+ Debug("pf::uf") << "b1.getNumChildren() " << b1.getNumChildren() << std::endl;
+ Debug("pf::uf") << "n1 " << n1 << std::endl;
+ Debug("pf::uf") << "n2 " << n2 << std::endl;
+ Debug("pf::uf") << "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 << ")";
while(!stk.empty()) {
if(tb == 1) {
- Debug("mgd") << "\nMORE TO DO\n";
+ Debug("pf::uf") << "\nMORE TO DO\n";
}
pf2 = stk.top();
stk.pop();
- Assert(pf2->d_id == eq::MERGED_THROUGH_CONGRUENCE);
+ Assert(pf2->d_id == theory::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";
+ Debug("pf::uf") << "\nok, in cong[" << stk.size() << "]" << "\n";
+ Debug("pf::uf") << "looking at " << pf2->d_node << "\n";
+ Debug("pf::uf") << " " << n1 << "\n";
+ Debug("pf::uf") << " " << n2 << "\n";
+ Debug("pf::uf") << " " << b1 << "\n";
+ Debug("pf::uf") << " " << b2 << "\n";
if(pf2->d_node[b1.getNumChildren()] == n2[side]) {
b1 << n2[side];
b2 << n2[1-side];
}
n1 = b1;
n2 = b2;
- Debug("mgd") << "at end assert, got " << pf2->d_node << " and " << n1 << std::endl;
+ Debug("pf::uf") << "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);
}
}
b1.append(n1.begin(), n1.end());
n1 = b1;
- Debug("mgd") << "at[2] end assert, got " << pf2->d_node << " and " << n1 << std::endl;
+ Debug("pf::uf") << "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);
}
}
Node n = (side == 0 ? eqNode(n1, n2) : eqNode(n2, n1));
if(tb == 1) {
- Debug("mgdx") << "\ncong proved: " << n << "\n";
+ Debug("pf::uf") << "\ncong proved: " << n << "\n";
}
return n;
}
- case eq::MERGED_THROUGH_REFLEXIVITY:
+ case theory::eq::MERGED_THROUGH_REFLEXIVITY:
Assert(!pf->d_node.isNull());
Assert(pf->d_children.empty());
out << "(refl _ ";
out << ")";
return eqNode(pf->d_node, pf->d_node);
- case eq::MERGED_THROUGH_EQUALITY:
+ case theory::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: {
+ case theory::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";
+ Debug("pf::uf") << "\ndoing trans proof[[\n";
+ pf->debug_print("pf::uf");
+ Debug("pf::uf") << "\n";
Node n1 = toStreamRecLFSC(ss, tp, pf->d_children[0], tb + 1, map);
- Debug("mgd") << "\ndoing trans proof, got n1 " << n1 << "\n";
+ Debug("pf::uf") << "\ndoing trans proof, got n1 " << n1 << "\n";
if(tb == 1) {
- Debug("mgdx") << "\ntrans proof[0], got n1 " << n1 << "\n";
+ Debug("pf::uf") << "\ntrans proof[0], got n1 " << n1 << "\n";
}
bool identicalEqualities = false;
bool evenLengthSequence;
Node nodeAfterEqualitySequence;
+ std::map<size_t, Node> childToStream;
+
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);
+
+ // It is possible that we've already converted the i'th child to stream. If so,
+ // use previously stored result. Otherwise, convert and store.
+ Node n2;
+ if (childToStream.find(i) != childToStream.end())
+ n2 = childToStream[i];
+ else {
+ n2 = toStreamRecLFSC(ss2, tp, pf->d_children[i], tb + 1, map);
+ childToStream[i] = n2;
+ }
// The following branch is dedicated to handling sequences of identical equalities,
// i.e. trans[ a=b, a=b, a=b ].
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;
+ Debug("pf::uf") << "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;
+ Debug("pf::uf") << "The sequence is just beginning. Determining length..." << std::endl;
// Determine whether the length of this sequence is odd or even.
evenLengthSequence = true;
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;
+ Debug("pf::uf") << "Equality sequence of even length" << std::endl;
+ Debug("pf::uf") << "n1 is: " << n1 << std::endl;
+ Debug("pf::uf") << "n2 is: " << n2 << std::endl;
+ Debug("pf::uf") << "pf-d_node is: " << pf->d_node << std::endl;
+ Debug("pf::uf") << "Next node is: " << nodeAfterEqualitySequence << std::endl;
ss << "(trans _ _ _ _ ";
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."
+ Debug("pf::uf") << "Error: identical equalities over, but hands don't match what we're proving."
<< std::endl;
Assert(false);
}
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;
+ Debug("pf::uf") << "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;
+ Debug("pf::uf") << "Equality sequence length is odd!" << std::endl;
ss.str(ss1.str());
}
- Debug("gk::proof") << "Have proven: " << n1 << std::endl;
+ Debug("pf::uf") << "Have proven: " << n1 << std::endl;
} else {
ss.str(ss1.str());
}
identicalEqualities = false;
}
- Debug("mgd") << "\ndoing trans proof, got n2 " << n2 << "\n";
+ Debug("pf::uf") << "\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";
+ Debug("pf::uf") << "\ntrans proof[" << i << "], got n2 " << n2 << "\n";
+ Debug("pf::uf") << (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";
+ Debug("pf::uf") << n1[0].getId() << " " << n1[1].getId() << " / " << n2[0].getId() << " " << n2[1].getId() << "\n";
+ Debug("pf::uf") << n1[0].getId() << " " << n1[0] << "\n";
+ Debug("pf::uf") << n1[1].getId() << " " << n1[1] << "\n";
+ Debug("pf::uf") << n2[0].getId() << " " << n2[0] << "\n";
+ Debug("pf::uf") << n2[1].getId() << " " << n2[1] << "\n";
+ Debug("pf::uf") << (n1[0] == n2[0]) << "\n";
+ Debug("pf::uf") << (n1[1] == n2[1]) << "\n";
+ Debug("pf::uf") << (n1[0] == n2[1]) << "\n";
+ Debug("pf::uf") << (n1[1] == n2[0]) << "\n";
}
}
ss << "(trans _ _ _ _ ";
// Both elements of the transitivity rule are equalities/iffs
{
if(n1[0] == n2[0]) {
- if(tb == 1) { Debug("mgdx") << "case 1\n"; }
+ if(tb == 1) { Debug("pf::uf") << "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"; }
+ if(tb == 1) { Debug("pf::uf") << "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"; }
+ if(tb == 1) { Debug("pf::uf") << "case 3\n"; }
n1 = eqNode(n2[0], n1[1]);
ss << ss2.str() << " " << ss1.str();
- if(tb == 1) { Debug("mgdx") << "++ proved " << n1 << "\n"; }
+ if(tb == 1) { Debug("pf::uf") << "++ proved " << n1 << "\n"; }
} else if(n1[1] == n2[0]) {
- if(tb == 1) { Debug("mgdx") << "case 4\n"; }
+ if(tb == 1) { Debug("pf::uf") << "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);
+ pf->debug_print("pf::uf",0);
//toStreamRec(Warning.getStream(), pf, 0);
Warning() << "\n\n";
Unreachable();
}
- Debug("mgd") << "++ trans proof[" << i << "], now have " << n1 << std::endl;
+ Debug("pf::uf") << "++ 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) {
ss << ")";
}
out << ss.str();
- Debug("mgd") << "\n++ trans proof done, have proven " << n1 << std::endl;
+ Debug("pf::uf") << "\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;
+ case theory::eq::MERGED_ARRAYS_ROW: {
+ Debug("pf::uf") << "eq::MERGED_ARRAYS_ROW encountered in UF_PROOF" << std::endl;
+ Unreachable();
+
+ Debug("pf::uf") << "row lemma: " << pf->d_node << std::endl;
Assert(pf->d_node.getKind() == kind::EQUAL);
TNode t1, t2, t3, t4;
Node ret;
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";
+ Debug("pf::uf") << "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 &&
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";
+ Debug("pf::uf") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\nt4 " << t4 << "\n";
}
out << "(row _ _ ";
tp->printTerm(t2.toExpr(), out, map);
return ret;
}
- case eq::MERGED_ARRAYS_ROW1: {
- Debug("mgd") << "row1 lemma: " << pf->d_node << std::endl;
+ case theory::eq::MERGED_ARRAYS_ROW1: {
+ Debug("pf::uf") << "eq::MERGED_ARRAYS_ROW1 encountered in UF_PROOF" << std::endl;
+ Unreachable();
+
+ Debug("pf::uf") << "row1 lemma: " << pf->d_node << std::endl;
Assert(pf->d_node.getKind() == kind::EQUAL);
TNode t1, t2, t3;
Node ret;
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";
+ Debug("pf::uf") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\n";
} else {
Assert(pf->d_node[0].getKind() == kind::SELECT &&
pf->d_node[0][0].getKind() == kind::STORE &&
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";
+ Debug("pf::uf") << "t1 " << t1 << "\nt2 " << t2 << "\nt3 " << t3 << "\n";
}
out << "(row1 _ _ ";
tp->printTerm(t1.toExpr(), out, map);
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;
+ Debug("pf::uf") << "theory proof: " << pf->d_node << " by rule " << int(pf->d_id) << std::endl;
AlwaysAssert(false);
return pf->d_node;
}
}
}
-void LFSCUFProof::printTerm(Expr term, std::ostream& os, const LetMap& map) {
- Assert (Theory::theoryOf(term) == THEORY_UF);
+void LFSCUFProof::printOwnedTerm(Expr term, std::ostream& os, const LetMap& map) {
+ Debug("pf::uf") << std::endl << "(pf::uf) LFSCUfProof::printOwnedTerm: term = " << term << std::endl;
+
+ Assert (theory::Theory::theoryOf(term) == theory::THEORY_UF);
if (term.getKind() == kind::VARIABLE ||
term.getKind() == kind::SKOLEM) {
}
os << func << " ";
for (unsigned i = 0; i < term.getNumChildren(); ++i) {
- printTerm(term[i], os, map);
+ d_proofEngine->printBoundTerm(term[i], os, map);
os << ")";
}
if(term.getType().isBoolean()) {
}
}
-void LFSCUFProof::printSort(Type type, std::ostream& os) {
+void LFSCUFProof::printOwnedSort(Type type, std::ostream& os) {
+ Debug("pf::uf") << std::endl << "(pf::uf) LFSCArrayProof::printOwnedSort: type is: " << type << std::endl;
+
Assert (type.isSort());
os << type <<" ";
}
UFProof::printTheoryLemmaProof( lemma, os, paren );
}
-void LFSCUFProof::printDeclarations(std::ostream& os, std::ostream& paren) {
- // declaring the sorts
+void LFSCUFProof::printSortDeclarations(std::ostream& os, std::ostream& paren) {
for (TypeSet::const_iterator it = d_sorts.begin(); it != d_sorts.end(); ++it) {
- os << "(% " << *it << " sort\n";
- paren << ")";
+ if (!ProofManager::currentPM()->wasPrinted(*it)) {
+ os << "(% " << *it << " sort\n";
+ paren << ")";
+ ProofManager::currentPM()->markPrinted(*it);
+ }
}
+}
+void LFSCUFProof::printTermDeclarations(std::ostream& os, std::ostream& paren) {
// declaring the terms
for (ExprSet::const_iterator it = d_declarations.begin(); it != d_declarations.end(); ++it) {
Expr term = *it;
paren << ")";
}
}
+
+void LFSCUFProof::printDeferredDeclarations(std::ostream& os, std::ostream& paren) {
+ // Nothing to do here at this point.
+}
+
+} /* namespace CVC4 */
static void toStreamLFSC(std::ostream& out, TheoryProof * tp, theory::eq::EqProof * pf, const LetMap& map);
};
-
+
namespace theory {
namespace uf {
class TheoryUF;
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);
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 printOwnedTerm(Expr term, std::ostream& os, const LetMap& map);
+ virtual void printOwnedSort(Type type, std::ostream& os);
virtual void printTheoryLemmaProof(std::vector<Expr>& lemma, std::ostream& os, std::ostream& paren);
- virtual void printDeclarations(std::ostream& os, std::ostream& paren);
+ virtual void printSortDeclarations(std::ostream& os, std::ostream& paren);
+ virtual void printTermDeclarations(std::ostream& os, std::ostream& paren);
+ virtual void printDeferredDeclarations(std::ostream& os, std::ostream& paren);
};
bool removable,
bool negated,
ProofRule proof_id,
- TNode from) {
+ TNode from,
+ theory::TheoryId ownerTheory) {
Debug("cnf") << "convertAndAssert(" << node
<< ", removable = " << (removable ? "true" : "false")
<< ", negated = " << (negated ? "true" : "false") << ")" << endl;
Node assertion = negated ? node.notNode() : (Node)node;
Node from_assertion = negated? from.notNode() : (Node) from;
+ d_cnfProof->setExplainerTheory(ownerTheory);
if (proof_id != RULE_INVALID) {
d_cnfProof->pushCurrentAssertion(from.isNull() ? assertion : from_assertion);
d_cnfProof->registerAssertion(from.isNull() ? assertion : from_assertion, proof_id);
});
convertAndAssert(node, negated);
- PROOF(if (d_cnfProof) d_cnfProof->popCurrentAssertion(); );
+ PROOF
+ (if (d_cnfProof) {
+ d_cnfProof->popCurrentAssertion();
+ });
}
void TseitinCnfStream::convertAndAssert(TNode node, bool negated) {
* @param node node to convert and assert
* @param removable whether the sat solver can choose to remove the clauses
* @param negated whether we are asserting the node negated
+ * @param ownerTheory indicates the theory that should invoked to prove the formula.
*/
- virtual void convertAndAssert(TNode node, bool removable, bool negated, ProofRule proof_id, TNode from = TNode::null()) = 0;
-
+ virtual void convertAndAssert(TNode node,
+ bool removable,
+ bool negated,
+ ProofRule proof_id,
+ TNode from = TNode::null(),
+ theory::TheoryId ownerTheory = theory::THEORY_LAST) = 0;
/**
* Get the node that is represented by the given SatLiteral.
* @param literal the literal from the sat solver
* @param negated true if negated
*/
void convertAndAssert(TNode node, bool removable,
- bool negated, ProofRule rule, TNode from = TNode::null());
+ bool negated, ProofRule rule, TNode from = TNode::null(),
+ theory::TheoryId ownerTheory = theory::THEORY_LAST);
/**
* Constructs the stream to use the given sat solver.
proxy->explainPropagation(MinisatSatSolver::toSatLiteral(l),
explanation_cl);
vec<Lit> explanation;
- MinisatSatSolver::toMinisatClause(explanation_cl, explanation);
+ MinisatSatSolver::toMinisatClause(explanation_cl, explanation);
// Sort the literals by trail index level
lemma_lt lt(*this);
/*_________________________________________________________________________________________________
|
| analyze : (confl : Clause*) (out_learnt : vec<Lit>&) (out_btlevel : int&) -> [void]
-|
+|
| Description:
| Analyze conflict and produce a reason clause.
-|
+|
| Pre-conditions:
| * 'out_learnt' is assumed to be cleared.
| * Current decision level must be greater than root level.
-|
+|
| Post-conditions:
| * 'out_learnt[0]' is the asserting literal at level 'out_btlevel'.
-| * If out_learnt.size() > 1 then 'out_learnt[1]' has the greatest decision level of the
+| * If out_learnt.size() > 1 then 'out_learnt[1]' has the greatest decision level of the
| rest of literals. There may be others from the same level though.
| * returns the maximal level of the resolved clauses
-|
+|
|________________________________________________________________________________________________@*/
int Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel)
{
}
}
}
-
+
// Select next clause to look at:
while (!seen[var(trail[index--])]);
p = trail[index+1];
confl = reason(var(p));
seen[var(p)] = 0;
pathC--;
-
+
if ( pathC > 0 && confl != CRef_Undef ) {
PROOF( ProofManager::getSatProof()->addResolutionStep(p, confl, sign(p)); )
}
out_learnt[j++] = out_learnt[i];
} else {
PROOF( ProofManager::getSatProof()->storeLitRedundant(out_learnt[i]); )
- // Literal is redundant, to be safe, mark the level as current assertion level
+ // Literal is redundant, to be safe, mark the level as current assertion level
// TODO: maybe optimize
max_resolution_level = std::max(max_resolution_level, user_level(var(out_learnt[i])));
}
}
}
-
+
}else if (ccmin_mode == 1){
Unreachable();
for (i = j = 1; i < out_learnt.size(); i++){
/*_________________________________________________________________________________________________
|
| analyzeFinal : (p : Lit) -> [void]
-|
+|
| Description:
| Specialized analysis procedure to express the final conflict in terms of assumptions.
| Calculates the (possibly empty) set of assumptions that led to the assignment of 'p', and
if (lemmas.size() > 0) {
recheck = true;
confl = updateLemmas();
- return confl;
+ return confl;
} else {
recheck = proxy->theoryNeedCheck();
return confl;
proxy->theoryPropagate(propagatedLiteralsClause);
vec<Lit> propagatedLiterals;
- MinisatSatSolver::toMinisatClause(propagatedLiteralsClause, propagatedLiterals);
+ MinisatSatSolver::toMinisatClause(propagatedLiteralsClause, propagatedLiterals);
int oldTrailSize = trail.size();
Debug("minisat") << "old trail size is " << oldTrailSize << ", propagating " << propagatedLiterals.size() << " lits..." << std::endl;
/*_________________________________________________________________________________________________
|
| propagateBool : [void] -> [Clause*]
-|
+|
| Description:
| Propagates all enqueued facts. If a conflict arises, the conflicting clause is returned,
| otherwise CRef_Undef.
-|
+|
| Post-conditions:
| * the propagation queue is empty, even if there was a conflict.
|________________________________________________________________________________________________@*/
/*_________________________________________________________________________________________________
|
| reduceDB : () -> [void]
-|
+|
| Description:
| Remove half of the learnt clauses, minus the clauses locked by the current assignment. Locked
| clauses are clauses that are reason to some assignment. Binary clauses are never removed.
|________________________________________________________________________________________________@*/
-struct reduceDB_lt {
+struct reduceDB_lt {
ClauseAllocator& ca;
reduceDB_lt(ClauseAllocator& ca_) : ca(ca_) {}
- bool operator () (CRef x, CRef y) {
- return ca[x].size() > 2 && (ca[y].size() == 2 || ca[x].activity() < ca[y].activity()); }
+ bool operator () (CRef x, CRef y) {
+ return ca[x].size() > 2 && (ca[y].size() == 2 || ca[x].activity() < ca[y].activity()); }
};
void Solver::reduceDB()
{
/*_________________________________________________________________________________________________
|
| simplify : [void] -> [bool]
-|
+|
| Description:
| Simplify the clause database according to the current top-level assigment. Currently, the only
| thing done here is the removal of satisfied clauses, but more things can be put here.
/*_________________________________________________________________________________________________
|
| search : (nof_conflicts : int) (params : const SearchParams&) -> [lbool]
-|
+|
| Description:
-| Search for a model the specified number of conflicts.
+| Search for a model the specified number of conflicts.
| NOTE! Use negative value for 'nof_conflicts' indicate infinity.
-|
+|
| Output:
| 'l_True' if a partial assigment that is consistent with respect to the clauseset is found. If
| all variables are decision variables, this means that the clause set is satisfiable. 'l_False'
max_learnts *= learntsize_inc;
if (verbosity >= 1)
- printf("| %9d | %7d %8d %8d | %8d %8d %6.0f | %6.3f %% |\n",
- (int)conflicts,
- (int)dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]), nClauses(), (int)clauses_literals,
+ printf("| %9d | %7d %8d %8d | %8d %8d %6.0f | %6.3f %% |\n",
+ (int)conflicts,
+ (int)dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]), nClauses(), (int)clauses_literals,
(int)max_learnts, nLearnts(), (double)learnts_literals/nLearnts(), progressEstimate()*100);
}
//=================================================================================================
// Writing CNF to DIMACS:
-//
+//
// FIXME: this needs to be rewritten completely.
static Var mapVar(Var x, vec<Var>& map, Var& max)
for (int i = 0; i < clauses_persistent.size(); i++)
if (!satisfied(ca[clauses_persistent[i]]))
cnt++;
-
+
for (int i = 0; i < clauses_persistent.size(); i++)
if (!satisfied(ca[clauses_persistent[i]])){
Clause& c = ca[clauses_persistent[i]];
{
// Initialize the next region to a size corresponding to the estimated utilization degree. This
// is not precise but should avoid some unnecessary reallocations for the new region:
- ClauseAllocator to(ca.size() - ca.wasted());
+ ClauseAllocator to(ca.size() - ca.wasted());
relocAll(to);
if (verbosity >= 2)
- printf("| Garbage collection: %12d bytes => %12d bytes |\n",
+ printf("| Garbage collection: %12d bytes => %12d bytes |\n",
ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size);
to.moveTo(ca);
}
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)
{
(
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);
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);
+ proxy->updateCRef(old, cr);
}
- // Copy extra data-fields:
+ // 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();
void PropEngine::assertLemma(TNode node, bool negated,
bool removable,
ProofRule rule,
+ theory::TheoryId ownerTheory,
TNode from) {
//Assert(d_inCheckSat, "Sat solver should be in solve()!");
Debug("prop::lemmas") << "assertLemma(" << node << ")" << endl;
// Assert as (possibly) removable
- d_cnfStream->convertAndAssert(node, removable, negated, rule, from);
+ d_cnfStream->convertAndAssert(node, removable, negated, rule, from, ownerTheory);
}
void PropEngine::requirePhase(TNode n, bool phase) {
* @param removable whether this lemma can be quietly removed based
* on an activity heuristic (or not)
*/
- void assertLemma(TNode node, bool negated, bool removable, ProofRule rule, TNode from = TNode::null());
+ void assertLemma(TNode node, bool negated, bool removable, ProofRule rule, theory::TheoryId ownerTheory, TNode from = TNode::null());
/**
* If ever n is decided upon, it must be in the given phase. This
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();
- Node::const_iterator it_end = theoryExplanation.end();
+
+ NodeTheoryPair theoryExplanation = d_theoryEngine->getExplanationAndExplainer(lNode);
+ Node explanationNode = theoryExplanation.node;
+ theory::TheoryId explainerTheory = theoryExplanation.theory;
+
+ PROOF({
+ ProofManager::getCnfProof()->pushCurrentAssertion(explanationNode);
+ ProofManager::getCnfProof()->setExplainerTheory(explainerTheory);
+
+ Debug("pf::sat") << "TheoryProxy::explainPropagation: setting explainer theory to: "
+ << explainerTheory << std::endl;
+ });
+
+ Debug("prop-explain") << "explainPropagation() => " << explanationNode << std::endl;
+ if (explanationNode.getKind() == kind::AND) {
+ Node::const_iterator it = explanationNode.begin();
+ Node::const_iterator it_end = explanationNode.end();
explanation.push_back(l);
for (; it != it_end; ++ it) {
explanation.push_back(~d_cnfStream->getLiteral(*it));
}
} else {
explanation.push_back(l);
- explanation.push_back(~d_cnfStream->getLiteral(theoryExplanation));
+ explanation.push_back(~d_cnfStream->getLiteral(explanationNode));
}
}
if(lemmaCount % 1 == 0) {
Debug("shared") << "=) " << asNode << std::endl;
}
- d_propEngine->assertLemma(d_theoryEngine->preprocess(asNode), false, true, RULE_INVALID);
+ d_propEngine->assertLemma(d_theoryEngine->preprocess(asNode), false, true, RULE_INVALID, theory::THEORY_LAST);
} else {
Debug("shared") << "=(" << asNode << std::endl;
}
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()) {
+ if ( !(d_logic.isPure(theory::THEORY_BOOL) ||
+ d_logic.isPure(theory::THEORY_BV) ||
+ d_logic.isPure(theory::THEORY_ARRAY) ||
+ (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/BV proofs yet" << endl;
return;
}
- char* pfFile = strdup("/tmp/cvc4_proof.XXXXXX");
+ char const* tempDir = getenv("TMPDIR");
+ if (!tempDir) {
+ tempDir = "/tmp";
+ }
+
+ stringstream pfPath;
+ pfPath << tempDir << "/cvc4_proof.XXXXXX";
+
+ char* pfFile = strdup(pfPath.str().c_str());
int fd = mkstemp(pfFile);
// ensure this temp file is removed after
in_stores->deleteSelf();
}
-ArrayInfo::ArrayInfo(context::Context* c, Backtracker<TNode>* b)
+ArrayInfo::ArrayInfo(context::Context* c, Backtracker<TNode>* b, std::string statisticsPrefix)
: ct(c), bck(b), info_map(),
- d_mergeInfoTimer("theory::arrays::mergeInfoTimer"),
- d_avgIndexListLength("theory::arrays::avgIndexListLength"),
- d_avgStoresListLength("theory::arrays::avgStoresListLength"),
- d_avgInStoresListLength("theory::arrays::avgInStoresListLength"),
- d_listsCount("theory::arrays::listsCount",0),
- d_callsMergeInfo("theory::arrays::callsMergeInfo",0),
- d_maxList("theory::arrays::maxList",0),
- d_tableSize("theory::arrays::infoTableSize", info_map) {
+ d_mergeInfoTimer(statisticsPrefix + "theory::arrays::mergeInfoTimer"),
+ d_avgIndexListLength(statisticsPrefix + "theory::arrays::avgIndexListLength"),
+ d_avgStoresListLength(statisticsPrefix + "theory::arrays::avgStoresListLength"),
+ d_avgInStoresListLength(statisticsPrefix + "theory::arrays::avgInStoresListLength"),
+ d_listsCount(statisticsPrefix + "theory::arrays::listsCount",0),
+ d_callsMergeInfo(statisticsPrefix + "theory::arrays::callsMergeInfo",0),
+ d_maxList(statisticsPrefix + "theory::arrays::maxList",0),
+ d_tableSize(statisticsPrefix + "theory::arrays::infoTableSize", info_map) {
emptyList = new(true) CTNodeList(ct);
emptyInfo = new Info(ct, bck);
smtStatisticsRegistry()->registerStat(&d_mergeInfoTimer);
} else {
(*it).second->isNonLinear = true;
}
-
+
}
void ArrayInfo::setRIntro1Applied(const TNode a) {
} else {
(*it).second->rIntro1Applied = true;
}
-
+
}
void ArrayInfo::setModelRep(const TNode a, const TNode b) {
} else {
(*it).second->modelRep = b;
}
-
+
}
void ArrayInfo::setConstArr(const TNode a, const TNode constArr) {
currentStatisticsRegistry()->registerStat(&d_maxList);
currentStatisticsRegistry()->registerStat(&d_tableSize);
}*/
- ArrayInfo(context::Context* c, Backtracker<TNode>* b);
+
+ ArrayInfo(context::Context* c, Backtracker<TNode>* b, std::string statisticsPrefix = "");
~ArrayInfo();
typerule ARR_TABLE_FUN ::CVC4::theory::arrays::ArrayTableFunTypeRule
typerule ARRAY_LAMBDA ::CVC4::theory::arrays::ArrayLambdaTypeRule
+operator PARTIAL_SELECT_0 0:2 "partial array select, for internal use only"
+operator PARTIAL_SELECT_1 0:2 "partial array select, for internal use only"
+typerule PARTIAL_SELECT_0 ::CVC4::theory::arrays::ArrayPartialSelectTypeRule
+typerule PARTIAL_SELECT_1 ::CVC4::theory::arrays::ArrayPartialSelectTypeRule
+
# store operations that are ordered (by index) over a store-all are constant
construle STORE ::CVC4::theory::arrays::ArrayStoreTypeRule
#include "expr/kind.h"
#include "options/arrays_options.h"
#include "options/smt_options.h"
+#include "proof/array_proof.h"
+#include "proof/proof_manager.h"
+#include "proof/theory_proof.h"
#include "smt/command.h"
#include "smt/logic_exception.h"
#include "smt/smt_statistics_registry.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;
d_equalityEngine(d_notify, c, name + "theory::arrays::TheoryArrays", true),
d_conflict(c, false),
d_backtracker(c),
- d_infoMap(c, &d_backtracker),
+ d_infoMap(c, &d_backtracker, name),
d_mergeQueue(c),
d_mergeInProgress(false),
d_RowQueue(c),
}/* TheoryArrays::propagate(TNode) */
-void TheoryArrays::explain(TNode literal, std::vector<TNode>& assumptions) {
+void TheoryArrays::explain(TNode literal, std::vector<TNode>& assumptions, eq::EqProof *proof) {
// Do the work
bool polarity = literal.getKind() != kind::NOT;
TNode atom = polarity ? literal : literal[0];
//eq::EqProof * eqp = new eq::EqProof;
- eq::EqProof * eqp = NULL;
+ // eq::EqProof * eqp = 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, proof);
} else {
- d_equalityEngine.explainPredicate(atom, polarity, assumptions);
+ d_equalityEngine.explainPredicate(atom, polarity, assumptions, proof);
}
- if( eqp ){
- Debug("array-pf") << " Proof is : " << std::endl;
- eqp->debug_print("array-pf");
+ if(proof){
+ Debug("pf::array") << " Proof is : " << std::endl;
+ proof->debug_print("pf::array");
}
+
+ Debug("pf::array") << "Array: explain( " << literal << " ):" << std::endl << "\t";
+ for (unsigned i = 0; i < assumptions.size(); ++i) {
+ Debug("pf::array") << assumptions[i] << " ";
+ }
+ Debug("pf::array") << std::endl;
}
TNode TheoryArrays::weakEquivGetRep(TNode node) {
}
}
}
- }
+ }
}
/**
else {
d_equalityEngine.addTerm(node);
}
+
break;
}
// Invariant: preregistered terms are exactly the terms in the equality engine
}
-Node TheoryArrays::explain(TNode literal)
+Node TheoryArrays::explain(TNode literal) {
+ return explain(literal, NULL);
+}
+
+Node TheoryArrays::explain(TNode literal, eq::EqProof *proof)
{
++d_numExplain;
Debug("arrays") << spaces(getSatContext()->getLevel()) << "TheoryArrays::explain(" << literal << ")" << std::endl;
std::vector<TNode> assumptions;
- explain(literal, assumptions);
+ explain(literal, assumptions, proof);
return mkAnd(assumptions);
}
makeEqual = false;
}
}
+
+ Debug("pf::array") << "Pregistering a Skolem" << std::endl;
preRegisterTermInternal(skolem);
+ Debug("pf::array") << "Pregistering a Skolem DONE" << std::endl;
+
if (makeEqual) {
Node d = skolem.eqNode(ref);
Debug("arrays-model-based") << "Asserting skolem equality " << d << endl;
d_skolemAssertions.push_back(d);
d_skolemIndex = d_skolemIndex + 1;
}
+
+ Debug("pf::array") << "getSkolem DONE" << std::endl;
return skolem;
}
// Apply ArrDiseq Rule if diseq is between arrays
if(fact[0][0].getType().isArray() && !d_conflict) {
+ if (d_conflict) { Debug("pf::array") << "Entering the skolemization branch" << std::endl; }
+
NodeManager* nm = NodeManager::currentNM();
TypeNode indexType = fact[0][0].getType()[0];
- TNode k = getSkolem(fact,"array_ext_index", indexType, "an extensional lemma index variable from the theory of arrays", false);
+
+ TNode k;
+ // k is the skolem for this disequality.
+ if (!d_proofsEnabled) {
+ Debug("pf::array") << "Check: kind::NOT: array theory making a skolem" << std::endl;
+
+ // If not in replay mode, generate a fresh skolem variable
+ k = getSkolem(fact,
+ "array_ext_index",
+ indexType,
+ "an extensional lemma index variable from the theory of arrays",
+ false);
+
+ // Register this skolem for the proof replay phase
+ PROOF(ProofManager::getSkolemizationManager()->registerSkolem(fact, k));
+ } else {
+ if (!ProofManager::getSkolemizationManager()->hasSkolem(fact)) {
+ // In the solution pass we didn't need this skolem. Therefore, we don't need it
+ // in this reply pass, either.
+ break;
+ }
+
+ // Reuse the same skolem as in the solution pass
+ k = ProofManager::getSkolemizationManager()->getSkolem(fact);
+ Debug("pf::array") << "Skolem = " << k << std::endl;
+ }
Node ak = nm->mkNode(kind::SELECT, fact[0][0], k);
Node bk = nm->mkNode(kind::SELECT, fact[0][1], k);
Node eq = ak.eqNode(bk);
Node lemma = fact[0].orNode(eq.notNode());
+
+ // In solve mode we don't care if ak and bk are registered. If they aren't, they'll be registered
+ // when we output the lemma. However, in replay need the lemma to be propagated, and so we
+ // preregister manually.
+ if (d_proofsEnabled) {
+ if (!d_equalityEngine.hasTerm(ak)) { preRegisterTermInternal(ak); }
+ if (!d_equalityEngine.hasTerm(bk)) { preRegisterTermInternal(bk); }
+ }
+
if (options::arraysPropagate() > 0 && d_equalityEngine.hasTerm(ak) && d_equalityEngine.hasTerm(bk)) {
// Propagate witness disequality - might produce a conflict
d_permRef.push_back(lemma);
- d_equalityEngine.assertEquality(eq, false, lemma, eq::MERGED_ARRAYS_EXT);
+ Debug("pf::array") << "Asserting to the equality engine:" << std::endl
+ << "\teq = " << eq << std::endl
+ << "\treason = " << fact << std::endl;
+
+ d_equalityEngine.assertEquality(eq, false, fact, eq::MERGED_ARRAYS_EXT);
++d_numProp;
}
- Trace("arrays-lem")<<"Arrays::addExtLemma " << lemma <<"\n";
- d_out->lemma(lemma);
- ++d_numExt;
+
+ if (!d_proofsEnabled) {
+ // If this is the solution pass, generate the lemma. Otherwise, don't generate it -
+ // as this is the lemma that we're reproving...
+ Trace("arrays-lem")<<"Arrays::addExtLemma " << lemma <<"\n";
+ d_out->lemma(lemma);
+ ++d_numExt;
+ }
+ } else {
+ Debug("pf::array") << "Check: kind::NOT: array theory NOT making a skolem" << std::endl;
+ d_modelConstraints.push_back(fact);
}
}
break;
- default:
- Unreachable();
+ default:
+ Unreachable();
}
}
weakEquivBuildCond(r2[0], r[1], conjunctions);
lemma = mkAnd(conjunctions, true);
// LSH FIXME: which kind of arrays lemma is this
+ Trace("arrays-lem") << "Arrays::addExtLemma " << lemma <<"\n";
d_out->lemma(lemma, RULE_INVALID, false, false, true);
d_readTableContext->pop();
+ Trace("arrays") << spaces(getSatContext()->getLevel()) << "Arrays::check(): done" << endl;
return;
}
}
if(!options::arraysEagerLemmas() && fullEffort(e) && !d_conflict && !options::arraysWeakEquivalence()) {
// generate the lemmas on the worklist
- Trace("arrays-lem")<<"Arrays::discharging lemmas: "<<d_RowQueue.size()<<"\n";
+ Trace("arrays-lem")<< "Arrays::discharging lemmas. Number of queued lemmas: " << d_RowQueue.size() << "\n";
while (d_RowQueue.size() > 0 && !d_conflict) {
if (dischargeLemmas()) {
break;
void TheoryArrays::propagate(RowLemmaType lem)
{
+ Debug("pf::array") << "TheoryArrays: RowLemma Propagate called. options::arraysPropagate() = "
+ << options::arraysPropagate() << std::endl;
+
TNode a = lem.first;
TNode b = lem.second;
TNode i = lem.third;
void TheoryArrays::queueRowLemma(RowLemmaType lem)
{
+ Debug("pf::array") << "Array solver: queue row lemma called" << std::endl;
+
if (d_conflict || d_RowAlreadyAdded.contains(lem)) {
return;
}
// Prefer equality between indexes so as not to introduce new read terms
if (options::arraysEagerIndexSplitting() && !bothExist && !d_equalityEngine.areDisequal(i,j, false)) {
- Node i_eq_j = d_valuation.ensureLiteral(i.eqNode(j));
+ Node i_eq_j;
+ if (!d_proofsEnabled) {
+ i_eq_j = d_valuation.ensureLiteral(i.eqNode(j)); // TODO: think about this
+ } else {
+ i_eq_j = i.eqNode(j);
+ }
+
getOutputChannel().requirePhase(i_eq_j, true);
d_decisionRequests.push(i_eq_j);
}
// TODO: maybe add triggers here
- if (options::arraysEagerLemmas() || bothExist) {
+ if ((options::arraysEagerLemmas() || bothExist) && !d_proofsEnabled) {
// Make sure that any terms introduced by rewriting are appropriately stored in the equality database
Node aj2 = Rewriter::rewrite(aj);
}
void TheoryArrays::conflict(TNode a, TNode b) {
+ Debug("pf::array") << "TheoryArrays::Conflict called" << std::endl;
+ eq::EqProof* proof = d_proofsEnabled ? new eq::EqProof() : NULL;
if (a.getKind() == kind::CONST_BOOLEAN) {
- d_conflictNode = explain(a.iffNode(b));
+ d_conflictNode = explain(a.iffNode(b), proof);
} else {
- d_conflictNode = explain(a.eqNode(b));
+ d_conflictNode = explain(a.eqNode(b), proof);
}
+
if (!d_inCheckModel) {
- d_out->conflict(d_conflictNode);
+ if (proof) { proof->debug_print("pf::array"); }
+ ProofArray* proof_array = d_proofsEnabled ? new ProofArray( proof ) : NULL;
+ d_out->conflict(d_conflictNode, proof_array);
}
+
d_conflict = true;
}
TheoryArrays(context::Context* c, context::UserContext* u, OutputChannel& out,
Valuation valuation, const LogicInfo& logicInfo,
- std::string instanceName = "");
+ std::string name = "");
~TheoryArrays();
void setMasterEqualityEngine(eq::EqualityEngine* eq);
bool propagate(TNode literal);
/** Explain why this literal is true by adding assumptions */
- void explain(TNode literal, std::vector<TNode>& assumptions);
+ void explain(TNode literal, std::vector<TNode>& assumptions, eq::EqProof *proof);
/** For debugging only- checks invariants about when things are preregistered*/
context::CDHashSet<Node, NodeHashFunction > d_isPreRegistered;
void preRegisterTerm(TNode n);
void propagate(Effort e);
+ Node explain(TNode n, eq::EqProof *proof);
Node explain(TNode n);
/////////////////////////////////////////////////////////////////////////////
}
};/* struct ArraysProperties */
+
+struct ArrayPartialSelectTypeRule {
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
+ throw (TypeCheckingExceptionPrivate, AssertionException) {
+ Assert(n.getKind() == kind::PARTIAL_SELECT_0 || n.getKind() == kind::PARTIAL_SELECT_1);
+ return nodeManager->integerType();
+ }
+};/* struct ArrayPartialSelectTypeRule */
+
}/* CVC4::theory::arrays namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
// 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);
+ AlwaysAssert (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER);
storeBBAtom(node, atom_bb);
d_cnfStream->convertAndAssert(atom_definition, false, false, RULE_INVALID, TNode::null());
}
if( d_bvp ){
d_bvp->registerAtomBB(atom.toExpr(), atom_bb.toExpr());
}
- d_bbAtoms.insert(atom);
+ d_bbAtoms.insert(atom);
}
void EagerBitblaster::storeBBTerm(TNode node, const Bits& bits) {
void EagerBitblaster::makeVariable(TNode var, Bits& bits) {
Assert(bits.size() == 0);
for (unsigned i = 0; i < utils::getSize(var); ++i) {
- bits.push_back(utils::mkBitOf(var, i));
+ bits.push_back(utils::mkBitOf(var, i));
}
- d_variables.insert(var);
+ d_variables.insert(var);
}
Node EagerBitblaster::getBBAtom(TNode node) const {
- return node;
+ return node;
}
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
- ** \brief Bitblaster for the lazy bv solver.
+ ** \brief Bitblaster for the lazy bv solver.
**
- ** Bitblaster for the lazy bv solver.
+ ** Bitblaster for the lazy bv solver.
**/
#include "bitblaster_template.h"
}
atom_bb = utils::mkAnd(atoms);
}
- Assert (!atom_bb.isNull());
+ Assert (!atom_bb.isNull());
Node atom_definition = utils::mkNode(kind::IFF, node, atom_bb);
storeBBAtom(node, atom_bb);
d_cnfStream->convertAndAssert(atom_definition, false, false, RULE_INVALID, TNode::null());
- return;
+ return;
}
// the bitblasted definition of the atom
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);
if( d_bvp != NULL ){
d_bvp->registerAtomBB(atom.toExpr(), atom_bb.toExpr());
}
- d_bbAtoms.insert(atom);
+ d_bbAtoms.insert(atom);
}
void TLazyBitblaster::storeBBTerm(TNode node, const Bits& bits) {
bool TLazyBitblaster::hasBBAtom(TNode atom) const {
- return d_bbAtoms.find(atom) != d_bbAtoms.end();
+ return d_bbAtoms.find(atom) != d_bbAtoms.end();
}
void TLazyBitblaster::makeVariable(TNode var, Bits& bits) {
Assert(bits.size() == 0);
for (unsigned i = 0; i < utils::getSize(var); ++i) {
- bits.push_back(utils::mkBitOf(var, i));
+ bits.push_back(utils::mkBitOf(var, i));
}
- d_variables.insert(var);
+ d_variables.insert(var);
}
uint64_t TLazyBitblaster::computeAtomWeight(TNode node, NodeSet& seen) {
// cnf conversion ensures the atom represents itself
Node TLazyBitblaster::getBBAtom(TNode node) const {
- return node;
+ return node;
}
void TLazyBitblaster::bbTerm(TNode node, Bits& bits) {
for (unsigned i = 0; i < literal_explanation.size(); ++i) {
explanation.push_back(d_cnfStream->getNode(literal_explanation[i]));
}
- return;
+ return;
}
-
+
std::vector<prop::SatLiteral> literal_explanation;
d_satSolver->explain(lit, literal_explanation);
for (unsigned i = 0; i < literal_explanation.size(); ++i) {
}
}
Debug("bitvector") << "TLazyBitblaster::solve() asserted atoms " << d_assertedAtoms->size() <<"\n";
- d_satSolverFullModel.set(true);
+ d_satSolverFullModel.set(true);
return prop::SAT_VALUE_TRUE == d_satSolver->solve();
}
d_lazyBB->d_explanations->insert(lit, literal_explanation);
} else {
// we propagated it at a lower level
- return true;
+ return true;
}
}
++(d_lazyBB->d_statistics.d_numBitblastingPropagations);
- TNode atom = d_cnf->getNode(lit);
+ TNode atom = d_cnf->getNode(lit);
return d_bv->storePropagation(atom, SUB_BITBLAST);
}
if (a_eq_b == utils::mkTrue()) return theory::EQUALITY_TRUE;
if (!d_satSolverFullModel.get())
- return theory::EQUALITY_UNKNOWN;
-
+ return theory::EQUALITY_UNKNOWN;
+
// Check if cache is valid (invalidated in check and pops)
if (d_bv->d_invalidateModelCache.get()) {
- invalidateModelCache();
+ invalidateModelCache();
}
- d_bv->d_invalidateModelCache.set(false);
+ d_bv->d_invalidateModelCache.set(false);
Node a_value = getTermModel(a, true);
Node b_value = getTermModel(b, true);
if (a_value == b_value) {
Debug("bv-equality-status")<< "theory::EQUALITY_TRUE_IN_MODEL\n";
- return theory::EQUALITY_TRUE_IN_MODEL;
+ return theory::EQUALITY_TRUE_IN_MODEL;
}
Debug("bv-equality-status")<< "theory::EQUALITY_FALSE_IN_MODEL\n";
- return theory::EQUALITY_FALSE_IN_MODEL;
+ return theory::EQUALITY_FALSE_IN_MODEL;
}
}
bool TLazyBitblaster::hasValue(TNode a) {
- Assert (hasBBTerm(a));
+ Assert (hasBBTerm(a));
Bits bits;
- getBBTerm(a, bits);
+ getBBTerm(a, bits);
for (int i = bits.size() -1; i >= 0; --i) {
prop::SatValue bit_value;
if (d_cnfStream->hasLiteral(bits[i])) {
if (!hasBBTerm(a)) {
return fullModel? utils::mkConst(utils::getSize(a), 0u) : Node();
}
-
+
Bits bits;
getBBTerm(a, bits);
Integer value(0);
// not actually a leaf of the bit-vector theory
if (d_variables.find(var) == d_variables.end())
continue;
-
- Assert (Theory::theoryOf(var) == theory::THEORY_BV || isSharedTerm(var));
+
+ Assert (Theory::theoryOf(var) == theory::THEORY_BV || isSharedTerm(var));
// only shared terms could not have been bit-blasted
Assert (hasBBTerm(var) || isSharedTerm(var));
-
+
Node const_value = getModelFromSatSolver(var, fullModel);
- Assert (const_value.isNull() || const_value.isConst());
+ Assert (const_value.isNull() || const_value.isConst());
if(const_value != Node()) {
Debug("bitvector-model") << "TLazyBitblaster::collectModelInfo (assert (= "
<< var << " "
bool SharedTermsDatabase::propagateSharedEquality(TheoryId theory, TNode a, TNode b, bool value)
{
- Debug("shared-terms-database") << "SharedTermsDatabase::newEquality(" << theory << a << "," << b << ", " << (value ? "true" : "false") << ")" << endl;
+ Debug("shared-terms-database") << "SharedTermsDatabase::newEquality(" << theory << "," << a << "," << b << ", " << (value ? "true" : "false") << ")" << endl;
if (d_inConflict) {
return false;
*
*/
bool d_proofsEnabled;
-
+
/**
* Returns the next assertion in the assertFact() queue.
*
void TheoryEngine::preRegister(TNode preprocessed) {
+ Debug("theory") << "TheoryEngine::preRegister( " << preprocessed << ")" << std::endl;
if(Dump.isOn("missed-t-propagations")) {
d_possiblePropagations.push_back(preprocessed);
}
}
Debug("theory") << "TheoryEngine::check(" << effort << "): done, we are " << (d_inConflict ? "unsat" : "sat") << (d_lemmasAdded ? " with new lemmas" : " with no new lemmas");
- Debug("theory") << ", need check = " << needCheck() << endl;
+ Debug("theory") << ", need check = " << (needCheck() ? "YES" : "NO") << endl;
if(!d_inConflict && Theory::fullEffort(effort) && d_masterEqualityEngine != NULL && !d_lemmasAdded) {
AlwaysAssert(d_masterEqualityEngine->consistent());
// We need to split on it
Debug("combineTheories") << "TheoryEngine::combineTheories(): requesting a split " << endl;
- lemma(equality.orNode(equality.notNode()), RULE_INVALID, false, false, false, carePair.theory);
+ lemma(equality.orNode(equality.notNode()), RULE_INVALID, false, false, false, carePair.theory, 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) {
return conjunction;
}
-
-Node TheoryEngine::getExplanation(TNode node) {
+NodeTheoryPair TheoryEngine::getExplanationAndExplainer(TNode node) {
Debug("theory::explain") << "TheoryEngine::getExplanation(" << node << "): current propagation index = " << d_propagationMapTimestamp << endl;
bool polarity = node.getKind() != kind::NOT;
if (!d_logicInfo.isSharingEnabled()) {
Node explanation = theoryOf(atom)->explain(node);
Debug("theory::explain") << "TheoryEngine::getExplanation(" << node << ") => " << explanation << endl;
- return explanation;
+ return NodeTheoryPair(explanation, theoryOf(atom)->getId());
}
// Initial thing to explain
NodeTheoryPair toExplain(node, THEORY_SAT_SOLVER, d_propagationMapTimestamp);
Assert(d_propagationMap.find(toExplain) != d_propagationMap.end());
+
+ NodeTheoryPair nodeExplainerPair = d_propagationMap[toExplain];
+ TheoryId explainer = nodeExplainerPair.theory;
+
// Create the workplace for explanations
std::vector<NodeTheoryPair> explanationVector;
explanationVector.push_back(d_propagationMap[toExplain]);
Debug("theory::explain") << "TheoryEngine::getExplanation(" << node << ") => " << explanation << endl;
- return explanation;
+ return NodeTheoryPair(explanation, explainer);
+}
+
+Node TheoryEngine::getExplanation(TNode node) {
+ return getExplanationAndExplainer(node).node;
}
struct AtomsCollect {
bool negated,
bool removable,
bool preprocess,
- theory::TheoryId atomsTo) {
+ theory::TheoryId atomsTo,
+ theory::TheoryId ownerTheory) {
// For resource-limiting (also does a time check).
// spendResource();
d_channels->getLemmaOutputChannel()->notifyNewLemma(node.toExpr());
}
+ std::vector<Node> additionalLemmas;
+ IteSkolemMap iteSkolemMap;
+
// Run theory preprocessing, maybe
Node ppNode = preprocess ? this->preprocess(node) : Node(node);
// Remove the ITEs
- std::vector<Node> additionalLemmas;
- IteSkolemMap iteSkolemMap;
additionalLemmas.push_back(ppNode);
d_iteRemover.run(additionalLemmas, iteSkolemMap);
additionalLemmas[0] = theory::Rewriter::rewrite(additionalLemmas[0]);
}
// assert to prop engine
- d_propEngine->assertLemma(additionalLemmas[0], negated, removable, rule, node);
+ d_propEngine->assertLemma(additionalLemmas[0], negated, removable, rule, ownerTheory, node);
for (unsigned i = 1; i < additionalLemmas.size(); ++ i) {
additionalLemmas[i] = theory::Rewriter::rewrite(additionalLemmas[i]);
- d_propEngine->assertLemma(additionalLemmas[i], false, removable, rule, node);
+ d_propEngine->assertLemma(additionalLemmas[i], false, removable, rule, ownerTheory, node);
}
// WARNING: Below this point don't assume additionalLemmas[0] to be not negated.
Node fullConflict = mkExplanation(explanationVector);
Debug("theory::conflict") << "TheoryEngine::conflict(" << conflict << ", " << theoryId << "): full = " << fullConflict << endl;
Assert(properConflict(fullConflict));
- lemma(fullConflict, RULE_CONFLICT, true, true, false, THEORY_LAST);
+ lemma(fullConflict, RULE_CONFLICT, true, true, false, THEORY_LAST, theoryId);
} else {
// When only one theory, the conflict should need no processing
Assert(properConflict(conflict));
- lemma(conflict, RULE_CONFLICT, true, true, false, THEORY_LAST);
+ lemma(conflict, RULE_CONFLICT, true, true, false, THEORY_LAST, theoryId);
}
}
Node node;
theory::TheoryId theory;
size_t timestamp;
- NodeTheoryPair(TNode node, theory::TheoryId theory, size_t timestamp)
+ NodeTheoryPair(TNode node, theory::TheoryId theory, size_t timestamp = 0)
: node(node), theory(theory), timestamp(timestamp) {}
NodeTheoryPair()
: theory(theory::THEORY_LAST) {}
{
}
- void safePoint(uint64_t ammount) throw(theory::Interrupted, UnsafeInterruptException, AssertionException) {
+ void safePoint(uint64_t ammount) throw(theory::Interrupted, UnsafeInterruptException, AssertionException) {
spendResource(ammount);
if (d_engine->d_interrupted) {
throw theory::Interrupted();
Trace("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::lemma(" << lemma << ")" << std::endl;
++ d_statistics.lemmas;
d_engine->d_outputChannelUsed = true;
- return d_engine->lemma(lemma, rule, false, removable, preprocess, sendAtoms ? d_theory: theory::THEORY_LAST);
+ return d_engine->lemma(lemma, rule, false, removable, preprocess, sendAtoms ? d_theory : theory::THEORY_LAST, d_theory);
}
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, RULE_SPLIT, false, removable, false, d_theory);
+ return d_engine->lemma(lemma, RULE_SPLIT, false, removable, false, d_theory, d_theory);
}
void demandRestart() throw(TypeCheckingExceptionPrivate, AssertionException, UnsafeInterruptException) {
bool negated,
bool removable,
bool preprocess,
- theory::TheoryId atomsTo);
+ theory::TheoryId atomsTo,
+ theory::TheoryId ownerTheory);
/** Enusre that the given atoms are send to the given theory */
void ensureLemmaAtoms(const std::vector<TNode>& atoms, theory::TheoryId theory);
*/
Node getExplanation(TNode node);
+ /**
+ * Returns an explanation of the node propagated to the SAT solver and the theory
+ * that propagated it.
+ */
+ NodeTheoryPair getExplanationAndExplainer(TNode node);
+
/**
* collect model info
*/
*/
void printSynthSolution( std::ostream& out );
- /**
- * Get instantiations
+ /**
+ * Get instantiations
*/
void getInstantiations( std::map< Node, std::vector< Node > >& insts );
smtStatisticsRegistry()->unregisterStat(&constantTermsCount);
}
-
/**
* Data used in the BFS search through the equality graph.
*/
}
void EqualityEngine::enqueue(const MergeCandidate& candidate, bool back) {
- Debug("equality") << d_name << "::eq::enqueue(" << d_nodes[candidate.t1Id] << ", " << d_nodes[candidate.t2Id] << ", " << candidate.type << ")" << std::endl;
+ Debug("equality") << d_name << "::eq::enqueue(" << d_nodes[candidate.t1Id] << ", " << d_nodes[candidate.t2Id] << ", " << candidate.type << "). reason: " << candidate.reason << std::endl;
if (back) {
d_propagationQueue.push_back(candidate);
} else {
}
void EqualityEngine::explainEquality(TNode t1, TNode t2, bool polarity, std::vector<TNode>& equalities, EqProof * eqp) const {
- Debug("equality") << d_name << "::eq::explainEquality(" << t1 << ", " << t2 << ", " << (polarity ? "true" : "false") << ")" << std::endl;
+ Debug("equality") << d_name << "::eq::explainEquality(" << t1 << ", " << t2 << ", " << (polarity ? "true" : "false") << ")" << ", proof = " << (eqp ? "ON" : "OFF") << std::endl;
// The terms must be there already
Assert(hasTerm(t1) && hasTerm(t2));;
// Get the explanation
getExplanation(t1Id, t2Id, equalities, eqp);
} else {
+ if (eqp) {
+ eqp->d_id = eq::MERGED_THROUGH_TRANS;
+ eqp->d_node = d_nodes[t1Id].eqNode(d_nodes[t2Id]).notNode();
+ }
+
// Get the reason for this disequality
EqualityPair pair(t1Id, t2Id);
Assert(d_disequalityReasonsMap.find(pair) != d_disequalityReasonsMap.end(), "Don't ask for stuff I didn't notify you about");
DisequalityReasonRef reasonRef = d_disequalityReasonsMap.find(pair)->second;
+
for (unsigned i = reasonRef.mergesStart; i < reasonRef.mergesEnd; ++ i) {
EqualityPair toExplain = d_deducedDisequalityReasons[i];
- getExplanation(toExplain.first, toExplain.second, equalities, eqp);
+ }
+
+ for (unsigned i = reasonRef.mergesStart; i < reasonRef.mergesEnd; ++ i) {
+
+ EqualityPair toExplain = d_deducedDisequalityReasons[i];
+ EqProof* eqpc = NULL;
+
+ // If we're constructing a (transitivity) proof, we don't need to include an explanation for x=x.
+ if (eqp && toExplain.first != toExplain.second) {
+ eqpc = new EqProof;
+ }
+
+ // Some edges have the form ((a == b) == false). Translate this into (not (a == b)).
+ // Assert(d_nodes[toExplain.first] != NodeManager::currentNM()->mkConst(false));
+
+ getExplanation(toExplain.first, toExplain.second, equalities, eqpc);
+
+ // if (eqpc) {
+ // eqp->d_children.push_back(eqpc);
+ // }
+
+ if (eqpc) {
+ Debug("pf::ee") << "Child proof is:" << std::endl;
+ eqpc->debug_print("pf::ee", 1);
+
+ if (eqpc->d_id == eq::MERGED_THROUGH_TRANS) {
+ std::vector<EqProof *> orderedChildren;
+ bool nullCongruenceFound = false;
+ for (unsigned i = 0; i < eqpc->d_children.size(); ++i) {
+ if (eqpc->d_children[i]->d_id==eq::MERGED_THROUGH_CONGRUENCE && eqpc->d_children[i]->d_node.isNull()) {
+
+ // For now, assume there can only be one null congruence child
+ Assert(!nullCongruenceFound);
+ nullCongruenceFound = true;
+
+ Debug("pf::ee") << "Have congruence with empty d_node. Splitting..." << std::endl;
+ orderedChildren.insert(orderedChildren.begin(), eqpc->d_children[i]->d_children[0]);
+ orderedChildren.push_back(eqpc->d_children[i]->d_children[1]);
+ } else {
+ orderedChildren.push_back(eqpc->d_children[i]);
+ }
+ }
+
+ if (nullCongruenceFound) {
+ eqpc->d_children = orderedChildren;
+ Debug("pf::ee") << "Child proof's children have been reordered. It is now:" << std::endl;
+ eqpc->debug_print("pf::ee", 1);
+ }
+ }
+
+ eqp->d_children.push_back(eqpc);
+ }
+ }
+
+ if (eqp) {
+ if(eqp->d_children.size() == 1) {
+ // The transitivity proof has just one child. Simplify.
+ EqProof* temp = eqp->d_children[0];
+ eqp->d_children.clear();
+ *eqp = *temp;
+ delete temp;
+ }
+
+ Debug("pf::ee") << "Disequality explanation final proof: " << std::endl;
+ eqp->debug_print("pf::ee", 1);
}
}
}
// If the nodes are the same, we're done
if (t1Id == t2Id){
if( eqp ) {
- eqp->d_node = ProofManager::currentPM()->mkOp(d_nodes[t1Id]);
+ if ((d_nodes[t1Id].getKind() == kind::BUILTIN) && (d_nodes[t1Id].getConst<Kind>() == kind::SELECT)) {
+ std::vector<Node> no_children;
+ eqp->d_node = NodeManager::currentNM()->mkNode(kind::PARTIAL_SELECT_0, no_children);
+ } else {
+ eqp->d_node = ProofManager::currentPM()->mkOp(d_nodes[t1Id]);
+ }
}
return;
}
Debug("equality") << d_name << "::eq::getExplanation(): path found: " << std::endl;
- std::vector< EqProof * > eqp_trans;
+ std::vector<EqProof *> eqp_trans;
// Reconstruct the path
do {
MergeReasonType reasonType = d_equalityEdges[currentEdge].getReasonType();
Debug("equality") << d_name << "::eq::getExplanation(): currentEdge = " << currentEdge << ", currentNode = " << currentNode << std::endl;
+ Debug("equality") << d_name << " targetNode = " << d_nodes[edgeNode] << std::endl;
Debug("equality") << d_name << " in currentEdge = (" << d_nodes[currentNode] << "," << d_nodes[edge.getNodeId()] << ")" << std::endl;
+ Debug("equality") << d_name << " reason type = " << reasonType << std::endl;
- EqProof * eqpc = NULL;
- //make child proof if a proof is being constructed
- if( eqp ){
+ EqProof* eqpc = NULL;
+ // Make child proof if a proof is being constructed
+ if (eqp) {
eqpc = new EqProof;
eqpc->d_id = reasonType;
}
Debug("equality") << d_name << "::eq::getExplanation(): due to congruence, going deeper" << std::endl;
const FunctionApplication& f1 = d_applications[currentNode].original;
const FunctionApplication& f2 = d_applications[edgeNode].original;
+
+ Debug("pf::ee") << "We need to prove two equalities:" << std::endl;
+ Debug("pf::ee") << "\tLHS: " << d_nodes[f1.a] << " = " << d_nodes[f2.a] << std::endl;
+ Debug("pf::ee") << "\tRHS: " << d_nodes[f1.b] << " = " << d_nodes[f2.b] << std::endl;
+
Debug("equality") << push;
+ Debug("equality") << "Explaining left hand side equalities" << std::endl;
EqProof * eqpc1 = eqpc ? new EqProof : NULL;
getExplanation(f1.a, f2.a, equalities, eqpc1);
+ Debug("equality") << "Explaining right hand side equalities" << std::endl;
EqProof * eqpc2 = eqpc ? new EqProof : NULL;
getExplanation(f1.b, f2.b, equalities, eqpc2);
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;
+ Debug("pf::ee") << "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;
+ Debug("pf::ee") << 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("pf::ee") << "f1.a is: " << d_nodes[f1.a]
+ << ". kind is: " << d_nodes[f1.a].getKind() << std::endl;
+
+ if (d_nodes[f1.a].getKind() == kind::BUILTIN && d_nodes[f1.a].getConst<Kind>() == kind::SELECT) {
+ Debug("pf::ee") << "f1.a getConst<kind> is: " << d_nodes[f1.a].getConst<Kind>() << std::endl;
+
+ eqpc->d_node = NodeManager::currentNM()->mkNode(kind::PARTIAL_SELECT_1, d_nodes[f1.b]);
+ // The first child is a PARTIAL_SELECT_0. Give it a child so that we know what kind of (read) it is, when we dump to LFSC.
+ Debug("pf::ee") << "eqpc->d_children[0]->d_node.getKind() == " << eqpc->d_children[0]->d_node.getKind() << std::endl;
+ Assert(eqpc->d_children[0]->d_node.getKind() == kind::PARTIAL_SELECT_0);
+ Assert(eqpc->d_children[0]->d_children.size() == 0);
+
+ Debug("pf::ee") << "Dumping the equality proof before:" << std::endl;
+ eqpc->debug_print("pf::ee", 1);
+
+ eqpc->d_children[0]->d_node = NodeManager::currentNM()->mkNode(kind::PARTIAL_SELECT_0, d_nodes[f1.b]);
+
+ Debug("pf::ee") << "Dumping the equality proof after:" << std::endl;
+ eqpc->debug_print("pf::ee", 1);
+
+ //eqpc->d_children[0]->d_node.append(d_nodes[f1.b]);
+ } else {
+ eqpc->d_node = NodeManager::currentNM()->mkNode(kind::PARTIAL_APPLY_UF,
+ ProofManager::currentPM()->mkOp(d_nodes[f1.a]),
+ d_nodes[f1.b]);
+ }
+ Debug("pf::ee") << "New d_node is: " << eqpc->d_node << std::endl;
}
}
}
break;
}
+ case MERGED_ARRAYS_EXT:
+
+ Debug("equality") << d_name << "::eq::getExplanation(): MERGED_ARRAYS_EXT" << std::endl;
+
+ if (eqpc) {
+ Node a = d_nodes[d_equalityEdges[currentEdge].getNodeId()];
+ Node b = d_nodes[currentNode];
+
+ // GK: todo: here we assume that a=b is an assertion. We should probably call explain()
+ // recursively, to explain this.
+
+ if (a == NodeManager::currentNM()->mkConst(false)) {
+ eqpc->d_node = b.notNode();
+ } else if (b == NodeManager::currentNM()->mkConst(false)) {
+ eqpc->d_node = a.notNode();
+ } else {
+ eqpc->d_node = a.eqNode(b);
+ }
+
+ EqProof* eqpc1 = new EqProof;
+ eqpc1->d_node = d_equalityEdges[currentEdge].getReason();
+ eqpc->d_children.push_back( eqpc1 );
+
+ eqpc1->debug_print("pf::ee", 1);
+ eqpc->debug_print("pf::ee", 1);
+ }
+
+ // We push the reason into "equalities" because that's what the theory of arrays expects.
+ equalities.push_back(d_equalityEdges[currentEdge].getReason());
+ break;
+
+ case MERGED_ARRAYS_ROW: {
+ Debug("equality") << d_name << "::eq::getExplanation(): MERGED_ARRAYS_ROW" << std::endl;
+
+ // ROW rules mean that (i==k) OR ((a[i]:=t)[k] == a[k])
+ // The equality here will be either (i == k) because ((a[i]:=t)[k] != a[k]),
+ // or ((a[i]:=t)[k] == a[k]) because (i != k).
+
+ if (eqpc) {
+ if (d_nodes[currentNode].getNumChildren() == 2) {
+ // This is the case of ((a[i]:=t)[k] == a[k]) because (i != k).
+
+ // The edge is ((a[i]:=t)[k], a[k]), or (a[k], (a[i]:=t)[k]). This flag should be
+ // false in the first case and true in the second case.
+ bool currentNodeIsUnchangedArray;
+
+ Assert(d_nodes[currentNode].getNumChildren() == 2);
+ Assert(d_nodes[edgeNode].getNumChildren() == 2);
+
+ if (d_nodes[currentNode][0].getKind() == kind::VARIABLE ||
+ d_nodes[currentNode][0].getKind() == kind::SKOLEM) {
+ currentNodeIsUnchangedArray = true;
+ } else if (d_nodes[edgeNode][0].getKind() == kind::VARIABLE ||
+ d_nodes[edgeNode][0].getKind() == kind::SKOLEM) {
+ currentNodeIsUnchangedArray = false;
+ } else {
+ Assert(d_nodes[currentNode][0].getKind() == kind::STORE);
+ Assert(d_nodes[edgeNode][0].getKind() == kind::STORE);
+
+ if (d_nodes[currentNode][0][0] == d_nodes[edgeNode][0]) {
+ currentNodeIsUnchangedArray = false;
+ } else if (d_nodes[edgeNode][0][0] == d_nodes[currentNode][0]) {
+ currentNodeIsUnchangedArray = true;
+ } else {
+ Unreachable();
+ }
+ }
+
+ Node indexOne =
+ currentNodeIsUnchangedArray ? d_nodes[currentNode][1] : d_nodes[currentNode][0][1];
+ Node indexTwo =
+ currentNodeIsUnchangedArray ? d_nodes[edgeNode][0][1] : d_nodes[edgeNode][1];
+
+ // Some assertions to ensure that the theory of arrays behaves as expected
+ Assert(d_nodes[currentNode][1] == d_nodes[edgeNode][1]);
+ if (currentNodeIsUnchangedArray) {
+ Assert(d_nodes[currentNode][0] == d_nodes[edgeNode][0][0]);
+ } else {
+ Assert(d_nodes[currentNode][0][0] == d_nodes[edgeNode][0]);
+ }
+
+ Debug("pf::ee") << "Getting explanation for ROW guard: "
+ << indexOne << " != " << indexTwo << std::endl;
+
+ EqProof* eqpcc = eqpc ? new EqProof : NULL;
+ explainEquality(indexOne, indexTwo, false, equalities, eqpcc);
+
+ Debug("pf::ee") << "The two indices are: " << indexOne << ", " << indexTwo << std::endl;
+ Debug("pf::ee") << "And the explanation of their disequality is: " << std::endl;
+ eqpcc->debug_print("pf::ee", 1);
+ eqpc->d_children.push_back(eqpcc);
+ } else {
+ // This is the case of (i == k) because ((a[i]:=t)[k] != a[k]),
+
+ Debug("pf::ee") << "In the new case of ROW!" << std::endl;
+
+ Node indexOne = d_nodes[currentNode];
+ Node indexTwo = d_nodes[edgeNode];
+
+ Debug("pf::ee") << "The two indices are: " << indexOne << ", " << indexTwo << std::endl;
+ Debug("pf::ee") << "The reason for the edge is: " << d_equalityEdges[currentEdge].getReason()
+ << std::endl;
+
+ Assert(d_equalityEdges[currentEdge].getReason().getNumChildren() == 2);
+ Node reason = d_equalityEdges[currentEdge].getReason()[1];
+ Debug("pf::ee") << "Getting explanation for ROW guard: " << reason << std::endl;
+
+ EqProof* eqpcc = eqpc ? new EqProof : NULL;
+ explainEquality(reason[0], reason[1], false, equalities, eqpcc);
+
+ if (eqpc) {
+ Debug("pf::ee") << "The guard's explanation is: " << std::endl;
+ eqpcc->debug_print("pf::ee", 1);
+ eqpc->d_children.push_back(eqpcc);
+ }
+ }
+
+ Node a = d_nodes[d_equalityEdges[currentEdge].getNodeId()];
+ Node b = d_nodes[currentNode];
+
+ if (a == NodeManager::currentNM()->mkConst(false)) {
+ eqpc->d_node = b.notNode();
+ } else if (b == NodeManager::currentNM()->mkConst(false)) {
+ eqpc->d_node = a.notNode();
+ } else {
+ eqpc->d_node = a.eqNode(b);
+ }
+ }
+
+ // We push the reason into "equalities" because that's what the theory of arrays expects.
+ equalities.push_back(d_equalityEdges[currentEdge].getReason());
+ break;
+ }
+
default: {
// Construct the equality
Debug("equality") << d_name << "::eq::getExplanation(): adding: " << d_equalityEdges[currentEdge].getReason() << std::endl;
- if( eqpc ){
- if(reasonType == MERGED_THROUGH_EQUALITY) {
+ Debug("equality") << d_name << "::eq::getExplanation(): reason type = " << reasonType << std::endl;
+
+ if (eqpc) {
+ if (reasonType == MERGED_THROUGH_EQUALITY) {
eqpc->d_node = d_equalityEdges[currentEdge].getReason();
} 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;
+ // The LFSC translator prefers (not (= a b)) over (= (a==b) false)
+
+ Node a = d_nodes[d_equalityEdges[currentEdge].getNodeId()];
+ Node b = d_nodes[currentNode];
+
+ if (a == NodeManager::currentNM()->mkConst(false)) {
+ eqpc->d_node = b.notNode();
+ } else if (b == NodeManager::currentNM()->mkConst(false)) {
+ eqpc->d_node = a.notNode();
+ } else {
+ eqpc->d_node = a.eqNode(b);
+ }
+ Debug("pf::ee") << "theory eq : " << eqpc->d_node << std::endl;
}
eqpc->d_id = reasonType;
}
currentIndex = bfsQueue[currentIndex].previousIndex;
//---from Morgan---
- if(eqpc != NULL && eqpc->d_id == MERGED_THROUGH_REFLEXIVITY) {
+ if (eqpc != NULL && eqpc->d_id == MERGED_THROUGH_REFLEXIVITY) {
if(eqpc->d_node.isNull()) {
Assert(eqpc->d_children.size() == 1);
EqProof *p = eqpc;
}
//---end from Morgan---
- eqp_trans.push_back( eqpc );
-
+ eqp_trans.push_back(eqpc);
} while (currentEdge != null_id);
- if(eqp) {
+ if (eqp) {
if(eqp_trans.size() == 1) {
*eqp = *eqp_trans[0];
delete eqp_trans[0];
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]);
}
+
+ eqp->debug_print("pf::ee", 1);
}
// Done
EqualityEdgeId edgeId = d_equalityGraph[nodeId];
while (edgeId != null_edge) {
const EqualityEdge& edge = d_equalityEdges[edgeId];
- Debug("equality::graph") << " " << d_nodes[edge.getNodeId()] << ":" << edge.getReason();
+ Debug("equality::graph") << " [" << edge.getNodeId() << "] " << d_nodes[edge.getNodeId()] << ":" << edge.getReason();
edgeId = edge.getNext();
}
}
bool EqualityEngine::areEqual(TNode t1, TNode t2) const {
- Debug("equality") << d_name << "::eq::areEqual(" << t1 << "," << t2 << ")" << std::endl;
+ Debug("equality") << d_name << "::eq::areEqual(" << t1 << "," << t2 << ")";
Assert(hasTerm(t1));
Assert(hasTerm(t2));
- return getEqualityNode(t1).getFind() == getEqualityNode(t2).getFind();
+ bool result = getEqualityNode(t1).getFind() == getEqualityNode(t2).getFind();
+ Debug("equality") << (result ? "\t(YES)" : "\t(NO)") << std::endl;
+ return result;
}
bool EqualityEngine::areDisequal(TNode t1, TNode t2, bool ensureProof) const
{
- Debug("equality") << d_name << "::eq::areDisequal(" << t1 << "," << t2 << ")" << std::endl;
+ Debug("equality") << d_name << "::eq::areDisequal(" << t1 << "," << t2 << ")";
// Add the terms
Assert(hasTerm(t1));
// If we propagated this disequality we're true
if (hasPropagatedDisequality(t1Id, t2Id)) {
+ Debug("equality") << "\t(YES)" << std::endl;
return true;
}
nonConst->d_deducedDisequalityReasons.push_back(EqualityPair(t2Id, t2ClassId));
nonConst->storePropagatedDisequality(THEORY_LAST, t1Id, t2Id);
}
+ Debug("equality") << "\t(YES)" << std::endl;
return true;
}
nonConst->d_deducedDisequalityReasons.push_back(EqualityPair(t2Id, original.b));
nonConst->storePropagatedDisequality(THEORY_LAST, t1Id, t2Id);
}
+ Debug("equality") << "\t(YES)" << std::endl;
return true;
}
}
nonConst->d_deducedDisequalityReasons.push_back(EqualityPair(t1Id, original.b));
nonConst->storePropagatedDisequality(THEORY_LAST, t1Id, t2Id);
}
+ Debug("equality") << "\t(YES)" << std::endl;
return true;
}
}
// Couldn't deduce dis-equalityReturn whether the terms are disequal
+ Debug("equality") << "\t(NO)" << std::endl;
return false;
}
d_children[i]->debug_print( c, tb+1 );
}
}
- Debug( c ) << ")";
+ Debug( c ) << ")" << std::endl;
}
case MERGED_THROUGH_TRANS:
out << "transitivity";
break;
- default:
+ case MERGED_ARRAYS_ROW:
+ out << "arrays ROW";
+ break;
+ case MERGED_ARRAYS_ROW1:
+ out << "arrays ROW1";
+ break;
+ case MERGED_ARRAYS_EXT:
+ out << "arrays EXT";
+ break;
+default:
out << "[theory]";
break;
}
} // namespace eq
} // namespace theory
} // namespace CVC4
-
TNode fact = assertion.assertion;
Debug("uf") << "TheoryUF::check(): processing " << fact << std::endl;
+ Debug("uf") << "Term's theory: " << theory::Theory::theoryOf(fact.toExpr()) << std::endl;
+
if (d_thss != NULL) {
bool isDecision = d_valuation.isSatLiteral(fact) && d_valuation.isDecision(fact);
d_thss->assertNode(fact, isDecision);
d_equalityEngine.explainPredicate(atom, polarity, assumptions, pf);
}
if( pf ){
- Debug("uf-pf") << std::endl;
- pf->debug_print("uf-pf");
+ Debug("pf::uf") << std::endl;
+ pf->debug_print("pf::uf");
+ }
+
+ Debug("pf::uf") << "UF: explain( " << literal << " ):" << std::endl << "\t";
+ for (unsigned i = 0; i < assumptions.size(); ++i) {
+ Debug("pf::uf") << assumptions[i] << " ";
}
+ Debug("pf::uf") << std::endl;
}
Node TheoryUF::explain(TNode literal) {
for(vector<Node>::const_iterator i = newClauses.begin();
i != newClauses.end();
++i) {
+ Debug("uf") << "uf: generating a lemma: " << *i << std::endl;
d_out->lemma(*i);
}
}
} else {
d_conflictNode = explain(a.eqNode(b),pf);
}
- ProofUF * puf = d_proofsEnabled ? new ProofUF( pf ) : NULL;
+ ProofUF* puf = d_proofsEnabled ? new ProofUF( pf ) : NULL;
d_out->conflict(d_conflictNode, puf);
d_conflict = true;
}
* Explain a literal, with proof (if "pf" is non-NULL).
*/
Node explain(TNode literal, eq::EqProof* pf);
-
+
/** Literals to propagate */
context::CDList<Node> d_literalsToPropagate;