Nikolaj Bjørner
Microsoft Research
nbjorner@microsoft.com |
Satisfiability Modulo Theories and Z3
Encoding and Programming Interfaces
SAT and SMT Algorithms using Z3
Book draft by Dennis Yurichev
Online Programming Z3
Online in your browser and in your other browser window.
Tie, Shirt = Bools('Tie Shirt')
s = Solver()
s.add(Or(Tie, Shirt), Or(Not(Tie), Shirt), Or(Not(Tie), Not(Shirt)))
print(s.check())
print(s.model())
I = IntSort()
f = Function('f', I, I)
x, y, z = Ints('x y z')
A = Array('A',I,I)
fml = Implies(x + 2 == y, f(Select(Store(A, x, 3), y - 2)) == f(y - x + 1))
s = Solver()
s.add(Not(fml))
print(s.check())
Is formula satisfiable under theory ?
SMT solvers use specialized algorithms for .
|
|
S = DeclareSort('S')
f = Function('f', S, S)
x = Const('x', S)
solve(f(f(x)) == x, f(f(f(x))) == x)
solve(f(f(x)) == x, f(f(f(x))) == x, f(x) != x)
x, y = Reals('x y')
solve([x >= 0, Or(x + y <= 2, x + 2*y >= 6),
Or(x + y >= 2, x + 2*y > 4)])
Z3 introduces auxiliary variables and represents the formula as
Only bounds (e.g., ) are asserted during search.
The declaration
A = Array('A', IntSort(), IntSort())
solve(A[x] == x, Store(A, x, y) == A)
which produces a solution where x
necessarily equals y
.
A = Array(Index, Elem) # array sort
a[i] # index array 'a' at index 'i'
# Select(a, i)
Store(a, i, v) # update array 'a' with value 'v' at index 'i'
# = lambda j: If(i == j, v, a[j])
Const(v, A) # constant array
# = lambda j: v
Map(f, a) # map function 'f' on values of 'a'
# = lambda j: f(a[j])
Ext(a, b) # Extensionality
# Implies(a[Ext(a, b)] == b[Ext(a, b)], a == b)
def array_axioms(s, index, range):
A = ArraySort(index, range)
a, b = Const('a b', A)
i, j = Const('i j', index)
v = Const('v', range)
s.add(ForAll([a, i, j, v], Store(a, i, v)[j] == If(i == j, v, a[j])))
s.add(ForAll([a, b], Implies(a[Ext(a,b)] == b[Ext(a,b)], a == b)))
def is_power_of_two(x):
return And(x != 0, 0 == (x & (x - 1)))
x = BitVec('x', 4)
prove(is_power_of_two(x) == Or([x == 2**i for i in range(4)]))
The absolute value of a variable can be obtained using addition and xor with a sign bit.
v = BitVec('v',32)
mask = v >> 31
prove(If(v > 0, v, -v) == (v + mask) ^ mask)
x = FP('x', FPSort(3, 4))
print(10 + x)
s, t, u = Strings('s t u')
prove(Implies(And(PrefixOf(s, t), SuffixOf(u, t),
Length(t) == Length(s) + Length(u)),
t == Concat(s, u)))
One can concatenate single elements to a sequence as units:
s, t = Consts('s t', SeqSort(IntSort()))
solve(Concat(s, Unit(IntVal(2))) == Concat(Unit(IntVal(1)), t))
prove(Concat(s, Unit(IntVal(2))) != Concat(Unit(IntVal(1)), s))
Tree = Datatype('Tree')
Tree.declare('Empty')
Tree.declare('Node', ('left', Tree), ('data', Z), ('right', Tree))
Tree = Tree.create()
t = Const('t', Tree)
solve(t != Tree.Empty)
It may produce the solution
[t = Node(Empty, 0, Empty)]
Similarly, one can prove that a tree cannot be a part of itself.
prove(t != Tree.Node(t, 0, t))