Building a function with x,y parameters using Reverse Polish notation - python

I'm trying to build a python function from a input given in Reverse Polish notation. My function is supposed to be able to take in x and y values as parameters and return the value of the function for the respective x and y.
My input is for example:
"x 1 + y 3 * +"
My expected result would be a function object similar to:
fun = lambda x,y: x+1+y*3
So that I can call fun(1,2) and get 9 as the result.
So far I can evaluate input without variables and give the result.
bin_ops = {
"+": (lambda a, b: a + b),
"-": (lambda a, b: a - b),
"*": (lambda a, b: a * b),
"/": (lambda a, b: a / b),
}
def eval(expression):
tokens = expression.split()
stack = []
for token in tokens:
if token in bin_ops:
arg2 = stack.pop()
arg1 = stack.pop()
result = bin_ops[token](arg1, arg2)
stack.append(result)
else:
stack.append(float(token))
return stack.pop()
txt = '2 1 + 2 3 * +'
print(eval(txt)) # prints 9.0
Can you help me how to build a function instead of directly the result
and how I can process variables (such as x and y) properly?

You can change your parsing code from creating values into creating functions that can be called with keyword arguments for final evaluation:
bin_ops = {
"+": lambda a, b: lambda **namespace: a(**namespace) + b(**namespace),
"-": lambda a, b: lambda **namespace: a(**namespace) - b(**namespace),
"*": lambda a, b: lambda **namespace: a(**namespace) * b(**namespace),
"/": lambda a, b: lambda **namespace: a(**namespace) / b(**namespace),
}
def eval(expression):
tokens = expression.split()
stack = []
for token in tokens:
if token in bin_ops:
arg2 = stack.pop()
arg1 = stack.pop()
result = bin_ops[token](arg1, arg2)
stack.append(result)
else:
try:
num = float(token)
except ValueError:
stack.append(lambda *, _token=token, **namespace: namespace[_token])
else:
stack.append(lambda *, _num=num, **namespace: _num)
return stack.pop()
txt = "x 1 + y 3 * +"
fun = eval(txt)
print(fun(x=2, y=4)) # prints 15.0
The way Python scopes work makes it a little tricky to generate functions that use variables from a loop. This is why I use token and num to set default values for arguments in our generated lambda functions, rather than using their names directly. If you just did lambda **namespace: namespace[token], you'd find that token had changed value as the loop kept running. The bin_ops code doesn't have that issue because the final functions are already nested in an extra scope, since the lambda a, b function is where we build the inner lambdas.

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.)

Function binding in python

n = 7
def f(x):
n = 8
return x + 1
def g(x):
n = 9
def h():
return x + 1
return h
def f(f, x):
return f(x + n)
f = f(g, n)
g = (lambda y: y())(f)
I'm trying to understand and keep track of all the changes in the binding of functions, but cannot seem to grasp why the y parameter in the lambda function gets binded to h() on being called.
The transition from step 14-15 in this Python Tutor link to be precise
Let's change the names of the functions so that twisted code is easier to follow. We can name then sequentially like fun_n and reassign the names after each function definition. I added some comments too
The first one would be
n = 7
def fun_1(x):
n = 8
return x + 1
f = fun1
The second one:
def fun_2(x):
n = 9
def h():
return x + 1
return h
g = fun_2
Now we are ready for some bad renaming
def fun_3(f, x):
return f(x + n)
f = fun_3
And now...
f = f(g, n)
which is equivalent to fun_3(fun2, n) with n=7.
fun_3 will return fun_2(7+n), again with n=7.
fun_2 will return a closure of h with x=14, so it will return a function that returns the result of 14 + 1. So f is now a function that always return 15
Finally,
g = (lambda y: y())(f)
creates a lambda function that calls whatever parameter is passed to it, and calls it passing f as a parameter. It is equivalent to:
fun_4 = lambda y: y()
g = fun_4(f)
I don't think it is really useful as an excercise.

Is it possible to construct symbols in SymPy that anticommute?

