src/glplpx01.c
author Alpar Juttner <alpar@cs.elte.hu>
Mon, 06 Dec 2010 13:09:21 +0100
changeset 1 c445c931472f
permissions -rw-r--r--
Import glpk-4.45

- Generated files and doc/notes are removed
     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 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 */