BrentLineSearcher.cpp 4.0 KB

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