I need to implement some Grassmann variables in python (i.e. anti-commuting variables). In other words, I would like something with behavior as follows
>>> from sympy import *
>>> x, y = symbols('x y')
>>> y*x
-x*y
>>> y*y
0
One other feature I would need from this is the ability to give a canonical ordering to my variables. When I typed >>> y*x, it would certainly have been valid to also output y*x over -x*y. But, I would like the ability to choose that x should appear to the left of y (perhaps only after calling a function simplify(y*x)).
Does SymPy or some other library have this ability? If not, what would be the best way to go about implementing this myself (e.g. should I create a symbolic library myself, extend SymPy, etc.)?
You can make a new class inheriting from Symbol and change its behaviour on multiplication (__mul__) to the desired one.
To make this any useful, you need a canonic ordering anyway, which should be the same as SymPy’s (which at a quick glance appears to be by name, i.e., Symbol.name) to avoid problems.
from sympy import Symbol, S
class AnticomSym(Symbol):
def __new__(cls,*args,**kwargs):
return super().__new__(cls,*args,**kwargs,commutative=False)
def __mul__(self,other):
if isinstance(other,AnticomSym):
if other==self:
return S.Zero
elif other.name<self.name:
return -Symbol.__mul__(other,self)
return super().__mul__(other)
def __pow__(self,exponent):
if exponent>=2:
return S.Zero
else:
return super().__pow__(exponent)
x = AnticomSym("x")
y = AnticomSym("y")
assert y*x == -x*y
assert y*y == 0
assert y**2 == 0
assert y**1 == y
assert ((x+y)**2).expand() == 0
assert x*y-y*x == 2*x*y
Now, this still does not resolve complex products such as x*y*x*y correctly.
For this, we can write a function that sorts an arbitrary product (using bubble sort):
from sympy import Mul
def sort_product(product):
while True:
if not isinstance(product,Mul):
return product
arglist = list(product.args)
i = 0
while i < len(arglist)-1:
slice_prod = arglist[i]*arglist[i+1]
is_mul = isinstance(slice_prod,Mul)
arglist[i:i+2] = slice_prod.args if is_mul else [slice_prod]
i += 1
new_product = Mul(*arglist)
if product == new_product:
return new_product
product = new_product
z = AnticomSym("z")
assert sort_product(y*(-x)) == x*y
assert sort_product(x*y*x*y) == 0
assert sort_product(z*y*x) == -x*y*z
Finally, we can write a function that sorts all products within an expression by iterating through the expression tree and applying sort_product to every product it encounters:
def sort_products(expr):
if expr.is_Atom:
return expr
else:
simplified_args = (sort_products(arg) for arg in expr.args)
if isinstance(expr,Mul):
return sort_product(Mul(*simplified_args))
else:
return expr.func(*simplified_args)
from sympy import exp
assert sort_products(exp(y*(-x))) == exp(x*y)
assert sort_products(exp(x*y*x*y)-exp(z*y*z*x)) == 0
assert sort_products(exp(z*y*x)) == exp(-x*y*z)
Note that I may still not have accounted for every eventuality.
Wrzlprmft's answer is a great start so I will add the next logical step. Since you are asking for anticommuting symbols to be handled by a computer algebra system, it is reasonable to assume that you want to be able to differentiate with respect to them. This will require a function to overwrite sympy's product rule.
from sympy import Add, Mul, prod
from sympy.ntheory.multinomial import multinomial_coefficients_iterator
def AnticomDeriv(ptr, s, n):
args = ptr.args
m = len(args)
terms = []
factor = S.One
if isinstance(s, AnticomSym):
if n > 1:
return S.Zero
args = list(args)
for i in range(len(args)):
d = args[i].diff(s)
terms.append(factor * reduce(lambda x, y: x*y, (args[:i] + [d] + args[i + 1:]), S.One))
if isinstance(args[i], AnticomSym):
factor *= -1
return Add.fromiter(terms)
for kvals, c in multinomial_coefficients_iterator(m, n):
p = prod([arg.diff((s, k)) for k, arg in zip(kvals, args)])
terms.append(c * p)
return Add(*terms)
Mul._eval_derivative_n_times = AnticomDeriv
This will give the following (correct) behaviour.
>>> x = AnticomSym('x')
>>> y = AnticomSym('y')
>>> expr = x*y
>>> expr.diff(x)
y
>>> expr.diff(y)
-x

U combinator on a fibonacci : how would you translate this code to python?

