Combining elements of a given set of items in z3 - z3

The following z3 code picks elements from {x1..x6} in order to maximize the total weight, while satisfying total length less than 10.
(declare-datatypes () ((Item (mk-item (size Int) (weight Int)))))
(define-fun ee () Item (mk-item 0 0)); empty item
(define-fun i1 () Item (mk-item 4 2))
(define-fun i2 () Item (mk-item 4 2))
(define-fun i3 () Item (mk-item 1 4))
(define-fun i4 () Item (mk-item 5 5))
(define-fun i5 () Item (mk-item 3 2))
(define-fun i6 () Item (mk-item 1 9))
(define-fun x_props ((x Bool) (i Item)) Item (ite x i ee))
; each x defines whether an item is selected or not
(declare-const x1 Bool)
(declare-const x2 Bool)
(declare-const x3 Bool)
(declare-const x4 Bool)
(declare-const x5 Bool)
(declare-const x6 Bool)
(define-fun total_size () Int
(+
(size (x_props x1 i1))
(size (x_props x2 i2))
(size (x_props x3 i3))
(size (x_props x4 i4))
(size (x_props x5 i5))
(size (x_props x6 i6))
))
(define-fun total_weight () Int
(+
(weight (x_props x1 i1))
(weight (x_props x2 i2))
(weight (x_props x3 i3))
(weight (x_props x4 i4))
(weight (x_props x5 i5))
(weight (x_props x6 i6))
))
(assert (< total_size 10))
(maximize total_weight)
(check-sat)
(get-model)
However, I can imagine this scaling very bad as the number of item properties explode, and the number of items as well.
Would there be a different, more concise approach? In particular, can you think of a way to factorize the total_size and total_weight functions, as there is a lot of repetition there?

There's really nothing wrong with your encoding. Since you need to sum through a number of elements, the only way to do that is either being explicit about them, or use a recursive function. While SMT-Lib and Z3 both support recursive-functions, the implementation isn't quite strong yet, and you'd better stick to the explicit style.
The issue here is really trying to use SMT-Lib as a programming language, which it was not really intended for. I'd recommend looking into high-level language interfaces instead, such as those from Python, Scala, or Haskell; which would take care of the repetitive coding. Here's a good site for describing how to do model such things in Python: https://ericpony.github.io/z3py-tutorial/guide-examples.htm and here's an example of a similar problem in Haskell: https://hackage.haskell.org/package/sbv-7.4/docs/src/Data.SBV.Examples.Optimization.VM.html

Related

Z3 optimization Issue?

I wanted to find the maximum value of a variable under some simple constraints. But the result is not the optimum (max). Indeed, we can add another constraint and the solver still find another solution...
I also tried this example in python with the Optimize solver and maximize(r), but I get the same result. I also checked the upper bound (with the upper method) and I get the same erroneous result (4).
I'm not used to playing with the optimization feature of Z3, I generally only make proof; that's why I'm almost sure that the mistake is mine...
For now, I use a loop over the check-sat in python and iteratively add a constraint (r > result). It's working but it's neither elegant nor efficient...
; (set-logic QF_LIA)
(define-const x Int 9)
(define-const a Int 3)
(define-const b Int 4)
(define-const c Int 4)
(define-const d Int 5)
(declare-const i Int)
(declare-const j Int)
(declare-const t Int)
(declare-const r Int)
(assert (>= i 0))
(assert (>= j 0))
(assert (= t (+ (* i b) (* j d) 1)))
(assert (= r (+ (* i a) (* j c) c)))
(assert (<= t x))
(maximize r)
(check-sat)
;sat
(get-model)
;(model
; (define-fun i () Int
; 0)
; (define-fun j () Int
; 0)
; (define-fun r () Int
; 4)
; (define-fun t () Int
; 1)
;)
(get-value (r))
;((r 4))
(assert (> r 4))
(check-sat)
;sat
(get-model)
;(model
; (define-fun i () Int
; 2)
; (define-fun j () Int
; 0)
; (define-fun r () Int
; 10)
; (define-fun t () Int
; 9)
;)
$ z3 --version
Z3 version 4.8.7 - 64 bit
I cannot replicate this. When I run your program, it gives me r = 10, and if I then further assert (> r 10), then I get unsat.
However, I'm using z3 4.8.13, and I noticed that your z3 version is rather old, 4.8.7; which dates to late 2019. See if you can upgrade: https://github.com/Z3Prover/z3/releases
(The latest released version is 4.8.12; though you can also directly build from their GitHub sources, which will be tagged 4.8.13.)
Please report back if you still see the issue after upgrading.

