123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660 |
- /* glpios09.c (branching heuristics) */
- /***********************************************************************
- * This code is part of GLPK (GNU Linear Programming Kit).
- *
- * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
- * 2009, 2010 Andrew Makhorin, Department for Applied Informatics,
- * Moscow Aviation Institute, Moscow, Russia. All rights reserved.
- * E-mail: <mao@gnu.org>.
- *
- * GLPK is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GLPK is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- * License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GLPK. If not, see <http://www.gnu.org/licenses/>.
- ***********************************************************************/
- #include "glpios.h"
- /***********************************************************************
- * NAME
- *
- * ios_choose_var - select variable to branch on
- *
- * SYNOPSIS
- *
- * #include "glpios.h"
- * int ios_choose_var(glp_tree *T, int *next);
- *
- * The routine ios_choose_var chooses a variable from the candidate
- * list to branch on. Additionally the routine provides a flag stored
- * in the location next to suggests which of the child subproblems
- * should be solved next.
- *
- * RETURNS
- *
- * The routine ios_choose_var returns the ordinal number of the column
- * choosen. */
- static int branch_first(glp_tree *T, int *next);
- static int branch_last(glp_tree *T, int *next);
- static int branch_mostf(glp_tree *T, int *next);
- static int branch_drtom(glp_tree *T, int *next);
- int ios_choose_var(glp_tree *T, int *next)
- { int j;
- if (T->parm->br_tech == GLP_BR_FFV)
- { /* branch on first fractional variable */
- j = branch_first(T, next);
- }
- else if (T->parm->br_tech == GLP_BR_LFV)
- { /* branch on last fractional variable */
- j = branch_last(T, next);
- }
- else if (T->parm->br_tech == GLP_BR_MFV)
- { /* branch on most fractional variable */
- j = branch_mostf(T, next);
- }
- else if (T->parm->br_tech == GLP_BR_DTH)
- { /* branch using the heuristic by Dreebeck and Tomlin */
- j = branch_drtom(T, next);
- }
- else if (T->parm->br_tech == GLP_BR_PCH)
- { /* hybrid pseudocost heuristic */
- j = ios_pcost_branch(T, next);
- }
- else
- xassert(T != T);
- return j;
- }
- /***********************************************************************
- * branch_first - choose first branching variable
- *
- * This routine looks up the list of structural variables and chooses
- * the first one, which is of integer kind and has fractional value in
- * optimal solution to the current LP relaxation.
- *
- * This routine also selects the branch to be solved next where integer
- * infeasibility of the chosen variable is less than in other one. */
- static int branch_first(glp_tree *T, int *_next)
- { int j, next;
- double beta;
- /* choose the column to branch on */
- for (j = 1; j <= T->n; j++)
- if (T->non_int[j]) break;
- xassert(1 <= j && j <= T->n);
- /* select the branch to be solved next */
- beta = glp_get_col_prim(T->mip, j);
- if (beta - floor(beta) < ceil(beta) - beta)
- next = GLP_DN_BRNCH;
- else
- next = GLP_UP_BRNCH;
- *_next = next;
- return j;
- }
- /***********************************************************************
- * branch_last - choose last branching variable
- *
- * This routine looks up the list of structural variables and chooses
- * the last one, which is of integer kind and has fractional value in
- * optimal solution to the current LP relaxation.
- *
- * This routine also selects the branch to be solved next where integer
- * infeasibility of the chosen variable is less than in other one. */
- static int branch_last(glp_tree *T, int *_next)
- { int j, next;
- double beta;
- /* choose the column to branch on */
- for (j = T->n; j >= 1; j--)
- if (T->non_int[j]) break;
- xassert(1 <= j && j <= T->n);
- /* select the branch to be solved next */
- beta = glp_get_col_prim(T->mip, j);
- if (beta - floor(beta) < ceil(beta) - beta)
- next = GLP_DN_BRNCH;
- else
- next = GLP_UP_BRNCH;
- *_next = next;
- return j;
- }
- /***********************************************************************
- * branch_mostf - choose most fractional branching variable
- *
- * This routine looks up the list of structural variables and chooses
- * that one, which is of integer kind and has most fractional value in
- * optimal solution to the current LP relaxation.
- *
- * This routine also selects the branch to be solved next where integer
- * infeasibility of the chosen variable is less than in other one.
- *
- * (Alexander Martin notices that "...most infeasible is as good as
- * random...".) */
- static int branch_mostf(glp_tree *T, int *_next)
- { int j, jj, next;
- double beta, most, temp;
- /* choose the column to branch on */
- jj = 0, most = DBL_MAX;
- for (j = 1; j <= T->n; j++)
- { if (T->non_int[j])
- { beta = glp_get_col_prim(T->mip, j);
- temp = floor(beta) + 0.5;
- if (most > fabs(beta - temp))
- { jj = j, most = fabs(beta - temp);
- if (beta < temp)
- next = GLP_DN_BRNCH;
- else
- next = GLP_UP_BRNCH;
- }
- }
- }
- *_next = next;
- return jj;
- }
- /***********************************************************************
- * branch_drtom - choose branching var using Driebeck-Tomlin heuristic
- *
- * This routine chooses a structural variable, which is required to be
- * integral and has fractional value in optimal solution of the current
- * LP relaxation, using a heuristic proposed by Driebeck and Tomlin.
- *
- * The routine also selects the branch to be solved next, again due to
- * Driebeck and Tomlin.
- *
- * This routine is based on the heuristic proposed in:
- *
- * Driebeck N.J. An algorithm for the solution of mixed-integer
- * programming problems, Management Science, 12: 576-87 (1966);
- *
- * and improved in:
- *
- * Tomlin J.A. Branch and bound methods for integer and non-convex
- * programming, in J.Abadie (ed.), Integer and Nonlinear Programming,
- * North-Holland, Amsterdam, pp. 437-50 (1970).
- *
- * Must note that this heuristic is time-expensive, because computing
- * one-step degradation (see the routine below) requires one BTRAN for
- * each fractional-valued structural variable. */
- static int branch_drtom(glp_tree *T, int *_next)
- { glp_prob *mip = T->mip;
- int m = mip->m;
- int n = mip->n;
- unsigned char *non_int = T->non_int;
- int j, jj, k, t, next, kase, len, stat, *ind;
- double x, dk, alfa, delta_j, delta_k, delta_z, dz_dn, dz_up,
- dd_dn, dd_up, degrad, *val;
- /* basic solution of LP relaxation must be optimal */
- xassert(glp_get_status(mip) == GLP_OPT);
- /* allocate working arrays */
- ind = xcalloc(1+n, sizeof(int));
- val = xcalloc(1+n, sizeof(double));
- /* nothing has been chosen so far */
- jj = 0, degrad = -1.0;
- /* walk through the list of columns (structural variables) */
- for (j = 1; j <= n; j++)
- { /* if j-th column is not marked as fractional, skip it */
- if (!non_int[j]) continue;
- /* obtain (fractional) value of j-th column in basic solution
- of LP relaxation */
- x = glp_get_col_prim(mip, j);
- /* since the value of j-th column is fractional, the column is
- basic; compute corresponding row of the simplex table */
- len = glp_eval_tab_row(mip, m+j, ind, val);
- /* the following fragment computes a change in the objective
- function: delta Z = new Z - old Z, where old Z is the
- objective value in the current optimal basis, and new Z is
- the objective value in the adjacent basis, for two cases:
- 1) if new upper bound ub' = floor(x[j]) is introduced for
- j-th column (down branch);
- 2) if new lower bound lb' = ceil(x[j]) is introduced for
- j-th column (up branch);
- since in both cases the solution remaining dual feasible
- becomes primal infeasible, one implicit simplex iteration
- is performed to determine the change delta Z;
- it is obvious that new Z, which is never better than old Z,
- is a lower (minimization) or upper (maximization) bound of
- the objective function for down- and up-branches. */
- for (kase = -1; kase <= +1; kase += 2)
- { /* if kase < 0, the new upper bound of x[j] is introduced;
- in this case x[j] should decrease in order to leave the
- basis and go to its new upper bound */
- /* if kase > 0, the new lower bound of x[j] is introduced;
- in this case x[j] should increase in order to leave the
- basis and go to its new lower bound */
- /* apply the dual ratio test in order to determine which
- auxiliary or structural variable should enter the basis
- to keep dual feasibility */
- k = glp_dual_rtest(mip, len, ind, val, kase, 1e-9);
- if (k != 0) k = ind[k];
- /* if no non-basic variable has been chosen, LP relaxation
- of corresponding branch being primal infeasible and dual
- unbounded has no primal feasible solution; in this case
- the change delta Z is formally set to infinity */
- if (k == 0)
- { delta_z =
- (T->mip->dir == GLP_MIN ? +DBL_MAX : -DBL_MAX);
- goto skip;
- }
- /* row of the simplex table that corresponds to non-basic
- variable x[k] choosen by the dual ratio test is:
- x[j] = ... + alfa * x[k] + ...
- where alfa is the influence coefficient (an element of
- the simplex table row) */
- /* determine the coefficient alfa */
- for (t = 1; t <= len; t++) if (ind[t] == k) break;
- xassert(1 <= t && t <= len);
- alfa = val[t];
- /* since in the adjacent basis the variable x[j] becomes
- non-basic, knowing its value in the current basis we can
- determine its change delta x[j] = new x[j] - old x[j] */
- delta_j = (kase < 0 ? floor(x) : ceil(x)) - x;
- /* and knowing the coefficient alfa we can determine the
- corresponding change delta x[k] = new x[k] - old x[k],
- where old x[k] is a value of x[k] in the current basis,
- and new x[k] is a value of x[k] in the adjacent basis */
- delta_k = delta_j / alfa;
- /* Tomlin noticed that if the variable x[k] is of integer
- kind, its change cannot be less (eventually) than one in
- the magnitude */
- if (k > m && glp_get_col_kind(mip, k-m) != GLP_CV)
- { /* x[k] is structural integer variable */
- if (fabs(delta_k - floor(delta_k + 0.5)) > 1e-3)
- { if (delta_k > 0.0)
- delta_k = ceil(delta_k); /* +3.14 -> +4 */
- else
- delta_k = floor(delta_k); /* -3.14 -> -4 */
- }
- }
- /* now determine the status and reduced cost of x[k] in the
- current basis */
- if (k <= m)
- { stat = glp_get_row_stat(mip, k);
- dk = glp_get_row_dual(mip, k);
- }
- else
- { stat = glp_get_col_stat(mip, k-m);
- dk = glp_get_col_dual(mip, k-m);
- }
- /* if the current basis is dual degenerate, some reduced
- costs which are close to zero may have wrong sign due to
- round-off errors, so correct the sign of d[k] */
- switch (T->mip->dir)
- { case GLP_MIN:
- if (stat == GLP_NL && dk < 0.0 ||
- stat == GLP_NU && dk > 0.0 ||
- stat == GLP_NF) dk = 0.0;
- break;
- case GLP_MAX:
- if (stat == GLP_NL && dk > 0.0 ||
- stat == GLP_NU && dk < 0.0 ||
- stat == GLP_NF) dk = 0.0;
- break;
- default:
- xassert(T != T);
- }
- /* now knowing the change of x[k] and its reduced cost d[k]
- we can compute the corresponding change in the objective
- function delta Z = new Z - old Z = d[k] * delta x[k];
- note that due to Tomlin's modification new Z can be even
- worse than in the adjacent basis */
- delta_z = dk * delta_k;
- skip: /* new Z is never better than old Z, therefore the change
- delta Z is always non-negative (in case of minimization)
- or non-positive (in case of maximization) */
- switch (T->mip->dir)
- { case GLP_MIN: xassert(delta_z >= 0.0); break;
- case GLP_MAX: xassert(delta_z <= 0.0); break;
- default: xassert(T != T);
- }
- /* save the change in the objective fnction for down- and
- up-branches, respectively */
- if (kase < 0) dz_dn = delta_z; else dz_up = delta_z;
- }
- /* thus, in down-branch no integer feasible solution can be
- better than Z + dz_dn, and in up-branch no integer feasible
- solution can be better than Z + dz_up, where Z is value of
- the objective function in the current basis */
- /* following the heuristic by Driebeck and Tomlin we choose a
- column (i.e. structural variable) which provides largest
- degradation of the objective function in some of branches;
- besides, we select the branch with smaller degradation to
- be solved next and keep other branch with larger degradation
- in the active list hoping to minimize the number of further
- backtrackings */
- if (degrad < fabs(dz_dn) || degrad < fabs(dz_up))
- { jj = j;
- if (fabs(dz_dn) < fabs(dz_up))
- { /* select down branch to be solved next */
- next = GLP_DN_BRNCH;
- degrad = fabs(dz_up);
- }
- else
- { /* select up branch to be solved next */
- next = GLP_UP_BRNCH;
- degrad = fabs(dz_dn);
- }
- /* save the objective changes for printing */
- dd_dn = dz_dn, dd_up = dz_up;
- /* if down- or up-branch has no feasible solution, we does
- not need to consider other candidates (in principle, the
- corresponding branch could be pruned right now) */
- if (degrad == DBL_MAX) break;
- }
- }
- /* free working arrays */
- xfree(ind);
- xfree(val);
- /* something must be chosen */
- xassert(1 <= jj && jj <= n);
- #if 1 /* 02/XI-2009 */
- if (degrad < 1e-6 * (1.0 + 0.001 * fabs(mip->obj_val)))
- { jj = branch_mostf(T, &next);
- goto done;
- }
- #endif
- if (T->parm->msg_lev >= GLP_MSG_DBG)
- { xprintf("branch_drtom: column %d chosen to branch on\n", jj);
- if (fabs(dd_dn) == DBL_MAX)
- xprintf("branch_drtom: down-branch is infeasible\n");
- else
- xprintf("branch_drtom: down-branch bound is %.9e\n",
- lpx_get_obj_val(mip) + dd_dn);
- if (fabs(dd_up) == DBL_MAX)
- xprintf("branch_drtom: up-branch is infeasible\n");
- else
- xprintf("branch_drtom: up-branch bound is %.9e\n",
- lpx_get_obj_val(mip) + dd_up);
- }
- done: *_next = next;
- return jj;
- }
- /**********************************************************************/
- struct csa
- { /* common storage area */
- int *dn_cnt; /* int dn_cnt[1+n]; */
- /* dn_cnt[j] is the number of subproblems, whose LP relaxations
- have been solved and which are down-branches for variable x[j];
- dn_cnt[j] = 0 means the down pseudocost is uninitialized */
- double *dn_sum; /* double dn_sum[1+n]; */
- /* dn_sum[j] is the sum of per unit degradations of the objective
- over all dn_cnt[j] subproblems */
- int *up_cnt; /* int up_cnt[1+n]; */
- /* up_cnt[j] is the number of subproblems, whose LP relaxations
- have been solved and which are up-branches for variable x[j];
- up_cnt[j] = 0 means the up pseudocost is uninitialized */
- double *up_sum; /* double up_sum[1+n]; */
- /* up_sum[j] is the sum of per unit degradations of the objective
- over all up_cnt[j] subproblems */
- };
- void *ios_pcost_init(glp_tree *tree)
- { /* initialize working data used on pseudocost branching */
- struct csa *csa;
- int n = tree->n, j;
- csa = xmalloc(sizeof(struct csa));
- csa->dn_cnt = xcalloc(1+n, sizeof(int));
- csa->dn_sum = xcalloc(1+n, sizeof(double));
- csa->up_cnt = xcalloc(1+n, sizeof(int));
- csa->up_sum = xcalloc(1+n, sizeof(double));
- for (j = 1; j <= n; j++)
- { csa->dn_cnt[j] = csa->up_cnt[j] = 0;
- csa->dn_sum[j] = csa->up_sum[j] = 0.0;
- }
- return csa;
- }
- static double eval_degrad(glp_prob *P, int j, double bnd)
- { /* compute degradation of the objective on fixing x[j] at given
- value with a limited number of dual simplex iterations */
- /* this routine fixes column x[j] at specified value bnd,
- solves resulting LP, and returns a lower bound to degradation
- of the objective, degrad >= 0 */
- glp_prob *lp;
- glp_smcp parm;
- int ret;
- double degrad;
- /* the current basis must be optimal */
- xassert(glp_get_status(P) == GLP_OPT);
- /* create a copy of P */
- lp = glp_create_prob();
- glp_copy_prob(lp, P, 0);
- /* fix column x[j] at specified value */
- glp_set_col_bnds(lp, j, GLP_FX, bnd, bnd);
- /* try to solve resulting LP */
- glp_init_smcp(&parm);
- parm.msg_lev = GLP_MSG_OFF;
- parm.meth = GLP_DUAL;
- parm.it_lim = 30;
- parm.out_dly = 1000;
- parm.meth = GLP_DUAL;
- ret = glp_simplex(lp, &parm);
- if (ret == 0 || ret == GLP_EITLIM)
- { if (glp_get_prim_stat(lp) == GLP_NOFEAS)
- { /* resulting LP has no primal feasible solution */
- degrad = DBL_MAX;
- }
- else if (glp_get_dual_stat(lp) == GLP_FEAS)
- { /* resulting basis is optimal or at least dual feasible,
- so we have the correct lower bound to degradation */
- if (P->dir == GLP_MIN)
- degrad = lp->obj_val - P->obj_val;
- else if (P->dir == GLP_MAX)
- degrad = P->obj_val - lp->obj_val;
- else
- xassert(P != P);
- /* degradation cannot be negative by definition */
- /* note that the lower bound to degradation may be close
- to zero even if its exact value is zero due to round-off
- errors on computing the objective value */
- if (degrad < 1e-6 * (1.0 + 0.001 * fabs(P->obj_val)))
- degrad = 0.0;
- }
- else
- { /* the final basis reported by the simplex solver is dual
- infeasible, so we cannot determine a non-trivial lower
- bound to degradation */
- degrad = 0.0;
- }
- }
- else
- { /* the simplex solver failed */
- degrad = 0.0;
- }
- /* delete the copy of P */
- glp_delete_prob(lp);
- return degrad;
- }
- void ios_pcost_update(glp_tree *tree)
- { /* update history information for pseudocost branching */
- /* this routine is called every time when LP relaxation of the
- current subproblem has been solved to optimality with all lazy
- and cutting plane constraints included */
- int j;
- double dx, dz, psi;
- struct csa *csa = tree->pcost;
- xassert(csa != NULL);
- xassert(tree->curr != NULL);
- /* if the current subproblem is the root, skip updating */
- if (tree->curr->up == NULL) goto skip;
- /* determine branching variable x[j], which was used in the
- parent subproblem to create the current subproblem */
- j = tree->curr->up->br_var;
- xassert(1 <= j && j <= tree->n);
- /* determine the change dx[j] = new x[j] - old x[j],
- where new x[j] is a value of x[j] in optimal solution to LP
- relaxation of the current subproblem, old x[j] is a value of
- x[j] in optimal solution to LP relaxation of the parent
- subproblem */
- dx = tree->mip->col[j]->prim - tree->curr->up->br_val;
- xassert(dx != 0.0);
- /* determine corresponding change dz = new dz - old dz in the
- objective function value */
- dz = tree->mip->obj_val - tree->curr->up->lp_obj;
- /* determine per unit degradation of the objective function */
- psi = fabs(dz / dx);
- /* update history information */
- if (dx < 0.0)
- { /* the current subproblem is down-branch */
- csa->dn_cnt[j]++;
- csa->dn_sum[j] += psi;
- }
- else /* dx > 0.0 */
- { /* the current subproblem is up-branch */
- csa->up_cnt[j]++;
- csa->up_sum[j] += psi;
- }
- skip: return;
- }
- void ios_pcost_free(glp_tree *tree)
- { /* free working area used on pseudocost branching */
- struct csa *csa = tree->pcost;
- xassert(csa != NULL);
- xfree(csa->dn_cnt);
- xfree(csa->dn_sum);
- xfree(csa->up_cnt);
- xfree(csa->up_sum);
- xfree(csa);
- tree->pcost = NULL;
- return;
- }
- static double eval_psi(glp_tree *T, int j, int brnch)
- { /* compute estimation of pseudocost of variable x[j] for down-
- or up-branch */
- struct csa *csa = T->pcost;
- double beta, degrad, psi;
- xassert(csa != NULL);
- xassert(1 <= j && j <= T->n);
- if (brnch == GLP_DN_BRNCH)
- { /* down-branch */
- if (csa->dn_cnt[j] == 0)
- { /* initialize down pseudocost */
- beta = T->mip->col[j]->prim;
- degrad = eval_degrad(T->mip, j, floor(beta));
- if (degrad == DBL_MAX)
- { psi = DBL_MAX;
- goto done;
- }
- csa->dn_cnt[j] = 1;
- csa->dn_sum[j] = degrad / (beta - floor(beta));
- }
- psi = csa->dn_sum[j] / (double)csa->dn_cnt[j];
- }
- else if (brnch == GLP_UP_BRNCH)
- { /* up-branch */
- if (csa->up_cnt[j] == 0)
- { /* initialize up pseudocost */
- beta = T->mip->col[j]->prim;
- degrad = eval_degrad(T->mip, j, ceil(beta));
- if (degrad == DBL_MAX)
- { psi = DBL_MAX;
- goto done;
- }
- csa->up_cnt[j] = 1;
- csa->up_sum[j] = degrad / (ceil(beta) - beta);
- }
- psi = csa->up_sum[j] / (double)csa->up_cnt[j];
- }
- else
- xassert(brnch != brnch);
- done: return psi;
- }
- static void progress(glp_tree *T)
- { /* display progress of pseudocost initialization */
- struct csa *csa = T->pcost;
- int j, nv = 0, ni = 0;
- for (j = 1; j <= T->n; j++)
- { if (glp_ios_can_branch(T, j))
- { nv++;
- if (csa->dn_cnt[j] > 0 && csa->up_cnt[j] > 0) ni++;
- }
- }
- xprintf("Pseudocosts initialized for %d of %d variables\n",
- ni, nv);
- return;
- }
- int ios_pcost_branch(glp_tree *T, int *_next)
- { /* choose branching variable with pseudocost branching */
- glp_long t = xtime();
- int j, jjj, sel;
- double beta, psi, d1, d2, d, dmax;
- /* initialize the working arrays */
- if (T->pcost == NULL)
- T->pcost = ios_pcost_init(T);
- /* nothing has been chosen so far */
- jjj = 0, dmax = -1.0;
- /* go through the list of branching candidates */
- for (j = 1; j <= T->n; j++)
- { if (!glp_ios_can_branch(T, j)) continue;
- /* determine primal value of x[j] in optimal solution to LP
- relaxation of the current subproblem */
- beta = T->mip->col[j]->prim;
- /* estimate pseudocost of x[j] for down-branch */
- psi = eval_psi(T, j, GLP_DN_BRNCH);
- if (psi == DBL_MAX)
- { /* down-branch has no primal feasible solution */
- jjj = j, sel = GLP_DN_BRNCH;
- goto done;
- }
- /* estimate degradation of the objective for down-branch */
- d1 = psi * (beta - floor(beta));
- /* estimate pseudocost of x[j] for up-branch */
- psi = eval_psi(T, j, GLP_UP_BRNCH);
- if (psi == DBL_MAX)
- { /* up-branch has no primal feasible solution */
- jjj = j, sel = GLP_UP_BRNCH;
- goto done;
- }
- /* estimate degradation of the objective for up-branch */
- d2 = psi * (ceil(beta) - beta);
- /* determine d = max(d1, d2) */
- d = (d1 > d2 ? d1 : d2);
- /* choose x[j] which provides maximal estimated degradation of
- the objective either in down- or up-branch */
- if (dmax < d)
- { dmax = d;
- jjj = j;
- /* continue the search from a subproblem, where degradation
- is less than in other one */
- sel = (d1 <= d2 ? GLP_DN_BRNCH : GLP_UP_BRNCH);
- }
- /* display progress of pseudocost initialization */
- if (T->parm->msg_lev >= GLP_ON)
- { if (xdifftime(xtime(), t) >= 10.0)
- { progress(T);
- t = xtime();
- }
- }
- }
- if (dmax == 0.0)
- { /* no degradation is indicated; choose a variable having most
- fractional value */
- jjj = branch_mostf(T, &sel);
- }
- done: *_next = sel;
- return jjj;
- }
- /* eof */
|