Newton Raphson: Can the user input the function? - python

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

Related

Using recursion to find derivative of a function (Three-Point Endpoint Formula)

I need to find the n derivative from a function using a Three-Point Endpoint formula.
This is the general formula
Can anyone help me with the code? Cause mine seems to be really lacking.
This is my code:
formula = input('Input the formula here : ')
n = input('Input the exponent here: ')
def f(x):
return eval(formula)
fungsi = pow(formula,n)
x0 = eval(input('Input the approximation of x here : '))
h = eval(input('Input the stepsize h here : '))
def TPEP(x,h,n,formula): #Three Point End Point
return (1/(2*h))*(-3*f(x,n-1)+4*f(x+h,n-1)-f(x+2*h,n-1))
print('Derivative of f in x0 = {0} is : '.format(x0))
print("f'({0}) = {1:.7f} (Three Point Endpoint)".format(x0,TPEP(x0,h,n,formula)))
I'd be really grateful if anyone could help. Thank you.
I think the main point is that you have to check for termination in your TPEP. The second thing is that you actually have to execute the recursion: you are calling f, not your recursive approximation of a derivative TPEP. With some other fixes (careful, not thoroughly tested and no error handling):
import math
formula = input('Input the formula here : ')
n = int(input('Input the degree of derivative here: '))
def f(formula, x):
return eval(formula, globals(), {'x': x}) # use global and local scope
x0 = float(input('Input the approximation of x here : ')) # no error handling here - TODO
h = float(input('Input the stepsize h here : '))
def TPEP(x, h, n, formula): # Three Point End Point
if n <= 1: # need to check for iteration stop: the grade of derivatives
return (1/(2*h))*(-3*f(formula, x)+4*f(formula, x+h)-f(formula, x+2*h))
return (1/(2*h))*(-3*TPEP(x,h,n-1,formula)+4*TPEP(x+h,h,n-1,formula)-TPEP(x+2*h,h,n-1,formula)) # error-term omitted
print('Derivative of f in x0 = {0} is : '.format(x0))
print("f'({0}) = {1:.7f} (Three Point Endpoint)".format(x0, TPEP(x0, h, n, formula)))
which produces
Input the formula here : x**3-3*x**2-1
Input the degree of derivative here: 2
Input the approximation of x here : 2
Input the stepsize h here : .1
Derivative of f in x0 = 2.0 is :
f'(2.0) = 6.0000000 (Three Point Endpoint)
Also in your eval of f, use a variable (here local scope) to evaluate it conveniently at different x-values.

How to fix TypeError: 'Add' object is not callable?

