Reputation:
Is there any limitations in functions declaring?
For example, this piece of code returning unsat.
from z3 import *
def one_op (op, arg1, arg2):
if op==1:
return arg1*arg2
if op==2:
return arg1-arg2
if op==3:
return arg1+arg2
return arg1+arg2 # default
s=Solver()
arg1, arg2, result, unk_op=Ints ('arg1 arg2 result unk_op')
s.add (unk_op>=1, unk_op<=3)
s.add (arg1==1)
s.add (arg2==2)
s.add (result==3)
s.add (one_op(unk_op, arg1, arg2)==result)
print s.check()
How Z3Py interpret declared function? Is it just calling it some times or some hidden machinery also here?
Upvotes: 3
Views: 282
Reputation: 21475
In the function call one_op(unk_op, arg1, arg2)
, unk_op
is a Z3 expression. Then, expressions such as op==1
and op==2
(in the definition of one_op
) are also Z3 symbolic expressions. Since op==1
is not the Python Boolean expression False
. The function one_op
will always return the Z3 expression arg1*arg2
. We can check that by executing print one_op(unk_op, arg1, arg2)
. Note that the if
statements in the definition of one_op
are Python statements.
I believe your true intention is to return a Z3 expression that contains conditional expressions. You can accomplish that by defining one_op
as:
def one_op (op, arg1, arg2):
return If(op==1,
arg1*arg2,
If(op==2,
arg1-arg2,
If(op==3,
arg1+arg2,
arg1+arg2)))
Now, the command If
builds a Z3 conditional expression. By using, this definition, we can find a satisfying solution. Here is the complete example:
from z3 import *
def one_op (op, arg1, arg2):
return If(op==1,
arg1*arg2,
If(op==2,
arg1-arg2,
If(op==3,
arg1+arg2,
arg1+arg2)))
s=Solver()
arg1, arg2, result, unk_op=Ints ('arg1 arg2 result unk_op')
s.add (unk_op>=1, unk_op<=3)
s.add (arg1==1)
s.add (arg2==2)
s.add (result==3)
s.add (one_op(unk_op, arg1, arg2)==result)
print s.check()
print s.model()
The result is:
sat
[unk_op = 3, result = 3, arg2 = 2, arg1 = 1]
Upvotes: 3