glpnpp01.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928
  1. /* glpnpp01.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 "glpnpp.h"
  24. NPP *npp_create_wksp(void)
  25. { /* create LP/MIP preprocessor workspace */
  26. NPP *npp;
  27. npp = xmalloc(sizeof(NPP));
  28. npp->orig_dir = 0;
  29. npp->orig_m = npp->orig_n = npp->orig_nnz = 0;
  30. npp->pool = dmp_create_pool();
  31. npp->name = npp->obj = NULL;
  32. npp->c0 = 0.0;
  33. npp->nrows = npp->ncols = 0;
  34. npp->r_head = npp->r_tail = NULL;
  35. npp->c_head = npp->c_tail = NULL;
  36. npp->stack = dmp_create_pool();
  37. npp->top = NULL;
  38. #if 0 /* 16/XII-2009 */
  39. memset(&npp->count, 0, sizeof(npp->count));
  40. #endif
  41. npp->m = npp->n = npp->nnz = 0;
  42. npp->row_ref = npp->col_ref = NULL;
  43. npp->sol = npp->scaling = 0;
  44. npp->p_stat = npp->d_stat = npp->t_stat = npp->i_stat = 0;
  45. npp->r_stat = NULL;
  46. /*npp->r_prim =*/ npp->r_pi = NULL;
  47. npp->c_stat = NULL;
  48. npp->c_value = /*npp->c_dual =*/ NULL;
  49. return npp;
  50. }
  51. void npp_insert_row(NPP *npp, NPPROW *row, int where)
  52. { /* insert row to the row list */
  53. if (where == 0)
  54. { /* insert row to the beginning of the row list */
  55. row->prev = NULL;
  56. row->next = npp->r_head;
  57. if (row->next == NULL)
  58. npp->r_tail = row;
  59. else
  60. row->next->prev = row;
  61. npp->r_head = row;
  62. }
  63. else
  64. { /* insert row to the end of the row list */
  65. row->prev = npp->r_tail;
  66. row->next = NULL;
  67. if (row->prev == NULL)
  68. npp->r_head = row;
  69. else
  70. row->prev->next = row;
  71. npp->r_tail = row;
  72. }
  73. return;
  74. }
  75. void npp_remove_row(NPP *npp, NPPROW *row)
  76. { /* remove row from the row list */
  77. if (row->prev == NULL)
  78. npp->r_head = row->next;
  79. else
  80. row->prev->next = row->next;
  81. if (row->next == NULL)
  82. npp->r_tail = row->prev;
  83. else
  84. row->next->prev = row->prev;
  85. return;
  86. }
  87. void npp_activate_row(NPP *npp, NPPROW *row)
  88. { /* make row active */
  89. if (!row->temp)
  90. { row->temp = 1;
  91. /* move the row to the beginning of the row list */
  92. npp_remove_row(npp, row);
  93. npp_insert_row(npp, row, 0);
  94. }
  95. return;
  96. }
  97. void npp_deactivate_row(NPP *npp, NPPROW *row)
  98. { /* make row inactive */
  99. if (row->temp)
  100. { row->temp = 0;
  101. /* move the row to the end of the row list */
  102. npp_remove_row(npp, row);
  103. npp_insert_row(npp, row, 1);
  104. }
  105. return;
  106. }
  107. void npp_insert_col(NPP *npp, NPPCOL *col, int where)
  108. { /* insert column to the column list */
  109. if (where == 0)
  110. { /* insert column to the beginning of the column list */
  111. col->prev = NULL;
  112. col->next = npp->c_head;
  113. if (col->next == NULL)
  114. npp->c_tail = col;
  115. else
  116. col->next->prev = col;
  117. npp->c_head = col;
  118. }
  119. else
  120. { /* insert column to the end of the column list */
  121. col->prev = npp->c_tail;
  122. col->next = NULL;
  123. if (col->prev == NULL)
  124. npp->c_head = col;
  125. else
  126. col->prev->next = col;
  127. npp->c_tail = col;
  128. }
  129. return;
  130. }
  131. void npp_remove_col(NPP *npp, NPPCOL *col)
  132. { /* remove column from the column list */
  133. if (col->prev == NULL)
  134. npp->c_head = col->next;
  135. else
  136. col->prev->next = col->next;
  137. if (col->next == NULL)
  138. npp->c_tail = col->prev;
  139. else
  140. col->next->prev = col->prev;
  141. return;
  142. }
  143. void npp_activate_col(NPP *npp, NPPCOL *col)
  144. { /* make column active */
  145. if (!col->temp)
  146. { col->temp = 1;
  147. /* move the column to the beginning of the column list */
  148. npp_remove_col(npp, col);
  149. npp_insert_col(npp, col, 0);
  150. }
  151. return;
  152. }
  153. void npp_deactivate_col(NPP *npp, NPPCOL *col)
  154. { /* make column inactive */
  155. if (col->temp)
  156. { col->temp = 0;
  157. /* move the column to the end of the column list */
  158. npp_remove_col(npp, col);
  159. npp_insert_col(npp, col, 1);
  160. }
  161. return;
  162. }
  163. NPPROW *npp_add_row(NPP *npp)
  164. { /* add new row to the current problem */
  165. NPPROW *row;
  166. row = dmp_get_atom(npp->pool, sizeof(NPPROW));
  167. row->i = ++(npp->nrows);
  168. row->name = NULL;
  169. row->lb = -DBL_MAX, row->ub = +DBL_MAX;
  170. row->ptr = NULL;
  171. row->temp = 0;
  172. npp_insert_row(npp, row, 1);
  173. return row;
  174. }
  175. NPPCOL *npp_add_col(NPP *npp)
  176. { /* add new column to the current problem */
  177. NPPCOL *col;
  178. col = dmp_get_atom(npp->pool, sizeof(NPPCOL));
  179. col->j = ++(npp->ncols);
  180. col->name = NULL;
  181. #if 0
  182. col->kind = GLP_CV;
  183. #else
  184. col->is_int = 0;
  185. #endif
  186. col->lb = col->ub = col->coef = 0.0;
  187. col->ptr = NULL;
  188. col->temp = 0;
  189. npp_insert_col(npp, col, 1);
  190. return col;
  191. }
  192. NPPAIJ *npp_add_aij(NPP *npp, NPPROW *row, NPPCOL *col, double val)
  193. { /* add new element to the constraint matrix */
  194. NPPAIJ *aij;
  195. aij = dmp_get_atom(npp->pool, sizeof(NPPAIJ));
  196. aij->row = row;
  197. aij->col = col;
  198. aij->val = val;
  199. aij->r_prev = NULL;
  200. aij->r_next = row->ptr;
  201. aij->c_prev = NULL;
  202. aij->c_next = col->ptr;
  203. if (aij->r_next != NULL)
  204. aij->r_next->r_prev = aij;
  205. if (aij->c_next != NULL)
  206. aij->c_next->c_prev = aij;
  207. row->ptr = col->ptr = aij;
  208. return aij;
  209. }
  210. int npp_row_nnz(NPP *npp, NPPROW *row)
  211. { /* count number of non-zero coefficients in row */
  212. NPPAIJ *aij;
  213. int nnz;
  214. xassert(npp == npp);
  215. nnz = 0;
  216. for (aij = row->ptr; aij != NULL; aij = aij->r_next)
  217. nnz++;
  218. return nnz;
  219. }
  220. int npp_col_nnz(NPP *npp, NPPCOL *col)
  221. { /* count number of non-zero coefficients in column */
  222. NPPAIJ *aij;
  223. int nnz;
  224. xassert(npp == npp);
  225. nnz = 0;
  226. for (aij = col->ptr; aij != NULL; aij = aij->c_next)
  227. nnz++;
  228. return nnz;
  229. }
  230. void *npp_push_tse(NPP *npp, int (*func)(NPP *npp, void *info),
  231. int size)
  232. { /* push new entry to the transformation stack */
  233. NPPTSE *tse;
  234. tse = dmp_get_atom(npp->stack, sizeof(NPPTSE));
  235. tse->func = func;
  236. tse->info = dmp_get_atom(npp->stack, size);
  237. tse->link = npp->top;
  238. npp->top = tse;
  239. return tse->info;
  240. }
  241. #if 1 /* 23/XII-2009 */
  242. void npp_erase_row(NPP *npp, NPPROW *row)
  243. { /* erase row content to make it empty */
  244. NPPAIJ *aij;
  245. while (row->ptr != NULL)
  246. { aij = row->ptr;
  247. row->ptr = aij->r_next;
  248. if (aij->c_prev == NULL)
  249. aij->col->ptr = aij->c_next;
  250. else
  251. aij->c_prev->c_next = aij->c_next;
  252. if (aij->c_next == NULL)
  253. ;
  254. else
  255. aij->c_next->c_prev = aij->c_prev;
  256. dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ));
  257. }
  258. return;
  259. }
  260. #endif
  261. void npp_del_row(NPP *npp, NPPROW *row)
  262. { /* remove row from the current problem */
  263. #if 0 /* 23/XII-2009 */
  264. NPPAIJ *aij;
  265. #endif
  266. if (row->name != NULL)
  267. dmp_free_atom(npp->pool, row->name, strlen(row->name)+1);
  268. #if 0 /* 23/XII-2009 */
  269. while (row->ptr != NULL)
  270. { aij = row->ptr;
  271. row->ptr = aij->r_next;
  272. if (aij->c_prev == NULL)
  273. aij->col->ptr = aij->c_next;
  274. else
  275. aij->c_prev->c_next = aij->c_next;
  276. if (aij->c_next == NULL)
  277. ;
  278. else
  279. aij->c_next->c_prev = aij->c_prev;
  280. dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ));
  281. }
  282. #else
  283. npp_erase_row(npp, row);
  284. #endif
  285. npp_remove_row(npp, row);
  286. dmp_free_atom(npp->pool, row, sizeof(NPPROW));
  287. return;
  288. }
  289. void npp_del_col(NPP *npp, NPPCOL *col)
  290. { /* remove column from the current problem */
  291. NPPAIJ *aij;
  292. if (col->name != NULL)
  293. dmp_free_atom(npp->pool, col->name, strlen(col->name)+1);
  294. while (col->ptr != NULL)
  295. { aij = col->ptr;
  296. col->ptr = aij->c_next;
  297. if (aij->r_prev == NULL)
  298. aij->row->ptr = aij->r_next;
  299. else
  300. aij->r_prev->r_next = aij->r_next;
  301. if (aij->r_next == NULL)
  302. ;
  303. else
  304. aij->r_next->r_prev = aij->r_prev;
  305. dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ));
  306. }
  307. npp_remove_col(npp, col);
  308. dmp_free_atom(npp->pool, col, sizeof(NPPCOL));
  309. return;
  310. }
  311. void npp_del_aij(NPP *npp, NPPAIJ *aij)
  312. { /* remove element from the constraint matrix */
  313. if (aij->r_prev == NULL)
  314. aij->row->ptr = aij->r_next;
  315. else
  316. aij->r_prev->r_next = aij->r_next;
  317. if (aij->r_next == NULL)
  318. ;
  319. else
  320. aij->r_next->r_prev = aij->r_prev;
  321. if (aij->c_prev == NULL)
  322. aij->col->ptr = aij->c_next;
  323. else
  324. aij->c_prev->c_next = aij->c_next;
  325. if (aij->c_next == NULL)
  326. ;
  327. else
  328. aij->c_next->c_prev = aij->c_prev;
  329. dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ));
  330. return;
  331. }
  332. void npp_load_prob(NPP *npp, glp_prob *orig, int names, int sol,
  333. int scaling)
  334. { /* load original problem into the preprocessor workspace */
  335. int m = orig->m;
  336. int n = orig->n;
  337. NPPROW **link;
  338. int i, j;
  339. double dir;
  340. xassert(names == GLP_OFF || names == GLP_ON);
  341. xassert(sol == GLP_SOL || sol == GLP_IPT || sol == GLP_MIP);
  342. xassert(scaling == GLP_OFF || scaling == GLP_ON);
  343. if (sol == GLP_MIP) xassert(!scaling);
  344. npp->orig_dir = orig->dir;
  345. if (npp->orig_dir == GLP_MIN)
  346. dir = +1.0;
  347. else if (npp->orig_dir == GLP_MAX)
  348. dir = -1.0;
  349. else
  350. xassert(npp != npp);
  351. npp->orig_m = m;
  352. npp->orig_n = n;
  353. npp->orig_nnz = orig->nnz;
  354. if (names && orig->name != NULL)
  355. { npp->name = dmp_get_atom(npp->pool, strlen(orig->name)+1);
  356. strcpy(npp->name, orig->name);
  357. }
  358. if (names && orig->obj != NULL)
  359. { npp->obj = dmp_get_atom(npp->pool, strlen(orig->obj)+1);
  360. strcpy(npp->obj, orig->obj);
  361. }
  362. npp->c0 = dir * orig->c0;
  363. /* load rows */
  364. link = xcalloc(1+m, sizeof(NPPROW *));
  365. for (i = 1; i <= m; i++)
  366. { GLPROW *rrr = orig->row[i];
  367. NPPROW *row;
  368. link[i] = row = npp_add_row(npp);
  369. xassert(row->i == i);
  370. if (names && rrr->name != NULL)
  371. { row->name = dmp_get_atom(npp->pool, strlen(rrr->name)+1);
  372. strcpy(row->name, rrr->name);
  373. }
  374. if (!scaling)
  375. { if (rrr->type == GLP_FR)
  376. row->lb = -DBL_MAX, row->ub = +DBL_MAX;
  377. else if (rrr->type == GLP_LO)
  378. row->lb = rrr->lb, row->ub = +DBL_MAX;
  379. else if (rrr->type == GLP_UP)
  380. row->lb = -DBL_MAX, row->ub = rrr->ub;
  381. else if (rrr->type == GLP_DB)
  382. row->lb = rrr->lb, row->ub = rrr->ub;
  383. else if (rrr->type == GLP_FX)
  384. row->lb = row->ub = rrr->lb;
  385. else
  386. xassert(rrr != rrr);
  387. }
  388. else
  389. { double rii = rrr->rii;
  390. if (rrr->type == GLP_FR)
  391. row->lb = -DBL_MAX, row->ub = +DBL_MAX;
  392. else if (rrr->type == GLP_LO)
  393. row->lb = rrr->lb * rii, row->ub = +DBL_MAX;
  394. else if (rrr->type == GLP_UP)
  395. row->lb = -DBL_MAX, row->ub = rrr->ub * rii;
  396. else if (rrr->type == GLP_DB)
  397. row->lb = rrr->lb * rii, row->ub = rrr->ub * rii;
  398. else if (rrr->type == GLP_FX)
  399. row->lb = row->ub = rrr->lb * rii;
  400. else
  401. xassert(rrr != rrr);
  402. }
  403. }
  404. /* load columns and constraint coefficients */
  405. for (j = 1; j <= n; j++)
  406. { GLPCOL *ccc = orig->col[j];
  407. GLPAIJ *aaa;
  408. NPPCOL *col;
  409. col = npp_add_col(npp);
  410. xassert(col->j == j);
  411. if (names && ccc->name != NULL)
  412. { col->name = dmp_get_atom(npp->pool, strlen(ccc->name)+1);
  413. strcpy(col->name, ccc->name);
  414. }
  415. if (sol == GLP_MIP)
  416. #if 0
  417. col->kind = ccc->kind;
  418. #else
  419. col->is_int = (char)(ccc->kind == GLP_IV);
  420. #endif
  421. if (!scaling)
  422. { if (ccc->type == GLP_FR)
  423. col->lb = -DBL_MAX, col->ub = +DBL_MAX;
  424. else if (ccc->type == GLP_LO)
  425. col->lb = ccc->lb, col->ub = +DBL_MAX;
  426. else if (ccc->type == GLP_UP)
  427. col->lb = -DBL_MAX, col->ub = ccc->ub;
  428. else if (ccc->type == GLP_DB)
  429. col->lb = ccc->lb, col->ub = ccc->ub;
  430. else if (ccc->type == GLP_FX)
  431. col->lb = col->ub = ccc->lb;
  432. else
  433. xassert(ccc != ccc);
  434. col->coef = dir * ccc->coef;
  435. for (aaa = ccc->ptr; aaa != NULL; aaa = aaa->c_next)
  436. npp_add_aij(npp, link[aaa->row->i], col, aaa->val);
  437. }
  438. else
  439. { double sjj = ccc->sjj;
  440. if (ccc->type == GLP_FR)
  441. col->lb = -DBL_MAX, col->ub = +DBL_MAX;
  442. else if (ccc->type == GLP_LO)
  443. col->lb = ccc->lb / sjj, col->ub = +DBL_MAX;
  444. else if (ccc->type == GLP_UP)
  445. col->lb = -DBL_MAX, col->ub = ccc->ub / sjj;
  446. else if (ccc->type == GLP_DB)
  447. col->lb = ccc->lb / sjj, col->ub = ccc->ub / sjj;
  448. else if (ccc->type == GLP_FX)
  449. col->lb = col->ub = ccc->lb / sjj;
  450. else
  451. xassert(ccc != ccc);
  452. col->coef = dir * ccc->coef * sjj;
  453. for (aaa = ccc->ptr; aaa != NULL; aaa = aaa->c_next)
  454. npp_add_aij(npp, link[aaa->row->i], col,
  455. aaa->row->rii * aaa->val * sjj);
  456. }
  457. }
  458. xfree(link);
  459. /* keep solution indicator and scaling option */
  460. npp->sol = sol;
  461. npp->scaling = scaling;
  462. return;
  463. }
  464. void npp_build_prob(NPP *npp, glp_prob *prob)
  465. { /* build resultant (preprocessed) problem */
  466. NPPROW *row;
  467. NPPCOL *col;
  468. NPPAIJ *aij;
  469. int i, j, type, len, *ind;
  470. double dir, *val;
  471. glp_erase_prob(prob);
  472. glp_set_prob_name(prob, npp->name);
  473. glp_set_obj_name(prob, npp->obj);
  474. glp_set_obj_dir(prob, npp->orig_dir);
  475. if (npp->orig_dir == GLP_MIN)
  476. dir = +1.0;
  477. else if (npp->orig_dir == GLP_MAX)
  478. dir = -1.0;
  479. else
  480. xassert(npp != npp);
  481. glp_set_obj_coef(prob, 0, dir * npp->c0);
  482. /* build rows */
  483. for (row = npp->r_head; row != NULL; row = row->next)
  484. { row->temp = i = glp_add_rows(prob, 1);
  485. glp_set_row_name(prob, i, row->name);
  486. if (row->lb == -DBL_MAX && row->ub == +DBL_MAX)
  487. type = GLP_FR;
  488. else if (row->ub == +DBL_MAX)
  489. type = GLP_LO;
  490. else if (row->lb == -DBL_MAX)
  491. type = GLP_UP;
  492. else if (row->lb != row->ub)
  493. type = GLP_DB;
  494. else
  495. type = GLP_FX;
  496. glp_set_row_bnds(prob, i, type, row->lb, row->ub);
  497. }
  498. /* build columns and the constraint matrix */
  499. ind = xcalloc(1+prob->m, sizeof(int));
  500. val = xcalloc(1+prob->m, sizeof(double));
  501. for (col = npp->c_head; col != NULL; col = col->next)
  502. { j = glp_add_cols(prob, 1);
  503. glp_set_col_name(prob, j, col->name);
  504. #if 0
  505. glp_set_col_kind(prob, j, col->kind);
  506. #else
  507. glp_set_col_kind(prob, j, col->is_int ? GLP_IV : GLP_CV);
  508. #endif
  509. if (col->lb == -DBL_MAX && col->ub == +DBL_MAX)
  510. type = GLP_FR;
  511. else if (col->ub == +DBL_MAX)
  512. type = GLP_LO;
  513. else if (col->lb == -DBL_MAX)
  514. type = GLP_UP;
  515. else if (col->lb != col->ub)
  516. type = GLP_DB;
  517. else
  518. type = GLP_FX;
  519. glp_set_col_bnds(prob, j, type, col->lb, col->ub);
  520. glp_set_obj_coef(prob, j, dir * col->coef);
  521. len = 0;
  522. for (aij = col->ptr; aij != NULL; aij = aij->c_next)
  523. { len++;
  524. ind[len] = aij->row->temp;
  525. val[len] = aij->val;
  526. }
  527. glp_set_mat_col(prob, j, len, ind, val);
  528. }
  529. xfree(ind);
  530. xfree(val);
  531. /* resultant problem has been built */
  532. npp->m = prob->m;
  533. npp->n = prob->n;
  534. npp->nnz = prob->nnz;
  535. npp->row_ref = xcalloc(1+npp->m, sizeof(int));
  536. npp->col_ref = xcalloc(1+npp->n, sizeof(int));
  537. for (row = npp->r_head, i = 0; row != NULL; row = row->next)
  538. npp->row_ref[++i] = row->i;
  539. for (col = npp->c_head, j = 0; col != NULL; col = col->next)
  540. npp->col_ref[++j] = col->j;
  541. /* transformed problem segment is no longer needed */
  542. dmp_delete_pool(npp->pool), npp->pool = NULL;
  543. npp->name = npp->obj = NULL;
  544. npp->c0 = 0.0;
  545. npp->r_head = npp->r_tail = NULL;
  546. npp->c_head = npp->c_tail = NULL;
  547. return;
  548. }
  549. void npp_postprocess(NPP *npp, glp_prob *prob)
  550. { /* postprocess solution from the resultant problem */
  551. GLPROW *row;
  552. GLPCOL *col;
  553. NPPTSE *tse;
  554. int i, j, k;
  555. double dir;
  556. xassert(npp->orig_dir == prob->dir);
  557. if (npp->orig_dir == GLP_MIN)
  558. dir = +1.0;
  559. else if (npp->orig_dir == GLP_MAX)
  560. dir = -1.0;
  561. else
  562. xassert(npp != npp);
  563. xassert(npp->m == prob->m);
  564. xassert(npp->n == prob->n);
  565. xassert(npp->nnz == prob->nnz);
  566. /* copy solution status */
  567. if (npp->sol == GLP_SOL)
  568. { npp->p_stat = prob->pbs_stat;
  569. npp->d_stat = prob->dbs_stat;
  570. }
  571. else if (npp->sol == GLP_IPT)
  572. npp->t_stat = prob->ipt_stat;
  573. else if (npp->sol == GLP_MIP)
  574. npp->i_stat = prob->mip_stat;
  575. else
  576. xassert(npp != npp);
  577. /* allocate solution arrays */
  578. if (npp->sol == GLP_SOL)
  579. { if (npp->r_stat == NULL)
  580. npp->r_stat = xcalloc(1+npp->nrows, sizeof(char));
  581. for (i = 1; i <= npp->nrows; i++)
  582. npp->r_stat[i] = 0;
  583. if (npp->c_stat == NULL)
  584. npp->c_stat = xcalloc(1+npp->ncols, sizeof(char));
  585. for (j = 1; j <= npp->ncols; j++)
  586. npp->c_stat[j] = 0;
  587. }
  588. #if 0
  589. if (npp->r_prim == NULL)
  590. npp->r_prim = xcalloc(1+npp->nrows, sizeof(double));
  591. for (i = 1; i <= npp->nrows; i++)
  592. npp->r_prim[i] = DBL_MAX;
  593. #endif
  594. if (npp->c_value == NULL)
  595. npp->c_value = xcalloc(1+npp->ncols, sizeof(double));
  596. for (j = 1; j <= npp->ncols; j++)
  597. npp->c_value[j] = DBL_MAX;
  598. if (npp->sol != GLP_MIP)
  599. { if (npp->r_pi == NULL)
  600. npp->r_pi = xcalloc(1+npp->nrows, sizeof(double));
  601. for (i = 1; i <= npp->nrows; i++)
  602. npp->r_pi[i] = DBL_MAX;
  603. #if 0
  604. if (npp->c_dual == NULL)
  605. npp->c_dual = xcalloc(1+npp->ncols, sizeof(double));
  606. for (j = 1; j <= npp->ncols; j++)
  607. npp->c_dual[j] = DBL_MAX;
  608. #endif
  609. }
  610. /* copy solution components from the resultant problem */
  611. if (npp->sol == GLP_SOL)
  612. { for (i = 1; i <= npp->m; i++)
  613. { row = prob->row[i];
  614. k = npp->row_ref[i];
  615. npp->r_stat[k] = (char)row->stat;
  616. /*npp->r_prim[k] = row->prim;*/
  617. npp->r_pi[k] = dir * row->dual;
  618. }
  619. for (j = 1; j <= npp->n; j++)
  620. { col = prob->col[j];
  621. k = npp->col_ref[j];
  622. npp->c_stat[k] = (char)col->stat;
  623. npp->c_value[k] = col->prim;
  624. /*npp->c_dual[k] = dir * col->dual;*/
  625. }
  626. }
  627. else if (npp->sol == GLP_IPT)
  628. { for (i = 1; i <= npp->m; i++)
  629. { row = prob->row[i];
  630. k = npp->row_ref[i];
  631. /*npp->r_prim[k] = row->pval;*/
  632. npp->r_pi[k] = dir * row->dval;
  633. }
  634. for (j = 1; j <= npp->n; j++)
  635. { col = prob->col[j];
  636. k = npp->col_ref[j];
  637. npp->c_value[k] = col->pval;
  638. /*npp->c_dual[k] = dir * col->dval;*/
  639. }
  640. }
  641. else if (npp->sol == GLP_MIP)
  642. {
  643. #if 0
  644. for (i = 1; i <= npp->m; i++)
  645. { row = prob->row[i];
  646. k = npp->row_ref[i];
  647. /*npp->r_prim[k] = row->mipx;*/
  648. }
  649. #endif
  650. for (j = 1; j <= npp->n; j++)
  651. { col = prob->col[j];
  652. k = npp->col_ref[j];
  653. npp->c_value[k] = col->mipx;
  654. }
  655. }
  656. else
  657. xassert(npp != npp);
  658. /* perform postprocessing to construct solution to the original
  659. problem */
  660. for (tse = npp->top; tse != NULL; tse = tse->link)
  661. { xassert(tse->func != NULL);
  662. xassert(tse->func(npp, tse->info) == 0);
  663. }
  664. return;
  665. }
  666. void npp_unload_sol(NPP *npp, glp_prob *orig)
  667. { /* store solution to the original problem */
  668. GLPROW *row;
  669. GLPCOL *col;
  670. int i, j;
  671. double dir;
  672. xassert(npp->orig_dir == orig->dir);
  673. if (npp->orig_dir == GLP_MIN)
  674. dir = +1.0;
  675. else if (npp->orig_dir == GLP_MAX)
  676. dir = -1.0;
  677. else
  678. xassert(npp != npp);
  679. xassert(npp->orig_m == orig->m);
  680. xassert(npp->orig_n == orig->n);
  681. xassert(npp->orig_nnz == orig->nnz);
  682. if (npp->sol == GLP_SOL)
  683. { /* store basic solution */
  684. orig->valid = 0;
  685. orig->pbs_stat = npp->p_stat;
  686. orig->dbs_stat = npp->d_stat;
  687. orig->obj_val = orig->c0;
  688. orig->some = 0;
  689. for (i = 1; i <= orig->m; i++)
  690. { row = orig->row[i];
  691. row->stat = npp->r_stat[i];
  692. if (!npp->scaling)
  693. { /*row->prim = npp->r_prim[i];*/
  694. row->dual = dir * npp->r_pi[i];
  695. }
  696. else
  697. { /*row->prim = npp->r_prim[i] / row->rii;*/
  698. row->dual = dir * npp->r_pi[i] * row->rii;
  699. }
  700. if (row->stat == GLP_BS)
  701. row->dual = 0.0;
  702. else if (row->stat == GLP_NL)
  703. { xassert(row->type == GLP_LO || row->type == GLP_DB);
  704. row->prim = row->lb;
  705. }
  706. else if (row->stat == GLP_NU)
  707. { xassert(row->type == GLP_UP || row->type == GLP_DB);
  708. row->prim = row->ub;
  709. }
  710. else if (row->stat == GLP_NF)
  711. { xassert(row->type == GLP_FR);
  712. row->prim = 0.0;
  713. }
  714. else if (row->stat == GLP_NS)
  715. { xassert(row->type == GLP_FX);
  716. row->prim = row->lb;
  717. }
  718. else
  719. xassert(row != row);
  720. }
  721. for (j = 1; j <= orig->n; j++)
  722. { col = orig->col[j];
  723. col->stat = npp->c_stat[j];
  724. if (!npp->scaling)
  725. { col->prim = npp->c_value[j];
  726. /*col->dual = dir * npp->c_dual[j];*/
  727. }
  728. else
  729. { col->prim = npp->c_value[j] * col->sjj;
  730. /*col->dual = dir * npp->c_dual[j] / col->sjj;*/
  731. }
  732. if (col->stat == GLP_BS)
  733. col->dual = 0.0;
  734. #if 1
  735. else if (col->stat == GLP_NL)
  736. { xassert(col->type == GLP_LO || col->type == GLP_DB);
  737. col->prim = col->lb;
  738. }
  739. else if (col->stat == GLP_NU)
  740. { xassert(col->type == GLP_UP || col->type == GLP_DB);
  741. col->prim = col->ub;
  742. }
  743. else if (col->stat == GLP_NF)
  744. { xassert(col->type == GLP_FR);
  745. col->prim = 0.0;
  746. }
  747. else if (col->stat == GLP_NS)
  748. { xassert(col->type == GLP_FX);
  749. col->prim = col->lb;
  750. }
  751. else
  752. xassert(col != col);
  753. #endif
  754. orig->obj_val += col->coef * col->prim;
  755. }
  756. #if 1
  757. /* compute primal values of inactive rows */
  758. for (i = 1; i <= orig->m; i++)
  759. { row = orig->row[i];
  760. if (row->stat == GLP_BS)
  761. { GLPAIJ *aij;
  762. double temp;
  763. temp = 0.0;
  764. for (aij = row->ptr; aij != NULL; aij = aij->r_next)
  765. temp += aij->val * aij->col->prim;
  766. row->prim = temp;
  767. }
  768. }
  769. /* compute reduced costs of active columns */
  770. for (j = 1; j <= orig->n; j++)
  771. { col = orig->col[j];
  772. if (col->stat != GLP_BS)
  773. { GLPAIJ *aij;
  774. double temp;
  775. temp = col->coef;
  776. for (aij = col->ptr; aij != NULL; aij = aij->c_next)
  777. temp -= aij->val * aij->row->dual;
  778. col->dual = temp;
  779. }
  780. }
  781. #endif
  782. }
  783. else if (npp->sol == GLP_IPT)
  784. { /* store interior-point solution */
  785. orig->ipt_stat = npp->t_stat;
  786. orig->ipt_obj = orig->c0;
  787. for (i = 1; i <= orig->m; i++)
  788. { row = orig->row[i];
  789. if (!npp->scaling)
  790. { /*row->pval = npp->r_prim[i];*/
  791. row->dval = dir * npp->r_pi[i];
  792. }
  793. else
  794. { /*row->pval = npp->r_prim[i] / row->rii;*/
  795. row->dval = dir * npp->r_pi[i] * row->rii;
  796. }
  797. }
  798. for (j = 1; j <= orig->n; j++)
  799. { col = orig->col[j];
  800. if (!npp->scaling)
  801. { col->pval = npp->c_value[j];
  802. /*col->dval = dir * npp->c_dual[j];*/
  803. }
  804. else
  805. { col->pval = npp->c_value[j] * col->sjj;
  806. /*col->dval = dir * npp->c_dual[j] / col->sjj;*/
  807. }
  808. orig->ipt_obj += col->coef * col->pval;
  809. }
  810. #if 1
  811. /* compute row primal values */
  812. for (i = 1; i <= orig->m; i++)
  813. { row = orig->row[i];
  814. { GLPAIJ *aij;
  815. double temp;
  816. temp = 0.0;
  817. for (aij = row->ptr; aij != NULL; aij = aij->r_next)
  818. temp += aij->val * aij->col->pval;
  819. row->pval = temp;
  820. }
  821. }
  822. /* compute column dual values */
  823. for (j = 1; j <= orig->n; j++)
  824. { col = orig->col[j];
  825. { GLPAIJ *aij;
  826. double temp;
  827. temp = col->coef;
  828. for (aij = col->ptr; aij != NULL; aij = aij->c_next)
  829. temp -= aij->val * aij->row->dval;
  830. col->dval = temp;
  831. }
  832. }
  833. #endif
  834. }
  835. else if (npp->sol == GLP_MIP)
  836. { /* store MIP solution */
  837. xassert(!npp->scaling);
  838. orig->mip_stat = npp->i_stat;
  839. orig->mip_obj = orig->c0;
  840. #if 0
  841. for (i = 1; i <= orig->m; i++)
  842. { row = orig->row[i];
  843. /*row->mipx = npp->r_prim[i];*/
  844. }
  845. #endif
  846. for (j = 1; j <= orig->n; j++)
  847. { col = orig->col[j];
  848. col->mipx = npp->c_value[j];
  849. if (col->kind == GLP_IV)
  850. xassert(col->mipx == floor(col->mipx));
  851. orig->mip_obj += col->coef * col->mipx;
  852. }
  853. #if 1
  854. /* compute row primal values */
  855. for (i = 1; i <= orig->m; i++)
  856. { row = orig->row[i];
  857. { GLPAIJ *aij;
  858. double temp;
  859. temp = 0.0;
  860. for (aij = row->ptr; aij != NULL; aij = aij->r_next)
  861. temp += aij->val * aij->col->mipx;
  862. row->mipx = temp;
  863. }
  864. }
  865. #endif
  866. }
  867. else
  868. xassert(npp != npp);
  869. return;
  870. }
  871. void npp_delete_wksp(NPP *npp)
  872. { /* delete LP/MIP preprocessor workspace */
  873. if (npp->pool != NULL)
  874. dmp_delete_pool(npp->pool);
  875. if (npp->stack != NULL)
  876. dmp_delete_pool(npp->stack);
  877. if (npp->row_ref != NULL)
  878. xfree(npp->row_ref);
  879. if (npp->col_ref != NULL)
  880. xfree(npp->col_ref);
  881. if (npp->r_stat != NULL)
  882. xfree(npp->r_stat);
  883. #if 0
  884. if (npp->r_prim != NULL)
  885. xfree(npp->r_prim);
  886. #endif
  887. if (npp->r_pi != NULL)
  888. xfree(npp->r_pi);
  889. if (npp->c_stat != NULL)
  890. xfree(npp->c_stat);
  891. if (npp->c_value != NULL)
  892. xfree(npp->c_value);
  893. #if 0
  894. if (npp->c_dual != NULL)
  895. xfree(npp->c_dual);
  896. #endif
  897. xfree(npp);
  898. return;
  899. }
  900. /* eof */