def f(x):
f='exp(x)-x-2'
y=eval(f)
print(y)
return y
def bissection(f,f_line,f_2lines,a,b,epsilon1,epsilon2):
x=a
result_a=f(a)
x=b
result_b=f(b)
if (f.evalf(a)*f.evalf(b)>=0):
print("Interval [a,b] does not contain a zero ")
exit()
zeta=min(epsilon1,epsilon2)/10
x=a
while(f_line(x)>0):
if(x<b or x>-b):
x=x+zeta
else:
stop
ak=a
bk=b
xk=(ak+bk)/2
k=0
if (f(xk)*f(ak)<0):
ak=ak
bk=xk
if (f(xk)*f(bk)<0):
ak=xk
bk=bk
k=k+1
from sympy import *
import math
x=Symbol('x')
f=exp(x)-x-2
f_line=f.diff(x)
f_2lines=f_line.diff(x)
print("Derivative of f:", f_line)
print("2nd Derivative of f:", f_2lines)
a=int(input('Beginning of interval: '))
b=int(input('End of interval: '))
epsilon1=input('1st tolerance: ')
epsilon2=input('2nd tolerance: ')
bissection(f,f_line,f_2lines,a,b,epsilon1,epsilon2)
This program is an attempt to implement the Bissection Method. I've tried writing two functions:
The first one, f, is supposed to receive the extremes of the interval that may or may not contain a root (a and b) and return the value of the function evaluated in this point.
The second one, bissection, should receive the function, the function's first and second derivatives, the extremes of the interval (a,b) and two tolerances (epsilon1,epsilon2).
What I want to do is pass each value a and b, one at a time, as arguments to the function f, that is supposed to return f(a) and f(b); that is, the values of the function in each of the points a and b.
Then, it should test two conditions:
1) If the function values in the extremes of the intervals have opposite signs. If they don't, the method won't converge for this interval, then the program should terminate.
if(f.evalf(a)*f.evalf(b)>=0)
exit()
2)
while(f_line(x)>0): #while the first derivative of the function evaluated in x is positive
if(x<b or x>-b): #This should test whether x belongs to the interval [a,b]
x=x+zeta #If it does, x should receive x plus zeta
else:
stop
At the end of this loop, my objective was to determine whether the first derivative was strictly positive (I didn't do the negative case yet).
The problem: I'm getting the error
Traceback (most recent call last):
File "bissec.py", line 96, in <module>
bissection(f,f_line,f_2lines,a,b,epsilon1,epsilon2)
File "bissec.py", line 41, in bissection
result_a=f(a)
TypeError: 'Add' object is not callable
How can I properly call the function so that it returns the value of the function (in this case, f(x)=exp(x)-x-2), for every x needed? That is, how can I evaluate f(a) and f(b)?
Ok, so I've figured it out where your program was failing and I've got 4 reasons why.
First of all, and the main topic of your question, if you want to evaluate a function f for a determined x value, let's say a, you need to use f.subs(x, a).evalf(), as it is described in SymPy documentation. You used in 2 different ways: f.evalf(2) and f_line(a); both were wrong and need to be substituted by the correct syntax.
Second, if you want to stop a while loop you should use the keyword break, not "stop", as written in your code.
Third, avoid using the same name for variables and functions. In your f function, you also used f as the name of a variable. In bissection function, you passed f as a parameter and tried to call the f function. That'll fail too. Instead, I've changed the f function to f_calc, and applied the correct syntax of my first point in it.
Fourth, your epsilon1 and epsilon2 inputs were missing a float() conversion. I've added that.
Now, I've also edited your code to use good practices and applied PEP8.
This code should fix this error that you're getting and a few others:
from sympy import *
def func_calc(func, x, val):
"""Evaluate a given function func, whose varible is x, with value val"""
return func.subs(x, val).evalf()
def bissection(x, f, f_line, f_2lines, a, b, epsilon1, epsilon2):
"""Applies the Bissection Method"""
result_a = func_calc(f, x, a)
result_b = func_calc(f, x, b)
if (result_a * result_b >= 0):
print("Interval [a,b] does not contain a zero")
exit()
zeta = min(epsilon1, epsilon2) / 10
x_val = a
while(func_calc(f_line, x, a) > 0):
if(-b < x_val or x_val < b):
x_val = x_val + zeta
else:
break # the keyword you're looking for is break, instead of "stop"
print(x_val)
ak = a
bk = b
xk = (ak + bk) / 2
k = 0
if (func_calc(f, x, xk) * func_calc(f, x, ak) < 0):
ak = ak
bk = xk
if (func_calc(f, x, xk) * func_calc(f, x, bk) < 0):
ak = xk
bk = bk
k = k + 1
def main():
x = Symbol('x')
f = exp(x) - x - 2
f_line = f.diff(x)
f_2lines = f_line.diff(x)
print("Derivative of f:", f_line)
print("2nd Derivative of f:", f_2lines)
a = int(input('Beginning of interval: '))
b = int(input('End of interval: '))
epsilon1 = float(input('1st tolerance: '))
epsilon2 = float(input('2nd tolerance: '))
bissection(x, f, f_line, f_2lines, a, b, epsilon1, epsilon2)
if __name__ == '__main__':
main()

Newton’s method on functions that contains matrices using Python

I was able to find several implementations of Newton's methods, for example, this link or maybe this one.
However, most of the time the examples are with simple functions such as:
x^2−9=0 or x^3-x^2-1=0. I am looking for something that would work for:
My question for that I am lost in how to use this code to solve my problem. For example, I am not sure how I would apply the derivative (dfdx) on my F(x) that contain matrices. Also, if I should direct input the matrices on my "def f(x)"
The code that I am using:
def Newton(f, dfdx, x, eps):
f_value = f(x)
iteration_counter = 0
while abs(f_value) > eps and iteration_counter < 100:
try:
x = x - float(f_value)/dfdx(x)
except ZeroDivisionError:
print "Error! - derivative zero for x = ", x
sys.exit(1) # Abort with error
f_value = f(x)
iteration_counter += 1
# Here, either a solution is found, or too many iterations
if abs(f_value) > eps:
iteration_counter = -1
return x, iteration_counter
def f(x):
return x**2 - 9
def dfdx(x):
return 2*x
solution, no_iterations = Newton(f, dfdx, x=1000, eps=1.0e-6)
if no_iterations > 0: # Solution found
print "Number of function calls: %d" % (1 + 2*no_iterations)
print "A solution is: %f" % (solution)
else:
print "Solution not found!"
There aren't any special rules for deriving matrices - the derivative is just calculated for each element separately. I would suggest evaluating the $[x1,x2]' * M * [x1,x2]$ expression on paper to get a matrix of polynomials, and then calculating the derivative of each one.

Wting reversed function using bisection method in logarithmic run time

I'm trying to write a function that can take any function and return the a parameter that if put in the function, will return answer close to 0 (close to epsilon), the function will look something like this:
def solve(f, x0=-10000, x1=10000, epsilon=EPSILON):
the x0, x1 are the range in which to look for the answer.
another thing I know is that it applies only to the function that can be both positive and negative ( for example f(X) = x^2+1 is not a good function to solve).
I found an answer here Bisection method
def solve(f, x0=-10000, x1=10000, epsilon=EPSILON):
""" return the solution to f in the range between x0 and x1\
use an algorithm to check if a solution can be found so f(x)<epsilon
iterates in a while loop until either a solution is found or if the abs
the value of the midpoint is smaller than epsilon (return None)"""
# make sure the function is in the type that can be solved
if (f(x1) * f(x0)) >= 0:
return None
while True:
mid = (x0 + x1) / 2
sol = f(mid)
if abs(sol) < epsilon:
return mid
if mid == 0 or (abs(f(x1) - f(x0)) / 2) < epsilon:
return None
elif sol * f(x0) < 0:
x1 = mid
elif sol * f(x1) < 0:
x0 = mid
edit:
so far so good. now I have the main function I need to write - a function that gives the revered value for function. the function itself gets the function that needs to be reversed and an epsilon to which the answer suppose to be close to.
for example, for f(x) = x+2, I want the inverse_func(f(100)) to return 100.
the hint I have is that I can use the prev function that I showed. I tryied doing so like this:
def inverse(g, epsilon=EPSILON):
"""return f s.t. f(g(x)) = x"""
def ret_function(x):
return find_x(x, g, epsilon)
return ret_function
def find_x(x, g, epsilon):
x0, x1 = -10000, 1001
g_sol = x
sent_epsilone = EPSILON
while True:
def f(x):
g_val = g(x)
ans = g_sol - g_val
return ans
sol = solve(f, x0, x1, sent_epsilone)
if sol == None:
pass
else:
return sol
x0, x1 = x0 * 10, x1 * 10
what I tried to give "solve" function to solve the problem for me. I'm giving it a function that calculates the given value from f(x) minus a value that solve function needs to find.
for example for f(x) = x+2, then a call to
minus_func = inverse(g(100)) =inverse(102)
print(minus_func)
is suppos to return
100
because it the function inside "solve" is 102-f(x) and of course "solve" can find the right value for this.
and I tried this in my code, and it work fine, but not good enough. for some functions, it works fine. but for others, it doesn't work at all.
for the functions:
math.e**x
x**-3
and probably others, it doesn't work. does someone has an idea how to solve this?.
p.s - I'm writing the code in python so it'll be great if the answer is also in python. but anything else is ok (I know java also and anything that will explain the logic is, of course, great)
thanks!
The condition
if mid == 0 or (abs(f(x1) - f(x0)) / 2) < epsilon:
return None
does not make sense. Why is 0 excluded as a possible root? With the default initial values the method will fail in the first loop. And if the function values are that close, they either have the same sign, which was excluded, or they represent a root of the function since both values are small enough.
It should be replaced by the missing
if abs(x1-x0) < epsilon:
return mid
Try this implementation of binary search:
def solve(f, x0=-10000, x1=10000, epsilon=EPSILON):
if f(x0) * f(x1) > 0: # predicate of binary search
return None
while x1 - x0 > epsilon: # while search interval is bigger than EPS
mid = (x0 + x1) / 2 # take middle of interval
sol = f(mid) # take function value in mid point
if sol * f(x0) > 0: # one of roots is located in [mid, x1] interval
x0 = mid
else: # one of roots is located in [x0, mid] interval
x1 = mid
return (x0 + x1) / 2
Feel free to ask questions about it.

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