line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Math::Function::Roots; |
2
|
6
|
|
|
6
|
|
150213
|
use base Exporter; |
|
6
|
|
|
|
|
15
|
|
|
6
|
|
|
|
|
604
|
|
3
|
6
|
|
|
6
|
|
34
|
use vars qw(@EXPORT_OK $E $Max_Iter $VERSION $Last_Iter); |
|
6
|
|
|
|
|
11
|
|
|
6
|
|
|
|
|
628
|
|
4
|
|
|
|
|
|
|
|
5
|
6
|
|
|
6
|
|
30
|
use warnings; |
|
6
|
|
|
|
|
13
|
|
|
6
|
|
|
|
|
194
|
|
6
|
6
|
|
|
6
|
|
41
|
use strict; |
|
6
|
|
|
|
|
16
|
|
|
6
|
|
|
|
|
166
|
|
7
|
6
|
|
|
6
|
|
30
|
use Carp; |
|
6
|
|
|
|
|
13
|
|
|
6
|
|
|
|
|
15760
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
=head1 NAME |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
Math::Function::Roots - Functions for finding roots of arbitrary functions |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=head1 VERSION |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
Version 0.065 |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=cut |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
$VERSION = '0.065'; |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=head1 SYNOPSIS |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
This is a collection of functions (in the perl sense) to find the root |
24
|
|
|
|
|
|
|
of arbitrary functions (in the mathmatical sense). The Functions take a |
25
|
|
|
|
|
|
|
sub reference and a range or guess of the answer and return the |
26
|
|
|
|
|
|
|
root of the function. |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
use Math::Function::Roots qw(bisection epsilon max_iter); |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
epsilon(0); # Set desired accuracy |
31
|
|
|
|
|
|
|
max_iter(50_000) # Put cap on runtime |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# Find the root of 2x+1 in the range (-5,5) |
34
|
|
|
|
|
|
|
my $result = bisection( sub {2*shift()+1}, -5, 5); |
35
|
|
|
|
|
|
|
# $result == -.5 |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
# Alternative method of setting epsilon and max_iter |
38
|
|
|
|
|
|
|
my $result2 = bisection( sub {2*shift()+1}, -5, 5, |
39
|
|
|
|
|
|
|
epsilon=>.00001, |
40
|
|
|
|
|
|
|
max_iter=>20); |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
=head1 DESCRIPTION |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
Numerical Analysis is the method of using algorithms, often |
45
|
|
|
|
|
|
|
iterative, to approximate the solution to a problem to which finding |
46
|
|
|
|
|
|
|
an exact solution would be difficult. Root Finding Algorithms are used |
47
|
|
|
|
|
|
|
to find the root of functions. They deal with continuous mathematical |
48
|
|
|
|
|
|
|
functions (one unique value of f(x) for every x). A root is anywhere |
49
|
|
|
|
|
|
|
the function evaluates to zero, i.e. where it crosses the |
50
|
|
|
|
|
|
|
x-axis. Different algortihms have different capacity for finding |
51
|
|
|
|
|
|
|
multiple roots, many can only find one root. |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
But enough of that, if you are here you probably know what a root |
54
|
|
|
|
|
|
|
finding algorithm is. I have begun implementing the following |
55
|
|
|
|
|
|
|
algorithms, which are described in detail below. The basic outline is |
56
|
|
|
|
|
|
|
algorithm( function, guess). Each function below is named after the |
57
|
|
|
|
|
|
|
underlying algorithm. |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=head1 PARAMETERS |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
All of the algorithms have similar parameters, so I will describe them |
62
|
|
|
|
|
|
|
once. Always mandatory is the function we are finding the root of. |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
=head2 I Parameter |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
Functions are passed as code references. These can take the form of |
67
|
|
|
|
|
|
|
"\&Function" or "sub{...}". Simple function can be inlined with sub{}, with more complicated functions taking the reference is recommended. |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
# f(x) = 2x - 4 |
70
|
|
|
|
|
|
|
# sub{ 2*shift() - 4 used as |
71
|
|
|
|
|
|
|
my $root = bisection( sub{ 2*shift() - 4 }, -10, 10 ); |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
Often you will have a function of multiple variables. This can be done with a wrapper function, such as: |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
sub foo{ |
76
|
|
|
|
|
|
|
my ($x1,$x2) = @_; |
77
|
|
|
|
|
|
|
return $x1**2 + $x2**2; |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
sub wrapper{ |
81
|
|
|
|
|
|
|
my $x2 = shift; |
82
|
|
|
|
|
|
|
return foo( 5, $x2 ); |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
my $result = bisection( \&wrapper, -10, 10 ); |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
Whatever subroutine is passed, it will be called with one argument, |
88
|
|
|
|
|
|
|
and is expected to return a single result. Functions not fitting that |
89
|
|
|
|
|
|
|
description will need a wrapper. |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
This will find the root of f(x) = 5**2 + x**2. Different algorithms |
92
|
|
|
|
|
|
|
react differently to certain functions. There is some advice below on |
93
|
|
|
|
|
|
|
good algorithms for certain types of functions. |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
=head2 I Parameters |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
Most algorithms require an initial range or guesses. If referred to as |
98
|
|
|
|
|
|
|
'guesses' then the solution (root) need not be in the range |
99
|
|
|
|
|
|
|
[guess1,guess2]. If a range or min and max are required, then to |
100
|
|
|
|
|
|
|
solution B lie within [min,max]. |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
=head2 I and I Parameters |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
Epsilon (I) is used to set the desired accuracy. Less accurate |
105
|
|
|
|
|
|
|
answers take fewer iterations and are therefore quicker to compute. In |
106
|
|
|
|
|
|
|
general I referres to the maximum distance from the given solution |
107
|
|
|
|
|
|
|
to the actual solution. If you need 6 decimals of accuracy, then I |
108
|
|
|
|
|
|
|
= .000_000_1 is appropriate, this is the default. Calculating a few |
109
|
|
|
|
|
|
|
decimals beyond what you need is generally recommended to prevent |
110
|
|
|
|
|
|
|
compounding rounding errors. I is a named parameter to set |
111
|
|
|
|
|
|
|
I for that particular run of the algorithm, it should always follow |
112
|
|
|
|
|
|
|
mandatory parameters: |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
my $result = bisection( sub{...}, -10, 10, epsilon => .01 ); |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
The I() function may be used to set I globally, be careful. |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
=cut |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
$E = 0.000_000_1; |
121
|
|
|
|
|
|
|
sub epsilon(;$){ |
122
|
17
|
100
|
|
17
|
1
|
77
|
if( @_ ){ |
123
|
9
|
|
|
|
|
21
|
$E = shift; |
124
|
9
|
100
|
|
|
|
33
|
$E = 0 if $E < 0; |
125
|
|
|
|
|
|
|
} |
126
|
17
|
|
|
|
|
63
|
return $E; |
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
=pod |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
Similar to epsilon, the maximum number of iterations an algorithm |
132
|
|
|
|
|
|
|
should run for may be set with the I named parameter, or |
133
|
|
|
|
|
|
|
globally with I(i). This maximum is normally used to catch |
134
|
|
|
|
|
|
|
errors, i.e. when a given function doesn't converge, or when there is |
135
|
|
|
|
|
|
|
a bug (nah...). Do not use this to control run-time, if you need an |
136
|
|
|
|
|
|
|
answer faster, use a larger epsilon. The only reason to change this |
137
|
|
|
|
|
|
|
would be if you had a slowly converging function, and you were willing |
138
|
|
|
|
|
|
|
to wait for a good answer, then you could raise the maximum to allow |
139
|
|
|
|
|
|
|
the algorithm to continue working. Default is 5,000. |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
=cut |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
$Max_Iter = 50_000; |
144
|
|
|
|
|
|
|
sub max_iter(;$){ |
145
|
11
|
100
|
|
11
|
1
|
34
|
if( @_ ){ |
146
|
7
|
|
|
|
|
12
|
$Max_Iter = shift; |
147
|
7
|
100
|
|
|
|
21
|
$Max_Iter = 1 if ($Max_Iter < 1); |
148
|
|
|
|
|
|
|
} |
149
|
11
|
|
|
|
|
27
|
return $Max_Iter; |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
=head1 PERFORMANCE CHECKING |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
=head2 last_iter( ) |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
This will return the number of iterations used to find the last |
157
|
|
|
|
|
|
|
result. This might help to give an indication on how an algorithm |
158
|
|
|
|
|
|
|
performs on your data. |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
=cut |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
sub last_iter{ |
163
|
7
|
|
|
7
|
1
|
50
|
return $Last_Iter; |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
=head1 ALGORITHMS |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
Below is a listing of availible algorithms. Many have restriction on the types of functions they work on, particularly the characteristics of the function near its root. Quick summary: |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
=over 4 |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
=item * bisection - Good for general purposes, you must provide a |
173
|
|
|
|
|
|
|
range in which one and only one root exists. Basically a binary search |
174
|
|
|
|
|
|
|
for the root. |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
=item * fixed_point - Only useful on a set of functions that can be |
177
|
|
|
|
|
|
|
converted to a fixed-point function with certain properties, see |
178
|
|
|
|
|
|
|
below. Fast when it can be used. |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
=item * secant - A fast converging algorithm which bases guesses on |
181
|
|
|
|
|
|
|
the slope of the function. Because slope is used, areas of the |
182
|
|
|
|
|
|
|
function where the slope is near horizontal (f'(x) == 0) should be |
183
|
|
|
|
|
|
|
avoided. |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
=back |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
=cut |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
@EXPORT_OK = qw(epsilon |
190
|
|
|
|
|
|
|
max_iter |
191
|
|
|
|
|
|
|
last_iter |
192
|
|
|
|
|
|
|
bisection |
193
|
|
|
|
|
|
|
fixed_point |
194
|
|
|
|
|
|
|
secant |
195
|
|
|
|
|
|
|
false_position |
196
|
|
|
|
|
|
|
find |
197
|
|
|
|
|
|
|
); |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
=head2 bisection( I ) |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
Uses the bisection algorithm. Average performance, but dependable. Min |
202
|
|
|
|
|
|
|
and max are used to specify a range which contains the root. To ensure |
203
|
|
|
|
|
|
|
this f(min) and f(max) must have opposite signs (meaning that there |
204
|
|
|
|
|
|
|
must be at least one root between them). Giving a range with multiple |
205
|
|
|
|
|
|
|
roots in it will not work in most cases. This method is dependable, |
206
|
|
|
|
|
|
|
because it does not care about the shape of the function. It is also a |
207
|
|
|
|
|
|
|
bit slower than som algorithms because it does not take hints from the |
208
|
|
|
|
|
|
|
shape. |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
=cut |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
sub bisection (&$$;%){ |
213
|
9
|
|
|
9
|
1
|
600
|
my $f = shift; |
214
|
9
|
|
|
|
|
17
|
my ($a,$b) = (shift, shift); |
215
|
9
|
|
|
|
|
24
|
my %optional = @_; |
216
|
9
|
|
66
|
|
|
38
|
my $E = $optional{epsilon} || $E; |
217
|
9
|
|
66
|
|
|
67
|
my $Max_Iter = $optional{max_iter} || $Max_Iter; |
218
|
|
|
|
|
|
|
|
219
|
9
|
|
|
|
|
31
|
my ($ay, $by ) = ( &$f($a), &$f($b) ); |
220
|
9
|
100
|
|
|
|
76
|
if( ($ay * $by) > 0 ){ |
221
|
|
|
|
|
|
|
# This algo doesn't work if a and b don't braket the root |
222
|
|
|
|
|
|
|
# f(a) must have and an opposite sign from f(b) |
223
|
|
|
|
|
|
|
# to ensure there is an odd number of roots |
224
|
1
|
|
|
|
|
190
|
croak "Bad range: f($a) and f($b) have the same sign"; |
225
|
|
|
|
|
|
|
} |
226
|
8
|
|
|
|
|
11
|
my $p = 0; |
227
|
8
|
|
|
|
|
24
|
for (1..$Max_Iter){ |
228
|
159
|
|
|
|
|
215
|
$Last_Iter = $_; |
229
|
|
|
|
|
|
|
|
230
|
159
|
|
|
|
|
224
|
$p = ($a+$b)/2.0; |
231
|
159
|
|
|
|
|
278
|
my $py = &$f($p); |
232
|
|
|
|
|
|
|
|
233
|
159
|
100
|
100
|
|
|
1065
|
if( $py == 0 || abs( $a - $b ) <= $E ){ |
|
|
100
|
|
|
|
|
|
234
|
|
|
|
|
|
|
#Uses relative change in p as stopping criteria |
235
|
|
|
|
|
|
|
#Alternative would be size of a..b range, i.e. abs(a-b) |
236
|
6
|
|
|
|
|
58
|
return $p; |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
elsif( $py * $ay < 0 ){ |
239
|
|
|
|
|
|
|
#If f at p and a have opposite sign |
240
|
|
|
|
|
|
|
#then there is a root between them |
241
|
|
|
|
|
|
|
#next iteration should be a..p |
242
|
92
|
|
|
|
|
118
|
$b = $p; |
243
|
92
|
|
|
|
|
145
|
$by = $py; |
244
|
|
|
|
|
|
|
} |
245
|
|
|
|
|
|
|
else{ |
246
|
|
|
|
|
|
|
# If $py != 0, $ay and $by have opposite signs, $py and $ay have same sign |
247
|
|
|
|
|
|
|
# then $py and $by must have opposite signs |
248
|
61
|
|
|
|
|
67
|
$a = $p; |
249
|
61
|
|
|
|
|
102
|
$ay = $py; |
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
|
253
|
2
|
|
|
|
|
344
|
carp "Maximum iterations: possible bad solution"; |
254
|
2
|
|
|
|
|
110
|
return $p; |
255
|
|
|
|
|
|
|
} |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
=head2 fixed_point( I ) |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
The Fixed-Point Iteration algorithm is a fast robust method which, |
260
|
|
|
|
|
|
|
unfortunately, works on a limited domain of problems, and requires |
261
|
|
|
|
|
|
|
some algebra. The benefits are that it can converge rapidly, and the |
262
|
|
|
|
|
|
|
range the root is in does not need to be known, any guess will |
263
|
|
|
|
|
|
|
converge, eventually. |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
A fixed-point is where g(x) = x. The method is to find a function, |
266
|
|
|
|
|
|
|
g(x), which has a fixed-point where f(x) has a root. This can be done |
267
|
|
|
|
|
|
|
trivially by using g(x) = x - f(x). In more general cases it is done |
268
|
|
|
|
|
|
|
by factoring an x so that g(x) = x = ff(x), where x = ff(x) is some |
269
|
|
|
|
|
|
|
identity derived from f(x). |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
As was mentioned there is a restriction on you choice of g(x), it is |
272
|
|
|
|
|
|
|
that the absolute value of the derivative of g(x) must be less than |
273
|
|
|
|
|
|
|
1. Or |g'(x)| < 1 (mathematical notation I handy sometimes). The |
274
|
|
|
|
|
|
|
closer g'(x) is to 0 the faster the rate of convergence. |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
Consider a range [a,b] which contains the fixed-point and within which |
277
|
|
|
|
|
|
|
|g'(x)| < 1 holds true. This might be an infinite range or a segment |
278
|
|
|
|
|
|
|
of the function. As long as your initial guess is within this range, |
279
|
|
|
|
|
|
|
the algorithm will converge. |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
I is an approximation of the answer. The algorithm will |
282
|
|
|
|
|
|
|
converge regardless of the relationship of I to the actual |
283
|
|
|
|
|
|
|
answer, just so long as I is within the range [a,b]. |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
Why go through all this hassle? Well, certain functions lend |
286
|
|
|
|
|
|
|
themselves to being transformed easily into fixed-point |
287
|
|
|
|
|
|
|
functions. Also, with a derivative near 0 the convergence is very |
288
|
|
|
|
|
|
|
fast, regardless of initial guess. |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
=cut |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
sub fixed_point(&$;%){ |
293
|
2
|
|
|
2
|
1
|
13
|
my $g = shift; |
294
|
2
|
|
|
|
|
3
|
my $guess = shift; |
295
|
2
|
|
|
|
|
5
|
my %optional = @_; |
296
|
2
|
|
33
|
|
|
12
|
my $E = $optional{epsilon} || $E; |
297
|
2
|
|
33
|
|
|
8
|
my $Max_Iter = $optional{max_iter} || $Max_Iter; |
298
|
|
|
|
|
|
|
|
299
|
2
|
|
|
|
|
4
|
my ($p,$last_p) = (0,$guess); |
300
|
2
|
|
|
|
|
6
|
for (1..$Max_Iter){ |
301
|
62
|
|
|
|
|
62
|
$Last_Iter = $_; |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
# Each iter we compute p = g(p') |
304
|
62
|
|
|
|
|
99
|
$p = &$g($last_p); |
305
|
62
|
100
|
|
|
|
302
|
if( abs( $p - $last_p ) <= $E ){ |
306
|
1
|
|
|
|
|
9
|
return $p; |
307
|
|
|
|
|
|
|
} |
308
|
61
|
|
|
|
|
82
|
$last_p = $p; |
309
|
|
|
|
|
|
|
} |
310
|
1
|
|
|
|
|
197
|
carp "Maximum iterations: divergence likely"; |
311
|
1
|
|
|
|
|
44
|
return undef; |
312
|
|
|
|
|
|
|
} |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
=head2 secant( I, guess1, guess2 >) |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
The secant method is a simplification of the Newton method, which uses |
317
|
|
|
|
|
|
|
the derivitive of the function to better predict the root of the |
318
|
|
|
|
|
|
|
function. The secant method uses a secant (line between two points on |
319
|
|
|
|
|
|
|
the function) as a substitute for knowing or calculating the |
320
|
|
|
|
|
|
|
derivative of the function. |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
As usual, provide the function, then provide two guesses. Unlike |
323
|
|
|
|
|
|
|
bisection, these do not need to bracket the solution. Local minimums |
324
|
|
|
|
|
|
|
or maximums, where the slope is near 0, are unfriendly to this |
325
|
|
|
|
|
|
|
algorithm. When the two guesses are near the solution however, this |
326
|
|
|
|
|
|
|
algorithm gives rapid convergence. |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
=cut |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
sub secant(&$$;%){ |
331
|
3
|
|
|
3
|
1
|
4
|
my $f = shift; |
332
|
3
|
|
|
|
|
6
|
my ($p0,$p1) = (shift,shift); |
333
|
|
|
|
|
|
|
|
334
|
3
|
|
|
|
|
5
|
my %optional = @_; |
335
|
3
|
|
33
|
|
|
13
|
my $E = $optional{epsilon} || $E; |
336
|
3
|
|
33
|
|
|
7
|
my $Max_Iter = $optional{max_iter} || $Max_Iter; |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
|
339
|
3
|
|
|
|
|
8
|
my ($q0,$q1,) = ( &$f($p0) , &$f($p1) ); |
340
|
3
|
|
|
|
|
26
|
my $p; |
341
|
3
|
|
|
|
|
7
|
for (1..$Max_Iter){ |
342
|
20
|
|
|
|
|
16
|
$Last_Iter = $_; |
343
|
|
|
|
|
|
|
|
344
|
20
|
|
|
|
|
27
|
$p = $p1 - ($q1 * ($p1 - $p0)) / ($q1 - $q0); |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
# Careful, the order of the assignments below and |
347
|
|
|
|
|
|
|
# following the test are important |
348
|
20
|
|
|
|
|
15
|
$p0 = $p1; |
349
|
20
|
|
|
|
|
18
|
$q0 = $q1; |
350
|
20
|
|
|
|
|
35
|
$q1 = &$f( $p ); |
351
|
|
|
|
|
|
|
|
352
|
20
|
100
|
100
|
|
|
157
|
if( $q1 eq 0 || abs( $p - $p1 ) <= $E ){ |
353
|
2
|
|
|
|
|
12
|
return $p; |
354
|
|
|
|
|
|
|
} |
355
|
|
|
|
|
|
|
|
356
|
18
|
|
|
|
|
29
|
$p1 = $p; |
357
|
|
|
|
|
|
|
} |
358
|
1
|
|
|
|
|
182
|
carp "Maximum iterations: divergence likely"; |
359
|
1
|
|
|
|
|
55
|
return undef; |
360
|
|
|
|
|
|
|
} |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
=head2 false_position( I ) |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
False Position is an algorithm similar to Secant, it uses secants |
365
|
|
|
|
|
|
|
of the function to pick better guesses. The difference is that this |
366
|
|
|
|
|
|
|
method incorporates the bracketing of the Bisection method, with the |
367
|
|
|
|
|
|
|
speed of the Secant method. |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
Bracketing is a desirable property because it makes the algorithm more |
370
|
|
|
|
|
|
|
dependable. Bracketing ensures that the algorithm will stay within the |
371
|
|
|
|
|
|
|
given range. This is useful with higer-order functions where you want |
372
|
|
|
|
|
|
|
to restrict your search to the area directly around the root. |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
The only restriction is that the functions derivative must not equal 0 |
375
|
|
|
|
|
|
|
within the range [min,max]. There must also only be one root within |
376
|
|
|
|
|
|
|
the range, which (as in Bisection) is ensured by requiring that f(min) |
377
|
|
|
|
|
|
|
and f(max) have opposite signs. |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
=cut |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
sub false_position(&$$;%){ |
382
|
7
|
|
|
7
|
1
|
21
|
my $f = shift; |
383
|
7
|
|
|
|
|
13
|
my ($a,$b) = (shift,shift); |
384
|
|
|
|
|
|
|
|
385
|
7
|
|
|
|
|
14
|
my %optional = @_; |
386
|
7
|
|
33
|
|
|
25
|
my $E = $optional{epsilon} || $E; |
387
|
7
|
|
33
|
|
|
23
|
my $Max_Iter = $optional{max_iter} || $Max_Iter; |
388
|
|
|
|
|
|
|
|
389
|
7
|
|
|
|
|
23
|
my ($ay, $by) = ( &$f($a), &$f($b) ); |
390
|
|
|
|
|
|
|
# This algorithm requires that f(a) and f(b) |
391
|
|
|
|
|
|
|
# always have opposite signs |
392
|
7
|
100
|
|
|
|
432
|
croak "Bad range: f($a) and f($b) have the same sign" |
393
|
|
|
|
|
|
|
if( $ay * $by > 0 ); |
394
|
|
|
|
|
|
|
|
395
|
6
|
|
|
|
|
13
|
my ($p,$last_py) = (0,0); |
396
|
6
|
|
|
|
|
46
|
for (1..$Max_Iter){ |
397
|
90
|
|
|
|
|
87
|
$Last_Iter = $_; |
398
|
|
|
|
|
|
|
|
399
|
90
|
|
|
|
|
635
|
$p = $b - $by*($b - $a)/($by - $ay); |
400
|
|
|
|
|
|
|
|
401
|
90
|
|
|
|
|
193
|
my $py = &$f($p); |
402
|
|
|
|
|
|
|
|
403
|
90
|
100
|
|
|
|
414
|
if( abs($py - $last_py) <= $E ){ |
|
|
100
|
|
|
|
|
|
404
|
5
|
|
|
|
|
31
|
return $p; |
405
|
|
|
|
|
|
|
} |
406
|
|
|
|
|
|
|
elsif( $py * $by < 0 ){ |
407
|
|
|
|
|
|
|
# If $py and $by have opposite signs |
408
|
|
|
|
|
|
|
# Then the root is within [p..b] |
409
|
82
|
|
|
|
|
77
|
$a = $p; |
410
|
82
|
|
|
|
|
109
|
$ay = $py; |
411
|
|
|
|
|
|
|
} |
412
|
|
|
|
|
|
|
else{ |
413
|
|
|
|
|
|
|
# root is in range [a..p] |
414
|
3
|
|
|
|
|
4
|
$b = $p; |
415
|
3
|
|
|
|
|
4
|
$by = $py; |
416
|
|
|
|
|
|
|
} |
417
|
85
|
|
|
|
|
117
|
$last_py = $py; |
418
|
|
|
|
|
|
|
} |
419
|
1
|
|
|
|
|
5047
|
carp "Maximum iterations: possible bad solution"; |
420
|
1
|
|
|
|
|
50
|
return $p; |
421
|
|
|
|
|
|
|
} |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
=head2 find() |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
This a hybrid function which uses a combination of algorithms to find |
426
|
|
|
|
|
|
|
the root of the given function. Both I and I are |
427
|
|
|
|
|
|
|
optional. If one is provided, it is used as an approximate starting |
428
|
|
|
|
|
|
|
point. If both are given, then they are taken as a range, the root |
429
|
|
|
|
|
|
|
B be within this range. |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
It will most likely return the root nearest your guess, but no |
432
|
|
|
|
|
|
|
guarantees. Don't provide a range with more than one root in it, you |
433
|
|
|
|
|
|
|
might find one, you might not. More information will give higher |
434
|
|
|
|
|
|
|
performance and more control over which root is being found, but if |
435
|
|
|
|
|
|
|
you don't know anything about the function, give it a try without a |
436
|
|
|
|
|
|
|
guess. Settings from epsilon and maximum iterations apply as normal. |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
=cut |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
sub find(&;$$%){ |
441
|
1
|
|
|
1
|
1
|
9
|
my $f = shift; |
442
|
1
|
|
|
|
|
2
|
my ($a,$b); |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
# This is totally wrong, need to not assign to $a and $b when no |
445
|
|
|
|
|
|
|
# arguments |
446
|
|
|
|
|
|
|
|
447
|
1
|
50
|
33
|
|
|
7
|
if( defined $_[0] && $_[0] =~ !/epsilon|max_iter/ ){ |
448
|
0
|
|
|
|
|
0
|
$a = shift; |
449
|
|
|
|
|
|
|
} |
450
|
1
|
50
|
33
|
|
|
4
|
if( defined $_[0] && $_[0] =~ !/epsilon|max_iter/ ){ |
451
|
0
|
|
|
|
|
0
|
$b = shift; |
452
|
|
|
|
|
|
|
} |
453
|
|
|
|
|
|
|
|
454
|
1
|
|
|
|
|
3
|
my %optional = @_; |
455
|
1
|
|
33
|
|
|
5
|
my $E = $optional{epsilon} || $E; |
456
|
1
|
|
33
|
|
|
4
|
my $Max_Iter = $optional{max_iter} || $Max_Iter; |
457
|
|
|
|
|
|
|
|
458
|
1
|
50
|
|
|
|
4
|
unless( defined $b ){ |
459
|
|
|
|
|
|
|
# If we don't have $b, we don't have a range, |
460
|
|
|
|
|
|
|
# but we might have a guess |
461
|
1
|
50
|
|
|
|
3
|
unless( defined $a ){ |
462
|
|
|
|
|
|
|
# If we have no guess we'll use 0 for initiation |
463
|
1
|
|
|
|
|
2
|
$a = 0; |
464
|
|
|
|
|
|
|
} |
465
|
|
|
|
|
|
|
# Start with a guess range +2 and -2 around guess |
466
|
1
|
|
|
|
|
2
|
$a -= 2; |
467
|
1
|
|
|
|
|
4
|
$b = $a + 4; |
468
|
1
|
|
|
|
|
1
|
my ($fa,$fb); |
469
|
1
|
|
|
|
|
2
|
do{ |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
# add max iteration catch to this loop |
472
|
|
|
|
|
|
|
# irr call to this function is causing both points to go negative |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
# Until $a and $b bracket the solution |
475
|
2
|
|
|
|
|
21
|
$fa = &$f($a); |
476
|
2
|
|
|
|
|
19
|
$fb = &$f($b); |
477
|
2
|
|
|
|
|
2000308
|
sleep 1; |
478
|
|
|
|
|
|
|
#use Data::Dumper::Simple; |
479
|
|
|
|
|
|
|
#warn Dumper($a,$fa,$b,$fb ); |
480
|
2
|
|
|
|
|
14
|
$a = $a*2; |
481
|
2
|
|
|
|
|
31
|
$b = $b*2; |
482
|
|
|
|
|
|
|
}until( $fa * $fb < 0 ); |
483
|
|
|
|
|
|
|
} |
484
|
|
|
|
|
|
|
# Now we have a possibly large range that must bracket the solution |
485
|
|
|
|
|
|
|
# It might also bracket an odd number of roots, |
486
|
|
|
|
|
|
|
# in this case, we don't know which one we might find, |
487
|
|
|
|
|
|
|
# and if the user cares, he should have given more info |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
|
490
|
1
|
|
|
|
|
8
|
my ($approx,$result); |
491
|
1
|
50
|
|
|
|
6
|
eval{ |
492
|
1
|
|
|
|
|
13
|
$approx = bisection( \&$f, $a, $b, epsilon => .1 ); |
493
|
|
|
|
|
|
|
} || die "find: Initial bisection approximation failed: ".$@; |
494
|
1
|
50
|
|
|
|
4
|
eval{ |
495
|
1
|
|
|
|
|
8
|
$result = false_position( \&$f, $approx - .1, $approx + .1 ); |
496
|
|
|
|
|
|
|
} || die "find: false_position refinement failed: ".$@; |
497
|
1
|
|
|
|
|
8
|
return $result; |
498
|
|
|
|
|
|
|
} |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
=head1 FUTURE IMPROVEMENTS |
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
The first priority witll be adding more algorithms. Then it might be |
504
|
|
|
|
|
|
|
interesting to implement a mechanism where several algorithms could be |
505
|
|
|
|
|
|
|
tried on love data to choose the best algorithm for the |
506
|
|
|
|
|
|
|
domain. Lastly, using Inline::C or XS to rewrite the algos in C would |
507
|
|
|
|
|
|
|
be desirable for performance. Ideally I would like it to work so that |
508
|
|
|
|
|
|
|
if a C compiler is availible, then the C version is compiled and used, |
509
|
|
|
|
|
|
|
otherwise the Perl version is used. I've seen examples of this, but |
510
|
|
|
|
|
|
|
don't know how it is done at the moment, so this is a ways off. |
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
Finish of test coverage. |
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
=head1 AUTHOR |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
Spencer Ogden, C<< >> |
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
=head1 BUGS |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
The find function is broken |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
Please report any bugs or feature requests to |
523
|
|
|
|
|
|
|
C, or through the web interface |
524
|
|
|
|
|
|
|
at L. I will be notified, and then you'll |
525
|
|
|
|
|
|
|
automatically be notified of progress on your bug as I make changes. |
526
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
528
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
Copyright 2005 Spencer Ogden, All Rights Reserved. |
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
532
|
|
|
|
|
|
|
under the same terms as Perl itself. |
533
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
=cut |
535
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
1; # End of Math::Bisection |