home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Education
/
collectionofeducationcarat1997.iso
/
SCIENCE
/
PRAXIS.ZIP
/
PRAXIS.I
< prev
next >
Wrap
Text File
|
1987-07-15
|
23KB
|
548 lines
(****************************************************************************)
(* p r o c e d u r e p r a x i s *)
(* *)
(* p r a x i s is for the minimization of a function in several *)
(* variables. the algorithm used is a modification of a conjugate *)
(* gradient method developed by powell. changes are due to brent, *)
(* who gives an algol w program. *)
(* users who are interested in more of the details should read *)
(* - powell, m. j. d., 1962. an efficient method for finding *)
(* the minimum of a function of several variables without *)
(* calculating derivatives, computer journal 7, 155-162. *)
(* - brent, r. p., 1973. algorithms for minimization without *)
(* derivatives. prentice hall, englewood cliffs. *)
(* if you have any further comments, questions, etc. please feel free *)
(* and contact me. *)
(* *)
(* karl gegenfurtner 02/17/86 *)
(* turbo - p version 1.0 *)
(****************************************************************************)
(* the use of praxis is fairly simple. there are only two parameters: *)
(* - x is of type vector and contains on input an initial guess *)
(* of the solution. on output x holds the final solution of the *)
(* system of equations. *)
(* - n is of type integer and gives the number of unknown parameters *)
(* the result of praxis is the least calculated value of the function f *)
(* f is one of the global parameters used by praxis: *)
(* - f(x,n) is declared forward and is the function to be minimized *)
(* all other globals are optional, i.e. you can change them or else *)
(* praxis will use some default values, which are adequate for most *)
(* problems under consideration. *)
(* - prin controls the printout from praxis *)
(* 0: no printout at all *)
(* 1: only initial and final values *)
(* 2: detailed map of the minimization process *)
(* 3: also prints eigenvalues and eigenvectors of the *)
(* direction matices in use (for insiders only). *)
(* - t is the tolerance for the precision of the solution *)
(* praxis returns if the criterion *)
(* 2 * ||x(k)-x(k-1)|| <= sqrt(macheps) * ||x(k)|| + t *)
(* is fulfilled more than ktm times, where *)
(* - ktm is another global parameter. it's default value is 1 and *)
(* a value of 4 leads to a very(!) cautious stopping criterion *)
(* - macheps is the relative machine precision and is *)
(* 1.0 e-15 using an 8087 and turbo-87 and *)
(* 1.0 e-06 without 8087. *)
(* - h is a steplength parameter and shoul be set to the expected *)
(* distance to the solution. an exceptional large or small value *)
(* of h leads to slower 3 on the first few iterations. *)
(* - scbd is a scaling parameter and should be set to about 10. *)
(* the default is 1 and with that value no scaling is done at all *)
(* it's only necessary when the parameters are scaled very different *)
(* - illc is a boolean variable and should be set to true if the *)
(* problem is known to be illconditioned. *)
(****************************************************************************)
function power(a,b: real):real;
begin power := exp(b*ln(a));
end; (* power *)
procedure minfit(n:integer;eps,tol:real;var ab:matrix;var q:vector);
label 1,
2,
3,
4;
var l, kt,
l2,
i, j, k: integer;
c, f, g,
h, s, x,
y, z: real;
e: vector;
begin (* householders reduction to bidiagonal form *)
x:= 0; g:= 0;
for i:= 1 to n do
begin e[i]:= g; s:= 0; l:= i+1;
for j:= i to n do
s:= s + sqr(ab[j,i]);
if s<tol then g:= 0 else
begin f:= ab[i,i];
if f<0
then g:= sqrt(s)
else g:= - sqrt(s);
h:= f*g-s; ab[i,i]:= f - g;
for j:= l to n do
begin f:= 0;
for k:= i to n do
f:= f + ab[k,i]*ab[k,j];
f:= f/h;
for k:= i to n do
ab[k,j]:= ab[k,j] + f*ab[k,i];
end; (* j *)
end; (* if *)
q[i]:= g; s:= 0;
if i<=n
then for j:= l to n do
s:= s + sqr(ab[i,j]);
if s<tol then g:= 0 else
begin f:= ab[i,i+1];
if f<0
then g:= sqrt(s)
else g:= - sqrt(s);
h:= f*g-s; ab[i,i+1]:= f-g;
for j:= l to n do e[j]:= ab[i,j]/h;
for j:= l to n do
begin s:= 0;
for k:= l to n do s:= s + ab[j,k]*ab[i,k];
for k:= l to n do ab[j,k]:= ab[j,k] + s*e[k];
end; (* j *)
end; (* if *)
y:= abs(q[i])+abs(e[i]);
if y > x then x:= y;
end; (* i *)
(* accumulation of right hand transformations *)
for i:= n downto 1 do
begin if g<>0.0 then
begin h:= ab[i,i+1]*g;
for j:= l to n do ab[j,i]:= ab[i,j]/h;
for j:= l to n do
begin s:= 0;
for k:= l to n do s:= s + ab[i,k]*ab[k,j];
for k:= l to n do ab[k,j]:= ab[k,j] + s*ab[k,i];
end; (* j *)
end; (* if *)
for j:= l to n do
begin ab[j,i]:= 0;
ab[i,j]:= 0;
end;
ab[i,i]:= 1; g:= e[i]; l:= i;
end; (* i *)
(* diagonalization to bidiagonal form *)
eps:= eps*x;
for k:= n downto 1 do
begin kt:= 0;
1: kt:= kt + 1;
if kt > 30 then
begin e[k]:= 0;
writeln('+++ qr failed');
end;
for l2:= k downto 1 do
begin l:= l2;
if abs(e[l])<=eps then goto 2;
if abs(q[l-1])<=eps then goto 4;
end; (* l2 *)
4: c:= 0; s:= 1;
for i:= l to k do
begin f:= s*e[i]; e[i]:= c*e[i];
if abs(f)<=eps then goto 2;
g:= q[i];
if abs(f) < abs(g)
then h:= abs(g)*sqrt(1+sqr(f/g))
else if f <> 0
then h:= abs(f)*sqrt(1+sqr(g/f))
else h:= 0;
q[i]:= h;
if h = 0 then
begin h: