Z3: how to encode If-the-else in Z3 python? - python

I want to encode If-the-else in Z3 python, but cannot find any docs or sample on how to do that.
I have a sample code like below.
F = True
tmp = BitVec('tmp', 1)
tmp1 = BitVec('tmp1', 8)
Now how can I encode this condition into F:
if tmp == 1, then tmp1 == 100. otherwise, tmp1 == 0
Thanks so much.

You'll need Z3's If function:
def z3py.If ( a,
b,
c,
ctx = None
)
Create a Z3 if-then-else expression.
>>> x = Int('x')
>>> y = Int('y')
>>> max = If(x > y, x, y)
>>> max
If(x > y, x, y)
>>> simplify(max)
If(x <= y, y, x)
(from here)

You can use If for this. If takes three arguments: the condition, an expression that should be true if the condition is true and an expression that should be true if the condition is false. So to express your logic, you'd write:
If(tmp==1, tmp1==100, tmp1==0)

Related

What does (x < y) | (x > z) do?

def my_function(x,y,z):
out = True
if(x < y) | (x > z):
out = False
return out
Can you help me understand what this is doing? Is it, "out is True, but if x is less than y or greater than z: out is False"? I am unsure about the | operator.
TL;DR, someone thought they were clever.
This code takes advantage of some implementation details about booleans and then does some binary integer operations.
To understand it we need to cover a few things:
the > and < operators in a comparison will give back boolean True or False.
Boolean True and False are actually subclasses of int and function as 1 and 0 respectively in operations that expect an integer (try running True + 1 in your REPL).
The | operator is bitwise OR (as opposed to logical OR which is just or) which works on integers.
And now we can understand the code: the <> comparisons gives us a bool that gets used as an integer 1 or 0 and ORed bitwise with the result of the other comparison.
An even cleverer person would note that bitwise OR with 1's and 0's would only be 0 if both were 0, and just check for that condition:
1 | 1 # 1
1 | 0 # 1
0 | 1 # 1
0 | 0 # 0
This code is needlessly obfuscated: there's no reason to treat the True/False as 1/0 just to do bit manipulation when regular boolean logic would work. This will work identically:
def my_function(x, y, z):
return y <= x <= z
Best way to wrap your head around code you are not sure about is to test it:
testValues = [(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]
for x, y, z in testValues:
print("The values are: x = %d, y = %d, z = %d" % (x, y, z))
print("out is:", my_function(x, y, z))
def my_function(x,y,z):
global out
out = True
if(x < y) | (x > z):
out = False
return out
x = 6
y = 2
z = 5
my_function(x,y,z)
The above code outputs True/False based on the values of x,y,z. If x is smaller than y OR if x is greater than z it will change the value of 'out' to False.You can further customize the code to do stuff with the output. Like so:
if out == True:
//some stuff to execute when true
else:
//some stuff to execute when false

Is there a way to convert z3.z3.ArithRef Real to Numpy Float64?

I recently started using Microsoft Z3 for Theorem Proving and I was wondering if there was a way to convert the Z3 Real Numbers to Python Floating Point Numbers so that I can pass them to other complex functions.
This is what I would like to do,
from z3 import *
def prediction(x):
if x > 10: # This is where Z3 gives me an error as 'x' is a z3 object
return 10
else:
return x
x = Real('x')
z = prediction(x)
s = Solver()
s.add(2 <= x, x < 5)
s.add(z > 4)
res = s.check()
print(res)
if res == sat:
print(s.model())
ERROR: Z3Exception: Symbolic expressions cannot be cast to concrete Boolean values.
I wish to convert them to NumPy format as the other libraries accept inputs as NumPy arrays and not as Arithref Objects.
Any help would be appreciated. Thanks!
You shouldn't try to convert a symbolic Real to a Python float. Not only there is no way to do so, these two types are incompatible with each other. Instead, you should directly program with the symbolic values using z3py control idioms. For if-then-else, use the If function. So, your example would be coded as:
from z3 import *
def prediction(x):
return If(x > 10, 10, x)
x = Real('x')
z = prediction(x)
s = Solver()
s.add(2 <= x, x < 5)
s.add(z > 4)
res = s.check()
print(res)
if res == sat:
print(s.model())
which prints:
sat
[x = 9/2]

Inputting three integers x,y, and z to see if any operation can be made on x and y to get z as a result

Is there a function python that performs all types of math functions on two variables?
Here's one that handles addition, subtraction, multiplication, division, exponents and modulo:
def all_operations(x, y, z):
if x + y == z:
return True
if x - y == z:
return True
if x * y == z:
return True
if x / y == z:
return True
if x % y == z:
return True
return False
Something like this maybe?
x, y, z = 6, 7, 42
for f in dir(x):
try:
if getattr(x, f)(y) == z:
print(f)
except:
pass
That example finds two operations:
__mul__
__rmul__

python function conditional return

When using a conditional return, if you attempt to return more than one value from function, the function behaves erratically with regard to the actual return value.
def test_function(x,y, diagnostic:bool=False):
w = x*y
z = []
if diagnostic:
z = [w,w*2]
return z, w if diagnostic else w
print(test_function(3,4)) # output tuple ([],12)
# lets switch order of the return from z,w to w,z
def test_function(x,y, diagnostic:bool=False):
w = x*y
z = []
if diagnostic:
z = [w,w*2]
return w,z if diagnostic else w
print(test_function(3,4)) # output tuple (12,12)
# lets try retun the diagnostic value itself to see what function things is happening
def test_function(x,y, diagnostic:bool=False):
w = x*y
z = []
if diagnostic:
z = [w,w*2]
return diagnostic if diagnostic else w
print(test_function(3,4)) # returns 12, so diagnostic is retuning false
# rewrite conditional to "if not"
def test_function(x,y, diagnostic:bool=False):
w = x*y
z = []
if diagnostic:
z = [w,w*2]
return w if not diagnostic else w,z
print(test_function(3,4)) # returns (12, [])
The problem is operator precedence: , has lower precedence than ... if ... else ..., so what you actually wrote is like return z, (w if diagnostic else w), or in the second function, it's like return w, (z if diagnostic else w).
The hint for this is that diagnostic is False but you're still returning a pair of values.
For the behaviour you want, you should write return (z, w) if diagnostic else w. Note that the brackets here are not needed to make it a tuple - it is a tuple either way - the brackets are to specify precedence.
If returning multiple values in a conditional return, the values must be explicitly returned as a tuple due to operator precedence:
def test_function(x,y, diagnostic:bool=False):
w = x*y
z = []
if diagnostic:
z = [w,w*2]
return (z, w) if diagnostic else w
print(test_function(3,4)) # returns 12
print(test_function(3,4, diagnostic=False)) # returns (12, [12, 24])
w, z = test_function(3,4, diagnostic=True)
print(w) # returns 12
print(z) # returns [12,24]

How to find a root for a mathematical function using Intermediate value theorem?

Accroding to the Intermediate value theorem for a given function F(x),
I'm supposed to write a function, which gets a mathematical function, two numbers a and b , and an error range, and it gives as an output the number x for which the functions' value for it is close to 0 up to epsilon.
Examples:
>>> find_root(lambda x : x - 1 , -10, 10)
1.0009765625
>>> find_root(lambda x : x**2 , -10, 10)
>>> #returned None
This is the code that I wrote so far, I think I'm on the right way, but I can't figure out what to loop over, I don't get the correct answer with this code.
So what should I fix in it?
def find_root(f, a, b, EPS=0.001):
if (f(a)*f(b))<0:
for i in range(a,b):
if f(i)<EPS:
return (i)
else:
return (None)
Use dichotomy :
def find_root(f, a, b, EPS=0.0001):
if f(a)==0 : return a
if f(b)==0 : return b
if f(a)*f(b)>0 : return None
c=(a+b)/2
while(abs(f(c))>EPS) :
if f(a)*f(c)<0 : b=c
else : a=c
c=(a+b)/2
return c
The simplest solution is this:
def find_root(f, a, b, EPS=0.001):
#assuming a < b
x = a
while x <= b:
if abs(f(x)) < EPS:
return x
else:
x += EPS
Result:
>>>find_root(lambda x: x-1, -10, 10)
0.9999999999998982
>>>find_root(lambda x: x-1, -10, -2)
None
As you know, your procedure cannot find the root if the initial values are both positive or both negative.
Here is a suggestion of how to implement it using a binary search, in order to accelerate the process:
def find_root(f, a, b, EPS=0.001):
fa = f(a)
fb = f(b)
if fa*fb > 0: # both positive or both negative
return None
while abs(fa) > EPS and abs(fb) > EPS:
c = (a+b)/2.0
fc = f(c)
if fa*fc >= 0:
a = c
fa = fc
else:
b = c
fb = fc
if abs(fa) <= EPS:
return a
else:
return b
The return value of find_root(lambda x : x-1, -10, 10) is 1.0009765625.

Categories