Explosive memory use when reasoning about XOR (all AC theories?) - z3

It appears that reasoning about XOR causes explosive memory use for Z3 (commit 210bca8f456361f696152be909e33a4e8b58607f2). For example, deriving a+b+c from something that is AC equivalent to a+b+c+x+x+y+y+z+z:
(declare-fun known (Bool) Bool)
(declare-fun p (Bool Bool Bool) Bool)
; Lift xor
(assert (forall ((x Bool) (y Bool))
(=> (and (known x) (known y)) (known (xor x y)))))
; Can reason about xor well
(assert (exists ((a1 Bool) (b1 Bool) (c1 Bool) (ra Bool) (rb Bool) (rc Bool))
(and (p a1 b1 c1)
(known (xor a1 (xor ra rc)))
(known (xor b1 (xor rb ra)))
(known (xor c1 (xor rc rb))))))
; Assert that we can derive a+b+c.
; Note: The behavior (non-termination) is the same when this example is
; inverted (forall ... not ...)
(assert (exists ((a1 Bool) (b1 Bool) (c1 Bool))
(and (p a1 b1 c1)
(known (xor a1 (xor b1 c1))))))
(check-sat)
Is this an accepted limitation? Are there alternate formulations I can use to answer queries like this with Z3?
Continuity: I had previously misused the HORN logic for this task.

The problem is that the assertion
(assert (forall ((x Bool) (y Bool))
(=> (and (known x) (known y)) (known (xor x y)))))
is really bad for the E-matching engine. This is one of the engines used to handle quantifiers in Z3.
There are many possible workarounds.
1) Use quantifier elimination. You just have to replace (check-sat) with (check-sat-using (then qe smt))
2) Annotate the quantifier with a :weight attribute. The E-matching engine will stop producing new instances earlier. Here is an example:
(assert (forall ((x Bool) (y Bool))
(! (=> (and (known x) (known y)) (known (xor x y)))
:weight 10)))
3) Disable the E-matching engine. Then, Z3 will use only the MBQI (model-based quantifier instantiation) engine, which is much more effective for this kind of problem. To disable E-matching, we should use
(set-option :smt.ematching false)
Remark: in Z3 version <= 4.3.1, this option is called (set-option :ematching false)

Related

(get-unsat-core) Z3: unsat core is not available

Here is my program which return SAT when there exists a cycle in the graph and UNSAT when there is no cycle:
(set-option :fixedpoint.engine datalog)
(define-sort s () Int)
(declare-rel edge (s s))
(declare-rel path (s s))
(declare-var a s)
(declare-var b s)
(declare-var c s)
(rule (=> (edge a b) (path a b)))
(rule (=> (and (path a b) (path b c)) (path a c)))
(rule (edge 1 2))
(rule (edge 2 3))
(declare-rel cycle (s))
(rule (=> (path a a) (cycle a)))
(query cycle :print-answer true)
I want to get the model when there is no cycle ( UNSAT ). I realised that i should use the command (get-unsat-core) and set the option to (set-option :produce-unsat-cores true) :
(set-option :fixedpoint.engine datalog)
(set-option :produce-unsat-cores true)
(define-sort s () Int)
(declare-rel edge (s s))
(declare-rel path (s s))
(declare-var a s)
(declare-var b s)
(declare-var c s)
(rule (=> (edge a b) (path a b)) P-1)
(rule (=> (and (path a b) (path b c)) (path a c)) P-2)
(rule (edge 1 2) E-1)
(rule (edge 2 3) E-2)
(rule (edge 3 1) E-3)
(declare-rel cycle (s))
(rule (=> (path a a) (cycle a)))
(query cycle :print-answer true)
(get-unsat-core)
I get this error:
unsat
(error "line 24 column 15: unsat core is not available")
Getting a model in the unsat case doesn't make sense. Unsatisfiable literally means there's no model that satisfies your constraints. Please post a more clear question of precisely what you're trying to achieve.
An unsat core is a subset of the assertions that are conflicting. This set is by definition not satisfiable, and does not constitute model as you are seeking. Furthermore, I very much doubt the fixed-point engine supports unsat-cores, so the error message you're getting simply means they are not computed.
If I may intrude, AFAIK one needs to name the constraints when one wants to retrieve the unsat core.
The smtlib website provides the following example:
; Getting unsatisfiable cores
(set-option :produce-unsat-cores true)
(set-logic QF_UF)
(declare-const p Bool) (declare-const q Bool) (declare-const r Bool)
(declare-const s Bool) (declare-const t Bool)
(assert (! (=> p q) :named PQ))
(assert (! (=> q r) :named QR))
(assert (! (=> r s) :named RS))
(assert (! (=> s t) :named ST))
(assert (! (not (=> q s)) :named NQS))
(check-sat)
; unsat
(get-unsat-core)
; (QR RS NQS)
(exit)
As #LeventErkok points out, a model is only available when the formula is sat and the unsat core is only available when the formula is unsat.