I am trying to learn about combinators and I am having trouble understand the example given at (Y overriding self-application). I think I am beginning to grasp the concept but I am still far from understanding.
I would like to translate the following code to Python:
(define (U f) (f f))
(define (fib-nr f)
(lambda (n)
(if (< n 2) 1 (+ ((f f) (- n 1)) ((f f) (- n 2))))))
# Usage:
((U fib-nr) 35) ;==> 14930352
I tried a 'literal' translation by writing:
U = lambda u: u(u)
def fibnr(f):
return lambda n: 1 if (n<2) else (f (f (n-1))) + (f (f (n-2)))
But this doesnt work (I think it has to do with the order the functions are evaluated inside the lambda).
So I tried to use function composition as:
# http://code.activestate.com/recipes/52902-function-composition/
class compose:
'''compose functions. compose(f,g,x...)(y...) = f(g(y...),x...))'''
def __init__(self, f, g, *args, **kwargs):
self.f = f
self.g = g
self.pending = args[:]
self.kwargs = kwargs.copy()
def __call__(self, *args, **kwargs):
return self.f(self.g(*args, **kwargs), *self.pending, **self.kwargs)
U = lambda u: compose(u, u)
def fibnr(f):
ff = compose(f, f)
return lambda n: 1 if (n<2) else (ff (n-1)) + (ff (n-2))
But still didn't work, when calling my last snippet of code I get a lambda back:
>>> U(fibnr)(35)
<function <lambda> at 0x01A1B6B0>
So, is it possible to write a 'literal' translation of the given example in Python? How could I do it?
I wrote a simple translation that seems to produce correct results:
def U(f): return f(f)
def fibnr(f):
def lam(n):
if (n < 2): return 1
return f(f)(n-1) + f(f)(n-2)
return lam
Or if you really like lambdas:
def fibnr(f): return lambda n: 1 if (n < 2) else f(f)(n-1) + f(f)(n-2)
I think your initial problem was translating Lisp ((f f) x) into Python f(f(x)) instead of f(f)(x).
Good luck understanding combinators :)

Can a lambda function call itself recursively in Python?

