glpini01.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. /* glpini01.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 "glpapi.h"
  24. /*----------------------------------------------------------------------
  25. -- triang - find maximal triangular part of a rectangular matrix.
  26. --
  27. -- *Synopsis*
  28. --
  29. -- int triang(int m, int n,
  30. -- void *info, int (*mat)(void *info, int k, int ndx[]),
  31. -- int rn[], int cn[]);
  32. --
  33. -- *Description*
  34. --
  35. -- For a given rectangular (sparse) matrix A with m rows and n columns
  36. -- the routine triang tries to find such permutation matrices P and Q
  37. -- that the first rows and columns of the matrix B = P*A*Q form a lower
  38. -- triangular submatrix of as greatest size as possible:
  39. --
  40. -- 1 n
  41. -- 1 * . . . . . . x x x x x x
  42. -- * * . . . . . x x x x x x
  43. -- * * * . . . . x x x x x x
  44. -- * * * * . . . x x x x x x
  45. -- B = P*A*Q = * * * * * . . x x x x x x
  46. -- * * * * * * . x x x x x x
  47. -- * * * * * * * x x x x x x
  48. -- x x x x x x x x x x x x x
  49. -- x x x x x x x x x x x x x
  50. -- m x x x x x x x x x x x x x
  51. --
  52. -- where: '*' - elements of the lower triangular part, '.' - structural
  53. -- zeros, 'x' - other (either non-zero or zero) elements.
  54. --
  55. -- The parameter info is a transit pointer passed to the formal routine
  56. -- mat (see below).
  57. --
  58. -- The formal routine mat specifies the given matrix A in both row- and
  59. -- column-wise formats. In order to obtain an i-th row of the matrix A
  60. -- the routine triang calls the routine mat with the parameter k = +i,
  61. -- 1 <= i <= m. In response the routine mat should store column indices
  62. -- of (non-zero) elements of the i-th row to the locations ndx[1], ...,
  63. -- ndx[len], where len is number of non-zeros in the i-th row returned
  64. -- on exit. Analogously, in order to obtain a j-th column of the matrix
  65. -- A, the routine mat is called with the parameter k = -j, 1 <= j <= n,
  66. -- and should return pattern of the j-th column in the same way as for
  67. -- row patterns. Note that the routine mat may be called more than once
  68. -- for the same rows and columns.
  69. --
  70. -- On exit the routine computes two resultant arrays rn and cn, which
  71. -- define the permutation matrices P and Q, respectively. The array rn
  72. -- should have at least 1+m locations, where rn[i] = i' (1 <= i <= m)
  73. -- means that i-th row of the original matrix A corresponds to i'-th row
  74. -- of the matrix B = P*A*Q. Similarly, the array cn should have at least
  75. -- 1+n locations, where cn[j] = j' (1 <= j <= n) means that j-th column
  76. -- of the matrix A corresponds to j'-th column of the matrix B.
  77. --
  78. -- *Returns*
  79. --
  80. -- The routine triang returns the size of the lower tringular part of
  81. -- the matrix B = P*A*Q (see the figure above).
  82. --
  83. -- *Complexity*
  84. --
  85. -- The time complexity of the routine triang is O(nnz), where nnz is
  86. -- number of non-zeros in the given matrix A.
  87. --
  88. -- *Algorithm*
  89. --
  90. -- The routine triang starts from the matrix B = P*Q*A, where P and Q
  91. -- are unity matrices, so initially B = A.
  92. --
  93. -- Before the next iteration B = (B1 | B2 | B3), where B1 is partially
  94. -- built a lower triangular submatrix, B2 is the active submatrix, and
  95. -- B3 is a submatrix that contains rejected columns. Thus, the current
  96. -- matrix B looks like follows (initially k1 = 1 and k2 = n):
  97. --
  98. -- 1 k1 k2 n
  99. -- 1 x . . . . . . . . . . . . . # # #
  100. -- x x . . . . . . . . . . . . # # #
  101. -- x x x . . . . . . . . . . # # # #
  102. -- x x x x . . . . . . . . . # # # #
  103. -- x x x x x . . . . . . . # # # # #
  104. -- k1 x x x x x * * * * * * * # # # # #
  105. -- x x x x x * * * * * * * # # # # #
  106. -- x x x x x * * * * * * * # # # # #
  107. -- x x x x x * * * * * * * # # # # #
  108. -- m x x x x x * * * * * * * # # # # #
  109. -- <--B1---> <----B2-----> <---B3-->
  110. --
  111. -- On each iteartion the routine looks for a singleton row, i.e. some
  112. -- row that has the only non-zero in the active submatrix B2. If such
  113. -- row exists and the corresponding non-zero is b[i,j], where (by the
  114. -- definition) k1 <= i <= m and k1 <= j <= k2, the routine permutes
  115. -- k1-th and i-th rows and k1-th and j-th columns of the matrix B (in
  116. -- order to place the element in the position b[k1,k1]), removes the
  117. -- k1-th column from the active submatrix B2, and adds this column to
  118. -- the submatrix B1. If no row singletons exist, but B2 is not empty
  119. -- yet, the routine chooses a j-th column, which has maximal number of
  120. -- non-zeros among other columns of B2, removes this column from B2 and
  121. -- adds it to the submatrix B3 in the hope that new row singletons will
  122. -- appear in the active submatrix. */
  123. static int triang(int m, int n,
  124. void *info, int (*mat)(void *info, int k, int ndx[]),
  125. int rn[], int cn[])
  126. { int *ndx; /* int ndx[1+max(m,n)]; */
  127. /* this array is used for querying row and column patterns of the
  128. given matrix A (the third parameter to the routine mat) */
  129. int *rs_len; /* int rs_len[1+m]; */
  130. /* rs_len[0] is not used;
  131. rs_len[i], 1 <= i <= m, is number of non-zeros in the i-th row
  132. of the matrix A, which (non-zeros) belong to the current active
  133. submatrix */
  134. int *rs_head; /* int rs_head[1+n]; */
  135. /* rs_head[len], 0 <= len <= n, is the number i of the first row
  136. of the matrix A, for which rs_len[i] = len */
  137. int *rs_prev; /* int rs_prev[1+m]; */
  138. /* rs_prev[0] is not used;
  139. rs_prev[i], 1 <= i <= m, is a number i' of the previous row of
  140. the matrix A, for which rs_len[i] = rs_len[i'] (zero marks the
  141. end of this linked list) */
  142. int *rs_next; /* int rs_next[1+m]; */
  143. /* rs_next[0] is not used;
  144. rs_next[i], 1 <= i <= m, is a number i' of the next row of the
  145. matrix A, for which rs_len[i] = rs_len[i'] (zero marks the end
  146. this linked list) */
  147. int cs_head;
  148. /* is a number j of the first column of the matrix A, which has
  149. maximal number of non-zeros among other columns */
  150. int *cs_prev; /* cs_prev[1+n]; */
  151. /* cs_prev[0] is not used;
  152. cs_prev[j], 1 <= j <= n, is a number of the previous column of
  153. the matrix A with the same or greater number of non-zeros than
  154. in the j-th column (zero marks the end of this linked list) */
  155. int *cs_next; /* cs_next[1+n]; */
  156. /* cs_next[0] is not used;
  157. cs_next[j], 1 <= j <= n, is a number of the next column of
  158. the matrix A with the same or lesser number of non-zeros than
  159. in the j-th column (zero marks the end of this linked list) */
  160. int i, j, ii, jj, k1, k2, len, t, size = 0;
  161. int *head, *rn_inv, *cn_inv;
  162. if (!(m > 0 && n > 0))
  163. xerror("triang: m = %d; n = %d; invalid dimension\n", m, n);
  164. /* allocate working arrays */
  165. ndx = xcalloc(1+(m >= n ? m : n), sizeof(int));
  166. rs_len = xcalloc(1+m, sizeof(int));
  167. rs_head = xcalloc(1+n, sizeof(int));
  168. rs_prev = xcalloc(1+m, sizeof(int));
  169. rs_next = xcalloc(1+m, sizeof(int));
  170. cs_prev = xcalloc(1+n, sizeof(int));
  171. cs_next = xcalloc(1+n, sizeof(int));
  172. /* build linked lists of columns of the matrix A with the same
  173. number of non-zeros */
  174. head = rs_len; /* currently rs_len is used as working array */
  175. for (len = 0; len <= m; len ++) head[len] = 0;
  176. for (j = 1; j <= n; j++)
  177. { /* obtain length of the j-th column */
  178. len = mat(info, -j, ndx);
  179. xassert(0 <= len && len <= m);
  180. /* include the j-th column in the corresponding linked list */
  181. cs_prev[j] = head[len];
  182. head[len] = j;
  183. }
  184. /* merge all linked lists of columns in one linked list, where
  185. columns are ordered by descending of their lengths */
  186. cs_head = 0;
  187. for (len = 0; len <= m; len++)
  188. { for (j = head[len]; j != 0; j = cs_prev[j])
  189. { cs_next[j] = cs_head;
  190. cs_head = j;
  191. }
  192. }
  193. jj = 0;
  194. for (j = cs_head; j != 0; j = cs_next[j])
  195. { cs_prev[j] = jj;
  196. jj = j;
  197. }
  198. /* build initial doubly linked lists of rows of the matrix A with
  199. the same number of non-zeros */
  200. for (len = 0; len <= n; len++) rs_head[len] = 0;
  201. for (i = 1; i <= m; i++)
  202. { /* obtain length of the i-th row */
  203. rs_len[i] = len = mat(info, +i, ndx);
  204. xassert(0 <= len && len <= n);
  205. /* include the i-th row in the correspondng linked list */
  206. rs_prev[i] = 0;
  207. rs_next[i] = rs_head[len];
  208. if (rs_next[i] != 0) rs_prev[rs_next[i]] = i;
  209. rs_head[len] = i;
  210. }
  211. /* initially all rows and columns of the matrix A are active */
  212. for (i = 1; i <= m; i++) rn[i] = 0;
  213. for (j = 1; j <= n; j++) cn[j] = 0;
  214. /* set initial bounds of the active submatrix */
  215. k1 = 1, k2 = n;
  216. /* main loop starts here */
  217. while (k1 <= k2)
  218. { i = rs_head[1];
  219. if (i != 0)
  220. { /* the i-th row of the matrix A is a row singleton, since
  221. it has the only non-zero in the active submatrix */
  222. xassert(rs_len[i] == 1);
  223. /* determine the number j of an active column of the matrix
  224. A, in which this non-zero is placed */
  225. j = 0;
  226. t = mat(info, +i, ndx);
  227. xassert(0 <= t && t <= n);
  228. for (t = t; t >= 1; t--)
  229. { jj = ndx[t];
  230. xassert(1 <= jj && jj <= n);
  231. if (cn[jj] == 0)
  232. { xassert(j == 0);
  233. j = jj;
  234. }
  235. }
  236. xassert(j != 0);
  237. /* the singleton is a[i,j]; move a[i,j] to the position
  238. b[k1,k1] of the matrix B */
  239. rn[i] = cn[j] = k1;
  240. /* shift the left bound of the active submatrix */
  241. k1++;
  242. /* increase the size of the lower triangular part */
  243. size++;
  244. }
  245. else
  246. { /* the current active submatrix has no row singletons */
  247. /* remove an active column with maximal number of non-zeros
  248. from the active submatrix */
  249. j = cs_head;
  250. xassert(j != 0);
  251. cn[j] = k2;
  252. /* shift the right bound of the active submatrix */
  253. k2--;
  254. }
  255. /* the j-th column of the matrix A has been removed from the
  256. active submatrix */
  257. /* remove the j-th column from the linked list */
  258. if (cs_prev[j] == 0)
  259. cs_head = cs_next[j];
  260. else
  261. cs_next[cs_prev[j]] = cs_next[j];
  262. if (cs_next[j] == 0)
  263. /* nop */;
  264. else
  265. cs_prev[cs_next[j]] = cs_prev[j];
  266. /* go through non-zeros of the j-th columns and update active
  267. lengths of the corresponding rows */
  268. t = mat(info, -j, ndx);
  269. xassert(0 <= t && t <= m);
  270. for (t = t; t >= 1; t--)
  271. { i = ndx[t];
  272. xassert(1 <= i && i <= m);
  273. /* the non-zero a[i,j] has left the active submatrix */
  274. len = rs_len[i];
  275. xassert(len >= 1);
  276. /* remove the i-th row from the linked list of rows with
  277. active length len */
  278. if (rs_prev[i] == 0)
  279. rs_head[len] = rs_next[i];
  280. else
  281. rs_next[rs_prev[i]] = rs_next[i];
  282. if (rs_next[i] == 0)
  283. /* nop */;
  284. else
  285. rs_prev[rs_next[i]] = rs_prev[i];
  286. /* decrease the active length of the i-th row */
  287. rs_len[i] = --len;
  288. /* return the i-th row to the corresponding linked list */
  289. rs_prev[i] = 0;
  290. rs_next[i] = rs_head[len];
  291. if (rs_next[i] != 0) rs_prev[rs_next[i]] = i;
  292. rs_head[len] = i;
  293. }
  294. }
  295. /* other rows of the matrix A, which are still active, correspond
  296. to rows k1, ..., m of the matrix B (in arbitrary order) */
  297. for (i = 1; i <= m; i++) if (rn[i] == 0) rn[i] = k1++;
  298. /* but for columns this is not needed, because now the submatrix
  299. B2 has no columns */
  300. for (j = 1; j <= n; j++) xassert(cn[j] != 0);
  301. /* perform some optional checks */
  302. /* make sure that rn is a permutation of {1, ..., m} and cn is a
  303. permutation of {1, ..., n} */
  304. rn_inv = rs_len; /* used as working array */
  305. for (ii = 1; ii <= m; ii++) rn_inv[ii] = 0;
  306. for (i = 1; i <= m; i++)
  307. { ii = rn[i];
  308. xassert(1 <= ii && ii <= m);
  309. xassert(rn_inv[ii] == 0);
  310. rn_inv[ii] = i;
  311. }
  312. cn_inv = rs_head; /* used as working array */
  313. for (jj = 1; jj <= n; jj++) cn_inv[jj] = 0;
  314. for (j = 1; j <= n; j++)
  315. { jj = cn[j];
  316. xassert(1 <= jj && jj <= n);
  317. xassert(cn_inv[jj] == 0);
  318. cn_inv[jj] = j;
  319. }
  320. /* make sure that the matrix B = P*A*Q really has the form, which
  321. was declared */
  322. for (ii = 1; ii <= size; ii++)
  323. { int diag = 0;
  324. i = rn_inv[ii];
  325. t = mat(info, +i, ndx);
  326. xassert(0 <= t && t <= n);
  327. for (t = t; t >= 1; t--)
  328. { j = ndx[t];
  329. xassert(1 <= j && j <= n);
  330. jj = cn[j];
  331. if (jj <= size) xassert(jj <= ii);
  332. if (jj == ii)
  333. { xassert(!diag);
  334. diag = 1;
  335. }
  336. }
  337. xassert(diag);
  338. }
  339. /* free working arrays */
  340. xfree(ndx);
  341. xfree(rs_len);
  342. xfree(rs_head);
  343. xfree(rs_prev);
  344. xfree(rs_next);
  345. xfree(cs_prev);
  346. xfree(cs_next);
  347. /* return to the calling program */
  348. return size;
  349. }
  350. /*----------------------------------------------------------------------
  351. -- adv_basis - construct advanced initial LP basis.
  352. --
  353. -- *Synopsis*
  354. --
  355. -- #include "glpini.h"
  356. -- void adv_basis(glp_prob *lp);
  357. --
  358. -- *Description*
  359. --
  360. -- The routine adv_basis constructs an advanced initial basis for an LP
  361. -- problem object, which the parameter lp points to.
  362. --
  363. -- In order to build the initial basis the routine does the following:
  364. --
  365. -- 1) includes in the basis all non-fixed auxiliary variables;
  366. --
  367. -- 2) includes in the basis as many as possible non-fixed structural
  368. -- variables preserving triangular form of the basis matrix;
  369. --
  370. -- 3) includes in the basis appropriate (fixed) auxiliary variables
  371. -- in order to complete the basis.
  372. --
  373. -- As a result the initial basis has minimum of fixed variables and the
  374. -- corresponding basis matrix is triangular. */
  375. static int mat(void *info, int k, int ndx[])
  376. { /* this auxiliary routine returns the pattern of a given row or
  377. a given column of the augmented constraint matrix A~ = (I|-A),
  378. in which columns of fixed variables are implicitly cleared */
  379. LPX *lp = info;
  380. int m = lpx_get_num_rows(lp);
  381. int n = lpx_get_num_cols(lp);
  382. int typx, i, j, lll, len = 0;
  383. if (k > 0)
  384. { /* the pattern of the i-th row is required */
  385. i = +k;
  386. xassert(1 <= i && i <= m);
  387. #if 0 /* 22/XII-2003 */
  388. /* if the auxiliary variable x[i] is non-fixed, include its
  389. element (placed in the i-th column) in the pattern */
  390. lpx_get_row_bnds(lp, i, &typx, NULL, NULL);
  391. if (typx != LPX_FX) ndx[++len] = i;
  392. /* include in the pattern elements placed in columns, which
  393. correspond to non-fixed structural varables */
  394. i_beg = aa_ptr[i];
  395. i_end = i_beg + aa_len[i] - 1;
  396. for (i_ptr = i_beg; i_ptr <= i_end; i_ptr++)
  397. { j = m + sv_ndx[i_ptr];
  398. lpx_get_col_bnds(lp, j-m, &typx, NULL, NULL);
  399. if (typx != LPX_FX) ndx[++len] = j;
  400. }
  401. #else
  402. lll = lpx_get_mat_row(lp, i, ndx, NULL);
  403. for (k = 1; k <= lll; k++)
  404. { lpx_get_col_bnds(lp, ndx[k], &typx, NULL, NULL);
  405. if (typx != LPX_FX) ndx[++len] = m + ndx[k];
  406. }
  407. lpx_get_row_bnds(lp, i, &typx, NULL, NULL);
  408. if (typx != LPX_FX) ndx[++len] = i;
  409. #endif
  410. }
  411. else
  412. { /* the pattern of the j-th column is required */
  413. j = -k;
  414. xassert(1 <= j && j <= m+n);
  415. /* if the (auxiliary or structural) variable x[j] is fixed,
  416. the pattern of its column is empty */
  417. if (j <= m)
  418. lpx_get_row_bnds(lp, j, &typx, NULL, NULL);
  419. else
  420. lpx_get_col_bnds(lp, j-m, &typx, NULL, NULL);
  421. if (typx != LPX_FX)
  422. { if (j <= m)
  423. { /* x[j] is non-fixed auxiliary variable */
  424. ndx[++len] = j;
  425. }
  426. else
  427. { /* x[j] is non-fixed structural variables */
  428. #if 0 /* 22/XII-2003 */
  429. j_beg = aa_ptr[j];
  430. j_end = j_beg + aa_len[j] - 1;
  431. for (j_ptr = j_beg; j_ptr <= j_end; j_ptr++)
  432. ndx[++len] = sv_ndx[j_ptr];
  433. #else
  434. len = lpx_get_mat_col(lp, j-m, ndx, NULL);
  435. #endif
  436. }
  437. }
  438. }
  439. /* return the length of the row/column pattern */
  440. return len;
  441. }
  442. static void adv_basis(glp_prob *lp)
  443. { int m = lpx_get_num_rows(lp);
  444. int n = lpx_get_num_cols(lp);
  445. int i, j, jj, k, size;
  446. int *rn, *cn, *rn_inv, *cn_inv;
  447. int typx, *tagx = xcalloc(1+m+n, sizeof(int));
  448. double lb, ub;
  449. xprintf("Constructing initial basis...\n");
  450. #if 0 /* 13/V-2009 */
  451. if (m == 0)
  452. xerror("glp_adv_basis: problem has no rows\n");
  453. if (n == 0)
  454. xerror("glp_adv_basis: problem has no columns\n");
  455. #else
  456. if (m == 0 || n == 0)
  457. { glp_std_basis(lp);
  458. return;
  459. }
  460. #endif
  461. /* use the routine triang (see above) to find maximal triangular
  462. part of the augmented constraint matrix A~ = (I|-A); in order
  463. to prevent columns of fixed variables to be included in the
  464. triangular part, such columns are implictly removed from the
  465. matrix A~ by the routine adv_mat */
  466. rn = xcalloc(1+m, sizeof(int));
  467. cn = xcalloc(1+m+n, sizeof(int));
  468. size = triang(m, m+n, lp, mat, rn, cn);
  469. if (lpx_get_int_parm(lp, LPX_K_MSGLEV) >= 3)
  470. xprintf("Size of triangular part = %d\n", size);
  471. /* the first size rows and columns of the matrix P*A~*Q (where
  472. P and Q are permutation matrices defined by the arrays rn and
  473. cn) form a lower triangular matrix; build the arrays (rn_inv
  474. and cn_inv), which define the matrices inv(P) and inv(Q) */
  475. rn_inv = xcalloc(1+m, sizeof(int));
  476. cn_inv = xcalloc(1+m+n, sizeof(int));
  477. for (i = 1; i <= m; i++) rn_inv[rn[i]] = i;
  478. for (j = 1; j <= m+n; j++) cn_inv[cn[j]] = j;
  479. /* include the columns of the matrix A~, which correspond to the
  480. first size columns of the matrix P*A~*Q, in the basis */
  481. for (k = 1; k <= m+n; k++) tagx[k] = -1;
  482. for (jj = 1; jj <= size; jj++)
  483. { j = cn_inv[jj];
  484. /* the j-th column of A~ is the jj-th column of P*A~*Q */
  485. tagx[j] = LPX_BS;
  486. }
  487. /* if size < m, we need to add appropriate columns of auxiliary
  488. variables to the basis */
  489. for (jj = size + 1; jj <= m; jj++)
  490. { /* the jj-th column of P*A~*Q should be replaced by the column
  491. of the auxiliary variable, for which the only unity element
  492. is placed in the position [jj,jj] */
  493. i = rn_inv[jj];
  494. /* the jj-th row of P*A~*Q is the i-th row of A~, but in the
  495. i-th row of A~ the unity element belongs to the i-th column
  496. of A~; therefore the disired column corresponds to the i-th
  497. auxiliary variable (note that this column doesn't belong to
  498. the triangular part found by the routine triang) */
  499. xassert(1 <= i && i <= m);
  500. xassert(cn[i] > size);
  501. tagx[i] = LPX_BS;
  502. }
  503. /* free working arrays */
  504. xfree(rn);
  505. xfree(cn);
  506. xfree(rn_inv);
  507. xfree(cn_inv);
  508. /* build tags of non-basic variables */
  509. for (k = 1; k <= m+n; k++)
  510. { if (tagx[k] != LPX_BS)
  511. { if (k <= m)
  512. lpx_get_row_bnds(lp, k, &typx, &lb, &ub);
  513. else
  514. lpx_get_col_bnds(lp, k-m, &typx, &lb, &ub);
  515. switch (typx)
  516. { case LPX_FR:
  517. tagx[k] = LPX_NF; break;
  518. case LPX_LO:
  519. tagx[k] = LPX_NL; break;
  520. case LPX_UP:
  521. tagx[k] = LPX_NU; break;
  522. case LPX_DB:
  523. tagx[k] =
  524. (fabs(lb) <= fabs(ub) ? LPX_NL : LPX_NU);
  525. break;
  526. case LPX_FX:
  527. tagx[k] = LPX_NS; break;
  528. default:
  529. xassert(typx != typx);
  530. }
  531. }
  532. }
  533. for (k = 1; k <= m+n; k++)
  534. { if (k <= m)
  535. lpx_set_row_stat(lp, k, tagx[k]);
  536. else
  537. lpx_set_col_stat(lp, k-m, tagx[k]);
  538. }
  539. xfree(tagx);
  540. return;
  541. }
  542. /***********************************************************************
  543. * NAME
  544. *
  545. * glp_adv_basis - construct advanced initial LP basis
  546. *
  547. * SYNOPSIS
  548. *
  549. * void glp_adv_basis(glp_prob *lp, int flags);
  550. *
  551. * DESCRIPTION
  552. *
  553. * The routine glp_adv_basis constructs an advanced initial basis for
  554. * the specified problem object.
  555. *
  556. * The parameter flags is reserved for use in the future and must be
  557. * specified as zero. */
  558. void glp_adv_basis(glp_prob *lp, int flags)
  559. { if (flags != 0)
  560. xerror("glp_adv_basis: flags = %d; invalid flags\n", flags);
  561. if (lp->m == 0 || lp->n == 0)
  562. glp_std_basis(lp);
  563. else
  564. adv_basis(lp);
  565. return;
  566. }
  567. /* eof */