Why does my lambdify not working when add my own function - python

I created a function and make it usable in my Sympy expression like this:
def Unit(x):
if(x != 0):
return 0
else:
return 1
Unit = Function('Unit')
x = Symbol('x')
My expression:
fx = x ** 2 + Unit(x)
But when I run:
lam_f = lambdify(x, fx, modules=["sympy"])
print(lam_f(-1))
It said that my Unit is not defined?
Can anyone explain where i went wrong?

Function('Unit') returns an undefined function with name Unit. See this question. If you want to use your previously defined function Unit, remove the call to Function():
def Unit(x):
if(x != 0):
return 0
else:
return 1
x = Symbol('x')
fx = x**2 + Unit(x)
lam_f = lambdify(x, fx, modules=['sympy'])
print(lam_f(-1)) # prints 1

Related

get a specific value from a function when function is given to as an argument?

I have a function that needs to give a specific value to an other function depending on the current iteration in a for loop. the get_change_vector returns a tuple of 4 elements depending on the iteration a want to get a specific value from it.
def get_change_vector(x, r,):
Xp = r*x + x**3 - x**5
Xp2 = r*x + x**2 - x**3
Xp3 = r*x -x/(1+x**2)
Xp4 = x-r+(2-x)/(1+x**2)
return (Xp, Xp2, Xp3, Xp4)
def main ():
for n in range (4):
Xs = [i for i in np.arange(-2, 2, 0.001)]
rs = [funcR(x)[n] for x in Xs]
i1, i2 = 0 if n < 2 else 1, 0 if n % 2 ==0 else 1
ax = axes[i1] [i2]
for x, r in zip (Xs, rs):
clr = 'g' if is_stable(get_change_vector,x, r) else 'r'
ax.plot(r, x, 'o', color=clr, markersize=0.1)
I tried to give a specific index to get_change_vector but it returns an error saying function is not subcriptable.
I tried making a variable of the needed function
function = get_change_vector(x,r)[n]
but this returned an error this is because of the what the is_stable when it reaches func(*args)
'numpy.float64' object is not callable
def get_derivative(func, n, i):
'''
Wrapper around our change_vector function
so derivative can handle multiple parameters
'''
def wraps(n):
args = i, n
return func(*args)
return derivative(wraps, n, dx=1e-6)
def is_stable(func, n , i ):
return get_derivative(func, n, i) < 0

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]

Composite functions in python - dual compose

I came across the following homework problem:
My code for this problem was marked wrong and when I viewed the suggested solution, I couldn't understand where I went wrong. I ran the codes of both functions in Python IDLE compiler only to see that both functions return the same output as seen below:
>>> def dual_function(f,g,n): #Suggested solution
def helper(x):
f1,g1 = f,g
if n%2==0:
f1,g1=g1,f1
for i in range(n):
x=f1(x)
f1,g1=g1,f1
return x
return helper
>>> def dual_function_two(f,g,n): #My solution
def helper(x):
if n%2==0:
for i in range (n):
if i%2==0:
x = g(x)
else:
x = f(x)
else:
for i in range(n):
if i%2==0:
x = f(x)
else:
x = g(x)
return x
return helper
>>> add1 = lambda x: x+1
>>> add2 = lambda x: x+2
>>> dual_function(add1,add2,4)(3)
9
>>> dual_function_two(add1,add2,4)(3)
9
>>>
I would appreciate it if someone could identify the mistake in my solution. Thank you.
The suggested solution is needlessly complex. Countless reassignments of variables and a loop are a recipe for a headache. Here's a simplified alternative -
def dual (f, g, n):
if n == 0:
return lambda x: x
else:
return lambda x: f(dual(g, f, n - 1)(x))
add1 = lambda x: 1 + x
add2 = lambda x: 2 + x
print(dual(add1,add2,4)(3))
# 9
# (1 + 2 + 1 + 2 + 3)
print(dual(add1,add2,9)(3))
# 16
# (1 + 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 3)
print(dual(add1,add2,0)(3))
# 3
The reason this works is because in the recursive branch, we call dual with swapped arguments, dual(g,f,n-1). So f and g change places each time as n decrements down to 0, the base case, which returns the identity (no-op) function.
A slightly less readable version, but works identically -
def dual (f, g, n):
return lambda x: \
x if n == 0 else f(dual(g, f, n - 1)(x))

Not recognized variable inside a loop in Python

I am trying to run loop in Python while specifying the variable x and y inside the loop. When I run the following loop:
my_funcs = {}
for i in range(len(data) - 1):
def foo(x, y):
x = data[i]['body']
y = data[i+1]['body']
tfidf = vectorizer.fit_transform([x, y])
return ((tfidf * tfidf.T).A)[0,1]
foo.func_name = "cosine_sim%d" % i
my_funcs["cosine_sim%d" % i] = foo
print(foo(x,y))
I get the strange error: x is not defined in the line print(foo(x,y)) Any idea why on earth this might be happening since I have stated that x = data[i]['body'] ?
Thanks in advance
If everything else is correct, I think you should move that method outside of the loop.
You only defined x within foo, so the print line doesn't know about it. Plus, you were overwriting the x parameter of foo anyways
def foo(x, y):
tfidf = vectorizer.fit_transform([x, y])
return ((tfidf * tfidf.T).A)[0,1]
my_funcs = {}
for i in range(len(data) - 1):
x = data[i]['body']
y = data[i+1]['body']
foo.func_name = "cosine_sim%d" % i
my_funcs["cosine_sim%d" % i] = foo
print(foo(x,y))

find the domain of a function, given the root of it

I need help writing a method that receives a function, and some number y and returns x such that f(x) = y. The function is differentiable using Newton's method:
from random import *
def diff_param(f,h=0.001):
return (lambda x: (f(x+h)-f(x))/h)
def NR(func, deriv, epsilon=10**(-8), n=100, x0=None):
""" returns a number such that f(number) == 0"""
if x0 is None:
x0 = uniform(-100.,100.)
x=x0; y=func(x)
for i in range(n):
if abs(y)<epsilon:
#print (x,y,"convergence in",i, "iterations")
return x
elif abs(deriv(x))<epsilon:
#print ("zero derivative, x0=",x0," i=",i, " xi=", x)
return None
else:
#print(x,y)
x = x- func(x)/deriv(x)
y = func(x)
#print("no convergence, x0=",x0," i=",i, " xi=", x)
return None
I need to write a method source(f,y) that returns the x such that f(x) = y.
def source(f,y):
You need to find the zeros of g(x) = f(x)-y :
def source(f,y):
def g(x):
return f(x)-y
x = NR(g, diff_param(g))
return x
This returns a single x, but there may be others. To find them you need to try other initial values x0.

Categories

Resources