Converting Z3 QBF formula directly to pcnf

I'm using Z3 theorem prover (using Z3Py: the Z3 API in Python) to create QBF (Quantified Boolean formula).
Is there any way in Z3 to directly convert your qbf formula into Prenex normal form ?
I don't think there's a tactic to convert to Prenex, but you can surely apply the quantifier-elimination tactic and further process your formulas. Note that the transformed formulas will not really look like the originals, as they are mechanically generated.
Here's an example:
from z3 import *
f = Function('f', IntSort(), IntSort(), IntSort())
x, y = Ints('x y')
p = ForAll(x, Or(x == 2, Exists(y, f (x, y) == 0)))
print Tactic('qe')(p)
Here qe is the quantifier elimination tactic. This produces:
[[Not(Exists(x!0,
Not(Or(x!0 == 2,
Exists(x!1,
And(f(x!0, x!1) <= 0,
f(x!0, x!1) >= 0))))))]]
For a nice tutorial on tactics, see here: http://ericpony.github.io/z3py-tutorial/strategies-examples.htm
You could use the skolemize tactic (snf) which will by definition be in prenex form. However it will also eliminate existential quantifiers which is not what you want. Here's an example.
(declare-fun a (Int) Bool)
(declare-fun b (Int) Bool)
(declare-fun c (Int) Bool)
(assert
(forall ((x Int))
(or
(exists ((y Int))
(a y)
)
(exists ((z Int))
(=>
(b z)
(c x)
)
)
)
)
)
(apply
(and-then
; mode (symbol) NNF translation mode: skolem (skolem normal form), quantifiers (skolem normal form + quantifiers in NNF), full (default: skolem)
(using-params snf :mode skolem)
)
:print_benchmark true
:print false
)
When Z3 is given the above it will responds with something like
(declare-fun c (Int) Bool)
(declare-fun b (Int) Bool)
(declare-fun a (Int) Bool)
(assert (forall ((x Int))
(or (exists ((y Int)) (a y)) (exists ((z Int)) (=> (b z) (c x))))))
(check-sat)
You can see the available tactics by running
echo "(help-tactic)" | ./z3 -in | less
from a bash shell.
Unfortunately I can't see one that states it does conversion to prenex.

Possible bug with Z3: Z3 is not able to prove a theorem in Topology

