python function conditional return - python

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]

Related

s Counterexamples for invalid model for Z3

This is an extension of the question:
Use Z3 to find counterexamples for a 'guess solution' to a particular CHC system?
In the below code, I am trying to use Z3 to get s counterexamples to a guess candidate for I satisfying some CHC clauses:
from z3 import *
x, xp = Ints('x xp')
P = lambda x: x == 0
B = lambda x: x < 5
T = lambda x, xp: xp == x + 1
Q = lambda x: x == 5
s = 10
def Check(mkConstraints, I, P , B, T , Q):
s = Solver()
# Add the negation of the conjunction of constraints
s.add(Not(mkConstraints(I, P , B, T , Q)))
r = s.check()
if r == sat:
return s.model()
elif r == unsat:
return {}
else:
print("Solver can't verify or disprove, it says: %s for invariant %s" %(r, I))
def System(I, P , B, T , Q):
# P(x) -> I(x)
c1 = Implies(P(x), I(x))
# P(x) /\ B(x) /\ T(x,xp) -> I(xp)
c2 = Implies(And(B(x), I(x), T(x, xp)) , I(xp))
# I(x) /\ ~B(x) -> Q(x)
c3 = Implies(And(I(x), Not(B(x))), Q(x))
return And(c1, c2, c3)
cex_List = []
I_guess = lambda x: x < 3
for i in range(s):
cex = Check(System, I_guess, P , B , T , Q)
I_guess = lambda t: Or(I_guess(t) , t == cex['x'])
cex_List.append( cex[x] )
print(cex_List )
The idea is to use Z3 to learn a counterexample x0 for guess invariant I, then run Z3 to learn a counterexample for I || (x == x0) and so on till we get s counterexamples. However the following code gives 'RecursionError: maximum recursion depth exceeded
'. I am confused because I am not even recursing with depth > 1 anywhere. Could anyone describe what's going wrong?
Your problem really has nothing to do with z3; but rather a Python peculiarity. Consider this:
f = lambda x: x
f = lambda x: f(x)
print(f(5))
If you run this program, you'll also see that it falls in to the same infinite-recursion loop, since by the time you "get" to the inner f, the outer f is bound to itself again. In your case, this is exhibited in the line:
I_guess = lambda t: Or(I_guess(t) , t == cex['x'])
which falls into the same trap by making I_guess recursive, which you did not intend.
The way to avoid this is to use an intermediate variable. It's ugly and counter-intuitive but that's the way of the python! For the example above, you'd write it as:
f = lambda x: x
g = f
f = lambda x: g(x)
print(f(5))
So, you need to do the same trick for your I_guess variable.
Note that since you're updating the function iteratively, you need to make sure to remember the function in each step, instead of using the same name over and over. That is, capture the old version each time you create the new function. When applied to the above case, it'll be something like:
f = lambda x: x
f = lambda x, old_f=f: old_f(x)
print(f(5))
This'll make sure the iterations don't clobber the captured function. Applying this idea to your problem, you can code as follows:
for i in range(s):
cex = Check(System, I_guess, P, B, T, Q)
I_guess = lambda t, old_I_guess=I_guess: Or(old_I_guess(t), t == cex[x])
cex_List.append(cex[x])
When run, this prints:
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
without any infinite-recursion problem. (Whether this is the correct output or what you really wanted to do, I'm not sure. Looks to me like you need to tell z3 to give you a "different" solution, and maybe you've forgotten to do that. But that's a different question. We're really discussing a Python issue here, not z3 modeling.)

How to write one-line ternary expressions using `is None` in Python?

