The daily routine
I will present one simple algorithm per day. It will add up. In fact one can get by very nicely with
about one dozen simple numerical recipes.
Day 1. Eulerian extrapolation
To solve a first order differential equation
we
simply write it as
which extrapolates the value of y(x + dx) from that of y(x). The increment dx should be small,
and even then the algorithm is prone to accumulated errors.
To numerically solve
we
perform the Hamiltonian split, and get two first order equations
and
apply the first method to both
Day 2. Newton’s method
The technique is based on the equation
The
idea is that if x0 is nearly a solution to f(x) = 0, then x1 = x0 -
is even closer to solving the
equation. This can be used to compute roots of functions, or to compute functions themselves to
higher precision.
Example Let
and
the sequence
converges on
.
The technique works for complex functions as well as real. Bisection may be superior for
real-valued functions.
Warning Newton’s method can be unstable if x0 is not chosen wisely.
Day 3. Numerical integration (naive)
A function f(x) can be numerically integrated over a domain a ≤ x ≤ b by coding the Riemann
sum
and
by choosing N to be fairly large. This utterly fails for infinite or semi-infinite domains.
Gaussian quadrature works in those cases, and is more efficient in all but the simplest
cases.
Day 4. Naive sorting
Simple comparative sorting is slow, requiring
comparisons to sort n data, but it is sure-fire.
Heap sorting can be orders of magnitude faster, but it is more complex to encode. A
well-coded heap sort program is somewhat inscrutible, but naive transposition sorting is
straightforward.
To sort n values {x0,x1,x2,
,xn-1} into ascending order of size, we run a pair of nested loops
on the numbers stored in an array.
(for i=0;i<n-1;i++){
for(j=i;j<n;j++){
tmp=x[i];
if(x[j]<x[i]){
x[i]=x[j];
x[j]=tmp; /* we swap them */
}
}
}
|
Day 5. Numerical integration (stochastic)
Riemann sums are totally impractical for multi-dimensional integrals. For multiple integrals Monte
Carlo or discrepancy sequencing may be the only practical algorithm for definite integration.
Take the following steps to integrate a single-variable non-negative function f(x) over
[a, b].
A. Pick a number Y max > f(x) for all a ≤ x ≤ b.
B. Generate N pairs of random numbers (rx,ry) with a ≤ rx ≤ b and 0 ≤ ry ≤ Y max.
C. for each pair, if ry ≤ f(rx), count the pair as a “hit”.
D. Let the number of “hits” be called h. Thinking of the rectangle of area Y max ⋅ (b - a) as a
target, the area ∫
abf(x) dx as a “bull’s eye”, the ratio of the number of hits to the number of shots
taken should be the area ratio, or
Day 6. Special functions by recursion
Many special functions of mathematical physics possess three-term recursions, for example the
Legendre polynomial Pn(x) for -1 ≤ x ≤ 1 obeys
Rather than writing a routine that calls itself recursively, which is very costly, a program to
compute Pn(x) should return 1 if n = 0, x if n = 1, and if n > 1, the program should loop and
build up successively higher-n values recursively.
A warning, many three-term recursions are numerically unstable to round-off errors performed in
the machine. In this case one uses the Miller recursion to work down the chain to lower n values
rather than higher.
Example Bessel functions obey
which can be frightfully unstable. The Miller algorithm would work in the following way; to
compute J0(x), we begin high up, and pick
and
go downwards;
and
finally
This
result is not correct since in reality J5(x)
1. Now we make use of the growth of the recursion;
we can see that whatever x was, our value for J0(x) is very large compared to the value for J5(x) ,
and so it will clearly dominate in the well known sum
Each
of our values for the various intervening Bessel functions is therefore off by a constant
multiplicative factor
which we now divide by to restore our values to the correct values
For
x = 1 this results in
How
close is this? The correct value is J0(1) = 0.7651976866
Day 7. Division-free matrix inversion
Newton’s method works for matrices as well as simple numerical types. Let
then
and
if xn and X are matrices, the sequence {x0, x1, x2,
} converges very rapidly on X-1, and
the entire computation is free of divisions. The matrix x0 must be chosen very wisely.
Define
the
sum of all matrix elements squared, and choose
and
the sequence converges on X-1 if X is invertible, or x
0 itself if X is non-invertible, faster than any
other algorithm for medium to large matrices.
Day 8. Creating random doubles distributed with density f(x)
The accept-reject method of John Von Neumann is not the most efficient for every PDF, but it
always works. To generate a random number n with PDF f(x);
A. Choose a domain, a ≤ x ≤ b,
B. for the PDF such f(x), and find its largest value fmax on your domain.
C. Generate a uniformly distributed random number x on this domain. The code fragment below
illustrates how to make this into a random float between a and b.
#include <stdlib.h>
srand((unsigned long)getpid());
x=(b-a)*((double)rand()/(double)RAND_MAX)+a;
|
D. Pick a second uniformly distributed random number y on the interval 0 ≤ y ≤ fmax. If
y ≤ f(x), then accept this number as being randomly distributed according to f(x). If y > f(x),
reject it and pick a new pair (x,y). One look at the figure below tells you why this works; the
probability of acceptance of x is the same as the probability that y < f(x), which is
℘(y) =
.
Day 9. Least squares methods
Least squares methods are based on the use of minimax methods for expanding a sampled
function f(x) into a sum basis functions {gi(x)} that minimizes the standard deviation
S;
Example the nonlinear regression for the coefficients of the polynomial
that
best fits a set of data points
is
gotten by minimizing the deviation
with
respect to the coefficients a0,a1 and a2, resulting in the simultaneous linear equations
These can be solved for the coefficients ai by writing these equations as a matrix relation and
inverting the matrix.
Call Sx = ∑
i=1mx
i, Sx2 = ∑
i=1mx
i2, S
x3 = ∑
i=1mx
i3, S
y = ∑
i=1my
i, Sxy = ∑
i=1mx
i yi and
Sx2y = ∑
i=1mx
i2 y
i and so on. We can write the equations above as
We
can use our multiplicative inversion to solve numerically or
This
method can be used to compute “Fourier transforms”, not true Fourier transforms, but numerically
very good fits to sampled functions. The technique is also the basis of the Gaussian quadrature
method of integration.
Day 10. Runge-Kutta extrapolation
This is a technique for solving differential equations superior to Euler (or any other method for
that matter).
Simple Runge-Kutta is a three-step extrapolation that works this way.
The equation y′′(x) = f(x,y)
in
which
The equations y′(x) = f(x,y,z), z′(x) = g(x,y,z)
with
This
is the scheme that is most useful in classical mechanics; we let x = t, y(x) = r(t) be the position
versus time, and z(x) = p(t) be the momentum versus time.
This case is also quite easy to derive, and doing so illustrates the order of the error in the formula.
We begin with the power series
and
We
now just split off the second term and regroup
Notice that the terms inside of the square brackets are in fact the first few terms of the
multi-variable Taylor series expansion for the function f(x,y,z)
and
so we have
and
similarly
and
so if we call
and
we
have proven this Runge-Kutta formula. The others are done the same way, with more or less
algebra.
Day 11. Eigenvalues of a matrix
Gershgorin’s theorem tells us that the magnitude of the eigenvalues of a real, symmetric matrix are
less than the maximum value of the sum of absolute values of row elements. For example, given a
matrix A, let
then
if
we
have
This
number ρ is called the spectral radius of the matrix A.
Matrix eigenvalues can be extracted by the very crude but effective method of iteration using this
fact. We construct an arbitrary vector v0 and build up the sequence of vectors
which converges on the eigenvector of the largest eigenvalue, since if
is
the equation satisfied by the ith eigenvector, then we can expand
and
we see that
and
as k increases, this sum becomes dominated by the largest summand, corresponding to the largest
magnitude eigenvalue. If for example the ℓth component of v
k is nonzero,
A
variation on this can be used to find any eigenvalue, but it may be a great deal of work, and better
methods do exist. Notice that if the eigenvalues of A are λ1,λ2,
,λN, then the eigenvalues of
A - t ⋅ 1 are λ1 - t,λ2 - t,
,λN - t, and of (A - t ⋅ 1)-1 are
,
,
,
. If we choose t
accordingly, the recursion
will
converge on the eigenvector of (A-t⋅ 1)-1 of largest magnitude, giving the eigenvalue of A closest
to the number t. If A has close eigenvalues, this method fails.
The advantages of this algorithm is that it is easy to understand and to encode. We need only
a matrix multipliction routine, and one to rescale the matrix. Other more powerful
methods are bigger coding jobs and involve more complex linear algebra principles.