/farmR/src/glpapi06.c

https://code.google.com/p/javawfm/ · C · 835 lines · 473 code · 33 blank · 329 comment · 158 complexity · 03be5eaa8873c2c443dbc8bd9d3c4119 MD5 · raw file

  1. /* glpapi06.c (simplex method routines) */
  2. /***********************************************************************
  3. * This code is part of GLPK (GNU Linear Programming Kit).
  4. *
  5. * Copyright (C) 2000,01,02,03,04,05,06,07,08,2009 Andrew Makhorin,
  6. * Department for Applied Informatics, Moscow Aviation Institute,
  7. * Moscow, Russia. All rights reserved. E-mail: <mao@mai2.rcnet.ru>.
  8. *
  9. * GLPK is free software: you can redistribute it and/or modify it
  10. * under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation, either version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * GLPK is distributed in the hope that it will be useful, but WITHOUT
  15. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  16. * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  17. * License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with GLPK. If not, see <http://www.gnu.org/licenses/>.
  21. ***********************************************************************/
  22. #include "glpapi.h"
  23. #include "glplpp.h"
  24. #include "glpspx.h"
  25. /***********************************************************************
  26. * NAME
  27. *
  28. * glp_simplex - solve LP problem with the simplex method
  29. *
  30. * SYNOPSIS
  31. *
  32. * int glp_simplex(glp_prob *lp, const glp_smcp *parm);
  33. *
  34. * DESCRIPTION
  35. *
  36. * The routine glp_simplex is a driver to the LP solver based on the
  37. * simplex method. This routine retrieves problem data from the
  38. * specified problem object, calls the solver to solve the problem
  39. * instance, and stores results of computations back into the problem
  40. * object.
  41. *
  42. * The simplex solver has a set of control parameters. Values of the
  43. * control parameters can be passed in a structure glp_smcp, which the
  44. * parameter parm points to.
  45. *
  46. * The parameter parm can be specified as NULL, in which case the LP
  47. * solver uses default settings.
  48. *
  49. * RETURNS
  50. *
  51. * 0 The LP problem instance has been successfully solved. This code
  52. * does not necessarily mean that the solver has found optimal
  53. * solution. It only means that the solution process was successful.
  54. *
  55. * GLP_EBADB
  56. * Unable to start the search, because the initial basis specified
  57. * in the problem object is invalid--the number of basic (auxiliary
  58. * and structural) variables is not the same as the number of rows in
  59. * the problem object.
  60. *
  61. * GLP_ESING
  62. * Unable to start the search, because the basis matrix correspodning
  63. * to the initial basis is singular within the working precision.
  64. *
  65. * GLP_ECOND
  66. * Unable to start the search, because the basis matrix correspodning
  67. * to the initial basis is ill-conditioned, i.e. its condition number
  68. * is too large.
  69. *
  70. * GLP_EBOUND
  71. * Unable to start the search, because some double-bounded variables
  72. * have incorrect bounds.
  73. *
  74. * GLP_EFAIL
  75. * The search was prematurely terminated due to the solver failure.
  76. *
  77. * GLP_EOBJLL
  78. * The search was prematurely terminated, because the objective
  79. * function being maximized has reached its lower limit and continues
  80. * decreasing (dual simplex only).
  81. *
  82. * GLP_EOBJUL
  83. * The search was prematurely terminated, because the objective
  84. * function being minimized has reached its upper limit and continues
  85. * increasing (dual simplex only).
  86. *
  87. * GLP_EITLIM
  88. * The search was prematurely terminated, because the simplex
  89. * iteration limit has been exceeded.
  90. *
  91. * GLP_ETMLIM
  92. * The search was prematurely terminated, because the time limit has
  93. * been exceeded.
  94. *
  95. * GLP_ENOPFS
  96. * The LP problem instance has no primal feasible solution (only if
  97. * the LP presolver is used).
  98. *
  99. * GLP_ENODFS
  100. * The LP problem instance has no dual feasible solution (only if the
  101. * LP presolver is used). */
  102. static void trivial1(glp_prob *lp, const glp_smcp *parm)
  103. { /* solve trivial LP problem which has no rows */
  104. int j;
  105. double dir;
  106. xassert(lp->m == 0);
  107. switch (lp->dir)
  108. { case GLP_MIN: dir = +1.0; break;
  109. case GLP_MAX: dir = -1.0; break;
  110. default: xassert(lp != lp);
  111. }
  112. lp->pbs_stat = lp->dbs_stat = GLP_FEAS;
  113. lp->obj_val = lp->c0;
  114. lp->some = 0;
  115. for (j = 1; j <= lp->n; j++)
  116. { GLPCOL *col = lp->col[j];
  117. col->dual = col->coef;
  118. switch (col->type)
  119. { case GLP_FR:
  120. if (dir * col->dual < -1e-7)
  121. lp->dbs_stat = GLP_NOFEAS;
  122. if (dir * col->dual > +1e-7)
  123. lp->dbs_stat = GLP_NOFEAS;
  124. col->stat = GLP_NF;
  125. col->prim = 0.0;
  126. break;
  127. case GLP_LO:
  128. if (dir * col->dual < -1e-7)
  129. lp->dbs_stat = GLP_NOFEAS;
  130. lo: col->stat = GLP_NL;
  131. col->prim = col->lb;
  132. break;
  133. case GLP_UP:
  134. if (dir * col->dual > +1e-7)
  135. lp->dbs_stat = GLP_NOFEAS;
  136. up: col->stat = GLP_NU;
  137. col->prim = col->ub;
  138. break;
  139. case GLP_DB:
  140. if (dir * col->dual < 0.0) goto up;
  141. if (dir * col->dual > 0.0) goto lo;
  142. if (fabs(col->lb) <= fabs(col->ub))
  143. goto lo;
  144. else
  145. goto up;
  146. case GLP_FX:
  147. col->stat = GLP_NS;
  148. col->prim = col->lb;
  149. break;
  150. default:
  151. xassert(lp != lp);
  152. }
  153. lp->obj_val += col->coef * col->prim;
  154. if (lp->dbs_stat == GLP_NOFEAS && lp->some == 0)
  155. lp->some = j;
  156. }
  157. if (parm->msg_lev >= GLP_MSG_ON && parm->out_dly == 0)
  158. { xprintf("~%6d: objval = %17.9e infeas = %17.9e\n",
  159. lp->it_cnt, lp->obj_val, 0.0);
  160. if (parm->msg_lev >= GLP_MSG_ALL)
  161. { if (lp->dbs_stat == GLP_FEAS)
  162. xprintf("OPTIMAL SOLUTION FOUND\n");
  163. else
  164. xprintf("PROBLEM HAS UNBOUNDED SOLUTION\n");
  165. }
  166. }
  167. return;
  168. }
  169. static void trivial2(glp_prob *lp, const glp_smcp *parm)
  170. { /* solve trivial LP problem which has no columns */
  171. int i;
  172. xassert(lp->n == 0);
  173. lp->pbs_stat = lp->dbs_stat = GLP_FEAS;
  174. lp->obj_val = lp->c0;
  175. lp->some = 0;
  176. for (i = 1; i <= lp->m; i++)
  177. { GLPROW *row = lp->row[i];
  178. row->stat = GLP_BS;
  179. row->prim = row->dual = 0.0;
  180. switch (row->type)
  181. { case GLP_FR:
  182. break;
  183. case GLP_LO:
  184. if (row->lb > +1e-8)
  185. lp->pbs_stat = GLP_NOFEAS;
  186. break;
  187. case GLP_UP:
  188. if (row->ub < -1e-8)
  189. lp->pbs_stat = GLP_NOFEAS;
  190. break;
  191. case GLP_DB:
  192. case GLP_FX:
  193. if (row->lb > +1e-8)
  194. lp->pbs_stat = GLP_NOFEAS;
  195. if (row->ub < -1e-8)
  196. lp->pbs_stat = GLP_NOFEAS;
  197. break;
  198. default:
  199. xassert(lp != lp);
  200. }
  201. }
  202. if (parm->msg_lev >= GLP_MSG_ON && parm->out_dly == 0)
  203. { xprintf("~%6d: objval = %17.9e infeas = %17.9e\n",
  204. lp->it_cnt, lp->obj_val);
  205. if (parm->msg_lev >= GLP_MSG_ALL)
  206. { if (lp->pbs_stat == GLP_FEAS)
  207. xprintf("OPTIMAL SOLUTION FOUND\n");
  208. else
  209. xprintf("PROBLEM HAS NO FEASIBLE SOLUTION\n");
  210. }
  211. }
  212. return;
  213. }
  214. #if 1 /* 18/VIII-2008 */
  215. static int simplex1(glp_prob *lp, const glp_smcp *parm)
  216. { /* base driver which does not use LP presolver */
  217. int ret;
  218. if (!glp_bf_exists(lp))
  219. { ret = glp_factorize(lp);
  220. switch (ret)
  221. { case 0:
  222. break;
  223. case GLP_EBADB:
  224. if (parm->msg_lev >= GLP_MSG_ERR)
  225. xprintf("glp_simplex: initial basis is invalid\n");
  226. goto done;
  227. case GLP_ESING:
  228. if (parm->msg_lev >= GLP_MSG_ERR)
  229. xprintf("glp_simplex: initial basis is singular\n");
  230. goto done;
  231. case GLP_ECOND:
  232. if (parm->msg_lev >= GLP_MSG_ERR)
  233. xprintf("glp_simplex: initial basis is ill-conditione"
  234. "d\n");
  235. goto done;
  236. default:
  237. xassert(ret != ret);
  238. }
  239. }
  240. switch (parm->meth)
  241. { case GLP_PRIMAL:
  242. ret = spx_primal(lp, parm);
  243. break;
  244. case GLP_DUALP:
  245. { glp_smcp parm1 = *parm;
  246. #if 0
  247. parm1.msg_lev = GLP_MSG_DBG;
  248. parm1.out_frq = 1;
  249. parm1.out_dly = 0;
  250. #endif
  251. ret = spx_dual(lp, &parm1);
  252. #if 1
  253. if (ret == GLP_EFAIL && lp->valid)
  254. ret = spx_primal(lp, parm);
  255. #endif
  256. }
  257. break;
  258. case GLP_DUAL:
  259. ret = spx_dual(lp, parm);
  260. break;
  261. default:
  262. xassert(parm != parm);
  263. }
  264. done: return ret;
  265. }
  266. #endif
  267. static int simplex2(glp_prob *orig, const glp_smcp *parm)
  268. { /* extended driver which uses LP presolver */
  269. LPP *lpp;
  270. glp_prob *prob;
  271. glp_bfcp bfcp;
  272. int orig_m, orig_n, orig_nnz, ret;
  273. orig_m = glp_get_num_rows(orig);
  274. orig_n = glp_get_num_cols(orig);
  275. orig_nnz = glp_get_num_nz(orig);
  276. if (parm->msg_lev >= GLP_MSG_ALL)
  277. { xprintf("glp_simplex: original LP has %d row%s, %d column%s, %"
  278. "d non-zero%s\n",
  279. orig_m, orig_m == 1 ? "" : "s",
  280. orig_n, orig_n == 1 ? "" : "s",
  281. orig_nnz, orig_nnz == 1 ? "" : "s");
  282. }
  283. /* the problem must have at least one row and one column */
  284. xassert(orig_m > 0 && orig_n > 0);
  285. /* create LP presolver workspace */
  286. lpp = lpp_create_wksp();
  287. /* load the original problem into LP presolver workspace */
  288. lpp_load_orig(lpp, orig);
  289. /* perform LP presolve analysis */
  290. ret = lpp_presolve(lpp);
  291. switch (ret)
  292. { case 0:
  293. /* presolving has been successfully completed */
  294. break;
  295. case 1:
  296. /* the original problem is primal infeasible */
  297. if (parm->msg_lev >= GLP_MSG_ALL)
  298. xprintf("PROBLEM HAS NO PRIMAL FEASIBLE SOLUTION\n");
  299. lpp_delete_wksp(lpp);
  300. return GLP_ENOPFS;
  301. case 2:
  302. /* the original problem is dual infeasible */
  303. if (parm->msg_lev >= GLP_MSG_ALL)
  304. xprintf("PROBLEM HAS NO DUAL FEASIBLE SOLUTION\n");
  305. lpp_delete_wksp(lpp);
  306. return GLP_ENODFS;
  307. default:
  308. xassert(ret != ret);
  309. }
  310. /* if the resultant problem is empty, it has an empty solution,
  311. which is optimal */
  312. if (lpp->row_ptr == NULL || lpp->col_ptr == NULL)
  313. { xassert(lpp->row_ptr == NULL);
  314. xassert(lpp->col_ptr == NULL);
  315. if (parm->msg_lev >= GLP_MSG_ALL)
  316. { xprintf("Objective value = %.10g\n",
  317. lpp->orig_dir == LPX_MIN ? + lpp->c0 : - lpp->c0);
  318. xprintf("OPTIMAL SOLUTION FOUND BY LP PRESOLVER\n");
  319. }
  320. /* allocate recovered solution segment */
  321. lpp_alloc_sol(lpp);
  322. goto post;
  323. }
  324. /* build resultant LP problem object */
  325. prob = lpp_build_prob(lpp);
  326. if (parm->msg_lev >= GLP_MSG_ALL)
  327. { int m = glp_get_num_rows(prob);
  328. int n = glp_get_num_cols(prob);
  329. int nnz = glp_get_num_nz(prob);
  330. xprintf("glp_simplex: presolved LP has %d row%s, %d column%s, "
  331. "%d non-zero%s\n", m, m == 1 ? "" : "s",
  332. n, n == 1 ? "" : "s", nnz, nnz == 1 ? "" : "s");
  333. }
  334. /* inherit basis factorization control parameters */
  335. glp_get_bfcp(orig, &bfcp);
  336. glp_set_bfcp(prob, &bfcp);
  337. /* scale the resultant problem */
  338. { LIBENV *env = lib_link_env();
  339. int term_out = env->term_out;
  340. if (!term_out || parm->msg_lev < GLP_MSG_ALL)
  341. env->term_out = GLP_OFF;
  342. else
  343. env->term_out = GLP_ON;
  344. glp_scale_prob(prob, GLP_SF_AUTO);
  345. env->term_out = term_out;
  346. }
  347. /* build advanced initial basis */
  348. { LIBENV *env = lib_link_env();
  349. int term_out = env->term_out;
  350. if (!term_out || parm->msg_lev < GLP_MSG_ALL)
  351. env->term_out = GLP_OFF;
  352. else
  353. env->term_out = GLP_ON;
  354. lpx_adv_basis(prob);
  355. env->term_out = term_out;
  356. }
  357. /* try to solve the resultant problem */
  358. prob->it_cnt = orig->it_cnt;
  359. ret = simplex1(prob, parm);
  360. orig->it_cnt = prob->it_cnt;
  361. /* check if the optimal solution has been found */
  362. if (glp_get_status(prob) != GLP_OPT)
  363. { if (parm->msg_lev >= GLP_MSG_ERR)
  364. xprintf("glp_simplex: cannot recover undefined or non-optim"
  365. "al solution\n");
  366. if (ret == 0)
  367. { if (glp_get_prim_stat(prob) == GLP_NOFEAS)
  368. ret = GLP_ENOPFS;
  369. else if (glp_get_dual_stat(prob) == GLP_NOFEAS)
  370. ret = GLP_ENODFS;
  371. }
  372. glp_delete_prob(prob);
  373. lpp_delete_wksp(lpp);
  374. return ret;
  375. }
  376. /* allocate recovered solution segment */
  377. lpp_alloc_sol(lpp);
  378. /* load basic solution of the resultant problem into LP presolver
  379. workspace */
  380. lpp_load_sol(lpp, prob);
  381. /* the resultant problem object is no longer needed */
  382. glp_delete_prob(prob);
  383. post: /* perform LP postsolve processing */
  384. lpp_postsolve(lpp);
  385. /* unload recovered basic solution and store it into the original
  386. problem object */
  387. lpp_unload_sol(lpp, orig);
  388. /* delete LP presolver workspace */
  389. lpp_delete_wksp(lpp);
  390. /* the original problem has been successfully solved */
  391. return 0;
  392. }
  393. int glp_simplex(glp_prob *lp, const glp_smcp *parm)
  394. { glp_smcp _parm;
  395. int i, j, ret;
  396. if (parm == NULL)
  397. parm = &_parm, glp_init_smcp((glp_smcp *)parm);
  398. /* check control parameters */
  399. if (!(parm->msg_lev == GLP_MSG_OFF ||
  400. parm->msg_lev == GLP_MSG_ERR ||
  401. parm->msg_lev == GLP_MSG_ON ||
  402. parm->msg_lev == GLP_MSG_ALL))
  403. xerror("glp_simplex: msg_lev = %d; invalid parameter\n",
  404. parm->msg_lev);
  405. if (!(parm->meth == GLP_PRIMAL ||
  406. parm->meth == GLP_DUALP ||
  407. parm->meth == GLP_DUAL))
  408. xerror("glp_simplex: meth = %d; invalid parameter\n",
  409. parm->meth);
  410. if (!(parm->pricing == GLP_PT_STD ||
  411. parm->pricing == GLP_PT_PSE))
  412. xerror("glp_simplex: pricing = %d; invalid parameter\n",
  413. parm->pricing);
  414. if (!(parm->r_test == GLP_RT_STD ||
  415. parm->r_test == GLP_RT_HAR))
  416. xerror("glp_simplex: r_test = %d; invalid parameter\n",
  417. parm->r_test);
  418. if (!(0.0 < parm->tol_bnd && parm->tol_bnd < 1.0))
  419. xerror("glp_simplex: tol_bnd = %g; invalid parameter\n",
  420. parm->tol_bnd);
  421. if (!(0.0 < parm->tol_dj && parm->tol_dj < 1.0))
  422. xerror("glp_simplex: tol_dj = %g; invalid parameter\n",
  423. parm->tol_dj);
  424. if (!(0.0 < parm->tol_piv && parm->tol_piv < 1.0))
  425. xerror("glp_simplex: tol_piv = %g; invalid parameter\n",
  426. parm->tol_piv);
  427. if (parm->it_lim < 0)
  428. xerror("glp_simplex: it_lim = %d; invalid parameter\n",
  429. parm->it_lim);
  430. if (parm->tm_lim < 0)
  431. xerror("glp_simplex: tm_lim = %d; invalid parameter\n",
  432. parm->tm_lim);
  433. if (parm->out_frq < 1)
  434. xerror("glp_simplex: out_frq = %d; invalid parameter\n",
  435. parm->out_frq);
  436. if (parm->out_dly < 0)
  437. xerror("glp_simplex: out_dly = %d; invalid parameter\n",
  438. parm->out_dly);
  439. if (!(parm->presolve == GLP_ON || parm->presolve == GLP_OFF))
  440. xerror("glp_simplex: presolve = %d; invalid parameter\n",
  441. parm->presolve);
  442. /* basic solution is currently undefined */
  443. lp->pbs_stat = lp->dbs_stat = GLP_UNDEF;
  444. lp->obj_val = 0.0;
  445. lp->some = 0;
  446. /* check bounds of double-bounded variables */
  447. for (i = 1; i <= lp->m; i++)
  448. { GLPROW *row = lp->row[i];
  449. if (row->type == GLP_DB && row->lb >= row->ub)
  450. { if (parm->msg_lev >= GLP_MSG_ERR)
  451. xprintf("glp_simplex: row %d: lb = %g, ub = %g; incorrec"
  452. "t bounds\n", i, row->lb, row->ub);
  453. ret = GLP_EBOUND;
  454. goto done;
  455. }
  456. }
  457. for (j = 1; j <= lp->n; j++)
  458. { GLPCOL *col = lp->col[j];
  459. if (col->type == GLP_DB && col->lb >= col->ub)
  460. { if (parm->msg_lev >= GLP_MSG_ERR)
  461. xprintf("glp_simplex: column %d: lb = %g, ub = %g; incor"
  462. "rect bounds\n", j, col->lb, col->ub);
  463. ret = GLP_EBOUND;
  464. goto done;
  465. }
  466. }
  467. /* solve LP problem */
  468. if (lp->m == 0)
  469. trivial1(lp, parm), ret = 0;
  470. else if (lp->n == 0)
  471. trivial2(lp, parm), ret = 0;
  472. else if (!parm->presolve)
  473. ret = simplex1(lp, parm);
  474. else
  475. ret = simplex2(lp, parm);
  476. done: /* return to the application program */
  477. return ret;
  478. }
  479. /***********************************************************************
  480. * NAME
  481. *
  482. * glp_init_smcp - initialize simplex method control parameters
  483. *
  484. * SYNOPSIS
  485. *
  486. * void glp_init_smcp(glp_smcp *parm);
  487. *
  488. * DESCRIPTION
  489. *
  490. * The routine glp_init_smcp initializes control parameters, which are
  491. * used by the simplex solver, with default values.
  492. *
  493. * Default values of the control parameters are stored in a glp_smcp
  494. * structure, which the parameter parm points to. */
  495. void glp_init_smcp(glp_smcp *parm)
  496. { parm->msg_lev = GLP_MSG_ALL;
  497. parm->meth = GLP_PRIMAL;
  498. parm->pricing = GLP_PT_PSE;
  499. parm->r_test = GLP_RT_HAR;
  500. parm->tol_bnd = 1e-7;
  501. parm->tol_dj = 1e-7;
  502. parm->tol_piv = 1e-10;
  503. parm->obj_ll = -DBL_MAX;
  504. parm->obj_ul = +DBL_MAX;
  505. parm->it_lim = INT_MAX;
  506. parm->tm_lim = INT_MAX;
  507. parm->out_frq = 200;
  508. parm->out_dly = 0;
  509. parm->presolve = GLP_OFF;
  510. return;
  511. }
  512. /***********************************************************************
  513. * NAME
  514. *
  515. * glp_get_status - retrieve generic status of basic solution
  516. *
  517. * SYNOPSIS
  518. *
  519. * int glp_get_status(glp_prob *lp);
  520. *
  521. * RETURNS
  522. *
  523. * The routine glp_get_status reports the generic status of the basic
  524. * solution for the specified problem object as follows:
  525. *
  526. * GLP_OPT - solution is optimal;
  527. * GLP_FEAS - solution is feasible;
  528. * GLP_INFEAS - solution is infeasible;
  529. * GLP_NOFEAS - problem has no feasible solution;
  530. * GLP_UNBND - problem has unbounded solution;
  531. * GLP_UNDEF - solution is undefined. */
  532. int glp_get_status(glp_prob *lp)
  533. { int status;
  534. status = glp_get_prim_stat(lp);
  535. switch (status)
  536. { case GLP_FEAS:
  537. switch (glp_get_dual_stat(lp))
  538. { case GLP_FEAS:
  539. status = GLP_OPT;
  540. break;
  541. case GLP_NOFEAS:
  542. status = GLP_UNBND;
  543. break;
  544. case GLP_UNDEF:
  545. case GLP_INFEAS:
  546. status = status;
  547. break;
  548. default:
  549. xassert(lp != lp);
  550. }
  551. break;
  552. case GLP_UNDEF:
  553. case GLP_INFEAS:
  554. case GLP_NOFEAS:
  555. status = status;
  556. break;
  557. default:
  558. xassert(lp != lp);
  559. }
  560. return status;
  561. }
  562. /***********************************************************************
  563. * NAME
  564. *
  565. * glp_get_prim_stat - retrieve status of primal basic solution
  566. *
  567. * SYNOPSIS
  568. *
  569. * int glp_get_prim_stat(glp_prob *lp);
  570. *
  571. * RETURNS
  572. *
  573. * The routine glp_get_prim_stat reports the status of the primal basic
  574. * solution for the specified problem object as follows:
  575. *
  576. * GLP_UNDEF - primal solution is undefined;
  577. * GLP_FEAS - primal solution is feasible;
  578. * GLP_INFEAS - primal solution is infeasible;
  579. * GLP_NOFEAS - no primal feasible solution exists. */
  580. int glp_get_prim_stat(glp_prob *lp)
  581. { int pbs_stat = lp->pbs_stat;
  582. return pbs_stat;
  583. }
  584. /***********************************************************************
  585. * NAME
  586. *
  587. * glp_get_dual_stat - retrieve status of dual basic solution
  588. *
  589. * SYNOPSIS
  590. *
  591. * int glp_get_dual_stat(glp_prob *lp);
  592. *
  593. * RETURNS
  594. *
  595. * The routine glp_get_dual_stat reports the status of the dual basic
  596. * solution for the specified problem object as follows:
  597. *
  598. * GLP_UNDEF - dual solution is undefined;
  599. * GLP_FEAS - dual solution is feasible;
  600. * GLP_INFEAS - dual solution is infeasible;
  601. * GLP_NOFEAS - no dual feasible solution exists. */
  602. int glp_get_dual_stat(glp_prob *lp)
  603. { int dbs_stat = lp->dbs_stat;
  604. return dbs_stat;
  605. }
  606. /***********************************************************************
  607. * NAME
  608. *
  609. * glp_get_obj_val - retrieve objective value (basic solution)
  610. *
  611. * SYNOPSIS
  612. *
  613. * double glp_get_obj_val(glp_prob *lp);
  614. *
  615. * RETURNS
  616. *
  617. * The routine glp_get_obj_val returns value of the objective function
  618. * for basic solution. */
  619. double glp_get_obj_val(glp_prob *lp)
  620. { struct LPXCPS *cps = lp->cps;
  621. double z;
  622. z = lp->obj_val;
  623. if (cps->round && fabs(z) < 1e-9) z = 0.0;
  624. return z;
  625. }
  626. /***********************************************************************
  627. * NAME
  628. *
  629. * glp_get_row_stat - retrieve row status
  630. *
  631. * SYNOPSIS
  632. *
  633. * int glp_get_row_stat(glp_prob *lp, int i);
  634. *
  635. * RETURNS
  636. *
  637. * The routine glp_get_row_stat returns current status assigned to the
  638. * auxiliary variable associated with i-th row as follows:
  639. *
  640. * GLP_BS - basic variable;
  641. * GLP_NL - non-basic variable on its lower bound;
  642. * GLP_NU - non-basic variable on its upper bound;
  643. * GLP_NF - non-basic free (unbounded) variable;
  644. * GLP_NS - non-basic fixed variable. */
  645. int glp_get_row_stat(glp_prob *lp, int i)
  646. { if (!(1 <= i && i <= lp->m))
  647. xerror("glp_get_row_stat: i = %d; row number out of range\n",
  648. i);
  649. return lp->row[i]->stat;
  650. }
  651. /***********************************************************************
  652. * NAME
  653. *
  654. * glp_get_row_prim - retrieve row primal value (basic solution)
  655. *
  656. * SYNOPSIS
  657. *
  658. * double glp_get_row_prim(glp_prob *lp, int i);
  659. *
  660. * RETURNS
  661. *
  662. * The routine glp_get_row_prim returns primal value of the auxiliary
  663. * variable associated with i-th row. */
  664. double glp_get_row_prim(glp_prob *lp, int i)
  665. { struct LPXCPS *cps = lp->cps;
  666. double prim;
  667. if (!(1 <= i && i <= lp->m))
  668. xerror("glp_get_row_prim: i = %d; row number out of range\n",
  669. i);
  670. prim = lp->row[i]->prim;
  671. if (cps->round && fabs(prim) < 1e-9) prim = 0.0;
  672. return prim;
  673. }
  674. /***********************************************************************
  675. * NAME
  676. *
  677. * glp_get_row_dual - retrieve row dual value (basic solution)
  678. *
  679. * SYNOPSIS
  680. *
  681. * double glp_get_row_dual(glp_prob *lp, int i);
  682. *
  683. * RETURNS
  684. *
  685. * The routine glp_get_row_dual returns dual value (i.e. reduced cost)
  686. * of the auxiliary variable associated with i-th row. */
  687. double glp_get_row_dual(glp_prob *lp, int i)
  688. { struct LPXCPS *cps = lp->cps;
  689. double dual;
  690. if (!(1 <= i && i <= lp->m))
  691. xerror("glp_get_row_dual: i = %d; row number out of range\n",
  692. i);
  693. dual = lp->row[i]->dual;
  694. if (cps->round && fabs(dual) < 1e-9) dual = 0.0;
  695. return dual;
  696. }
  697. /***********************************************************************
  698. * NAME
  699. *
  700. * glp_get_col_stat - retrieve column status
  701. *
  702. * SYNOPSIS
  703. *
  704. * int glp_get_col_stat(glp_prob *lp, int j);
  705. *
  706. * RETURNS
  707. *
  708. * The routine glp_get_col_stat returns current status assigned to the
  709. * structural variable associated with j-th column as follows:
  710. *
  711. * GLP_BS - basic variable;
  712. * GLP_NL - non-basic variable on its lower bound;
  713. * GLP_NU - non-basic variable on its upper bound;
  714. * GLP_NF - non-basic free (unbounded) variable;
  715. * GLP_NS - non-basic fixed variable. */
  716. int glp_get_col_stat(glp_prob *lp, int j)
  717. { if (!(1 <= j && j <= lp->n))
  718. xerror("glp_get_col_stat: j = %d; column number out of range\n"
  719. , j);
  720. return lp->col[j]->stat;
  721. }
  722. /***********************************************************************
  723. * NAME
  724. *
  725. * glp_get_col_prim - retrieve column primal value (basic solution)
  726. *
  727. * SYNOPSIS
  728. *
  729. * double glp_get_col_prim(glp_prob *lp, int j);
  730. *
  731. * RETURNS
  732. *
  733. * The routine glp_get_col_prim returns primal value of the structural
  734. * variable associated with j-th column. */
  735. double glp_get_col_prim(glp_prob *lp, int j)
  736. { struct LPXCPS *cps = lp->cps;
  737. double prim;
  738. if (!(1 <= j && j <= lp->n))
  739. xerror("glp_get_col_prim: j = %d; column number out of range\n"
  740. , j);
  741. prim = lp->col[j]->prim;
  742. if (cps->round && fabs(prim) < 1e-9) prim = 0.0;
  743. return prim;
  744. }
  745. /***********************************************************************
  746. * NAME
  747. *
  748. * glp_get_col_dual - retrieve column dual value (basic solution)
  749. *
  750. * SYNOPSIS
  751. *
  752. * double glp_get_col_dual(glp_prob *lp, int j);
  753. *
  754. * RETURNS
  755. *
  756. * The routine glp_get_col_dual returns dual value (i.e. reduced cost)
  757. * of the structural variable associated with j-th column. */
  758. double glp_get_col_dual(glp_prob *lp, int j)
  759. { struct LPXCPS *cps = lp->cps;
  760. double dual;
  761. if (!(1 <= j && j <= lp->n))
  762. xerror("glp_get_col_dual: j = %d; column number out of range\n"
  763. , j);
  764. dual = lp->col[j]->dual;
  765. if (cps->round && fabs(dual) < 1e-9) dual = 0.0;
  766. return dual;
  767. }
  768. /***********************************************************************
  769. * NAME
  770. *
  771. * glp_get_unbnd_ray - determine variable causing unboundedness
  772. *
  773. * SYNOPSIS
  774. *
  775. * int glp_get_unbnd_ray(glp_prob *lp);
  776. *
  777. * RETURNS
  778. *
  779. * The routine glp_get_unbnd_ray returns the number k of a variable,
  780. * which causes primal or dual unboundedness. If 1 <= k <= m, it is
  781. * k-th auxiliary variable, and if m+1 <= k <= m+n, it is (k-m)-th
  782. * structural variable, where m is the number of rows, n is the number
  783. * of columns in the problem object. If such variable is not defined,
  784. * the routine returns 0.
  785. *
  786. * COMMENTS
  787. *
  788. * If it is not exactly known which version of the simplex solver
  789. * detected unboundedness, i.e. whether the unboundedness is primal or
  790. * dual, it is sufficient to check the status of the variable reported
  791. * with the routine glp_get_row_stat or glp_get_col_stat. If the
  792. * variable is non-basic, the unboundedness is primal, otherwise, if
  793. * the variable is basic, the unboundedness is dual (the latter case
  794. * means that the problem has no primal feasible dolution). */
  795. int glp_get_unbnd_ray(glp_prob *lp)
  796. { int k;
  797. k = lp->some;
  798. xassert(k >= 0);
  799. if (k > lp->m + lp->n) k = 0;
  800. return k;
  801. }
  802. /* eof */