I am interested in using one-line ternary expressions instead of traditional multiline if-else blocks. However, expressions comparing is None give different results.
Here is an example comparing multiline and one-line variants of two forms of a conditional expression for a predicate:
if pred is not None
if pred is None
Code
import operator as op
# First form
def is_not_none_multiline(a, b, pred=None):
if pred is not None:
predicate = pred
else:
predicate = lambda x, y: x + y
return predicate(a, b)
def is_not_none_oneline(a, b, pred=None):
predicate = pred if pred is not None else lambda x, y: x + y
return predicate(a, b)
# Second Form
def is_none_multiline(a, b, pred=None):
if pred is None:
predicate = lambda x, y: x + y
else:
predicate = pred
return predicate(a, b)
def is_none_oneline(a, b, pred=None):
predicate = lambda x, y: x + y if pred is None else pred
return predicate(a, b)
Tests
Here are tests for optional arguments in mutliline and one-line variants. The final result was unexpected:
assert is_not_none_multiline(1, 2) == 3
assert is_not_none_oneline(1, 2) == 3
assert is_not_none_multiline(1, 2, pred=op.mul) == 2
assert is_not_none_oneline(1, 2, pred=op.mul) == 2
assert is_none_multiline(1, 2) == 3
assert is_none_oneline(1, 2) == 3
assert is_none_multiline(1, 2, pred=op.mul) == 2
assert is_none_oneline(1, 2, pred=op.mul) == 2
# ----> 4 assert is_none_oneline(1, 2, pred=op.mul) == 2
# AssertionError:
Although pred is not None works as one-line:
predicate = pred if pred is not None else lambda x, y: x + y
pred is None does not work as one-line:
predicate = lambda x, y: x + y if pred is None else pred
Details
Apparantly, the pred function is not evaluated when passed in as a keyword to is_none_oneline(). Rather, it is returned:
print(is_none_oneline(1, 2, pred=op.mul))
# <built-in function mul>
This analysis was verified in a Python Tutor visualization when executing both variants of the second form (see visualizations here is not None multiline, is not None one-line, is None multiline, is None one-line).
Questions
It is unclear why an equivalent ternary expression returns a function rather than a computed value.
Can someone explain why the predicate is not evaluated in the second form - a one-line, pred is None expression?
How does one correctly write pred is None in one-line?
Just a simple case of operator precedence.
You're getting a callable which returns a callable. I think you wanted this instead, to make sure the conditional gets grouped the other way:
def is_none_oneline(a, b, pred=None):
predicate = (lambda x, y: x + y) if pred is None else pred
return predicate(a, b)

Linear Regression in Python

I am a brand new to programming and am taking a course in Python. I was asked to do linear regression on a data set that my professor gave out. Below is the program I have written (it doesn't work).
from math import *
f=open("data_setshort.csv", "r")
data = f.readlines()
f.close()
xvalues=[]; yvalues=[]
for line in data:
x,y=line.strip().split(",")
x=float(x.strip())
y=float(y.strip())
xvalues.append(x)
yvalues.append(y)
def regression(x,y):
n = len(x)
X = sum(x)
Y = sum(y)
for i in x:
A = sum(i**2)
return A
for i in x:
for j in y:
C = sum(x*y)
return C
return C
D = (X**2)-nA
m = (XY - nC)/D
b = (CX - AY)/D
return m,b
print "xvalues:", xvalues
print "yvalues:", yvalues
regression(xvalues,yvalues)
I am getting an error that says: line 23, in regression, A = sum (I**2). TypeError: 'float' object is not iterable.
I need to eventually create a plot for this data set (which I know how to do) and for the line defined by the regression. But for now I am trying to do linear regression in Python.
You can't sum over a single float, but you can sum over lists. E. g. you probably mean A = sum([xi**2 for xi in x]) to calculate Sum of each element in x to the power of 2. You also have various return statements in your code that don't really make any sense and can probably be removed completely, e. g. return C after the loop. Additionally, multiplication of two variables a and b can only be done by using a*b in python. Simply writing ab is not possible and will instead be regarded as a single variable with name "ab".
The corrected code could look like this:
def regression(x,y):
n = len(x)
X = sum(x)
Y = sum(y)
A = sum([xi**2 for xi in x])
C = sum([xi*yi for xi, yi in zip(x,y)])
D = X**2 - n*A
m = (X*Y - n*C) / float(D)
b = (C*X - A*Y) / float(D)
return (m, b)
You should probably put in something like A += i**2
As you must understand from the error message that you cannot iterate over a float, which means if i=2 you can't iterate over it as it is not a list, but if as you need to sum all the squares of x, you are iterating over x in for i in x and then you add the squares of i i**2 to A A+=i**2 adn then you return A.
Hope this helps!

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.

Z3: how to encode If-the-else in Z3 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)

Categories