lemon-project-template-glpk

comparison deps/glpk/src/glplpx01.c @ 9:33de93886c88

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