Find the bounds (x1,x2) of the smallest root in Python
''' x1,x2 = rootsearch(f,a,b,dx). Searches the interval (a,b) in increments dx for the bounds (x1,x2) of the smallest root of f(x). Returns x1 = x2 = None if no roots were detected. ''' def rootsearch(f,a,b,dx): x1 = a; f1 = f(a) x2 = a + dx; f2 = f(x2) while f1*f2 > 0.0: if x1 >= b: return None,None x1 = x2; f1 = f2 x2 = x1 + dx; f2 = f(x2) else: return x1,x2
Python code for Romberg intergration to return the integral and the number of panels used.
''' I,nPanels = romberg(f,a,b,tol=1.0e-6). Romberg intergration of f(x) from x = a to b. Returns the integral and the number of panels used. ''' from numpy import zeros from trapezoid import * def romberg(f,a,b,tol=1.0e-6): def richardson(r,k): for j in range(k-1,0,-1): const = 4.0**(k-j) r[j] = (const*r[j+1] - r[j])/(const - 1.0) return r r = zeros(21) r[1] = trapezoid(f,a,b,0.0,1) r_old = r[1] for k in range(2,21): r[k] = trapezoid(f,a,b,r[k-1],k) r = richardson(r,k) if abs(r[1]-r_old) < tol*max(abs(r[1]),1.0): return r[1],2**(k-1) r_old = r[1] print "Romberg quadrature did not converge"
Find a root of f(x) = 0 with Ridder’s method in Python
''' root = ridder(f,a,b,tol=1.0e-9). Finds a root of f(x) = 0 with Ridder's method. The root must be bracketed in (a,b). ''' import error from math import sqrt def ridder(f,a,b,tol=1.0e-9): fa = f(a) if fa == 0.0: return a fb = f(b) if fb == 0.0: return b if fa*fb > 0.0: error.err('Root is not bracketed') for i in range(30): # Compute the improved root x from Ridder's formula c = 0.5*(a + b); fc = f(c) s = sqrt(fc**2 - fa*fb) if s == 0.0: return None dx = (c - a)*fc/s if (fa - fb) < 0.0: dx = -dx x = c + dx; fx = f(x) # Test for convergence if i > 0: if abs(x - xOld) < tol*max(abs(x),1.0): return x xOld = x # Re-bracket the root as tightly as possible if fc*fx > 0.0: if fa*fx < 0.0: b = x; fb = fx else: a = x; fa = fx else: a = c; b = x; fa = fc; fb = fx return None print 'Too many iterations'
Evaluate the diagonal rational function interpolant in Python
''' p = rational(xData,yData,x) Evaluates the diagonal rational function interpolant p(x) that passes through he data points ''' from numpy import zeros def rational(xData,yData,x): m = len(xData) r = yData.copy() rOld = zeros(m) for k in range(m-1): for i in range(m-k-1): if abs(x - xData[i+k+1]) < 1.0e-9: return yData[i+k+1] else: c1 = r[i+1] - r[i] c2 = r[i+1] - rOld[i+1] c3 = (x - xData[i])/(x - xData[i+k+1]) r[i] = r[i+1] + c1/(c3*(1.0 - c1/c2) - 1.0) rOld[i+1] = r[i+1] return r[0]
Evaluate X and Y returned from the differential equation solvers using printput frequency in Python
''' printSoln(X,Y,freq). Prints X and Y returned from the differential equation solvers using printput frequency 'freq'. freq = n prints every nth step. freq = 0 prints initial and final values only. ''' def printSoln(X,Y,freq): def printHead(n): print "\n x ", for i in range (n): print " y[",i,"] ", print def printLine(x,y,n): print "%13.4e"% x, for i in range (n): print "%13.4e"% y[i], print m = len(Y) try: n = len(Y[0]) except TypeError: n = 1 if freq == 0: freq = m printHead(n) for i in range(0,m,freq): printLine(X[i],Y[i],n) if i != m - 1: printLine(X[m - 1],Y[m - 1],n)
Powell’s method of minimizing user-supplied function in Python
''' xMin,nCyc = powell(F,x,h=0.1,tol=1.0e-6) Powell's method of minimizing user-supplied function F(x). x = starting point h = initial search increment used in 'bracket' xMin = mimimum point nCyc = number of cycles ''' from numpy import identity,array,dot,zeros,argmax from goldSearch import * from math import sqrt def powell(F,x,h=0.1,tol=1.0e-6): def f(s): return F(x + s*v) # F in direction of v n = len(x) # Number of design variables df = zeros(n) # Decreases of F stored here u = identity(n) # Vectors v stored here by rows for j in range(30): # Allow for 30 cycles: xOld = x.copy() # Save starting point fOld = F(xOld) # First n line searches record decreases of F for i in range(n): v = u[i] a,b = bracket(f,0.0,h) s,fMin = search(f,a,b) df[i] = fOld - fMin fOld = fMin x = x + s*v # Last line search in the cycle v = x - xOld a,b = bracket(f,0.0,h) s,fLast = search(f,a,b) x = x + s*v # Check for convergence if sqrt(dot(x-xOld,x-xOld)/n) < tol: return x,j+1 # Identify biggest decrease & update search directions iMax = argmax(df) for i in range(iMax,n-1): u[i] = u[i+1] u[n-1] = v print "Powell did not converge"
Python example of using Laguerre’s method to compute all the roots of equation
''' roots = polyRoots(a). Uses Laguerre's method to compute all the roots of a[0] + a[1]*x + a[2]*x^2 +...+ a[n]*x^n = 0. The roots are returned in the array 'roots', ''' from evalPoly import * from numpy import zeros,complex from cmath import sqrt from random import random def polyRoots(a,tol=1.0e-12): def laguerre(a,tol): x = random() # Starting value (random number) n = len(a) - 1 for i in range(30): p,dp,ddp = evalPoly(a,x) if abs(p) < tol: return x g = dp/p h = g*g - ddp/p f = sqrt((n - 1)*(n*h - g*g)) if abs(g + f) > abs(g - f): dx = n/(g + f) else: dx = n/(g - f) x = x - dx if abs(dx) < tol: return x print 'Too many iterations' def deflPoly(a,root): # Deflates a polynomial n = len(a)-1 b = [(0.0 + 0.0j)]*n b[n-1] = a[n] for i in range(n-2,-1,-1): b[i] = a[i+1] + root*b[i+1] return b n = len(a) - 1 roots = zeros((n),dtype=complex) for i in range(n): x = laguerre(a,tol) if abs(x.imag) < tol: x = x.real roots[i] = x a = deflPoly(a,x) return roots raw_input("\nPress return to exit")
Find the coefficients of the polynomial that fits the specified data in the least squares sense
''' c = polyFit(xData,yData,m). Returns coefficients of the polynomial p(x) = c[0] + c[1]x + c[2]x^2 +...+ c[m]x^m that fits the specified data in the least squares sense. sigma = stdDev(c,xData,yData). Computes the std. deviation between p(x) and the data. ''' from numpy import zeros from math import sqrt from gaussPivot import * def polyFit(xData,yData,m): a = zeros((m+1,m+1)) b = zeros(m+1) s = zeros(2*m+1) for i in range(len(xData)): temp = yData[i] for j in range(m+1): b[j] = b[j] + temp temp = temp*xData[i] temp = 1.0 for j in range(2*m+1): s[j] = s[j] + temp temp = temp*xData[i] for i in range(m+1): for j in range(m+1): a[i,j] = s[i+j] return gaussPivot(a,b) def stdDev(c,xData,yData): def evalPoly(c,x): m = len(c) - 1 p = c[m] for j in range(m): p = p*x + c[m-j-1] return p n = len(xData) - 1 m = len(c) - 1 sigma = 0.0 for i in range(n+1): p = evalPoly(c,xData[i]) sigma = sigma + (yData[i] - p)**2 sigma = sqrt(sigma/(n - m)) return sigma
Plots data points and the fitting polynomial using Python
''' plotPoly(xData,yData,coeff) Plots data points and the fitting polynomial defined by its coefficient array {coeff} = {a0, a1. ...} ''' from numpy import zeros,arange from xyPlot import * def plotPoly(xData,yData,coeff): m = len(coeff) x1 = min(xData) x2 = max(xData) dx = (x2 - x1)/20.0 x = arange(x1,x2 + dx/10.0,dx) y = zeros((len(x)))*1.0 for i in range(m): y = y + coeff[i]*x**i xyPlot(xData,yData,'no',x,y,'ln')
Solve simultaneous equations using the Newton-Raphson method in Python
''' soln = newtonRaphson2(f,x,tol=1.0e-9). Solves the simultaneous equations f(x) = 0 by the Newton-Raphson method using {x} as the initial guess. Note that {f} and {x} are vectors. ''' from numpy import zeros,dot from gaussPivot import * from math import sqrt def newtonRaphson2(f,x,tol=1.0e-9): def jacobian(f,x): h = 1.0e-4 n = len(x) jac = zeros((n,n)) f0 = f(x) for i in range(n): temp = x[i] x[i] = temp + h f1 = f(x) x[i] = temp jac[:,i] = (f1 - f0)/h return jac,f0 for i in range(30): jac,f0 = jacobian(f,x) if sqrt(dot(f0,f0)/len(x)) < tol: return x dx = gaussPivot(jac,-f0) x = x + dx if sqrt(dot(dx,dx)) < tol*max(max(abs(x)),1.0): return x print 'Too many iterations'
Example of Newton-Raphson method with bisection in Python
''' root = newtonRaphson(f,df,a,b,tol=1.0e-9). Finds a root of f(x) = 0 by combining the Newton-Raphson method with bisection. The root must be bracketed in (a,b). Calls user-supplied functions f(x) and its derivative df(x). ''' def newtonRaphson(f,df,a,b,tol=1.0e-9): import error fa = f(a) if fa == 0.0: return a fb = f(b) if fb == 0.0: return b if fa*fb > 0.0: error.err('Root is not bracketed') x = 0.5*(a + b) for i in range(30): fx = f(x) if abs(fx) < tol: return x # Tighten the brackets on the root if fa*fx < 0.0: b = x else: a = x # Try a Newton-Raphson step dfx = df(x) # If division by zero, push x out of bounds try: dx = -fx/dfx except ZeroDivisionError: dx = b - a x = x + dx # If the result is outside the brackets, use bisection if (b - x)*(x - a) < 0.0: dx = 0.5*(b - a) x = a + dx # Check for convergence if abs(dx) < tol*max(abs(b),1.0): return x print 'Too many iterations in Newton-Raphson'
Evaluate Newton’s polynomial using Python
''' p = evalPoly(a,xData,x). Evaluates Newton's polynomial p at x. The coefficient vector 'a' can be computed by the function 'coeffts'. a = coeffts(xData,yData). Computes the coefficients of Newton's polynomial. ''' def evalPoly(a,xData,x): n = len(xData) - 1 # Degree of polynomial p = a[n] for k in range(1,n+1): p = a[n-k] + (x -xData[n-k])*p return p def coeffts(xData,yData): m = len(xData) # Number of data points a = yData.copy() for k in range(1,m): a[k:m] = (a[k:m] - a[k-1])/(xData[k:m] - xData[k-1]) return a
Evaluate the polynomial interpolant by Neville’s method in Python
''' p = neville(xData,yData,x). Evaluates the polynomial interpolant p(x) that passes trough the specified data points by Neville's method. ''' def neville(xData,yData,x): m = len(xData) # number of data points y = yData.copy() for k in range(1,m): y[0:m-k] = ((x - xData[k:m])*y[0:m-k] + \ (xData[0:m-k] - x)*y[1:m-k+1])/ \ (xData[0:m-k] - xData[k:m]) return y[0]
Modified midpoint method for solving the initial value problem in Python
''' yStop = integrate (F,x,y,xStop,tol=1.0e-6) Modified midpoint method for solving the initial value problem y' = F(x,y}. x,y = initial conditions xStop = terminal value of x yStop = y(xStop) F = user-supplied function that returns the array F(x,y) = {y'[0],y'[1],...,y'[n-1]}. ''' from numpy import zeros,float,sum from math import sqrt def integrate(F,x,y,xStop,tol): def midpoint(F,x,y,xStop,nSteps): # Midpoint formulas h = (xStop - x)/nSteps y0 = y y1 = y0 + h*F(x,y0) for i in range(nSteps-1): x = x + h y2 = y0 + 2.0*h*F(x,y1) y0 = y1 y1 = y2 return 0.5*(y1 + y0 + h*F(x,y2)) def richardson(r,k): # Richardson's extrapolation for j in range(k-1,0,-1): const = (k/(k - 1.0))**(2.0*(k-j)) r[j] = (const*r[j+1] - r[j])/(const - 1.0) return kMax = 51 n = len(y) r = zeros((kMax,n),dtype=float) # Start with two integration steps nSteps = 2 r[1] = midpoint(F,x,y,xStop,nSteps) r_old = r[1].copy() # Increase the number of integration points by 2 # and refine result by Richardson extrapolation for k in range(2,kMax): nSteps = 2*k r[k] = midpoint(F,x,y,xStop,nSteps) richardson(r,k) # Compute RMS change in solution e = sqrt(sum((r[1] - r_old)**2)/n) # Check for convergence if e < tol: return r[1] r_old = r[1].copy() print "Midpoint method did not converge"
LU decomposition of symetric pentadiagonal matrix in Python
''' d,e,f = LUdecomp5(d,e,f). LU decomposition of symetric pentadiagonal matrix [f\e\d\e\f]. On output {d},{e} and {f} are the diagonals of the decomposed matrix. x = LUsolve5(d,e,f,b). Solves [f\e\d\e\f]{x} = {b}, where {d}, {e} and {f} are the vectors returned from LUdecomp5. ''' def LUdecomp5(d,e,f): n = len(d) for k in range(n-2): lam = e[k]/d[k] d[k+1] = d[k+1] - lam*e[k] e[k+1] = e[k+1] - lam*f[k] e[k] = lam lam = f[k]/d[k] d[k+2] = d[k+2] - lam*f[k] f[k] = lam lam = e[n-2]/d[n-2] d[n-1] = d[n-1] - lam*e[n-2] e[n-2] = lam return d,e,f def LUsolve5(d,e,f,b): n = len(d) b[1] = b[1] - e[0]*b[0] for k in range(2,n): b[k] = b[k] - e[k-1]*b[k-1] - f[k-2]*b[k-2] b[n-1] = b[n-1]/d[n-1] b[n-2] = b[n-2]/d[n-2] - e[n-2]*b[n-1] for k in range(n-3,-1,-1): b[k] = b[k]/d[k] - e[k]*b[k+1] - f[k]*b[k+2] return b
LU decomposition of tridiagonal matrix in Python
''' c,d,e = LUdecomp3(c,d,e). LU decomposition of tridiagonal matrix [c\d\e]. On output {c},{d} and {e} are the diagonals of the decomposed matrix. x = LUsolve3(c,d,e,b). Solves [c\d\e]{x} = {b}, where {c}, {d} and {e} are the vectors returned from LUdecomp3. ''' def LUdecomp3(c,d,e): n = len(d) for k in range(1,n): lam = c[k-1]/d[k-1] d[k] = d[k] - lam*e[k-1] c[k-1] = lam return c,d,e def LUsolve3(c,d,e,b): n = len(d) for k in range(1,n): b[k] = b[k] - c[k-1]*b[k-1] b[n-1] = b[n-1]/d[n-1] for k in range(n-2,-1,-1): b[k] = (b[k] - e[k]*b[k+1])/d[k] return b
LU decomposition in Python
''' a = LUdecomp(a). LU decomposition: [L][U] = [a]. The returned matrix [a] = [L\U] contains [U] in the upper triangle and the nondiagonal terms of [L] in the lower triangle. x = LUsolve(a,b). Solves [L][U]{x} = b, where [a] = [L\U] is the matrix returned from LUdecomp. ''' from numpy import dot def LUdecomp(a): n = len(a) for k in range(0,n-1): for i in range(k+1,n): if abs(a[i,k]) > 1.0e-9: lam = a [i,k]/a[k,k] a[i,k+1:n] = a[i,k+1:n] - lam*a[k,k+1:n] a[i,k] = lam return a def LUsolve(a,b): n = len(a) for k in range(1,n): b[k] = b[k] - dot(a[k,0:k],b[0:k]) b[n-1] = b[n-1]/a[n-1,n-1] for k in range(n-2,-1,-1): b[k] = (b[k] - dot(a[k,k+1:n],b[k+1:n]))/a[k,k] return b
Find the zero of the linear function straight line interpolation in Python
''' root = linInterp(f,x1,x2). Finds the zero of the linear function f(x) by straight line interpolation based on x = x1 and x2. ''' def linInterp(f,x1,x2): f1 = f(x1) f2 = f(x2) return x2 - f2*(x2 - x1)/(f2 - f1)
N lowest eigenvalues of the tridiagonal matrix in python
''' r = lamRange(d,c,N). Returns the sequence {r[0],r[1],...,r[N]} that separates the N lowest eigenvalues of the tridiagonal matrix [A] = [c\d\c]; that is, r[i] < lam[i] < r[i+1]. ''' from numpy import ones from sturmSeq import * from gerschgorin import * def lamRange(d,c,N): lamMin,lamMax = gerschgorin(d,c) r = ones(N+1) r[0] = lamMin # Search for eigenvalues in descending order for k in range(N,0,-1): # First bisection of interval(lamMin,lamMax) lam = (lamMax + lamMin)/2.0 h = (lamMax - lamMin)/2.0 for i in range(1000): # Find number of eigenvalues less than lam p = sturmSeq(d,c,lam) numLam = numLambdas(p) # Bisect again & find the half containing lam h = h/2.0 if numLam < k: lam = lam + h elif numLam > k: lam = lam - h else: break # If eigenvalue located, change the upper limit # of search and record it in [r] lamMax = lam r[k] = lam return r
python code for solving eigenvalue problem by Jacobi’s method
''' lam,x = jacobi(a,tol = 1.0e-9). Solution of std. eigenvalue problem [a]{x} = lam{x} by Jacobi's method. Returns eigenvalues in vector {lam} and the eigenvectors as columns of matrix [x]. ''' from numpy import array,identity,diagonal from math import sqrt def jacobi(a,tol = 1.0e-9): # Jacobi method def maxElem(a): # Find largest off-diag. element a[k,l] n = len(a) aMax = 0.0 for i in range(n-1): for j in range(i+1,n): if abs(a[i,j]) >= aMax: aMax = abs(a[i,j]) k = i; l = j return aMax,k,l def rotate(a,p,k,l): # Rotate to make a[k,l] = 0 n = len(a) aDiff = a[l,l] - a[k,k] if abs(a[k,l]) < abs(aDiff)*1.0e-36: t = a[k,l]/aDiff else: phi = aDiff/(2.0*a[k,l]) t = 1.0/(abs(phi) + sqrt(phi**2 + 1.0)) if phi < 0.0: t = -t c = 1.0/sqrt(t**2 + 1.0); s = t*c tau = s/(1.0 + c) temp = a[k,l] a[k,l] = 0.0 a[k,k] = a[k,k] - t*temp a[l,l] = a[l,l] + t*temp for i in range(k): # Case of i < k temp = a[i,k] a[i,k] = temp - s*(a[i,l] + tau*temp) a[i,l] = a[i,l] + s*(temp - tau*a[i,l]) for i in range(k+1,l): # Case of k < i < l temp = a[k,i] a[k,i] = temp - s*(a[i,l] + tau*a[k,i]) a[i,l] = a[i,l] + s*(temp - tau*a[i,l]) for i in range(l+1,n): # Case of i > l temp = a[k,i] a[k,i] = temp - s*(a[l,i] + tau*temp) a[l,i] = a[l,i] + s*(temp - tau*a[l,i]) for i in range(n): # Update transformation matrix temp = p[i,k] p[i,k] = temp - s*(p[i,l] + tau*p[i,k]) p[i,l] = p[i,l] + s*(temp - tau*p[i,l]) n = len(a) maxRot = 5*(n**2) # Set limit on number of rotations p = identity(n)*1.0 # Initialize transformation matrix for i in range(maxRot): # Jacobi rotation loop aMax,k,l = maxElem(a) if aMax < tol: return diagonal(a),p rotate(a,p,k,l) print 'Jacobi method did not converge'
