How to pass function expression to lambda (sympy) - python

I don't know how to pass an expression to lambda parameter.
I think this is a problem of type with sympy.core.power.pow type.
Here is the code :
import sympy
def trapezoid(f, a, b, n):
h = float(b - a) / n
result = 0.5 * f(a) + 0.5 * f(b)
for i in range(1, n):
result += f(a + i * h)
result *= h
return result
if __name__ == "__main__":
x = sympy.Symbol('x')
fonction = sympy.Pow(x,2)
print(fonction) # x**2
print(type(fonction)) # <class 'sympy.core.power.Pow'>
print("Expected Result : ", trapezoid(lambda x: x ** 2, 1, 5, 100))
print("Not expected result : ",trapezoid(lambda x:fonction, 1, 5, 100)) # Won't give me expected result
Have you guys any idea what is the correct syntax I need to use ?
I couldn't find an example of that even though I searched through several subjects.

Updating my answer based on the changes in your question -
Sympy lets you create expressions that can be utilized across multiple languages but you have to evaluate them when trying to run them. Your code's issue was that you were passing a sympy expression (which is NOT callable directly) to your trapezoid function. I have modified your trapezoid function to evaluate the 'fonction' you have defined.
from sympy import *
def trapezoid(f, a, b, n):
h = float(b - a) / n
result = 0.5 * f.evalf(subs={x: a}) + 0.5 * f.evalf(subs={x: b})
for i in range(1, n):
result += f.evalf(subs={x: (a + i * h)})
result *= h
return result
if __name__ == "__main__":
x = Symbol('x')
fonction = Pow(x,2)
print(fonction) # x**2
print("Expected result : ",trapezoid(fonction, 1, 5, 100))
x**2
Expected result : 41.3344000000000
Check this post out. Here you can find different ways of evaluating your sympy expressions in python.

https://www.w3schools.com/python/python_lambda.asp
The example below of how to create a lambda function and to call it.
my_func = lambda x: x**2;
print(my_func(3))
In your example:
def test(function):
print(function)
print(type(function))
print(function(3))
Calling it:
>>> test(lambda x:x**2)
<function <lambda> at 0x7f49d24d7d50>
<type 'function'>
9

Related

How to pass a function as an argument

I would like to find an approximate value for the number pi = 3.14.. by using the Newton method. In order to use it also for some other purpose and thus other function than sin(x), the aim is to implement a generic function that will be passed over as an argument. I have an issue in passing a function as an argument into an other function. I also tried lambda in different variations. The code I am showing below produces the error message: IndexError: list index out of range. I will appreciate your help in solving this issue and eventually make any suggestion in the code which may not be correct. Thanks.
from sympy import *
import numpy as np
import math
x = Symbol('x')
# find the derivative of f
def deriv(f,x):
h = 1e-5
return (lambda x: (f(x+h)-f(x))/h)
def newton(x0,f,err):
A = [x0]
n = 1
while abs(A[n]-A[n-1])<=err:
if n == 1:
y = lambda x0: (math.f(x0))
b = x0-y(x0)/(deriv(y,x0))
A.append(b)
n += 1
else:
k = len(A)
xk = A[k]
y = lambda xk: (math.f(xk))
b = newton(A[k],y,err)-y(newton(A[k],y,err))/deriv(y,k)
A.append(b)
n += 1
return A, A[-1]
print(newton(3,math.sin(3),0.000001))
I don't know why you use sympy because I made it without Symbol
At the beginning you have to calculate second value and append it to list A and later you can calculate abs(A[n]-A[n-1]) (or the same without n: abs(A[-1] - A[-2])) because it needs two values from this list.
Other problem is that it has to check > instead of <=.
If you want to send function sin(x) then you have to use math.sin without () and arguments.
If you want to send function sin(3*x) then you would have to use lambda x: math.sin(3*x)
import math
def deriv(f, x, h=1e-5):
return (f(x+h) - f(x)) / h
def newton(x0, f, err):
A = [x0]
x = A[-1] # get last value
b = x - (f(x) / deriv(f, x)) # calculate new value
A.append(b) # add to list
while abs(A[-1] - A[-2]) > err: # it has to be `>` instead of `<=`
x = A[-1] # get last value
b = x - (f(x) / deriv(f, x)) # calculate new value
A.append(b) # add to list
return A, A[-1]
# sin(x)
print(newton(3, math.sin, 0.000001)) # it needs function's name without `()`
# sin(3*x)
print(newton(3, lambda x:math.sin(3*x), 0.000001))
# sin(3*x) # the same without `lambda`
def function(x):
return math.sin(3*x)
print(newton(3, function, 0.000001))
Result:
([3, 3.1425464414785056, 3.1415926532960112, 3.141592653589793], 3.141592653589793)
([3, 3.150770863559604, 3.1415903295877707, 3.1415926535897936, 3.141592653589793], 3.141592653589793)
EDIT:
You may write loop in newton in different way and it will need <=
def newton(x0, f, err):
A = [x0]
while True:
x = A[-1] # get last value
b = x - (f(x) / deriv(f, x)) # calculate new value
A.append(b) # add to list
if abs(A[-1] - A[-2]) <= err:
break
return A, A[-1]

