glpapi06.c 26 KB

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