I am trying to prove with Z3 the theorem in general topology given at
TPTP-Topology
I am translating the code given there using the following Z3-SMT-LIB code
;; File : TOP001-2 : TPTP v6.0.0. Released v1.0.0.
;; Domain : Topology
;; Problem : Topology generated by a basis forms a topological space, part 1
(declare-sort S)
(declare-sort Q)
(declare-sort P)
(declare-fun elemcoll (S Q) Bool)
(declare-fun elemset (P S) Bool)
(declare-fun unionmemb (Q) S)
(declare-fun f1 (Q P) S)
(declare-fun f11 (Q S) P)
(declare-fun basis (S Q) Bool)
(declare-fun Subset (S S) Bool)
(declare-fun topbasis (Q) Q)
;; union of members axiom 1.
(assert (forall ((U P) (Vf Q)) (or (not (elemset U (unionmemb Vf)))
(elemset U (f1 Vf U) ) ) ))
;; union of members axiom 2.
(assert (forall ((U P) (Vf Q)) (or (not (elemset U (unionmemb Vf)))
(elemcoll (f1 Vf U) Vf ) ) ))
;; basis for topology, axiom 28
(assert (forall ((X S) (Vf Q)) (or (not (basis X Vf)) (= (unionmemb Vf) X ) ) ))
;; Topology generated by a basis, axiom 40.
(assert (forall ((Vf Q) (U S)) (or (elemcoll U (topbasis Vf))
(elemset (f11 Vf U) U)) ))
;; Set theory, axiom 7.
(assert (forall ((X S) (Y Q)) (or (not (elemcoll X Y)) (Subset X (unionmemb Y) ) ) ))
;; Set theory, axiom 8.
(assert (forall ((X S) (Y S) (U P)) (or (not (Subset X Y)) (not (elemset U X))
(elemset U Y) )))
;; Set theory, axiom 9.
(assert (forall ((X S)) (Subset X X ) ))
;; Set theory, axiom 10.
(assert (forall ((X S) (Y S) (Z S)) (or (not (= X Y)) (not (Subset Z X)) (Subset Z Y) ) ))
;; Set theory, axiom 11.
(assert (forall ((X S) (Y S) (Z S)) (or (not (= X Y)) (not (Subset X Z)) (Subset Y Z) ) ))
(check-sat)
(push)
(declare-fun cx () S)
(declare-fun f () Q)
(assert (basis cx f))
(assert (not (elemcoll cx (topbasis f))))
(check-sat)
(pop)
(push)
(assert (basis cx f))
(assert (elemcoll cx (topbasis f)))
(check-sat)
(pop)
The corresponding output is
sat
sat
sat
Please run this example online here
The first sat is correct; but the second sat is wrong, it must be unsat. In other words, Z3 is saying that the theorem and its negation are true simultaneously.
Please let me know what happens in this case. Many thanks. All the best.
It is possible that both a formula and the negation of the formula is consistent with respect to a background theory T. In particular, when T is not complete, then there are sentences that are neither consequences of T nor inconsistent with T. In your case the theory T is the set of topology axioms.
You can use the command (get-model) to obtain a model that satisfies the axioms and the sentence.

Can z3 always give result when handling nonlinear real arithmetic

