1 /* lpx.c (old GLPK API) */
2 
3 /* Written by Andrew Makhorin <mao@gnu.org>, August 2013. */
4 
5 /* This file contains routines that implement the old GLPK API as it
6 *  was defined in GLPK 4.48.
7 *
8 *  To compile an existing project using these routines you need to add
9 *  to the project this file and the header lpx.h.
10 *
11 *  Please note that you may mix calls to old and new GLPK API routines
12 *  (except calls to glp_create_prob and glp_delete_prob). */
13 
14 #include <float.h>
15 #include <limits.h>
16 #include "lpx.h"
17 
18 #define xassert glp_assert
19 #define xerror  glp_error
20 
21 struct CPS
22 {     /* control parameters */
23       LPX *lp;
24       /* pointer to corresponding problem object */
25       int msg_lev;
26       /* level of messages output by the solver:
27          0 - no output
28          1 - error messages only
29          2 - normal output
30          3 - full output (includes informational messages) */
31       int scale;
32       /* scaling option:
33          0 - no scaling
34          1 - equilibration scaling
35          2 - geometric mean scaling
36          3 - geometric mean scaling, then equilibration scaling */
37       int dual;
38       /* dual simplex option:
39          0 - use primal simplex
40          1 - use dual simplex */
41       int price;
42       /* pricing option (for both primal and dual simplex):
43          0 - textbook pricing
44          1 - steepest edge pricing */
45       double relax;
46       /* relaxation parameter used in the ratio test; if it is zero,
47          the textbook ratio test is used; if it is non-zero (should be
48          positive), Harris' two-pass ratio test is used; in the latter
49          case on the first pass basic variables (in the case of primal
50          simplex) or reduced costs of non-basic variables (in the case
51          of dual simplex) are allowed to slightly violate their bounds,
52          but not more than (relax * tol_bnd) or (relax * tol_dj) (thus,
53          relax is a percentage of tol_bnd or tol_dj) */
54       double tol_bnd;
55       /* relative tolerance used to check if the current basic solution
56          is primal feasible */
57       double tol_dj;
58       /* absolute tolerance used to check if the current basic solution
59          is dual feasible */
60       double tol_piv;
61       /* relative tolerance used to choose eligible pivotal elements of
62          the simplex table in the ratio test */
63       int round;
64       /* solution rounding option:
65          0 - report all computed values and reduced costs "as is"
66          1 - if possible (allowed by the tolerances), replace computed
67              values and reduced costs which are close to zero by exact
68              zeros */
69       double obj_ll;
70       /* lower limit of the objective function; if on the phase II the
71          objective function reaches this limit and continues decreasing,
72          the solver stops the search */
73       double obj_ul;
74       /* upper limit of the objective function; if on the phase II the
75          objective function reaches this limit and continues increasing,
76          the solver stops the search */
77       int it_lim;
78       /* simplex iterations limit; if this value is positive, it is
79          decreased by one each time when one simplex iteration has been
80          performed, and reaching zero value signals the solver to stop
81          the search; negative value means no iterations limit */
82       double tm_lim;
83       /* searching time limit, in seconds; if this value is positive,
84          it is decreased each time when one simplex iteration has been
85          performed by the amount of time spent for the iteration, and
86          reaching zero value signals the solver to stop the search;
87          negative value means no time limit */
88       int out_frq;
89       /* output frequency, in iterations; this parameter specifies how
90          frequently the solver sends information about the solution to
91          the standard output */
92       double out_dly;
93       /* output delay, in seconds; this parameter specifies how long
94          the solver should delay sending information about the solution
95          to the standard output; zero value means no delay */
96       int branch; /* MIP */
97       /* branching heuristic:
98          0 - branch on first variable
99          1 - branch on last variable
100          2 - branch using heuristic by Driebeck and Tomlin
101          3 - branch on most fractional variable */
102       int btrack; /* MIP */
103       /* backtracking heuristic:
104          0 - select most recent node (depth first search)
105          1 - select earliest node (breadth first search)
106          2 - select node using the best projection heuristic
107          3 - select node with best local bound */
108       double tol_int; /* MIP */
109       /* absolute tolerance used to check if the current basic solution
110          is integer feasible */
111       double tol_obj; /* MIP */
112       /* relative tolerance used to check if the value of the objective
113          function is not better than in the best known integer feasible
114          solution */
115       int mps_info; /* lpx_write_mps */
116       /* if this flag is set, the routine lpx_write_mps outputs several
117          comment cards that contains some information about the problem;
118          otherwise the routine outputs no comment cards */
119       int mps_obj; /* lpx_write_mps */
120       /* this parameter tells the routine lpx_write_mps how to output
121          the objective function row:
122          0 - never output objective function row
123          1 - always output objective function row
124          2 - output objective function row if and only if the problem
125              has no free rows */
126       int mps_orig; /* lpx_write_mps */
127       /* if this flag is set, the routine lpx_write_mps uses original
128          row and column symbolic names; otherwise the routine generates
129          plain names using ordinal numbers of rows and columns */
130       int mps_wide; /* lpx_write_mps */
131       /* if this flag is set, the routine lpx_write_mps uses all data
132          fields; otherwise the routine keeps fields 5 and 6 empty */
133       int mps_free; /* lpx_write_mps */
134       /* if this flag is set, the routine lpx_write_mps omits column
135          and vector names everytime if possible (free style); otherwise
136          the routine never omits these names (pedantic style) */
137       int mps_skip; /* lpx_write_mps */
138       /* if this flag is set, the routine lpx_write_mps skips empty
139          columns (i.e. which has no constraint coefficients); otherwise
140          the routine outputs all columns */
141       int lpt_orig; /* lpx_write_lpt */
142       /* if this flag is set, the routine lpx_write_lpt uses original
143          row and column symbolic names; otherwise the routine generates
144          plain names using ordinal numbers of rows and columns */
145       int presol; /* lpx_simplex */
146       /* LP presolver option:
147          0 - do not use LP presolver
148          1 - use LP presolver */
149       int binarize; /* lpx_intopt */
150       /* if this flag is set, the routine lpx_intopt replaces integer
151          columns by binary ones */
152       int use_cuts; /* lpx_intopt */
153       /* if this flag is set, the routine lpx_intopt tries generating
154          cutting planes:
155          LPX_C_COVER  - mixed cover cuts
156          LPX_C_CLIQUE - clique cuts
157          LPX_C_GOMORY - Gomory's mixed integer cuts
158          LPX_C_ALL    - all cuts */
159       double mip_gap; /* MIP */
160       /* relative MIP gap tolerance */
161       struct CPS *link;
162       /* pointer to CPS for another problem object */
163 };
164 
165 static struct CPS *cps_ptr = NULL;
166 /* initial pointer to CPS linked list */
167 
find_cps(LPX * lp)168 static struct CPS *find_cps(LPX *lp)
169 {     /* find CPS for specified problem object */
170       struct CPS *cps;
171       for (cps = cps_ptr; cps != NULL; cps = cps->link)
172          if (cps->lp == lp) break;
173       /* if cps is NULL (not found), the problem object was created
174          with glp_create_prob rather than with lpx_create_prob */
175       xassert(cps != NULL);
176       return cps;
177 }
178 
reset_cps(struct CPS * cps)179 static void reset_cps(struct CPS *cps)
180 {     /* reset control parameters to default values */
181       cps->msg_lev  = 3;
182       cps->scale    = 1;
183       cps->dual     = 0;
184       cps->price    = 1;
185       cps->relax    = 0.07;
186       cps->tol_bnd  = 1e-7;
187       cps->tol_dj   = 1e-7;
188       cps->tol_piv  = 1e-9;
189       cps->round    = 0;
190       cps->obj_ll   = -DBL_MAX;
191       cps->obj_ul   = +DBL_MAX;
192       cps->it_lim   = -1;
193       cps->tm_lim   = -1.0;
194       cps->out_frq  = 200;
195       cps->out_dly  = 0.0;
196       cps->branch   = 2;
197       cps->btrack   = 3;
198       cps->tol_int  = 1e-5;
199       cps->tol_obj  = 1e-7;
200       cps->mps_info = 1;
201       cps->mps_obj  = 2;
202       cps->mps_orig = 0;
203       cps->mps_wide = 1;
204       cps->mps_free = 0;
205       cps->mps_skip = 0;
206       cps->lpt_orig = 0;
207       cps->presol   = 0;
208       cps->binarize = 0;
209       cps->use_cuts = 0;
210       cps->mip_gap  = 0.0;
211       return;
212 }
213 
lpx_create_prob(void)214 LPX *lpx_create_prob(void)
215 {     /* create problem object */
216       LPX *lp;
217       struct CPS *cps;
218       lp = glp_create_prob();
219       cps = glp_alloc(1, sizeof(struct CPS));
220       cps->lp = lp;
221       reset_cps(cps);
222       cps->link = cps_ptr;
223       cps_ptr = cps;
224       return lp;
225 }
226 
lpx_set_prob_name(LPX * lp,const char * name)227 void lpx_set_prob_name(LPX *lp, const char *name)
228 {     /* assign (change) problem name */
229       glp_set_prob_name(lp, name);
230       return;
231 }
232 
lpx_set_obj_name(LPX * lp,const char * name)233 void lpx_set_obj_name(LPX *lp, const char *name)
234 {     /* assign (change) objective function name */
235       glp_set_obj_name(lp, name);
236       return;
237 }
238 
lpx_set_obj_dir(LPX * lp,int dir)239 void lpx_set_obj_dir(LPX *lp, int dir)
240 {     /* set (change) optimization direction flag */
241       glp_set_obj_dir(lp, dir - LPX_MIN + GLP_MIN);
242       return;
243 }
244 
lpx_add_rows(LPX * lp,int nrs)245 int lpx_add_rows(LPX *lp, int nrs)
246 {     /* add new rows to problem object */
247       return glp_add_rows(lp, nrs);
248 }
249 
lpx_add_cols(LPX * lp,int ncs)250 int lpx_add_cols(LPX *lp, int ncs)
251 {     /* add new columns to problem object */
252       return glp_add_cols(lp, ncs);
253 }
254 
lpx_set_row_name(LPX * lp,int i,const char * name)255 void lpx_set_row_name(LPX *lp, int i, const char *name)
256 {     /* assign (change) row name */
257       glp_set_row_name(lp, i, name);
258       return;
259 }
260 
lpx_set_col_name(LPX * lp,int j,const char * name)261 void lpx_set_col_name(LPX *lp, int j, const char *name)
262 {     /* assign (change) column name */
263       glp_set_col_name(lp, j, name);
264       return;
265 }
266 
lpx_set_row_bnds(LPX * lp,int i,int type,double lb,double ub)267 void lpx_set_row_bnds(LPX *lp, int i, int type, double lb, double ub)
268 {     /* set (change) row bounds */
269       glp_set_row_bnds(lp, i, type - LPX_FR + GLP_FR, lb, ub);
270       return;
271 }
272 
lpx_set_col_bnds(LPX * lp,int j,int type,double lb,double ub)273 void lpx_set_col_bnds(LPX *lp, int j, int type, double lb, double ub)
274 {     /* set (change) column bounds */
275       glp_set_col_bnds(lp, j, type - LPX_FR + GLP_FR, lb, ub);
276       return;
277 }
278 
lpx_set_obj_coef(glp_prob * lp,int j,double coef)279 void lpx_set_obj_coef(glp_prob *lp, int j, double coef)
280 {     /* set (change) obj. coefficient or constant term */
281       glp_set_obj_coef(lp, j, coef);
282       return;
283 }
284 
lpx_set_mat_row(LPX * lp,int i,int len,const int ind[],const double val[])285 void lpx_set_mat_row(LPX *lp, int i, int len, const int ind[],
286       const double val[])
287 {     /* set (replace) row of the constraint matrix */
288       glp_set_mat_row(lp, i, len, ind, val);
289       return;
290 }
291 
lpx_set_mat_col(LPX * lp,int j,int len,const int ind[],const double val[])292 void lpx_set_mat_col(LPX *lp, int j, int len, const int ind[],
293       const double val[])
294 {     /* set (replace) column of the constraint matrix */
295       glp_set_mat_col(lp, j, len, ind, val);
296       return;
297 }
298 
lpx_load_matrix(LPX * lp,int ne,const int ia[],const int ja[],const double ar[])299 void lpx_load_matrix(LPX *lp, int ne, const int ia[], const int ja[],
300       const double ar[])
301 {     /* load (replace) the whole constraint matrix */
302       glp_load_matrix(lp, ne, ia, ja, ar);
303       return;
304 }
305 
lpx_del_rows(LPX * lp,int nrs,const int num[])306 void lpx_del_rows(LPX *lp, int nrs, const int num[])
307 {     /* delete specified rows from problem object */
308       glp_del_rows(lp, nrs, num);
309       return;
310 }
311 
lpx_del_cols(LPX * lp,int ncs,const int num[])312 void lpx_del_cols(LPX *lp, int ncs, const int num[])
313 {     /* delete specified columns from problem object */
314       glp_del_cols(lp, ncs, num);
315       return;
316 }
317 
lpx_delete_prob(LPX * lp)318 void lpx_delete_prob(LPX *lp)
319 {     /* delete problem object */
320       struct CPS *cps = find_cps(lp);
321       if (cps_ptr == cps)
322          cps_ptr = cps->link;
323       else
324       {  struct CPS *prev;
325          for (prev = cps_ptr; prev != NULL; prev = prev->link)
326             if (prev->link == cps) break;
327          xassert(prev != NULL);
328          prev->link = cps->link;
329       }
330       glp_free(cps);
331       glp_delete_prob(lp);
332       return;
333 }
334 
lpx_get_prob_name(LPX * lp)335 const char *lpx_get_prob_name(LPX *lp)
336 {     /* retrieve problem name */
337       return glp_get_prob_name(lp);
338 }
339 
lpx_get_obj_name(LPX * lp)340 const char *lpx_get_obj_name(LPX *lp)
341 {     /* retrieve objective function name */
342       return glp_get_obj_name(lp);
343 }
344 
lpx_get_obj_dir(LPX * lp)345 int lpx_get_obj_dir(LPX *lp)
346 {     /* retrieve optimization direction flag */
347       return glp_get_obj_dir(lp) - GLP_MIN + LPX_MIN;
348 }
349 
lpx_get_num_rows(LPX * lp)350 int lpx_get_num_rows(LPX *lp)
351 {     /* retrieve number of rows */
352       return glp_get_num_rows(lp);
353 }
354 
lpx_get_num_cols(LPX * lp)355 int lpx_get_num_cols(LPX *lp)
356 {     /* retrieve number of columns */
357       return glp_get_num_cols(lp);
358 }
359 
lpx_get_row_name(LPX * lp,int i)360 const char *lpx_get_row_name(LPX *lp, int i)
361 {     /* retrieve row name */
362       return glp_get_row_name(lp, i);
363 }
364 
lpx_get_col_name(LPX * lp,int j)365 const char *lpx_get_col_name(LPX *lp, int j)
366 {     /* retrieve column name */
367       return glp_get_col_name(lp, j);
368 }
369 
lpx_get_row_type(LPX * lp,int i)370 int lpx_get_row_type(LPX *lp, int i)
371 {     /* retrieve row type */
372       return glp_get_row_type(lp, i) - GLP_FR + LPX_FR;
373 }
374 
lpx_get_row_lb(glp_prob * lp,int i)375 double lpx_get_row_lb(glp_prob *lp, int i)
376 {     /* retrieve row lower bound */
377       double lb;
378       lb = glp_get_row_lb(lp, i);
379       if (lb == -DBL_MAX) lb = 0.0;
380       return lb;
381 }
382 
lpx_get_row_ub(glp_prob * lp,int i)383 double lpx_get_row_ub(glp_prob *lp, int i)
384 {     /* retrieve row upper bound */
385       double ub;
386       ub = glp_get_row_ub(lp, i);
387       if (ub == +DBL_MAX) ub = 0.0;
388       return ub;
389 }
390 
lpx_get_row_bnds(glp_prob * lp,int i,int * typx,double * lb,double * ub)391 void lpx_get_row_bnds(glp_prob *lp, int i, int *typx, double *lb,
392       double *ub)
393 {     /* retrieve row bounds */
394       if (typx != NULL) *typx = lpx_get_row_type(lp, i);
395       if (lb != NULL) *lb = lpx_get_row_lb(lp, i);
396       if (ub != NULL) *ub = lpx_get_row_ub(lp, i);
397       return;
398 }
399 
lpx_get_col_type(LPX * lp,int j)400 int lpx_get_col_type(LPX *lp, int j)
401 {     /* retrieve column type */
402       return glp_get_col_type(lp, j) - GLP_FR + LPX_FR;
403 }
404 
lpx_get_col_lb(glp_prob * lp,int j)405 double lpx_get_col_lb(glp_prob *lp, int j)
406 {     /* retrieve column lower bound */
407       double lb;
408       lb = glp_get_col_lb(lp, j);
409       if (lb == -DBL_MAX) lb = 0.0;
410       return lb;
411 }
412 
lpx_get_col_ub(glp_prob * lp,int j)413 double lpx_get_col_ub(glp_prob *lp, int j)
414 {     /* retrieve column upper bound */
415       double ub;
416       ub = glp_get_col_ub(lp, j);
417       if (ub == +DBL_MAX) ub = 0.0;
418       return ub;
419 }
420 
lpx_get_col_bnds(glp_prob * lp,int j,int * typx,double * lb,double * ub)421 void lpx_get_col_bnds(glp_prob *lp, int j, int *typx, double *lb,
422       double *ub)
423 {     /* retrieve column bounds */
424       if (typx != NULL) *typx = lpx_get_col_type(lp, j);
425       if (lb != NULL) *lb = lpx_get_col_lb(lp, j);
426       if (ub != NULL) *ub = lpx_get_col_ub(lp, j);
427       return;
428 }
429 
lpx_get_obj_coef(LPX * lp,int j)430 double lpx_get_obj_coef(LPX *lp, int j)
431 {     /* retrieve obj. coefficient or constant term */
432       return glp_get_obj_coef(lp, j);
433 }
434 
lpx_get_num_nz(LPX * lp)435 int lpx_get_num_nz(LPX *lp)
436 {     /* retrieve number of constraint coefficients */
437       return glp_get_num_nz(lp);
438 }
439 
lpx_get_mat_row(LPX * lp,int i,int ind[],double val[])440 int lpx_get_mat_row(LPX *lp, int i, int ind[], double val[])
441 {     /* retrieve row of the constraint matrix */
442       return glp_get_mat_row(lp, i, ind, val);
443 }
444 
lpx_get_mat_col(LPX * lp,int j,int ind[],double val[])445 int lpx_get_mat_col(LPX *lp, int j, int ind[], double val[])
446 {     /* retrieve column of the constraint matrix */
447       return glp_get_mat_col(lp, j, ind, val);
448 }
449 
lpx_create_index(LPX * lp)450 void lpx_create_index(LPX *lp)
451 {     /* create the name index */
452       glp_create_index(lp);
453       return;
454 }
455 
lpx_find_row(LPX * lp,const char * name)456 int lpx_find_row(LPX *lp, const char *name)
457 {     /* find row by its name */
458       return glp_find_row(lp, name);
459 }
460 
lpx_find_col(LPX * lp,const char * name)461 int lpx_find_col(LPX *lp, const char *name)
462 {     /* find column by its name */
463       return glp_find_col(lp, name);
464 }
465 
lpx_delete_index(LPX * lp)466 void lpx_delete_index(LPX *lp)
467 {     /* delete the name index */
468       glp_delete_index(lp);
469       return;
470 }
471 
lpx_scale_prob(LPX * lp)472 void lpx_scale_prob(LPX *lp)
473 {     /* scale problem data */
474       switch (lpx_get_int_parm(lp, LPX_K_SCALE))
475       {  case 0:
476             /* no scaling */
477             glp_unscale_prob(lp);
478             break;
479          case 1:
480             /* equilibration scaling */
481             glp_scale_prob(lp, GLP_SF_EQ);
482             break;
483          case 2:
484             /* geometric mean scaling */
485             glp_scale_prob(lp, GLP_SF_GM);
486             break;
487          case 3:
488             /* geometric mean scaling, then equilibration scaling */
489             glp_scale_prob(lp, GLP_SF_GM | GLP_SF_EQ);
490             break;
491          default:
492             xassert(lp != lp);
493       }
494       return;
495 }
496 
lpx_unscale_prob(LPX * lp)497 void lpx_unscale_prob(LPX *lp)
498 {     /* unscale problem data */
499       glp_unscale_prob(lp);
500       return;
501 }
502 
lpx_set_row_stat(LPX * lp,int i,int stat)503 void lpx_set_row_stat(LPX *lp, int i, int stat)
504 {     /* set (change) row status */
505       glp_set_row_stat(lp, i, stat - LPX_BS + GLP_BS);
506       return;
507 }
508 
lpx_set_col_stat(LPX * lp,int j,int stat)509 void lpx_set_col_stat(LPX *lp, int j, int stat)
510 {     /* set (change) column status */
511       glp_set_col_stat(lp, j, stat - LPX_BS + GLP_BS);
512       return;
513 }
514 
lpx_std_basis(LPX * lp)515 void lpx_std_basis(LPX *lp)
516 {     /* construct standard initial LP basis */
517       glp_std_basis(lp);
518       return;
519 }
520 
lpx_adv_basis(LPX * lp)521 void lpx_adv_basis(LPX *lp)
522 {     /* construct advanced initial LP basis */
523       glp_adv_basis(lp, 0);
524       return;
525 }
526 
lpx_cpx_basis(LPX * lp)527 void lpx_cpx_basis(LPX *lp)
528 {     /* construct Bixby's initial LP basis */
529       glp_cpx_basis(lp);
530       return;
531 }
532 
fill_smcp(LPX * lp,glp_smcp * parm)533 static void fill_smcp(LPX *lp, glp_smcp *parm)
534 {     glp_init_smcp(parm);
535       switch (lpx_get_int_parm(lp, LPX_K_MSGLEV))
536       {  case 0:  parm->msg_lev = GLP_MSG_OFF;   break;
537          case 1:  parm->msg_lev = GLP_MSG_ERR;   break;
538          case 2:  parm->msg_lev = GLP_MSG_ON;    break;
539          case 3:  parm->msg_lev = GLP_MSG_ALL;   break;
540          default: xassert(lp != lp);
541       }
542       switch (lpx_get_int_parm(lp, LPX_K_DUAL))
543       {  case 0:  parm->meth = GLP_PRIMAL;       break;
544          case 1:  parm->meth = GLP_DUAL;         break;
545          default: xassert(lp != lp);
546       }
547       switch (lpx_get_int_parm(lp, LPX_K_PRICE))
548       {  case 0:  parm->pricing = GLP_PT_STD;    break;
549          case 1:  parm->pricing = GLP_PT_PSE;    break;
550          default: xassert(lp != lp);
551       }
552       if (lpx_get_real_parm(lp, LPX_K_RELAX) == 0.0)
553          parm->r_test = GLP_RT_STD;
554       else
555          parm->r_test = GLP_RT_HAR;
556       parm->tol_bnd = lpx_get_real_parm(lp, LPX_K_TOLBND);
557       parm->tol_dj  = lpx_get_real_parm(lp, LPX_K_TOLDJ);
558       parm->tol_piv = lpx_get_real_parm(lp, LPX_K_TOLPIV);
559       parm->obj_ll  = lpx_get_real_parm(lp, LPX_K_OBJLL);
560       parm->obj_ul  = lpx_get_real_parm(lp, LPX_K_OBJUL);
561       if (lpx_get_int_parm(lp, LPX_K_ITLIM) < 0)
562          parm->it_lim = INT_MAX;
563       else
564          parm->it_lim = lpx_get_int_parm(lp, LPX_K_ITLIM);
565       if (lpx_get_real_parm(lp, LPX_K_TMLIM) < 0.0)
566          parm->tm_lim = INT_MAX;
567       else
568          parm->tm_lim =
569             (int)(1000.0 * lpx_get_real_parm(lp, LPX_K_TMLIM));
570       parm->out_frq = lpx_get_int_parm(lp, LPX_K_OUTFRQ);
571       parm->out_dly =
572             (int)(1000.0 * lpx_get_real_parm(lp, LPX_K_OUTDLY));
573       switch (lpx_get_int_parm(lp, LPX_K_PRESOL))
574       {  case 0:  parm->presolve = GLP_OFF;      break;
575          case 1:  parm->presolve = GLP_ON;       break;
576          default: xassert(lp != lp);
577       }
578       return;
579 }
580 
lpx_simplex(LPX * lp)581 int lpx_simplex(LPX *lp)
582 {     /* easy-to-use driver to the simplex method */
583       glp_smcp parm;
584       int ret;
585       fill_smcp(lp, &parm);
586       ret = glp_simplex(lp, &parm);
587       switch (ret)
588       {  case 0:           ret = LPX_E_OK;      break;
589          case GLP_EBADB:
590          case GLP_ESING:
591          case GLP_ECOND:
592          case GLP_EBOUND:  ret = LPX_E_FAULT;   break;
593          case GLP_EFAIL:   ret = LPX_E_SING;    break;
594          case GLP_EOBJLL:  ret = LPX_E_OBJLL;   break;
595          case GLP_EOBJUL:  ret = LPX_E_OBJUL;   break;
596          case GLP_EITLIM:  ret = LPX_E_ITLIM;   break;
597          case GLP_ETMLIM:  ret = LPX_E_TMLIM;   break;
598          case GLP_ENOPFS:  ret = LPX_E_NOPFS;   break;
599          case GLP_ENODFS:  ret = LPX_E_NODFS;   break;
600          default:          xassert(ret != ret);
601       }
602       return ret;
603 }
604 
lpx_exact(LPX * lp)605 int lpx_exact(LPX *lp)
606 {     /* easy-to-use driver to the exact simplex method */
607       glp_smcp parm;
608       int ret;
609       fill_smcp(lp, &parm);
610       ret = glp_exact(lp, &parm);
611       switch (ret)
612       {  case 0:           ret = LPX_E_OK;      break;
613          case GLP_EBADB:
614          case GLP_ESING:
615          case GLP_EBOUND:
616          case GLP_EFAIL:   ret = LPX_E_FAULT;   break;
617          case GLP_EITLIM:  ret = LPX_E_ITLIM;   break;
618          case GLP_ETMLIM:  ret = LPX_E_TMLIM;   break;
619          default:          xassert(ret != ret);
620       }
621       return ret;
622 }
623 
lpx_get_status(glp_prob * lp)624 int lpx_get_status(glp_prob *lp)
625 {     /* retrieve generic status of basic solution */
626       int status;
627       switch (glp_get_status(lp))
628       {  case GLP_OPT:    status = LPX_OPT;    break;
629          case GLP_FEAS:   status = LPX_FEAS;   break;
630          case GLP_INFEAS: status = LPX_INFEAS; break;
631          case GLP_NOFEAS: status = LPX_NOFEAS; break;
632          case GLP_UNBND:  status = LPX_UNBND;  break;
633          case GLP_UNDEF:  status = LPX_UNDEF;  break;
634          default:         xassert(lp != lp);
635       }
636       return status;
637 }
638 
lpx_get_prim_stat(glp_prob * lp)639 int lpx_get_prim_stat(glp_prob *lp)
640 {     /* retrieve status of primal basic solution */
641       return glp_get_prim_stat(lp) - GLP_UNDEF + LPX_P_UNDEF;
642 }
643 
lpx_get_dual_stat(glp_prob * lp)644 int lpx_get_dual_stat(glp_prob *lp)
645 {     /* retrieve status of dual basic solution */
646       return glp_get_dual_stat(lp) - GLP_UNDEF + LPX_D_UNDEF;
647 }
648 
lpx_get_obj_val(LPX * lp)649 double lpx_get_obj_val(LPX *lp)
650 {     /* retrieve objective value (basic solution) */
651       return glp_get_obj_val(lp);
652 }
653 
lpx_get_row_stat(LPX * lp,int i)654 int lpx_get_row_stat(LPX *lp, int i)
655 {     /* retrieve row status (basic solution) */
656       return glp_get_row_stat(lp, i) - GLP_BS + LPX_BS;
657 }
658 
lpx_get_row_prim(LPX * lp,int i)659 double lpx_get_row_prim(LPX *lp, int i)
660 {     /* retrieve row primal value (basic solution) */
661       return glp_get_row_prim(lp, i);
662 }
663 
lpx_get_row_dual(LPX * lp,int i)664 double lpx_get_row_dual(LPX *lp, int i)
665 {     /* retrieve row dual value (basic solution) */
666       return glp_get_row_dual(lp, i);
667 }
668 
lpx_get_row_info(glp_prob * lp,int i,int * tagx,double * vx,double * dx)669 void lpx_get_row_info(glp_prob *lp, int i, int *tagx, double *vx,
670       double *dx)
671 {     /* obtain row solution information */
672       if (tagx != NULL) *tagx = lpx_get_row_stat(lp, i);
673       if (vx != NULL) *vx = lpx_get_row_prim(lp, i);
674       if (dx != NULL) *dx = lpx_get_row_dual(lp, i);
675       return;
676 }
677 
lpx_get_col_stat(LPX * lp,int j)678 int lpx_get_col_stat(LPX *lp, int j)
679 {     /* retrieve column status (basic solution) */
680       return glp_get_col_stat(lp, j) - GLP_BS + LPX_BS;
681 }
682 
lpx_get_col_prim(LPX * lp,int j)683 double lpx_get_col_prim(LPX *lp, int j)
684 {     /* retrieve column primal value (basic solution) */
685       return glp_get_col_prim(lp, j);
686 }
687 
lpx_get_col_dual(glp_prob * lp,int j)688 double lpx_get_col_dual(glp_prob *lp, int j)
689 {     /* retrieve column dual value (basic solution) */
690       return glp_get_col_dual(lp, j);
691 }
692 
lpx_get_col_info(glp_prob * lp,int j,int * tagx,double * vx,double * dx)693 void lpx_get_col_info(glp_prob *lp, int j, int *tagx, double *vx,
694       double *dx)
695 {     /* obtain column solution information */
696       if (tagx != NULL) *tagx = lpx_get_col_stat(lp, j);
697       if (vx != NULL) *vx = lpx_get_col_prim(lp, j);
698       if (dx != NULL) *dx = lpx_get_col_dual(lp, j);
699       return;
700 }
701 
lpx_get_ray_info(LPX * lp)702 int lpx_get_ray_info(LPX *lp)
703 {     /* determine what causes primal unboundness */
704       return glp_get_unbnd_ray(lp);
705 }
706 
lpx_check_kkt(LPX * lp,int scaled,LPXKKT * kkt)707 void lpx_check_kkt(LPX *lp, int scaled, LPXKKT *kkt)
708 {     /* check Karush-Kuhn-Tucker conditions */
709       int m = glp_get_num_rows(lp);
710       int ae_ind, re_ind;
711       double ae_max, re_max;
712       xassert(scaled == scaled);
713       glp_check_kkt(lp, GLP_SOL, GLP_KKT_PE, &ae_max, &ae_ind, &re_max,
714          &re_ind);
715       kkt->pe_ae_max = ae_max;
716       kkt->pe_ae_row = ae_ind;
717       kkt->pe_re_max = re_max;
718       kkt->pe_re_row = re_ind;
719       if (re_max <= 1e-9)
720          kkt->pe_quality = 'H';
721       else if (re_max <= 1e-6)
722          kkt->pe_quality = 'M';
723       else if (re_max <= 1e-3)
724          kkt->pe_quality = 'L';
725       else
726          kkt->pe_quality = '?';
727       glp_check_kkt(lp, GLP_SOL, GLP_KKT_PB, &ae_max, &ae_ind, &re_max,
728          &re_ind);
729       kkt->pb_ae_max = ae_max;
730       kkt->pb_ae_ind = ae_ind;
731       kkt->pb_re_max = re_max;
732       kkt->pb_re_ind = re_ind;
733       if (re_max <= 1e-9)
734          kkt->pb_quality = 'H';
735       else if (re_max <= 1e-6)
736          kkt->pb_quality = 'M';
737       else if (re_max <= 1e-3)
738          kkt->pb_quality = 'L';
739       else
740          kkt->pb_quality = '?';
741       glp_check_kkt(lp, GLP_SOL, GLP_KKT_DE, &ae_max, &ae_ind, &re_max,
742          &re_ind);
743       kkt->de_ae_max = ae_max;
744       if (ae_ind == 0)
745          kkt->de_ae_col = 0;
746       else
747          kkt->de_ae_col = ae_ind - m;
748       kkt->de_re_max = re_max;
749       if (re_ind == 0)
750          kkt->de_re_col = 0;
751       else
752          kkt->de_re_col = ae_ind - m;
753       if (re_max <= 1e-9)
754          kkt->de_quality = 'H';
755       else if (re_max <= 1e-6)
756          kkt->de_quality = 'M';
757       else if (re_max <= 1e-3)
758          kkt->de_quality = 'L';
759       else
760          kkt->de_quality = '?';
761       glp_check_kkt(lp, GLP_SOL, GLP_KKT_DB, &ae_max, &ae_ind, &re_max,
762          &re_ind);
763       kkt->db_ae_max = ae_max;
764       kkt->db_ae_ind = ae_ind;
765       kkt->db_re_max = re_max;
766       kkt->db_re_ind = re_ind;
767       if (re_max <= 1e-9)
768          kkt->db_quality = 'H';
769       else if (re_max <= 1e-6)
770          kkt->db_quality = 'M';
771       else if (re_max <= 1e-3)
772          kkt->db_quality = 'L';
773       else
774          kkt->db_quality = '?';
775       kkt->cs_ae_max = 0.0, kkt->cs_ae_ind = 0;
776       kkt->cs_re_max = 0.0, kkt->cs_re_ind = 0;
777       kkt->cs_quality = 'H';
778       return;
779 }
780 
lpx_warm_up(LPX * lp)781 int lpx_warm_up(LPX *lp)
782 {     /* "warm up" LP basis */
783       int ret;
784       ret = glp_warm_up(lp);
785       if (ret == 0)
786          ret = LPX_E_OK;
787       else if (ret == GLP_EBADB)
788          ret = LPX_E_BADB;
789       else if (ret == GLP_ESING)
790          ret = LPX_E_SING;
791       else if (ret == GLP_ECOND)
792          ret = LPX_E_SING;
793       else
794          xassert(ret != ret);
795       return ret;
796 }
797 
lpx_eval_tab_row(LPX * lp,int k,int ind[],double val[])798 int lpx_eval_tab_row(LPX *lp, int k, int ind[], double val[])
799 {     /* compute row of the simplex tableau */
800       return glp_eval_tab_row(lp, k, ind, val);
801 }
802 
lpx_eval_tab_col(LPX * lp,int k,int ind[],double val[])803 int lpx_eval_tab_col(LPX *lp, int k, int ind[], double val[])
804 {     /* compute column of the simplex tableau */
805       return glp_eval_tab_col(lp, k, ind, val);
806 }
807 
lpx_transform_row(LPX * lp,int len,int ind[],double val[])808 int lpx_transform_row(LPX *lp, int len, int ind[], double val[])
809 {     /* transform explicitly specified row */
810       return glp_transform_row(lp, len, ind, val);
811 }
812 
lpx_transform_col(LPX * lp,int len,int ind[],double val[])813 int lpx_transform_col(LPX *lp, int len, int ind[], double val[])
814 {     /* transform explicitly specified column */
815       return glp_transform_col(lp, len, ind, val);
816 }
817 
lpx_prim_ratio_test(LPX * lp,int len,const int ind[],const double val[],int how,double tol)818 int lpx_prim_ratio_test(LPX *lp, int len, const int ind[],
819       const double val[], int how, double tol)
820 {     /* perform primal ratio test */
821       int piv;
822       piv = glp_prim_rtest(lp, len, ind, val, how, tol);
823       xassert(0 <= piv && piv <= len);
824       return piv == 0 ? 0 : ind[piv];
825 }
826 
lpx_dual_ratio_test(LPX * lp,int len,const int ind[],const double val[],int how,double tol)827 int lpx_dual_ratio_test(LPX *lp, int len, const int ind[],
828       const double val[], int how, double tol)
829 {     /* perform dual ratio test */
830       int piv;
831       piv = glp_dual_rtest(lp, len, ind, val, how, tol);
832       xassert(0 <= piv && piv <= len);
833       return piv == 0 ? 0 : ind[piv];
834 }
835 
lpx_interior(LPX * lp)836 int lpx_interior(LPX *lp)
837 {     /* easy-to-use driver to the interior-point method */
838       int ret;
839       ret = glp_interior(lp, NULL);
840       switch (ret)
841       {  case 0:           ret = LPX_E_OK;      break;
842          case GLP_EFAIL:   ret = LPX_E_FAULT;   break;
843          case GLP_ENOFEAS: ret = LPX_E_NOFEAS;  break;
844          case GLP_ENOCVG:  ret = LPX_E_NOCONV;  break;
845          case GLP_EITLIM:  ret = LPX_E_ITLIM;   break;
846          case GLP_EINSTAB: ret = LPX_E_INSTAB;  break;
847          default:          xassert(ret != ret);
848       }
849       return ret;
850 }
851 
lpx_ipt_status(glp_prob * lp)852 int lpx_ipt_status(glp_prob *lp)
853 {     /* retrieve status of interior-point solution */
854       int status;
855       switch (glp_ipt_status(lp))
856       {  case GLP_UNDEF:  status = LPX_T_UNDEF;  break;
857          case GLP_OPT:    status = LPX_T_OPT;    break;
858          default:         xassert(lp != lp);
859       }
860       return status;
861 }
862 
lpx_ipt_obj_val(LPX * lp)863 double lpx_ipt_obj_val(LPX *lp)
864 {     /* retrieve objective value (interior point) */
865       return glp_ipt_obj_val(lp);
866 }
867 
lpx_ipt_row_prim(LPX * lp,int i)868 double lpx_ipt_row_prim(LPX *lp, int i)
869 {     /* retrieve row primal value (interior point) */
870       return glp_ipt_row_prim(lp, i);
871 }
872 
lpx_ipt_row_dual(LPX * lp,int i)873 double lpx_ipt_row_dual(LPX *lp, int i)
874 {     /* retrieve row dual value (interior point) */
875       return glp_ipt_row_dual(lp, i);
876 }
877 
lpx_ipt_col_prim(LPX * lp,int j)878 double lpx_ipt_col_prim(LPX *lp, int j)
879 {     /* retrieve column primal value (interior point) */
880       return glp_ipt_col_prim(lp, j);
881 }
882 
lpx_ipt_col_dual(LPX * lp,int j)883 double lpx_ipt_col_dual(LPX *lp, int j)
884 {     /* retrieve column dual value (interior point) */
885       return glp_ipt_col_dual(lp, j);
886 }
887 
lpx_set_class(LPX * lp,int klass)888 void lpx_set_class(LPX *lp, int klass)
889 {     /* set problem class */
890       xassert(lp == lp);
891       if (!(klass == LPX_LP || klass == LPX_MIP))
892          xerror("lpx_set_class: invalid problem class\n");
893       return;
894 }
895 
lpx_get_class(LPX * lp)896 int lpx_get_class(LPX *lp)
897 {     /* determine problem klass */
898       return glp_get_num_int(lp) == 0 ? LPX_LP : LPX_MIP;
899 }
900 
lpx_set_col_kind(LPX * lp,int j,int kind)901 void lpx_set_col_kind(LPX *lp, int j, int kind)
902 {     /* set (change) column kind */
903       glp_set_col_kind(lp, j, kind - LPX_CV + GLP_CV);
904       return;
905 }
906 
lpx_get_col_kind(LPX * lp,int j)907 int lpx_get_col_kind(LPX *lp, int j)
908 {     /* retrieve column kind */
909       return glp_get_col_kind(lp, j) == GLP_CV ? LPX_CV : LPX_IV;
910 }
911 
lpx_get_num_int(LPX * lp)912 int lpx_get_num_int(LPX *lp)
913 {     /* retrieve number of integer columns */
914       return glp_get_num_int(lp);
915 }
916 
lpx_get_num_bin(LPX * lp)917 int lpx_get_num_bin(LPX *lp)
918 {     /* retrieve number of binary columns */
919       return glp_get_num_bin(lp);
920 }
921 
solve_mip(LPX * lp,int presolve)922 static int solve_mip(LPX *lp, int presolve)
923 {     glp_iocp parm;
924       int ret;
925       glp_init_iocp(&parm);
926       switch (lpx_get_int_parm(lp, LPX_K_MSGLEV))
927       {  case 0:  parm.msg_lev = GLP_MSG_OFF;   break;
928          case 1:  parm.msg_lev = GLP_MSG_ERR;   break;
929          case 2:  parm.msg_lev = GLP_MSG_ON;    break;
930          case 3:  parm.msg_lev = GLP_MSG_ALL;   break;
931          default: xassert(lp != lp);
932       }
933       switch (lpx_get_int_parm(lp, LPX_K_BRANCH))
934       {  case 0:  parm.br_tech = GLP_BR_FFV;    break;
935          case 1:  parm.br_tech = GLP_BR_LFV;    break;
936          case 2:  parm.br_tech = GLP_BR_DTH;    break;
937          case 3:  parm.br_tech = GLP_BR_MFV;    break;
938          default: xassert(lp != lp);
939       }
940       switch (lpx_get_int_parm(lp, LPX_K_BTRACK))
941       {  case 0:  parm.bt_tech = GLP_BT_DFS;    break;
942          case 1:  parm.bt_tech = GLP_BT_BFS;    break;
943          case 2:  parm.bt_tech = GLP_BT_BPH;    break;
944          case 3:  parm.bt_tech = GLP_BT_BLB;    break;
945          default: xassert(lp != lp);
946       }
947       parm.tol_int = lpx_get_real_parm(lp, LPX_K_TOLINT);
948       parm.tol_obj = lpx_get_real_parm(lp, LPX_K_TOLOBJ);
949       if (lpx_get_real_parm(lp, LPX_K_TMLIM) < 0.0 ||
950           lpx_get_real_parm(lp, LPX_K_TMLIM) > 1e6)
951          parm.tm_lim = INT_MAX;
952       else
953          parm.tm_lim =
954             (int)(1000.0 * lpx_get_real_parm(lp, LPX_K_TMLIM));
955       parm.mip_gap = lpx_get_real_parm(lp, LPX_K_MIPGAP);
956       if (lpx_get_int_parm(lp, LPX_K_USECUTS) & LPX_C_GOMORY)
957          parm.gmi_cuts = GLP_ON;
958       else
959          parm.gmi_cuts = GLP_OFF;
960       if (lpx_get_int_parm(lp, LPX_K_USECUTS) & LPX_C_MIR)
961          parm.mir_cuts = GLP_ON;
962       else
963          parm.mir_cuts = GLP_OFF;
964       if (lpx_get_int_parm(lp, LPX_K_USECUTS) & LPX_C_COVER)
965          parm.cov_cuts = GLP_ON;
966       else
967          parm.cov_cuts = GLP_OFF;
968       if (lpx_get_int_parm(lp, LPX_K_USECUTS) & LPX_C_CLIQUE)
969          parm.clq_cuts = GLP_ON;
970       else
971          parm.clq_cuts = GLP_OFF;
972       parm.presolve = presolve;
973       if (lpx_get_int_parm(lp, LPX_K_BINARIZE))
974          parm.binarize = GLP_ON;
975       ret = glp_intopt(lp, &parm);
976       switch (ret)
977       {  case 0:           ret = LPX_E_OK;      break;
978          case GLP_ENOPFS:  ret = LPX_E_NOPFS;   break;
979          case GLP_ENODFS:  ret = LPX_E_NODFS;   break;
980          case GLP_EBOUND:
981          case GLP_EROOT:   ret = LPX_E_FAULT;   break;
982          case GLP_EFAIL:   ret = LPX_E_SING;    break;
983          case GLP_EMIPGAP: ret = LPX_E_MIPGAP;  break;
984          case GLP_ETMLIM:  ret = LPX_E_TMLIM;   break;
985          default:          xassert(ret != ret);
986       }
987       return ret;
988 }
989 
lpx_integer(LPX * lp)990 int lpx_integer(LPX *lp)
991 {     /* easy-to-use driver to the branch-and-bound method */
992       return solve_mip(lp, GLP_OFF);
993 }
994 
lpx_intopt(LPX * lp)995 int lpx_intopt(LPX *lp)
996 {     /* easy-to-use driver to the branch-and-bound method */
997       return solve_mip(lp, GLP_ON);
998 }
999 
lpx_mip_status(glp_prob * lp)1000 int lpx_mip_status(glp_prob *lp)
1001 {     /* retrieve status of MIP solution */
1002       int status;
1003       switch (glp_mip_status(lp))
1004       {  case GLP_UNDEF:  status = LPX_I_UNDEF;  break;
1005          case GLP_OPT:    status = LPX_I_OPT;    break;
1006          case GLP_FEAS:   status = LPX_I_FEAS;   break;
1007          case GLP_NOFEAS: status = LPX_I_NOFEAS; break;
1008          default:         xassert(lp != lp);
1009       }
1010       return status;
1011 }
1012 
lpx_mip_obj_val(LPX * lp)1013 double lpx_mip_obj_val(LPX *lp)
1014 {     /* retrieve objective value (MIP solution) */
1015       return glp_mip_obj_val(lp);
1016 }
1017 
lpx_mip_row_val(LPX * lp,int i)1018 double lpx_mip_row_val(LPX *lp, int i)
1019 {     /* retrieve row value (MIP solution) */
1020       return glp_mip_row_val(lp, i);
1021 }
1022 
lpx_mip_col_val(LPX * lp,int j)1023 double lpx_mip_col_val(LPX *lp, int j)
1024 {     /* retrieve column value (MIP solution) */
1025       return glp_mip_col_val(lp, j);
1026 }
1027 
lpx_check_int(LPX * lp,LPXKKT * kkt)1028 void lpx_check_int(LPX *lp, LPXKKT *kkt)
1029 {     /* check integer feasibility conditions */
1030       int ae_ind, re_ind;
1031       double ae_max, re_max;
1032       glp_check_kkt(lp, GLP_MIP, GLP_KKT_PE, &ae_max, &ae_ind, &re_max,
1033          &re_ind);
1034       kkt->pe_ae_max = ae_max;
1035       kkt->pe_ae_row = ae_ind;
1036       kkt->pe_re_max = re_max;
1037       kkt->pe_re_row = re_ind;
1038       if (re_max <= 1e-9)
1039          kkt->pe_quality = 'H';
1040       else if (re_max <= 1e-6)
1041          kkt->pe_quality = 'M';
1042       else if (re_max <= 1e-3)
1043          kkt->pe_quality = 'L';
1044       else
1045          kkt->pe_quality = '?';
1046       glp_check_kkt(lp, GLP_MIP, GLP_KKT_PB, &ae_max, &ae_ind, &re_max,
1047          &re_ind);
1048       kkt->pb_ae_max = ae_max;
1049       kkt->pb_ae_ind = ae_ind;
1050       kkt->pb_re_max = re_max;
1051       kkt->pb_re_ind = re_ind;
1052       if (re_max <= 1e-9)
1053          kkt->pb_quality = 'H';
1054       else if (re_max <= 1e-6)
1055          kkt->pb_quality = 'M';
1056       else if (re_max <= 1e-3)
1057          kkt->pb_quality = 'L';
1058       else
1059          kkt->pb_quality = '?';
1060       return;
1061 }
1062 
lpx_reset_parms(LPX * lp)1063 void lpx_reset_parms(LPX *lp)
1064 {     /* reset control parameters to default values */
1065       struct CPS *cps = find_cps(lp);
1066       reset_cps(cps);
1067       return;
1068 }
1069 
lpx_set_int_parm(LPX * lp,int parm,int val)1070 void lpx_set_int_parm(LPX *lp, int parm, int val)
1071 {     /* set (change) integer control parameter */
1072       struct CPS *cps = find_cps(lp);
1073       switch (parm)
1074       {  case LPX_K_MSGLEV:
1075             if (!(0 <= val && val <= 3))
1076                xerror("lpx_set_int_parm: MSGLEV = %d; invalid value\n",
1077                   val);
1078             cps->msg_lev = val;
1079             break;
1080          case LPX_K_SCALE:
1081             if (!(0 <= val && val <= 3))
1082                xerror("lpx_set_int_parm: SCALE = %d; invalid value\n",
1083                   val);
1084             cps->scale = val;
1085             break;
1086          case LPX_K_DUAL:
1087             if (!(val == 0 || val == 1))
1088                xerror("lpx_set_int_parm: DUAL = %d; invalid value\n",
1089                   val);
1090             cps->dual = val;
1091             break;
1092          case LPX_K_PRICE:
1093             if (!(val == 0 || val == 1))
1094                xerror("lpx_set_int_parm: PRICE = %d; invalid value\n",
1095                   val);
1096             cps->price = val;
1097             break;
1098          case LPX_K_ROUND:
1099             if (!(val == 0 || val == 1))
1100                xerror("lpx_set_int_parm: ROUND = %d; invalid value\n",
1101                   val);
1102             cps->round = val;
1103             break;
1104          case LPX_K_ITLIM:
1105             cps->it_lim = val;
1106             break;
1107          case LPX_K_ITCNT:
1108             glp_set_it_cnt(lp, val);
1109             break;
1110          case LPX_K_OUTFRQ:
1111             if (!(val > 0))
1112                xerror("lpx_set_int_parm: OUTFRQ = %d; invalid value\n",
1113                   val);
1114             cps->out_frq = val;
1115             break;
1116          case LPX_K_BRANCH:
1117             if (!(val == 0 || val == 1 || val == 2 || val == 3))
1118                xerror("lpx_set_int_parm: BRANCH = %d; invalid value\n",
1119                   val);
1120             cps->branch = val;
1121             break;
1122          case LPX_K_BTRACK:
1123             if (!(val == 0 || val == 1 || val == 2 || val == 3))
1124                xerror("lpx_set_int_parm: BTRACK = %d; invalid value\n",
1125                   val);
1126             cps->btrack = val;
1127             break;
1128          case LPX_K_MPSINFO:
1129             if (!(val == 0 || val == 1))
1130                xerror("lpx_set_int_parm: MPSINFO = %d; invalid value\n",
1131                   val);
1132             cps->mps_info = val;
1133             break;
1134          case LPX_K_MPSOBJ:
1135             if (!(val == 0 || val == 1 || val == 2))
1136                xerror("lpx_set_int_parm: MPSOBJ = %d; invalid value\n",
1137                   val);
1138             cps->mps_obj = val;
1139             break;
1140          case LPX_K_MPSORIG:
1141             if (!(val == 0 || val == 1))
1142                xerror("lpx_set_int_parm: MPSORIG = %d; invalid value\n",
1143                   val);
1144             cps->mps_orig = val;
1145             break;
1146          case LPX_K_MPSWIDE:
1147             if (!(val == 0 || val == 1))
1148                xerror("lpx_set_int_parm: MPSWIDE = %d; invalid value\n",
1149                   val);
1150             cps->mps_wide = val;
1151             break;
1152          case LPX_K_MPSFREE:
1153             if (!(val == 0 || val == 1))
1154                xerror("lpx_set_int_parm: MPSFREE = %d; invalid value\n",
1155                   val);
1156             cps->mps_free = val;
1157             break;
1158          case LPX_K_MPSSKIP:
1159             if (!(val == 0 || val == 1))
1160                xerror("lpx_set_int_parm: MPSSKIP = %d; invalid value\n",
1161                   val);
1162             cps->mps_skip = val;
1163             break;
1164          case LPX_K_LPTORIG:
1165             if (!(val == 0 || val == 1))
1166                xerror("lpx_set_int_parm: LPTORIG = %d; invalid value\n",
1167                   val);
1168             cps->lpt_orig = val;
1169             break;
1170          case LPX_K_PRESOL:
1171             if (!(val == 0 || val == 1))
1172                xerror("lpx_set_int_parm: PRESOL = %d; invalid value\n",
1173                   val);
1174             cps->presol = val;
1175             break;
1176          case LPX_K_BINARIZE:
1177             if (!(val == 0 || val == 1))
1178                xerror("lpx_set_int_parm: BINARIZE = %d; invalid value\n"
1179                   , val);
1180             cps->binarize = val;
1181             break;
1182          case LPX_K_USECUTS:
1183             if (val & ~LPX_C_ALL)
1184             xerror("lpx_set_int_parm: USECUTS = 0x%X; invalid value\n",
1185                   val);
1186             cps->use_cuts = val;
1187             break;
1188          case LPX_K_BFTYPE:
1189             {  glp_bfcp parm;
1190                glp_get_bfcp(lp, &parm);
1191                switch (val)
1192                {  case 1:
1193                      parm.type = GLP_BF_FT; break;
1194                   case 2:
1195                      parm.type = GLP_BF_BG; break;
1196                   case 3:
1197                      parm.type = GLP_BF_GR; break;
1198                   default:
1199                      xerror("lpx_set_int_parm: BFTYPE = %d; invalid val"
1200                         "ue\n", val);
1201                }
1202                glp_set_bfcp(lp, &parm);
1203             }
1204             break;
1205          default:
1206             xerror("lpx_set_int_parm: parm = %d; invalid parameter\n",
1207                parm);
1208       }
1209       return;
1210 }
1211 
lpx_get_int_parm(LPX * lp,int parm)1212 int lpx_get_int_parm(LPX *lp, int parm)
1213 {     /* query integer control parameter */
1214       struct CPS *cps = find_cps(lp);
1215       int val = 0;
1216       switch (parm)
1217       {  case LPX_K_MSGLEV:
1218             val = cps->msg_lev; break;
1219          case LPX_K_SCALE:
1220             val = cps->scale; break;
1221          case LPX_K_DUAL:
1222             val = cps->dual; break;
1223          case LPX_K_PRICE:
1224             val = cps->price; break;
1225          case LPX_K_ROUND:
1226             val = cps->round; break;
1227          case LPX_K_ITLIM:
1228             val = cps->it_lim; break;
1229          case LPX_K_ITCNT:
1230             val = glp_get_it_cnt(lp); break;
1231          case LPX_K_OUTFRQ:
1232             val = cps->out_frq; break;
1233          case LPX_K_BRANCH:
1234             val = cps->branch; break;
1235          case LPX_K_BTRACK:
1236             val = cps->btrack; break;
1237          case LPX_K_MPSINFO:
1238             val = cps->mps_info; break;
1239          case LPX_K_MPSOBJ:
1240             val = cps->mps_obj; break;
1241          case LPX_K_MPSORIG:
1242             val = cps->mps_orig; break;
1243          case LPX_K_MPSWIDE:
1244             val = cps->mps_wide; break;
1245          case LPX_K_MPSFREE:
1246             val = cps->mps_free; break;
1247          case LPX_K_MPSSKIP:
1248             val = cps->mps_skip; break;
1249          case LPX_K_LPTORIG:
1250             val = cps->lpt_orig; break;
1251          case LPX_K_PRESOL:
1252             val = cps->presol; break;
1253          case LPX_K_BINARIZE:
1254             val = cps->binarize; break;
1255          case LPX_K_USECUTS:
1256             val = cps->use_cuts; break;
1257          case LPX_K_BFTYPE:
1258             {  glp_bfcp parm;
1259                glp_get_bfcp(lp, &parm);
1260                switch (parm.type)
1261                {  case GLP_BF_FT:
1262                      val = 1; break;
1263                   case GLP_BF_BG:
1264                      val = 2; break;
1265                   case GLP_BF_GR:
1266                      val = 3; break;
1267                   default:
1268                      xassert(lp != lp);
1269                }
1270             }
1271             break;
1272          default:
1273             xerror("lpx_get_int_parm: parm = %d; invalid parameter\n",
1274                parm);
1275       }
1276       return val;
1277 }
1278 
lpx_set_real_parm(LPX * lp,int parm,double val)1279 void lpx_set_real_parm(LPX *lp, int parm, double val)
1280 {     /* set (change) real control parameter */
1281       struct CPS *cps = find_cps(lp);
1282       switch (parm)
1283       {  case LPX_K_RELAX:
1284             if (!(0.0 <= val && val <= 1.0))
1285                xerror("lpx_set_real_parm: RELAX = %g; invalid value\n",
1286                   val);
1287             cps->relax = val;
1288             break;
1289          case LPX_K_TOLBND:
1290             if (!(DBL_EPSILON <= val && val <= 0.001))
1291                xerror("lpx_set_real_parm: TOLBND = %g; invalid value\n",
1292                   val);
1293             cps->tol_bnd = val;
1294             break;
1295          case LPX_K_TOLDJ:
1296             if (!(DBL_EPSILON <= val && val <= 0.001))
1297                xerror("lpx_set_real_parm: TOLDJ = %g; invalid value\n",
1298                   val);
1299             cps->tol_dj = val;
1300             break;
1301          case LPX_K_TOLPIV:
1302             if (!(DBL_EPSILON <= val && val <= 0.001))
1303                xerror("lpx_set_real_parm: TOLPIV = %g; invalid value\n",
1304                   val);
1305             cps->tol_piv = val;
1306             break;
1307          case LPX_K_OBJLL:
1308             cps->obj_ll = val;
1309             break;
1310          case LPX_K_OBJUL:
1311             cps->obj_ul = val;
1312             break;
1313          case LPX_K_TMLIM:
1314             cps->tm_lim = val;
1315             break;
1316          case LPX_K_OUTDLY:
1317             cps->out_dly = val;
1318             break;
1319          case LPX_K_TOLINT:
1320             if (!(DBL_EPSILON <= val && val <= 0.001))
1321                xerror("lpx_set_real_parm: TOLINT = %g; invalid value\n",
1322                   val);
1323             cps->tol_int = val;
1324             break;
1325          case LPX_K_TOLOBJ:
1326             if (!(DBL_EPSILON <= val && val <= 0.001))
1327                xerror("lpx_set_real_parm: TOLOBJ = %g; invalid value\n",
1328                   val);
1329             cps->tol_obj = val;
1330             break;
1331          case LPX_K_MIPGAP:
1332             if (val < 0.0)
1333                xerror("lpx_set_real_parm: MIPGAP = %g; invalid value\n",
1334                   val);
1335             cps->mip_gap = val;
1336             break;
1337          default:
1338             xerror("lpx_set_real_parm: parm = %d; invalid parameter\n",
1339                parm);
1340       }
1341       return;
1342 }
1343 
lpx_get_real_parm(LPX * lp,int parm)1344 double lpx_get_real_parm(LPX *lp, int parm)
1345 {     /* query real control parameter */
1346       struct CPS *cps = find_cps(lp);
1347       double val = 0.0;
1348       switch (parm)
1349       {  case LPX_K_RELAX:
1350             val = cps->relax;
1351             break;
1352          case LPX_K_TOLBND:
1353             val = cps->tol_bnd;
1354             break;
1355          case LPX_K_TOLDJ:
1356             val = cps->tol_dj;
1357             break;
1358          case LPX_K_TOLPIV:
1359             val = cps->tol_piv;
1360             break;
1361          case LPX_K_OBJLL:
1362             val = cps->obj_ll;
1363             break;
1364          case LPX_K_OBJUL:
1365             val = cps->obj_ul;
1366             break;
1367          case LPX_K_TMLIM:
1368             val = cps->tm_lim;
1369             break;
1370          case LPX_K_OUTDLY:
1371             val = cps->out_dly;
1372             break;
1373          case LPX_K_TOLINT:
1374             val = cps->tol_int;
1375             break;
1376          case LPX_K_TOLOBJ:
1377             val = cps->tol_obj;
1378             break;
1379          case LPX_K_MIPGAP:
1380             val = cps->mip_gap;
1381             break;
1382          default:
1383             xerror("lpx_get_real_parm: parm = %d; invalid parameter\n",
1384                parm);
1385       }
1386       return val;
1387 }
1388 
lpx_read_mps(const char * fname)1389 LPX *lpx_read_mps(const char *fname)
1390 {     /* read problem data in fixed MPS format */
1391       LPX *lp = lpx_create_prob();
1392       if (glp_read_mps(lp, GLP_MPS_DECK, NULL, fname))
1393          lpx_delete_prob(lp), lp = NULL;
1394       return lp;
1395 }
1396 
lpx_write_mps(LPX * lp,const char * fname)1397 int lpx_write_mps(LPX *lp, const char *fname)
1398 {     /* write problem data in fixed MPS format */
1399       return glp_write_mps(lp, GLP_MPS_DECK, NULL, fname);
1400 }
1401 
lpx_read_bas(LPX * lp,const char * fname)1402 int lpx_read_bas(LPX *lp, const char *fname)
1403 {     /* read LP basis in fixed MPS format */
1404       xassert(lp == lp);
1405       xassert(fname == fname);
1406       xerror("lpx_read_bas: operation not supported\n");
1407       return 0;
1408 }
1409 
lpx_write_bas(LPX * lp,const char * fname)1410 int lpx_write_bas(LPX *lp, const char *fname)
1411 {     /* write LP basis in fixed MPS format */
1412       xassert(lp == lp);
1413       xassert(fname == fname);
1414       xerror("lpx_write_bas: operation not supported\n");
1415       return 0;
1416 }
1417 
lpx_read_freemps(const char * fname)1418 LPX *lpx_read_freemps(const char *fname)
1419 {     /* read problem data in free MPS format */
1420       LPX *lp = lpx_create_prob();
1421       if (glp_read_mps(lp, GLP_MPS_FILE, NULL, fname))
1422          lpx_delete_prob(lp), lp = NULL;
1423       return lp;
1424 }
1425 
lpx_write_freemps(LPX * lp,const char * fname)1426 int lpx_write_freemps(LPX *lp, const char *fname)
1427 {     /* write problem data in free MPS format */
1428       return glp_write_mps(lp, GLP_MPS_FILE, NULL, fname);
1429 }
1430 
lpx_read_cpxlp(const char * fname)1431 LPX *lpx_read_cpxlp(const char *fname)
1432 {     /* read problem data in CPLEX LP format */
1433       LPX *lp;
1434       lp = lpx_create_prob();
1435       if (glp_read_lp(lp, NULL, fname))
1436          lpx_delete_prob(lp), lp = NULL;
1437       return lp;
1438 }
1439 
lpx_write_cpxlp(LPX * lp,const char * fname)1440 int lpx_write_cpxlp(LPX *lp, const char *fname)
1441 {     /* write problem data in CPLEX LP format */
1442       return glp_write_lp(lp, NULL, fname);
1443 }
1444 
lpx_read_model(const char * model,const char * data,const char * output)1445 LPX *lpx_read_model(const char *model, const char *data, const char
1446       *output)
1447 {     /* read LP/MIP model written in GNU MathProg language */
1448       LPX *lp = NULL;
1449       glp_tran *tran;
1450       /* allocate the translator workspace */
1451       tran = glp_mpl_alloc_wksp();
1452       /* read model section and optional data section */
1453       if (glp_mpl_read_model(tran, model, data != NULL)) goto done;
1454       /* read separate data section, if required */
1455       if (data != NULL)
1456          if (glp_mpl_read_data(tran, data)) goto done;
1457       /* generate the model */
1458       if (glp_mpl_generate(tran, output)) goto done;
1459       /* build the problem instance from the model */
1460       lp = lpx_create_prob();
1461       glp_mpl_build_prob(tran, lp);
1462 done: /* free the translator workspace */
1463       glp_mpl_free_wksp(tran);
1464       /* bring the problem object to the calling program */
1465       return lp;
1466 }
1467 
lpx_print_prob(LPX * lp,const char * fname)1468 int lpx_print_prob(LPX *lp, const char *fname)
1469 {     /* write problem data in plain text format */
1470       return glp_write_lp(lp, NULL, fname);
1471 }
1472 
lpx_print_sol(LPX * lp,const char * fname)1473 int lpx_print_sol(LPX *lp, const char *fname)
1474 {     /* write LP problem solution in printable format */
1475       return glp_print_sol(lp, fname);
1476 }
1477 
lpx_print_sens_bnds(LPX * lp,const char * fname)1478 int lpx_print_sens_bnds(LPX *lp, const char *fname)
1479 {     /* write bounds sensitivity information */
1480       if (glp_get_status(lp) == GLP_OPT && !glp_bf_exists(lp))
1481          glp_factorize(lp);
1482       return glp_print_ranges(lp, 0, NULL, 0, fname);
1483 }
1484 
lpx_print_ips(LPX * lp,const char * fname)1485 int lpx_print_ips(LPX *lp, const char *fname)
1486 {     /* write interior point solution in printable format */
1487       return glp_print_ipt(lp, fname);
1488 }
1489 
lpx_print_mip(LPX * lp,const char * fname)1490 int lpx_print_mip(LPX *lp, const char *fname)
1491 {     /* write MIP problem solution in printable format */
1492       return glp_print_mip(lp, fname);
1493 }
1494 
lpx_is_b_avail(glp_prob * lp)1495 int lpx_is_b_avail(glp_prob *lp)
1496 {     /* check if LP basis is available */
1497       return glp_bf_exists(lp);
1498 }
1499 
lpx_main(int argc,const char * argv[])1500 int lpx_main(int argc, const char *argv[])
1501 {     /* stand-alone LP/MIP solver */
1502       return glp_main(argc, argv);
1503 }
1504 
1505 /* eof */
1506