Which nonlinear assert is complete in smt/z3 optimize?

I list some assert about Quadratic function:
(declare-fun H () Int)
(assert (>= H 8000))
(assert (<= H 12000))
(minimize (- (^ H 2) H))
(check-sat)
but the answer is "unknown" and the reason for unknown is (incomplete (theory arithmetic)); I can't understand which is the lost one
In general z3 cannot deal with non-linear terms. (A term is non-linear if you multiply two variables together. In your case, that'd be (^ H 2).
This is especially true of the optimization engine: Nonlinear constraints over integers is most likely going to be beyond reach. But you're in luck: Your formula is rather simple so it can handle it fine. Rewrite it using multiplication:
(declare-fun H () Int)
(assert (>= H 8000))
(assert (<= H 12000))
(minimize (- (* H H) H))
(check-sat)
(get-model)
This prints:
sat
(model
(define-fun H () Int
8000)
)

Having assertions inside definitions in SMT

I want to capture the assertion inside fac.
int f( x )
{
if( x == 1) return 1;
else{
assert( x > 0 );
return 2;
}
}
int g (x)
{ assert( x > 5 );
return f(x-1) + f(x-2);
}
I want an smt2 code for this.
I can do this by striping the argument and making it global with unique name (also rename inside f), then do this 3 times each with a different name for function. Like below :
( declare-const x1 Int )
(define-fun f1 () Int
( ite ( x1 > 0) 1 2 )
)
(assert (> x1 0))
( declare-const x2 Int )
(define-fun f2 () Int
( ite ( x2 > 0) 1 2 )
)
(assert (> x2 0))
( declare-const x3 Int )
(define-fun g1 () Int
( + f1 f2 )
)
(assert (> x3 5))
I don't want to this. Is there any other way to do this without repeating ?
EDIT
My purpose is to find values violating the asserts.
As far as I know, it is not possible to embed assertions within function definitions.
What I would try to do is to separate the expected behavior, the input assumptions and the output guarantees (if any).
Example:
(define-fun f ((x Int)) Int
(ite (= x 1) 1 2)
)
(define-fun f-helper ((x Int)) Bool
(< 0 x)
)
(define-fun g ((x Int)) Int
(+ (f (- x 1)) (f (- x 2)))
)
(define-fun g-helper ((x Int)) Bool
(and (< 5 x)
(f-helper (- x 1))
(f-helper (- x 2))
)
)
(declare-const x Int)
(declare-const y Int)
(assert (and (= y (g x))
(g-helper x)
))
(check-sat)
(get-model)
In this example we use f to model the behavior of the original function f, and f-helper to model the assumptions of f. The output, using the online Z3 tool, is as follows:
sat
(model
(define-fun x () Int
6)
(define-fun y () Int
4)
)
I would conclude saying that this approach could become tricky as soon as f and g are used inside both positive and negative contexts.. in this case one should pay extra attention that the polarity of the assertions is correct wrt. the expected result.

Partially interpreted Const in z3

In z3, one can declare a fully-uninterpreted const like so:
(declare-const x Int)
Similarly, one can define a fully-interpreted one like this:
(define-fun y () Int 3)
; y == 3
Given an algebraic datatype, one can have a fully interpreted tuple like the following:
(declare-datatypes () ((Item (mk-item (size Int) (weight Int)))))
(define-fun z () Item (mk-item 3 4))
; z == Item(size=3, weight=4)
... Or a non-interpreted one like below:
(declare-const i1 (Item Int Int))
Now is it possible to have a partially-interpreted data type, so that, based on the previous example, weight would be fixed for each item and size could vary?
; (bad syntax, but I hope you get the idea)
; in this case the size is varying, but weight is fixed to 5
(declare-const i2 (Item Int 5))
You should simply declare it with declare-fun and assert an equality for the portions that you know:
(declare-datatypes () ((Item (mk-item (size Int) (weight Int)))))
(declare-fun x () Item)
(assert (= (weight x) 5))
(check-sat)
(get-model)
This produces:
sat
(model
(define-fun x () Item
(mk-item 0 5))
)

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