lemon-project-template-glpk

diff deps/glpk/src/glpios09.c @ 9:33de93886c88

Import GLPK 4.47
author Alpar Juttner <alpar@cs.elte.hu>
date Sun, 06 Nov 2011 20:59:10 +0100
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/deps/glpk/src/glpios09.c	Sun Nov 06 20:59:10 2011 +0100
     1.3 @@ -0,0 +1,659 @@
     1.4 +/* glpios09.c (branching heuristics) */
     1.5 +
     1.6 +/***********************************************************************
     1.7 +*  This code is part of GLPK (GNU Linear Programming Kit).
     1.8 +*
     1.9 +*  Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
    1.10 +*  2009, 2010, 2011 Andrew Makhorin, Department for Applied Informatics,
    1.11 +*  Moscow Aviation Institute, Moscow, Russia. All rights reserved.
    1.12 +*  E-mail: <mao@gnu.org>.
    1.13 +*
    1.14 +*  GLPK is free software: you can redistribute it and/or modify it
    1.15 +*  under the terms of the GNU General Public License as published by
    1.16 +*  the Free Software Foundation, either version 3 of the License, or
    1.17 +*  (at your option) any later version.
    1.18 +*
    1.19 +*  GLPK is distributed in the hope that it will be useful, but WITHOUT
    1.20 +*  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    1.21 +*  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
    1.22 +*  License for more details.
    1.23 +*
    1.24 +*  You should have received a copy of the GNU General Public License
    1.25 +*  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
    1.26 +***********************************************************************/
    1.27 +
    1.28 +#include "glpios.h"
    1.29 +
    1.30 +/***********************************************************************
    1.31 +*  NAME
    1.32 +*
    1.33 +*  ios_choose_var - select variable to branch on
    1.34 +*
    1.35 +*  SYNOPSIS
    1.36 +*
    1.37 +*  #include "glpios.h"
    1.38 +*  int ios_choose_var(glp_tree *T, int *next);
    1.39 +*
    1.40 +*  The routine ios_choose_var chooses a variable from the candidate
    1.41 +*  list to branch on. Additionally the routine provides a flag stored
    1.42 +*  in the location next to suggests which of the child subproblems
    1.43 +*  should be solved next.
    1.44 +*
    1.45 +*  RETURNS
    1.46 +*
    1.47 +*  The routine ios_choose_var returns the ordinal number of the column
    1.48 +*  choosen. */
    1.49 +
    1.50 +static int branch_first(glp_tree *T, int *next);
    1.51 +static int branch_last(glp_tree *T, int *next);
    1.52 +static int branch_mostf(glp_tree *T, int *next);
    1.53 +static int branch_drtom(glp_tree *T, int *next);
    1.54 +
    1.55 +int ios_choose_var(glp_tree *T, int *next)
    1.56 +{     int j;
    1.57 +      if (T->parm->br_tech == GLP_BR_FFV)
    1.58 +      {  /* branch on first fractional variable */
    1.59 +         j = branch_first(T, next);
    1.60 +      }
    1.61 +      else if (T->parm->br_tech == GLP_BR_LFV)
    1.62 +      {  /* branch on last fractional variable */
    1.63 +         j = branch_last(T, next);
    1.64 +      }
    1.65 +      else if (T->parm->br_tech == GLP_BR_MFV)
    1.66 +      {  /* branch on most fractional variable */
    1.67 +         j = branch_mostf(T, next);
    1.68 +      }
    1.69 +      else if (T->parm->br_tech == GLP_BR_DTH)
    1.70 +      {  /* branch using the heuristic by Dreebeck and Tomlin */
    1.71 +         j = branch_drtom(T, next);
    1.72 +      }
    1.73 +      else if (T->parm->br_tech == GLP_BR_PCH)
    1.74 +      {  /* hybrid pseudocost heuristic */
    1.75 +         j = ios_pcost_branch(T, next);
    1.76 +      }
    1.77 +      else
    1.78 +         xassert(T != T);
    1.79 +      return j;
    1.80 +}
    1.81 +
    1.82 +/***********************************************************************
    1.83 +*  branch_first - choose first branching variable
    1.84 +*
    1.85 +*  This routine looks up the list of structural variables and chooses
    1.86 +*  the first one, which is of integer kind and has fractional value in
    1.87 +*  optimal solution to the current LP relaxation.
    1.88 +*
    1.89 +*  This routine also selects the branch to be solved next where integer
    1.90 +*  infeasibility of the chosen variable is less than in other one. */
    1.91 +
    1.92 +static int branch_first(glp_tree *T, int *_next)
    1.93 +{     int j, next;
    1.94 +      double beta;
    1.95 +      /* choose the column to branch on */
    1.96 +      for (j = 1; j <= T->n; j++)
    1.97 +         if (T->non_int[j]) break;
    1.98 +      xassert(1 <= j && j <= T->n);
    1.99 +      /* select the branch to be solved next */
   1.100 +      beta = glp_get_col_prim(T->mip, j);
   1.101 +      if (beta - floor(beta) < ceil(beta) - beta)
   1.102 +         next = GLP_DN_BRNCH;
   1.103 +      else
   1.104 +         next = GLP_UP_BRNCH;
   1.105 +      *_next = next;
   1.106 +      return j;
   1.107 +}
   1.108 +
   1.109 +/***********************************************************************
   1.110 +*  branch_last - choose last branching variable
   1.111 +*
   1.112 +*  This routine looks up the list of structural variables and chooses
   1.113 +*  the last one, which is of integer kind and has fractional value in
   1.114 +*  optimal solution to the current LP relaxation.
   1.115 +*
   1.116 +*  This routine also selects the branch to be solved next where integer
   1.117 +*  infeasibility of the chosen variable is less than in other one. */
   1.118 +
   1.119 +static int branch_last(glp_tree *T, int *_next)
   1.120 +{     int j, next;
   1.121 +      double beta;
   1.122 +      /* choose the column to branch on */
   1.123 +      for (j = T->n; j >= 1; j--)
   1.124 +         if (T->non_int[j]) break;
   1.125 +      xassert(1 <= j && j <= T->n);
   1.126 +      /* select the branch to be solved next */
   1.127 +      beta = glp_get_col_prim(T->mip, j);
   1.128 +      if (beta - floor(beta) < ceil(beta) - beta)
   1.129 +         next = GLP_DN_BRNCH;
   1.130 +      else
   1.131 +         next = GLP_UP_BRNCH;
   1.132 +      *_next = next;
   1.133 +      return j;
   1.134 +}
   1.135 +
   1.136 +/***********************************************************************
   1.137 +*  branch_mostf - choose most fractional branching variable
   1.138 +*
   1.139 +*  This routine looks up the list of structural variables and chooses
   1.140 +*  that one, which is of integer kind and has most fractional value in
   1.141 +*  optimal solution to the current LP relaxation.
   1.142 +*
   1.143 +*  This routine also selects the branch to be solved next where integer
   1.144 +*  infeasibility of the chosen variable is less than in other one.
   1.145 +*
   1.146 +*  (Alexander Martin notices that "...most infeasible is as good as
   1.147 +*  random...".) */
   1.148 +
   1.149 +static int branch_mostf(glp_tree *T, int *_next)
   1.150 +{     int j, jj, next;
   1.151 +      double beta, most, temp;
   1.152 +      /* choose the column to branch on */
   1.153 +      jj = 0, most = DBL_MAX;
   1.154 +      for (j = 1; j <= T->n; j++)
   1.155 +      {  if (T->non_int[j])
   1.156 +         {  beta = glp_get_col_prim(T->mip, j);
   1.157 +            temp = floor(beta) + 0.5;
   1.158 +            if (most > fabs(beta - temp))
   1.159 +            {  jj = j, most = fabs(beta - temp);
   1.160 +               if (beta < temp)
   1.161 +                  next = GLP_DN_BRNCH;
   1.162 +               else
   1.163 +                  next = GLP_UP_BRNCH;
   1.164 +            }
   1.165 +         }
   1.166 +      }
   1.167 +      *_next = next;
   1.168 +      return jj;
   1.169 +}
   1.170 +
   1.171 +/***********************************************************************
   1.172 +*  branch_drtom - choose branching var using Driebeck-Tomlin heuristic
   1.173 +*
   1.174 +*  This routine chooses a structural variable, which is required to be
   1.175 +*  integral and has fractional value in optimal solution of the current
   1.176 +*  LP relaxation, using a heuristic proposed by Driebeck and Tomlin.
   1.177 +*
   1.178 +*  The routine also selects the branch to be solved next, again due to
   1.179 +*  Driebeck and Tomlin.
   1.180 +*
   1.181 +*  This routine is based on the heuristic proposed in:
   1.182 +*
   1.183 +*  Driebeck N.J. An algorithm for the solution of mixed-integer
   1.184 +*  programming problems, Management Science, 12: 576-87 (1966);
   1.185 +*
   1.186 +*  and improved in:
   1.187 +*
   1.188 +*  Tomlin J.A. Branch and bound methods for integer and non-convex
   1.189 +*  programming, in J.Abadie (ed.), Integer and Nonlinear Programming,
   1.190 +*  North-Holland, Amsterdam, pp. 437-50 (1970).
   1.191 +*
   1.192 +*  Must note that this heuristic is time-expensive, because computing
   1.193 +*  one-step degradation (see the routine below) requires one BTRAN for
   1.194 +*  each fractional-valued structural variable. */
   1.195 +
   1.196 +static int branch_drtom(glp_tree *T, int *_next)
   1.197 +{     glp_prob *mip = T->mip;
   1.198 +      int m = mip->m;
   1.199 +      int n = mip->n;
   1.200 +      char *non_int = T->non_int;
   1.201 +      int j, jj, k, t, next, kase, len, stat, *ind;
   1.202 +      double x, dk, alfa, delta_j, delta_k, delta_z, dz_dn, dz_up,
   1.203 +         dd_dn, dd_up, degrad, *val;
   1.204 +      /* basic solution of LP relaxation must be optimal */
   1.205 +      xassert(glp_get_status(mip) == GLP_OPT);
   1.206 +      /* allocate working arrays */
   1.207 +      ind = xcalloc(1+n, sizeof(int));
   1.208 +      val = xcalloc(1+n, sizeof(double));
   1.209 +      /* nothing has been chosen so far */
   1.210 +      jj = 0, degrad = -1.0;
   1.211 +      /* walk through the list of columns (structural variables) */
   1.212 +      for (j = 1; j <= n; j++)
   1.213 +      {  /* if j-th column is not marked as fractional, skip it */
   1.214 +         if (!non_int[j]) continue;
   1.215 +         /* obtain (fractional) value of j-th column in basic solution
   1.216 +            of LP relaxation */
   1.217 +         x = glp_get_col_prim(mip, j);
   1.218 +         /* since the value of j-th column is fractional, the column is
   1.219 +            basic; compute corresponding row of the simplex table */
   1.220 +         len = glp_eval_tab_row(mip, m+j, ind, val);
   1.221 +         /* the following fragment computes a change in the objective
   1.222 +            function: delta Z = new Z - old Z, where old Z is the
   1.223 +            objective value in the current optimal basis, and new Z is
   1.224 +            the objective value in the adjacent basis, for two cases:
   1.225 +            1) if new upper bound ub' = floor(x[j]) is introduced for
   1.226 +               j-th column (down branch);
   1.227 +            2) if new lower bound lb' = ceil(x[j]) is introduced for
   1.228 +               j-th column (up branch);
   1.229 +            since in both cases the solution remaining dual feasible
   1.230 +            becomes primal infeasible, one implicit simplex iteration
   1.231 +            is performed to determine the change delta Z;
   1.232 +            it is obvious that new Z, which is never better than old Z,
   1.233 +            is a lower (minimization) or upper (maximization) bound of
   1.234 +            the objective function for down- and up-branches. */
   1.235 +         for (kase = -1; kase <= +1; kase += 2)
   1.236 +         {  /* if kase < 0, the new upper bound of x[j] is introduced;
   1.237 +               in this case x[j] should decrease in order to leave the
   1.238 +               basis and go to its new upper bound */
   1.239 +            /* if kase > 0, the new lower bound of x[j] is introduced;
   1.240 +               in this case x[j] should increase in order to leave the
   1.241 +               basis and go to its new lower bound */
   1.242 +            /* apply the dual ratio test in order to determine which
   1.243 +               auxiliary or structural variable should enter the basis
   1.244 +               to keep dual feasibility */
   1.245 +            k = glp_dual_rtest(mip, len, ind, val, kase, 1e-9);
   1.246 +            if (k != 0) k = ind[k];
   1.247 +            /* if no non-basic variable has been chosen, LP relaxation
   1.248 +               of corresponding branch being primal infeasible and dual
   1.249 +               unbounded has no primal feasible solution; in this case
   1.250 +               the change delta Z is formally set to infinity */
   1.251 +            if (k == 0)
   1.252 +            {  delta_z =
   1.253 +                  (T->mip->dir == GLP_MIN ? +DBL_MAX : -DBL_MAX);
   1.254 +               goto skip;
   1.255 +            }
   1.256 +            /* row of the simplex table that corresponds to non-basic
   1.257 +               variable x[k] choosen by the dual ratio test is:
   1.258 +                  x[j] = ... + alfa * x[k] + ...
   1.259 +               where alfa is the influence coefficient (an element of
   1.260 +               the simplex table row) */
   1.261 +            /* determine the coefficient alfa */
   1.262 +            for (t = 1; t <= len; t++) if (ind[t] == k) break;
   1.263 +            xassert(1 <= t && t <= len);
   1.264 +            alfa = val[t];
   1.265 +            /* since in the adjacent basis the variable x[j] becomes
   1.266 +               non-basic, knowing its value in the current basis we can
   1.267 +               determine its change delta x[j] = new x[j] - old x[j] */
   1.268 +            delta_j = (kase < 0 ? floor(x) : ceil(x)) - x;
   1.269 +            /* and knowing the coefficient alfa we can determine the
   1.270 +               corresponding change delta x[k] = new x[k] - old x[k],
   1.271 +               where old x[k] is a value of x[k] in the current basis,
   1.272 +               and new x[k] is a value of x[k] in the adjacent basis */
   1.273 +            delta_k = delta_j / alfa;
   1.274 +            /* Tomlin noticed that if the variable x[k] is of integer
   1.275 +               kind, its change cannot be less (eventually) than one in
   1.276 +               the magnitude */
   1.277 +            if (k > m && glp_get_col_kind(mip, k-m) != GLP_CV)
   1.278 +            {  /* x[k] is structural integer variable */
   1.279 +               if (fabs(delta_k - floor(delta_k + 0.5)) > 1e-3)
   1.280 +               {  if (delta_k > 0.0)
   1.281 +                     delta_k = ceil(delta_k);  /* +3.14 -> +4 */
   1.282 +                  else
   1.283 +                     delta_k = floor(delta_k); /* -3.14 -> -4 */
   1.284 +               }
   1.285 +            }
   1.286 +            /* now determine the status and reduced cost of x[k] in the
   1.287 +               current basis */
   1.288 +            if (k <= m)
   1.289 +            {  stat = glp_get_row_stat(mip, k);
   1.290 +               dk = glp_get_row_dual(mip, k);
   1.291 +            }
   1.292 +            else
   1.293 +            {  stat = glp_get_col_stat(mip, k-m);
   1.294 +               dk = glp_get_col_dual(mip, k-m);
   1.295 +            }
   1.296 +            /* if the current basis is dual degenerate, some reduced
   1.297 +               costs which are close to zero may have wrong sign due to
   1.298 +               round-off errors, so correct the sign of d[k] */
   1.299 +            switch (T->mip->dir)
   1.300 +            {  case GLP_MIN:
   1.301 +                  if (stat == GLP_NL && dk < 0.0 ||
   1.302 +                      stat == GLP_NU && dk > 0.0 ||
   1.303 +                      stat == GLP_NF) dk = 0.0;
   1.304 +                  break;
   1.305 +               case GLP_MAX:
   1.306 +                  if (stat == GLP_NL && dk > 0.0 ||
   1.307 +                      stat == GLP_NU && dk < 0.0 ||
   1.308 +                      stat == GLP_NF) dk = 0.0;
   1.309 +                  break;
   1.310 +               default:
   1.311 +                  xassert(T != T);
   1.312 +            }
   1.313 +            /* now knowing the change of x[k] and its reduced cost d[k]
   1.314 +               we can compute the corresponding change in the objective
   1.315 +               function delta Z = new Z - old Z = d[k] * delta x[k];
   1.316 +               note that due to Tomlin's modification new Z can be even
   1.317 +               worse than in the adjacent basis */
   1.318 +            delta_z = dk * delta_k;
   1.319 +skip:       /* new Z is never better than old Z, therefore the change
   1.320 +               delta Z is always non-negative (in case of minimization)
   1.321 +               or non-positive (in case of maximization) */
   1.322 +            switch (T->mip->dir)
   1.323 +            {  case GLP_MIN: xassert(delta_z >= 0.0); break;
   1.324 +               case GLP_MAX: xassert(delta_z <= 0.0); break;
   1.325 +               default: xassert(T != T);
   1.326 +            }
   1.327 +            /* save the change in the objective fnction for down- and
   1.328 +               up-branches, respectively */
   1.329 +            if (kase < 0) dz_dn = delta_z; else dz_up = delta_z;
   1.330 +         }
   1.331 +         /* thus, in down-branch no integer feasible solution can be
   1.332 +            better than Z + dz_dn, and in up-branch no integer feasible
   1.333 +            solution can be better than Z + dz_up, where Z is value of
   1.334 +            the objective function in the current basis */
   1.335 +         /* following the heuristic by Driebeck and Tomlin we choose a
   1.336 +            column (i.e. structural variable) which provides largest
   1.337 +            degradation of the objective function in some of branches;
   1.338 +            besides, we select the branch with smaller degradation to
   1.339 +            be solved next and keep other branch with larger degradation
   1.340 +            in the active list hoping to minimize the number of further
   1.341 +            backtrackings */
   1.342 +         if (degrad < fabs(dz_dn) || degrad < fabs(dz_up))
   1.343 +         {  jj = j;
   1.344 +            if (fabs(dz_dn) < fabs(dz_up))
   1.345 +            {  /* select down branch to be solved next */
   1.346 +               next = GLP_DN_BRNCH;
   1.347 +               degrad = fabs(dz_up);
   1.348 +            }
   1.349 +            else
   1.350 +            {  /* select up branch to be solved next */
   1.351 +               next = GLP_UP_BRNCH;
   1.352 +               degrad = fabs(dz_dn);
   1.353 +            }
   1.354 +            /* save the objective changes for printing */
   1.355 +            dd_dn = dz_dn, dd_up = dz_up;
   1.356 +            /* if down- or up-branch has no feasible solution, we does
   1.357 +               not need to consider other candidates (in principle, the
   1.358 +               corresponding branch could be pruned right now) */
   1.359 +            if (degrad == DBL_MAX) break;
   1.360 +         }
   1.361 +      }
   1.362 +      /* free working arrays */
   1.363 +      xfree(ind);
   1.364 +      xfree(val);
   1.365 +      /* something must be chosen */
   1.366 +      xassert(1 <= jj && jj <= n);
   1.367 +#if 1 /* 02/XI-2009 */
   1.368 +      if (degrad < 1e-6 * (1.0 + 0.001 * fabs(mip->obj_val)))
   1.369 +      {  jj = branch_mostf(T, &next);
   1.370 +         goto done;
   1.371 +      }
   1.372 +#endif
   1.373 +      if (T->parm->msg_lev >= GLP_MSG_DBG)
   1.374 +      {  xprintf("branch_drtom: column %d chosen to branch on\n", jj);
   1.375 +         if (fabs(dd_dn) == DBL_MAX)
   1.376 +            xprintf("branch_drtom: down-branch is infeasible\n");
   1.377 +         else
   1.378 +            xprintf("branch_drtom: down-branch bound is %.9e\n",
   1.379 +               lpx_get_obj_val(mip) + dd_dn);
   1.380 +         if (fabs(dd_up) == DBL_MAX)
   1.381 +            xprintf("branch_drtom: up-branch   is infeasible\n");
   1.382 +         else
   1.383 +            xprintf("branch_drtom: up-branch   bound is %.9e\n",
   1.384 +               lpx_get_obj_val(mip) + dd_up);
   1.385 +      }
   1.386 +done: *_next = next;
   1.387 +      return jj;
   1.388 +}
   1.389 +
   1.390 +/**********************************************************************/
   1.391 +
   1.392 +struct csa
   1.393 +{     /* common storage area */
   1.394 +      int *dn_cnt; /* int dn_cnt[1+n]; */
   1.395 +      /* dn_cnt[j] is the number of subproblems, whose LP relaxations
   1.396 +         have been solved and which are down-branches for variable x[j];
   1.397 +         dn_cnt[j] = 0 means the down pseudocost is uninitialized */
   1.398 +      double *dn_sum; /* double dn_sum[1+n]; */
   1.399 +      /* dn_sum[j] is the sum of per unit degradations of the objective
   1.400 +         over all dn_cnt[j] subproblems */
   1.401 +      int *up_cnt; /* int up_cnt[1+n]; */
   1.402 +      /* up_cnt[j] is the number of subproblems, whose LP relaxations
   1.403 +         have been solved and which are up-branches for variable x[j];
   1.404 +         up_cnt[j] = 0 means the up pseudocost is uninitialized */
   1.405 +      double *up_sum; /* double up_sum[1+n]; */
   1.406 +      /* up_sum[j] is the sum of per unit degradations of the objective
   1.407 +         over all up_cnt[j] subproblems */
   1.408 +};
   1.409 +
   1.410 +void *ios_pcost_init(glp_tree *tree)
   1.411 +{     /* initialize working data used on pseudocost branching */
   1.412 +      struct csa *csa;
   1.413 +      int n = tree->n, j;
   1.414 +      csa = xmalloc(sizeof(struct csa));
   1.415 +      csa->dn_cnt = xcalloc(1+n, sizeof(int));
   1.416 +      csa->dn_sum = xcalloc(1+n, sizeof(double));
   1.417 +      csa->up_cnt = xcalloc(1+n, sizeof(int));
   1.418 +      csa->up_sum = xcalloc(1+n, sizeof(double));
   1.419 +      for (j = 1; j <= n; j++)
   1.420 +      {  csa->dn_cnt[j] = csa->up_cnt[j] = 0;
   1.421 +         csa->dn_sum[j] = csa->up_sum[j] = 0.0;
   1.422 +      }
   1.423 +      return csa;
   1.424 +}
   1.425 +
   1.426 +static double eval_degrad(glp_prob *P, int j, double bnd)
   1.427 +{     /* compute degradation of the objective on fixing x[j] at given
   1.428 +         value with a limited number of dual simplex iterations */
   1.429 +      /* this routine fixes column x[j] at specified value bnd,
   1.430 +         solves resulting LP, and returns a lower bound to degradation
   1.431 +         of the objective, degrad >= 0 */
   1.432 +      glp_prob *lp;
   1.433 +      glp_smcp parm;
   1.434 +      int ret;
   1.435 +      double degrad;
   1.436 +      /* the current basis must be optimal */
   1.437 +      xassert(glp_get_status(P) == GLP_OPT);
   1.438 +      /* create a copy of P */
   1.439 +      lp = glp_create_prob();
   1.440 +      glp_copy_prob(lp, P, 0);
   1.441 +      /* fix column x[j] at specified value */
   1.442 +      glp_set_col_bnds(lp, j, GLP_FX, bnd, bnd);
   1.443 +      /* try to solve resulting LP */
   1.444 +      glp_init_smcp(&parm);
   1.445 +      parm.msg_lev = GLP_MSG_OFF;
   1.446 +      parm.meth = GLP_DUAL;
   1.447 +      parm.it_lim = 30;
   1.448 +      parm.out_dly = 1000;
   1.449 +      parm.meth = GLP_DUAL;
   1.450 +      ret = glp_simplex(lp, &parm);
   1.451 +      if (ret == 0 || ret == GLP_EITLIM)
   1.452 +      {  if (glp_get_prim_stat(lp) == GLP_NOFEAS)
   1.453 +         {  /* resulting LP has no primal feasible solution */
   1.454 +            degrad = DBL_MAX;
   1.455 +         }
   1.456 +         else if (glp_get_dual_stat(lp) == GLP_FEAS)
   1.457 +         {  /* resulting basis is optimal or at least dual feasible,
   1.458 +               so we have the correct lower bound to degradation */
   1.459 +            if (P->dir == GLP_MIN)
   1.460 +               degrad = lp->obj_val - P->obj_val;
   1.461 +            else if (P->dir == GLP_MAX)
   1.462 +               degrad = P->obj_val - lp->obj_val;
   1.463 +            else
   1.464 +               xassert(P != P);
   1.465 +            /* degradation cannot be negative by definition */
   1.466 +            /* note that the lower bound to degradation may be close
   1.467 +               to zero even if its exact value is zero due to round-off
   1.468 +               errors on computing the objective value */
   1.469 +            if (degrad < 1e-6 * (1.0 + 0.001 * fabs(P->obj_val)))
   1.470 +               degrad = 0.0;
   1.471 +         }
   1.472 +         else
   1.473 +         {  /* the final basis reported by the simplex solver is dual
   1.474 +               infeasible, so we cannot determine a non-trivial lower
   1.475 +               bound to degradation */
   1.476 +            degrad = 0.0;
   1.477 +         }
   1.478 +      }
   1.479 +      else
   1.480 +      {  /* the simplex solver failed */
   1.481 +         degrad = 0.0;
   1.482 +      }
   1.483 +      /* delete the copy of P */
   1.484 +      glp_delete_prob(lp);
   1.485 +      return degrad;
   1.486 +}
   1.487 +
   1.488 +void ios_pcost_update(glp_tree *tree)
   1.489 +{     /* update history information for pseudocost branching */
   1.490 +      /* this routine is called every time when LP relaxation of the
   1.491 +         current subproblem has been solved to optimality with all lazy
   1.492 +         and cutting plane constraints included */
   1.493 +      int j;
   1.494 +      double dx, dz, psi;
   1.495 +      struct csa *csa = tree->pcost;
   1.496 +      xassert(csa != NULL);
   1.497 +      xassert(tree->curr != NULL);
   1.498 +      /* if the current subproblem is the root, skip updating */
   1.499 +      if (tree->curr->up == NULL) goto skip;
   1.500 +      /* determine branching variable x[j], which was used in the
   1.501 +         parent subproblem to create the current subproblem */
   1.502 +      j = tree->curr->up->br_var;
   1.503 +      xassert(1 <= j && j <= tree->n);
   1.504 +      /* determine the change dx[j] = new x[j] - old x[j],
   1.505 +         where new x[j] is a value of x[j] in optimal solution to LP
   1.506 +         relaxation of the current subproblem, old x[j] is a value of
   1.507 +         x[j] in optimal solution to LP relaxation of the parent
   1.508 +         subproblem */
   1.509 +      dx = tree->mip->col[j]->prim - tree->curr->up->br_val;
   1.510 +      xassert(dx != 0.0);
   1.511 +      /* determine corresponding change dz = new dz - old dz in the
   1.512 +         objective function value */
   1.513 +      dz = tree->mip->obj_val - tree->curr->up->lp_obj;
   1.514 +      /* determine per unit degradation of the objective function */
   1.515 +      psi = fabs(dz / dx);
   1.516 +      /* update history information */
   1.517 +      if (dx < 0.0)
   1.518 +      {  /* the current subproblem is down-branch */
   1.519 +         csa->dn_cnt[j]++;
   1.520 +         csa->dn_sum[j] += psi;
   1.521 +      }
   1.522 +      else /* dx > 0.0 */
   1.523 +      {  /* the current subproblem is up-branch */
   1.524 +         csa->up_cnt[j]++;
   1.525 +         csa->up_sum[j] += psi;
   1.526 +      }
   1.527 +skip: return;
   1.528 +}
   1.529 +
   1.530 +void ios_pcost_free(glp_tree *tree)
   1.531 +{     /* free working area used on pseudocost branching */
   1.532 +      struct csa *csa = tree->pcost;
   1.533 +      xassert(csa != NULL);
   1.534 +      xfree(csa->dn_cnt);
   1.535 +      xfree(csa->dn_sum);
   1.536 +      xfree(csa->up_cnt);
   1.537 +      xfree(csa->up_sum);
   1.538 +      xfree(csa);
   1.539 +      tree->pcost = NULL;
   1.540 +      return;
   1.541 +}
   1.542 +
   1.543 +static double eval_psi(glp_tree *T, int j, int brnch)
   1.544 +{     /* compute estimation of pseudocost of variable x[j] for down-
   1.545 +         or up-branch */
   1.546 +      struct csa *csa = T->pcost;
   1.547 +      double beta, degrad, psi;
   1.548 +      xassert(csa != NULL);
   1.549 +      xassert(1 <= j && j <= T->n);
   1.550 +      if (brnch == GLP_DN_BRNCH)
   1.551 +      {  /* down-branch */
   1.552 +         if (csa->dn_cnt[j] == 0)
   1.553 +         {  /* initialize down pseudocost */
   1.554 +            beta = T->mip->col[j]->prim;
   1.555 +            degrad = eval_degrad(T->mip, j, floor(beta));
   1.556 +            if (degrad == DBL_MAX)
   1.557 +            {  psi = DBL_MAX;
   1.558 +               goto done;
   1.559 +            }
   1.560 +            csa->dn_cnt[j] = 1;
   1.561 +            csa->dn_sum[j] = degrad / (beta - floor(beta));
   1.562 +         }
   1.563 +         psi = csa->dn_sum[j] / (double)csa->dn_cnt[j];
   1.564 +      }
   1.565 +      else if (brnch == GLP_UP_BRNCH)
   1.566 +      {  /* up-branch */
   1.567 +         if (csa->up_cnt[j] == 0)
   1.568 +         {  /* initialize up pseudocost */
   1.569 +            beta = T->mip->col[j]->prim;
   1.570 +            degrad = eval_degrad(T->mip, j, ceil(beta));
   1.571 +            if (degrad == DBL_MAX)
   1.572 +            {  psi = DBL_MAX;
   1.573 +               goto done;
   1.574 +            }
   1.575 +            csa->up_cnt[j] = 1;
   1.576 +            csa->up_sum[j] = degrad / (ceil(beta) - beta);
   1.577 +         }
   1.578 +         psi = csa->up_sum[j] / (double)csa->up_cnt[j];
   1.579 +      }
   1.580 +      else
   1.581 +         xassert(brnch != brnch);
   1.582 +done: return psi;
   1.583 +}
   1.584 +
   1.585 +static void progress(glp_tree *T)
   1.586 +{     /* display progress of pseudocost initialization */
   1.587 +      struct csa *csa = T->pcost;
   1.588 +      int j, nv = 0, ni = 0;
   1.589 +      for (j = 1; j <= T->n; j++)
   1.590 +      {  if (glp_ios_can_branch(T, j))
   1.591 +         {  nv++;
   1.592 +            if (csa->dn_cnt[j] > 0 && csa->up_cnt[j] > 0) ni++;
   1.593 +         }
   1.594 +      }
   1.595 +      xprintf("Pseudocosts initialized for %d of %d variables\n",
   1.596 +         ni, nv);
   1.597 +      return;
   1.598 +}
   1.599 +
   1.600 +int ios_pcost_branch(glp_tree *T, int *_next)
   1.601 +{     /* choose branching variable with pseudocost branching */
   1.602 +      glp_long t = xtime();
   1.603 +      int j, jjj, sel;
   1.604 +      double beta, psi, d1, d2, d, dmax;
   1.605 +      /* initialize the working arrays */
   1.606 +      if (T->pcost == NULL)
   1.607 +         T->pcost = ios_pcost_init(T);
   1.608 +      /* nothing has been chosen so far */
   1.609 +      jjj = 0, dmax = -1.0;
   1.610 +      /* go through the list of branching candidates */
   1.611 +      for (j = 1; j <= T->n; j++)
   1.612 +      {  if (!glp_ios_can_branch(T, j)) continue;
   1.613 +         /* determine primal value of x[j] in optimal solution to LP
   1.614 +            relaxation of the current subproblem */
   1.615 +         beta = T->mip->col[j]->prim;
   1.616 +         /* estimate pseudocost of x[j] for down-branch */
   1.617 +         psi = eval_psi(T, j, GLP_DN_BRNCH);
   1.618 +         if (psi == DBL_MAX)
   1.619 +         {  /* down-branch has no primal feasible solution */
   1.620 +            jjj = j, sel = GLP_DN_BRNCH;
   1.621 +            goto done;
   1.622 +         }
   1.623 +         /* estimate degradation of the objective for down-branch */
   1.624 +         d1 = psi * (beta - floor(beta));
   1.625 +         /* estimate pseudocost of x[j] for up-branch */
   1.626 +         psi = eval_psi(T, j, GLP_UP_BRNCH);
   1.627 +         if (psi == DBL_MAX)
   1.628 +         {  /* up-branch has no primal feasible solution */
   1.629 +            jjj = j, sel = GLP_UP_BRNCH;
   1.630 +            goto done;
   1.631 +         }
   1.632 +         /* estimate degradation of the objective for up-branch */
   1.633 +         d2 = psi * (ceil(beta) - beta);
   1.634 +         /* determine d = max(d1, d2) */
   1.635 +         d = (d1 > d2 ? d1 : d2);
   1.636 +         /* choose x[j] which provides maximal estimated degradation of
   1.637 +            the objective either in down- or up-branch */
   1.638 +         if (dmax < d)
   1.639 +         {  dmax = d;
   1.640 +            jjj = j;
   1.641 +            /* continue the search from a subproblem, where degradation
   1.642 +               is less than in other one */
   1.643 +            sel = (d1 <= d2 ? GLP_DN_BRNCH : GLP_UP_BRNCH);
   1.644 +         }
   1.645 +         /* display progress of pseudocost initialization */
   1.646 +         if (T->parm->msg_lev >= GLP_ON)
   1.647 +         {  if (xdifftime(xtime(), t) >= 10.0)
   1.648 +            {  progress(T);
   1.649 +               t = xtime();
   1.650 +            }
   1.651 +         }
   1.652 +      }
   1.653 +      if (dmax == 0.0)
   1.654 +      {  /* no degradation is indicated; choose a variable having most
   1.655 +            fractional value */
   1.656 +         jjj = branch_mostf(T, &sel);
   1.657 +      }
   1.658 +done: *_next = sel;
   1.659 +      return jjj;
   1.660 +}
   1.661 +
   1.662 +/* eof */