-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathrootFindFunctions.py
More file actions
261 lines (214 loc) · 9.06 KB
/
rootFindFunctions.py
File metadata and controls
261 lines (214 loc) · 9.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
"""
Created on Thu May 30 21:01:03 2013
PHYS 510, Assignment 2 Functions
(Called by 'PHYS510 A2 Root Find.py' main program)
"""
# Root Finding
"""
The following functions are called for Assignment 2 in the root finding program.
1. Bisection method
2. Hybrid Bisection/Newton-Raphson method
3. Hybrid Bisection/Secant method
4. Hybrid Bisection/Muller-Brent method
"""
import math
import sympy
# 1
def rootBisection(g, f, xI, xF, Tol, nMax, Mthd):
# enter root finding algorithm by Bisection method
#***********************************************************************
# initialize variables
error = 1
n = 1
found = 'no'
xiMid = 0 # initial midpoint value to store the n-1 value
# loop until error is less than input tolerance
while error > Tol:
xMid = 0.5*(xI+xF)
# set up main Bisection method:
# make bracket interval smaller each iteration until root is found
# check conditions and update bracket points
if f(xI)*f(xMid) > 0:
xI = xMid
error = abs(xMid - xiMid) # calculate approx error
n = n + 1
xiMid = xMid # store the n-1 midpoint
elif f(xI)*f(xMid) < 0:
xF = xMid
error = abs(xMid - xiMid) # calculate approx error
n = n + 1
xiMid = xMid # store the n-1 midpoint
# break out of loop if root round
else:
found = 'yes'
break
# output results to user
if found == 'yes':
print 'Exact Root Found =', xMid
print 'Iterations = ', n
print '\n'
else:
print 'Approximate Root =', xMid
print 'Approximate Error =', error
print 'Iterations = ', n-1
print '\n'
# end rootBisection function
#***********************************************************************
# 2
def rootNewtonRaphson(g, f, xI, xF, Tol, nMax, Mthd):
# enter root finding algorithm by hybrid Bisection/Newton-Raphson method
#***********************************************************************
# initialize variables
error = 1
n = 1
found = 'no'
# get symbolic derivative of input function
x = sympy.Symbol('x') # define x as symbolic variable
sdf = sympy.diff(g, x) # get symbolic derivative of input function g
df = sympy.lambdify(x, sdf) # turn symbolic derivative into numeric function
# check condition for starting x value
if f(xI) < f(xF): xn0 = xI
else: xn0 = xF
# loop until error is less than input tolerance
while error > Tol:
# set up main Newton-Raphson method:
# use derivative of function as tangent line to get new x point
# calcuate new x value from f(x) and df(x)
xn1 = xn0 - (f(xn0)/df(xn0))
# if new x point is outside bracket interval then use midpoint instead
if xn1 < xI or xn1 > xF:
xn1 = 0.5*(xI+xF)
# check conditions and update bracket points
if f(xI)*f(xn1) > 0:
xI = xn1
elif f(xI)*f(xn1) < 0:
xF = xn1
error = abs(xn1 - xn0) # calculate approx error
n = n + 1
xn0 = xn1 # store the n-1 value for x
# break out of loop if input max iterations met
if n-1 >= nMax:
found = 'yes'
break
# output results to user
if found == 'yes':
print 'MAXIMUM ITERATIONS EXCEEDED'
print 'Approximate Root =', xn1
print 'Approximate Error =', error
print 'Iterations =', n-1
print '\n'
else:
print 'Approximate Root =', xn1
print 'Approximate Error =', error
print 'Iterations =', n-1
print '\n'
# end rootNewtonRaphson function
#***********************************************************************
# 3
def rootSecant(g, f, xI, xF, Tol, nMax, Mthd):
# enter root finding algorithm by hybrid Bisection/Secant method
#***********************************************************************
# initialize variables
error = 1
n = 1
found = 'no'
# initialize starting values
xn0 = xI
xn1 = xF
# loop until error is less than input tolerance
while error > Tol:
# set up main Secant method:
# use secant line as linear approx to function to get new x point
# calcuate new x value from secant line
xn2 = xn1 - ((f(xn1)*(xn1 - xn0)) / (f(xn1) - f(xn0)))
# if new x point is outside bracket then use midpoint instead
if xn2 < xI or xn2 > xF:
xn2 = 0.5*(xI+xF)
# check conditions and update bracket points
if f(xI)*f(xn2) > 0:
xI = xn2
elif f(xI)*f(xn2) < 0:
xF = xn2
error = abs(xn2 - xn1) # calculate approx error
n = n + 1
xn0 = xn1 # store the n-1 value for x
xn1 = xn2 # store the nth value for x
# break out of loop if input max iterations met
if n-1 >= nMax:
found = 'yes'
break
# output results to user
if found == 'yes':
print 'MAXIMUM ITERATIONS EXCEEDED'
print 'Approximate Root =', xn2
print 'Approximate Error =', error
print 'Iterations =', n-1
print '\n'
else:
print 'Approximate Root =', xn2
print 'Approximate Error =', error
print 'Iterations =', n-1
print '\n'
# end rootSecant function
#***********************************************************************
# 4
def rootMullerBrent(g, f, xI, xF, Tol, nMax, Mthd):
# enter root finding algorithm by hybrid Bisection/Muller-Brent method
#***********************************************************************
# initialize variables
error = 1
n = 1
found = 'no'
# initialize starting values
xn0 = xI
xn1 = xF
# use midpoint for 3rd point for use in quadratic approx to function
xn2 = 0.5*(xn0+xn1)
# loop until error is less than input tolerance
while error > Tol:
# set up main Muller-Brent method:
# use 3 points as quadratic approx to function to get new x point
# first calculate a, b, c from function values at 3 known points
c = f(xn2)
bNumer = (((xn0-xn2)**2)*(f(xn1)-f(xn2))) - (((xn1-xn2)**2)*(f(xn0)-f(xn2)))
aNumer = ((xn1-xn2)*(f(xn0)-f(xn2))) - ((xn0-xn2)*(f(xn1)-f(xn2)))
Denom = (xn0-xn1)*(xn0-xn2)*(xn1-xn2)
b = bNumer / Denom
a = aNumer / Denom
# then calculate new x value from quadratic eq
# check b and use alternate quadratic eq to avoid subtractive cancellations
if b >= 0:
xn3 = xn2 - (2*c) / (b + math.sqrt(b**2 - 4*a*c))
else:
xn3 = xn2 + (2*c) / (-b + math.sqrt(b**2 - 4*a*c))
# if new x point is outside bracket interval then use midpoint instead
if xn3 < xI or xn3 > xF:
xn3 = 0.5*(xI+xF)
# check conditions and update bracket points
if f(xI)*f(xn3) > 0:
xI = xn3
elif f(xI)*f(xn3) < 0:
xF = xn3
error = abs(xn3 - xn2) # calculate approx error
n = n + 1
xn0 = xn1 # store the n-1 value for x
xn1 = xn2 # store the nth value for x
xn2 = xn3 # store the n+1 value for x
# break out of loop if input max iterations met
if n-1 >= nMax:
found = 'yes'
break
# output results to user
if found == 'yes':
print 'MAXIMUM ITERATIONS EXCEEDED'
print 'Approximate Root =', xn3
print 'Approximate Error =', error
print 'Iterations =', n-1
print '\n'
else:
print 'Approximate Root =', xn3
print 'Approximate Error =', error
print 'Iterations =', n-1
print '\n'
# end rootMullerBrent function
#***********************************************************************