fixed points in Z3 - z3

Can someone kindly point out why the final query doesn't have output?
Basically I tell Z3 if vs-)vd and vs->ss and vd->sd, then sd is derived from ss.
(set-option :fixedpoint.engine datalog)
(define-sort site () (_ BitVec 3))
(declare-rel pointsto (Int site))
(declare-rel dcall (Int Int))
(declare-rel derived (site site))
(declare-var vs Int)
(declare-var vd Int)
(declare-var ss site)
(declare-var sd site)
;;;;; definition of derived ;;
(rule (=> (and (dcall vs vd) (pointsto vs ss) (pointsto vd sd)) (derived ss sd)))
(rule (dcall 11 12))
(rule (pointsto 11 #b001))
(rule (pointsto 12 #b010))
(query (derived #b001 #b010))

This example exposes a few things. I will try to go through these.
The query returns "sat" or "unsat". In the "sat" case there is a set of tuples corresponding to the free variables in the query such that the query is derivable. To print these tuples you can specify ":print-answer true" as an option.
Your particular query does not contain any free variables, so there are no tuples to print.
I added another example that contains free variables and Z3 prints a solution.
The datalog engine doesn't really support infinite domains. You should use relations over Booleans, bit-vectors or finite domain values (a special sort used for programs entered in datalog format). I have changed your example to use bit-vectors.
(set-option :fixedpoint.engine datalog)
(define-sort site () (_ BitVec 3))
(define-sort Loc () (_ BitVec 8))
(declare-rel pointsto (Loc site))
(declare-rel dcall (Loc Loc))
(declare-rel derived (site site))
(declare-var vs Loc)
(declare-var vd Loc)
(declare-var ss site)
(declare-var sd site)
;;;;; definition of derived ;;
(rule (=> (and (dcall vs vd) (pointsto vs ss) (pointsto vd sd)) (derived ss sd)))
(rule (dcall (_ bv11 8) (_ bv12 8)))
(rule (pointsto (_ bv11 8) #b001))
(rule (pointsto (_ bv12 8) #b010))
(query (derived #b001 #b010)
:print-answer true)
(query (derived #b001 ss)
:print-answer true)

Related

What are the equivalent horn clauses to these clauses?

I am using Z3 and the extended SMT-LIB2 syntax to solve my horn clauses.
I know that head of a horn clause should be an uninterpreted predicate; but, I wonder how I should rewrite the following clauses to be a set of horn clauses.
(declare-rel inv (Int Int ))
(declare-var k Int)
(declare-var k_p Int)
(declare-var a Int)
(declare-var a_p Int)
(rule (=> (and (= a 0) (= k 0)) (inv a k)))
(rule (=> (and (inv a k) (= a_p (+ a 1))(= k_p (+ k 1))) (inv a_p k_p)))
(rule (=> (and (inv a k) (> k 0) ) (> a 0)))
(query inv )
Z3 complains that (> a 0) cannot be head of a horn clause.
I can rewrite the last clause as the following:
(rule (=> (and (inv a k) (> k 0) ) (gtz a)))
(rule (=> (> a 0) (gtz a)))
But, then the clauses become so weak that I don't get the intended model for the invariant inv. I wonder if there is a better way to do this.
Maybe you want to say
(declare-rel inv (Int Int ))
(declare-rel q ())
(declare-var k Int)
(declare-var k_p Int)
(declare-var a Int)
(declare-var a_p Int)
(rule (=> (and (= a 0) (= k 0)) (inv a k)))
(rule (=> (and (inv a k) (= a_p (+ a 1))(= k_p (+ k 1))) (inv a_p k_p)))
(rule (=> (and (inv a k) (> k 0) (not (> a 0))) q))
(query q )

(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.

Bug in Z3 Datalog

For the datalog program in Z3 at the bottom, the result of query
(query (CallGraph invo heap):print-answer true)
given by Z3 is:
sat
(and (= (:var 0) #b011) (= (:var 1) #b1))
However, the answer should be
sat
(and (= (:var 0) #b1) (= (:var 1) #b011))
am I right? is it a bug in Z3?
(set-option :fixedpoint.engine datalog)
(declare-rel VarPointsTo ( (_ BitVec 4) (_ BitVec 3)))
(declare-rel Reachable ( (_ BitVec 3)))
(declare-rel Alloc ( (_ BitVec 4) (_ BitVec 3) (_ BitVec 3)))
(declare-rel Move ( (_ BitVec 4) (_ BitVec 4)))
(declare-rel FldPointsTo ( (_ BitVec 3) (_ BitVec 1) (_ BitVec 3)))
(declare-rel Store ( (_ BitVec 4) (_ BitVec 4) (_ BitVec 4)))
(declare-rel StrMap ( (_ BitVec 4) (_ BitVec 1)))
(declare-rel Load ( (_ BitVec 4) (_ BitVec 4) (_ BitVec 4)))
(declare-rel VCall ( (_ BitVec 4) (_ BitVec 1) (_ BitVec 3)))
(declare-rel CallGraph ( (_ BitVec 1) (_ BitVec 3)))
(declare-rel InterProcAssign ( (_ BitVec 4) (_ BitVec 4)))
(declare-rel FormalArg ( (_ BitVec 3) (_ BitVec 1) (_ BitVec 4)))
(declare-rel ActualArg ( (_ BitVec 1) (_ BitVec 1) (_ BitVec 4)))
(declare-rel FormalReturn ( (_ BitVec 3) (_ BitVec 4)))
(declare-rel ActualReturn ( (_ BitVec 1) (_ BitVec 4)))
(declare-var var (_ BitVec 4))
(declare-var heap (_ BitVec 3))
(declare-var methHeap (_ BitVec 3))
(declare-var to (_ BitVec 4))
(declare-var from (_ BitVec 4))
(declare-var baseH (_ BitVec 3))
(declare-var fld (_ BitVec 1))
(declare-var base (_ BitVec 4))
(declare-var toMethHeap (_ BitVec 3))
(declare-var invo (_ BitVec 1))
(declare-var inMethHeap (_ BitVec 3))
(declare-var n (_ BitVec 1))
(rule (=> (and (Reachable methHeap) (Alloc var heap methHeap) )(VarPointsTo var heap)))
(rule (=> (and (Move to from) (VarPointsTo from heap) )(VarPointsTo to heap)))
(rule (=> (and (Store base var from) (and (VarPointsTo from heap) (and (VarPointsTo base baseH) (StrMap var fld) )))(FldPointsTo baseH fld heap)))
(rule (=> (and (Load to var base) (and (VarPointsTo base baseH) (and (FldPointsTo baseH fld heap) (StrMap var fld) )))(VarPointsTo to heap)))
(rule (=> (and (VCall var invo inMethHeap) (and (Reachable inMethHeap) (VarPointsTo var toMethHeap) ))(Reachable toMethHeap)))
(rule (=> (and (VCall var invo inMethHeap) (and (Reachable inMethHeap) (VarPointsTo var toMethHeap) ))(CallGraph invo toMethHeap)))
(rule (=> (and (CallGraph invo methHeap) (and (FormalArg methHeap n to) (ActualArg invo n from) ))(InterProcAssign to from)))
(rule (=> (and (CallGraph invo methHeap) (and (FormalReturn methHeap from) (ActualReturn invo to) ))(InterProcAssign to from)))
(rule (=> (and (InterProcAssign to from) (VarPointsTo from heap) )(VarPointsTo to heap)))
(rule (Alloc #b0001 #b001 #b010))
(rule (Alloc #b0010 #b001 #b010))
(rule (Reachable #b001))
(rule (Reachable #b010))
(rule (Alloc #b0011 #b011 #b001))
(rule (Alloc #b0100 #b100 #b011))
(rule (Move #b0101 #b0100))
(rule (StrMap #b0110 #b1))
(rule (Store #b0001 #b0110 #b0011))
(rule (StrMap #b0111 #b1))
(rule (Load #b1000 #b0111 #b0001))
(rule (VCall #b1000 #b1 #b001))
(rule (ActualReturn #b1 #b1001))
(query (VarPointsTo var heap):print-answer true)
(query (CallGraph invo heap):print-answer true)
(query (Reachable heap):print-answer true)
This does not appear to reproduce in the version of Z3 checked into GitHub/z3prover/z3 master branch.
The way the engine associates variable indices with variable names has been brittle and there might still be a way to trigger this bug with the newest version of Z3, although I cannot reproduce it.
The binary API exposes a more reliable API: one poses a query given one or more predicate declarations (The function from the C API is called Z3_fixedpoint_query_relations, and the other supported programming languages support similarly named functions).

Why does Z3 return unknown result?

all, I am a newer to use Z3. I wrote this smt2 file, but the result return unknown, what is wrong in my file?
(set-option :fixedpoint.engine datalog)
(define-sort site () (_ BitVec 3))
(declare-rel pointsto (Int Int)) ;used to get all points-to relation
(declare-rel dcall (Int Int)) ;used to label all function call or assignment
(declare-rel derived (Int Int)) ;used to get h1->hk
(declare-rel assign (Int Int))
(declare-var vs Int)
(declare-var vd Int)
(declare-var ss Int)
(declare-var sd Int)
(declare-var sm Int)
;;;;; definition of derived ;;;
(rule (=> (dcall vs vd) (pointsto vs vd)))
(rule (=> (and (dcall vs vd) (pointsto vs ss) (pointsto vd sd) ) (derived ss sd)))
(rule (=> (and (derived ss sm) (derived sm sd)) (derived ss sd)))
;facts 0-999 for var, 999** for addr
;(rule (dcall 3 6));src and sink
(rule (dcall 3 4))
(rule (dcall 4 6))
(rule (pointsto 0 9992))
(rule (pointsto 1 9991))
(rule (pointsto 2 9991))
(rule (pointsto 3 99948))
(rule (pointsto 4 99950))
(rule (pointsto 5 99928))
(rule (pointsto 6 9999))
(query (derived 99948 9999))
As a different post explains, the datalog engine should only use finite sorts.
THe newest unstable version of Z3 will reject the input above and indicate that arguments to predicates should be over a finite domain type.
Here is the example rewritten:
(set-option :fixedpoint.engine datalog)
(define-sort site () (_ BitVec 3))
(define-sort Loc () (_ BitVec 16))
(declare-rel pointsto (Loc Loc)) ;used to get all points-to relation
(declare-rel dcall (Loc Loc)) ;used to label all function call or assignment
(declare-rel derived (Loc Loc)) ;used to get h1->hk
(declare-rel assign (Loc Loc))
(declare-var vs Loc)
(declare-var vd Loc)
(declare-var ss Loc)
(declare-var sd Loc)
(declare-var sm Loc)
;;;;; definition of derived ;;;
(rule (=> (dcall vs vd) (pointsto vs vd)))
(rule (=> (and (dcall vs vd) (pointsto vs ss) (pointsto vd sd) ) (derived ss sd)))
(rule (=> (and (derived ss sm) (derived sm sd)) (derived ss sd)))
;facts 0-999 for var, 999** for addr
;(rule (dcall (_ bv3 16) (_ bv6 16)));src and sink
(rule (dcall (_ bv3 16) (_ bv4 16)))
(rule (dcall (_ bv4 16) (_ bv6 16)))
(rule (pointsto (_ bv0 16) (_ bv9992 16)))
(rule (pointsto (_ bv1 16) (_ bv9991 16)))
(rule (pointsto (_ bv2 16) (_ bv9991 16)))
(rule (pointsto (_ bv3 16) (_ bv99948 16)))
(rule (pointsto (_ bv4 16) (_ bv99950 16)))
(rule (pointsto (_ bv5 16) (_ bv9992 16)))
(rule (pointsto (_ bv6 16) (_ bv9999 16)))
(query (derived (_ bv99948 16) (_ bv9999 16)))
Z3 reports "sat", in other words, the query can be derived

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

Resources