lemon-project-template-glpk

comparison deps/glpk/src/glpapi06.c @ 11:4fc6ad2fb8a6

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