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