1 /* glplpx01.c (obsolete API routines) */
3 /***********************************************************************
4 * This code is part of GLPK (GNU Linear Programming Kit).
6 * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
7 * 2009, 2010 Andrew Makhorin, Department for Applied Informatics,
8 * Moscow Aviation Institute, Moscow, Russia. All rights reserved.
9 * E-mail: <mao@gnu.org>.
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.
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.
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 ***********************************************************************/
28 { /* control parameters and statistics */
30 /* level of messages output by the solver:
32 1 - error messages only
34 3 - full output (includes informational messages) */
38 1 - equilibration scaling
39 2 - geometric mean scaling
40 3 - geometric mean scaling, then equilibration scaling */
42 /* dual simplex option:
43 0 - use primal simplex
44 1 - use dual simplex */
46 /* pricing option (for both primal and dual simplex):
48 1 - steepest edge pricing */
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) */
59 /* relative tolerance used to check if the current basic solution
62 /* absolute tolerance used to check if the current basic solution
65 /* relative tolerance used to choose eligible pivotal elements of
66 the simplex table in the ratio test */
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
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 */
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 */
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 */
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 */
93 /* output frequency, in iterations; this parameter specifies how
94 frequently the solver sends information about the solution to
95 the standard output */
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
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
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
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 */
167 LPX *lpx_create_prob(void)
168 { /* create problem object */
169 return glp_create_prob();
172 void lpx_set_prob_name(LPX *lp, const char *name)
173 { /* assign (change) problem name */
174 glp_set_prob_name(lp, name);
178 void lpx_set_obj_name(LPX *lp, const char *name)
179 { /* assign (change) objective function name */
180 glp_set_obj_name(lp, name);
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);
190 int lpx_add_rows(LPX *lp, int nrs)
191 { /* add new rows to problem object */
192 return glp_add_rows(lp, nrs);
195 int lpx_add_cols(LPX *lp, int ncs)
196 { /* add new columns to problem object */
197 return glp_add_cols(lp, ncs);
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);
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);
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);
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);
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);
230 void lpx_set_mat_row(LPX *lp, int i, int len, const int ind[],
232 { /* set (replace) row of the constraint matrix */
233 glp_set_mat_row(lp, i, len, ind, val);
237 void lpx_set_mat_col(LPX *lp, int j, int len, const int ind[],
239 { /* set (replace) column of the constraint matrix */
240 glp_set_mat_col(lp, j, len, ind, val);
244 void lpx_load_matrix(LPX *lp, int ne, const int ia[], const int ja[],
246 { /* load (replace) the whole constraint matrix */
247 glp_load_matrix(lp, ne, ia, ja, ar);
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);
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);
263 void lpx_delete_prob(LPX *lp)
264 { /* delete problem object */
269 const char *lpx_get_prob_name(LPX *lp)
270 { /* retrieve problem name */
271 return glp_get_prob_name(lp);
274 const char *lpx_get_obj_name(LPX *lp)
275 { /* retrieve objective function name */
276 return glp_get_obj_name(lp);
279 int lpx_get_obj_dir(LPX *lp)
280 { /* retrieve optimization direction flag */
281 return glp_get_obj_dir(lp) - GLP_MIN + LPX_MIN;
284 int lpx_get_num_rows(LPX *lp)
285 { /* retrieve number of rows */
286 return glp_get_num_rows(lp);
289 int lpx_get_num_cols(LPX *lp)
290 { /* retrieve number of columns */
291 return glp_get_num_cols(lp);
294 const char *lpx_get_row_name(LPX *lp, int i)
295 { /* retrieve row name */
296 return glp_get_row_name(lp, i);
299 const char *lpx_get_col_name(LPX *lp, int j)
300 { /* retrieve column name */
301 return glp_get_col_name(lp, j);
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;
309 double lpx_get_row_lb(glp_prob *lp, int i)
310 { /* retrieve row lower bound */
312 lb = glp_get_row_lb(lp, i);
313 if (lb == -DBL_MAX) lb = 0.0;
317 double lpx_get_row_ub(glp_prob *lp, int i)
318 { /* retrieve row upper bound */
320 ub = glp_get_row_ub(lp, i);
321 if (ub == +DBL_MAX) ub = 0.0;
325 void lpx_get_row_bnds(glp_prob *lp, int i, int *typx, double *lb,
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);
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;
339 double lpx_get_col_lb(glp_prob *lp, int j)
340 { /* retrieve column lower bound */
342 lb = glp_get_col_lb(lp, j);
343 if (lb == -DBL_MAX) lb = 0.0;
347 double lpx_get_col_ub(glp_prob *lp, int j)
348 { /* retrieve column upper bound */
350 ub = glp_get_col_ub(lp, j);
351 if (ub == +DBL_MAX) ub = 0.0;
355 void lpx_get_col_bnds(glp_prob *lp, int j, int *typx, double *lb,
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);
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);
369 int lpx_get_num_nz(LPX *lp)
370 { /* retrieve number of constraint coefficients */
371 return glp_get_num_nz(lp);
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);
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);
384 void lpx_create_index(LPX *lp)
385 { /* create the name index */
386 glp_create_index(lp);
390 int lpx_find_row(LPX *lp, const char *name)
391 { /* find row by its name */
392 return glp_find_row(lp, name);
395 int lpx_find_col(LPX *lp, const char *name)
396 { /* find column by its name */
397 return glp_find_col(lp, name);
400 void lpx_delete_index(LPX *lp)
401 { /* delete the name index */
402 glp_delete_index(lp);
406 void lpx_scale_prob(LPX *lp)
407 { /* scale problem data */
408 switch (lpx_get_int_parm(lp, LPX_K_SCALE))
411 glp_unscale_prob(lp);
414 /* equilibration scaling */
415 glp_scale_prob(lp, GLP_SF_EQ);
418 /* geometric mean scaling */
419 glp_scale_prob(lp, GLP_SF_GM);
422 /* geometric mean scaling, then equilibration scaling */
423 glp_scale_prob(lp, GLP_SF_GM | GLP_SF_EQ);
431 void lpx_unscale_prob(LPX *lp)
432 { /* unscale problem data */
433 glp_unscale_prob(lp);
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);
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);
449 void lpx_std_basis(LPX *lp)
450 { /* construct standard initial LP basis */
455 void lpx_adv_basis(LPX *lp)
456 { /* construct advanced initial LP basis */
457 glp_adv_basis(lp, 0);
461 void lpx_cpx_basis(LPX *lp)
462 { /* construct Bixby's initial LP basis */
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);
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);
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);
486 if (lpx_get_real_parm(lp, LPX_K_RELAX) == 0.0)
487 parm->r_test = GLP_RT_STD;
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;
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;
503 (int)(1000.0 * lpx_get_real_parm(lp, LPX_K_TMLIM));
504 parm->out_frq = lpx_get_int_parm(lp, LPX_K_OUTFRQ);
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);
515 int lpx_simplex(LPX *lp)
516 { /* easy-to-use driver to the simplex method */
519 fill_smcp(lp, &parm);
520 ret = glp_simplex(lp, &parm);
522 { case 0: ret = LPX_E_OK; break;
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);
539 int lpx_exact(LPX *lp)
540 { /* easy-to-use driver to the exact simplex method */
543 fill_smcp(lp, &parm);
544 ret = glp_exact(lp, &parm);
546 { case 0: ret = LPX_E_OK; break;
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);
558 int lpx_get_status(glp_prob *lp)
559 { /* retrieve generic status of basic solution */
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);
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;
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;
583 double lpx_get_obj_val(LPX *lp)
584 { /* retrieve objective value (basic solution) */
585 return glp_get_obj_val(lp);
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;
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);
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);
603 void lpx_get_row_info(glp_prob *lp, int i, int *tagx, double *vx,
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);
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;
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);
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);
627 void lpx_get_col_info(glp_prob *lp, int j, int *tagx, double *vx,
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);
636 int lpx_get_ray_info(LPX *lp)
637 { /* determine what causes primal unboundness */
638 return glp_get_unbnd_ray(lp);
641 void lpx_check_kkt(LPX *lp, int scaled, LPXKKT *kkt)
642 { /* check Karush-Kuhn-Tucker conditions */
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,
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;
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';
659 kkt->pe_quality = '?';
660 _glp_check_kkt(lp, GLP_SOL, GLP_KKT_PB, &ae_max, &ae_ind, &re_max,
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;
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';
673 kkt->pb_quality = '?';
674 _glp_check_kkt(lp, GLP_SOL, GLP_KKT_DE, &ae_max, &ae_ind, &re_max,
676 kkt->de_ae_max = ae_max;
680 kkt->de_ae_col = ae_ind - lp->m;
681 kkt->de_re_max = re_max;
685 kkt->de_re_col = ae_ind - lp->m;
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';
693 kkt->de_quality = '?';
694 _glp_check_kkt(lp, GLP_SOL, GLP_KKT_DB, &ae_max, &ae_ind, &re_max,
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;
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';
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';
714 int lpx_warm_up(LPX *lp)
715 { /* "warm up" LP basis */
717 ret = glp_warm_up(lp);
720 else if (ret == GLP_EBADB)
722 else if (ret == GLP_ESING)
724 else if (ret == GLP_ECOND)
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);
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);
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);
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);
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 */
755 piv = glp_prim_rtest(lp, len, ind, val, how, tol);
756 xassert(0 <= piv && piv <= len);
757 return piv == 0 ? 0 : ind[piv];
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 */
764 piv = glp_dual_rtest(lp, len, ind, val, how, tol);
765 xassert(0 <= piv && piv <= len);
766 return piv == 0 ? 0 : ind[piv];
769 int lpx_interior(LPX *lp)
770 { /* easy-to-use driver to the interior-point method */
772 ret = glp_interior(lp, NULL);
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);
785 int lpx_ipt_status(glp_prob *lp)
786 { /* retrieve status of interior-point solution */
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);
796 double lpx_ipt_obj_val(LPX *lp)
797 { /* retrieve objective value (interior point) */
798 return glp_ipt_obj_val(lp);
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);
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);
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);
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);
821 void lpx_set_class(LPX *lp, int klass)
822 { /* set problem class */
824 if (!(klass == LPX_LP || klass == LPX_MIP))
825 xerror("lpx_set_class: invalid problem class\n");
829 int lpx_get_class(LPX *lp)
830 { /* determine problem klass */
831 return glp_get_num_int(lp) == 0 ? LPX_LP : LPX_MIP;
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);
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;
845 int lpx_get_num_int(LPX *lp)
846 { /* retrieve number of integer columns */
847 return glp_get_num_int(lp);
850 int lpx_get_num_bin(LPX *lp)
851 { /* retrieve number of binary columns */
852 return glp_get_num_bin(lp);
855 static int solve_mip(LPX *lp, int presolve)
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);
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);
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);
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;
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;
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;
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;
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;
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);
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;
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);
923 int lpx_integer(LPX *lp)
924 { /* easy-to-use driver to the branch-and-bound method */
925 return solve_mip(lp, GLP_OFF);
928 int lpx_intopt(LPX *lp)
929 { /* easy-to-use driver to the branch-and-bound method */
930 return solve_mip(lp, GLP_ON);
933 int lpx_mip_status(glp_prob *lp)
934 { /* retrieve status of MIP solution */
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);
946 double lpx_mip_obj_val(LPX *lp)
947 { /* retrieve objective value (MIP solution) */
948 return glp_mip_obj_val(lp);
951 double lpx_mip_row_val(LPX *lp, int i)
952 { /* retrieve row value (MIP solution) */
953 return glp_mip_row_val(lp, i);
956 double lpx_mip_col_val(LPX *lp, int j)
957 { /* retrieve column value (MIP solution) */
958 return glp_mip_col_val(lp, j);
961 void lpx_check_int(LPX *lp, LPXKKT *kkt)
962 { /* check integer feasibility conditions */
964 double ae_max, re_max;
965 _glp_check_kkt(lp, GLP_MIP, GLP_KKT_PE, &ae_max, &ae_ind, &re_max,
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;
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';
978 kkt->pe_quality = '?';
979 _glp_check_kkt(lp, GLP_MIP, GLP_KKT_PB, &ae_max, &ae_ind, &re_max,
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;
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';
992 kkt->pb_quality = '?';
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);
1006 cps->tol_bnd = 1e-7;
1008 cps->tol_piv = 1e-9;
1010 cps->obj_ll = -DBL_MAX;
1011 cps->obj_ul = +DBL_MAX;
1013 #if 0 /* 02/XII-2010 */
1021 cps->tol_int = 1e-5;
1022 cps->tol_obj = 1e-7;
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));
1049 #if 1 /* 17/XI-2009 */
1050 void lpx_reset_parms(LPX *lp)
1051 { /* reset control parameters to default values */
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;
1063 struct LPXCPS *cps = access_parms(lp);
1066 { case LPX_K_MSGLEV:
1067 if (!(0 <= val && val <= 3))
1068 xerror("lpx_set_int_parm: MSGLEV = %d; invalid value\n",
1073 if (!(0 <= val && val <= 3))
1074 xerror("lpx_set_int_parm: SCALE = %d; invalid value\n",
1079 if (!(val == 0 || val == 1))
1080 xerror("lpx_set_int_parm: DUAL = %d; invalid value\n",
1085 if (!(val == 0 || val == 1))
1086 xerror("lpx_set_int_parm: PRICE = %d; invalid value\n",
1091 if (!(val == 0 || val == 1))
1092 xerror("lpx_set_int_parm: ROUND = %d; invalid value\n",
1104 xerror("lpx_set_int_parm: OUTFRQ = %d; invalid value\n",
1109 if (!(val == 0 || val == 1 || val == 2 || val == 3))
1110 xerror("lpx_set_int_parm: BRANCH = %d; invalid value\n",
1115 if (!(val == 0 || val == 1 || val == 2 || val == 3))
1116 xerror("lpx_set_int_parm: BTRACK = %d; invalid value\n",
1121 if (!(val == 0 || val == 1))
1122 xerror("lpx_set_int_parm: MPSINFO = %d; invalid value\n",
1124 cps->mps_info = val;
1127 if (!(val == 0 || val == 1 || val == 2))
1128 xerror("lpx_set_int_parm: MPSOBJ = %d; invalid value\n",
1133 if (!(val == 0 || val == 1))
1134 xerror("lpx_set_int_parm: MPSORIG = %d; invalid value\n",
1136 cps->mps_orig = val;
1139 if (!(val == 0 || val == 1))
1140 xerror("lpx_set_int_parm: MPSWIDE = %d; invalid value\n",
1142 cps->mps_wide = val;
1145 if (!(val == 0 || val == 1))
1146 xerror("lpx_set_int_parm: MPSFREE = %d; invalid value\n",
1148 cps->mps_free = val;
1151 if (!(val == 0 || val == 1))
1152 xerror("lpx_set_int_parm: MPSSKIP = %d; invalid value\n",
1154 cps->mps_skip = val;
1157 if (!(val == 0 || val == 1))
1158 xerror("lpx_set_int_parm: LPTORIG = %d; invalid value\n",
1160 cps->lpt_orig = val;
1163 if (!(val == 0 || val == 1))
1164 xerror("lpx_set_int_parm: PRESOL = %d; invalid value\n",
1168 case LPX_K_BINARIZE:
1169 if (!(val == 0 || val == 1))
1170 xerror("lpx_set_int_parm: BINARIZE = %d; invalid value\n"
1172 cps->binarize = val;
1175 if (val & ~LPX_C_ALL)
1176 xerror("lpx_set_int_parm: USECUTS = 0x%X; invalid value\n",
1178 cps->use_cuts = val;
1182 if (!(1 <= val && val <= 3))
1183 xerror("lpx_set_int_parm: BFTYPE = %d; invalid value\n",
1188 glp_get_bfcp(lp, &parm);
1191 parm.type = GLP_BF_FT; break;
1193 parm.type = GLP_BF_BG; break;
1195 parm.type = GLP_BF_GR; break;
1197 xerror("lpx_set_int_parm: BFTYPE = %d; invalid val"
1200 glp_set_bfcp(lp, &parm);
1205 xerror("lpx_set_int_parm: parm = %d; invalid parameter\n",
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;
1216 struct LPXCPS *cps = access_parms(lp);
1220 { case LPX_K_MSGLEV:
1221 val = cps->msg_lev; break;
1223 val = cps->scale; break;
1225 val = cps->dual; break;
1227 val = cps->price; break;
1229 val = cps->round; break;
1231 val = cps->it_lim; break;
1233 val = lp->it_cnt; break;
1235 val = cps->out_frq; break;
1237 val = cps->branch; break;
1239 val = cps->btrack; break;
1241 val = cps->mps_info; break;
1243 val = cps->mps_obj; break;
1245 val = cps->mps_orig; break;
1247 val = cps->mps_wide; break;
1249 val = cps->mps_free; break;
1251 val = cps->mps_skip; break;
1253 val = cps->lpt_orig; break;
1255 val = cps->presol; break;
1256 case LPX_K_BINARIZE:
1257 val = cps->binarize; break;
1259 val = cps->use_cuts; break;
1262 val = cps->bf_type; break;
1265 glp_get_bfcp(lp, &parm);
1280 xerror("lpx_get_int_parm: parm = %d; invalid parameter\n",
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;
1291 struct LPXCPS *cps = access_parms(lp);
1295 if (!(0.0 <= val && val <= 1.0))
1296 xerror("lpx_set_real_parm: RELAX = %g; invalid value\n",
1301 if (!(DBL_EPSILON <= val && val <= 0.001))
1302 xerror("lpx_set_real_parm: TOLBND = %g; invalid value\n",
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;
1314 if (!(DBL_EPSILON <= val && val <= 0.001))
1315 xerror("lpx_set_real_parm: TOLDJ = %g; invalid value\n",
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;
1327 if (!(DBL_EPSILON <= val && val <= 0.001))
1328 xerror("lpx_set_real_parm: TOLPIV = %g; invalid value\n",
1345 if (!(DBL_EPSILON <= val && val <= 0.001))
1346 xerror("lpx_set_real_parm: TOLINT = %g; invalid value\n",
1351 if (!(DBL_EPSILON <= val && val <= 0.001))
1352 xerror("lpx_set_real_parm: TOLOBJ = %g; invalid value\n",
1358 xerror("lpx_set_real_parm: MIPGAP = %g; invalid value\n",
1363 xerror("lpx_set_real_parm: parm = %d; invalid parameter\n",
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;
1374 struct LPXCPS *cps = access_parms(lp);
1412 xerror("lpx_get_real_parm: parm = %d; invalid parameter\n",
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;
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);
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);
1437 xassert(fname == fname);
1438 xerror("lpx_read_bas: operation not supported\n");
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);
1449 xassert(fname == fname);
1450 xerror("lpx_write_bas: operation not supported\n");
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;
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);
1468 LPX *lpx_read_cpxlp(const char *fname)
1469 { /* read problem data in CPLEX LP format */
1471 lp = lpx_create_prob();
1472 if (glp_read_lp(lp, NULL, fname))
1473 lpx_delete_prob(lp), lp = NULL;
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);
1482 LPX *lpx_read_model(const char *model, const char *data, const char
1484 { /* read LP/MIP model written in GNU MathProg language */
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 */
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 */
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);
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);
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))
1519 return glp_print_ranges(lp, 0, NULL, 0, fname);
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);
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);
1532 int lpx_is_b_avail(glp_prob *lp)
1533 { /* check if LP basis is available */
1534 return glp_bf_exists(lp);
1537 int lpx_main(int argc, const char *argv[])
1538 { /* stand-alone LP/MIP solver */
1539 return glp_main(argc, argv);