MatrixIterativeOptimizer.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. //////////////////////////////////////////////////////////////////////
  2. //
  3. // MatrixIterativeOptimizer.cpp: Implementation of the MatrixIterativeOptimizer
  4. // Optimizer class.
  5. //
  6. // Written by Matthias Wacker
  7. //
  8. //////////////////////////////////////////////////////////////////////
  9. #include "optimization/MatrixIterativeOptimizer.h"
  10. #include <iostream>
  11. #include "optimization/AdditionalIceUtils.h" // for linsolve
  12. #include "core/optimization/blackbox/DownhillSimplexOptimizer.h" //FIXME WACKER: INCLUDE DOWNHILL SIMPLEX FOR THE GET RANK FUNCTION -> EXPORT IT
  13. using namespace OPTIMIZATION;
  14. MatrixIterativeOptimizer::MatrixIterativeOptimizer(OptLogBase *loger) : SuperClass(loger)
  15. {
  16. m_IterationMatrix = matrix_type(m_numberOfParameters,m_numberOfParameters);
  17. m_hk = matrix_type(m_numberOfParameters,1);
  18. m_stepSize = matrix_type(m_numberOfParameters,1);
  19. m_oldGradient = matrix_type(m_numberOfParameters,1);
  20. m_oldParams = matrix_type(m_numberOfParameters,1);
  21. m_lambdak = 1.0;
  22. }
  23. MatrixIterativeOptimizer::MatrixIterativeOptimizer( const MatrixIterativeOptimizer &opt) : SuperClass(opt)
  24. {
  25. m_IterationMatrix = opt.m_IterationMatrix;
  26. m_hk = opt.m_hk;
  27. m_lin = opt.m_lin;
  28. m_stepSize = opt.m_stepSize;
  29. m_lambdak = opt.m_lambdak;
  30. m_oldParams = opt.m_oldParams;
  31. m_oldGradient = opt.m_oldGradient;
  32. }
  33. MatrixIterativeOptimizer::~MatrixIterativeOptimizer()
  34. {
  35. }
  36. void MatrixIterativeOptimizer::init()
  37. {
  38. if(m_loger)
  39. m_loger->logTrace("entering MatrixIterativeOptimizer:: init ... \n");
  40. SuperClass::init();
  41. m_lin= ArmijoLineSearcher(m_costFunction,m_loger);
  42. //if(m_verbose==true) //FIXME commented out as output is not human readable
  43. // m_lin.setVerbose(true);
  44. if(m_maximize == true)
  45. {
  46. m_lin.setMaximize(true);
  47. }
  48. m_IterationMatrix=matrix_type(m_numberOfParameters,m_numberOfParameters);
  49. for(int i =0;i < static_cast<int>(m_numberOfParameters); i++)
  50. {
  51. m_IterationMatrix(i,i) = 1.0;
  52. }
  53. if(m_loger)
  54. m_loger->logTrace("leaving MatrixIterativeOptimizer:: init ...\n");
  55. }
  56. MatrixIterativeOptimizer & MatrixIterativeOptimizer::operator=(const MatrixIterativeOptimizer &opt)
  57. {
  58. /*
  59. avoid self-copy
  60. */
  61. if(this != &opt)
  62. {
  63. /*
  64. =operator of SuperClass
  65. */
  66. SuperClass::operator=(opt);
  67. /*
  68. own values:
  69. */
  70. m_IterationMatrix = opt.m_IterationMatrix;
  71. m_hk = opt.m_hk;
  72. m_lin = opt.m_lin;
  73. m_stepSize = opt.m_stepSize;
  74. m_lambdak = opt.m_lambdak;
  75. m_oldParams = opt.m_oldParams;
  76. m_oldGradient = opt.m_oldGradient;
  77. }
  78. return *this;
  79. }
  80. void MatrixIterativeOptimizer::computeDescentDirection()
  81. {
  82. if(m_loger)
  83. m_loger->logTrace("entering MatrixIterativeOptimizer::computeDescentDirection ... \n");
  84. if(m_numberOfParameters == 1)
  85. {
  86. if(fabs(m_IterationMatrix(0,0)) >= 1.0e-20 )
  87. {
  88. m_hk(0,0) = -m_gradient(0,0) / m_IterationMatrix(0,0);
  89. }
  90. else
  91. {
  92. m_hk = m_gradient;
  93. m_hk *= -1.0;
  94. }
  95. }
  96. else
  97. {
  98. //if(getRank(m_IterationMatrix, 1.0e-5 ) == m_numberOfParameters)
  99. if(true)
  100. {
  101. /*
  102. solve system equation for descent direction
  103. */
  104. matrix_type tmp=(m_gradient * -1.0 );
  105. linSolve(m_IterationMatrix, m_hk, tmp );
  106. /*
  107. direction orthogonal to gradient? -> use gradient
  108. */
  109. if(fabs((!m_hk * m_gradient)(0,0)) <= 1.0e-3)
  110. {
  111. m_hk = m_gradient;
  112. m_hk *= -1.0;
  113. }
  114. }
  115. else
  116. {
  117. m_hk = m_gradient;
  118. m_hk *= -1.0;
  119. }
  120. }
  121. if(m_loger)
  122. m_loger->logTrace("leaving MatrixIterativeOptimizer::computeDescentDirection ... \n");
  123. }
  124. void MatrixIterativeOptimizer::resetMatrix()
  125. {
  126. m_IterationMatrix=matrix_type(m_numberOfParameters,m_numberOfParameters);
  127. for(int i =0;i < static_cast<int>(m_numberOfParameters); i++)
  128. {
  129. m_IterationMatrix(i,i) = 1.0;
  130. }
  131. }
  132. void MatrixIterativeOptimizer::setStepSize(const matrix_type & stepSize)
  133. {
  134. m_stepSize = stepSize;
  135. }
  136. int MatrixIterativeOptimizer::optimize()
  137. {
  138. if(m_loger)
  139. m_loger->logTrace("entering MatrixIterativeOptimizer:optimize ... \n");
  140. init();
  141. bool abort = false;
  142. /******************************
  143. start time criteria
  144. ******************************/
  145. m_startTime = clock();
  146. /******************************
  147. compute start value
  148. and first gradient
  149. ******************************/
  150. m_currentCostFunctionValue = evaluateCostFunction(m_parameters);
  151. m_gradient = (m_analyticalGradients == true &&
  152. (m_costFunction->hasAnalyticGradient() == true) ) ?
  153. getAnalyticalGradient(m_parameters) :
  154. getNumericalGradient(m_parameters, m_stepSize);
  155. m_hk = m_gradient * -1.0;
  156. matrix_type hk_norm;
  157. double factor = m_hk.frobeniusNorm();
  158. if(fabs(factor) > 1.0e-12)
  159. {
  160. hk_norm = m_hk * (1.0/ factor);
  161. }
  162. matrix_type grad_norm;
  163. double factor2 = m_gradient.frobeniusNorm();
  164. if(fabs(factor2) > 1.0e-12)
  165. {
  166. grad_norm = m_gradient * (1.0/ factor2);
  167. }
  168. /*******************************
  169. optimize step length
  170. *******************************/
  171. /// ARMIJO
  172. //m_lin.setXkGkDk(m_parameters, m_gradient, hk_norm);
  173. m_lin.setXkGkDk(m_parameters, grad_norm, hk_norm);
  174. m_lambdak = m_lin.optimize();
  175. if(m_verbose == true)
  176. {
  177. std::cout << "stepsize lambda: " << m_lambdak << std::endl;
  178. std::cout << "in direction: " << std::endl;
  179. for(int r = 0; r < static_cast<int>(m_numberOfParameters); r++)
  180. {
  181. std::cout<< hk_norm(r,0) << " ";
  182. }
  183. std::cout << std::endl;
  184. }
  185. /*******************************
  186. update the parameters
  187. *******************************/
  188. m_oldParams = m_parameters;
  189. m_parameters = m_parameters + hk_norm * m_lambdak;
  190. /******************************
  191. check abort criteria
  192. for gradient
  193. ******************************/
  194. if(m_gradientTolActive)
  195. {
  196. if(m_gradient.frobeniusNorm() < m_gradientTol){
  197. m_returnReason = SUCCESS_GRADIENTTOL;
  198. abort = true;
  199. }
  200. }
  201. /* do the optimization loop */
  202. while(abort == false)
  203. {
  204. /******************************
  205. increase iteration
  206. counter
  207. ******************************/
  208. m_numIter++;
  209. /******************************
  210. cout actual iteration
  211. ******************************/
  212. if(m_verbose == true)
  213. {
  214. std::cout << "MatrixIterativeOptimizer :: Iteration: " << m_numIter << " : current parameters : ";
  215. for(int r = 0; r < static_cast<int>(m_numberOfParameters); r++)
  216. {
  217. std::cout<< m_parameters(r,0) << "\t ";
  218. }
  219. std::cout << " value: " << m_currentCostFunctionValue << std::endl;
  220. }
  221. /******************************
  222. Check iteration limit
  223. ******************************/
  224. if(m_maxNumIterActive)
  225. {
  226. if(m_numIter >= m_maxNumIter)
  227. {
  228. if(m_verbose == true)
  229. {
  230. std::cout << "Gradient Descenct :: aborting because of numIter" << std::endl;
  231. }
  232. /* set according return status and return */
  233. m_returnReason = SUCCESS_MAXITER;
  234. abort = true;
  235. continue;
  236. }
  237. }
  238. /******************************
  239. get the new Gradient
  240. ******************************/
  241. m_oldGradient = m_gradient;
  242. m_gradient = (m_analyticalGradients == true &&
  243. (m_costFunction->hasAnalyticGradient() == true) ) ?
  244. getAnalyticalGradient(m_parameters) :
  245. getNumericalGradient(m_parameters, m_stepSize);
  246. /******************************
  247. check gradient tol
  248. ******************************/
  249. if(m_gradientTolActive)
  250. {
  251. if(m_gradient.frobeniusNorm() < m_gradientTol)
  252. {
  253. if(m_verbose == true)
  254. {
  255. std::cout << "MatrixIterativeOptimizer :: aborting because of GradientTol" << std::endl;
  256. }
  257. m_returnReason = SUCCESS_GRADIENTTOL;
  258. abort = true;
  259. continue;
  260. }
  261. }
  262. /******************************
  263. Update the Iteration
  264. Matrix
  265. ******************************/
  266. //matrix_type oldMatrix = m_IterationMatrix;
  267. updateIterationMatrix();
  268. /******************************
  269. compute a descent
  270. direction
  271. ******************************/
  272. computeDescentDirection();
  273. // check if descent direction is really a descent direction
  274. // if not: reset the iteration matrix and take
  275. // the gradient as iteration direction
  276. if( (!m_hk *m_gradient)(0,0) > 0.0)
  277. {
  278. std::cout << " resetting matrix" << std::endl;
  279. resetMatrix();
  280. m_hk=m_gradient * -1.0;
  281. }
  282. double factor = m_hk.frobeniusNorm();
  283. if(fabs(factor) > 1.0e-12)
  284. {
  285. hk_norm = m_hk * (1.0/ factor);
  286. }
  287. matrix_type grad_norm;
  288. double factor2 = m_gradient.frobeniusNorm();
  289. if(fabs(factor2) > 1.0e-12)
  290. {
  291. grad_norm = m_gradient * (1.0/ factor2);
  292. }
  293. /*******************************
  294. optimize step length
  295. *******************************/
  296. //m_lin.setXkGkDk(m_parameters, m_gradient, hk_norm);
  297. m_lin.setXkGkDk(m_parameters, grad_norm, hk_norm);
  298. m_lambdak = m_lin.optimize();
  299. /*******************************
  300. update the parameters
  301. *******************************/
  302. m_oldParams = m_parameters;
  303. m_parameters = m_parameters + hk_norm * m_lambdak;
  304. if(m_verbose == true)
  305. {
  306. //matrix_type hk_normu=S2U(hk_norm);
  307. std::cout << "MatrixIterativeOptimizer :: Iterating with lambda = " << m_lambdak << std::endl;
  308. std::cout << "MatrixIterativeOptimizer :: in direction : ";
  309. for(int mu = 0; mu < static_cast<int>(m_numberOfParameters); mu++)
  310. {
  311. //std::cout<< hk_normu(mu,0) << "\t ";
  312. std::cout<< hk_norm(mu,0) << "\t ";
  313. }
  314. std::cout << std::endl;
  315. //matrix_type m_gradientu=S2U(m_gradient);
  316. std::cout << "MatrixIterativeOptimizer :: Gradient was ";
  317. for(int nu = 0; nu < static_cast<int>(m_numberOfParameters); nu++)
  318. {
  319. //std::cout<< m_gradientu(nu,0) << "\t ";
  320. std::cout<< m_gradient(nu,0) << "\t ";
  321. }
  322. std::cout << std::endl;
  323. }
  324. /*******************************
  325. Check new parameters
  326. are it is in bounds,
  327. paramTol,
  328. funcTol,
  329. maxSeconds
  330. *******************************/
  331. if(!checkParameters(m_parameters))
  332. {
  333. if(m_verbose == true)
  334. {
  335. std::cout << "Gradient Descenct :: aborting because of parameter Bounds" << std::endl;
  336. }
  337. /* set according return status and the last parameters and return */
  338. m_returnReason = ERROR_XOUTOFBOUNDS;
  339. m_parameters = m_oldParams;
  340. abort = true;
  341. continue;
  342. }
  343. /*
  344. Get new Costfunction Value
  345. */
  346. double oldFuncValue = m_currentCostFunctionValue;
  347. m_currentCostFunctionValue = evaluateCostFunction(m_parameters);
  348. /*
  349. Check ParamTol
  350. */
  351. if(m_paramTolActive)
  352. {
  353. if( (m_parameters - m_oldParams).frobeniusNorm() < m_paramTol)
  354. {
  355. if(m_verbose == true)
  356. {
  357. std::cout << "Gradient Descenct :: aborting because of param Tol" << std::endl;
  358. }
  359. /* set according return status and the last parameters and return */
  360. m_returnReason = SUCCESS_PARAMTOL;
  361. /*m_parameters = oldParams;*/
  362. abort = true;
  363. continue;
  364. }
  365. }
  366. if(m_funcTolActive)
  367. {
  368. if( abs((m_currentCostFunctionValue - oldFuncValue)) < m_funcTol)
  369. {
  370. if(m_verbose == true)
  371. {
  372. std::cout << "MatrixIterativeOptimizer :: aborting because of Func Tol" << std::endl;
  373. }
  374. /* set according return status and the last parameters and return */
  375. m_returnReason = SUCCESS_FUNCTOL;
  376. abort = true;
  377. continue;
  378. }
  379. }
  380. /*
  381. Check Optimization Timilimit, if active
  382. */
  383. if(m_maxSecondsActive)
  384. {
  385. m_currentTime = clock();
  386. /* time limit exceeded ? */
  387. if(((float)(m_currentTime - m_startTime )/CLOCKS_PER_SEC) >= m_maxSeconds )
  388. {
  389. if(m_verbose == true)
  390. {
  391. std::cout << "MatrixIterativeOptimizer :: aborting because of Time Limit" << std::endl;
  392. }
  393. /* set according return status and the last parameters and return */
  394. m_returnReason = SUCCESS_TIMELIMIT;
  395. m_parameters = m_oldParams;
  396. abort = true;
  397. continue;
  398. }
  399. }
  400. }
  401. if(m_verbose)
  402. {
  403. std::cout << "MatrixIterativeOptimizer :: RESULT: ";
  404. for(int r = 0; r < static_cast<int>(m_numberOfParameters); r++)
  405. {
  406. std::cout<< m_parameters(r,0) << " ";
  407. }
  408. std::cout << " value: " << m_currentCostFunctionValue << std::endl;
  409. }
  410. if(m_loger)
  411. m_loger->logTrace("leaving MatrixIterativeOptimizer:optimize ... \n");
  412. return m_returnReason;
  413. }