Lemma is an Electromagnetics API
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

logbarriercg_newton.h 75KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956
  1. /* This file is part of Lemma, a geophysical modelling and inversion API */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. /**
  6. @file
  7. @author Trevor Irons
  8. @date 10/11/2010
  9. @version $Id: logbarriercg.h 88 2013-09-06 17:24:44Z tirons $
  10. **/
  11. #ifndef LOGBARRIERCG_INC
  12. #define LOGBARRIERCG_INC
  13. #include <Eigen/IterativeLinearSolvers>
  14. #include <iostream>
  15. #include <iomanip>
  16. #include <fstream>
  17. #include <Eigen/Eigen>
  18. #include "cg.h"
  19. #include "bicgstab.h"
  20. #include "lemma.h"
  21. namespace Lemma {
  22. template < typename Scalar >
  23. Scalar PhiB (const Scalar& mux, const Scalar& muy, const Scalar& minVal,
  24. const Scalar& maxVal, const VectorXr x) {
  25. Scalar phib = std::abs((x.array() - minVal).log().sum()*mux);
  26. phib += std::abs((maxVal - x.array()).log().sum()*muy);
  27. return phib;
  28. }
  29. // PhiB for block log barrier
  30. template < typename Scalar >
  31. Scalar PhiB2 (const Scalar& mux, const Scalar& muy, const Scalar& minVal,
  32. const Scalar& maxVal, const VectorXr x, const int& block,
  33. const int &nblocks) {
  34. Scalar phib = std::abs((x.array() - minVal).log().sum()*mux);
  35. //phib += std::abs((maxVal - x.array()).log().sum()*muy);
  36. for (int ib=0; ib<nblocks; ++ib) {
  37. //HiSegments(ib) = x.segment(ib*block, block).sum();
  38. phib += Scalar(block)*std::log(maxVal - x.segment(ib*block, block).sum())*muy;
  39. }
  40. return phib;
  41. }
  42. template < typename Scalar >
  43. Scalar PhiB2 (const Scalar& minVal, const Scalar& maxVal, const VectorXr x,
  44. const int& block, const int &nblocks) {
  45. Scalar phib = std::abs((x.array() - minVal).log().sum());
  46. //phib += std::abs((maxVal - x.array()).log().sum()*muy);
  47. for (int ib=0; ib<nblocks; ++ib) {
  48. //HiSegments(ib) = x.segment(ib*block, block).sum();
  49. phib += Scalar(block)*std::log(maxVal - x.segment(ib*block, block).sum());
  50. }
  51. return phib;
  52. }
  53. template < typename Scalar >
  54. Scalar PhiB2_NN (const Scalar& mux, const Scalar& minVal, const VectorXr x) {
  55. Scalar phib = std::abs((x.array() - minVal).log().sum()*mux);
  56. return phib;
  57. }
  58. /** Impliments a logarithmic barrier CG solution of a Real linear system of
  59. * the form \f[ \mathbf{A} \mathbf{x} = \mathbf{b} \f] s.t. \f$ x \in
  60. * (minVal, maxVal) \f$. Note that this method optimized the complete
  61. * solution, using the large matrix ATA. If you have a system with a huge
  62. * number of columns, see the implicit version of this routine. Solution of
  63. * the dual problem (interior-point) follows "Tikhonov Regularization with
  64. * Nonnegativity constraint, (Calavetti et. al. 2004)"
  65. * @param[in] A is a Real Matrix.
  66. * @param[in] b is a Real vector
  67. * @param[in] x0 is a reference model.
  68. * @param[in] Wd is a Sparse Real matrix, that specifies data objective
  69. * function.
  70. * @param[in] Wm is a Sparse Real matrix, that sepcifies the model
  71. * objective function.
  72. * @param[in] minVal is the minimum allowed value \f$ x \in (minVal, maxVal) \f$
  73. * @param[in] maxVal is the minimum allowed value \f$ x \in (minVal, maxVal) \f$
  74. */
  75. template < typename Scalar >
  76. VectorXr LogBarrierCG(const MatrixXr &A, const VectorXr &b,
  77. const VectorXr &x0,
  78. const Eigen::SparseMatrix<Scalar>& WdTWd,
  79. const Eigen::SparseMatrix<Scalar>& WmTWm,
  80. const Scalar &minVal,
  81. const Scalar &maxVal) {
  82. // Check that everything is aligned OK
  83. if (A.rows() != b.size() ) {
  84. std::cerr << "Matrix A is not aligned with Vector b" << "\n";
  85. exit(1);
  86. }
  87. /////////////////////////////////////////////
  88. // Build all the large static matrices
  89. // NOTE, ATA can be large. For some problems an implicit algorithm may
  90. // be better suited.
  91. //Eigen::SparseMatrix<Scalar> WmTWm = Wm.transpose()*Wm;
  92. //Eigen::SparseMatrix<Scalar> WdTWd = Wd.transpose()*Wd;
  93. MatrixXr ATWdTWdA = A.transpose()*WdTWd*A;
  94. /////////////////////////
  95. // Jacobi Preconditioner
  96. Eigen::SparseMatrix<Scalar> MM (ATWdTWdA.rows(), ATWdTWdA.cols());
  97. for (int i=0; i<ATWdTWdA.rows(); ++i) {
  98. MM.insert(i,i) = 1. / ATWdTWdA(i,i);
  99. }
  100. MM.finalize();
  101. int N = A.cols(); // number of model
  102. int M = A.rows(); // number of data
  103. int MAXITER = 100; // M*N;
  104. Scalar SIGMA = 1e-2; // 1e-1;
  105. // Determine starting lambda_0, find lim_sup of the norm of impulse
  106. // responses and scale.
  107. /// @todo the starting lambda is not always a very good number.
  108. Scalar limsup = 1e10;
  109. for (int i=0; i<N; ++i) {
  110. VectorXr Spike = VectorXr::Zero(N);
  111. Spike(i) = (minVal + maxVal) / 2.;
  112. limsup = std::min(limsup, (ATWdTWdA*Spike).array().abs().maxCoeff());
  113. }
  114. Scalar lambda = limsup;
  115. Scalar mux0 = 1e-1*lambda;
  116. Scalar muy0 = 1e-1*lambda;
  117. Scalar epsilon = 1e-20; // Ratio between phib and phim+phid
  118. // initial guess, start with reference model
  119. VectorXr x=x0;
  120. // predicted b
  121. VectorXr b_pre = A*x;
  122. Scalar phid = (b - (b_pre)).norm();
  123. Scalar phim = x.norm();
  124. Scalar phib = PhiB(mux0, muy0, minVal, maxVal, x);
  125. Scalar mux = mux0;
  126. Scalar muy = muy0;
  127. Scalar tol = 1e-5*phid; // 1e-14;
  128. std::fstream phireport("phimphid.dat", std::ios::out);
  129. /// @todo add stopping criteria.
  130. //int iLambda = MAXITER - 1;
  131. for (int ii=0; ii<MAXITER; ++ii) {
  132. //lambda = Lambdas[iLambda];
  133. //iLambda -= 1;
  134. // Phi_m is just L2Norm right now. Maybe add s, alpha_T2, and
  135. // alpha_z terms
  136. VectorXr Xm1 = x;
  137. int iter = N*M;
  138. mux = mux0;
  139. muy = muy0;
  140. int iloop(0);
  141. do {
  142. ///////////////////////////////////////////////////////////
  143. // Log barrier terms
  144. VectorXr X1 = VectorXr::Ones(N).array() / (x.array()-minVal) ;
  145. VectorXr Y1 = VectorXr::Ones(N).array() / (maxVal-x.array()) ;
  146. VectorXr X2 = VectorXr::Ones(N).array() / ((x.array()-minVal)*(x.array()-minVal));
  147. VectorXr Y2 = VectorXr::Ones(N).array() / ((maxVal-x.array())*(maxVal-x.array()));
  148. /////////////////////////////////////////////////////////////
  149. // Solve system
  150. tol = 1e-5*phid;// 1e-14;
  151. iter = N*M;
  152. //////////////////////////
  153. // CG solution of complete system
  154. VectorXr b2 = (-A.transpose()*WdTWd*(b_pre-b)).array() -
  155. (lambda*WmTWm*(x0-x0)).array() +
  156. 2.*mux*X1.array() + 2.*muy*Y1.array();
  157. // Eigen requires these temporaries :(
  158. MatrixXr A2 = ATWdTWdA;
  159. A2 += lambda*WmTWm;
  160. A2.diagonal() += mux*X2 + muy*Y2;
  161. VectorXr ztilde = CG(A2, VectorXr::Zero(N), b2, MM, iter, tol);
  162. // update x
  163. VectorXr h = ztilde; // - x;
  164. Scalar d = std::min(1., 0.995*(x.array()/h.array().abs()).minCoeff() );
  165. x += d*h;
  166. // Determine mu steps to take
  167. VectorXr s1 = mux * (X2.asDiagonal()*ztilde - 2.*X1);
  168. VectorXr s2 = muy * (Y2.asDiagonal()*ztilde - 2.*Y1);
  169. // determine mu for next step
  170. mux = SIGMA/((Scalar)(N)) * std::abs( s1.dot(x) ) ;
  171. muy = SIGMA/((Scalar)(N)) * std::abs( s2.dot(x) ) ;
  172. b_pre = A*x;
  173. phid = (WdTWd*(b-b_pre)).norm() ; //(b - (b_pre)).norm();
  174. phim = (WmTWm*(x-x0)).norm();
  175. phib = PhiB(mux, muy, minVal, maxVal, x);
  176. ++iloop;
  177. } while (std::abs(phib / (phid+lambda*phim)) > epsilon);
  178. // report
  179. phireport.precision(12);
  180. std::cout << ii << "\t" << x.norm() << "\t" << (b-(A*x)).norm()
  181. << "\t" << lambda << "\t" << mux << "\t" << muy << "\t"
  182. << iter << "\t" << iloop << std::endl;
  183. phireport << ii << "\t" << x.norm() << "\t" << (b-(A*x)).norm()
  184. << "\t" << lambda << "\t" << mux << "\t" << muy << "\t"
  185. << iter << "\t" << iloop << std::endl;
  186. std::fstream modfile;
  187. std::string fname = "iteration" + to_string(ii) + ".dat";
  188. modfile.open( fname.c_str(), std::ios::out);
  189. modfile << ii << "\t" << x.norm() << "\t" << (b-(A*x)).norm()
  190. << "\t" << lambda << "\t" << mux << "\t" << muy << "\t" << iter << "\n";
  191. modfile << x << "\n";
  192. modfile.close();
  193. // update lambda
  194. /// @todo smarter lambda change
  195. lambda *= .9;
  196. }
  197. phireport.close();
  198. // TODO, determine optimal solution
  199. return x;
  200. }
  201. /** Impliments a logarithmic barrier CG solution of a Real linear system of
  202. * the form \f[ \mathbf{A} \mathbf{x} = \mathbf{b} \f] s.t. \f$ x \in
  203. * (minVal, maxVal) \f$. Note that this method optimized the complete
  204. * solution, using the large matrix ATA. If you have a system with a huge
  205. * number of columns, see the implicit version of this routine. Solution of
  206. * the dual problem (interior-point) follows "Tikhonov Regularization with
  207. * Nonnegativity constraint, (Calavetti et. al. 2004)"
  208. * @param[in] A is a Real Matrix.
  209. * @param[in] b is a Real vector
  210. * @param[in] minVal is the minimum allowed value \f$ x \in (minVal, maxVal) \f$
  211. * @param[in] maxVal is the minimum allowed value \f$ x \in (minVal, maxVal) \f$
  212. */
  213. template < typename Scalar >
  214. VectorXr LogBarrierCG(const MatrixXr &A, const VectorXr &b, const Scalar &minVal,
  215. const Scalar &maxVal) {
  216. // Check that everything is aligned OK
  217. if (A.rows() != b.size() ) {
  218. std::cerr << "Matrix A is not aligned with Vector b" << "\n";
  219. exit(1);
  220. }
  221. // TODO make ATA implicit
  222. MatrixXr ATA = A.transpose()*A;
  223. int N = A.cols(); // number of model
  224. int M = A.rows(); // number of data
  225. int MAXITER = 100; // M*N;
  226. Scalar SIGMA = 1e-2; //1e-1;
  227. Scalar delta = 1e-4;
  228. // Cholesky preconditioner
  229. //Eigen::FullPivLU <MatrixXr> Pre;
  230. //Eigen::ColPivHouseholderQR <MatrixXr> Pre;
  231. //Pre.compute(ATA);
  232. // Determine starting lambda_0, find lim_sup of the norm of impulse responses and scale
  233. Scalar limsup = 1e10;
  234. for (int i=0; i<N; ++i) {
  235. VectorXr Spike = VectorXr::Zero(N);
  236. Spike(i) = (minVal + maxVal) / 2.;
  237. limsup = std::min(limsup, (ATA*Spike).array().abs().maxCoeff());
  238. }
  239. Scalar lambda = 1e3*limsup;//e-1;//limsup;
  240. Scalar mux0 = 1e-1*lambda;
  241. Scalar muy0 = 1e-1*lambda;
  242. Scalar epsilon = 1e-20; // Ratio between phib and phim+phid
  243. /////////////////////////////
  244. // logX spacing
  245. //Scalar MinLam = 1e-24;
  246. //Scalar MaxLam = 1e-4;
  247. //VectorXr Lambdas;
  248. //Scalar LS = 5000;
  249. //Scalar dl10 = std::log(LS*MaxLam+1.)/(Scalar)MAXITER;
  250. //Lambdas = 1./LS*(dl10*VectorXr::LinSpaced(MAXITER+1, 0, MAXITER)).array().exp()
  251. // + MinLam - 1./LS;
  252. // initial guess, just near zero for now
  253. VectorXr x = VectorXr::Zero(N).array() + minVal+delta;// ((minVal + maxVal) / 2.);
  254. // predicted b
  255. VectorXr b_pre = A*x;
  256. Scalar phid = (b - (b_pre)).norm();
  257. Scalar phim = x.norm();
  258. Scalar phib = PhiB(mux0, muy0, minVal, maxVal, x);
  259. Scalar mux = mux0;
  260. Scalar muy = muy0;
  261. Scalar tol = 1e-5*phid; // 1e-14;
  262. std::fstream phireport("phimphid.dat", std::ios::out);
  263. /// @todo add stopping criteria.
  264. //int iLambda = MAXITER - 1;
  265. for (int ii=0; ii<MAXITER; ++ii) {
  266. //lambda = Lambdas[iLambda];
  267. //iLambda -= 1;
  268. // Phi_m is just L2Norm right now. Maybe add s, alpha_T2, and
  269. // alpha_z terms
  270. VectorXr WmT_Wm = VectorXr::Ones(N).array()*lambda;
  271. VectorXr Xm1 = x;
  272. int iter = N*M;
  273. mux = mux0;
  274. muy = muy0;
  275. int iloop(0);
  276. do {
  277. VectorXr X1(x.size());
  278. VectorXr Y1(x.size());
  279. VectorXr X2(x.size());
  280. VectorXr Y2(x.size());
  281. VectorXr b2;
  282. //VectorXr HiSegments = VectorXr::Zero(nblocks);
  283. MatrixXr A2;
  284. ///////////////////////////////////
  285. // setup
  286. #ifdef LEMMAUSEOMP
  287. #pragma omp parallel sections
  288. {
  289. #endif
  290. ///////////////////////////////////////////////////////////
  291. // Log barrier terms
  292. #ifdef LEMMAUSEOMP
  293. #pragma omp section
  294. #endif
  295. {
  296. X1 = VectorXr::Ones(N).array() / (x.array()-minVal) ;
  297. }
  298. #ifdef LEMMAUSEOMP
  299. #pragma omp section
  300. #endif
  301. {
  302. Y1 = VectorXr::Ones(N).array() / (maxVal-x.array()) ;
  303. }
  304. #ifdef LEMMAUSEOMP
  305. #pragma omp section
  306. #endif
  307. {
  308. X2 = VectorXr::Ones(N).array() / ((x.array()-minVal)*(x.array()-minVal));
  309. }
  310. #ifdef LEMMAUSEOMP
  311. #pragma omp section
  312. #endif
  313. {
  314. Y2 = VectorXr::Ones(N).array() / ((maxVal-x.array())*(maxVal-x.array()));
  315. }
  316. #ifdef LEMMAUSEOMP
  317. } // parallel sections
  318. #endif
  319. #ifdef LEMMAUSEOMP
  320. #pragma omp parallel sections
  321. {
  322. #endif
  323. #ifdef LEMMAUSEOMP
  324. #pragma omp section
  325. #endif
  326. {
  327. b2 = -(A.transpose()*(b_pre-b)).array() -
  328. (WmT_Wm.array()*x.array()).array() +
  329. (2.*mux)*X1.array() + (2.*muy)*Y1.array();
  330. }
  331. #ifdef LEMMAUSEOMP
  332. #pragma omp section
  333. #endif
  334. {
  335. A2 = ATA;
  336. A2.diagonal().array() += WmT_Wm.array() + mux*X2.array() +
  337. muy*Y2.array();
  338. }
  339. #ifdef LEMMAUSEOMP
  340. } // parallel sections
  341. #endif
  342. // // Jacobi Preconditioner
  343. // Eigen::SparseMatrix<Scalar> MM =
  344. // Eigen::SparseMatrix<Scalar>(A2.rows(), A2.cols());
  345. // for (int i=0; i<ATA.rows(); ++i) {
  346. // MM.insert(i,i) = 1./ATA(i,i);
  347. // }
  348. // MM.finalize();
  349. /////////////////////////////////////////////////////////////
  350. // Solve system,
  351. // CG solution of complete system
  352. // TODO add reference model
  353. tol = 1e-5*phid+mux+muy;// 1e-14;
  354. iter = N*M;
  355. //std::cout << "Call cg" << std::endl;
  356. // Decomposition preconditioner
  357. //Pre.setThreshold(1e1*tol);
  358. //Pre.compute(A2);
  359. // Jacobi Preconditioner
  360. //VectorXr ztilde = CG(A2, VectorXr::Zero(N), b2, MM, iter, tol);
  361. // Decomposition preconditioner
  362. //VectorXr ztilde = CG(A2, VectorXr::Zero(N), b2, Pre, iter, tol);
  363. // No preconditioner
  364. VectorXr ztilde = CG(A2, VectorXr::Zero(N), b2, iter, tol);
  365. //std::cout << "out cg" << std::endl;
  366. /////////////////////////////////////////////////////////////
  367. // update x, mux, muy
  368. //VectorXr h = ztilde; // - x;
  369. VectorXr s1, s2;
  370. // update x
  371. //VectorXr h = ztilde; // - x;
  372. //Scalar d = std::min(1., 0.995*(x.array()/h.array().abs()).minCoeff() );
  373. //x += d*h;
  374. Scalar d = std::min(1.,0.995*(x.array()/ztilde.array().abs()).minCoeff());
  375. x += d*ztilde;
  376. // // Fix any overstepping
  377. // for (int ib=0; ib<nblocks; ++ib) {
  378. // while (x.segment(ib*block, block).sum() > maxVal) {
  379. // x.segment(ib*block, block).array() *= (.9);
  380. // }
  381. // }
  382. // for (int i=0; i<x.size(); ++i) {
  383. // if (x(i) < minVal) {
  384. // x(i) = minVal + delta;
  385. // }
  386. // }
  387. b_pre = A*x;
  388. #ifdef LEMMAUSEOMP
  389. #pragma omp parallel sections
  390. {
  391. #endif
  392. #ifdef LEMMAUSEOMP
  393. #pragma omp section
  394. #endif
  395. {
  396. phib = PhiB(mux, muy, minVal, maxVal, x);
  397. }
  398. #ifdef LEMMAUSEOMP
  399. #pragma omp section
  400. #endif
  401. {
  402. phid = (b - (b_pre)).norm();
  403. }
  404. #ifdef LEMMAUSEOMP
  405. #pragma omp section
  406. #endif
  407. {
  408. phim = x.norm();
  409. }
  410. #ifdef LEMMAUSEOMP
  411. }
  412. #endif
  413. // Determine mu steps to take
  414. #ifdef LEMMAUSEOMP
  415. #pragma omp parallel sections
  416. {
  417. #endif
  418. #ifdef LEMMAUSEOMP
  419. #pragma omp section
  420. #endif
  421. {
  422. s1 = mux * (X2.asDiagonal()*(x+ztilde) - 2.*X1);
  423. mux = SIGMA/((Scalar)(N)) * std::abs( s1.dot(x) ) ;
  424. }
  425. #ifdef LEMMAUSEOMP
  426. #pragma omp section
  427. #endif
  428. {
  429. s2 = muy * (Y2.asDiagonal()*(x+ztilde) - 2.*Y1);
  430. muy = SIGMA/((Scalar)(N)) * std::abs( s2.dot(x) ) ;
  431. }
  432. #ifdef LEMMAUSEOMP
  433. }
  434. #endif
  435. ++iloop;
  436. } while (std::abs(phib / (phid+lambda*phim)) > epsilon);
  437. // report
  438. phireport.precision(12);
  439. std::cout << ii << "\t" << x.norm() << "\t" << (b-(A*x)).norm()
  440. << "\t" << lambda << "\t" << mux << "\t" << muy << "\t"
  441. << iter << "\t" << iloop << std::endl;
  442. phireport << ii << "\t" << x.norm() << "\t" << (b-(A*x)).norm()
  443. << "\t" << lambda << "\t" << mux << "\t" << muy << "\t"
  444. << iter << "\t" << iloop << std::endl;
  445. // write model file
  446. std::fstream modfile;
  447. std::string fname = "iteration" + to_string(ii) + ".dat";
  448. modfile.open( fname.c_str(), std::ios::out);
  449. modfile << ii << "\t" << x.norm() << "\t" << (b-(A*x)).norm()
  450. << "\t" << lambda << "\t" << mux << "\t" << muy << "\t" << iter << "\n";
  451. modfile << x << "\n";
  452. modfile.close();
  453. // write predicted data file
  454. std::fstream predata;
  455. fname = "iteration" + to_string(ii) + "pre.dat";
  456. predata.open(fname.c_str(), std::ios::out);
  457. predata << b_pre << std::endl;
  458. predata.close();
  459. // update lambda
  460. // @todo smarter lambda change
  461. lambda *= .92;
  462. }
  463. phireport.close();
  464. // TODO, determine optimal solution
  465. return x;
  466. }
  467. /** Impliments a logarithmic barrier CG solution of a Real linear system of
  468. * the form \f[ \mathbf{A} \mathbf{x} = \mathbf{b} \f] s.t. \f$ x \in
  469. * (minVal, maxVal) \f$. Note that this method optimized the complete
  470. * solution, using the large matrix ATA. If you have a system with a huge
  471. * number of columns, see the implicit version of this routine. Solution of
  472. * the dual problem (interior-point) follows "Tikhonov Regularization with
  473. * Nonnegativity constraint, (Calavetti et. al. 2004)"
  474. * @param[in] A is a Real Matrix.
  475. * @param[in] b is a Real vector
  476. * @param[in] minVal is the minimum allowed value \f$ x \in (minVal, maxVal) \f$
  477. * @param[in] maxVal is the minimum allowed value \f$ x \in (minVal, maxVal) \f$
  478. * @param[in] block is the number of parameters to sum together for the
  479. * upper barrier term. So block block number parameters are kept under maxVal.
  480. * as such A.rows() / block must be evenly divisible.
  481. */
  482. template <typename Scalar>
  483. VectorXr LogBarrierCG(const MatrixXr &A, const VectorXr &b, const Scalar &minVal,
  484. const Scalar &maxVal, const int& block) {
  485. // Check that everything is aligned OK
  486. if (A.rows() != b.size() ) {
  487. std::cerr << "Matrix A is not aligned with Vector b" << "\n";
  488. exit(1);
  489. }
  490. // write predicted data file
  491. std::fstream obsdata;
  492. std::string fname = "obsdata.dat";
  493. obsdata.open(fname.c_str(), std::ios::out);
  494. obsdata << b << std::endl;
  495. obsdata.close();
  496. // #ifdef LEMMAUSEVTK
  497. // double blue[3] = {0.0,0.0,1.0};
  498. // double red[3] = {1.0,0.0,0.0};
  499. // VectorXr ind = VectorXr::LinSpaced(b.size(), 1, b.size());
  500. // #endif
  501. // TODO make ATA implicit
  502. MatrixXr ATA = A.transpose()*A;
  503. int N = A.cols(); // number of model
  504. int M = A.rows(); // number of data
  505. int MAXITER = 100; // M*N;
  506. Scalar SIGMA = 1e-2; //1e-1;
  507. Scalar delta = 1e-4;
  508. // Cholesky preconditioner
  509. //Eigen::FullPivLU <MatrixXr> Pre;
  510. //Eigen::ColPivHouseholderQR <MatrixXr> Pre;
  511. //Pre.compute(ATA);
  512. // Determine starting lambda_0, find lim_sup of the norm of impulse responses and scale
  513. Scalar limsup = 1e10;
  514. for (int i=0; i<N; ++i) {
  515. VectorXr Spike = VectorXr::Zero(N);
  516. Spike(i) = (minVal + maxVal) / 2.;
  517. limsup = std::min(limsup, (ATA*Spike).array().abs().maxCoeff());
  518. }
  519. Scalar lambda = 1e-6;//*limsup;//e-1;//limsup;
  520. Scalar mux0 = 1e-1*lambda;
  521. Scalar muy0 = 1e-1*lambda;
  522. Scalar epsilon = 1e-25; // Ratio between phib and phim+phid
  523. /////////////////////////////
  524. // logX spacing
  525. //Scalar MinLam = 1e-24;
  526. //Scalar MaxLam = 1e-4;
  527. //VectorXr Lambdas;
  528. //Scalar LS = 5000;
  529. //Scalar dl10 = std::log(LS*MaxLam+1.)/(Scalar)MAXITER;
  530. //Lambdas = 1./LS*(dl10*VectorXr::LinSpaced(MAXITER+1, 0, MAXITER)).array().exp()
  531. // + MinLam - 1./LS;
  532. // initial guess, just near zero for now
  533. VectorXr x = VectorXr::Zero(N).array() + minVal+delta;// ((minVal + maxVal) / 2.);
  534. // predicted b
  535. VectorXr b_pre = A*x;
  536. int nblocks = x.size()/block;
  537. Scalar phid = (b - (b_pre)).norm();
  538. Scalar phim = x.norm();
  539. Scalar phib = PhiB2(mux0, muy0, minVal, maxVal, x, block, nblocks);
  540. Scalar mux = mux0;
  541. Scalar muy = muy0;
  542. Scalar tol = 1e-5*phid; // 1e-14;
  543. std::fstream phireport("phimphid.dat", std::ios::out);
  544. /// @todo add stopping criteria.
  545. //int iLambda = MAXITER - 1;
  546. for (int ii=0; ii<MAXITER; ++ii) {
  547. //lambda = Lambdas[iLambda];
  548. //iLambda -= 1;
  549. // Phi_m is just L2Norm right now. Maybe add s, alpha_T2, and
  550. // alpha_z terms
  551. VectorXr WmT_Wm = VectorXr::Ones(N).array()*lambda;
  552. VectorXr Xm1 = x;
  553. int iter = N*M;
  554. mux = mux0;
  555. muy = muy0;
  556. int iloop(0);
  557. // #ifdef LEMMAUSEVTK
  558. // matplot::Plot2D_VTK p_2d("x(t)","y(t)",800,600);
  559. // p_2d.plot(ind, b, blue, "-");
  560. // p_2d.plot(ind, b_pre, red, "-");
  561. // p_2d.show();
  562. // #endif
  563. do {
  564. VectorXr X1(x.size());
  565. VectorXr Y1(x.size());
  566. VectorXr X2(x.size());
  567. VectorXr Y2(x.size());
  568. VectorXr b2;
  569. //VectorXr HiSegments = VectorXr::Zero(nblocks);
  570. MatrixXr A2;
  571. ///////////////////////////////////
  572. // setup
  573. #ifdef LEMMAUSEOMP
  574. #pragma omp parallel sections
  575. {
  576. #endif
  577. ///////////////////////////////////////////////////////////
  578. // Log barrier terms
  579. #ifdef LEMMAUSEOMP
  580. #pragma omp section
  581. #endif
  582. {
  583. X1 = VectorXr::Ones(N).array() / (x.array()-minVal) ;
  584. }
  585. #ifdef LEMMAUSEOMP
  586. #pragma omp section
  587. #endif
  588. {
  589. for (int ib=0; ib<nblocks; ++ib) {
  590. //HiSegments(ib) = x.segment(ib*block, block).sum();
  591. Y1.segment(ib*block, block) = VectorXr::Ones(block).array() /
  592. (maxVal - x.segment(ib*block, block).sum());
  593. }
  594. //for (int ix=0; ix<x.size(); ++ix) {
  595. // Y1(ix) = 1./( (maxVal-HiSegments(ib)) );
  596. //}
  597. //Y1 = VectorXr::Ones(N).array() / (maxVal-x.array()) ;
  598. }
  599. #ifdef LEMMAUSEOMP
  600. #pragma omp section
  601. #endif
  602. {
  603. X2 = VectorXr::Ones(N).array() / ((x.array()-minVal)*(x.array()-minVal));
  604. }
  605. #ifdef LEMMAUSEOMP
  606. #pragma omp section
  607. #endif
  608. {
  609. for (int ib=0; ib<nblocks; ++ib) {
  610. //HiSegments(ib) = x.segment( ib*block, block ).sum();
  611. Y2.segment(ib*block, block) = VectorXr::Ones(block).array() /
  612. ( (maxVal-x.segment(ib*block, block).sum()) *
  613. (maxVal-x.segment(ib*block, block).sum()) );
  614. }
  615. //Y2 = VectorXr::Ones(N).array() / ((maxVal-x.array())*(maxVal-x.array()));
  616. //std::cout << Y1.transpose() << std::endl << std::endl;
  617. //std::cout << Y2.transpose() << std::endl;
  618. }
  619. #ifdef LEMMAUSEOMP
  620. } // parallel sections
  621. #endif
  622. #ifdef LEMMAUSEOMP
  623. #pragma omp parallel sections
  624. {
  625. #endif
  626. #ifdef LEMMAUSEOMP
  627. #pragma omp section
  628. #endif
  629. {
  630. b2 = -(A.transpose()*(b_pre-b)).array() -
  631. (WmT_Wm.array()*x.array()).array() +
  632. (2.*mux)*X1.array() + (2.*muy)*Y1.array();
  633. }
  634. #ifdef LEMMAUSEOMP
  635. #pragma omp section
  636. #endif
  637. {
  638. A2 = ATA;
  639. A2.diagonal().array() += WmT_Wm.array() + mux*X2.array() +
  640. muy*Y2.array();
  641. }
  642. #ifdef LEMMAUSEOMP
  643. } // parallel sections
  644. #endif
  645. // // Jacobi Preconditioner
  646. // Eigen::SparseMatrix<Scalar> MM =
  647. // Eigen::SparseMatrix<Scalar>(A2.rows(), A2.cols());
  648. // for (int i=0; i<ATA.rows(); ++i) {
  649. // MM.insert(i,i) = 1./ATA(i,i);
  650. // }
  651. // MM.finalize();
  652. /////////////////////////////////////////////////////////////
  653. // Solve system,
  654. // CG solution of complete system
  655. // TODO add reference model
  656. tol = 1e-5*phid+mux+muy;// 1e-14;
  657. iter = N*M;
  658. //std::cout << "Call cg" << std::endl;
  659. // Decomposition preconditioner
  660. //Pre.setThreshold(1e1*tol);
  661. //Pre.compute(A2);
  662. // Jacobi Preconditioner
  663. //VectorXr ztilde = CG(A2, VectorXr::Zero(N), b2, MM, iter, tol);
  664. // Decomposition preconditioner
  665. //VectorXr ztilde = CG(A2, VectorXr::Zero(N), b2, Pre, iter, tol);
  666. // No preconditioner
  667. VectorXr ztilde = CG(A2, VectorXr::Zero(N), b2, iter, tol);
  668. //std::cout << "out cg" << std::endl;
  669. /////////////////////////////////////////////////////////////
  670. // update x, mux, muy
  671. //VectorXr h = ztilde; // - x;
  672. VectorXr s1, s2;
  673. // update x
  674. //VectorXr h = ztilde; // - x;
  675. //Scalar d = std::min(1., 0.995*(x.array()/h.array().abs()).minCoeff() );
  676. //x += d*h;
  677. Scalar d = std::min(1.,0.995*(x.array()/ztilde.array().abs()).minCoeff());
  678. x += d*ztilde;
  679. // // Fix any overstepping
  680. // for (int ib=0; ib<nblocks; ++ib) {
  681. // while (x.segment(ib*block, block).sum() > maxVal) {
  682. // x.segment(ib*block, block).array() *= (.9);
  683. // }
  684. // }
  685. // for (int i=0; i<x.size(); ++i) {
  686. // if (x(i) < minVal) {
  687. // x(i) = minVal + delta;
  688. // }
  689. // }
  690. b_pre = A*x;
  691. #ifdef LEMMAUSEOMP
  692. #pragma omp parallel sections
  693. {
  694. #endif
  695. #ifdef LEMMAUSEOMP
  696. #pragma omp section
  697. #endif
  698. {
  699. phib = PhiB2(mux, muy, minVal, maxVal, x, block, nblocks);
  700. }
  701. #ifdef LEMMAUSEOMP
  702. #pragma omp section
  703. #endif
  704. {
  705. phid = (b - (b_pre)).norm();
  706. }
  707. #ifdef LEMMAUSEOMP
  708. #pragma omp section
  709. #endif
  710. {
  711. phim = x.norm();
  712. }
  713. #ifdef LEMMAUSEOMP
  714. }
  715. #endif
  716. // Determine mu steps to take
  717. #ifdef LEMMAUSEOMP
  718. #pragma omp parallel sections
  719. {
  720. #endif
  721. #ifdef LEMMAUSEOMP
  722. #pragma omp section
  723. #endif
  724. {
  725. s1 = mux * (X2.asDiagonal()*(x+ztilde) - 2.*X1);
  726. mux = SIGMA/((Scalar)(N)) * std::abs( s1.dot(x) ) ;
  727. }
  728. #ifdef LEMMAUSEOMP
  729. #pragma omp section
  730. #endif
  731. {
  732. s2 = muy * (Y2.asDiagonal()*(x+ztilde) - 2.*Y1);
  733. muy = SIGMA/((Scalar)(N)) * std::abs( s2.dot(x) ) ;
  734. }
  735. #ifdef LEMMAUSEOMP
  736. }
  737. #endif
  738. ++iloop;
  739. } while (std::abs(phib / (phid+lambda*phim)) > epsilon);
  740. // report
  741. phireport.precision(12);
  742. std::cout << ii << "\t" << x.norm() << "\t" << (b-(A*x)).norm()
  743. << "\t" << lambda << "\t" << mux << "\t" << muy << "\t"
  744. << iter << "\t" << iloop << std::endl;
  745. phireport << ii << "\t" << x.norm() << "\t" << (b-(A*x)).norm()
  746. << "\t" << lambda << "\t" << mux << "\t" << muy << "\t"
  747. << iter << "\t" << iloop << std::endl;
  748. std::fstream modfile;
  749. std::string fname = "iteration" + to_string(ii) + ".dat";
  750. modfile.open( fname.c_str(), std::ios::out);
  751. modfile << ii << "\t" << x.norm() << "\t" << (b-(A*x)).norm()
  752. << "\t" << lambda << "\t" << mux << "\t" << muy << "\t" << iter << "\n";
  753. modfile << x << "\n";
  754. modfile.close();
  755. // write predicted data file
  756. std::fstream predata;
  757. fname = "iteration" + to_string(ii) + "pre.dat";
  758. predata.open(fname.c_str(), std::ios::out);
  759. predata << b_pre << std::endl;
  760. predata.close();
  761. // update lambda
  762. // @todo smarter lambda change
  763. lambda *= .85;
  764. }
  765. phireport.close();
  766. // TODO, determine optimal solution
  767. return x;
  768. }
  769. /** Impliments a logarithmic barrier CG solution of a Real linear system of
  770. * the form \f[ \mathbf{A} \mathbf{x} = \mathbf{b} \f] s.t. \f$ x \in
  771. * (minVal, maxVal) \f$. Note that this method optimized the complete
  772. * solution, using the large matrix ATA. If you have a system with a huge
  773. * number of columns, see the implicit version of this routine. Solution of
  774. * the dual problem (interior-point) follows "Tikhonov Regularization with
  775. * Nonnegativity constraint, (Calavetti et. al. 2004)"
  776. * @param[in] A is a Real Matrix.
  777. * @param[in] xref is a reference model
  778. * @param[in] b is a Real vector
  779. * @param[in] minVal is the minimum allowed value \f$ x \in (minVal, maxVal) \f$
  780. * @param[in] maxVal is the minimum allowed value \f$ x \in (minVal, maxVal) \f$
  781. * @param[in] block is the number of parameters to sum together for the
  782. * upper barrier term. So block block number parameters are kept under maxVal.
  783. * as such A.rows() / block must be evenly divisible.
  784. * @param[in] WdTWd is the data objective function
  785. * @param[in] WmTWm is the model objective function
  786. */
  787. template <typename Scalar>
  788. VectorXr LogBarrierCG(const MatrixXr &A, const VectorXr &xr,
  789. const VectorXr &b, const Scalar &minVal,
  790. const Scalar &maxVal, const int& block,
  791. const Eigen::SparseMatrix<Scalar>& WdTWd,
  792. const Eigen::SparseMatrix<Scalar>& WmTWm, Real lambda0=1e1) {
  793. // Check that everything is aligned OK
  794. if (A.rows() != b.size() ) {
  795. std::cerr << "Matrix A is not aligned with Vector b" << "\n";
  796. std::cerr << "A.rows() " << A.rows() << "\n";
  797. std::cerr << "A.cols() " << A.cols() << "\n";
  798. std::cerr << "b.size() " << b.size() << "\n";
  799. exit(1);
  800. }
  801. // write predicted data file
  802. std::fstream obsdata;
  803. std::string fname = "obsdata.dat";
  804. obsdata.open(fname.c_str(), std::ios::out);
  805. obsdata << b << std::endl;
  806. obsdata.close();
  807. // TODO make ATA implicit
  808. MatrixXr ATWdTWdA = A.transpose()*WdTWd*A;
  809. int N = A.cols(); // number of model
  810. int M = A.rows(); // number of data
  811. int MAXITER = 175; // M*N;
  812. Scalar SIGMA = .25;//5.85; //1e-2; // .25; //1e-2; // 1e-1;
  813. Scalar delta = 1e-4;
  814. // // Determine starting lambda_0, find lim_sup of the norm of impulse responses and scale
  815. // Scalar limsup = 1e10;
  816. // for (int i=0; i<N; ++i) {
  817. // VectorXr Spike = VectorXr::Zero(N);
  818. // Spike(i) = (minVal + maxVal) / 2.;
  819. // limsup = std::min(limsup, (ATWdTWdA*Spike).array().abs().maxCoeff());
  820. // }
  821. Scalar lambda = lambda0; //*limsup;//e-1;//limsup;
  822. Scalar epsilon = 1e-15; // Ratio between phib and phim+phid
  823. // initial guess, just near zero for now
  824. VectorXr x = VectorXr::Zero(N).array() + minVal+delta;// ((minVal + maxVal) / 2.);
  825. // predicted b
  826. VectorXr b_pre = A*x;
  827. int nblocks = x.size()/block;
  828. Scalar phid = (WdTWd*(b - b_pre)).norm();
  829. Scalar phim = (WmTWm*(x - xr)).norm();
  830. Scalar phib = PhiB2(minVal, maxVal, x, block, nblocks);
  831. Scalar mux = (phid + lambda*phim) / phib;
  832. Scalar muy = mux;
  833. //Scalar tol;// = 1e-5*phid; // 1e-14;
  834. std::fstream phireport("phimphid.dat", std::ios::out);
  835. Eigen::ConjugateGradient< MatrixXr > cg;
  836. /// @todo add stopping criteria.
  837. for (int ii=0; ii<MAXITER; ++ii) {
  838. int iter = N*M;
  839. mux = (phid + lambda*phim) / phib;
  840. muy = mux;
  841. int iloop(0);
  842. int itertot(0);
  843. VectorXr h;
  844. bool cont(true);
  845. do {
  846. //restart:
  847. VectorXr X1(x.size());
  848. VectorXr Y1(x.size());
  849. VectorXr X2(x.size());
  850. VectorXr Y2(x.size());
  851. VectorXr b2;
  852. MatrixXr A2;
  853. ///////////////////////////////////
  854. // setup
  855. ///////////////////////////////////////////////////////////
  856. // Log barrier terms
  857. X1 = VectorXr::Ones(N).array() / (x.array()-minVal) ;
  858. for (int ib=0; ib<nblocks; ++ib) {
  859. Y1.segment(ib*block, block) = VectorXr::Ones(block).array() /
  860. (maxVal - x.segment(ib*block, block).sum());
  861. }
  862. X2 = VectorXr::Ones(N).array() / ((x.array()-minVal)*(x.array()-minVal));
  863. for (int ib=0; ib<nblocks; ++ib) {
  864. Y2.segment(ib*block, block) = VectorXr::Ones(block).array() /
  865. ( (maxVal-x.segment(ib*block, block).sum()) *
  866. (maxVal-x.segment(ib*block, block).sum()) );
  867. }
  868. // Newton step
  869. //b2 = - (A.transpose()*WdTWd*(b_pre-b)).array()
  870. // - lambda*(WmTWm*(x-xr)).array()
  871. // + (2.*mux)*X1.array() + (2.*muy)*Y1.array();
  872. // Full
  873. b2 = (A.transpose()*WdTWd*(b)).array()
  874. //- lambda*(WmTWm*(x-xr)).array()
  875. + (2.*mux)*X1.array() + (2.*muy)*Y1.array();
  876. A2 = ATWdTWdA;
  877. A2 += lambda*WmTWm;
  878. A2.diagonal().array() += mux*X2.array() + muy*Y2.array();
  879. // // Jacobi Preconditioner
  880. // Eigen::SparseMatrix<Scalar> MM =
  881. // Eigen::SparseMatrix<Scalar>(A2.rows(), A2.cols());
  882. // for (int i=0; i<ATWdTWdA.rows(); ++i) {
  883. // MM.insert(i,i) = 1./ATWdTWdA(i,i);
  884. // }
  885. // MM.finalize();
  886. /////////////////////////////////////////////////////////////
  887. // Solve system,
  888. // CG solution of complete system
  889. // TODO add reference model
  890. //tol = 1e-5*phid+mux+muy;// 1e-14;
  891. iter = N*M;
  892. //std::cout << "Call cg" << std::endl;
  893. // Decomposition preconditioner
  894. //Pre.setThreshold(1e1*tol);
  895. //Pre.compute(A2);
  896. // Jacobi Preconditioner
  897. //VectorXr ztilde = CGJ(A2, VectorXr::Zero(N), b2, MM, iter, tol);
  898. // Decomposition preconditioner
  899. //VectorXr ztilde = CG(A2, VectorXr::Zero(N), b2, Pre, iter, tol);
  900. // No preconditioner
  901. // Newton Setp
  902. //VectorXr ztilde = CG(A2, VectorXr::Zero(N), b2, iter, tol);
  903. // Full soln
  904. //VectorXr ztilde = CG(A2, x, b2, iter, tol);
  905. //std::cout << "out cg" << std::endl;
  906. cg.compute(A2);
  907. VectorXr ztilde = cg.solveWithGuess(b2, x);
  908. iter = cg.iterations();
  909. //tol = cg.error();
  910. ++iloop;
  911. itertot += iter;
  912. /////////////////////////////////////////////////////////////
  913. // update x, mux, muy
  914. //VectorXr h = ztilde; // - x;
  915. // update x
  916. h = ztilde - x;
  917. // determing steplength
  918. //Scalar d = std::min(1., 0.925*(x.array()/h.array().abs()).minCoeff() );
  919. Scalar d(1.);
  920. for (int ix=0; ix<x.size(); ++ix) {
  921. if (h[ix] < 0.) {
  922. d = std::min(d, (Scalar).925*(x[ix]/std::abs(h[ix])));
  923. }
  924. }
  925. // if (d < 1e-5) {
  926. // std::cout << "not going anywhere d=" << d << " |h| = " << h.norm() << "\n";
  927. // //break;
  928. // mux = (phid + lambda*phim) / phib;
  929. // muy = mux;
  930. // x = VectorXr::Zero(N).array() + minVal+delta;// ((minVal + maxVal) / 2.);
  931. // //goto restart; // Gasp!
  932. // continue;
  933. // }
  934. // Newton
  935. //Scalar d = std::min(1., 0.9*((x.array()/ztilde.array()).abs()).minCoeff());
  936. // Make step
  937. x += d*h; // whole soln
  938. //x += d*ztilde; // Newton
  939. // Fix any overstepping
  940. for (int ib=0; ib<nblocks; ++ib) {
  941. while (x.segment(ib*block, block).sum() >= maxVal) {
  942. x.segment(ib*block, block).array() *= .99;
  943. }
  944. }
  945. for (int i=0; i<x.size(); ++i) {
  946. if (x(i) < minVal) {
  947. x(i) = minVal + delta;
  948. }
  949. }
  950. b_pre = A*x;
  951. phib = PhiB2(mux, muy, minVal, maxVal, x, block, nblocks);
  952. phid = (WdTWd*(b-b_pre)).norm();
  953. phim = (WmTWm*(x-xr)).norm();
  954. // Determine mu steps to take
  955. VectorXr s1 = mux * (X2.asDiagonal()*(ztilde) - 2.*X1);
  956. mux = SIGMA/((Scalar)(N)) * std::abs( s1.dot(x) ) ;
  957. VectorXr s2 = muy * (Y2.asDiagonal()*(ztilde) - 2.*Y1);
  958. muy = SIGMA/((Scalar)(N)) * std::abs( s2.dot(x) ) ;
  959. if ( (std::abs(phib / (phid+lambda*phim)) < epsilon)) {
  960. //if ( (std::abs(phib / (phid+lambda*phim)) < epsilon) && h.norm() < 1e-5) {
  961. cont = false;
  962. }
  963. } while ( cont );
  964. // report
  965. //std::cout << std::ios::left;
  966. //std::cout.precision(8);
  967. std::cout << std::setw(6) << ii << std::scientific << std::setw(18) << phim << std::setw(18) << phid
  968. << std::setw(18) << lambda << std::setw(18) << mux << std::setw(18) << muy
  969. << std::setw(12) << itertot << std::setw(12) << iloop << std::setw(18) << h.norm() << std::endl;
  970. phireport.precision(12);
  971. phireport << ii << "\t" << phim << "\t" << phid
  972. << "\t" << lambda << "\t" << mux << "\t" << muy << "\t"
  973. << itertot << "\t" << iloop << "\t" << h.norm() << std::endl;
  974. std::fstream modfile;
  975. std::string fname = "iteration" + to_string(ii) + ".dat";
  976. modfile.open( fname.c_str(), std::ios::out);
  977. modfile << ii << "\t" << phim << "\t" << phid
  978. << "\t" << lambda << "\t" << mux << "\t" << muy << "\t" << iter << "\n";
  979. modfile << x << "\n";
  980. modfile.close();
  981. // write predicted data file
  982. std::fstream predata;
  983. fname = "iteration" + to_string(ii) + "pre.dat";
  984. predata.open(fname.c_str(), std::ios::out);
  985. predata << b_pre << std::endl;
  986. predata.close();
  987. // update lambda
  988. // @todo smarter lambda change
  989. lambda *= .9;
  990. }
  991. phireport.close();
  992. // TODO, determine optimal solution
  993. return x;
  994. }
  995. /** Impliments a logarithmic barrier CG solution of a Real linear system of
  996. * the form \f[ \mathbf{A} \mathbf{x} = \mathbf{b} \f] s.t. \f$ x \in
  997. * (minVal, maxVal) \f$. Note that this method optimized the complete
  998. * solution, using the large matrix ATA. If you have a system with a huge
  999. * number of columns, see the implicit version of this routine. Solution of
  1000. * the dual problem (interior-point) follows "Tikhonov Regularization with
  1001. * Nonnegativity constraint, (Calavetti et. al. 2004)". This routine only imposes non-negativity. No upper bound
  1002. * @param[in] A is a Real Matrix.
  1003. * @param[in] xref is a reference model
  1004. * @param[in] b is a Real vector
  1005. * @param[in] minVal is the minimum allowed value \f$ x \in (minVal, maxVal) \f$
  1006. * @param[in] maxVal is the minimum allowed value \f$ x \in (minVal, maxVal) \f$
  1007. * @param[in] block is the number of parameters to sum together for the
  1008. * upper barrier term. So block block number parameters are kept under maxVal.
  1009. * as such A.rows() / block must be evenly divisible.
  1010. * @param[in] WdTWd is the data objective function
  1011. * @param[in] WmTWm is the model objective function
  1012. */
  1013. template <typename Scalar>
  1014. VectorXr LogBarrierCG_NN(const MatrixXr &A, const VectorXr &xr,
  1015. const VectorXr &b, const Scalar &minVal,
  1016. const Eigen::SparseMatrix<Scalar>& WdTWd,
  1017. const Eigen::SparseMatrix<Scalar>& WmTWm, Real lambda0=1e1) {
  1018. // Check that everything is aligned OK
  1019. if (A.rows() != b.size() ) {
  1020. std::cerr << "Matrix A is not aligned with Vector b" << "\n";
  1021. std::cerr << "A.rows() " << A.rows() << "\n";
  1022. std::cerr << "A.cols() " << A.cols() << "\n";
  1023. std::cerr << "b.size() " << b.size() << "\n";
  1024. exit(1);
  1025. }
  1026. // write predicted data file
  1027. std::fstream obsdata;
  1028. std::string fname = "obsdata.dat";
  1029. obsdata.open(fname.c_str(), std::ios::out);
  1030. obsdata << b << std::endl;
  1031. obsdata.close();
  1032. // TODO make ATA implicit, or at least only compute half
  1033. MatrixXr ATWdTWdA = A.transpose()*WdTWd*A;
  1034. int N = A.cols(); // number of model
  1035. int M = A.rows(); // number of data
  1036. int MAXITER = 175; // M*N;
  1037. Scalar SIGMA = .25;//5.85; //1e-2; // .25; //1e-2; // 1e-1;
  1038. Scalar delta = 1e-12;
  1039. // // Determine starting lambda_0, find lim_sup of the norm of impulse responses and scale
  1040. // Scalar limsup = 1e10;
  1041. // for (int i=0; i<N; ++i) {
  1042. // VectorXr Spike = VectorXr::Zero(N);
  1043. // Spike(i) = (minVal + maxVal) / 2.;
  1044. // limsup = std::min(limsup, (ATWdTWdA*Spike).array().abs().maxCoeff());
  1045. // }
  1046. Scalar lambda = lambda0; //*limsup;//e-1;//limsup;
  1047. Scalar epsilon = 1e-16; // Ratio between phib and phim+phid
  1048. // initial guess, just near zero for now
  1049. VectorXr x = VectorXr::Zero(N).array() + minVal+delta;// ((minVal + maxVal) / 2.);
  1050. // predicted b
  1051. VectorXr b_pre = A*x;
  1052. //Eigen::ConjugateGradient< MatrixXr > cg;
  1053. // Use ILUT preconditioner
  1054. Eigen::ConjugateGradient< MatrixXr, Eigen::Upper, Eigen::DiagonalPreconditioner<Real> > cg;
  1055. //Eigen::ConjugateGradient< MatrixXr, Eigen::Upper, Eigen::IncompleteLUT<Real> > cg;
  1056. Scalar phid = (WdTWd*(b - b_pre)).norm();
  1057. Scalar phim = (WmTWm*(x - xr)).norm();
  1058. Scalar phib = PhiB2_NN(1., minVal, x);
  1059. Scalar mux = (phid + lambda*phim) / phib;
  1060. //Scalar tol; // = 1e-5*phid; // 1e-14;
  1061. std::fstream phireport("phimphid.dat", std::ios::out);
  1062. mux = (phid + lambda*phim) / phib;
  1063. /// @todo add stopping criteria.
  1064. for (int ii=0; ii<MAXITER; ++ii) {
  1065. int iter = N*M;
  1066. int iloop(0);
  1067. int itertot(0);
  1068. //VectorXr h;
  1069. VectorXr ztilde;
  1070. bool cont(true);
  1071. do {
  1072. //restart:
  1073. VectorXr X1(x.size());
  1074. VectorXr X2(x.size());
  1075. VectorXr b2;
  1076. MatrixXr A2;
  1077. ///////////////////////////////////
  1078. // setup
  1079. ///////////////////////////////////////////////////////////
  1080. // Log barrier terms
  1081. X1 = VectorXr::Ones(N).array() / (x.array()-minVal) ;
  1082. X2 = VectorXr::Ones(N).array() / ((x.array()-minVal)*(x.array()-minVal));
  1083. // Full
  1084. b2 = (A.transpose()*WdTWd*(b-b_pre)).array()
  1085. - lambda*(WmTWm*(x-xr)).array()
  1086. + (2.*mux)*X1.array(); // + (2.*muy)*Y1.array();
  1087. // The first two terms could be moved out of the loop, don't know if its worth it
  1088. A2 = ATWdTWdA;
  1089. A2 += lambda*WmTWm;
  1090. A2.diagonal().array() += mux*X2.array();
  1091. /////////////////////////////////////////////////////////////
  1092. // Solve system,
  1093. // CG solution of complete system
  1094. // TODO add reference model
  1095. //tol = 1e-5*phid+mux;// 1e-14;
  1096. iter = N*M;
  1097. // Full soln
  1098. //VectorXr ztilde = CG(A2, x, b2, iter, tol);
  1099. cg.compute(A2);
  1100. //ztilde = cg.solveWithGuess(b2, x);
  1101. ztilde = cg.solve(b2); // Newton step, don't guess!
  1102. //std::cout << "out cg" << std::endl;
  1103. iter = cg.iterations();
  1104. //tol = cg.error();
  1105. ++iloop;
  1106. itertot += iter;
  1107. /////////////////////////////////////////////////////////////
  1108. // update x, mux, muy
  1109. //h = ztilde - x;
  1110. // determing steplength
  1111. Scalar d(1.);
  1112. for (int ix=0; ix<x.size(); ++ix) {
  1113. if (ztilde[ix] < 0.) {
  1114. d = std::min(d, (Scalar).925*(x[ix]/std::abs(ztilde[ix])));
  1115. }
  1116. }
  1117. // if (d < 1e-5) {
  1118. // std::cout << "not going anywhere d=" << d << " |h| = " << h.norm() << "\n";
  1119. // //break;
  1120. // mux = (phid + lambda*phim) / phib;
  1121. // muy = mux;
  1122. // x = VectorXr::Zero(N).array() + minVal+delta;// ((minVal + maxVal) / 2.);
  1123. // //goto restart; // Gasp!
  1124. // continue;
  1125. // }
  1126. // Newton
  1127. //Scalar d = std::min(1., 0.9*((x.array()/ztilde.array()).abs()).minCoeff());
  1128. // Make step
  1129. x += d*ztilde; // whole soln
  1130. // Fix any overstepping
  1131. for (int i=0; i<x.size(); ++i) {
  1132. if (x(i) < minVal) {
  1133. x(i) = minVal + delta;
  1134. }
  1135. }
  1136. b_pre = A*x;
  1137. phib = PhiB2_NN(mux, minVal, x);
  1138. phid = (WdTWd*(b-b_pre)).norm();
  1139. phim = (WmTWm*(x-xr)).norm();
  1140. // Determine mu steps to take
  1141. VectorXr s1 = mux * (X2.asDiagonal()*(ztilde) - 2.*X1);
  1142. mux = SIGMA/((Scalar)(N)) * std::abs( s1.dot(x) ) ;
  1143. if ( (std::abs(phib / (phid+lambda*phim)) < epsilon)) {
  1144. //if ( (std::abs(phib / (phid+lambda*phim)) < epsilon) && h.norm() < 1e-5) {
  1145. cont = false;
  1146. }
  1147. } while ( cont );
  1148. // report
  1149. //std::cout << std::ios::left;
  1150. //std::cout.precision(8);
  1151. std::cout << std::setw(6) << ii << std::scientific << std::setw(18) << phim << std::setw(18) << phid
  1152. << std::setw(18) << lambda << std::setw(18) << mux
  1153. << std::setw(12) << itertot << std::setw(12) << iloop << std::setw(18) << ztilde.norm() << std::endl;
  1154. phireport.precision(12);
  1155. phireport << ii << "\t" << phim << "\t" << phid
  1156. << "\t" << lambda << "\t" << mux << "\t"
  1157. << itertot << "\t" << iloop << "\t" << ztilde.norm() << std::endl;
  1158. std::fstream modfile;
  1159. std::string fname = "iteration" + to_string(ii) + ".dat";
  1160. modfile.open( fname.c_str(), std::ios::out);
  1161. modfile << ii << "\t" << phim << "\t" << phid
  1162. << "\t" << lambda << "\t" << mux << "\t" << iter << "\n";
  1163. modfile << x << "\n";
  1164. modfile.close();
  1165. // write predicted data file
  1166. std::fstream predata;
  1167. fname = "iteration" + to_string(ii) + "pre.dat";
  1168. predata.open(fname.c_str(), std::ios::out);
  1169. predata << b_pre << std::endl;
  1170. predata.close();
  1171. // update lambda
  1172. // @todo smarter lambda change
  1173. lambda *= .9;
  1174. }
  1175. phireport.close();
  1176. // TODO, determine optimal solution
  1177. return x;
  1178. }
  1179. // Specialized Function that incorporates a buried modulus function.
  1180. // solves the usual problem Ax = b, where A \in C but x and b are real.
  1181. // b = mod(Ax).
  1182. template <typename Scalar>
  1183. VectorXr Tikhonov_CG(const MatrixXr &A, const VectorXr &xr,
  1184. const VectorXr &b,
  1185. const Eigen::SparseMatrix<Scalar>& WdTWd,
  1186. const Eigen::SparseMatrix<Scalar>& WmTWm, Real lambda0=1e1) {
  1187. // Check that everything is aligned OK
  1188. if (A.rows() != b.size() ) {
  1189. std::cerr << "Matrix A is not aligned with Vector b" << "\n";
  1190. std::cerr << "A.rows() " << A.rows() << "\n";
  1191. std::cerr << "A.cols() " << A.cols() << "\n";
  1192. std::cerr << "b.size() " << b.size() << "\n";
  1193. exit(1);
  1194. }
  1195. // write predicted data file
  1196. std::fstream obsdata;
  1197. std::string fname = "obsdata.dat";
  1198. obsdata.open(fname.c_str(), std::ios::out);
  1199. obsdata << b.array() << std::endl;
  1200. obsdata.close();
  1201. // TODO make ATA implicit
  1202. MatrixXr ATWdTWdA = A.transpose()*WdTWd*A;
  1203. int N = A.cols(); // number of model
  1204. int M = A.rows(); // number of dat
  1205. int MAXITER = 175; // M*N;
  1206. //Scalar SIGMA = .25;//5.85; //1e-2; // .25; //1e-2; // 1e-1;
  1207. Scalar delta = 1e-4;
  1208. Scalar lambda = lambda0; // * limsup;//e-1;//limsup;
  1209. Scalar epsilon = 1e-15; // Ratio between phib and phim+phid
  1210. // initial guess, just near zero for now
  1211. VectorXr x = VectorXr::Zero(N).array() + delta;// ((minVal + maxVal) / 2.);
  1212. // predicted b
  1213. VectorXr b_pre = A*x;
  1214. Scalar phid = (WdTWd*(b - b_pre)).norm();
  1215. Scalar phim = (WmTWm*(x - xr)).norm();
  1216. Scalar tol = 1e-5*phid; // 1e-14;
  1217. std::fstream phireport("phimphid.dat", std::ios::out);
  1218. //ConjugateGradient<SparseMatrix<double> > cg;
  1219. // can't use Eigen, b/c we have mixed types of Re and complex
  1220. Eigen::ConjugateGradient< MatrixXr > cg;
  1221. //Eigen::BiCGSTAB< MatrixXcr > solver;
  1222. /// @todo add stopping criteria.
  1223. for (int ii=0; ii<MAXITER; ++ii) {
  1224. int iter = N*M;
  1225. int iloop(0);
  1226. int itertot(0);
  1227. VectorXr h;
  1228. bool cont(true);
  1229. do {
  1230. //restart:
  1231. //VectorXr b2;
  1232. //MatrixXr A2;
  1233. ///////////////////////////////////
  1234. // setup
  1235. // Newton step
  1236. //b2 = - (A.transpose()*WdTWd*(b_pre-b)).array()
  1237. // - lambda*(WmTWm*(x-xr)).array();
  1238. // + (2.*mux)*X1.array() + (2.*muy)*Y1.array();
  1239. // Full
  1240. VectorXr b2 = A.transpose()*WdTWd*b;
  1241. MatrixXr A2 = ATWdTWdA;
  1242. A2 += lambda*WmTWm;
  1243. // // Jacobi Preconditioner
  1244. // Eigen::SparseMatrix<Scalar> MM =
  1245. // Eigen::SparseMatrix<Scalar>(A2.rows(), A2.cols());
  1246. // for (int i=0; i<ATWdTWdA.rows(); ++i) {
  1247. // MM.insert(i,i) = 1./ATWdTWdA(i,i);
  1248. // }
  1249. // MM.finalize();
  1250. /////////////////////////////////////////////////////////////
  1251. // Solve system,
  1252. // CG solution of complete system
  1253. // TODO add reference model
  1254. tol = 1e-5*phid;// 1e-14;
  1255. iter = N*M;
  1256. //std::cout << "Call cg" << std::endl;
  1257. // Decomposition preconditioner
  1258. //Pre.setThreshold(1e1*tol);
  1259. //Pre.compute(A2);
  1260. // Jacobi Preconditioner
  1261. //VectorXr ztilde = CGJ(A2, VectorXr::Zero(N), b2, MM, iter, tol);
  1262. // Decomposition preconditioner
  1263. //VectorXr ztilde = CG(A2, VectorXr::Zero(N), b2, Pre, iter, tol);
  1264. // No preconditioner
  1265. // Newton Setp
  1266. //VectorXr ztilde = CG(A2, VectorXr::Zero(N), b2, iter, tol);
  1267. // Full soln
  1268. //cg.compute(A2);
  1269. //cg.setTolerance(tol);
  1270. //VectorXr ztilde = (cg.solveWithGuess(b2,x.cast<Complex>())).real();
  1271. //iter = cg.iterations();
  1272. //VectorXr ztilde = CG(A2, x, b2, iter, tol);
  1273. //cg.setTolerance();
  1274. cg.compute(A2);
  1275. x = cg.solveWithGuess(b2, x);
  1276. b_pre = A*x;
  1277. phid = (WdTWd*(b - b_pre)).norm();
  1278. phim = (WmTWm*(x - xr)).norm();
  1279. //std::cout << "out cg" << std::endl;
  1280. ++iloop;
  1281. itertot += iter;
  1282. /////////////////////////////////////////////////////////////
  1283. // update x, mux, muy
  1284. //VectorXr h = ztilde; // - x;
  1285. // update x
  1286. //h = ztilde - x;
  1287. // determing steplength
  1288. //Scalar d = std::min(1., 0.925*(x.array()/h.array().abs()).minCoeff() );
  1289. // Scalar d(1.);
  1290. // for (int ix=0; ix<x.size(); ++ix) {
  1291. // if (h[ix] < 0.) {
  1292. // d = std::min(d, (Scalar).925*(x[ix]/std::abs(h[ix])));
  1293. // }
  1294. // }
  1295. // if (d < 1e-5) {
  1296. // std::cout << "not going anywhere d=" << d << " |h| = " << h.norm() << "\n";
  1297. // //break;
  1298. // mux = (phid + lambda*phim) / phib;
  1299. // muy = mux;
  1300. // x = VectorXr::Zero(N).array() + minVal+delta;// ((minVal + maxVal) / 2.);
  1301. // //goto restart; // Gasp!
  1302. // continue;
  1303. // }
  1304. // Newton
  1305. //Scalar d = std::min(1., 0.9*((x.array()/ztilde.array()).abs()).minCoeff());
  1306. // Make step
  1307. //x += d*h; // whole soln
  1308. //x += d*ztilde; // Newton
  1309. // // TODO readd
  1310. // // Fix any overstepping
  1311. // for (int ib=0; ib<nblocks; ++ib) {
  1312. // while (x.segment(ib*block, block).sum() >= maxVal) {
  1313. // x.segment(ib*block, block).array() *= .99;
  1314. // }
  1315. // }
  1316. /*
  1317. for (int i=0; i<x.size(); ++i) {
  1318. if (x(i) < minVal) {
  1319. x(i) = minVal + delta;
  1320. }
  1321. }
  1322. b_pre = (A*x).array().abs();
  1323. phib = PhiB2(mux, muy, minVal, maxVal, x, block, nblocks);
  1324. phid = (WdTWd*(b-b_pre)).norm();
  1325. phim = (WmTWm*(x-xr)).norm();
  1326. // Determine mu steps to take
  1327. VectorXr s1 = mux * (X2.asDiagonal()*(ztilde) - 2.*X1);
  1328. mux = SIGMA/((Scalar)(N)) * std::abs( s1.dot(x) ) ;
  1329. VectorXr s2 = muy * (Y2.asDiagonal()*(ztilde) - 2.*Y1);
  1330. muy = SIGMA/((Scalar)(N)) * std::abs( s2.dot(x) ) ;
  1331. if ( (std::abs(phib / (phid+lambda*phim)) < epsilon)) {
  1332. //if ( (std::abs(phib / (phid+lambda*phim)) < epsilon) && h.norm() < 1e-5) {
  1333. cont = false;
  1334. }
  1335. */
  1336. cont = false;
  1337. } while ( cont );
  1338. // report
  1339. std::cout << std::ios::left;
  1340. std::cout.precision(8);
  1341. std::cout << std::setw(6) << ii << std::scientific << std::setw(18) << phim << std::setw(18) << phid
  1342. << std::setw(18) << lambda << std::setw(18) << cg.error()
  1343. << std::setw(12) << cg.iterations() << std::endl;
  1344. phireport.precision(12);
  1345. phireport << ii << "\t" << phim << "\t" << phid
  1346. << "\t" << lambda << "\t" << 0.0 << "\t" << 0.0 << "\t"
  1347. << cg.iterations() << "\t" << 0.0 << "\t" << 0.0 << std::endl;
  1348. std::fstream modfile;
  1349. std::string fname = "iteration" + to_string(ii) + ".dat";
  1350. modfile.open( fname.c_str(), std::ios::out);
  1351. modfile << ii << "\t" << phim << "\t" << phid
  1352. << "\t" << lambda << "\t" << 0 << "\t" << 0 << "\t" << cg.iterations() << "\n";
  1353. modfile << x << "\n";
  1354. modfile.close();
  1355. // write predicted data file
  1356. std::fstream predata;
  1357. fname = "iteration" + to_string(ii) + "pre.dat";
  1358. predata.open(fname.c_str(), std::ios::out);
  1359. predata << b_pre << std::endl;
  1360. predata.close();
  1361. // update lambda
  1362. // @todo smarter lambda change
  1363. lambda *= .9;
  1364. }
  1365. phireport.close();
  1366. // TODO, determine optimal solution
  1367. return x;
  1368. }
  1369. /** Impliments a logarithmic barrier CG solution of a Real linear system of
  1370. * the form \f[ \mathbf{A} \mathbf{x} = \mathbf{b} \f] s.t. \f$ x \in
  1371. * (minVal, maxVal) \f$. Note that this method optimized the complete
  1372. * solution, using the large matrix ATA. If you have a system with a huge
  1373. * number of columns, see the implicit version of this routine. Solution of
  1374. * the dual problem (interior-point) follows "Tikhonov Regularization with
  1375. * Nonnegativity constraint, (Calavetti et. al. 2004)"
  1376. * Seeks the overdetermined least squares solution
  1377. * @param[in] A is a Real Matrix.
  1378. * @param[in] b is a Real vector
  1379. * @param[in] minVal is the minimum allowed value \f$ x \in (minVal, maxVal) \f$
  1380. * @param[in] maxVal is the minimum allowed value \f$ x \in (minVal, maxVal) \f$
  1381. * @param[in] block is the number of parameters to sum together for the
  1382. * upper barrier term. So block block number parameters are kept under maxVal.
  1383. * as such A.rows() / block must be evenly divisible.
  1384. */
  1385. template <typename Scalar>
  1386. VectorXr LogBarrierCGLS(const MatrixXr &A, const VectorXr &b, const Scalar &minVal,
  1387. const Scalar &maxVal, const int& block) {
  1388. // Check that everything is aligned OK
  1389. if (A.rows() != b.size() ) {
  1390. std::cerr << "Matrix A is not aligned with Vector b" << "\n";
  1391. exit(1);
  1392. }
  1393. // write predicted data file
  1394. std::fstream obsdata;
  1395. std::string fname = "obsdata.dat";
  1396. obsdata.open(fname.c_str(), std::ios::out);
  1397. obsdata << b << std::endl;
  1398. obsdata.close();
  1399. // #ifdef LEMMAUSEVTK
  1400. // double blue[3] = {0.0,0.0,1.0};
  1401. // double red[3] = {1.0,0.0,0.0};
  1402. // VectorXr ind = VectorXr::LinSpaced(b.size(), 1, b.size());
  1403. // #endif
  1404. // TODO make ATA implicit
  1405. MatrixXr ATA = A.transpose()*A;
  1406. int N = A.cols(); // number of model
  1407. int M = A.rows(); // number of data
  1408. int MAXITER = 100; // M*N;
  1409. Scalar SIGMA = .25; // 1e-2; //1e-1;
  1410. Scalar delta = 1e-8;
  1411. // Cholesky preconditioner
  1412. //Eigen::FullPivLU <MatrixXr> Pre;
  1413. //Eigen::ColPivHouseholderQR <MatrixXr> Pre;
  1414. //Pre.compute(ATA);
  1415. // Determine starting lambda_0, find lim_sup of the norm of impulse responses and scale
  1416. Scalar limsup = 1e10;
  1417. for (int i=0; i<N; ++i) {
  1418. VectorXr Spike = VectorXr::Zero(N);
  1419. Spike(i) = (minVal + maxVal) / 2.;
  1420. limsup = std::min(limsup, (ATA*Spike).array().abs().maxCoeff());
  1421. }
  1422. Scalar lambda = 1e-6;//*limsup;//e-1;//limsup;
  1423. Scalar mux0 = 1e-1*lambda;
  1424. Scalar muy0 = 1e-1*lambda;
  1425. Scalar epsilon = 1e-5; // Ratio between phib and phim+phid
  1426. /////////////////////////////
  1427. // logX spacing
  1428. //Scalar MinLam = 1e-24;
  1429. //Scalar MaxLam = 1e-4;
  1430. //VectorXr Lambdas;
  1431. //Scalar LS = 5000;
  1432. //Scalar dl10 = std::log(LS*MaxLam+1.)/(Scalar)MAXITER;
  1433. //Lambdas = 1./LS*(dl10*VectorXr::LinSpaced(MAXITER+1, 0, MAXITER)).array().exp()
  1434. // + MinLam - 1./LS;
  1435. // initial guess, just near zero for now
  1436. VectorXr x = VectorXr::Zero(N).array() + minVal+delta;// ((minVal + maxVal) / 2.);
  1437. // predicted b
  1438. VectorXr b_pre = A*x;
  1439. int nblocks = x.size()/block;
  1440. Scalar phid = (b - (b_pre)).norm();
  1441. Scalar phim = x.norm();
  1442. Scalar phib = PhiB2(mux0, muy0, minVal, maxVal, x, block, nblocks);
  1443. Scalar mux = mux0;
  1444. Scalar muy = muy0;
  1445. Scalar tol = 1e-5*phid; // 1e-14;
  1446. std::fstream phireport("phimphid.dat", std::ios::out);
  1447. /// @todo add stopping criteria.
  1448. //int iLambda = MAXITER - 1;
  1449. for (int ii=0; ii<MAXITER; ++ii) {
  1450. //lambda = Lambdas[iLambda];
  1451. //iLambda -= 1;
  1452. // Phi_m is just L2Norm right now. Maybe add s, alpha_T2, and
  1453. // alpha_z terms
  1454. VectorXr WmT_Wm = VectorXr::Ones(N).array()*lambda;
  1455. VectorXr Xm1 = x;
  1456. int iter = N*M;
  1457. int iloop(0);
  1458. do {
  1459. VectorXr X1(x.size());
  1460. VectorXr Y1(x.size());
  1461. VectorXr X2(x.size());
  1462. VectorXr Y2(x.size());
  1463. VectorXr b2;
  1464. //VectorXr HiSegments = VectorXr::Zero(nblocks);
  1465. MatrixXr A2;
  1466. ///////////////////////////////////
  1467. // setup
  1468. #ifdef LEMMAUSEOMP
  1469. #pragma omp parallel sections
  1470. {
  1471. #endif
  1472. ///////////////////////////////////////////////////////////
  1473. // Log barrier terms
  1474. #ifdef LEMMAUSEOMP
  1475. #pragma omp section
  1476. #endif
  1477. {
  1478. X1 = VectorXr::Ones(N).array() / (x.array()-minVal) ;
  1479. }
  1480. #ifdef LEMMAUSEOMP
  1481. #pragma omp section
  1482. #endif
  1483. {
  1484. for (int ib=0; ib<nblocks; ++ib) {
  1485. //HiSegments(ib) = x.segment(ib*block, block).sum();
  1486. Y1.segment(ib*block, block) = VectorXr::Ones(block).array() /
  1487. (maxVal - x.segment(ib*block, block).sum());
  1488. }
  1489. //for (int ix=0; ix<x.size(); ++ix) {
  1490. // Y1(ix) = 1./( (maxVal-HiSegments(ib)) );
  1491. //}
  1492. //Y1 = VectorXr::Ones(N).array() / (maxVal-x.array()) ;
  1493. }
  1494. #ifdef LEMMAUSEOMP
  1495. #pragma omp section
  1496. #endif
  1497. {
  1498. X2 = VectorXr::Ones(N).array() / ((x.array()-minVal)*(x.array()-minVal));
  1499. }
  1500. #ifdef LEMMAUSEOMP
  1501. #pragma omp section
  1502. #endif
  1503. {
  1504. for (int ib=0; ib<nblocks; ++ib) {
  1505. //HiSegments(ib) = x.segment( ib*block, block ).sum();
  1506. Y2.segment(ib*block, block) = VectorXr::Ones(block).array() /
  1507. ( (maxVal-x.segment(ib*block, block).sum()) *
  1508. (maxVal-x.segment(ib*block, block).sum()) );
  1509. }
  1510. //Y2 = VectorXr::Ones(N).array() / ((maxVal-x.array())*(maxVal-x.array()));
  1511. //std::cout << Y1.transpose() << std::endl << std::endl;
  1512. //std::cout << Y2.transpose() << std::endl;
  1513. }
  1514. #ifdef LEMMAUSEOMP
  1515. } // parallel sections
  1516. #endif
  1517. #ifdef LEMMAUSEOMP
  1518. #pragma omp parallel sections
  1519. {
  1520. #endif
  1521. #ifdef LEMMAUSEOMP
  1522. #pragma omp section
  1523. #endif
  1524. {
  1525. b2 = -(A.transpose()*(b_pre-b)).array() -
  1526. (WmT_Wm.array()*x.array()).array() +
  1527. (2.*mux)*X1.array() + (2.*muy)*Y1.array();
  1528. }
  1529. #ifdef LEMMAUSEOMP
  1530. #pragma omp section
  1531. #endif
  1532. {
  1533. A2 = ATA;
  1534. A2.diagonal().array() += WmT_Wm.array() + mux*X2.array() +
  1535. muy*Y2.array();
  1536. }
  1537. #ifdef LEMMAUSEOMP
  1538. } // parallel sections
  1539. #endif
  1540. // // Jacobi Preconditioner
  1541. // Eigen::SparseMatrix<Scalar> MM =
  1542. // Eigen::SparseMatrix<Scalar>(A2.rows(), A2.cols());
  1543. // for (int i=0; i<ATA.rows(); ++i) {
  1544. // MM.insert(i,i) = 1./ATA(i,i);
  1545. // }
  1546. // MM.finalize();
  1547. /////////////////////////////////////////////////////////////
  1548. // Solve system,
  1549. // CG solution of complete system
  1550. // TODO add reference model
  1551. tol = 1e-5*phid+mux+muy;// 1e-14;
  1552. iter = N*M;
  1553. //std::cout << "Call cg" << std::endl;
  1554. // Decomposition preconditioner
  1555. //Pre.setThreshold(1e1*tol);
  1556. //Pre.compute(A2);
  1557. // Jacobi Preconditioner
  1558. //VectorXr ztilde = CG(A2, VectorXr::Zero(N), b2, MM, iter, tol);
  1559. // Decomposition preconditioner
  1560. //VectorXr ztilde = CG(A2, VectorXr::Zero(N), b2, Pre, iter, tol);
  1561. // No preconditioner
  1562. VectorXr ztilde = CG(A2, VectorXr::Zero(N), b2, iter, tol);
  1563. //std::cout << "out cg" << std::endl;
  1564. /////////////////////////////////////////////////////////////
  1565. // update x, mux, muy
  1566. //VectorXr h = ztilde; // - x;
  1567. VectorXr s1, s2;
  1568. // update x
  1569. //VectorXr h = ztilde; // - x;
  1570. //Scalar d = std::min(1., 0.995*(x.array()/h.array().abs()).minCoeff() );
  1571. //x += d*h;
  1572. Scalar d = std::min(1.,0.995*(x.array()/ztilde.array().abs()).minCoeff());
  1573. x += d*ztilde;
  1574. // // Fix any overstepping
  1575. // for (int ib=0; ib<nblocks; ++ib) {
  1576. // while (x.segment(ib*block, block).sum() > maxVal) {
  1577. // x.segment(ib*block, block).array() *= (.9);
  1578. // }
  1579. // }
  1580. // for (int i=0; i<x.size(); ++i) {
  1581. // if (x(i) < minVal) {
  1582. // x(i) = minVal + delta;
  1583. // }
  1584. // }
  1585. b_pre = A*x;
  1586. #ifdef LEMMAUSEOMP
  1587. #pragma omp parallel sections
  1588. {
  1589. #endif
  1590. #ifdef LEMMAUSEOMP
  1591. #pragma omp section
  1592. #endif
  1593. {
  1594. phib = PhiB2(mux, muy, minVal, maxVal, x, block, nblocks);
  1595. }
  1596. #ifdef LEMMAUSEOMP
  1597. #pragma omp section
  1598. #endif
  1599. {
  1600. phid = (b - (b_pre)).norm();
  1601. }
  1602. #ifdef LEMMAUSEOMP
  1603. #pragma omp section
  1604. #endif
  1605. {
  1606. phim = x.norm();
  1607. }
  1608. #ifdef LEMMAUSEOMP
  1609. }
  1610. #endif
  1611. // Determine mu steps to take
  1612. #ifdef LEMMAUSEOMP
  1613. #pragma omp parallel sections
  1614. {
  1615. #endif
  1616. #ifdef LEMMAUSEOMP
  1617. #pragma omp section
  1618. #endif
  1619. {
  1620. s1 = mux * (X2.asDiagonal()*(x+ztilde) - 2.*X1);
  1621. mux = SIGMA/((Scalar)(N)) * std::abs( s1.dot(x) ) ;
  1622. }
  1623. #ifdef LEMMAUSEOMP
  1624. #pragma omp section
  1625. #endif
  1626. {
  1627. s2 = muy * (Y2.asDiagonal()*(x+ztilde) - 2.*Y1);
  1628. muy = SIGMA/((Scalar)(N)) * std::abs( s2.dot(x) ) ;
  1629. }
  1630. #ifdef LEMMAUSEOMP
  1631. }
  1632. #endif
  1633. ++iloop;
  1634. } while (std::abs(phib / (phid+lambda*phim)) > epsilon);
  1635. // report
  1636. phireport.precision(12);
  1637. std::cout << ii << "\t" << x.norm() << "\t" << (b-(A*x)).norm()
  1638. << "\t" << lambda << "\t" << mux << "\t" << muy << "\t"
  1639. << iter << "\t" << iloop << std::endl;
  1640. phireport << ii << "\t" << x.norm() << "\t" << (b-(A*x)).norm()
  1641. << "\t" << lambda << "\t" << mux << "\t" << muy << "\t"
  1642. << iter << "\t" << iloop << std::endl;
  1643. std::fstream modfile;
  1644. std::string fname = "iteration" + to_string(ii) + ".dat";
  1645. modfile.open( fname.c_str(), std::ios::out);
  1646. modfile << ii << "\t" << x.norm() << "\t" << (b-(A*x)).norm()
  1647. << "\t" << lambda << "\t" << mux << "\t" << muy << "\t" << iter << "\n";
  1648. modfile << x << "\n";
  1649. modfile.close();
  1650. // write predicted data file
  1651. std::fstream predata;
  1652. fname = "iteration" + to_string(ii) + "pre.dat";
  1653. predata.open(fname.c_str(), std::ios::out);
  1654. predata << b_pre << std::endl;
  1655. predata.close();
  1656. // update lambda
  1657. // @todo smarter lambda change
  1658. lambda *= .85;
  1659. }
  1660. phireport.close();
  1661. // TODO, determine optimal solution
  1662. return x;
  1663. }
  1664. }
  1665. #endif // ----- #ifndef LOGBARRIERCG_INC -----