BrentLineSearcher.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. //////////////////////////////////////////////////////////////////////
  2. //
  3. // BrentLineSearcher.cpp: Implementation of the Brent LineSearcher class.
  4. //
  5. // Written by Matthias Wacker
  6. //
  7. // Big parts of code are from numerical recipes in C
  8. //
  9. //////////////////////////////////////////////////////////////////////
  10. #include "optimization/BrentLineSearcher.h"
  11. #include <iostream>
  12. #define BrentSHFT(a,b,c,d) (a)=(b);(b)=(c);(c)=(d);
  13. #define BrentSIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
  14. BrentLineSearcher::BrentLineSearcher() : m_CGOLD(0.38196601125010515179541316563436), m_ZEPS(1.0e-10)
  15. {
  16. m_a = 0.0;
  17. m_b = 3.8196601125010515179541316563436;
  18. m_c = 10.0;
  19. m_eps = 0.1;
  20. }
  21. BrentLineSearcher::BrentLineSearcher(CostFunction *costFunc,OptLogBase* loger) : SuperClass(costFunc,loger),m_CGOLD(0.38196601125010515179541316563436), m_ZEPS(1.0e-10)
  22. {
  23. m_a = 0.0;
  24. m_b = 3.8196601125010515179541316563436;
  25. m_c = 10.0;
  26. m_eps = 0.1;
  27. }
  28. BrentLineSearcher::BrentLineSearcher(const BrentLineSearcher &lin) : SuperClass(lin),m_CGOLD(0.38196601125010515179541316563436), m_ZEPS(1.0e-10)
  29. {
  30. m_a = lin.m_a;
  31. m_b = lin.m_b;
  32. m_c = lin.m_c;
  33. m_eps = lin.m_eps;
  34. }
  35. BrentLineSearcher & BrentLineSearcher::operator =(const BrentLineSearcher &lin)
  36. {
  37. /*
  38. avoid self-copy
  39. */
  40. if(this != &lin)
  41. {
  42. /*
  43. =operator of SuperClass
  44. */
  45. SuperClass::operator=(lin);
  46. m_a = lin.m_a;
  47. m_b = lin.m_b;
  48. m_c = lin.m_c;
  49. m_eps = lin.m_eps;
  50. }
  51. return *this;
  52. }
  53. BrentLineSearcher::~BrentLineSearcher()
  54. {
  55. }
  56. bool BrentLineSearcher::setBounds(double a, double c)
  57. {
  58. if (a >= c)
  59. {
  60. return false;
  61. }
  62. m_a = a;
  63. m_b = a + m_CGOLD * (c - a);
  64. m_c = c;
  65. return true;
  66. }
  67. bool BrentLineSearcher::setEps(double eps)
  68. {
  69. if(eps < 0)
  70. {
  71. return false;
  72. }
  73. m_eps = eps;
  74. return true;
  75. }
  76. double BrentLineSearcher::optimize()
  77. {
  78. int numIter=0;
  79. double a=0.0;
  80. double b=0.0;
  81. double d=0.0;
  82. double etemp=0.0;
  83. double fu=0.0;
  84. double fv=0.0;
  85. double fw=0.0;
  86. double fx=0.0;
  87. double p=0.0;
  88. double q=0.0;
  89. double r=0.0;
  90. double tol1=0.0;
  91. double tol2=0.0;
  92. double u=0.0;
  93. double v=0.0;
  94. double w=0.0;
  95. double x=0.0;
  96. double xm=0.0;
  97. double e = 0.0;
  98. double xmin=0.0;
  99. int maxNumIter = 100;
  100. x=w=v= m_b;
  101. fw=fv=fx= evaluateSub(x);
  102. a = m_a;
  103. b = m_c;
  104. /*
  105. main loop
  106. */
  107. for (numIter = 1;numIter <= maxNumIter; numIter++)
  108. {
  109. xm = 0.5* (a+b);
  110. tol2 = 2.0 * (tol1=m_eps*fabs(x)+m_ZEPS);
  111. if(fabs(x-xm) <= (tol2-0.5*(b-a)))
  112. {
  113. xmin = x;
  114. return xmin;
  115. }
  116. /*
  117. construct trial parabolic fit
  118. */
  119. if(fabs(e) > tol1)
  120. {
  121. r=(x-w)*(fx-fv);
  122. q=(x-v)*(fx-fw); // FIXME WACKER CHECK IF NR IS WRONG HERE!?
  123. p=(x-v)*q-(x-w)*r;
  124. q=2.0*(q-r);
  125. if(q > 0.0) p = -p;
  126. q = fabs(q);
  127. etemp = e;
  128. e=d;
  129. if(fabs(p) >= fabs(0.5*q*etemp) || p <= q *(a-x) || p >= q*(b-x))
  130. {
  131. d=m_CGOLD * (e=(x >= xm ? a-x : b-x ));
  132. }
  133. else
  134. {
  135. d=p/q; // take the parabolic step
  136. u = x+d;
  137. if(u-a < tol2 || b-u < tol2)
  138. {
  139. d=BrentSIGN(tol1, xm - x);
  140. }
  141. }
  142. }
  143. else
  144. {
  145. d=m_CGOLD * (e=(x >= xm ? a-x : b-x ));
  146. }
  147. u = (fabs(d) >= tol1 ? x+d : x + BrentSIGN(tol1,d));
  148. /*
  149. this is the one function evaluation per step
  150. */
  151. fu= evaluateSub(u);
  152. if (fu <= fx)
  153. {
  154. if(u >= x )
  155. {
  156. a=x;
  157. }
  158. else
  159. {
  160. b=x;
  161. }
  162. BrentSHFT(v,w,x,u);
  163. BrentSHFT(fv,fw,fx,fu);
  164. }
  165. else
  166. {
  167. if (u < x)
  168. {
  169. a=u;
  170. }
  171. else
  172. {
  173. b=u;
  174. }
  175. if(fu <= fw || w == x)
  176. {
  177. v=w;
  178. w=u;
  179. fv=fw;
  180. fw=fu;
  181. }
  182. else if (fu <= fv || v== x || v == w)
  183. {
  184. v=u;
  185. fv=fu;
  186. }
  187. }
  188. if(m_verbose)
  189. {
  190. std::cout //<< "a,b,d,etemp,fu,fv,fw,fx,p,q,r,u,v,w,x,xm;" << std::endl
  191. << a << " "
  192. << b << " "
  193. << d << " "
  194. << etemp << " "
  195. << fu << " "
  196. << fv << " "
  197. << fw << " "
  198. << fx << " "
  199. << p << " "
  200. << q << " "
  201. << r << " "
  202. << u << " "
  203. << v << " "
  204. << w << " "
  205. << x << " "
  206. << xm << " "
  207. << std::endl;
  208. }
  209. } // main loop
  210. if(m_pLoger)
  211. m_pLoger->logWarning("Brent took too many iterations.. Tol threshold was to low for the number of iterations..\n");
  212. return x;
  213. }