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.
Related
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
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]
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
[This image here is my python code for the Newton-Raphson method. The problem is with the mathematical function and the derivative. At the moment I am the one who specifies the function and its derivative. Is there any way to get the user to input the function that he/she desires?
import math
""" f: function, f_ : derivative of function, x0: initial guess, errortolerance: tolerance, maxIter: max number of iterations """
def newtonraphson(f, f_, x0, errortolerance=0.00001, maxIter=100):
"""
Take a function f, its derivative f_, initial value x0, TOL and NMAX,
and returns the root(s) of the equation using the NR method
"""
n = 1 #initial numebr of iterations
while n<=maxIter: # check while n less than maxIter
x1 = x0 - (f(x0)/f_(x0)) #newtonraphson formula
if x1 - x0 < errortolerance:
return x1
else:
x0 = x1
return False
if __name__ == "__main__":
def func(x): #initial function
return 5*math.pow(x,2) - 8*math.pow(x,1) + 4
def func_(x): #its derivative
return 10*math.pow(x,1) - 8
resNR = newtonraphson(func,func_,3) #result of newtonraphson
print(resNR)
You can use lambda and eval to let the user input the function and its derivative. I assume you are using Python 3. If you are using Python 2, replace input with raw_input.
if __name__ == '__main__':
f = lambda x : eval(input())
f_ = lambda x : eval(input())
print(newtonraphson(f, f_, 3))
Now, have your user enter an expression in x. Remember, only the already defined names are allowed in the input.
I have the following simple function:
def divide(x, y):
quotient = x/y
remainder = x % y
return quotient, remainder
x = divide(22, 7)
If I accesss the variable x I get:
x
Out[139]: (3, 1)
Is there a way to get only the quotient or the remainder?
You are essentially returning a tuple, which is an iterable we can index, so in the example above:
print x[0] would return the quotient and
print x[1] would return the remainder
You have two broad options, either:
Modify the function to return either or both as appropriate, for example:
def divide(x, y, output=(True, True)):
quot, rem = x // y, x % y
if all(output):
return quot, rem
elif output[0]:
return quot
return rem
quot = divide(x, y, (True, False))
Leave the function as it is, but explicitly ignore one or the other of the returned values:
quot, _ = divide(x, y) # assign one to _, which means ignore by convention
rem = divide(x, y)[1] # select one by index
I would strongly recommend one of the latter formulations; it's much simpler!
You can either unpack the return values when you call your method:
x, y = divide(22, 7)
Or you can just grab the first returned value:
x = divide(22, 7)[0]