I am trying to carry out the Newton's method in Python to solve a problem. I have followed the approach of some examples but I am getting an Overflow Error. Do you have any idea what is causing this?
def f1(x):
return x**3-(2.*x)-5.
def df1(x):
return (3.*x**2)-2.
def Newton(f, df, x, tol):
while True:
x1 = f(x) - (f(x)/df(x))
t = abs(x1-x)
if t < tol:
break
x = x1
return x
init = 2
print Newton(f1,df1,init,0.000001)
Newton's method is
so x1 = f(x) - (f(x)/df(x))
should be
x1 = x - (f(x)/df(x))
There is a bug in your code. It should be
def Newton(f, df, x, tol):
while True:
x1 = x - (f(x)/df(x)) # it was f(x) - (f(x)/df(x))
t = abs(x1-x)
if t < tol:
break
x = x1
return x
The equation you're solving is cubic, so there are two values of x where df(x)=0. Dividing by zero or a value close to zero will cause an overflow, so you need to avoid doing that.
One practical consideration for Newton's algorithm is how to handle values of x near local maxima or minima. Overflow is likely caused by dividing by something near zero. You can show this by adding a print statement before your x= line -- print x and df(x). To avoid this problem, you can calculate df(x) before dividing, and if it's below some threshold, bump the value of x up or down a small amount and try again.
Related
I am trying to approximate the volume of a 2 variable definite integral sin^2(x)-cos^2(y) using while and for loops. I've changed the code quite often and with the most recent change, it broke. I am very new to python so I'm still figuring out how to work with arrays properly.
This is what I have untill now (EDIT: With alani's comment I managed to fix the error, but now I'm not receiving an answer when running the code)
import numpy as np
import scipy.integrate
def f(x,y):
return np.sin(x)**2-np.cos(y)**2
print(scipy.integrate.dblquad(f,0,1,0,2))
def Riemann(x0,xn,y0,yn,N):
e = 1;
while e > 1e-3:
x = np.linspace(0,1,N)
y = np.linspace(0,2,N)
dx = (x0-xn)/N
dy = (y0-yn)/N
for i in range(N):
V = (dx*dy)*(f(x,y))
np.sum(V)
e = abs(1-V)
print(Riemann(0,1,0,2,1000))
When running this code I receive:
(-0.2654480895858587, 9.090239973208559e-15)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-9-c654507b2f73> in <module>
19 np.sum(V)
20 e = abs(1-V)
---> 21 print(Riemann(0,1,0,2,10))
22
23
<ipython-input-9-c654507b2f73> in Riemann(x0, xn, y0, yn, N)
10 def Riemann(x0,xn,y0,yn,N):
11 e = 1;
---> 12 while e > 1e-3:
13 x = np.linspace(0,1,N)
14 y = np.linspace(0,2,N)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Your code has multiple issues, I'll address them so that you can improve. First off all, the formatting is pretty terrible. Put spaces after commas, separate things more with white-space, etc. You can see the difference in my code, and I'm by no means an expert at code formatting.
Second, your method is not doing what you think it's doing. Every time you iterate i, you create an entire array of values and you assign it to V, since x and y are both arrays. Neither x nor y are being updated here. The loop does the same thing every time, and V get re-assigned the same value every time. np.sum(V) never gets assigned anywhere, so the only thing getting updated at all in that loop is e. Of course, that bit is incorrect since you cannot subtract a vector from a scalar, since, as I wrote above, V is a vector.
Your function didn't use x0, y0, etc. for your bounds of integration, since your linspaces were hardcoded.
Now we come to the solution. There are two approaches to this problem. There's the "slow" pure Python way, where we just loop over our y's and x's and take function values multiplied by the base dx * dy. That version looks like this:
# This a naive version, using two for loops. It's very slow.
def Riemann(x0, xn, y0, yn, N):
xs = np.linspace(x0, xn, N)
ys = np.linspace(y0, yn, N)
dx = (x0 - xn) / N
dy = (y0 - yn) / N
V = 0
for y in ys:
for x in xs:
V += f(x, y)
return dx * dy * V
Note I moved the multiplication outside to save some on performance.
The other way is to use numpy, that version looks like this:
def Riemann(x0, xn, y0, yn, N):
points = itertools.product(np.linspace(x0, xn, N), np.linspace(y0, yn, N))
points = np.array(list(points))
xs = points[:, 0]
ys = points[:, 1]
dx = (x0 - xn) / N
dy = (y0 - yn) / N
return dx * dy * np.sum(f(xs, ys))
Here we avoid the double for-loop. Note that you must include import itertools for this to work. Here we use the Cartesian product to create all points we wish to evaluate, and then give those points to your function f which is designed to work with numpy arrays. We get a vector back from f of all the function values at each point, and we simply just sum all the elements, just like we did in the for-loop. Then we can multiply by the common base dx * dy and return that.
The only thing I do not understand about your code is what you want e to do, and how it relates to N. I'm guessing it's some sort of error tolerance, but why you were trying to subtract the total volume so far (even if your code did nothing of the sort) from 1 I can't understand.
I need to find the lower and upper intersections with the x-axis of a curve given by
y=f(x)=10⋅exp(sin(x))−(x^2)/2
In order to find the arc length of the curve, in Python
I have already tried two methods, The secant method which I cannot get to work at all. And the Newton Method which finds one intersection.
from math import exp
from math import sin
from math import cos
def func( x ):
return 10*exp(sin(x))-(x**2)/2
def derivFunc( x ):
return 10*exp(sin(x))*cos(x)-x
def newtonRaphson( x ):
h = func(x) / derivFunc(x)
while abs(h) >= 0.0001:
h = func(x)/derivFunc(x)
x = x - h
print("The value of the root is : ",
"%.4f"% x)
x0 = -20
newtonRaphson(x0)
which gives
The value of the root is : -5.7546
Then the second method
import math
from math import exp
from math import sin
def f(x):
f = 10*exp(sin(x))-(x**2)/2
return f;
def secant(x1, x2, E):
n = 0; xm = 0; x0 = 0; c = 0;
if (f(x1) * f(x2) < 0):
while True:
x0 = ((x1 * f(x2) - x2 * f(x1)) /(f(x2) - f(x1)));
c = f(x1) * f(x0);
x1 = x2;
x2 = x0;
n += 1;
if (c == 0):
xm = ((x1 * f(x2) - x2 * f(x1)) /(f(x2) - f(x1)));
if(abs(xm - x0) < E):
print("Root of the given equation =",round(x0, 6));
print("No. of iterations = ", n);
print("Can not find a root in ","the given inteval");
x1 = 0; x2 = 1;
E = 0.0001;
secant(x1, x2, E);
Only results in
NameError: name 'x2' is not defined
Yet whenever I've tried defining the characters it won't run
I would like to be able to get the upper and lower intersections with the x-axis, So I can find the arc length. And is there a way to get it to plot the graph as well
About the Newton-Raphson method:
Normal behaviour
It works mostly as intended. The method may converge to a single root only, which depends on the starting point. To get another root, you need another starting point.
Your function yields:
>>> newtonRaphson(-20)
-5.7545790362989
>>> newtonRaphson(5)
3.594007784799419
Which seems to be correct.
Bugs
The Newton-Raphson method isn't guaranteed to converge, it may enter an ifinite loop, in which case your program would hang indefinitely, or the derivative at a point may be zero, in which case you can't compute h. You need to handle these cases.
Style
There is a lot of things that can be inproved:
The bug must be fixed
You Newton-Raphson method currently only works for one function only. You should pass the function and derivative as arguments, so you can apply the method to any function you want.
The desired precision and max iterations can also be passed as arguments
It's bad practice to print within the function. You should return the value instead, so you can decide to do whatever with the result.
you should follow PEP8's style guidelines
include a docstring if you plan to reuse it (wich is very possible, it is a very useful tool!)
My take on the method:
def newton_raphson(f, df, x, epsilon = 0.0001, maxiter = 1000):
""" Estimates the root of a function.
Gives an estimate to the required precision of a root of the given function
using the Newton-Raphson method.
Raises an Exception if the Newton-Raphson method doesn't converge in the
specified number of iterations.
Raises a ZeroDivisionError if the derivative is zero at a calculated point
:param f: The function
:param df: The function's derivative
:param x: the starting point for the method
:param epsilon: The desired precision
:param maxiter: The maximum number of iterations
:return: The root extimate
:rtype: float
"""
for _ in range(maxiter):
h = f(x)/df(x)
if abs(h) < epsilon:
return x
x = x - h
raise Exception("Newton Raphson method didn't "
+ "converge in {} iterations".format(maxiter))
usage:
>>> print(newton_raphson(func, derivFunc, 20))
-5.7545790362989
>>> print(newton_raphson(func, derivFunc, 5, 0.1, 100))
3.5837828560043477
>>> print(newton_raphson(func, derivFunc, 5, 0.001, 100))
3.594007784799419
>>> print(newton_raphson(func, derivFunc, 5, 1e-9, 4))
Traceback (most recent call last):
(...)
Exception: Newton Raphson method didn't converge in 4 iterations
About the secant method:
I'm not as familiar with that one, so I'll just mention the error you have is due to bad identation. Here it is fixed:
def secant(x1, x2, E):
n = 0; xm = 0; x0 = 0; c = 0;
if (f(x1) * f(x2) < 0):
while True:
x0 = ((x1 * f(x2) - x2 * f(x1)) /(f(x2) - f(x1)));
c = f(x1) * f(x0);
x1 = x2;
x2 = x0;
n += 1;
if (c == 0):
xm = ((x1 * f(x2) - x2 * f(x1)) /(f(x2) - f(x1)));
if(abs(xm - x0) < E):
print("Root of the given equation =",round(x0, 6));
print("No. of iterations = ", n);
print("Can not find a root in ","the given inteval");
If you plan to propely implement this method, the remarks about the Newton-Raphson method still hold.
My code for a linear interpolation is functioning strangely.
n = np.linspace(t[0],t[-1],101)
print(n)
ypl = np.zeros(len(n))
def closestPoint(x,ydat):
return ydat[int(round(x))]
def linearInt(T,ydat):
t0 = round(T+0.01-1)
y0 = closestPoint(T-1,ydat)
yn = closestPoint(T,ydat)
return y0 + (yn-y0)*(T-t0)
for i in range(len(n)):
if(i != 0):
ypl[i] = linearInt(n[i],y)
pl.plot(t,y,'o')
pl.plot(n,ypl)
The variable t is an array from 0 to 10 with a stepsize of 1.
The variable y is an array of data points (same size as t).
When I run this code the interpolation runs through all of the points, and looks almost correct, except for the weird spikes. What could be causing this?
Image of the output
I wrote this a year ago, and while it serves its purpose, I wondered if someone much cleverer than me could suggest ways to improve its efficiency.
def tempcolor(mintemp=0,maxtemp=32,mincolor=44000,maxcolor=3200,ctemp=10,c=0):
tempdiff=(mincolor-maxcolor) / (maxtemp-mintemp)
ccolor=(ctemp-mintemp) * tempdiff
ctouse=(mincolor-ccolor)
#print ctouse
return ctouse;
There's a range of numbers (mintemp to maxtemp). When ctouse is called, we calculate the ratio, then apply that same ratio to the other range of numbers (mincolor and maxcolor).
I'm using it in another script, and just wondered if anyone had any advice on making it neater. Or more accurate!
Thanks
Will
I am going to assume that you rarely or never change the given values for mintemp, maxtemp, mincolor, maxcolor.
The only efficiency improvement I can see would be to precalculate the ratio - something like
def make_linear_interpolator(x0, x1, y0, y1):
"""
Return a function to convert x in (x0..x1) to y in (y0..y1)
"""
dy_dx = (y1 - y0) / float(x1 - x0)
def y(x):
return y0 + (x - x0) * dy_dx
return y
color_to_temp = make_linear_interpolator(0, 32, 44000, 3200)
color_to_temp(10) # => 32150.0
I have a second order differential equation that I want to solve it in python. The problem is that for one of the variables I don't have the initial condition in 0 but only the value at infinity. Can one tell me what parameters I should provide for scipy.integrate.odeint ? Can it be solved?
Equation:
Theta needs to be found in terms of time. Its first derivative is equal to zero at t=0. theta is not known at t=0 but it goes to zero at sufficiently large time. all the rest is known. As an approximate I can be set to zero, thus removing the second order derivative which should make the problem easier.
This is far from being a full answer, but is posted here on the OP's request.
The method I described in the comment is what is known as a shooting method, that allows converting a boundary value problem into an initial value problem. For convenience, I am going to rename your function theta as y. To solve your equation numerically, you would first turn it into a first order system, using two auxiliary function, z1 = y and z2 = y', and so your current equation
I y'' + g y' + k y = f(y, t)
would be rewitten as the system
z1' = z2
z2' = f(z1, t) - g z2 - k z1
and your boundary conditions are
z1(inf) = 0
z2(0) = 0
So first we set up the function to compute the derivative of your new vectorial function:
def deriv(z, t) :
return np.array([z[1],
f(z[0], t) - g * z[1] - k * z[0]])
If we had a condition z1[0] = a we could solve this numerically between t = 0 and t = 1000, and get the value of y at the last time as something like
def y_at_inf(a) :
return scipy.integrate.odeint(deriv, np.array([a, 0]),
np.linspace(0, 1000, 10000))[0][-1, 0]
So now all we need to know is what value of a makes y = 0 at t = 1000, our poor man's infinity, with
a = scipy.optimize.root(y_at_inf, [1])