steepstd.red 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. module steepstd; % Optimization and root finding with method of
  2. % steepest descent.
  3. % Author: H. Melenk, ZIB, Berlin.
  4. % Copyright (c): ZIB Berlin 1991, all rights reserved.
  5. fluid '(!*noequiv accuracy!*);
  6. global '(iterations!* !*trnumeric);
  7. symbolic procedure rdmineval u;
  8. begin scalar e,vars,x,y,z,oldmode,p,!*noequiv;
  9. oldmode:=steepdecedmode(nil,nil);
  10. u := for each x in u collect reval x;
  11. u := accuracycontrol(u,6,40);
  12. e :=car u; u :=cdr u;
  13. if eqcar(car u,'list) then
  14. u := for each x in cdar u collect reval x;
  15. for each x in u do
  16. <<if eqcar(x,'equal) then
  17. <<z:=cadr x; y:=caddr x>> else <<z:=x; y:=random 100>>;
  18. vars:=z . vars; p := y . p>>;
  19. vars := reversip vars; p := reversip p;
  20. x := steepdeceval1(e,vars,p,'num_min);
  21. steepdecedmode(t,oldmode);
  22. return list('list, car x, 'list.
  23. for each p in pair(vars,cdr x) collect
  24. list('equal,car p,cdr p));
  25. end;
  26. put('num_min,'psopfn,'rdmineval);
  27. symbolic procedure rdsolvestdeval u;
  28. % solving a system of equations via minimizing the
  29. % sum of sqares.
  30. begin scalar e,vars,x,y,z,oldmode,p,q,!*noequiv;
  31. oldmode:=steepdecedmode(nil,nil);
  32. u := for each x in u collect reval x;
  33. e :=car u; u :=cdr u;
  34. % construct the function to minimize.
  35. e:=if eqcar(e,'list) then cdr e else list e;
  36. q := 'plus . for each f in e collect
  37. list('expt,if eqexpr f then !*eqn2a f else f,2);
  38. q := prepsq simp q;
  39. % starting point & variables.
  40. if eqcar(car u,'list) then
  41. u := for each x in cdar u collect reval x;
  42. for each x in u do
  43. <<if eqcar(x,'equal) then
  44. <<z:=cadr x; y:=caddr x>> else <<z:=x; y:=random 100>>;
  45. vars:=z . vars; p := y . p>>;
  46. vars := reversip vars; p := reversip p;
  47. x := steepdeceval1(q,vars,p,'root);
  48. steepdecedmode(t,oldmode);
  49. if null x then rederr "no solution found";
  50. return 'list.
  51. for each p in pair(vars,cdr x) collect
  52. list('equal,car p,cdr p);
  53. end;
  54. symbolic procedure steepdecedmode(m,oldmode);
  55. if not m then % initial call
  56. << if !*complex then rederr
  57. "steepest descent method not applicable under complex";
  58. if not (dmode!*='!:rd!:)then
  59. <<oldmode:=t; setdmode('rounded,t)>>;
  60. {oldmode,precision 0,!*roundbf}>>
  61. else % reset to old dmode.
  62. <<if car oldmode then setdmode('rounded,nil);
  63. precision cadr oldmode;
  64. !*roundbf:=caddr oldmode>>;
  65. symbolic procedure steepdeceval1(f,vars,x,mode);
  66. begin scalar e,g,r,acc;
  67. integer n;
  68. n := length vars;
  69. % establish the target function and the gradient.
  70. e := prepsq simp f;
  71. if !*trnumeric then lprim "computing symbolic gradient";
  72. g := for each v in vars collect prepsq simp list('df,f,v);
  73. !*noequiv:=t;
  74. if !*trnumeric then
  75. lprim "starting Fletcher Reeves steepest descent iteration";
  76. acc := !:!:quotient(1,expt(10,accuracy!*));
  77. x := for each u in x collect force!-to!-dm numr simp u;
  78. r:= steepdec2(e,g,vars,acc,x,mode);
  79. r:= for each x in r collect prepf x;
  80. return r;
  81. end;
  82. symbolic procedure steepdec2(f,grad,vars,acc,x,mode);
  83. % Algorithm for finding the minimum of function f
  84. % with technique of steepest descent, version Fletcher-Reeves.
  85. % f: function to minimize (standard quotient);
  86. % grad: symbolic gradient (list of standard quotients);
  87. % vars: variables (list of id's);
  88. % acc: target precision (e.g. 0.000001)
  89. % x: starting point (list of numerical standard forms).
  90. % mode: minimum / roots type of operation
  91. dm!:
  92. begin scalar e0,e00,e1,e2,a,a1,a1a1,a2,a2a2,x1,x2,g,h,dx,
  93. delta,limit,gold,gnorm,goldnorm,multi;
  94. integer count,k,n;
  95. n:=length grad; multi:=n>1; n:=10*n;
  96. e00 := e0 := evaluate(f,vars,x);
  97. a1 := 1;
  98. init:
  99. k:=0;
  100. % evaluate gradient (negative).
  101. g := for each v in grad collect -evaluate(v,vars,x);
  102. gnorm := normlist g; h:=g;
  103. loop:
  104. count := add1 count; k:=add1 k;
  105. if count>iterations!* then
  106. <<lprim "requested accuracy not reached within iteration limit";
  107. % mode := nil;
  108. goto ready>>;
  109. % quadratic interpolation in direction of h in order
  110. % to find the minimum value of f in that direction.
  111. a2 := nil;
  112. l1:
  113. x1 := list!+list(x, scal!*list(a1,h));
  114. e1 := evaluate(f,vars,x1);
  115. if e1>e0 then <<a2:=a1; x2:=x1; e2:=e1;
  116. a1 := a1/2; goto l1>>;
  117. if a2 then goto alph;
  118. l2:
  119. a2 := a1+a1;
  120. x2 := list!+list(x, scal!*list(a2,h));
  121. e2 := evaluate(f,vars,x2);
  122. if e2<e1 then <<a1:=a2; e1:=e2; goto l2>>;
  123. alph: %compute lowest point of parabel
  124. if abs(e1-e2)<acc then goto ready; % constant?
  125. a1a1:=a1*a1; a2a2:=a2*a2;
  126. a:= (a1a1-a2a2)*e0 + a2a2*e1 - a1a1*e2 ;
  127. a:= a/((a1-a2)*e0 + a2*e1-a1*e2);
  128. a:= a/2;
  129. % new point
  130. dx:=scal!*list(a,h); x:=list!+list(x, dx);
  131. e0 := evaluate(f,vars,x);
  132. if e0>e1 then % a1 was better than interpolation.
  133. <<dx:=scal!*list(a1-a ,h); x:=list!+list(x,dx);
  134. e0 := e1; dx:=scal!*list(a1,h)>>;
  135. delta:= normlist dx;
  136. steepdecprintpoint(count,x,delta,e0,gnorm);
  137. update!-precision list(delta,e0,gnorm);
  138. % compute next direction;
  139. if k>n then goto init; % reinitialize time to time.
  140. gold := g; goldnorm:= gnorm;
  141. g := for each v in grad collect -evaluate(v,vars,x);
  142. gnorm := normlist g;
  143. if gnorm<limit then goto ready;
  144. h := if not multi then g else
  145. list!+list(g,scal!*list(gnorm/goldnorm,h));
  146. if mode='num_min and gnorm > acc or
  147. mode='root and e0 > acc then goto loop;
  148. ready:
  149. if mode='root and not(abs e0 < acc) then
  150. <<lprim "probably fallen into local minimum of f^2";
  151. return nil>>;
  152. return e0 . x;
  153. end;
  154. symbolic procedure steepdecprintpoint(count,x,d,e0,ng);
  155. if !*trnumeric then
  156. begin integer n;
  157. writepri(count,'first);
  158. writepri(". residue=",nil);
  159. writepri(mkquote prepf e0,nil);
  160. writepri(", gradient length=",nil);
  161. writepri(mkquote prepf ng,'last);
  162. writepri(" at (",nil);
  163. for each y in x do
  164. <<if n>0 then writepri(" , ",nil);
  165. n:=n+1;
  166. writepri(mkquote prepf y,nil)>>;
  167. writepri(")",nil);
  168. writepri(", stepsize=",nil);
  169. writepri(mkquote prepf d,nil);
  170. writepri("",'last);
  171. end;
  172. endmodule;
  173. end;