How can i change a variable name in a sympy expression

I am working on a project where I need to change all variables that are named 'a' to a new variable ai, where i is the order of the variable a in the expression. For instance if we use the expression: 1 + x + a + a ** 2, the output should be: 1 + x + a0 + a1 ** 2. Here is a code that I've written to solve this but it doesn't work, the expression remains unchanged.
import sympy.parsing.sympy_parser as sp1
import sympy as sp
I=sp1.parse_expr('1 + x + a + a**2', evaluate=False)
a,x=sp.symbols('a x')
def pre(expr):
i=0
for arg in sp.postorder_traversal(expr):
if arg==a:
tmp=sp.symbols('a'+str(i))
arg=tmp
print(arg)
i=i+1
pre(I)
print(I)
One way to achieve that is:
from sympy import Pow, Mul, Symbol, degree
def change_symbol(expr, a):
"""expr: the expression to modify
a: the symbol to look for and substitute
"""
# define a wild symbol to look for Symbols, Multiplications and Powers
# containing the specified symbol
w = Wild("w", properties=[
lambda t: isinstance(t, (Pow, Mul, Symbol)) and ((a in t.args) or (t == a))
])
# find the terms that satisfy the above criteria
terms = list(expr.find(w))
terms.sort(key=lambda t: degree(t), reverse=True)
# loop over those terms and performs the substitution with new symbols
name = a.name
for t in terms:
o = degree(t)
s = Symbol(name + "%s" % (o - 1))
expr = expr.subs(t, s**o)
return expr
change_symbol(I, a)
# out: a0 + a1**2 + x + 1
Your code did not work because you never changed the expression. When you say arg = tmp that assigns a value of tmp to arg but this does not update expr. #Davide_sd shows a way to recreate an expression with pieces that have been modified. You can also let replace do the traversal and let it replace a as it encounters it.
suffix = [0] #mutable suffix
def na():
rv = Symbol('a%s'%suffix[0])
suffix[0]+=1 # modify for next time
return rv
>>> a,x=var('a x')
>>> (1 + x + 2*a + a**2).replace(lambda x: x==a, lambda x: na())
a0**2 + 2*a1 + x + 1
Note that you said "order in expression" and coded as though you meant "order encountered" but in the polynomial sense, "higher order" terms will not necessarily appear later in the ordered terms. Note that a**2 appears before 2*a and that is why the replace gave it a value of a0:
>>> (1 + x + 2*a + a**2).args
(1, x, a**2, 2*a)

'NoneType' object is not iterable - where is an error?

My aim is to take a triple (A, B, C), compute three "neighbours", and then output the maximum of each of those neighbours to a list.
For example, the neighbours of (sqrt(6), 4*sqrt(3), 9*sqrt(2)) are
(sqrt(3)*sqrt(2), 3*sqrt(2), 4*sqrt(3))
(4*sqrt(3), 35*sqrt(3)*sqrt(2), 9*sqrt(2))
(sqrt(3)*sqrt(2), 9*sqrt(2), 14*sqrt(3))
so the values 14*sqrt(3), 36*sqrt(6), 4*sqrt(3) would be the output.
When I try this:
A = 1*sqrt(6)
B = 4*sqrt(3)
C = 9*sqrt(2)
def nbhs_1(triple):
X = triple[0]
Y = triple[1]
Z = triple[2]
print((X.canonicalize_radical(), (X * Y - Z).canonicalize_radical(), Y.canonicalize_radical()))
def nbhs_2(triple):
X = triple[0]
Y = triple[1]
Z = triple[2]
print((Y.canonicalize_radical(), (Y * Z - X).canonicalize_radical(), Z.canonicalize_radical()))
def nbhs_3(triple):
X = triple[0]
Y = triple[1]
Z = triple[2]
print((X.canonicalize_radical(), Z.canonicalize_radical(), (X * Z - Y).canonicalize_radical()))
result_1 = nbhs_1((A, B, C))
result_2 = nbhs_2((A, B, C))
result_3 = nbhs_3((A, B, C))
print(result_1)
print(result_2)
print(result_3)
l = [max(result_1), max(result_2), max(result_3)]
I get 'NoneType' object is not iterable.
The main problem is that you are not structuring the function properly:
It is recommended that you expose your arguments within the function call. Don't def nbhs_1(triple), do instead def nbhs_1(X, Y, Z). In this way you can actually have one single function that does what you want (easier to maintain)
Return your result. At the moment you are printing the outcome of the function call but you are not returning those results.
I'm also not sure the canonicalize_radical() call is also done properly. Python is object-oriented and by writing var.canonicalize_radical() you are inferring that var should itself know about this function (e.g. the function is part of var) but that sounds wrong. The correct call may be canonicalize_radical(var)
Basically, this should be closer to a correct solution:
A=1*sqrt(6)
B=4*sqrt(3)
C=9*sqrt(2)
def nbhs(X, Y, Z):
out1 = canonicalize_radical(X)
out2 = canonicalize_radical(X*Y-Z)
out3 = canonicalize_radical(Y)
return out1, out2, out3
l = [max(nbhs(A, B, C)), max(nbhs(B, A, C)), max(nbhs(C, B, A))]
The problem is that you are not calling the functions nbhs_1, nbhs_2, and nbhs_3 and also the functions aren't returning any values
from math import sqrt
A=1*sqrt(6)
B=4*sqrt(3)
C=9*sqrt(2)
triple = (A, B, C)
def nbhs_1(triple):
X=triple[0]
Y=triple[1]
Z=triple[2]
return (X.canonicalize_radical(),(X*Y-Z).canonicalize_radical(),Y.canonicalize_radical())
def nbhs_2(triple):
X=triple[0]
Y=triple[1]
Z=triple[2]
return (Y.canonicalize_radical(),(Y*Z-X).canonicalize_radical(),Z.canonicalize_radical())
def nbhs_3(triple):
X=triple[0]
Y=triple[1]
Z=triple[2]
return (X.canonicalize_radical(),Z.canonicalize_radical(),(X*Z-Y).canonicalize_radical())
l=[max(nbhs_1(triple)),max(nbhs_2(triple)),max(nbhs_3(triple))]

Create a formal linear function in Sympy

I have an expression in Sympy (like
-M - n + x(n)
) and I would
like to create a formal linear function, says f, and apply it to my expression, in order to get, after simplification:
-f(M) - f(n) + f(x(n))
Is it possible to tell sympy that a property such as linearity is verified?
A very hacky way to do it would be to apply the function f to every subexpression which is in a sum.
For instance when given an expressions like the first one I gave, it would be nice to simply access the terms appearing in the sum (here it would be
[-M, -n , x(n)]
Then mapping f on the list and sum it to get what is expected.
Is there an easy way to do so, or have I necessarily to go trough the syntactic tree of the expression ?
This works:
>>> x,f = map(Function, 'xf'); n,M = symbols('n,M'); expr = -M - n + x(n)
>>> Add(*[f(a) for a in Add.make_args(expr)])
f(-M) + f(-n) + f(x(n))
If you have an expression like f(n*(M + 1)) and you expand it you will get f(n*M + n). Can you tell SymPy to apply the function to the args of f's args? Yes:
>>> expr = f(n*(M + 1))
>>> expr.expand().replace(lambda x: x.func == f,
... lambda x: Add(*[f(a) for a in Add.make_args(x.args[0])]))
f(n) + f(M*n)
If you call such a replacement linapp you can use it for any function that you want:
def linapp(expr, *f):
return expr.expand().replace(
lambda x: x.func in f,
lambda x: Add(*[x.func(a) for a in Add.make_args(x.args[0])]))
>>> print(linapp(cos(x+y) + sin(x + y), cos, sin))
sin(x) + sin(y) + cos(x) + cos(y)
(Not saying that it's a true result, just that you can do it. And if you replace a variable with something else and you want to reapply the linearization, you can:
>>> linapp(_.subs(y, z + 1), cos)
sin(x) + sin(z + 1) + cos(x) + cos(z) + cos(1)
Here's a hackey way that goes through the syntactic tree:
from sympy import *
init_session()
M,n=symbols('M n')
thing=-f(M) - f(n) + f(x(n))
def linerize_element(bro):
return bro.args[0] if len(bro.args) == 1 else bro.args[0] * bro.args[1].args[0]
print([ linerize_element(tmp) for tmp in thing.args])

Modular multiplicative inverse function in Python

Does some standard Python module contain a function to compute modular multiplicative inverse of a number, i.e. a number y = invmod(x, p) such that x*y == 1 (mod p)? Google doesn't seem to give any good hints on this.
Of course, one can come up with home-brewed 10-liner of extended Euclidean algorithm, but why reinvent the wheel.
For example, Java's BigInteger has modInverse method. Doesn't Python have something similar?
Python 3.8+
y = pow(x, -1, p)
Python 3.7 and earlier
Maybe someone will find this useful (from wikibooks):
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
raise Exception('modular inverse does not exist')
else:
return x % m
If your modulus is prime (you call it p) then you may simply compute:
y = x**(p-2) mod p # Pseudocode
Or in Python proper:
y = pow(x, p-2, p)
Here is someone who has implemented some number theory capabilities in Python: http://www.math.umbc.edu/~campbell/Computers/Python/numbthy.html
Here is an example done at the prompt:
m = 1000000007
x = 1234567
y = pow(x,m-2,m)
y
989145189L
x*y
1221166008548163L
x*y % m
1L
You might also want to look at the gmpy module. It is an interface between Python and the GMP multiple-precision library. gmpy provides an invert function that does exactly what you need:
>>> import gmpy
>>> gmpy.invert(1234567, 1000000007)
mpz(989145189)
Updated answer
As noted by #hyh , the gmpy.invert() returns 0 if the inverse does not exist. That matches the behavior of GMP's mpz_invert() function. gmpy.divm(a, b, m) provides a general solution to a=bx (mod m).
>>> gmpy.divm(1, 1234567, 1000000007)
mpz(989145189)
>>> gmpy.divm(1, 0, 5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: not invertible
>>> gmpy.divm(1, 4, 8)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: not invertible
>>> gmpy.divm(1, 4, 9)
mpz(7)
divm() will return a solution when gcd(b,m) == 1 and raises an exception when the multiplicative inverse does not exist.
Disclaimer: I'm the current maintainer of the gmpy library.
Updated answer 2
gmpy2 now properly raises an exception when the inverse does not exists:
>>> import gmpy2
>>> gmpy2.invert(0,5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: invert() no inverse exists
As of 3.8 pythons pow() function can take a modulus and a negative integer. See here. Their case for how to use it is
>>> pow(38, -1, 97)
23
>>> 23 * 38 % 97 == 1
True
Here is a one-liner for CodeFights; it is one of the shortest solutions:
MMI = lambda A, n,s=1,t=0,N=0: (n < 2 and t%N or MMI(n, A%n, t, s-A//n*t, N or n),-1)[n<1]
It will return -1 if A has no multiplicative inverse in n.
Usage:
MMI(23, 99) # returns 56
MMI(18, 24) # return -1
The solution uses the Extended Euclidean Algorithm.
Sympy, a python module for symbolic mathematics, has a built-in modular inverse function if you don't want to implement your own (or if you're using Sympy already):
from sympy import mod_inverse
mod_inverse(11, 35) # returns 16
mod_inverse(15, 35) # raises ValueError: 'inverse of 15 (mod 35) does not exist'
This doesn't seem to be documented on the Sympy website, but here's the docstring: Sympy mod_inverse docstring on Github
Here is a concise 1-liner that does it, without using any external libraries.
# Given 0<a<b, returns the unique c such that 0<c<b and a*c == gcd(a,b) (mod b).
# In particular, if a,b are relatively prime, returns the inverse of a modulo b.
def invmod(a,b): return 0 if a==0 else 1 if b%a==0 else b - invmod(b%a,a)*b//a
Note that this is really just egcd, streamlined to return only the single coefficient of interest.
I try different solutions from this thread and in the end I use this one:
def egcd(a, b):
lastremainder, remainder = abs(a), abs(b)
x, lastx, y, lasty = 0, 1, 1, 0
while remainder:
lastremainder, (quotient, remainder) = remainder, divmod(lastremainder, remainder)
x, lastx = lastx - quotient*x, x
y, lasty = lasty - quotient*y, y
return lastremainder, lastx * (-1 if a < 0 else 1), lasty * (-1 if b < 0 else 1)
def modinv(a, m):
g, x, y = self.egcd(a, m)
if g != 1:
raise ValueError('modinv for {} does not exist'.format(a))
return x % m
Modular_inverse in Python
Here is my code, it might be sloppy but it seems to work for me anyway.
# a is the number you want the inverse for
# b is the modulus
def mod_inverse(a, b):
r = -1
B = b
A = a
eq_set = []
full_set = []
mod_set = []
#euclid's algorithm
while r!=1 and r!=0:
r = b%a
q = b//a
eq_set = [r, b, a, q*-1]
b = a
a = r
full_set.append(eq_set)
for i in range(0, 4):
mod_set.append(full_set[-1][i])
mod_set.insert(2, 1)
counter = 0
#extended euclid's algorithm
for i in range(1, len(full_set)):
if counter%2 == 0:
mod_set[2] = full_set[-1*(i+1)][3]*mod_set[4]+mod_set[2]
mod_set[3] = full_set[-1*(i+1)][1]
elif counter%2 != 0:
mod_set[4] = full_set[-1*(i+1)][3]*mod_set[2]+mod_set[4]
mod_set[1] = full_set[-1*(i+1)][1]
counter += 1
if mod_set[3] == B:
return mod_set[2]%B
return mod_set[4]%B
The code above will not run in python3 and is less efficient compared to the GCD variants. However, this code is very transparent. It triggered me to create a more compact version:
def imod(a, n):
c = 1
while (c % a > 0):
c += n
return c // a
from the cpython implementation source code:
def invmod(a, n):
b, c = 1, 0
while n:
q, r = divmod(a, n)
a, b, c, n = n, c, b - q*c, r
# at this point a is the gcd of the original inputs
if a == 1:
return b
raise ValueError("Not invertible")
according to the comment above this code, it can return small negative values, so you could potentially check if negative and add n when negative before returning b.
To figure out the modular multiplicative inverse I recommend using the Extended Euclidean Algorithm like this:
def multiplicative_inverse(a, b):
origA = a
X = 0
prevX = 1
Y = 1
prevY = 0
while b != 0:
temp = b
quotient = a/b
b = a%b
a = temp
temp = X
a = prevX - quotient * X
prevX = temp
temp = Y
Y = prevY - quotient * Y
prevY = temp
return origA + prevY
Well, here's a function in C which you can easily convert to python. In the below c function extended euclidian algorithm is used to calculate inverse mod.
int imod(int a,int n){
int c,i=1;
while(1){
c = n * i + 1;
if(c%a==0){
c = c/a;
break;
}
i++;
}
return c;}
Translates to Python Function
def imod(a,n):
i=1
while True:
c = n * i + 1;
if(c%a==0):
c = c/a
break;
i = i+1
return c
Reference to the above C function is taken from the following link C program to find Modular Multiplicative Inverse of two Relatively Prime Numbers

Categories

Resources