src/glpapi09.c
changeset 2 4c8956a7bdf4
equal deleted inserted replaced
-1:000000000000 0:a10dbb9f7a55
       
     1 /* glpapi09.c (mixed integer programming 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 "glpios.h"
       
    26 #include "glpnpp.h"
       
    27 
       
    28 /***********************************************************************
       
    29 *  NAME
       
    30 *
       
    31 *  glp_set_col_kind - set (change) column kind
       
    32 *
       
    33 *  SYNOPSIS
       
    34 *
       
    35 *  void glp_set_col_kind(glp_prob *mip, int j, int kind);
       
    36 *
       
    37 *  DESCRIPTION
       
    38 *
       
    39 *  The routine glp_set_col_kind sets (changes) the kind of j-th column
       
    40 *  (structural variable) as specified by the parameter kind:
       
    41 *
       
    42 *  GLP_CV - continuous variable;
       
    43 *  GLP_IV - integer variable;
       
    44 *  GLP_BV - binary variable. */
       
    45 
       
    46 void glp_set_col_kind(glp_prob *mip, int j, int kind)
       
    47 {     GLPCOL *col;
       
    48       if (!(1 <= j && j <= mip->n))
       
    49          xerror("glp_set_col_kind: j = %d; column number out of range\n"
       
    50             , j);
       
    51       col = mip->col[j];
       
    52       switch (kind)
       
    53       {  case GLP_CV:
       
    54             col->kind = GLP_CV;
       
    55             break;
       
    56          case GLP_IV:
       
    57             col->kind = GLP_IV;
       
    58             break;
       
    59          case GLP_BV:
       
    60             col->kind = GLP_IV;
       
    61             if (!(col->type == GLP_DB && col->lb == 0.0 && col->ub ==
       
    62                1.0)) glp_set_col_bnds(mip, j, GLP_DB, 0.0, 1.0);
       
    63             break;
       
    64          default:
       
    65             xerror("glp_set_col_kind: j = %d; kind = %d; invalid column"
       
    66                " kind\n", j, kind);
       
    67       }
       
    68       return;
       
    69 }
       
    70 
       
    71 /***********************************************************************
       
    72 *  NAME
       
    73 *
       
    74 *  glp_get_col_kind - retrieve column kind
       
    75 *
       
    76 *  SYNOPSIS
       
    77 *
       
    78 *  int glp_get_col_kind(glp_prob *mip, int j);
       
    79 *
       
    80 *  RETURNS
       
    81 *
       
    82 *  The routine glp_get_col_kind returns the kind of j-th column, i.e.
       
    83 *  the kind of corresponding structural variable, as follows:
       
    84 *
       
    85 *  GLP_CV - continuous variable;
       
    86 *  GLP_IV - integer variable;
       
    87 *  GLP_BV - binary variable */
       
    88 
       
    89 int glp_get_col_kind(glp_prob *mip, int j)
       
    90 {     GLPCOL *col;
       
    91       int kind;
       
    92       if (!(1 <= j && j <= mip->n))
       
    93          xerror("glp_get_col_kind: j = %d; column number out of range\n"
       
    94             , j);
       
    95       col = mip->col[j];
       
    96       kind = col->kind;
       
    97       switch (kind)
       
    98       {  case GLP_CV:
       
    99             break;
       
   100          case GLP_IV:
       
   101             if (col->type == GLP_DB && col->lb == 0.0 && col->ub == 1.0)
       
   102                kind = GLP_BV;
       
   103             break;
       
   104          default:
       
   105             xassert(kind != kind);
       
   106       }
       
   107       return kind;
       
   108 }
       
   109 
       
   110 /***********************************************************************
       
   111 *  NAME
       
   112 *
       
   113 *  glp_get_num_int - retrieve number of integer columns
       
   114 *
       
   115 *  SYNOPSIS
       
   116 *
       
   117 *  int glp_get_num_int(glp_prob *mip);
       
   118 *
       
   119 *  RETURNS
       
   120 *
       
   121 *  The routine glp_get_num_int returns the current number of columns,
       
   122 *  which are marked as integer. */
       
   123 
       
   124 int glp_get_num_int(glp_prob *mip)
       
   125 {     GLPCOL *col;
       
   126       int j, count = 0;
       
   127       for (j = 1; j <= mip->n; j++)
       
   128       {  col = mip->col[j];
       
   129          if (col->kind == GLP_IV) count++;
       
   130       }
       
   131       return count;
       
   132 }
       
   133 
       
   134 /***********************************************************************
       
   135 *  NAME
       
   136 *
       
   137 *  glp_get_num_bin - retrieve number of binary columns
       
   138 *
       
   139 *  SYNOPSIS
       
   140 *
       
   141 *  int glp_get_num_bin(glp_prob *mip);
       
   142 *
       
   143 *  RETURNS
       
   144 *
       
   145 *  The routine glp_get_num_bin returns the current number of columns,
       
   146 *  which are marked as binary. */
       
   147 
       
   148 int glp_get_num_bin(glp_prob *mip)
       
   149 {     GLPCOL *col;
       
   150       int j, count = 0;
       
   151       for (j = 1; j <= mip->n; j++)
       
   152       {  col = mip->col[j];
       
   153          if (col->kind == GLP_IV && col->type == GLP_DB && col->lb ==
       
   154             0.0 && col->ub == 1.0) count++;
       
   155       }
       
   156       return count;
       
   157 }
       
   158 
       
   159 /***********************************************************************
       
   160 *  NAME
       
   161 *
       
   162 *  glp_intopt - solve MIP problem with the branch-and-bound method
       
   163 *
       
   164 *  SYNOPSIS
       
   165 *
       
   166 *  int glp_intopt(glp_prob *P, const glp_iocp *parm);
       
   167 *
       
   168 *  DESCRIPTION
       
   169 *
       
   170 *  The routine glp_intopt is a driver to the MIP solver based on the
       
   171 *  branch-and-bound method.
       
   172 *
       
   173 *  On entry the problem object should contain optimal solution to LP
       
   174 *  relaxation (which can be obtained with the routine glp_simplex).
       
   175 *
       
   176 *  The MIP solver has a set of control parameters. Values of the control
       
   177 *  parameters can be passed in a structure glp_iocp, which the parameter
       
   178 *  parm points to.
       
   179 *
       
   180 *  The parameter parm can be specified as NULL, in which case the MIP
       
   181 *  solver uses default settings.
       
   182 *
       
   183 *  RETURNS
       
   184 *
       
   185 *  0  The MIP problem instance has been successfully solved. This code
       
   186 *     does not necessarily mean that the solver has found optimal
       
   187 *     solution. It only means that the solution process was successful.
       
   188 *
       
   189 *  GLP_EBOUND
       
   190 *     Unable to start the search, because some double-bounded variables
       
   191 *     have incorrect bounds or some integer variables have non-integer
       
   192 *     (fractional) bounds.
       
   193 *
       
   194 *  GLP_EROOT
       
   195 *     Unable to start the search, because optimal basis for initial LP
       
   196 *     relaxation is not provided.
       
   197 *
       
   198 *  GLP_EFAIL
       
   199 *     The search was prematurely terminated due to the solver failure.
       
   200 *
       
   201 *  GLP_EMIPGAP
       
   202 *     The search was prematurely terminated, because the relative mip
       
   203 *     gap tolerance has been reached.
       
   204 *
       
   205 *  GLP_ETMLIM
       
   206 *     The search was prematurely terminated, because the time limit has
       
   207 *     been exceeded.
       
   208 *
       
   209 *  GLP_ENOPFS
       
   210 *     The MIP problem instance has no primal feasible solution (only if
       
   211 *     the MIP presolver is used).
       
   212 *
       
   213 *  GLP_ENODFS
       
   214 *     LP relaxation of the MIP problem instance has no dual feasible
       
   215 *     solution (only if the MIP presolver is used).
       
   216 *
       
   217 *  GLP_ESTOP
       
   218 *     The search was prematurely terminated by application. */
       
   219 
       
   220 static int solve_mip(glp_prob *P, const glp_iocp *parm)
       
   221 {     /* solve MIP directly without using the preprocessor */
       
   222       glp_tree *T;
       
   223       int ret;
       
   224       /* optimal basis to LP relaxation must be provided */
       
   225       if (glp_get_status(P) != GLP_OPT)
       
   226       {  if (parm->msg_lev >= GLP_MSG_ERR)
       
   227             xprintf("glp_intopt: optimal basis to initial LP relaxation"
       
   228                " not provided\n");
       
   229          ret = GLP_EROOT;
       
   230          goto done;
       
   231       }
       
   232       /* it seems all is ok */
       
   233       if (parm->msg_lev >= GLP_MSG_ALL)
       
   234          xprintf("Integer optimization begins...\n");
       
   235       /* create the branch-and-bound tree */
       
   236       T = ios_create_tree(P, parm);
       
   237       /* solve the problem instance */
       
   238       ret = ios_driver(T);
       
   239       /* delete the branch-and-bound tree */
       
   240       ios_delete_tree(T);
       
   241       /* analyze exit code reported by the mip driver */
       
   242       if (ret == 0)
       
   243       {  if (P->mip_stat == GLP_FEAS)
       
   244          {  if (parm->msg_lev >= GLP_MSG_ALL)
       
   245                xprintf("INTEGER OPTIMAL SOLUTION FOUND\n");
       
   246             P->mip_stat = GLP_OPT;
       
   247          }
       
   248          else
       
   249          {  if (parm->msg_lev >= GLP_MSG_ALL)
       
   250                xprintf("PROBLEM HAS NO INTEGER FEASIBLE SOLUTION\n");
       
   251             P->mip_stat = GLP_NOFEAS;
       
   252          }
       
   253       }
       
   254       else if (ret == GLP_EMIPGAP)
       
   255       {  if (parm->msg_lev >= GLP_MSG_ALL)
       
   256             xprintf("RELATIVE MIP GAP TOLERANCE REACHED; SEARCH TERMINA"
       
   257                "TED\n");
       
   258       }
       
   259       else if (ret == GLP_ETMLIM)
       
   260       {  if (parm->msg_lev >= GLP_MSG_ALL)
       
   261             xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n");
       
   262       }
       
   263       else if (ret == GLP_EFAIL)
       
   264       {  if (parm->msg_lev >= GLP_MSG_ERR)
       
   265             xprintf("glp_intopt: cannot solve current LP relaxation\n");
       
   266       }
       
   267       else if (ret == GLP_ESTOP)
       
   268       {  if (parm->msg_lev >= GLP_MSG_ALL)
       
   269             xprintf("SEARCH TERMINATED BY APPLICATION\n");
       
   270       }
       
   271       else
       
   272          xassert(ret != ret);
       
   273 done: return ret;
       
   274 }
       
   275 
       
   276 static int preprocess_and_solve_mip(glp_prob *P, const glp_iocp *parm)
       
   277 {     /* solve MIP using the preprocessor */
       
   278       ENV *env = get_env_ptr();
       
   279       int term_out = env->term_out;
       
   280       NPP *npp;
       
   281       glp_prob *mip = NULL;
       
   282       glp_bfcp bfcp;
       
   283       glp_smcp smcp;
       
   284       int ret;
       
   285       if (parm->msg_lev >= GLP_MSG_ALL)
       
   286          xprintf("Preprocessing...\n");
       
   287       /* create preprocessor workspace */
       
   288       npp = npp_create_wksp();
       
   289       /* load original problem into the preprocessor workspace */
       
   290       npp_load_prob(npp, P, GLP_OFF, GLP_MIP, GLP_OFF);
       
   291       /* process MIP prior to applying the branch-and-bound method */
       
   292       if (!term_out || parm->msg_lev < GLP_MSG_ALL)
       
   293          env->term_out = GLP_OFF;
       
   294       else
       
   295          env->term_out = GLP_ON;
       
   296       ret = npp_integer(npp, parm);
       
   297       env->term_out = term_out;
       
   298       if (ret == 0)
       
   299          ;
       
   300       else if (ret == GLP_ENOPFS)
       
   301       {  if (parm->msg_lev >= GLP_MSG_ALL)
       
   302             xprintf("PROBLEM HAS NO PRIMAL FEASIBLE SOLUTION\n");
       
   303       }
       
   304       else if (ret == GLP_ENODFS)
       
   305       {  if (parm->msg_lev >= GLP_MSG_ALL)
       
   306             xprintf("LP RELAXATION HAS NO DUAL FEASIBLE SOLUTION\n");
       
   307       }
       
   308       else
       
   309          xassert(ret != ret);
       
   310       if (ret != 0) goto done;
       
   311       /* build transformed MIP */
       
   312       mip = glp_create_prob();
       
   313       npp_build_prob(npp, mip);
       
   314       /* if the transformed MIP is empty, it has empty solution, which
       
   315          is optimal */
       
   316       if (mip->m == 0 && mip->n == 0)
       
   317       {  mip->mip_stat = GLP_OPT;
       
   318          mip->mip_obj = mip->c0;
       
   319          if (parm->msg_lev >= GLP_MSG_ALL)
       
   320          {  xprintf("Objective value = %17.9e\n", mip->mip_obj);
       
   321             xprintf("INTEGER OPTIMAL SOLUTION FOUND BY MIP PREPROCESSOR"
       
   322                "\n");
       
   323          }
       
   324          goto post;
       
   325       }
       
   326       /* display some statistics */
       
   327       if (parm->msg_lev >= GLP_MSG_ALL)
       
   328       {  int ni = glp_get_num_int(mip);
       
   329          int nb = glp_get_num_bin(mip);
       
   330          char s[50];
       
   331          xprintf("%d row%s, %d column%s, %d non-zero%s\n",
       
   332             mip->m, mip->m == 1 ? "" : "s", mip->n, mip->n == 1 ? "" :
       
   333             "s", mip->nnz, mip->nnz == 1 ? "" : "s");
       
   334          if (nb == 0)
       
   335             strcpy(s, "none of");
       
   336          else if (ni == 1 && nb == 1)
       
   337             strcpy(s, "");
       
   338          else if (nb == 1)
       
   339             strcpy(s, "one of");
       
   340          else if (nb == ni)
       
   341             strcpy(s, "all of");
       
   342          else
       
   343             sprintf(s, "%d of", nb);
       
   344          xprintf("%d integer variable%s, %s which %s binary\n",
       
   345             ni, ni == 1 ? "" : "s", s, nb == 1 ? "is" : "are");
       
   346       }
       
   347       /* inherit basis factorization control parameters */
       
   348       glp_get_bfcp(P, &bfcp);
       
   349       glp_set_bfcp(mip, &bfcp);
       
   350       /* scale the transformed problem */
       
   351       if (!term_out || parm->msg_lev < GLP_MSG_ALL)
       
   352          env->term_out = GLP_OFF;
       
   353       else
       
   354          env->term_out = GLP_ON;
       
   355       glp_scale_prob(mip,
       
   356          GLP_SF_GM | GLP_SF_EQ | GLP_SF_2N | GLP_SF_SKIP);
       
   357       env->term_out = term_out;
       
   358       /* build advanced initial basis */
       
   359       if (!term_out || parm->msg_lev < GLP_MSG_ALL)
       
   360          env->term_out = GLP_OFF;
       
   361       else
       
   362          env->term_out = GLP_ON;
       
   363       glp_adv_basis(mip, 0);
       
   364       env->term_out = term_out;
       
   365       /* solve initial LP relaxation */
       
   366       if (parm->msg_lev >= GLP_MSG_ALL)
       
   367          xprintf("Solving LP relaxation...\n");
       
   368       glp_init_smcp(&smcp);
       
   369       smcp.msg_lev = parm->msg_lev;
       
   370       mip->it_cnt = P->it_cnt;
       
   371       ret = glp_simplex(mip, &smcp);
       
   372       P->it_cnt = mip->it_cnt;
       
   373       if (ret != 0)
       
   374       {  if (parm->msg_lev >= GLP_MSG_ERR)
       
   375             xprintf("glp_intopt: cannot solve LP relaxation\n");
       
   376          ret = GLP_EFAIL;
       
   377          goto done;
       
   378       }
       
   379       /* check status of the basic solution */
       
   380       ret = glp_get_status(mip);
       
   381       if (ret == GLP_OPT)
       
   382          ret = 0;
       
   383       else if (ret == GLP_NOFEAS)
       
   384          ret = GLP_ENOPFS;
       
   385       else if (ret == GLP_UNBND)
       
   386          ret = GLP_ENODFS;
       
   387       else
       
   388          xassert(ret != ret);
       
   389       if (ret != 0) goto done;
       
   390       /* solve the transformed MIP */
       
   391       mip->it_cnt = P->it_cnt;
       
   392       ret = solve_mip(mip, parm);
       
   393       P->it_cnt = mip->it_cnt;
       
   394       /* only integer feasible solution can be postprocessed */
       
   395       if (!(mip->mip_stat == GLP_OPT || mip->mip_stat == GLP_FEAS))
       
   396       {  P->mip_stat = mip->mip_stat;
       
   397          goto done;
       
   398       }
       
   399       /* postprocess solution from the transformed MIP */
       
   400 post: npp_postprocess(npp, mip);
       
   401       /* the transformed MIP is no longer needed */
       
   402       glp_delete_prob(mip), mip = NULL;
       
   403       /* store solution to the original problem */
       
   404       npp_unload_sol(npp, P);
       
   405 done: /* delete the transformed MIP, if it exists */
       
   406       if (mip != NULL) glp_delete_prob(mip);
       
   407       /* delete preprocessor workspace */
       
   408       npp_delete_wksp(npp);
       
   409       return ret;
       
   410 }
       
   411 
       
   412 #ifndef HAVE_ALIEN_SOLVER /* 28/V-2010 */
       
   413 int _glp_intopt1(glp_prob *P, const glp_iocp *parm)
       
   414 {     xassert(P == P);
       
   415       xassert(parm == parm);
       
   416       xprintf("glp_intopt: no alien solver is available\n");
       
   417       return GLP_EFAIL;
       
   418 }
       
   419 #endif
       
   420 
       
   421 int glp_intopt(glp_prob *P, const glp_iocp *parm)
       
   422 {     /* solve MIP problem with the branch-and-bound method */
       
   423       glp_iocp _parm;
       
   424       int i, j, ret;
       
   425       /* check problem object */
       
   426       if (P == NULL || P->magic != GLP_PROB_MAGIC)
       
   427          xerror("glp_intopt: P = %p; invalid problem object\n", P);
       
   428       if (P->tree != NULL)
       
   429          xerror("glp_intopt: operation not allowed\n");
       
   430       /* check control parameters */
       
   431       if (parm == NULL)
       
   432          parm = &_parm, glp_init_iocp((glp_iocp *)parm);
       
   433       if (!(parm->msg_lev == GLP_MSG_OFF ||
       
   434             parm->msg_lev == GLP_MSG_ERR ||
       
   435             parm->msg_lev == GLP_MSG_ON  ||
       
   436             parm->msg_lev == GLP_MSG_ALL ||
       
   437             parm->msg_lev == GLP_MSG_DBG))
       
   438          xerror("glp_intopt: msg_lev = %d; invalid parameter\n",
       
   439             parm->msg_lev);
       
   440       if (!(parm->br_tech == GLP_BR_FFV ||
       
   441             parm->br_tech == GLP_BR_LFV ||
       
   442             parm->br_tech == GLP_BR_MFV ||
       
   443             parm->br_tech == GLP_BR_DTH ||
       
   444             parm->br_tech == GLP_BR_PCH))
       
   445          xerror("glp_intopt: br_tech = %d; invalid parameter\n",
       
   446             parm->br_tech);
       
   447       if (!(parm->bt_tech == GLP_BT_DFS ||
       
   448             parm->bt_tech == GLP_BT_BFS ||
       
   449             parm->bt_tech == GLP_BT_BLB ||
       
   450             parm->bt_tech == GLP_BT_BPH))
       
   451          xerror("glp_intopt: bt_tech = %d; invalid parameter\n",
       
   452             parm->bt_tech);
       
   453       if (!(0.0 < parm->tol_int && parm->tol_int < 1.0))
       
   454          xerror("glp_intopt: tol_int = %g; invalid parameter\n",
       
   455             parm->tol_int);
       
   456       if (!(0.0 < parm->tol_obj && parm->tol_obj < 1.0))
       
   457          xerror("glp_intopt: tol_obj = %g; invalid parameter\n",
       
   458             parm->tol_obj);
       
   459       if (parm->tm_lim < 0)
       
   460          xerror("glp_intopt: tm_lim = %d; invalid parameter\n",
       
   461             parm->tm_lim);
       
   462       if (parm->out_frq < 0)
       
   463          xerror("glp_intopt: out_frq = %d; invalid parameter\n",
       
   464             parm->out_frq);
       
   465       if (parm->out_dly < 0)
       
   466          xerror("glp_intopt: out_dly = %d; invalid parameter\n",
       
   467             parm->out_dly);
       
   468       if (!(0 <= parm->cb_size && parm->cb_size <= 256))
       
   469          xerror("glp_intopt: cb_size = %d; invalid parameter\n",
       
   470             parm->cb_size);
       
   471       if (!(parm->pp_tech == GLP_PP_NONE ||
       
   472             parm->pp_tech == GLP_PP_ROOT ||
       
   473             parm->pp_tech == GLP_PP_ALL))
       
   474          xerror("glp_intopt: pp_tech = %d; invalid parameter\n",
       
   475             parm->pp_tech);
       
   476       if (parm->mip_gap < 0.0)
       
   477          xerror("glp_intopt: mip_gap = %g; invalid parameter\n",
       
   478             parm->mip_gap);
       
   479       if (!(parm->mir_cuts == GLP_ON || parm->mir_cuts == GLP_OFF))
       
   480          xerror("glp_intopt: mir_cuts = %d; invalid parameter\n",
       
   481             parm->mir_cuts);
       
   482       if (!(parm->gmi_cuts == GLP_ON || parm->gmi_cuts == GLP_OFF))
       
   483          xerror("glp_intopt: gmi_cuts = %d; invalid parameter\n",
       
   484             parm->gmi_cuts);
       
   485       if (!(parm->cov_cuts == GLP_ON || parm->cov_cuts == GLP_OFF))
       
   486          xerror("glp_intopt: cov_cuts = %d; invalid parameter\n",
       
   487             parm->cov_cuts);
       
   488       if (!(parm->clq_cuts == GLP_ON || parm->clq_cuts == GLP_OFF))
       
   489          xerror("glp_intopt: clq_cuts = %d; invalid parameter\n",
       
   490             parm->clq_cuts);
       
   491       if (!(parm->presolve == GLP_ON || parm->presolve == GLP_OFF))
       
   492          xerror("glp_intopt: presolve = %d; invalid parameter\n",
       
   493             parm->presolve);
       
   494       if (!(parm->binarize == GLP_ON || parm->binarize == GLP_OFF))
       
   495          xerror("glp_intopt: binarize = %d; invalid parameter\n",
       
   496             parm->binarize);
       
   497       if (!(parm->fp_heur == GLP_ON || parm->fp_heur == GLP_OFF))
       
   498          xerror("glp_intopt: fp_heur = %d; invalid parameter\n",
       
   499             parm->fp_heur);
       
   500 #if 1 /* 28/V-2010 */
       
   501       if (!(parm->alien == GLP_ON || parm->alien == GLP_OFF))
       
   502          xerror("glp_intopt: alien = %d; invalid parameter\n",
       
   503             parm->alien);
       
   504 #endif
       
   505       /* integer solution is currently undefined */
       
   506       P->mip_stat = GLP_UNDEF;
       
   507       P->mip_obj = 0.0;
       
   508       /* check bounds of double-bounded variables */
       
   509       for (i = 1; i <= P->m; i++)
       
   510       {  GLPROW *row = P->row[i];
       
   511          if (row->type == GLP_DB && row->lb >= row->ub)
       
   512          {  if (parm->msg_lev >= GLP_MSG_ERR)
       
   513                xprintf("glp_intopt: row %d: lb = %g, ub = %g; incorrect"
       
   514                   " bounds\n", i, row->lb, row->ub);
       
   515             ret = GLP_EBOUND;
       
   516             goto done;
       
   517          }
       
   518       }
       
   519       for (j = 1; j <= P->n; j++)
       
   520       {  GLPCOL *col = P->col[j];
       
   521          if (col->type == GLP_DB && col->lb >= col->ub)
       
   522          {  if (parm->msg_lev >= GLP_MSG_ERR)
       
   523                xprintf("glp_intopt: column %d: lb = %g, ub = %g; incorr"
       
   524                   "ect bounds\n", j, col->lb, col->ub);
       
   525             ret = GLP_EBOUND;
       
   526             goto done;
       
   527          }
       
   528       }
       
   529       /* bounds of all integer variables must be integral */
       
   530       for (j = 1; j <= P->n; j++)
       
   531       {  GLPCOL *col = P->col[j];
       
   532          if (col->kind != GLP_IV) continue;
       
   533          if (col->type == GLP_LO || col->type == GLP_DB)
       
   534          {  if (col->lb != floor(col->lb))
       
   535             {  if (parm->msg_lev >= GLP_MSG_ERR)
       
   536                   xprintf("glp_intopt: integer column %d has non-intege"
       
   537                      "r lower bound %g\n", j, col->lb);
       
   538                ret = GLP_EBOUND;
       
   539                goto done;
       
   540             }
       
   541          }
       
   542          if (col->type == GLP_UP || col->type == GLP_DB)
       
   543          {  if (col->ub != floor(col->ub))
       
   544             {  if (parm->msg_lev >= GLP_MSG_ERR)
       
   545                   xprintf("glp_intopt: integer column %d has non-intege"
       
   546                      "r upper bound %g\n", j, col->ub);
       
   547                ret = GLP_EBOUND;
       
   548                goto done;
       
   549             }
       
   550          }
       
   551          if (col->type == GLP_FX)
       
   552          {  if (col->lb != floor(col->lb))
       
   553             {  if (parm->msg_lev >= GLP_MSG_ERR)
       
   554                   xprintf("glp_intopt: integer column %d has non-intege"
       
   555                      "r fixed value %g\n", j, col->lb);
       
   556                ret = GLP_EBOUND;
       
   557                goto done;
       
   558             }
       
   559          }
       
   560       }
       
   561       /* solve MIP problem */
       
   562       if (parm->msg_lev >= GLP_MSG_ALL)
       
   563       {  int ni = glp_get_num_int(P);
       
   564          int nb = glp_get_num_bin(P);
       
   565          char s[50];
       
   566          xprintf("GLPK Integer Optimizer, v%s\n", glp_version());
       
   567          xprintf("%d row%s, %d column%s, %d non-zero%s\n",
       
   568             P->m, P->m == 1 ? "" : "s", P->n, P->n == 1 ? "" : "s",
       
   569             P->nnz, P->nnz == 1 ? "" : "s");
       
   570          if (nb == 0)
       
   571             strcpy(s, "none of");
       
   572          else if (ni == 1 && nb == 1)
       
   573             strcpy(s, "");
       
   574          else if (nb == 1)
       
   575             strcpy(s, "one of");
       
   576          else if (nb == ni)
       
   577             strcpy(s, "all of");
       
   578          else
       
   579             sprintf(s, "%d of", nb);
       
   580          xprintf("%d integer variable%s, %s which %s binary\n",
       
   581             ni, ni == 1 ? "" : "s", s, nb == 1 ? "is" : "are");
       
   582       }
       
   583 #if 1 /* 28/V-2010 */
       
   584       if (parm->alien)
       
   585       {  /* use alien integer optimizer */
       
   586          ret = _glp_intopt1(P, parm);
       
   587          goto done;
       
   588       }
       
   589 #endif
       
   590       if (!parm->presolve)
       
   591          ret = solve_mip(P, parm);
       
   592       else
       
   593          ret = preprocess_and_solve_mip(P, parm);
       
   594 done: /* return to the application program */
       
   595       return ret;
       
   596 }
       
   597 
       
   598 /***********************************************************************
       
   599 *  NAME
       
   600 *
       
   601 *  glp_init_iocp - initialize integer optimizer control parameters
       
   602 *
       
   603 *  SYNOPSIS
       
   604 *
       
   605 *  void glp_init_iocp(glp_iocp *parm);
       
   606 *
       
   607 *  DESCRIPTION
       
   608 *
       
   609 *  The routine glp_init_iocp initializes control parameters, which are
       
   610 *  used by the integer optimizer, with default values.
       
   611 *
       
   612 *  Default values of the control parameters are stored in a glp_iocp
       
   613 *  structure, which the parameter parm points to. */
       
   614 
       
   615 void glp_init_iocp(glp_iocp *parm)
       
   616 {     parm->msg_lev = GLP_MSG_ALL;
       
   617       parm->br_tech = GLP_BR_DTH;
       
   618       parm->bt_tech = GLP_BT_BLB;
       
   619       parm->tol_int = 1e-5;
       
   620       parm->tol_obj = 1e-7;
       
   621       parm->tm_lim = INT_MAX;
       
   622       parm->out_frq = 5000;
       
   623       parm->out_dly = 10000;
       
   624       parm->cb_func = NULL;
       
   625       parm->cb_info = NULL;
       
   626       parm->cb_size = 0;
       
   627       parm->pp_tech = GLP_PP_ALL;
       
   628       parm->mip_gap = 0.0;
       
   629       parm->mir_cuts = GLP_OFF;
       
   630       parm->gmi_cuts = GLP_OFF;
       
   631       parm->cov_cuts = GLP_OFF;
       
   632       parm->clq_cuts = GLP_OFF;
       
   633       parm->presolve = GLP_OFF;
       
   634       parm->binarize = GLP_OFF;
       
   635       parm->fp_heur = GLP_OFF;
       
   636 #if 1 /* 28/V-2010 */
       
   637       parm->alien = GLP_OFF;
       
   638 #endif
       
   639       return;
       
   640 }
       
   641 
       
   642 /***********************************************************************
       
   643 *  NAME
       
   644 *
       
   645 *  glp_mip_status - retrieve status of MIP solution
       
   646 *
       
   647 *  SYNOPSIS
       
   648 *
       
   649 *  int glp_mip_status(glp_prob *mip);
       
   650 *
       
   651 *  RETURNS
       
   652 *
       
   653 *  The routine lpx_mip_status reports the status of MIP solution found
       
   654 *  by the branch-and-bound solver as follows:
       
   655 *
       
   656 *  GLP_UNDEF  - MIP solution is undefined;
       
   657 *  GLP_OPT    - MIP solution is integer optimal;
       
   658 *  GLP_FEAS   - MIP solution is integer feasible but its optimality
       
   659 *               (or non-optimality) has not been proven, perhaps due to
       
   660 *               premature termination of the search;
       
   661 *  GLP_NOFEAS - problem has no integer feasible solution (proven by the
       
   662 *               solver). */
       
   663 
       
   664 int glp_mip_status(glp_prob *mip)
       
   665 {     int mip_stat = mip->mip_stat;
       
   666       return mip_stat;
       
   667 }
       
   668 
       
   669 /***********************************************************************
       
   670 *  NAME
       
   671 *
       
   672 *  glp_mip_obj_val - retrieve objective value (MIP solution)
       
   673 *
       
   674 *  SYNOPSIS
       
   675 *
       
   676 *  double glp_mip_obj_val(glp_prob *mip);
       
   677 *
       
   678 *  RETURNS
       
   679 *
       
   680 *  The routine glp_mip_obj_val returns value of the objective function
       
   681 *  for MIP solution. */
       
   682 
       
   683 double glp_mip_obj_val(glp_prob *mip)
       
   684 {     /*struct LPXCPS *cps = mip->cps;*/
       
   685       double z;
       
   686       z = mip->mip_obj;
       
   687       /*if (cps->round && fabs(z) < 1e-9) z = 0.0;*/
       
   688       return z;
       
   689 }
       
   690 
       
   691 /***********************************************************************
       
   692 *  NAME
       
   693 *
       
   694 *  glp_mip_row_val - retrieve row value (MIP solution)
       
   695 *
       
   696 *  SYNOPSIS
       
   697 *
       
   698 *  double glp_mip_row_val(glp_prob *mip, int i);
       
   699 *
       
   700 *  RETURNS
       
   701 *
       
   702 *  The routine glp_mip_row_val returns value of the auxiliary variable
       
   703 *  associated with i-th row. */
       
   704 
       
   705 double glp_mip_row_val(glp_prob *mip, int i)
       
   706 {     /*struct LPXCPS *cps = mip->cps;*/
       
   707       double mipx;
       
   708       if (!(1 <= i && i <= mip->m))
       
   709          xerror("glp_mip_row_val: i = %d; row number out of range\n", i)
       
   710             ;
       
   711       mipx = mip->row[i]->mipx;
       
   712       /*if (cps->round && fabs(mipx) < 1e-9) mipx = 0.0;*/
       
   713       return mipx;
       
   714 }
       
   715 
       
   716 /***********************************************************************
       
   717 *  NAME
       
   718 *
       
   719 *  glp_mip_col_val - retrieve column value (MIP solution)
       
   720 *
       
   721 *  SYNOPSIS
       
   722 *
       
   723 *  double glp_mip_col_val(glp_prob *mip, int j);
       
   724 *
       
   725 *  RETURNS
       
   726 *
       
   727 *  The routine glp_mip_col_val returns value of the structural variable
       
   728 *  associated with j-th column. */
       
   729 
       
   730 double glp_mip_col_val(glp_prob *mip, int j)
       
   731 {     /*struct LPXCPS *cps = mip->cps;*/
       
   732       double mipx;
       
   733       if (!(1 <= j && j <= mip->n))
       
   734          xerror("glp_mip_col_val: j = %d; column number out of range\n",
       
   735             j);
       
   736       mipx = mip->col[j]->mipx;
       
   737       /*if (cps->round && fabs(mipx) < 1e-9) mipx = 0.0;*/
       
   738       return mipx;
       
   739 }
       
   740 
       
   741 /* eof */