QuadProg++.cpp 22 KB

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