QuadProg++.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853
  1. /*
  2. Author: Luca Di Gaspero
  3. DIEGM - University of Udine, Italy
  4. l.digaspero@uniud.it
  5. http://www.diegm.uniud.it/digaspero/
  6. LICENSE
  7. This file is part of QuadProg++: a C++ library implementing
  8. the algorithm of Goldfarb and Idnani for the solution of a (convex)
  9. Quadratic Programming problem by means of an active-set dual method.
  10. Copyright (C) 2007-2009 Luca Di Gaspero.
  11. Copyright (C) 2009 Eric Moyer.
  12. QuadProg++ is free software: you can redistribute it and/or modify
  13. it under the terms of the GNU Lesser General Public License as published by
  14. the Free Software Foundation, either version 3 of the License, or
  15. (at your option) any later version.
  16. QuadProg++ is distributed in the hope that it will be useful,
  17. but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. GNU Lesser General Public License for more details.
  20. You should have received a copy of the GNU Lesser General Public License
  21. along with QuadProg++. If not, see <http://www.gnu.org/licenses/>.
  22. */
  23. #include <iostream>
  24. #include <algorithm>
  25. #include <cmath>
  26. #include <limits>
  27. #include <sstream>
  28. #include <stdexcept>
  29. #include "vislearning/optimization/quadprog/QuadProg++.h"
  30. #include "core/algebra/CholeskyRobustAuto.h"
  31. #include "core/algebra/CholeskyRobust.h"
  32. //#define TRACE_SOLVER
  33. namespace QuadProgPP{
  34. // Utility functions for updating some data needed by the solution method
  35. void compute_d(Vector<double>& d, const Matrix<double>& J, const Vector<double>& np);
  36. void update_z(Vector<double>& z, const Matrix<double>& J, const Vector<double>& d, int iq);
  37. void update_r(const Matrix<double>& R, Vector<double>& r, const Vector<double>& d, int iq);
  38. bool add_constraint(Matrix<double>& R, Matrix<double>& J, Vector<double>& d, int& iq, double& rnorm);
  39. void delete_constraint(Matrix<double>& R, Matrix<double>& J, Vector<int>& A, Vector<double>& u, int n, int p, int& iq, int l);
  40. // Utility functions for computing the Cholesky decomposition and solving
  41. // linear systems
  42. void cholesky_decomposition(Matrix<double>& A);
  43. void cholesky_solve(const Matrix<double>& L, Vector<double>& x, const Vector<double>& b);
  44. void forward_elimination(const Matrix<double>& L, Vector<double>& y, const Vector<double>& b);
  45. void backward_elimination(const Matrix<double>& U, Vector<double>& x, const Vector<double>& y);
  46. // Utility functions for computing the scalar product and the euclidean
  47. // distance between two numbers
  48. double scalar_product(const Vector<double>& x, const Vector<double>& y);
  49. double distance(double a, double b);
  50. // Utility functions for printing vectors and matrices
  51. void print_matrix(const char* name, const Matrix<double>& A, int n = -1, int m = -1);
  52. template<typename T>
  53. void print_vector(const char* name, const Vector<T>& v, int n = -1);
  54. // The Solving function, implementing the Goldfarb-Idnani method
  55. double solve_quadprog(Matrix<double>& G, Vector<double>& g0,
  56. const Matrix<double>& CE, const Vector<double>& ce0,
  57. const Matrix<double>& CI, const Vector<double>& ci0,
  58. Vector<double>& x)
  59. {
  60. std::ostringstream msg;
  61. {
  62. //Ensure that the dimensions of the matrices and vectors can be
  63. //safely converted from unsigned int into to int without overflow.
  64. unsigned mx = std::numeric_limits<int>::max();
  65. if(G.ncols() >= mx || G.nrows() >= mx ||
  66. CE.nrows() >= mx || CE.ncols() >= mx ||
  67. CI.nrows() >= mx || CI.ncols() >= mx ||
  68. ci0.size() >= mx || ce0.size() >= mx || g0.size() >= mx){
  69. msg << "The dimensions of one of the input matrices or vectors were "
  70. << "too large." << std::endl
  71. << "The maximum allowable size for inputs to solve_quadprog is:"
  72. << mx << std::endl;
  73. throw std::logic_error(msg.str());
  74. }
  75. }
  76. int n = G.ncols(), p = CE.ncols(), m = CI.ncols();
  77. if ((int)G.nrows() != n)
  78. {
  79. msg << "The matrix G is not a square matrix (" << G.nrows() << " x "
  80. << G.ncols() << ")";
  81. throw std::logic_error(msg.str());
  82. }
  83. if ((int)CE.nrows() != n)
  84. {
  85. msg << "The matrix CE is incompatible (incorrect number of rows "
  86. << CE.nrows() << " , expecting " << n << ")";
  87. throw std::logic_error(msg.str());
  88. }
  89. if ((int)ce0.size() != p)
  90. {
  91. msg << "The vector ce0 is incompatible (incorrect dimension "
  92. << ce0.size() << ", expecting " << p << ")";
  93. throw std::logic_error(msg.str());
  94. }
  95. if ((int)CI.nrows() != n)
  96. {
  97. msg << "The matrix CI is incompatible (incorrect number of rows "
  98. << CI.nrows() << " , expecting " << n << ")";
  99. throw std::logic_error(msg.str());
  100. }
  101. if ((int)ci0.size() != m)
  102. {
  103. msg << "The vector ci0 is incompatible (incorrect dimension "
  104. << ci0.size() << ", expecting " << m << ")";
  105. throw std::logic_error(msg.str());
  106. }
  107. x.resize(n);
  108. register int i, j, k, l; /* indices */
  109. int ip; // this is the index of the constraint to be added to the active set
  110. Matrix<double> R(n, n), J(n, n);
  111. Vector<double> s(m + p), z(n), r(m + p), d(n), np(n), u(m + p), x_old(n), u_old(m + p);
  112. double f_value, psi, c1, c2, sum, ss, R_norm;
  113. double inf;
  114. if (std::numeric_limits<double>::has_infinity)
  115. inf = std::numeric_limits<double>::infinity();
  116. else
  117. inf = 1.0E300;
  118. double t, t1, t2; /* t is the step lenght, which is the minimum of the partial step length t1
  119. * and the full step length t2 */
  120. Vector<int> A(m + p), A_old(m + p), iai(m + p);
  121. int q, iq, iter = 0;
  122. Vector<bool> iaexcl(m + p);
  123. /* p is the number of equality constraints */
  124. /* m is the number of inequality constraints */
  125. q = 0; /* size of the active set A (containing the indices of the active constraints) */
  126. #ifdef TRACE_SOLVER
  127. std::cout << std::endl << "Starting solve_quadprog" << std::endl;
  128. print_matrix("G", G);
  129. print_vector("g0", g0);
  130. print_matrix("CE", CE);
  131. print_vector("ce0", ce0);
  132. print_matrix("CI", CI);
  133. print_vector("ci0", ci0);
  134. #endif
  135. /*
  136. * Preprocessing phase
  137. */
  138. /* compute the trace of the original matrix G */
  139. c1 = 0.0;
  140. for (i = 0; i < n; i++)
  141. {
  142. c1 += G[i][i];
  143. }
  144. /* decompose the matrix G in the form L^T L */
  145. cholesky_decomposition(G);
  146. #ifdef TRACE_SOLVER
  147. print_matrix("G", G);
  148. #endif
  149. /* initialize the matrix R */
  150. for (i = 0; i < n; i++)
  151. {
  152. d[i] = 0.0;
  153. for (j = 0; j < n; j++)
  154. R[i][j] = 0.0;
  155. }
  156. R_norm = 1.0; /* this variable will hold the norm of the matrix R */
  157. /* compute the inverse of the factorized matrix G^-1, this is the initial value for H */
  158. c2 = 0.0;
  159. for (i = 0; i < n; i++)
  160. {
  161. d[i] = 1.0;
  162. forward_elimination(G, z, d);
  163. for (j = 0; j < n; j++)
  164. J[i][j] = z[j];
  165. c2 += z[i];
  166. d[i] = 0.0;
  167. }
  168. #ifdef TRACE_SOLVER
  169. print_matrix("J", J);
  170. #endif
  171. /* c1 * c2 is an estimate for cond(G) */
  172. /*
  173. * Find the unconstrained minimizer of the quadratic form 0.5 * x G x + g0 x
  174. * this is a feasible point in the dual space
  175. * x = G^-1 * g0
  176. */
  177. cholesky_solve(G, x, g0);
  178. for (i = 0; i < n; i++)
  179. x[i] = -x[i];
  180. /* and compute the current solution value */
  181. f_value = 0.5 * scalar_product(g0, x);
  182. #ifdef TRACE_SOLVER
  183. std::cout << "Unconstrained solution: " << f_value << std::endl;
  184. print_vector("x", x);
  185. #endif
  186. /* Add equality constraints to the working set A */
  187. iq = 0;
  188. for (i = 0; i < p; i++)
  189. {
  190. for (j = 0; j < n; j++)
  191. np[j] = CE[j][i];
  192. compute_d(d, J, np);
  193. update_z(z, J, d, iq);
  194. update_r(R, r, d, iq);
  195. #ifdef TRACE_SOLVER
  196. print_matrix("R", R, n, iq);
  197. print_vector("z", z);
  198. print_vector("r", r, iq);
  199. print_vector("d", d);
  200. #endif
  201. /* compute full step length t2: i.e., the minimum step in primal space s.t. the contraint
  202. becomes feasible */
  203. t2 = 0.0;
  204. if (fabs(scalar_product(z, z)) > std::numeric_limits<double>::epsilon()) // i.e. z != 0
  205. t2 = (-scalar_product(np, x) - ce0[i]) / scalar_product(z, np);
  206. /* set x = x + t2 * z */
  207. for (k = 0; k < n; k++)
  208. x[k] += t2 * z[k];
  209. /* set u = u+ */
  210. u[iq] = t2;
  211. for (k = 0; k < iq; k++)
  212. u[k] -= t2 * r[k];
  213. /* compute the new solution value */
  214. f_value += 0.5 * (t2 * t2) * scalar_product(z, np);
  215. A[i] = -i - 1;
  216. if (!add_constraint(R, J, d, iq, R_norm))
  217. {
  218. // Equality constraints are linearly dependent
  219. throw std::runtime_error("Constraints are linearly dependent");
  220. return f_value;
  221. }
  222. }
  223. /* set iai = K \ A */
  224. for (i = 0; i < m; i++)
  225. iai[i] = i;
  226. l1: iter++;
  227. #ifdef TRACE_SOLVER
  228. print_vector("x", x);
  229. #endif
  230. /* step 1: choose a violated constraint */
  231. for (i = p; i < iq; i++)
  232. {
  233. ip = A[i];
  234. iai[ip] = -1;
  235. }
  236. /* compute s[x] = ci^T * x + ci0 for all elements of K \ A */
  237. ss = 0.0;
  238. psi = 0.0; /* this value will contain the sum of all infeasibilities */
  239. ip = 0; /* ip will be the index of the chosen violated constraint */
  240. for (i = 0; i < m; i++)
  241. {
  242. iaexcl[i] = true;
  243. sum = 0.0;
  244. for (j = 0; j < n; j++)
  245. sum += CI[j][i] * x[j];
  246. sum += ci0[i];
  247. s[i] = sum;
  248. psi += std::min(0.0, sum);
  249. }
  250. #ifdef TRACE_SOLVER
  251. print_vector("s", s, m);
  252. #endif
  253. if (fabs(psi) <= m * std::numeric_limits<double>::epsilon() * c1 * c2* 100.0)
  254. {
  255. /* numerically there are not infeasibilities anymore */
  256. q = iq;
  257. return f_value;
  258. }
  259. /* save old values for u and A */
  260. for (i = 0; i < iq; i++)
  261. {
  262. u_old[i] = u[i];
  263. A_old[i] = A[i];
  264. }
  265. /* and for x */
  266. for (i = 0; i < n; i++)
  267. x_old[i] = x[i];
  268. l2: /* Step 2: check for feasibility and determine a new S-pair */
  269. for (i = 0; i < m; i++)
  270. {
  271. if (s[i] < ss && iai[i] != -1 && iaexcl[i])
  272. {
  273. ss = s[i];
  274. ip = i;
  275. }
  276. }
  277. if (ss >= 0.0)
  278. {
  279. q = iq;
  280. return f_value;
  281. }
  282. /* set np = n[ip] */
  283. for (i = 0; i < n; i++)
  284. np[i] = CI[i][ip];
  285. /* set u = [u 0]^T */
  286. u[iq] = 0.0;
  287. /* add ip to the active set A */
  288. A[iq] = ip;
  289. #ifdef TRACE_SOLVER
  290. std::cout << "Trying with constraint " << ip << std::endl;
  291. print_vector("np", np);
  292. #endif
  293. l2a:/* Step 2a: determine step direction */
  294. /* compute z = H np: the step direction in the primal space (through J, see the paper) */
  295. compute_d(d, J, np);
  296. update_z(z, J, d, iq);
  297. /* compute N* np (if q > 0): the negative of the step direction in the dual space */
  298. update_r(R, r, d, iq);
  299. #ifdef TRACE_SOLVER
  300. std::cout << "Step direction z" << std::endl;
  301. print_vector("z", z);
  302. print_vector("r", r, iq + 1);
  303. print_vector("u", u, iq + 1);
  304. print_vector("d", d);
  305. print_vector("A", A, iq + 1);
  306. #endif
  307. /* Step 2b: compute step length */
  308. l = 0;
  309. /* Compute t1: partial step length (maximum step in dual space without violating dual feasibility */
  310. t1 = inf; /* +inf */
  311. /* find the index l s.t. it reaches the minimum of u+[x] / r */
  312. for (k = p; k < iq; k++)
  313. {
  314. if (r[k] > 0.0)
  315. {
  316. if (u[k] / r[k] < t1)
  317. {
  318. t1 = u[k] / r[k];
  319. l = A[k];
  320. }
  321. }
  322. }
  323. /* Compute t2: full step length (minimum step in primal space such that the constraint ip becomes feasible */
  324. if (fabs(scalar_product(z, z)) > std::numeric_limits<double>::epsilon()) // i.e. z != 0
  325. t2 = -s[ip] / scalar_product(z, np);
  326. else
  327. t2 = inf; /* +inf */
  328. /* the step is chosen as the minimum of t1 and t2 */
  329. t = std::min(t1, t2);
  330. #ifdef TRACE_SOLVER
  331. std::cout << "Step sizes: " << t << " (t1 = " << t1 << ", t2 = " << t2 << ") ";
  332. #endif
  333. /* Step 2c: determine new S-pair and take step: */
  334. /* case (i): no step in primal or dual space */
  335. if (t >= inf)
  336. {
  337. /* QPP is infeasible */
  338. // FIXME: unbounded to raise
  339. q = iq;
  340. return inf;
  341. }
  342. /* case (ii): step in dual space */
  343. if (t2 >= inf)
  344. {
  345. /* set u = u + t * [-r 1] and drop constraint l from the active set A */
  346. for (k = 0; k < iq; k++)
  347. u[k] -= t * r[k];
  348. u[iq] += t;
  349. iai[l] = l;
  350. delete_constraint(R, J, A, u, n, p, iq, l);
  351. #ifdef TRACE_SOLVER
  352. std::cout << " in dual space: "
  353. << f_value << std::endl;
  354. print_vector("x", x);
  355. print_vector("z", z);
  356. print_vector("A", A, iq + 1);
  357. #endif
  358. goto l2a;
  359. }
  360. /* case (iii): step in primal and dual space */
  361. /* set x = x + t * z */
  362. for (k = 0; k < n; k++)
  363. x[k] += t * z[k];
  364. /* update the solution value */
  365. f_value += t * scalar_product(z, np) * (0.5 * t + u[iq]);
  366. /* u = u + t * [-r 1] */
  367. for (k = 0; k < iq; k++)
  368. u[k] -= t * r[k];
  369. u[iq] += t;
  370. #ifdef TRACE_SOLVER
  371. std::cout << " in both spaces: "
  372. << f_value << std::endl;
  373. print_vector("x", x);
  374. print_vector("u", u, iq + 1);
  375. print_vector("r", r, iq + 1);
  376. print_vector("A", A, iq + 1);
  377. #endif
  378. if (fabs(t - t2) < std::numeric_limits<double>::epsilon())
  379. {
  380. #ifdef TRACE_SOLVER
  381. std::cout << "Full step has taken " << t << std::endl;
  382. print_vector("x", x);
  383. #endif
  384. /* full step has taken */
  385. /* add constraint ip to the active set*/
  386. if (!add_constraint(R, J, d, iq, R_norm))
  387. {
  388. iaexcl[ip] = false;
  389. delete_constraint(R, J, A, u, n, p, iq, ip);
  390. #ifdef TRACE_SOLVER
  391. print_matrix("R", R);
  392. print_vector("A", A, iq);
  393. print_vector("iai", iai);
  394. #endif
  395. for (i = 0; i < m; i++)
  396. iai[i] = i;
  397. for (i = p; i < iq; i++)
  398. {
  399. A[i] = A_old[i];
  400. u[i] = u_old[i];
  401. iai[A[i]] = -1;
  402. }
  403. for (i = 0; i < n; i++)
  404. x[i] = x_old[i];
  405. goto l2; /* go to step 2 */
  406. }
  407. else
  408. iai[ip] = -1;
  409. #ifdef TRACE_SOLVER
  410. print_matrix("R", R);
  411. print_vector("A", A, iq);
  412. print_vector("iai", iai);
  413. #endif
  414. goto l1;
  415. }
  416. /* a patial step has taken */
  417. #ifdef TRACE_SOLVER
  418. std::cout << "Partial step has taken " << t << std::endl;
  419. print_vector("x", x);
  420. #endif
  421. /* drop constraint l */
  422. iai[l] = l;
  423. delete_constraint(R, J, A, u, n, p, iq, l);
  424. #ifdef TRACE_SOLVER
  425. print_matrix("R", R);
  426. print_vector("A", A, iq);
  427. #endif
  428. /* update s[ip] = CI * x + ci0 */
  429. sum = 0.0;
  430. for (k = 0; k < n; k++)
  431. sum += CI[k][ip] * x[k];
  432. s[ip] = sum + ci0[ip];
  433. #ifdef TRACE_SOLVER
  434. print_vector("s", s, m);
  435. #endif
  436. goto l2a;
  437. }
  438. inline void compute_d(Vector<double>& d, const Matrix<double>& J, const Vector<double>& np)
  439. {
  440. register int i, j, n = d.size();
  441. register double sum;
  442. /* compute d = H^T * np */
  443. for (i = 0; i < n; i++)
  444. {
  445. sum = 0.0;
  446. for (j = 0; j < n; j++)
  447. sum += J[j][i] * np[j];
  448. d[i] = sum;
  449. }
  450. }
  451. inline void update_z(Vector<double>& z, const Matrix<double>& J, const Vector<double>& d, int iq)
  452. {
  453. register int i, j, n = z.size();
  454. /* setting of z = H * d */
  455. for (i = 0; i < n; i++)
  456. {
  457. z[i] = 0.0;
  458. for (j = iq; j < n; j++)
  459. z[i] += J[i][j] * d[j];
  460. }
  461. }
  462. inline void update_r(const Matrix<double>& R, Vector<double>& r, const Vector<double>& d, int iq)
  463. {
  464. register int i, j;/*, n = d.size();*/
  465. register double sum;
  466. /* setting of r = R^-1 d */
  467. for (i = iq - 1; i >= 0; i--)
  468. {
  469. sum = 0.0;
  470. for (j = i + 1; j < iq; j++)
  471. sum += R[i][j] * r[j];
  472. r[i] = (d[i] - sum) / R[i][i];
  473. }
  474. }
  475. bool add_constraint(Matrix<double>& R, Matrix<double>& J, Vector<double>& d, int& iq, double& R_norm)
  476. {
  477. int n = d.size();
  478. #ifdef TRACE_SOLVER
  479. std::cout << "Add constraint " << iq << '/';
  480. #endif
  481. register int i, j, k;
  482. double cc, ss, h, t1, t2, xny;
  483. /* we have to find the Givens rotation which will reduce the element
  484. d[j] to zero.
  485. if it is already zero we don't have to do anything, except of
  486. decreasing j */
  487. for (j = n - 1; j >= iq + 1; j--)
  488. {
  489. /* The Givens rotation is done with the matrix (cc cs, cs -cc).
  490. If cc is one, then element (j) of d is zero compared with element
  491. (j - 1). Hence we don't have to do anything.
  492. If cc is zero, then we just have to switch column (j) and column (j - 1)
  493. of J. Since we only switch columns in J, we have to be careful how we
  494. update d depending on the sign of gs.
  495. Otherwise we have to apply the Givens rotation to these columns.
  496. The i - 1 element of d has to be updated to h. */
  497. cc = d[j - 1];
  498. ss = d[j];
  499. h = distance(cc, ss);
  500. if (fabs(h) < std::numeric_limits<double>::epsilon()) // h == 0
  501. continue;
  502. d[j] = 0.0;
  503. ss = ss / h;
  504. cc = cc / h;
  505. if (cc < 0.0)
  506. {
  507. cc = -cc;
  508. ss = -ss;
  509. d[j - 1] = -h;
  510. }
  511. else
  512. d[j - 1] = h;
  513. xny = ss / (1.0 + cc);
  514. for (k = 0; k < n; k++)
  515. {
  516. t1 = J[k][j - 1];
  517. t2 = J[k][j];
  518. J[k][j - 1] = t1 * cc + t2 * ss;
  519. J[k][j] = xny * (t1 + J[k][j - 1]) - t2;
  520. }
  521. }
  522. /* update the number of constraints added*/
  523. iq++;
  524. /* To update R we have to put the iq components of the d vector
  525. into column iq - 1 of R
  526. */
  527. for (i = 0; i < iq; i++)
  528. R[i][iq - 1] = d[i];
  529. #ifdef TRACE_SOLVER
  530. std::cout << iq << std::endl;
  531. print_matrix("R", R, iq, iq);
  532. print_matrix("J", J);
  533. print_vector("d", d, iq);
  534. #endif
  535. if (fabs(d[iq - 1]) <= std::numeric_limits<double>::epsilon() * R_norm)
  536. {
  537. // problem degenerate
  538. return false;
  539. }
  540. R_norm = std::max<double>(R_norm, fabs(d[iq - 1]));
  541. return true;
  542. }
  543. void delete_constraint(Matrix<double>& R, Matrix<double>& J, Vector<int>& A, Vector<double>& u, int n, int p, int& iq, int l)
  544. {
  545. #ifdef TRACE_SOLVER
  546. std::cout << "Delete constraint " << l << ' ' << iq;
  547. #endif
  548. register int i, j, k, qq = -1; // just to prevent warnings from smart compilers
  549. double cc, ss, h, xny, t1, t2;
  550. /* Find the index qq for active constraint l to be removed */
  551. for (i = p; i < iq; i++)
  552. if (A[i] == l)
  553. {
  554. qq = i;
  555. break;
  556. }
  557. /* remove the constraint from the active set and the duals */
  558. for (i = qq; i < iq - 1; i++)
  559. {
  560. A[i] = A[i + 1];
  561. u[i] = u[i + 1];
  562. for (j = 0; j < n; j++)
  563. R[j][i] = R[j][i + 1];
  564. }
  565. A[iq - 1] = A[iq];
  566. u[iq - 1] = u[iq];
  567. A[iq] = 0;
  568. u[iq] = 0.0;
  569. for (j = 0; j < iq; j++)
  570. R[j][iq - 1] = 0.0;
  571. /* constraint has been fully removed */
  572. iq--;
  573. #ifdef TRACE_SOLVER
  574. std::cout << '/' << iq << std::endl;
  575. #endif
  576. if (iq == 0)
  577. return;
  578. for (j = qq; j < iq; j++)
  579. {
  580. cc = R[j][j];
  581. ss = R[j + 1][j];
  582. h = distance(cc, ss);
  583. if (fabs(h) < std::numeric_limits<double>::epsilon()) // h == 0
  584. continue;
  585. cc = cc / h;
  586. ss = ss / h;
  587. R[j + 1][j] = 0.0;
  588. if (cc < 0.0)
  589. {
  590. R[j][j] = -h;
  591. cc = -cc;
  592. ss = -ss;
  593. }
  594. else
  595. R[j][j] = h;
  596. xny = ss / (1.0 + cc);
  597. for (k = j + 1; k < iq; k++)
  598. {
  599. t1 = R[j][k];
  600. t2 = R[j + 1][k];
  601. R[j][k] = t1 * cc + t2 * ss;
  602. R[j + 1][k] = xny * (t1 + R[j][k]) - t2;
  603. }
  604. for (k = 0; k < n; k++)
  605. {
  606. t1 = J[k][j];
  607. t2 = J[k][j + 1];
  608. J[k][j] = t1 * cc + t2 * ss;
  609. J[k][j + 1] = xny * (J[k][j] + t1) - t2;
  610. }
  611. }
  612. }
  613. inline double distance(double a, double b)
  614. {
  615. register double a1, b1, t;
  616. a1 = fabs(a);
  617. b1 = fabs(b);
  618. if (a1 > b1)
  619. {
  620. t = (b1 / a1);
  621. return a1 * ::std::sqrt(1.0 + t * t);
  622. }
  623. else
  624. if (b1 > a1)
  625. {
  626. t = (a1 / b1);
  627. return b1 * ::std::sqrt(1.0 + t * t);
  628. }
  629. return a1 * ::std::sqrt(2.0);
  630. }
  631. inline double scalar_product(const Vector<double>& x, const Vector<double>& y)
  632. {
  633. register int i, n = x.size();
  634. register double sum;
  635. sum = 0.0;
  636. for (i = 0; i < n; i++)
  637. sum += x[i] * y[i];
  638. return sum;
  639. }
  640. void cholesky_decomposition(Matrix<double>& A)
  641. {
  642. register int n = A.nrows(),i,j;
  643. NICE::Matrix M;
  644. M.resize(n,n);
  645. //copy array to nice matrix
  646. for (i = 0; i < n; i++)
  647. {
  648. for (j = 0; j < n; j++)
  649. {
  650. M(n,n)= A[i][j];
  651. }
  652. }
  653. NICE::Matrix L;
  654. L.resize(n,n);
  655. NICE::CholeskyRobust *cra = new NICE::CholeskyRobustAuto(true);
  656. cra->robustChol ( M, L );
  657. //copy back
  658. for (i = 0; i < n; i++)
  659. {
  660. for (j = 0; j <= i; j++)
  661. {
  662. A[i][j]=L(i,j);
  663. A[j][i]=L(i,j);
  664. }
  665. }
  666. delete cra;
  667. /*
  668. register int i, j, k, n = A.nrows();
  669. register double sum;
  670. for (i = 0; i < n; i++)
  671. {
  672. for (j = i; j < n; j++)
  673. {
  674. sum = A[i][j];
  675. for (k = i - 1; k >= 0; k--)
  676. sum -= A[i][k]*A[j][k];
  677. if (i == j)
  678. {
  679. if (sum <= 0.0)
  680. {
  681. std::ostringstream os;
  682. // raise error
  683. print_matrix("A", A);
  684. os << "Error in cholesky decomposition, sum: " << sum;
  685. throw std::logic_error(os.str());
  686. exit(-1);
  687. }
  688. A[i][i] = ::std::sqrt(sum);
  689. }
  690. else
  691. A[j][i] = sum / A[i][i];
  692. }
  693. for (k = i + 1; k < n; k++)
  694. A[i][k] = A[k][i];
  695. }
  696. */
  697. }
  698. void cholesky_solve(const Matrix<double>& L, Vector<double>& x, const Vector<double>& b)
  699. {
  700. int n = L.nrows();
  701. Vector<double> y(n);
  702. /* Solve L * y = b */
  703. forward_elimination(L, y, b);
  704. /* Solve L^T * x = y */
  705. backward_elimination(L, x, y);
  706. }
  707. inline void forward_elimination(const Matrix<double>& L, Vector<double>& y, const Vector<double>& b)
  708. {
  709. register int i, j, n = L.nrows();
  710. y[0] = b[0] / L[0][0];
  711. for (i = 1; i < n; i++)
  712. {
  713. y[i] = b[i];
  714. for (j = 0; j < i; j++)
  715. y[i] -= L[i][j] * y[j];
  716. y[i] = y[i] / L[i][i];
  717. }
  718. }
  719. inline void backward_elimination(const Matrix<double>& U, Vector<double>& x, const Vector<double>& y)
  720. {
  721. register int i, j, n = U.nrows();
  722. x[n - 1] = y[n - 1] / U[n - 1][n - 1];
  723. for (i = n - 2; i >= 0; i--)
  724. {
  725. x[i] = y[i];
  726. for (j = i + 1; j < n; j++)
  727. x[i] -= U[i][j] * x[j];
  728. x[i] = x[i] / U[i][i];
  729. }
  730. }
  731. void print_matrix(const char* name, const Matrix<double>& A, int n, int m)
  732. {
  733. std::ostringstream s;
  734. std::string t;
  735. if (n == -1)
  736. n = A.nrows();
  737. if (m == -1)
  738. m = A.ncols();
  739. s << name << ": " << std::endl;
  740. for (int i = 0; i < n; i++)
  741. {
  742. s << " ";
  743. for (int j = 0; j < m; j++)
  744. s << A[i][j] << ", ";
  745. s << std::endl;
  746. }
  747. t = s.str();
  748. t = t.substr(0, t.size() - 3); // To remove the trailing space, comma and newline
  749. std::cout << t << std::endl;
  750. }
  751. template<typename T>
  752. void print_vector(const char* name, const Vector<T>& v, int n)
  753. {
  754. std::ostringstream s;
  755. std::string t;
  756. if (n == -1)
  757. n = v.size();
  758. s << name << ": " << std::endl << " ";
  759. for (int i = 0; i < n; i++)
  760. {
  761. s << v[i] << ", ";
  762. }
  763. t = s.str();
  764. t = t.substr(0, t.size() - 2); // To remove the trailing space and comma
  765. std::cout << t << std::endl;
  766. }
  767. }