glpnpp05.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810
  1. /* glpnpp05.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. /***********************************************************************
  25. * NAME
  26. *
  27. * npp_clean_prob - perform initial LP/MIP processing
  28. *
  29. * SYNOPSIS
  30. *
  31. * #include "glpnpp.h"
  32. * void npp_clean_prob(NPP *npp);
  33. *
  34. * DESCRIPTION
  35. *
  36. * The routine npp_clean_prob performs initial LP/MIP processing that
  37. * currently includes:
  38. *
  39. * 1) removing free rows;
  40. *
  41. * 2) replacing double-sided constraint rows with almost identical
  42. * bounds, by equality constraint rows;
  43. *
  44. * 3) removing fixed columns;
  45. *
  46. * 4) replacing double-bounded columns with almost identical bounds by
  47. * fixed columns and removing those columns;
  48. *
  49. * 5) initial processing constraint coefficients (not implemented);
  50. *
  51. * 6) initial processing objective coefficients (not implemented). */
  52. void npp_clean_prob(NPP *npp)
  53. { /* perform initial LP/MIP processing */
  54. NPPROW *row, *next_row;
  55. NPPCOL *col, *next_col;
  56. int ret;
  57. xassert(npp == npp);
  58. /* process rows which originally are free */
  59. for (row = npp->r_head; row != NULL; row = next_row)
  60. { next_row = row->next;
  61. if (row->lb == -DBL_MAX && row->ub == +DBL_MAX)
  62. { /* process free row */
  63. #ifdef GLP_DEBUG
  64. xprintf("1");
  65. #endif
  66. npp_free_row(npp, row);
  67. /* row was deleted */
  68. }
  69. }
  70. /* process rows which originally are double-sided inequalities */
  71. for (row = npp->r_head; row != NULL; row = next_row)
  72. { next_row = row->next;
  73. if (row->lb != -DBL_MAX && row->ub != +DBL_MAX &&
  74. row->lb < row->ub)
  75. { ret = npp_make_equality(npp, row);
  76. if (ret == 0)
  77. ;
  78. else if (ret == 1)
  79. { /* row was replaced by equality constraint */
  80. #ifdef GLP_DEBUG
  81. xprintf("2");
  82. #endif
  83. }
  84. else
  85. xassert(ret != ret);
  86. }
  87. }
  88. /* process columns which are originally fixed */
  89. for (col = npp->c_head; col != NULL; col = next_col)
  90. { next_col = col->next;
  91. if (col->lb == col->ub)
  92. { /* process fixed column */
  93. #ifdef GLP_DEBUG
  94. xprintf("3");
  95. #endif
  96. npp_fixed_col(npp, col);
  97. /* column was deleted */
  98. }
  99. }
  100. /* process columns which are originally double-bounded */
  101. for (col = npp->c_head; col != NULL; col = next_col)
  102. { next_col = col->next;
  103. if (col->lb != -DBL_MAX && col->ub != +DBL_MAX &&
  104. col->lb < col->ub)
  105. { ret = npp_make_fixed(npp, col);
  106. if (ret == 0)
  107. ;
  108. else if (ret == 1)
  109. { /* column was replaced by fixed column; process it */
  110. #ifdef GLP_DEBUG
  111. xprintf("4");
  112. #endif
  113. npp_fixed_col(npp, col);
  114. /* column was deleted */
  115. }
  116. }
  117. }
  118. return;
  119. }
  120. /***********************************************************************
  121. * NAME
  122. *
  123. * npp_process_row - perform basic row processing
  124. *
  125. * SYNOPSIS
  126. *
  127. * #include "glpnpp.h"
  128. * int npp_process_row(NPP *npp, NPPROW *row, int hard);
  129. *
  130. * DESCRIPTION
  131. *
  132. * The routine npp_process_row performs basic row processing that
  133. * currently includes:
  134. *
  135. * 1) removing empty row;
  136. *
  137. * 2) removing equality constraint row singleton and corresponding
  138. * column;
  139. *
  140. * 3) removing inequality constraint row singleton and corresponding
  141. * column if it was fixed;
  142. *
  143. * 4) performing general row analysis;
  144. *
  145. * 5) removing redundant row bounds;
  146. *
  147. * 6) removing forcing row and corresponding columns;
  148. *
  149. * 7) removing row which becomes free due to redundant bounds;
  150. *
  151. * 8) computing implied bounds for all columns in the row and using
  152. * them to strengthen current column bounds (MIP only, optional,
  153. * performed if the flag hard is on).
  154. *
  155. * Additionally the routine may activate affected rows and/or columns
  156. * for further processing.
  157. *
  158. * RETURNS
  159. *
  160. * 0 success;
  161. *
  162. * GLP_ENOPFS primal/integer infeasibility detected;
  163. *
  164. * GLP_ENODFS dual infeasibility detected. */
  165. int npp_process_row(NPP *npp, NPPROW *row, int hard)
  166. { /* perform basic row processing */
  167. NPPCOL *col;
  168. NPPAIJ *aij, *next_aij, *aaa;
  169. int ret;
  170. /* row must not be free */
  171. xassert(!(row->lb == -DBL_MAX && row->ub == +DBL_MAX));
  172. /* start processing row */
  173. if (row->ptr == NULL)
  174. { /* empty row */
  175. ret = npp_empty_row(npp, row);
  176. if (ret == 0)
  177. { /* row was deleted */
  178. #ifdef GLP_DEBUG
  179. xprintf("A");
  180. #endif
  181. return 0;
  182. }
  183. else if (ret == 1)
  184. { /* primal infeasibility */
  185. return GLP_ENOPFS;
  186. }
  187. else
  188. xassert(ret != ret);
  189. }
  190. if (row->ptr->r_next == NULL)
  191. { /* row singleton */
  192. col = row->ptr->col;
  193. if (row->lb == row->ub)
  194. { /* equality constraint */
  195. ret = npp_eq_singlet(npp, row);
  196. if (ret == 0)
  197. { /* column was fixed, row was deleted */
  198. #ifdef GLP_DEBUG
  199. xprintf("B");
  200. #endif
  201. /* activate rows affected by column */
  202. for (aij = col->ptr; aij != NULL; aij = aij->c_next)
  203. npp_activate_row(npp, aij->row);
  204. /* process fixed column */
  205. npp_fixed_col(npp, col);
  206. /* column was deleted */
  207. return 0;
  208. }
  209. else if (ret == 1 || ret == 2)
  210. { /* primal/integer infeasibility */
  211. return GLP_ENOPFS;
  212. }
  213. else
  214. xassert(ret != ret);
  215. }
  216. else
  217. { /* inequality constraint */
  218. ret = npp_ineq_singlet(npp, row);
  219. if (0 <= ret && ret <= 3)
  220. { /* row was deleted */
  221. #ifdef GLP_DEBUG
  222. xprintf("C");
  223. #endif
  224. /* activate column, since its length was changed due to
  225. row deletion */
  226. npp_activate_col(npp, col);
  227. if (ret >= 2)
  228. { /* column bounds changed significantly or column was
  229. fixed */
  230. /* activate rows affected by column */
  231. for (aij = col->ptr; aij != NULL; aij = aij->c_next)
  232. npp_activate_row(npp, aij->row);
  233. }
  234. if (ret == 3)
  235. { /* column was fixed; process it */
  236. #ifdef GLP_DEBUG
  237. xprintf("D");
  238. #endif
  239. npp_fixed_col(npp, col);
  240. /* column was deleted */
  241. }
  242. return 0;
  243. }
  244. else if (ret == 4)
  245. { /* primal infeasibility */
  246. return GLP_ENOPFS;
  247. }
  248. else
  249. xassert(ret != ret);
  250. }
  251. }
  252. #if 0
  253. /* sometimes this causes too large round-off errors; probably
  254. pivot coefficient should be chosen more carefully */
  255. if (row->ptr->r_next->r_next == NULL)
  256. { /* row doubleton */
  257. if (row->lb == row->ub)
  258. { /* equality constraint */
  259. if (!(row->ptr->col->is_int ||
  260. row->ptr->r_next->col->is_int))
  261. { /* both columns are continuous */
  262. NPPCOL *q;
  263. q = npp_eq_doublet(npp, row);
  264. if (q != NULL)
  265. { /* column q was eliminated */
  266. #ifdef GLP_DEBUG
  267. xprintf("E");
  268. #endif
  269. /* now column q is singleton of type "implied slack
  270. variable"; we process it here to make sure that on
  271. recovering basic solution the row is always active
  272. equality constraint (as required by the routine
  273. rcv_eq_doublet) */
  274. xassert(npp_process_col(npp, q) == 0);
  275. /* column q was deleted; note that row p also may be
  276. deleted */
  277. return 0;
  278. }
  279. }
  280. }
  281. }
  282. #endif
  283. /* general row analysis */
  284. ret = npp_analyze_row(npp, row);
  285. xassert(0x00 <= ret && ret <= 0xFF);
  286. if (ret == 0x33)
  287. { /* row bounds are inconsistent with column bounds */
  288. return GLP_ENOPFS;
  289. }
  290. if ((ret & 0x0F) == 0x00)
  291. { /* row lower bound does not exist or redundant */
  292. if (row->lb != -DBL_MAX)
  293. { /* remove redundant row lower bound */
  294. #ifdef GLP_DEBUG
  295. xprintf("F");
  296. #endif
  297. npp_inactive_bound(npp, row, 0);
  298. }
  299. }
  300. else if ((ret & 0x0F) == 0x01)
  301. { /* row lower bound can be active */
  302. /* see below */
  303. }
  304. else if ((ret & 0x0F) == 0x02)
  305. { /* row lower bound is a forcing bound */
  306. #ifdef GLP_DEBUG
  307. xprintf("G");
  308. #endif
  309. /* process forcing row */
  310. if (npp_forcing_row(npp, row, 0) == 0)
  311. fixup: { /* columns were fixed, row was made free */
  312. for (aij = row->ptr; aij != NULL; aij = next_aij)
  313. { /* process column fixed by forcing row */
  314. #ifdef GLP_DEBUG
  315. xprintf("H");
  316. #endif
  317. col = aij->col;
  318. next_aij = aij->r_next;
  319. /* activate rows affected by column */
  320. for (aaa = col->ptr; aaa != NULL; aaa = aaa->c_next)
  321. npp_activate_row(npp, aaa->row);
  322. /* process fixed column */
  323. npp_fixed_col(npp, col);
  324. /* column was deleted */
  325. }
  326. /* process free row (which now is empty due to deletion of
  327. all its columns) */
  328. npp_free_row(npp, row);
  329. /* row was deleted */
  330. return 0;
  331. }
  332. }
  333. else
  334. xassert(ret != ret);
  335. if ((ret & 0xF0) == 0x00)
  336. { /* row upper bound does not exist or redundant */
  337. if (row->ub != +DBL_MAX)
  338. { /* remove redundant row upper bound */
  339. #ifdef GLP_DEBUG
  340. xprintf("I");
  341. #endif
  342. npp_inactive_bound(npp, row, 1);
  343. }
  344. }
  345. else if ((ret & 0xF0) == 0x10)
  346. { /* row upper bound can be active */
  347. /* see below */
  348. }
  349. else if ((ret & 0xF0) == 0x20)
  350. { /* row upper bound is a forcing bound */
  351. #ifdef GLP_DEBUG
  352. xprintf("J");
  353. #endif
  354. /* process forcing row */
  355. if (npp_forcing_row(npp, row, 1) == 0) goto fixup;
  356. }
  357. else
  358. xassert(ret != ret);
  359. if (row->lb == -DBL_MAX && row->ub == +DBL_MAX)
  360. { /* row became free due to redundant bounds removal */
  361. #ifdef GLP_DEBUG
  362. xprintf("K");
  363. #endif
  364. /* activate its columns, since their length will change due
  365. to row deletion */
  366. for (aij = row->ptr; aij != NULL; aij = aij->r_next)
  367. npp_activate_col(npp, aij->col);
  368. /* process free row */
  369. npp_free_row(npp, row);
  370. /* row was deleted */
  371. return 0;
  372. }
  373. #if 1 /* 23/XII-2009 */
  374. /* row lower and/or upper bounds can be active */
  375. if (npp->sol == GLP_MIP && hard)
  376. { /* improve current column bounds (optional) */
  377. if (npp_improve_bounds(npp, row, 1) < 0)
  378. return GLP_ENOPFS;
  379. }
  380. #endif
  381. return 0;
  382. }
  383. /***********************************************************************
  384. * NAME
  385. *
  386. * npp_improve_bounds - improve current column bounds
  387. *
  388. * SYNOPSIS
  389. *
  390. * #include "glpnpp.h"
  391. * int npp_improve_bounds(NPP *npp, NPPROW *row, int flag);
  392. *
  393. * DESCRIPTION
  394. *
  395. * The routine npp_improve_bounds analyzes specified row (inequality
  396. * or equality constraint) to determine implied column bounds and then
  397. * uses these bounds to improve (strengthen) current column bounds.
  398. *
  399. * If the flag is on and current column bounds changed significantly
  400. * or the column was fixed, the routine activate rows affected by the
  401. * column for further processing. (This feature is intended to be used
  402. * in the main loop of the routine npp_process_row.)
  403. *
  404. * NOTE: This operation can be used for MIP problem only.
  405. *
  406. * RETURNS
  407. *
  408. * The routine npp_improve_bounds returns the number of significantly
  409. * changed bounds plus the number of column having been fixed due to
  410. * bound improvements. However, if the routine detects primal/integer
  411. * infeasibility, it returns a negative value. */
  412. int npp_improve_bounds(NPP *npp, NPPROW *row, int flag)
  413. { /* improve current column bounds */
  414. NPPCOL *col;
  415. NPPAIJ *aij, *next_aij, *aaa;
  416. int kase, ret, count = 0;
  417. double lb, ub;
  418. xassert(npp->sol == GLP_MIP);
  419. /* row must not be free */
  420. xassert(!(row->lb == -DBL_MAX && row->ub == +DBL_MAX));
  421. /* determine implied column bounds */
  422. npp_implied_bounds(npp, row);
  423. /* and use these bounds to strengthen current column bounds */
  424. for (aij = row->ptr; aij != NULL; aij = next_aij)
  425. { col = aij->col;
  426. next_aij = aij->r_next;
  427. for (kase = 0; kase <= 1; kase++)
  428. { /* save current column bounds */
  429. lb = col->lb, ub = col->ub;
  430. if (kase == 0)
  431. { /* process implied column lower bound */
  432. if (col->ll.ll == -DBL_MAX) continue;
  433. ret = npp_implied_lower(npp, col, col->ll.ll);
  434. }
  435. else
  436. { /* process implied column upper bound */
  437. if (col->uu.uu == +DBL_MAX) continue;
  438. ret = npp_implied_upper(npp, col, col->uu.uu);
  439. }
  440. if (ret == 0 || ret == 1)
  441. { /* current column bounds did not change or changed, but
  442. not significantly; restore current column bounds */
  443. col->lb = lb, col->ub = ub;
  444. }
  445. else if (ret == 2 || ret == 3)
  446. { /* current column bounds changed significantly or column
  447. was fixed */
  448. #ifdef GLP_DEBUG
  449. xprintf("L");
  450. #endif
  451. count++;
  452. /* activate other rows affected by column, if required */
  453. if (flag)
  454. { for (aaa = col->ptr; aaa != NULL; aaa = aaa->c_next)
  455. { if (aaa->row != row)
  456. npp_activate_row(npp, aaa->row);
  457. }
  458. }
  459. if (ret == 3)
  460. { /* process fixed column */
  461. #ifdef GLP_DEBUG
  462. xprintf("M");
  463. #endif
  464. npp_fixed_col(npp, col);
  465. /* column was deleted */
  466. break; /* for kase */
  467. }
  468. }
  469. else if (ret == 4)
  470. { /* primal/integer infeasibility */
  471. return -1;
  472. }
  473. else
  474. xassert(ret != ret);
  475. }
  476. }
  477. return count;
  478. }
  479. /***********************************************************************
  480. * NAME
  481. *
  482. * npp_process_col - perform basic column processing
  483. *
  484. * SYNOPSIS
  485. *
  486. * #include "glpnpp.h"
  487. * int npp_process_col(NPP *npp, NPPCOL *col);
  488. *
  489. * DESCRIPTION
  490. *
  491. * The routine npp_process_col performs basic column processing that
  492. * currently includes:
  493. *
  494. * 1) fixing and removing empty column;
  495. *
  496. * 2) removing column singleton, which is implied slack variable, and
  497. * corresponding row if it becomes free;
  498. *
  499. * 3) removing bounds of column, which is implied free variable, and
  500. * replacing corresponding row by equality constraint.
  501. *
  502. * Additionally the routine may activate affected rows and/or columns
  503. * for further processing.
  504. *
  505. * RETURNS
  506. *
  507. * 0 success;
  508. *
  509. * GLP_ENOPFS primal/integer infeasibility detected;
  510. *
  511. * GLP_ENODFS dual infeasibility detected. */
  512. int npp_process_col(NPP *npp, NPPCOL *col)
  513. { /* perform basic column processing */
  514. NPPROW *row;
  515. NPPAIJ *aij;
  516. int ret;
  517. /* column must not be fixed */
  518. xassert(col->lb < col->ub);
  519. /* start processing column */
  520. if (col->ptr == NULL)
  521. { /* empty column */
  522. ret = npp_empty_col(npp, col);
  523. if (ret == 0)
  524. { /* column was fixed and deleted */
  525. #ifdef GLP_DEBUG
  526. xprintf("N");
  527. #endif
  528. return 0;
  529. }
  530. else if (ret == 1)
  531. { /* dual infeasibility */
  532. return GLP_ENODFS;
  533. }
  534. else
  535. xassert(ret != ret);
  536. }
  537. if (col->ptr->c_next == NULL)
  538. { /* column singleton */
  539. row = col->ptr->row;
  540. if (row->lb == row->ub)
  541. { /* equality constraint */
  542. if (!col->is_int)
  543. slack: { /* implied slack variable */
  544. #ifdef GLP_DEBUG
  545. xprintf("O");
  546. #endif
  547. npp_implied_slack(npp, col);
  548. /* column was deleted */
  549. if (row->lb == -DBL_MAX && row->ub == +DBL_MAX)
  550. { /* row became free due to implied slack variable */
  551. #ifdef GLP_DEBUG
  552. xprintf("P");
  553. #endif
  554. /* activate columns affected by row */
  555. for (aij = row->ptr; aij != NULL; aij = aij->r_next)
  556. npp_activate_col(npp, aij->col);
  557. /* process free row */
  558. npp_free_row(npp, row);
  559. /* row was deleted */
  560. }
  561. else
  562. { /* row became inequality constraint; activate it
  563. since its length changed due to column deletion */
  564. npp_activate_row(npp, row);
  565. }
  566. return 0;
  567. }
  568. }
  569. else
  570. { /* inequality constraint */
  571. if (!col->is_int)
  572. { ret = npp_implied_free(npp, col);
  573. if (ret == 0)
  574. { /* implied free variable */
  575. #ifdef GLP_DEBUG
  576. xprintf("Q");
  577. #endif
  578. /* column bounds were removed, row was replaced by
  579. equality constraint */
  580. goto slack;
  581. }
  582. else if (ret == 1)
  583. { /* column is not implied free variable, because its
  584. lower and/or upper bounds can be active */
  585. }
  586. else if (ret == 2)
  587. { /* dual infeasibility */
  588. return GLP_ENODFS;
  589. }
  590. }
  591. }
  592. }
  593. /* column still exists */
  594. return 0;
  595. }
  596. /***********************************************************************
  597. * NAME
  598. *
  599. * npp_process_prob - perform basic LP/MIP processing
  600. *
  601. * SYNOPSIS
  602. *
  603. * #include "glpnpp.h"
  604. * int npp_process_prob(NPP *npp, int hard);
  605. *
  606. * DESCRIPTION
  607. *
  608. * The routine npp_process_prob performs basic LP/MIP processing that
  609. * currently includes:
  610. *
  611. * 1) initial LP/MIP processing (see the routine npp_clean_prob),
  612. *
  613. * 2) basic row processing (see the routine npp_process_row), and
  614. *
  615. * 3) basic column processing (see the routine npp_process_col).
  616. *
  617. * If the flag hard is on, the routine attempts to improve current
  618. * column bounds multiple times within the main processing loop, in
  619. * which case this feature may take a time. Otherwise, if the flag hard
  620. * is off, improving column bounds is performed only once at the end of
  621. * the main loop. (Note that this feature is used for MIP only.)
  622. *
  623. * The routine uses two sets: the set of active rows and the set of
  624. * active columns. Rows/columns are marked by a flag (the field temp in
  625. * NPPROW/NPPCOL). If the flag is non-zero, the row/column is active,
  626. * in which case it is placed in the beginning of the row/column list;
  627. * otherwise, if the flag is zero, the row/column is inactive, in which
  628. * case it is placed in the end of the row/column list. If a row/column
  629. * being currently processed may affect other rows/columns, the latters
  630. * are activated for further processing.
  631. *
  632. * RETURNS
  633. *
  634. * 0 success;
  635. *
  636. * GLP_ENOPFS primal/integer infeasibility detected;
  637. *
  638. * GLP_ENODFS dual infeasibility detected. */
  639. int npp_process_prob(NPP *npp, int hard)
  640. { /* perform basic LP/MIP processing */
  641. NPPROW *row;
  642. NPPCOL *col;
  643. int processing, ret;
  644. /* perform initial LP/MIP processing */
  645. npp_clean_prob(npp);
  646. /* activate all remaining rows and columns */
  647. for (row = npp->r_head; row != NULL; row = row->next)
  648. row->temp = 1;
  649. for (col = npp->c_head; col != NULL; col = col->next)
  650. col->temp = 1;
  651. /* main processing loop */
  652. processing = 1;
  653. while (processing)
  654. { processing = 0;
  655. /* process all active rows */
  656. for (;;)
  657. { row = npp->r_head;
  658. if (row == NULL || !row->temp) break;
  659. npp_deactivate_row(npp, row);
  660. ret = npp_process_row(npp, row, hard);
  661. if (ret != 0) goto done;
  662. processing = 1;
  663. }
  664. /* process all active columns */
  665. for (;;)
  666. { col = npp->c_head;
  667. if (col == NULL || !col->temp) break;
  668. npp_deactivate_col(npp, col);
  669. ret = npp_process_col(npp, col);
  670. if (ret != 0) goto done;
  671. processing = 1;
  672. }
  673. }
  674. #if 1 /* 23/XII-2009 */
  675. if (npp->sol == GLP_MIP && !hard)
  676. { /* improve current column bounds (optional) */
  677. for (row = npp->r_head; row != NULL; row = row->next)
  678. { if (npp_improve_bounds(npp, row, 0) < 0)
  679. { ret = GLP_ENOPFS;
  680. goto done;
  681. }
  682. }
  683. }
  684. #endif
  685. /* all seems ok */
  686. ret = 0;
  687. done: xassert(ret == 0 || ret == GLP_ENOPFS || ret == GLP_ENODFS);
  688. #ifdef GLP_DEBUG
  689. xprintf("\n");
  690. #endif
  691. return ret;
  692. }
  693. /**********************************************************************/
  694. int npp_simplex(NPP *npp, const glp_smcp *parm)
  695. { /* process LP prior to applying primal/dual simplex method */
  696. int ret;
  697. xassert(npp->sol == GLP_SOL);
  698. xassert(parm == parm);
  699. ret = npp_process_prob(npp, 0);
  700. return ret;
  701. }
  702. /**********************************************************************/
  703. int npp_integer(NPP *npp, const glp_iocp *parm)
  704. { /* process MIP prior to applying branch-and-bound method */
  705. NPPROW *row, *prev_row;
  706. NPPCOL *col;
  707. NPPAIJ *aij;
  708. int count, ret;
  709. xassert(npp->sol == GLP_MIP);
  710. xassert(parm == parm);
  711. /*==============================================================*/
  712. /* perform basic MIP processing */
  713. ret = npp_process_prob(npp, 1);
  714. if (ret != 0) goto done;
  715. /*==============================================================*/
  716. /* binarize problem, if required */
  717. if (parm->binarize)
  718. npp_binarize_prob(npp);
  719. /*==============================================================*/
  720. /* identify hidden packing inequalities */
  721. count = 0;
  722. /* new rows will be added to the end of the row list, so we go
  723. from the end to beginning of the row list */
  724. for (row = npp->r_tail; row != NULL; row = prev_row)
  725. { prev_row = row->prev;
  726. /* skip free row */
  727. if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) continue;
  728. /* skip equality constraint */
  729. if (row->lb == row->ub) continue;
  730. /* skip row having less than two variables */
  731. if (row->ptr == NULL || row->ptr->r_next == NULL) continue;
  732. /* skip row having non-binary variables */
  733. for (aij = row->ptr; aij != NULL; aij = aij->r_next)
  734. { col = aij->col;
  735. if (!(col->is_int && col->lb == 0.0 && col->ub == 1.0))
  736. break;
  737. }
  738. if (aij != NULL) continue;
  739. count += npp_hidden_packing(npp, row);
  740. }
  741. if (count > 0)
  742. xprintf("%d hidden packing inequaliti(es) were detected\n",
  743. count);
  744. /*==============================================================*/
  745. /* identify hidden covering inequalities */
  746. count = 0;
  747. /* new rows will be added to the end of the row list, so we go
  748. from the end to beginning of the row list */
  749. for (row = npp->r_tail; row != NULL; row = prev_row)
  750. { prev_row = row->prev;
  751. /* skip free row */
  752. if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) continue;
  753. /* skip equality constraint */
  754. if (row->lb == row->ub) continue;
  755. /* skip row having less than three variables */
  756. if (row->ptr == NULL || row->ptr->r_next == NULL ||
  757. row->ptr->r_next->r_next == NULL) continue;
  758. /* skip row having non-binary variables */
  759. for (aij = row->ptr; aij != NULL; aij = aij->r_next)
  760. { col = aij->col;
  761. if (!(col->is_int && col->lb == 0.0 && col->ub == 1.0))
  762. break;
  763. }
  764. if (aij != NULL) continue;
  765. count += npp_hidden_covering(npp, row);
  766. }
  767. if (count > 0)
  768. xprintf("%d hidden covering inequaliti(es) were detected\n",
  769. count);
  770. /*==============================================================*/
  771. /* reduce inequality constraint coefficients */
  772. count = 0;
  773. /* new rows will be added to the end of the row list, so we go
  774. from the end to beginning of the row list */
  775. for (row = npp->r_tail; row != NULL; row = prev_row)
  776. { prev_row = row->prev;
  777. /* skip equality constraint */
  778. if (row->lb == row->ub) continue;
  779. count += npp_reduce_ineq_coef(npp, row);
  780. }
  781. if (count > 0)
  782. xprintf("%d constraint coefficient(s) were reduced\n", count);
  783. /*==============================================================*/
  784. #ifdef GLP_DEBUG
  785. routine(npp);
  786. #endif
  787. /*==============================================================*/
  788. /* all seems ok */
  789. ret = 0;
  790. done: return ret;
  791. }
  792. /* eof */