glplux.c 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029
  1. /* glplux.c */
  2. /***********************************************************************
  3. * This code is part of GLPK (GNU Linear Programming Kit).
  4. *
  5. * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
  6. * 2009, 2010 Andrew Makhorin, Department for Applied Informatics,
  7. * Moscow Aviation Institute, Moscow, Russia. All rights reserved.
  8. * E-mail: <mao@gnu.org>.
  9. *
  10. * GLPK is free software: you can redistribute it and/or modify it
  11. * under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation, either version 3 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * GLPK is distributed in the hope that it will be useful, but WITHOUT
  16. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  17. * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  18. * License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with GLPK. If not, see <http://www.gnu.org/licenses/>.
  22. ***********************************************************************/
  23. #include "glplux.h"
  24. #define xfault xerror
  25. #define dmp_create_poolx(size) dmp_create_pool()
  26. /*----------------------------------------------------------------------
  27. // lux_create - create LU-factorization.
  28. //
  29. // SYNOPSIS
  30. //
  31. // #include "glplux.h"
  32. // LUX *lux_create(int n);
  33. //
  34. // DESCRIPTION
  35. //
  36. // The routine lux_create creates LU-factorization data structure for
  37. // a matrix of the order n. Initially the factorization corresponds to
  38. // the unity matrix (F = V = P = Q = I, so A = I).
  39. //
  40. // RETURNS
  41. //
  42. // The routine returns a pointer to the created LU-factorization data
  43. // structure, which represents the unity matrix of the order n. */
  44. LUX *lux_create(int n)
  45. { LUX *lux;
  46. int k;
  47. if (n < 1)
  48. xfault("lux_create: n = %d; invalid parameter\n", n);
  49. lux = xmalloc(sizeof(LUX));
  50. lux->n = n;
  51. lux->pool = dmp_create_poolx(sizeof(LUXELM));
  52. lux->F_row = xcalloc(1+n, sizeof(LUXELM *));
  53. lux->F_col = xcalloc(1+n, sizeof(LUXELM *));
  54. lux->V_piv = xcalloc(1+n, sizeof(mpq_t));
  55. lux->V_row = xcalloc(1+n, sizeof(LUXELM *));
  56. lux->V_col = xcalloc(1+n, sizeof(LUXELM *));
  57. lux->P_row = xcalloc(1+n, sizeof(int));
  58. lux->P_col = xcalloc(1+n, sizeof(int));
  59. lux->Q_row = xcalloc(1+n, sizeof(int));
  60. lux->Q_col = xcalloc(1+n, sizeof(int));
  61. for (k = 1; k <= n; k++)
  62. { lux->F_row[k] = lux->F_col[k] = NULL;
  63. mpq_init(lux->V_piv[k]);
  64. mpq_set_si(lux->V_piv[k], 1, 1);
  65. lux->V_row[k] = lux->V_col[k] = NULL;
  66. lux->P_row[k] = lux->P_col[k] = k;
  67. lux->Q_row[k] = lux->Q_col[k] = k;
  68. }
  69. lux->rank = n;
  70. return lux;
  71. }
  72. /*----------------------------------------------------------------------
  73. // initialize - initialize LU-factorization data structures.
  74. //
  75. // This routine initializes data structures for subsequent computing
  76. // the LU-factorization of a given matrix A, which is specified by the
  77. // formal routine col. On exit V = A and F = P = Q = I, where I is the
  78. // unity matrix. */
  79. static void initialize(LUX *lux, int (*col)(void *info, int j,
  80. int ind[], mpq_t val[]), void *info, LUXWKA *wka)
  81. { int n = lux->n;
  82. DMP *pool = lux->pool;
  83. LUXELM **F_row = lux->F_row;
  84. LUXELM **F_col = lux->F_col;
  85. mpq_t *V_piv = lux->V_piv;
  86. LUXELM **V_row = lux->V_row;
  87. LUXELM **V_col = lux->V_col;
  88. int *P_row = lux->P_row;
  89. int *P_col = lux->P_col;
  90. int *Q_row = lux->Q_row;
  91. int *Q_col = lux->Q_col;
  92. int *R_len = wka->R_len;
  93. int *R_head = wka->R_head;
  94. int *R_prev = wka->R_prev;
  95. int *R_next = wka->R_next;
  96. int *C_len = wka->C_len;
  97. int *C_head = wka->C_head;
  98. int *C_prev = wka->C_prev;
  99. int *C_next = wka->C_next;
  100. LUXELM *fij, *vij;
  101. int i, j, k, len, *ind;
  102. mpq_t *val;
  103. /* F := I */
  104. for (i = 1; i <= n; i++)
  105. { while (F_row[i] != NULL)
  106. { fij = F_row[i], F_row[i] = fij->r_next;
  107. mpq_clear(fij->val);
  108. dmp_free_atom(pool, fij, sizeof(LUXELM));
  109. }
  110. }
  111. for (j = 1; j <= n; j++) F_col[j] = NULL;
  112. /* V := 0 */
  113. for (k = 1; k <= n; k++) mpq_set_si(V_piv[k], 0, 1);
  114. for (i = 1; i <= n; i++)
  115. { while (V_row[i] != NULL)
  116. { vij = V_row[i], V_row[i] = vij->r_next;
  117. mpq_clear(vij->val);
  118. dmp_free_atom(pool, vij, sizeof(LUXELM));
  119. }
  120. }
  121. for (j = 1; j <= n; j++) V_col[j] = NULL;
  122. /* V := A */
  123. ind = xcalloc(1+n, sizeof(int));
  124. val = xcalloc(1+n, sizeof(mpq_t));
  125. for (k = 1; k <= n; k++) mpq_init(val[k]);
  126. for (j = 1; j <= n; j++)
  127. { /* obtain j-th column of matrix A */
  128. len = col(info, j, ind, val);
  129. if (!(0 <= len && len <= n))
  130. xfault("lux_decomp: j = %d: len = %d; invalid column length"
  131. "\n", j, len);
  132. /* copy elements of j-th column to matrix V */
  133. for (k = 1; k <= len; k++)
  134. { /* get row index of a[i,j] */
  135. i = ind[k];
  136. if (!(1 <= i && i <= n))
  137. xfault("lux_decomp: j = %d: i = %d; row index out of ran"
  138. "ge\n", j, i);
  139. /* check for duplicate indices */
  140. if (V_row[i] != NULL && V_row[i]->j == j)
  141. xfault("lux_decomp: j = %d: i = %d; duplicate row indice"
  142. "s not allowed\n", j, i);
  143. /* check for zero value */
  144. if (mpq_sgn(val[k]) == 0)
  145. xfault("lux_decomp: j = %d: i = %d; zero elements not al"
  146. "lowed\n", j, i);
  147. /* add new element v[i,j] = a[i,j] to V */
  148. vij = dmp_get_atom(pool, sizeof(LUXELM));
  149. vij->i = i, vij->j = j;
  150. mpq_init(vij->val);
  151. mpq_set(vij->val, val[k]);
  152. vij->r_prev = NULL;
  153. vij->r_next = V_row[i];
  154. vij->c_prev = NULL;
  155. vij->c_next = V_col[j];
  156. if (vij->r_next != NULL) vij->r_next->r_prev = vij;
  157. if (vij->c_next != NULL) vij->c_next->c_prev = vij;
  158. V_row[i] = V_col[j] = vij;
  159. }
  160. }
  161. xfree(ind);
  162. for (k = 1; k <= n; k++) mpq_clear(val[k]);
  163. xfree(val);
  164. /* P := Q := I */
  165. for (k = 1; k <= n; k++)
  166. P_row[k] = P_col[k] = Q_row[k] = Q_col[k] = k;
  167. /* the rank of A and V is not determined yet */
  168. lux->rank = -1;
  169. /* initially the entire matrix V is active */
  170. /* determine its row lengths */
  171. for (i = 1; i <= n; i++)
  172. { len = 0;
  173. for (vij = V_row[i]; vij != NULL; vij = vij->r_next) len++;
  174. R_len[i] = len;
  175. }
  176. /* build linked lists of active rows */
  177. for (len = 0; len <= n; len++) R_head[len] = 0;
  178. for (i = 1; i <= n; i++)
  179. { len = R_len[i];
  180. R_prev[i] = 0;
  181. R_next[i] = R_head[len];
  182. if (R_next[i] != 0) R_prev[R_next[i]] = i;
  183. R_head[len] = i;
  184. }
  185. /* determine its column lengths */
  186. for (j = 1; j <= n; j++)
  187. { len = 0;
  188. for (vij = V_col[j]; vij != NULL; vij = vij->c_next) len++;
  189. C_len[j] = len;
  190. }
  191. /* build linked lists of active columns */
  192. for (len = 0; len <= n; len++) C_head[len] = 0;
  193. for (j = 1; j <= n; j++)
  194. { len = C_len[j];
  195. C_prev[j] = 0;
  196. C_next[j] = C_head[len];
  197. if (C_next[j] != 0) C_prev[C_next[j]] = j;
  198. C_head[len] = j;
  199. }
  200. return;
  201. }
  202. /*----------------------------------------------------------------------
  203. // find_pivot - choose a pivot element.
  204. //
  205. // This routine chooses a pivot element v[p,q] in the active submatrix
  206. // of matrix U = P*V*Q.
  207. //
  208. // It is assumed that on entry the matrix U has the following partially
  209. // triangularized form:
  210. //
  211. // 1 k n
  212. // 1 x x x x x x x x x x
  213. // . x x x x x x x x x
  214. // . . x x x x x x x x
  215. // . . . x x x x x x x
  216. // k . . . . * * * * * *
  217. // . . . . * * * * * *
  218. // . . . . * * * * * *
  219. // . . . . * * * * * *
  220. // . . . . * * * * * *
  221. // n . . . . * * * * * *
  222. //
  223. // where rows and columns k, k+1, ..., n belong to the active submatrix
  224. // (elements of the active submatrix are marked by '*').
  225. //
  226. // Since the matrix U = P*V*Q is not stored, the routine works with the
  227. // matrix V. It is assumed that the row-wise representation corresponds
  228. // to the matrix V, but the column-wise representation corresponds to
  229. // the active submatrix of the matrix V, i.e. elements of the matrix V,
  230. // which does not belong to the active submatrix, are missing from the
  231. // column linked lists. It is also assumed that each active row of the
  232. // matrix V is in the set R[len], where len is number of non-zeros in
  233. // the row, and each active column of the matrix V is in the set C[len],
  234. // where len is number of non-zeros in the column (in the latter case
  235. // only elements of the active submatrix are counted; such elements are
  236. // marked by '*' on the figure above).
  237. //
  238. // Due to exact arithmetic any non-zero element of the active submatrix
  239. // can be chosen as a pivot. However, to keep sparsity of the matrix V
  240. // the routine uses Markowitz strategy, trying to choose such element
  241. // v[p,q], which has smallest Markowitz cost (nr[p]-1) * (nc[q]-1),
  242. // where nr[p] and nc[q] are the number of non-zero elements, resp., in
  243. // p-th row and in q-th column of the active submatrix.
  244. //
  245. // In order to reduce the search, i.e. not to walk through all elements
  246. // of the active submatrix, the routine exploits a technique proposed by
  247. // I.Duff. This technique is based on using the sets R[len] and C[len]
  248. // of active rows and columns.
  249. //
  250. // On exit the routine returns a pointer to a pivot v[p,q] chosen, or
  251. // NULL, if the active submatrix is empty. */
  252. static LUXELM *find_pivot(LUX *lux, LUXWKA *wka)
  253. { int n = lux->n;
  254. LUXELM **V_row = lux->V_row;
  255. LUXELM **V_col = lux->V_col;
  256. int *R_len = wka->R_len;
  257. int *R_head = wka->R_head;
  258. int *R_next = wka->R_next;
  259. int *C_len = wka->C_len;
  260. int *C_head = wka->C_head;
  261. int *C_next = wka->C_next;
  262. LUXELM *piv, *some, *vij;
  263. int i, j, len, min_len, ncand, piv_lim = 5;
  264. double best, cost;
  265. /* nothing is chosen so far */
  266. piv = NULL, best = DBL_MAX, ncand = 0;
  267. /* if in the active submatrix there is a column that has the only
  268. non-zero (column singleton), choose it as a pivot */
  269. j = C_head[1];
  270. if (j != 0)
  271. { xassert(C_len[j] == 1);
  272. piv = V_col[j];
  273. xassert(piv != NULL && piv->c_next == NULL);
  274. goto done;
  275. }
  276. /* if in the active submatrix there is a row that has the only
  277. non-zero (row singleton), choose it as a pivot */
  278. i = R_head[1];
  279. if (i != 0)
  280. { xassert(R_len[i] == 1);
  281. piv = V_row[i];
  282. xassert(piv != NULL && piv->r_next == NULL);
  283. goto done;
  284. }
  285. /* there are no singletons in the active submatrix; walk through
  286. other non-empty rows and columns */
  287. for (len = 2; len <= n; len++)
  288. { /* consider active columns having len non-zeros */
  289. for (j = C_head[len]; j != 0; j = C_next[j])
  290. { /* j-th column has len non-zeros */
  291. /* find an element in the row of minimal length */
  292. some = NULL, min_len = INT_MAX;
  293. for (vij = V_col[j]; vij != NULL; vij = vij->c_next)
  294. { if (min_len > R_len[vij->i])
  295. some = vij, min_len = R_len[vij->i];
  296. /* if Markowitz cost of this element is not greater than
  297. (len-1)**2, it can be chosen right now; this heuristic
  298. reduces the search and works well in many cases */
  299. if (min_len <= len)
  300. { piv = some;
  301. goto done;
  302. }
  303. }
  304. /* j-th column has been scanned */
  305. /* the minimal element found is a next pivot candidate */
  306. xassert(some != NULL);
  307. ncand++;
  308. /* compute its Markowitz cost */
  309. cost = (double)(min_len - 1) * (double)(len - 1);
  310. /* choose between the current candidate and this element */
  311. if (cost < best) piv = some, best = cost;
  312. /* if piv_lim candidates have been considered, there is a
  313. doubt that a much better candidate exists; therefore it
  314. is the time to terminate the search */
  315. if (ncand == piv_lim) goto done;
  316. }
  317. /* now consider active rows having len non-zeros */
  318. for (i = R_head[len]; i != 0; i = R_next[i])
  319. { /* i-th row has len non-zeros */
  320. /* find an element in the column of minimal length */
  321. some = NULL, min_len = INT_MAX;
  322. for (vij = V_row[i]; vij != NULL; vij = vij->r_next)
  323. { if (min_len > C_len[vij->j])
  324. some = vij, min_len = C_len[vij->j];
  325. /* if Markowitz cost of this element is not greater than
  326. (len-1)**2, it can be chosen right now; this heuristic
  327. reduces the search and works well in many cases */
  328. if (min_len <= len)
  329. { piv = some;
  330. goto done;
  331. }
  332. }
  333. /* i-th row has been scanned */
  334. /* the minimal element found is a next pivot candidate */
  335. xassert(some != NULL);
  336. ncand++;
  337. /* compute its Markowitz cost */
  338. cost = (double)(len - 1) * (double)(min_len - 1);
  339. /* choose between the current candidate and this element */
  340. if (cost < best) piv = some, best = cost;
  341. /* if piv_lim candidates have been considered, there is a
  342. doubt that a much better candidate exists; therefore it
  343. is the time to terminate the search */
  344. if (ncand == piv_lim) goto done;
  345. }
  346. }
  347. done: /* bring the pivot v[p,q] to the factorizing routine */
  348. return piv;
  349. }
  350. /*----------------------------------------------------------------------
  351. // eliminate - perform gaussian elimination.
  352. //
  353. // This routine performs elementary gaussian transformations in order
  354. // to eliminate subdiagonal elements in the k-th column of the matrix
  355. // U = P*V*Q using the pivot element u[k,k], where k is the number of
  356. // the current elimination step.
  357. //
  358. // The parameter piv specifies the pivot element v[p,q] = u[k,k].
  359. //
  360. // Each time when the routine applies the elementary transformation to
  361. // a non-pivot row of the matrix V, it stores the corresponding element
  362. // to the matrix F in order to keep the main equality A = F*V.
  363. //
  364. // The routine assumes that on entry the matrices L = P*F*inv(P) and
  365. // U = P*V*Q are the following:
  366. //
  367. // 1 k 1 k n
  368. // 1 1 . . . . . . . . . 1 x x x x x x x x x x
  369. // x 1 . . . . . . . . . x x x x x x x x x
  370. // x x 1 . . . . . . . . . x x x x x x x x
  371. // x x x 1 . . . . . . . . . x x x x x x x
  372. // k x x x x 1 . . . . . k . . . . * * * * * *
  373. // x x x x _ 1 . . . . . . . . # * * * * *
  374. // x x x x _ . 1 . . . . . . . # * * * * *
  375. // x x x x _ . . 1 . . . . . . # * * * * *
  376. // x x x x _ . . . 1 . . . . . # * * * * *
  377. // n x x x x _ . . . . 1 n . . . . # * * * * *
  378. //
  379. // matrix L matrix U
  380. //
  381. // where rows and columns of the matrix U with numbers k, k+1, ..., n
  382. // form the active submatrix (eliminated elements are marked by '#' and
  383. // other elements of the active submatrix are marked by '*'). Note that
  384. // each eliminated non-zero element u[i,k] of the matrix U gives the
  385. // corresponding element l[i,k] of the matrix L (marked by '_').
  386. //
  387. // Actually all operations are performed on the matrix V. Should note
  388. // that the row-wise representation corresponds to the matrix V, but the
  389. // column-wise representation corresponds to the active submatrix of the
  390. // matrix V, i.e. elements of the matrix V, which doesn't belong to the
  391. // active submatrix, are missing from the column linked lists.
  392. //
  393. // Let u[k,k] = v[p,q] be the pivot. In order to eliminate subdiagonal
  394. // elements u[i',k] = v[i,q], i' = k+1, k+2, ..., n, the routine applies
  395. // the following elementary gaussian transformations:
  396. //
  397. // (i-th row of V) := (i-th row of V) - f[i,p] * (p-th row of V),
  398. //
  399. // where f[i,p] = v[i,q] / v[p,q] is a gaussian multiplier.
  400. //
  401. // Additionally, in order to keep the main equality A = F*V, each time
  402. // when the routine applies the transformation to i-th row of the matrix
  403. // V, it also adds f[i,p] as a new element to the matrix F.
  404. //
  405. // IMPORTANT: On entry the working arrays flag and work should contain
  406. // zeros. This status is provided by the routine on exit. */
  407. static void eliminate(LUX *lux, LUXWKA *wka, LUXELM *piv, int flag[],
  408. mpq_t work[])
  409. { DMP *pool = lux->pool;
  410. LUXELM **F_row = lux->F_row;
  411. LUXELM **F_col = lux->F_col;
  412. mpq_t *V_piv = lux->V_piv;
  413. LUXELM **V_row = lux->V_row;
  414. LUXELM **V_col = lux->V_col;
  415. int *R_len = wka->R_len;
  416. int *R_head = wka->R_head;
  417. int *R_prev = wka->R_prev;
  418. int *R_next = wka->R_next;
  419. int *C_len = wka->C_len;
  420. int *C_head = wka->C_head;
  421. int *C_prev = wka->C_prev;
  422. int *C_next = wka->C_next;
  423. LUXELM *fip, *vij, *vpj, *viq, *next;
  424. mpq_t temp;
  425. int i, j, p, q;
  426. mpq_init(temp);
  427. /* determine row and column indices of the pivot v[p,q] */
  428. xassert(piv != NULL);
  429. p = piv->i, q = piv->j;
  430. /* remove p-th (pivot) row from the active set; it will never
  431. return there */
  432. if (R_prev[p] == 0)
  433. R_head[R_len[p]] = R_next[p];
  434. else
  435. R_next[R_prev[p]] = R_next[p];
  436. if (R_next[p] == 0)
  437. ;
  438. else
  439. R_prev[R_next[p]] = R_prev[p];
  440. /* remove q-th (pivot) column from the active set; it will never
  441. return there */
  442. if (C_prev[q] == 0)
  443. C_head[C_len[q]] = C_next[q];
  444. else
  445. C_next[C_prev[q]] = C_next[q];
  446. if (C_next[q] == 0)
  447. ;
  448. else
  449. C_prev[C_next[q]] = C_prev[q];
  450. /* store the pivot value in a separate array */
  451. mpq_set(V_piv[p], piv->val);
  452. /* remove the pivot from p-th row */
  453. if (piv->r_prev == NULL)
  454. V_row[p] = piv->r_next;
  455. else
  456. piv->r_prev->r_next = piv->r_next;
  457. if (piv->r_next == NULL)
  458. ;
  459. else
  460. piv->r_next->r_prev = piv->r_prev;
  461. R_len[p]--;
  462. /* remove the pivot from q-th column */
  463. if (piv->c_prev == NULL)
  464. V_col[q] = piv->c_next;
  465. else
  466. piv->c_prev->c_next = piv->c_next;
  467. if (piv->c_next == NULL)
  468. ;
  469. else
  470. piv->c_next->c_prev = piv->c_prev;
  471. C_len[q]--;
  472. /* free the space occupied by the pivot */
  473. mpq_clear(piv->val);
  474. dmp_free_atom(pool, piv, sizeof(LUXELM));
  475. /* walk through p-th (pivot) row, which already does not contain
  476. the pivot v[p,q], and do the following... */
  477. for (vpj = V_row[p]; vpj != NULL; vpj = vpj->r_next)
  478. { /* get column index of v[p,j] */
  479. j = vpj->j;
  480. /* store v[p,j] in the working array */
  481. flag[j] = 1;
  482. mpq_set(work[j], vpj->val);
  483. /* remove j-th column from the active set; it will return there
  484. later with a new length */
  485. if (C_prev[j] == 0)
  486. C_head[C_len[j]] = C_next[j];
  487. else
  488. C_next[C_prev[j]] = C_next[j];
  489. if (C_next[j] == 0)
  490. ;
  491. else
  492. C_prev[C_next[j]] = C_prev[j];
  493. /* v[p,j] leaves the active submatrix, so remove it from j-th
  494. column; however, v[p,j] is kept in p-th row */
  495. if (vpj->c_prev == NULL)
  496. V_col[j] = vpj->c_next;
  497. else
  498. vpj->c_prev->c_next = vpj->c_next;
  499. if (vpj->c_next == NULL)
  500. ;
  501. else
  502. vpj->c_next->c_prev = vpj->c_prev;
  503. C_len[j]--;
  504. }
  505. /* now walk through q-th (pivot) column, which already does not
  506. contain the pivot v[p,q], and perform gaussian elimination */
  507. while (V_col[q] != NULL)
  508. { /* element v[i,q] has to be eliminated */
  509. viq = V_col[q];
  510. /* get row index of v[i,q] */
  511. i = viq->i;
  512. /* remove i-th row from the active set; later it will return
  513. there with a new length */
  514. if (R_prev[i] == 0)
  515. R_head[R_len[i]] = R_next[i];
  516. else
  517. R_next[R_prev[i]] = R_next[i];
  518. if (R_next[i] == 0)
  519. ;
  520. else
  521. R_prev[R_next[i]] = R_prev[i];
  522. /* compute gaussian multiplier f[i,p] = v[i,q] / v[p,q] and
  523. store it in the matrix F */
  524. fip = dmp_get_atom(pool, sizeof(LUXELM));
  525. fip->i = i, fip->j = p;
  526. mpq_init(fip->val);
  527. mpq_div(fip->val, viq->val, V_piv[p]);
  528. fip->r_prev = NULL;
  529. fip->r_next = F_row[i];
  530. fip->c_prev = NULL;
  531. fip->c_next = F_col[p];
  532. if (fip->r_next != NULL) fip->r_next->r_prev = fip;
  533. if (fip->c_next != NULL) fip->c_next->c_prev = fip;
  534. F_row[i] = F_col[p] = fip;
  535. /* v[i,q] has to be eliminated, so remove it from i-th row */
  536. if (viq->r_prev == NULL)
  537. V_row[i] = viq->r_next;
  538. else
  539. viq->r_prev->r_next = viq->r_next;
  540. if (viq->r_next == NULL)
  541. ;
  542. else
  543. viq->r_next->r_prev = viq->r_prev;
  544. R_len[i]--;
  545. /* and also from q-th column */
  546. V_col[q] = viq->c_next;
  547. C_len[q]--;
  548. /* free the space occupied by v[i,q] */
  549. mpq_clear(viq->val);
  550. dmp_free_atom(pool, viq, sizeof(LUXELM));
  551. /* perform gaussian transformation:
  552. (i-th row) := (i-th row) - f[i,p] * (p-th row)
  553. note that now p-th row, which is in the working array,
  554. does not contain the pivot v[p,q], and i-th row does not
  555. contain the element v[i,q] to be eliminated */
  556. /* walk through i-th row and transform existing non-zero
  557. elements */
  558. for (vij = V_row[i]; vij != NULL; vij = next)
  559. { next = vij->r_next;
  560. /* get column index of v[i,j] */
  561. j = vij->j;
  562. /* v[i,j] := v[i,j] - f[i,p] * v[p,j] */
  563. if (flag[j])
  564. { /* v[p,j] != 0 */
  565. flag[j] = 0;
  566. mpq_mul(temp, fip->val, work[j]);
  567. mpq_sub(vij->val, vij->val, temp);
  568. if (mpq_sgn(vij->val) == 0)
  569. { /* new v[i,j] is zero, so remove it from the active
  570. submatrix */
  571. /* remove v[i,j] from i-th row */
  572. if (vij->r_prev == NULL)
  573. V_row[i] = vij->r_next;
  574. else
  575. vij->r_prev->r_next = vij->r_next;
  576. if (vij->r_next == NULL)
  577. ;
  578. else
  579. vij->r_next->r_prev = vij->r_prev;
  580. R_len[i]--;
  581. /* remove v[i,j] from j-th column */
  582. if (vij->c_prev == NULL)
  583. V_col[j] = vij->c_next;
  584. else
  585. vij->c_prev->c_next = vij->c_next;
  586. if (vij->c_next == NULL)
  587. ;
  588. else
  589. vij->c_next->c_prev = vij->c_prev;
  590. C_len[j]--;
  591. /* free the space occupied by v[i,j] */
  592. mpq_clear(vij->val);
  593. dmp_free_atom(pool, vij, sizeof(LUXELM));
  594. }
  595. }
  596. }
  597. /* now flag is the pattern of the set v[p,*] \ v[i,*] */
  598. /* walk through p-th (pivot) row and create new elements in
  599. i-th row, which appear due to fill-in */
  600. for (vpj = V_row[p]; vpj != NULL; vpj = vpj->r_next)
  601. { j = vpj->j;
  602. if (flag[j])
  603. { /* create new non-zero v[i,j] = 0 - f[i,p] * v[p,j] and
  604. add it to i-th row and j-th column */
  605. vij = dmp_get_atom(pool, sizeof(LUXELM));
  606. vij->i = i, vij->j = j;
  607. mpq_init(vij->val);
  608. mpq_mul(vij->val, fip->val, work[j]);
  609. mpq_neg(vij->val, vij->val);
  610. vij->r_prev = NULL;
  611. vij->r_next = V_row[i];
  612. vij->c_prev = NULL;
  613. vij->c_next = V_col[j];
  614. if (vij->r_next != NULL) vij->r_next->r_prev = vij;
  615. if (vij->c_next != NULL) vij->c_next->c_prev = vij;
  616. V_row[i] = V_col[j] = vij;
  617. R_len[i]++, C_len[j]++;
  618. }
  619. else
  620. { /* there is no fill-in, because v[i,j] already exists in
  621. i-th row; restore the flag, which was reset before */
  622. flag[j] = 1;
  623. }
  624. }
  625. /* now i-th row has been completely transformed and can return
  626. to the active set with a new length */
  627. R_prev[i] = 0;
  628. R_next[i] = R_head[R_len[i]];
  629. if (R_next[i] != 0) R_prev[R_next[i]] = i;
  630. R_head[R_len[i]] = i;
  631. }
  632. /* at this point q-th (pivot) column must be empty */
  633. xassert(C_len[q] == 0);
  634. /* walk through p-th (pivot) row again and do the following... */
  635. for (vpj = V_row[p]; vpj != NULL; vpj = vpj->r_next)
  636. { /* get column index of v[p,j] */
  637. j = vpj->j;
  638. /* erase v[p,j] from the working array */
  639. flag[j] = 0;
  640. mpq_set_si(work[j], 0, 1);
  641. /* now j-th column has been completely transformed, so it can
  642. return to the active list with a new length */
  643. C_prev[j] = 0;
  644. C_next[j] = C_head[C_len[j]];
  645. if (C_next[j] != 0) C_prev[C_next[j]] = j;
  646. C_head[C_len[j]] = j;
  647. }
  648. mpq_clear(temp);
  649. /* return to the factorizing routine */
  650. return;
  651. }
  652. /*----------------------------------------------------------------------
  653. // lux_decomp - compute LU-factorization.
  654. //
  655. // SYNOPSIS
  656. //
  657. // #include "glplux.h"
  658. // int lux_decomp(LUX *lux, int (*col)(void *info, int j, int ind[],
  659. // mpq_t val[]), void *info);
  660. //
  661. // DESCRIPTION
  662. //
  663. // The routine lux_decomp computes LU-factorization of a given square
  664. // matrix A.
  665. //
  666. // The parameter lux specifies LU-factorization data structure built by
  667. // means of the routine lux_create.
  668. //
  669. // The formal routine col specifies the original matrix A. In order to
  670. // obtain j-th column of the matrix A the routine lux_decomp calls the
  671. // routine col with the parameter j (1 <= j <= n, where n is the order
  672. // of A). In response the routine col should store row indices and
  673. // numerical values of non-zero elements of j-th column of A to the
  674. // locations ind[1], ..., ind[len] and val[1], ..., val[len], resp.,
  675. // where len is the number of non-zeros in j-th column, which should be
  676. // returned on exit. Neiter zero nor duplicate elements are allowed.
  677. //
  678. // The parameter info is a transit pointer passed to the formal routine
  679. // col; it can be used for various purposes.
  680. //
  681. // RETURNS
  682. //
  683. // The routine lux_decomp returns the singularity flag. Zero flag means
  684. // that the original matrix A is non-singular while non-zero flag means
  685. // that A is (exactly!) singular.
  686. //
  687. // Note that LU-factorization is valid in both cases, however, in case
  688. // of singularity some rows of the matrix V (including pivot elements)
  689. // will be empty.
  690. //
  691. // REPAIRING SINGULAR MATRIX
  692. //
  693. // If the routine lux_decomp returns non-zero flag, it provides all
  694. // necessary information that can be used for "repairing" the matrix A,
  695. // where "repairing" means replacing linearly dependent columns of the
  696. // matrix A by appropriate columns of the unity matrix. This feature is
  697. // needed when the routine lux_decomp is used for reinverting the basis
  698. // matrix within the simplex method procedure.
  699. //
  700. // On exit linearly dependent columns of the matrix U have the numbers
  701. // rank+1, rank+2, ..., n, where rank is the exact rank of the matrix A
  702. // stored by the routine to the member lux->rank. The correspondence
  703. // between columns of A and U is the same as between columns of V and U.
  704. // Thus, linearly dependent columns of the matrix A have the numbers
  705. // Q_col[rank+1], Q_col[rank+2], ..., Q_col[n], where Q_col is an array
  706. // representing the permutation matrix Q in column-like format. It is
  707. // understood that each j-th linearly dependent column of the matrix U
  708. // should be replaced by the unity vector, where all elements are zero
  709. // except the unity diagonal element u[j,j]. On the other hand j-th row
  710. // of the matrix U corresponds to the row of the matrix V (and therefore
  711. // of the matrix A) with the number P_row[j], where P_row is an array
  712. // representing the permutation matrix P in row-like format. Thus, each
  713. // j-th linearly dependent column of the matrix U should be replaced by
  714. // a column of the unity matrix with the number P_row[j].
  715. //
  716. // The code that repairs the matrix A may look like follows:
  717. //
  718. // for (j = rank+1; j <= n; j++)
  719. // { replace column Q_col[j] of the matrix A by column P_row[j] of
  720. // the unity matrix;
  721. // }
  722. //
  723. // where rank, P_row, and Q_col are members of the structure LUX. */
  724. int lux_decomp(LUX *lux, int (*col)(void *info, int j, int ind[],
  725. mpq_t val[]), void *info)
  726. { int n = lux->n;
  727. LUXELM **V_row = lux->V_row;
  728. LUXELM **V_col = lux->V_col;
  729. int *P_row = lux->P_row;
  730. int *P_col = lux->P_col;
  731. int *Q_row = lux->Q_row;
  732. int *Q_col = lux->Q_col;
  733. LUXELM *piv, *vij;
  734. LUXWKA *wka;
  735. int i, j, k, p, q, t, *flag;
  736. mpq_t *work;
  737. /* allocate working area */
  738. wka = xmalloc(sizeof(LUXWKA));
  739. wka->R_len = xcalloc(1+n, sizeof(int));
  740. wka->R_head = xcalloc(1+n, sizeof(int));
  741. wka->R_prev = xcalloc(1+n, sizeof(int));
  742. wka->R_next = xcalloc(1+n, sizeof(int));
  743. wka->C_len = xcalloc(1+n, sizeof(int));
  744. wka->C_head = xcalloc(1+n, sizeof(int));
  745. wka->C_prev = xcalloc(1+n, sizeof(int));
  746. wka->C_next = xcalloc(1+n, sizeof(int));
  747. /* initialize LU-factorization data structures */
  748. initialize(lux, col, info, wka);
  749. /* allocate working arrays */
  750. flag = xcalloc(1+n, sizeof(int));
  751. work = xcalloc(1+n, sizeof(mpq_t));
  752. for (k = 1; k <= n; k++)
  753. { flag[k] = 0;
  754. mpq_init(work[k]);
  755. }
  756. /* main elimination loop */
  757. for (k = 1; k <= n; k++)
  758. { /* choose a pivot element v[p,q] */
  759. piv = find_pivot(lux, wka);
  760. if (piv == NULL)
  761. { /* no pivot can be chosen, because the active submatrix is
  762. empty */
  763. break;
  764. }
  765. /* determine row and column indices of the pivot element */
  766. p = piv->i, q = piv->j;
  767. /* let v[p,q] correspond to u[i',j']; permute k-th and i'-th
  768. rows and k-th and j'-th columns of the matrix U = P*V*Q to
  769. move the element u[i',j'] to the position u[k,k] */
  770. i = P_col[p], j = Q_row[q];
  771. xassert(k <= i && i <= n && k <= j && j <= n);
  772. /* permute k-th and i-th rows of the matrix U */
  773. t = P_row[k];
  774. P_row[i] = t, P_col[t] = i;
  775. P_row[k] = p, P_col[p] = k;
  776. /* permute k-th and j-th columns of the matrix U */
  777. t = Q_col[k];
  778. Q_col[j] = t, Q_row[t] = j;
  779. Q_col[k] = q, Q_row[q] = k;
  780. /* eliminate subdiagonal elements of k-th column of the matrix
  781. U = P*V*Q using the pivot element u[k,k] = v[p,q] */
  782. eliminate(lux, wka, piv, flag, work);
  783. }
  784. /* determine the rank of A (and V) */
  785. lux->rank = k - 1;
  786. /* free working arrays */
  787. xfree(flag);
  788. for (k = 1; k <= n; k++) mpq_clear(work[k]);
  789. xfree(work);
  790. /* build column lists of the matrix V using its row lists */
  791. for (j = 1; j <= n; j++)
  792. xassert(V_col[j] == NULL);
  793. for (i = 1; i <= n; i++)
  794. { for (vij = V_row[i]; vij != NULL; vij = vij->r_next)
  795. { j = vij->j;
  796. vij->c_prev = NULL;
  797. vij->c_next = V_col[j];
  798. if (vij->c_next != NULL) vij->c_next->c_prev = vij;
  799. V_col[j] = vij;
  800. }
  801. }
  802. /* free working area */
  803. xfree(wka->R_len);
  804. xfree(wka->R_head);
  805. xfree(wka->R_prev);
  806. xfree(wka->R_next);
  807. xfree(wka->C_len);
  808. xfree(wka->C_head);
  809. xfree(wka->C_prev);
  810. xfree(wka->C_next);
  811. xfree(wka);
  812. /* return to the calling program */
  813. return (lux->rank < n);
  814. }
  815. /*----------------------------------------------------------------------
  816. // lux_f_solve - solve system F*x = b or F'*x = b.
  817. //
  818. // SYNOPSIS
  819. //
  820. // #include "glplux.h"
  821. // void lux_f_solve(LUX *lux, int tr, mpq_t x[]);
  822. //
  823. // DESCRIPTION
  824. //
  825. // The routine lux_f_solve solves either the system F*x = b (if the
  826. // flag tr is zero) or the system F'*x = b (if the flag tr is non-zero),
  827. // where the matrix F is a component of LU-factorization specified by
  828. // the parameter lux, F' is a matrix transposed to F.
  829. //
  830. // On entry the array x should contain elements of the right-hand side
  831. // vector b in locations x[1], ..., x[n], where n is the order of the
  832. // matrix F. On exit this array will contain elements of the solution
  833. // vector x in the same locations. */
  834. void lux_f_solve(LUX *lux, int tr, mpq_t x[])
  835. { int n = lux->n;
  836. LUXELM **F_row = lux->F_row;
  837. LUXELM **F_col = lux->F_col;
  838. int *P_row = lux->P_row;
  839. LUXELM *fik, *fkj;
  840. int i, j, k;
  841. mpq_t temp;
  842. mpq_init(temp);
  843. if (!tr)
  844. { /* solve the system F*x = b */
  845. for (j = 1; j <= n; j++)
  846. { k = P_row[j];
  847. if (mpq_sgn(x[k]) != 0)
  848. { for (fik = F_col[k]; fik != NULL; fik = fik->c_next)
  849. { mpq_mul(temp, fik->val, x[k]);
  850. mpq_sub(x[fik->i], x[fik->i], temp);
  851. }
  852. }
  853. }
  854. }
  855. else
  856. { /* solve the system F'*x = b */
  857. for (i = n; i >= 1; i--)
  858. { k = P_row[i];
  859. if (mpq_sgn(x[k]) != 0)
  860. { for (fkj = F_row[k]; fkj != NULL; fkj = fkj->r_next)
  861. { mpq_mul(temp, fkj->val, x[k]);
  862. mpq_sub(x[fkj->j], x[fkj->j], temp);
  863. }
  864. }
  865. }
  866. }
  867. mpq_clear(temp);
  868. return;
  869. }
  870. /*----------------------------------------------------------------------
  871. // lux_v_solve - solve system V*x = b or V'*x = b.
  872. //
  873. // SYNOPSIS
  874. //
  875. // #include "glplux.h"
  876. // void lux_v_solve(LUX *lux, int tr, double x[]);
  877. //
  878. // DESCRIPTION
  879. //
  880. // The routine lux_v_solve solves either the system V*x = b (if the
  881. // flag tr is zero) or the system V'*x = b (if the flag tr is non-zero),
  882. // where the matrix V is a component of LU-factorization specified by
  883. // the parameter lux, V' is a matrix transposed to V.
  884. //
  885. // On entry the array x should contain elements of the right-hand side
  886. // vector b in locations x[1], ..., x[n], where n is the order of the
  887. // matrix V. On exit this array will contain elements of the solution
  888. // vector x in the same locations. */
  889. void lux_v_solve(LUX *lux, int tr, mpq_t x[])
  890. { int n = lux->n;
  891. mpq_t *V_piv = lux->V_piv;
  892. LUXELM **V_row = lux->V_row;
  893. LUXELM **V_col = lux->V_col;
  894. int *P_row = lux->P_row;
  895. int *Q_col = lux->Q_col;
  896. LUXELM *vij;
  897. int i, j, k;
  898. mpq_t *b, temp;
  899. b = xcalloc(1+n, sizeof(mpq_t));
  900. for (k = 1; k <= n; k++)
  901. mpq_init(b[k]), mpq_set(b[k], x[k]), mpq_set_si(x[k], 0, 1);
  902. mpq_init(temp);
  903. if (!tr)
  904. { /* solve the system V*x = b */
  905. for (k = n; k >= 1; k--)
  906. { i = P_row[k], j = Q_col[k];
  907. if (mpq_sgn(b[i]) != 0)
  908. { mpq_set(x[j], b[i]);
  909. mpq_div(x[j], x[j], V_piv[i]);
  910. for (vij = V_col[j]; vij != NULL; vij = vij->c_next)
  911. { mpq_mul(temp, vij->val, x[j]);
  912. mpq_sub(b[vij->i], b[vij->i], temp);
  913. }
  914. }
  915. }
  916. }
  917. else
  918. { /* solve the system V'*x = b */
  919. for (k = 1; k <= n; k++)
  920. { i = P_row[k], j = Q_col[k];
  921. if (mpq_sgn(b[j]) != 0)
  922. { mpq_set(x[i], b[j]);
  923. mpq_div(x[i], x[i], V_piv[i]);
  924. for (vij = V_row[i]; vij != NULL; vij = vij->r_next)
  925. { mpq_mul(temp, vij->val, x[i]);
  926. mpq_sub(b[vij->j], b[vij->j], temp);
  927. }
  928. }
  929. }
  930. }
  931. for (k = 1; k <= n; k++) mpq_clear(b[k]);
  932. mpq_clear(temp);
  933. xfree(b);
  934. return;
  935. }
  936. /*----------------------------------------------------------------------
  937. // lux_solve - solve system A*x = b or A'*x = b.
  938. //
  939. // SYNOPSIS
  940. //
  941. // #include "glplux.h"
  942. // void lux_solve(LUX *lux, int tr, mpq_t x[]);
  943. //
  944. // DESCRIPTION
  945. //
  946. // The routine lux_solve solves either the system A*x = b (if the flag
  947. // tr is zero) or the system A'*x = b (if the flag tr is non-zero),
  948. // where the parameter lux specifies LU-factorization of the matrix A,
  949. // A' is a matrix transposed to A.
  950. //
  951. // On entry the array x should contain elements of the right-hand side
  952. // vector b in locations x[1], ..., x[n], where n is the order of the
  953. // matrix A. On exit this array will contain elements of the solution
  954. // vector x in the same locations. */
  955. void lux_solve(LUX *lux, int tr, mpq_t x[])
  956. { if (lux->rank < lux->n)
  957. xfault("lux_solve: LU-factorization has incomplete rank\n");
  958. if (!tr)
  959. { /* A = F*V, therefore inv(A) = inv(V)*inv(F) */
  960. lux_f_solve(lux, 0, x);
  961. lux_v_solve(lux, 0, x);
  962. }
  963. else
  964. { /* A' = V'*F', therefore inv(A') = inv(F')*inv(V') */
  965. lux_v_solve(lux, 1, x);
  966. lux_f_solve(lux, 1, x);
  967. }
  968. return;
  969. }
  970. /*----------------------------------------------------------------------
  971. // lux_delete - delete LU-factorization.
  972. //
  973. // SYNOPSIS
  974. //
  975. // #include "glplux.h"
  976. // void lux_delete(LUX *lux);
  977. //
  978. // DESCRIPTION
  979. //
  980. // The routine lux_delete deletes LU-factorization data structure,
  981. // which the parameter lux points to, freeing all the memory allocated
  982. // to this object. */
  983. void lux_delete(LUX *lux)
  984. { int n = lux->n;
  985. LUXELM *fij, *vij;
  986. int i;
  987. for (i = 1; i <= n; i++)
  988. { for (fij = lux->F_row[i]; fij != NULL; fij = fij->r_next)
  989. mpq_clear(fij->val);
  990. mpq_clear(lux->V_piv[i]);
  991. for (vij = lux->V_row[i]; vij != NULL; vij = vij->r_next)
  992. mpq_clear(vij->val);
  993. }
  994. dmp_delete_pool(lux->pool);
  995. xfree(lux->F_row);
  996. xfree(lux->F_col);
  997. xfree(lux->V_piv);
  998. xfree(lux->V_row);
  999. xfree(lux->V_col);
  1000. xfree(lux->P_row);
  1001. xfree(lux->P_col);
  1002. xfree(lux->Q_row);
  1003. xfree(lux->Q_col);
  1004. xfree(lux);
  1005. return;
  1006. }
  1007. /* eof */