A regular function can contain a call to itself in its definition, no problem. I can't figure out how to do it with a lambda function though for the simple reason that the lambda function has no name to refer back to. Is there a way to do it? How?
The only way I can think of to do this amounts to giving the function a name:
fact = lambda x: 1 if x == 0 else x * fact(x-1)
or alternately, for earlier versions of python:
fact = lambda x: x == 0 and 1 or x * fact(x-1)
Update: using the ideas from the other answers, I was able to wedge the factorial function into a single unnamed lambda:
>>> map(lambda n: (lambda f, *a: f(f, *a))(lambda rec, n: 1 if n == 0 else n*rec(rec, n-1), n), range(10))
[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]
So it's possible, but not really recommended!
without reduce, map, named lambdas or python internals:
(lambda a:lambda v:a(a,v))(lambda s,x:1 if x==0 else x*s(s,x-1))(10)
Contrary to what sth said, you CAN directly do this.
(lambda f: (lambda x: f(lambda v: x(x)(v)))(lambda x: f(lambda v: x(x)(v))))(lambda f: (lambda i: 1 if (i == 0) else i * f(i - 1)))(n)
The first part is the fixed-point combinator Y that facilitates recursion in lambda calculus
Y = (lambda f: (lambda x: f(lambda v: x(x)(v)))(lambda x: f(lambda v: x(x)(v))))
the second part is the factorial function fact defined recursively
fact = (lambda f: (lambda i: 1 if (i == 0) else i * f(i - 1)))
Y is applied to fact to form another lambda expression
F = Y(fact)
which is applied to the third part, n, which evaulates to the nth factorial
>>> n = 5
>>> F(n)
120
or equivalently
>>> (lambda f: (lambda x: f(lambda v: x(x)(v)))(lambda x: f(lambda v: x(x)(v))))(lambda f: (lambda i: 1 if (i == 0) else i * f(i - 1)))(5)
120
If however you prefer fibs to facts you can do that too using the same combinator
>>> (lambda f: (lambda x: f(lambda v: x(x)(v)))(lambda x: f(lambda v: x(x)(v))))(lambda f: (lambda i: f(i - 1) + f(i - 2) if i > 1 else 1))(5)
8
You can't directly do it, because it has no name. But with a helper function like the Y-combinator Lemmy pointed to, you can create recursion by passing the function as a parameter to itself (as strange as that sounds):
# helper function
def recursive(f, *p, **kw):
return f(f, *p, **kw)
def fib(n):
# The rec parameter will be the lambda function itself
return recursive((lambda rec, n: rec(rec, n-1) + rec(rec, n-2) if n>1 else 1), n)
# using map since we already started to do black functional programming magic
print map(fib, range(10))
This prints the first ten Fibonacci numbers: [1, 1, 2, 3, 5, 8, 13, 21, 34, 55],
Yes. I have two ways to do it, and one was already covered. This is my preferred way.
(lambda v: (lambda n: n * __import__('types').FunctionType(
__import__('inspect').stack()[0][0].f_code,
dict(__import__=__import__, dict=dict)
)(n - 1) if n > 1 else 1)(v))(5)
This answer is pretty basic. It is a little simpler than Hugo Walter's answer:
>>> (lambda f: f(f))(lambda f, i=0: (i < 10)and f(f, i + 1)or i)
10
>>>
Hugo Walter's answer:
(lambda a:lambda v:a(a,v))(lambda s,x:1 if x==0 else x*s(s,x-1))(10)
We can now use new python syntax to make it way shorter and easier to read:
Fibonacci:
>>> (f:=lambda x: 1 if x <= 1 else f(x - 1) + f(x - 2))(5)
8
Factorial:
>>> (f:=lambda x: 1 if x == 0 else x*f(x - 1))(5)
120
We use := to name the lambda: use the name directly in the lambda itself and call it right away as an anonymous function.
(see https://www.python.org/dev/peps/pep-0572)
def recursive(def_fun):
def wrapper(*p, **kw):
fi = lambda *p, **kw: def_fun(fi, *p, **kw)
return def_fun(fi, *p, **kw)
return wrapper
factorial = recursive(lambda f, n: 1 if n < 2 else n * f(n - 1))
print(factorial(10))
fibonaci = recursive(lambda f, n: f(n - 1) + f(n - 2) if n > 1 else 1)
print(fibonaci(10))
Hope it would be helpful to someone.
By the way, instead of slow calculation of Fibonacci:
f = lambda x: 1 if x in (1,2) else f(x-1)+f(x-2)
I suggest fast calculation of Fibonacci:
fib = lambda n, pp=1, pn=1, c=1: pp if c > n else fib(n, pn, pn+pp, c+1)
It works really fast.
Also here is factorial calculation:
fact = lambda n, p=1, c=1: p if c > n else fact(n, p*c, c+1)
Well, not exactly pure lambda recursion, but it's applicable in places, where you can only use lambdas, e.g. reduce, map and list comprehensions, or other lambdas. The trick is to benefit from list comprehension and Python's name scope. The following example traverses the dictionary by the given chain of keys.
>>> data = {'John': {'age': 33}, 'Kate': {'age': 32}}
>>> [fn(data, ['John', 'age']) for fn in [lambda d, keys: None if d is None or type(d) is not dict or len(keys) < 1 or keys[0] not in d else (d[keys[0]] if len(keys) == 1 else fn(d[keys[0]], keys[1:]))]][0]
33
The lambda reuses its name defined in the list comprehension expression (fn). The example is rather complicated, but it shows the concept.
Short answer
Z = lambda f : (lambda x : f(lambda v : x(x)(v)))(lambda x : f(lambda v : x(x)(v)))
fact = Z(lambda f : lambda n : 1 if n == 0 else n * f(n - 1))
print(fact(5))
Edited: 04/24/2022
Explanation
For this we can use Fixed-point combinators, specifically Z combinator, because it will work in strict languages, also called eager languages:
const Z = f => (x => f(v => x(x)(v)))(x => f(v => x(x)(v)))
Define fact function and modify it:
1. const fact n = n === 0 ? 1 : n * fact(n - 1)
2. const fact = n => n === 0 ? 1 : n * fact(n - 1)
3. const _fact = (fact => n => n === 0 ? 1 : n * fact(n - 1))
Notice that:
fact === Z(_fact)
And use it:
const Z = f => (x => f(v => x(x)(v)))(x => f(v => x(x)(v)));
const _fact = f => n => n === 0 ? 1 : n * f(n - 1);
const fact = Z(_fact);
console.log(fact(5)); //120
See also:
Fixed-point combinators in JavaScript: Memoizing recursive functions
I got some homework about it and figured out something, heres an example of a lambda function with recursive calls:
sucesor = lambda n,f,x: (f)(x) if n == 0 else sucesor(n-1,f,(f)(x))
I know this is an old thread, but it ranks high on some google search results :). With the arrival of python 3.8 you can use the walrus operator to implement a Y-combinator with less syntax!
fib = (lambda f: (rec := lambda args: f(rec, args)))\
(lambda f, n: n if n <= 1 else f(n-2) + f(n-1))
As simple as:
fac = lambda n: 1 if n <= 1 else n*fac(n-1)
Lambda can easily replace recursive functions in Python:
For example, this basic compound_interest:
def interest(amount, rate, period):
if period == 0:
return amount
else:
return interest(amount * rate, rate, period - 1)
can be replaced by:
lambda_interest = lambda a,r,p: a if p == 0 else lambda_interest(a * r, r, p - 1)
or for more visibility :
lambda_interest = lambda amount, rate, period: \
amount if period == 0 else \
lambda_interest(amount * rate, rate, period - 1)
USAGE:
print(interest(10000, 1.1, 3))
print(lambda_interest(10000, 1.1, 3))
Output:
13310.0
13310.0
If you were truly masochistic, you might be able to do it using C extensions, but this exceeds the capability of a lambda (unnamed, anonymous) functon.
No. (for most values of no).

Categories