I have a problem required to solve a set of nonlinear polynomial constraints. Can z3 always give a result (sat or unsat) when handling nonlinear real arithmetic.
Is the result also sound?
Yes, it is complete assuming (1) availability of resources, and (2) you only use real constraints so that the nlsat tactic is used, as the last I checked, it wasn't full integrated with the other solvers, see the below questions/answers for more details. Here's a simple example illustrating this (at least by default, rise4fun link: http://rise4fun.com/Z3/SRZ8 ):
(declare-fun x () Real)
(declare-fun y () Real)
(declare-fun z () Real)
(assert (>= (* 2 (^ x 2)) (* y z)))
(assert (> x 100))
(assert (< y 0))
(assert (< z 0))
(assert (> (^ y 2) 1234))
(assert (< (^ z 3) -25))
(check-sat) ; sat
(get-model)
(declare-fun b () Int)
(assert (> b x))
(check-sat) ; unknown
Z3 Theorem Prover: Pythagorean Theorem (Non-Linear Artithmetic)
mixing reals and bit-vectors
z3 produces unknown for assertions without quantifiers
z3 existential theory of the reals
Combining nonlinear Real with linear Int
Z3 support for nonlinear arithmetic
Encoding returns "unknown"
For the incremental question, it may be possible to use nlsat with incremental solving, but in this simple example applying a standard method (rise4fun link: http://rise4fun.com/Z3/Ce1F and see: Soft/Hard constraints in Z3 ) there is an unknown, although a model assignment is made, so it may be useful for your purposes. If not, you can try push/pop: Incremental solving in Z3 using push command
(set-option :produce-unsat-cores true)
(set-option :produce-models true)
(declare-const p1 Bool)
(declare-const p2 Bool)
(declare-const p3 Bool)
(declare-const p4 Bool)
(declare-const p5 Bool)
(declare-const p6 Bool)
(declare-const p7 Bool)
(declare-fun x () Real)
(declare-fun y () Real)
(declare-fun z () Real)
(assert (=> p1 (>= (* 2 (^ x 2)) (* y z))))
(assert (=> p2 (> x 100)))
(assert (=> p3 (< y 0)))
(assert (=> p4 (< z 0)))
(assert (=> p5 (> (^ y 2) 1234)))
(assert (=> p6 (< (^ z 3) -25)))
(assert (=> p7 (< x 50)))
(check-sat p1 p2 p3 p4 p5 p6 p7) ; unsat
(get-unsat-core) ; (p2 p7)
(check-sat p1 p2 p3 p4 p5 p6) ; unknown, removed one of the unsat core clauses
(get-model)
(declare-fun b () Int)
(assert (> b x))
(check-sat) ; unknown

Program satisfiability using Z3

How to check satisfiability of a program using Z3? For example:
Boolean x, y
while(x is False) {
x = x or y
y = x & y
}
y = x or y
You can represent programs as a set of Horn clauses. For your program you can represent it as follows:
(set-logic HORN)
(set-option :fixedpoint.engine bmc)
(declare-fun L0 (Bool Bool) Bool)
(declare-fun L1 (Bool Bool) Bool)
(declare-fun L2 (Bool Bool) Bool)
(declare-fun L3 (Bool Bool) Bool)
(assert (forall ((x Bool) (y Bool)) (L0 x y))) ; all values of x,y are possible at L0
(assert (forall ((x Bool) (y Bool)) (=> (L0 x y) (L1 x y)))) ; from L0 move to L1 without changing x, y
(assert (forall ((x Bool) (y Bool) (x1 Bool) (y1 Bool))
(=> (and (not x) (L1 x y) (= x1 (or x y)) (= y1 (and x1 y))) (L1 x1 y1)))); assignment in while loop
(assert (forall ((x Bool) (y Bool)) (=> (and x (L1 x y)) (L2 x y)))) ; exit while loop
(assert (forall ((x Bool) (y Bool)) (=> (L2 x y) (L3 x (or x y))))) ; assignment after while loop
(assert (forall ((x Bool) (y Bool)) (=> (L3 true true) false))) ; say x = true, y = true is unreachable.
(check-sat)
I have added a last assertion to make a reachability statement.
I have also instructed Z3 to use a BMC engine to unfold the Horn clauses using
bounded model checking. Other engines are available as well, for the example the PDR/IC3
engine (set-option :fixedpoint.engine pdr), does not unfold transition relations.
Now the meaning of reachability vs. satisfiability
is going to be different for Horn clauses, as compared to a conjunction of the unfolded
transition relation:
the above clauses are UNSAT.
This does in fact correspond to a feasible path from L0 to (L3 true true).
If you change the last statement to (L3 true false), you get the answer "sat"
(The BMC problem is UNSAT). While BMC itself would not terminate on with such a loop,
it turns out that the last transition and loop exit condition are enough to prune out
the possibility of (L3 true false) so Z3 solves this problem by pre-processing the horn clauses.
You can of course also write down the transition relation for the program statements you have and unfold this directly yourself into a logical formula that you check satisfiability of.

Resources