rev |
line source |
alpar@9
|
1 /* glpios09.c (branching heuristics) */
|
alpar@9
|
2
|
alpar@9
|
3 /***********************************************************************
|
alpar@9
|
4 * This code is part of GLPK (GNU Linear Programming Kit).
|
alpar@9
|
5 *
|
alpar@9
|
6 * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
|
alpar@9
|
7 * 2009, 2010, 2011 Andrew Makhorin, Department for Applied Informatics,
|
alpar@9
|
8 * Moscow Aviation Institute, Moscow, Russia. All rights reserved.
|
alpar@9
|
9 * E-mail: <mao@gnu.org>.
|
alpar@9
|
10 *
|
alpar@9
|
11 * GLPK is free software: you can redistribute it and/or modify it
|
alpar@9
|
12 * under the terms of the GNU General Public License as published by
|
alpar@9
|
13 * the Free Software Foundation, either version 3 of the License, or
|
alpar@9
|
14 * (at your option) any later version.
|
alpar@9
|
15 *
|
alpar@9
|
16 * GLPK is distributed in the hope that it will be useful, but WITHOUT
|
alpar@9
|
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
alpar@9
|
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
alpar@9
|
19 * License for more details.
|
alpar@9
|
20 *
|
alpar@9
|
21 * You should have received a copy of the GNU General Public License
|
alpar@9
|
22 * along with GLPK. If not, see <http://www.gnu.org/licenses/>.
|
alpar@9
|
23 ***********************************************************************/
|
alpar@9
|
24
|
alpar@9
|
25 #include "glpios.h"
|
alpar@9
|
26
|
alpar@9
|
27 /***********************************************************************
|
alpar@9
|
28 * NAME
|
alpar@9
|
29 *
|
alpar@9
|
30 * ios_choose_var - select variable to branch on
|
alpar@9
|
31 *
|
alpar@9
|
32 * SYNOPSIS
|
alpar@9
|
33 *
|
alpar@9
|
34 * #include "glpios.h"
|
alpar@9
|
35 * int ios_choose_var(glp_tree *T, int *next);
|
alpar@9
|
36 *
|
alpar@9
|
37 * The routine ios_choose_var chooses a variable from the candidate
|
alpar@9
|
38 * list to branch on. Additionally the routine provides a flag stored
|
alpar@9
|
39 * in the location next to suggests which of the child subproblems
|
alpar@9
|
40 * should be solved next.
|
alpar@9
|
41 *
|
alpar@9
|
42 * RETURNS
|
alpar@9
|
43 *
|
alpar@9
|
44 * The routine ios_choose_var returns the ordinal number of the column
|
alpar@9
|
45 * choosen. */
|
alpar@9
|
46
|
alpar@9
|
47 static int branch_first(glp_tree *T, int *next);
|
alpar@9
|
48 static int branch_last(glp_tree *T, int *next);
|
alpar@9
|
49 static int branch_mostf(glp_tree *T, int *next);
|
alpar@9
|
50 static int branch_drtom(glp_tree *T, int *next);
|
alpar@9
|
51
|
alpar@9
|
52 int ios_choose_var(glp_tree *T, int *next)
|
alpar@9
|
53 { int j;
|
alpar@9
|
54 if (T->parm->br_tech == GLP_BR_FFV)
|
alpar@9
|
55 { /* branch on first fractional variable */
|
alpar@9
|
56 j = branch_first(T, next);
|
alpar@9
|
57 }
|
alpar@9
|
58 else if (T->parm->br_tech == GLP_BR_LFV)
|
alpar@9
|
59 { /* branch on last fractional variable */
|
alpar@9
|
60 j = branch_last(T, next);
|
alpar@9
|
61 }
|
alpar@9
|
62 else if (T->parm->br_tech == GLP_BR_MFV)
|
alpar@9
|
63 { /* branch on most fractional variable */
|
alpar@9
|
64 j = branch_mostf(T, next);
|
alpar@9
|
65 }
|
alpar@9
|
66 else if (T->parm->br_tech == GLP_BR_DTH)
|
alpar@9
|
67 { /* branch using the heuristic by Dreebeck and Tomlin */
|
alpar@9
|
68 j = branch_drtom(T, next);
|
alpar@9
|
69 }
|
alpar@9
|
70 else if (T->parm->br_tech == GLP_BR_PCH)
|
alpar@9
|
71 { /* hybrid pseudocost heuristic */
|
alpar@9
|
72 j = ios_pcost_branch(T, next);
|
alpar@9
|
73 }
|
alpar@9
|
74 else
|
alpar@9
|
75 xassert(T != T);
|
alpar@9
|
76 return j;
|
alpar@9
|
77 }
|
alpar@9
|
78
|
alpar@9
|
79 /***********************************************************************
|
alpar@9
|
80 * branch_first - choose first branching variable
|
alpar@9
|
81 *
|
alpar@9
|
82 * This routine looks up the list of structural variables and chooses
|
alpar@9
|
83 * the first one, which is of integer kind and has fractional value in
|
alpar@9
|
84 * optimal solution to the current LP relaxation.
|
alpar@9
|
85 *
|
alpar@9
|
86 * This routine also selects the branch to be solved next where integer
|
alpar@9
|
87 * infeasibility of the chosen variable is less than in other one. */
|
alpar@9
|
88
|
alpar@9
|
89 static int branch_first(glp_tree *T, int *_next)
|
alpar@9
|
90 { int j, next;
|
alpar@9
|
91 double beta;
|
alpar@9
|
92 /* choose the column to branch on */
|
alpar@9
|
93 for (j = 1; j <= T->n; j++)
|
alpar@9
|
94 if (T->non_int[j]) break;
|
alpar@9
|
95 xassert(1 <= j && j <= T->n);
|
alpar@9
|
96 /* select the branch to be solved next */
|
alpar@9
|
97 beta = glp_get_col_prim(T->mip, j);
|
alpar@9
|
98 if (beta - floor(beta) < ceil(beta) - beta)
|
alpar@9
|
99 next = GLP_DN_BRNCH;
|
alpar@9
|
100 else
|
alpar@9
|
101 next = GLP_UP_BRNCH;
|
alpar@9
|
102 *_next = next;
|
alpar@9
|
103 return j;
|
alpar@9
|
104 }
|
alpar@9
|
105
|
alpar@9
|
106 /***********************************************************************
|
alpar@9
|
107 * branch_last - choose last branching variable
|
alpar@9
|
108 *
|
alpar@9
|
109 * This routine looks up the list of structural variables and chooses
|
alpar@9
|
110 * the last one, which is of integer kind and has fractional value in
|
alpar@9
|
111 * optimal solution to the current LP relaxation.
|
alpar@9
|
112 *
|
alpar@9
|
113 * This routine also selects the branch to be solved next where integer
|
alpar@9
|
114 * infeasibility of the chosen variable is less than in other one. */
|
alpar@9
|
115
|
alpar@9
|
116 static int branch_last(glp_tree *T, int *_next)
|
alpar@9
|
117 { int j, next;
|
alpar@9
|
118 double beta;
|
alpar@9
|
119 /* choose the column to branch on */
|
alpar@9
|
120 for (j = T->n; j >= 1; j--)
|
alpar@9
|
121 if (T->non_int[j]) break;
|
alpar@9
|
122 xassert(1 <= j && j <= T->n);
|
alpar@9
|
123 /* select the branch to be solved next */
|
alpar@9
|
124 beta = glp_get_col_prim(T->mip, j);
|
alpar@9
|
125 if (beta - floor(beta) < ceil(beta) - beta)
|
alpar@9
|
126 next = GLP_DN_BRNCH;
|
alpar@9
|
127 else
|
alpar@9
|
128 next = GLP_UP_BRNCH;
|
alpar@9
|
129 *_next = next;
|
alpar@9
|
130 return j;
|
alpar@9
|
131 }
|
alpar@9
|
132
|
alpar@9
|
133 /***********************************************************************
|
alpar@9
|
134 * branch_mostf - choose most fractional branching variable
|
alpar@9
|
135 *
|
alpar@9
|
136 * This routine looks up the list of structural variables and chooses
|
alpar@9
|
137 * that one, which is of integer kind and has most fractional value in
|
alpar@9
|
138 * optimal solution to the current LP relaxation.
|
alpar@9
|
139 *
|
alpar@9
|
140 * This routine also selects the branch to be solved next where integer
|
alpar@9
|
141 * infeasibility of the chosen variable is less than in other one.
|
alpar@9
|
142 *
|
alpar@9
|
143 * (Alexander Martin notices that "...most infeasible is as good as
|
alpar@9
|
144 * random...".) */
|
alpar@9
|
145
|
alpar@9
|
146 static int branch_mostf(glp_tree *T, int *_next)
|
alpar@9
|
147 { int j, jj, next;
|
alpar@9
|
148 double beta, most, temp;
|
alpar@9
|
149 /* choose the column to branch on */
|
alpar@9
|
150 jj = 0, most = DBL_MAX;
|
alpar@9
|
151 for (j = 1; j <= T->n; j++)
|
alpar@9
|
152 { if (T->non_int[j])
|
alpar@9
|
153 { beta = glp_get_col_prim(T->mip, j);
|
alpar@9
|
154 temp = floor(beta) + 0.5;
|
alpar@9
|
155 if (most > fabs(beta - temp))
|
alpar@9
|
156 { jj = j, most = fabs(beta - temp);
|
alpar@9
|
157 if (beta < temp)
|
alpar@9
|
158 next = GLP_DN_BRNCH;
|
alpar@9
|
159 else
|
alpar@9
|
160 next = GLP_UP_BRNCH;
|
alpar@9
|
161 }
|
alpar@9
|
162 }
|
alpar@9
|
163 }
|
alpar@9
|
164 *_next = next;
|
alpar@9
|
165 return jj;
|
alpar@9
|
166 }
|
alpar@9
|
167
|
alpar@9
|
168 /***********************************************************************
|
alpar@9
|
169 * branch_drtom - choose branching var using Driebeck-Tomlin heuristic
|
alpar@9
|
170 *
|
alpar@9
|
171 * This routine chooses a structural variable, which is required to be
|
alpar@9
|
172 * integral and has fractional value in optimal solution of the current
|
alpar@9
|
173 * LP relaxation, using a heuristic proposed by Driebeck and Tomlin.
|
alpar@9
|
174 *
|
alpar@9
|
175 * The routine also selects the branch to be solved next, again due to
|
alpar@9
|
176 * Driebeck and Tomlin.
|
alpar@9
|
177 *
|
alpar@9
|
178 * This routine is based on the heuristic proposed in:
|
alpar@9
|
179 *
|
alpar@9
|
180 * Driebeck N.J. An algorithm for the solution of mixed-integer
|
alpar@9
|
181 * programming problems, Management Science, 12: 576-87 (1966);
|
alpar@9
|
182 *
|
alpar@9
|
183 * and improved in:
|
alpar@9
|
184 *
|
alpar@9
|
185 * Tomlin J.A. Branch and bound methods for integer and non-convex
|
alpar@9
|
186 * programming, in J.Abadie (ed.), Integer and Nonlinear Programming,
|
alpar@9
|
187 * North-Holland, Amsterdam, pp. 437-50 (1970).
|
alpar@9
|
188 *
|
alpar@9
|
189 * Must note that this heuristic is time-expensive, because computing
|
alpar@9
|
190 * one-step degradation (see the routine below) requires one BTRAN for
|
alpar@9
|
191 * each fractional-valued structural variable. */
|
alpar@9
|
192
|
alpar@9
|
193 static int branch_drtom(glp_tree *T, int *_next)
|
alpar@9
|
194 { glp_prob *mip = T->mip;
|
alpar@9
|
195 int m = mip->m;
|
alpar@9
|
196 int n = mip->n;
|
alpar@9
|
197 char *non_int = T->non_int;
|
alpar@9
|
198 int j, jj, k, t, next, kase, len, stat, *ind;
|
alpar@9
|
199 double x, dk, alfa, delta_j, delta_k, delta_z, dz_dn, dz_up,
|
alpar@9
|
200 dd_dn, dd_up, degrad, *val;
|
alpar@9
|
201 /* basic solution of LP relaxation must be optimal */
|
alpar@9
|
202 xassert(glp_get_status(mip) == GLP_OPT);
|
alpar@9
|
203 /* allocate working arrays */
|
alpar@9
|
204 ind = xcalloc(1+n, sizeof(int));
|
alpar@9
|
205 val = xcalloc(1+n, sizeof(double));
|
alpar@9
|
206 /* nothing has been chosen so far */
|
alpar@9
|
207 jj = 0, degrad = -1.0;
|
alpar@9
|
208 /* walk through the list of columns (structural variables) */
|
alpar@9
|
209 for (j = 1; j <= n; j++)
|
alpar@9
|
210 { /* if j-th column is not marked as fractional, skip it */
|
alpar@9
|
211 if (!non_int[j]) continue;
|
alpar@9
|
212 /* obtain (fractional) value of j-th column in basic solution
|
alpar@9
|
213 of LP relaxation */
|
alpar@9
|
214 x = glp_get_col_prim(mip, j);
|
alpar@9
|
215 /* since the value of j-th column is fractional, the column is
|
alpar@9
|
216 basic; compute corresponding row of the simplex table */
|
alpar@9
|
217 len = glp_eval_tab_row(mip, m+j, ind, val);
|
alpar@9
|
218 /* the following fragment computes a change in the objective
|
alpar@9
|
219 function: delta Z = new Z - old Z, where old Z is the
|
alpar@9
|
220 objective value in the current optimal basis, and new Z is
|
alpar@9
|
221 the objective value in the adjacent basis, for two cases:
|
alpar@9
|
222 1) if new upper bound ub' = floor(x[j]) is introduced for
|
alpar@9
|
223 j-th column (down branch);
|
alpar@9
|
224 2) if new lower bound lb' = ceil(x[j]) is introduced for
|
alpar@9
|
225 j-th column (up branch);
|
alpar@9
|
226 since in both cases the solution remaining dual feasible
|
alpar@9
|
227 becomes primal infeasible, one implicit simplex iteration
|
alpar@9
|
228 is performed to determine the change delta Z;
|
alpar@9
|
229 it is obvious that new Z, which is never better than old Z,
|
alpar@9
|
230 is a lower (minimization) or upper (maximization) bound of
|
alpar@9
|
231 the objective function for down- and up-branches. */
|
alpar@9
|
232 for (kase = -1; kase <= +1; kase += 2)
|
alpar@9
|
233 { /* if kase < 0, the new upper bound of x[j] is introduced;
|
alpar@9
|
234 in this case x[j] should decrease in order to leave the
|
alpar@9
|
235 basis and go to its new upper bound */
|
alpar@9
|
236 /* if kase > 0, the new lower bound of x[j] is introduced;
|
alpar@9
|
237 in this case x[j] should increase in order to leave the
|
alpar@9
|
238 basis and go to its new lower bound */
|
alpar@9
|
239 /* apply the dual ratio test in order to determine which
|
alpar@9
|
240 auxiliary or structural variable should enter the basis
|
alpar@9
|
241 to keep dual feasibility */
|
alpar@9
|
242 k = glp_dual_rtest(mip, len, ind, val, kase, 1e-9);
|
alpar@9
|
243 if (k != 0) k = ind[k];
|
alpar@9
|
244 /* if no non-basic variable has been chosen, LP relaxation
|
alpar@9
|
245 of corresponding branch being primal infeasible and dual
|
alpar@9
|
246 unbounded has no primal feasible solution; in this case
|
alpar@9
|
247 the change delta Z is formally set to infinity */
|
alpar@9
|
248 if (k == 0)
|
alpar@9
|
249 { delta_z =
|
alpar@9
|
250 (T->mip->dir == GLP_MIN ? +DBL_MAX : -DBL_MAX);
|
alpar@9
|
251 goto skip;
|
alpar@9
|
252 }
|
alpar@9
|
253 /* row of the simplex table that corresponds to non-basic
|
alpar@9
|
254 variable x[k] choosen by the dual ratio test is:
|
alpar@9
|
255 x[j] = ... + alfa * x[k] + ...
|
alpar@9
|
256 where alfa is the influence coefficient (an element of
|
alpar@9
|
257 the simplex table row) */
|
alpar@9
|
258 /* determine the coefficient alfa */
|
alpar@9
|
259 for (t = 1; t <= len; t++) if (ind[t] == k) break;
|
alpar@9
|
260 xassert(1 <= t && t <= len);
|
alpar@9
|
261 alfa = val[t];
|
alpar@9
|
262 /* since in the adjacent basis the variable x[j] becomes
|
alpar@9
|
263 non-basic, knowing its value in the current basis we can
|
alpar@9
|
264 determine its change delta x[j] = new x[j] - old x[j] */
|
alpar@9
|
265 delta_j = (kase < 0 ? floor(x) : ceil(x)) - x;
|
alpar@9
|
266 /* and knowing the coefficient alfa we can determine the
|
alpar@9
|
267 corresponding change delta x[k] = new x[k] - old x[k],
|
alpar@9
|
268 where old x[k] is a value of x[k] in the current basis,
|
alpar@9
|
269 and new x[k] is a value of x[k] in the adjacent basis */
|
alpar@9
|
270 delta_k = delta_j / alfa;
|
alpar@9
|
271 /* Tomlin noticed that if the variable x[k] is of integer
|
alpar@9
|
272 kind, its change cannot be less (eventually) than one in
|
alpar@9
|
273 the magnitude */
|
alpar@9
|
274 if (k > m && glp_get_col_kind(mip, k-m) != GLP_CV)
|
alpar@9
|
275 { /* x[k] is structural integer variable */
|
alpar@9
|
276 if (fabs(delta_k - floor(delta_k + 0.5)) > 1e-3)
|
alpar@9
|
277 { if (delta_k > 0.0)
|
alpar@9
|
278 delta_k = ceil(delta_k); /* +3.14 -> +4 */
|
alpar@9
|
279 else
|
alpar@9
|
280 delta_k = floor(delta_k); /* -3.14 -> -4 */
|
alpar@9
|
281 }
|
alpar@9
|
282 }
|
alpar@9
|
283 /* now determine the status and reduced cost of x[k] in the
|
alpar@9
|
284 current basis */
|
alpar@9
|
285 if (k <= m)
|
alpar@9
|
286 { stat = glp_get_row_stat(mip, k);
|
alpar@9
|
287 dk = glp_get_row_dual(mip, k);
|
alpar@9
|
288 }
|
alpar@9
|
289 else
|
alpar@9
|
290 { stat = glp_get_col_stat(mip, k-m);
|
alpar@9
|
291 dk = glp_get_col_dual(mip, k-m);
|
alpar@9
|
292 }
|
alpar@9
|
293 /* if the current basis is dual degenerate, some reduced
|
alpar@9
|
294 costs which are close to zero may have wrong sign due to
|
alpar@9
|
295 round-off errors, so correct the sign of d[k] */
|
alpar@9
|
296 switch (T->mip->dir)
|
alpar@9
|
297 { case GLP_MIN:
|
alpar@9
|
298 if (stat == GLP_NL && dk < 0.0 ||
|
alpar@9
|
299 stat == GLP_NU && dk > 0.0 ||
|
alpar@9
|
300 stat == GLP_NF) dk = 0.0;
|
alpar@9
|
301 break;
|
alpar@9
|
302 case GLP_MAX:
|
alpar@9
|
303 if (stat == GLP_NL && dk > 0.0 ||
|
alpar@9
|
304 stat == GLP_NU && dk < 0.0 ||
|
alpar@9
|
305 stat == GLP_NF) dk = 0.0;
|
alpar@9
|
306 break;
|
alpar@9
|
307 default:
|
alpar@9
|
308 xassert(T != T);
|
alpar@9
|
309 }
|
alpar@9
|
310 /* now knowing the change of x[k] and its reduced cost d[k]
|
alpar@9
|
311 we can compute the corresponding change in the objective
|
alpar@9
|
312 function delta Z = new Z - old Z = d[k] * delta x[k];
|
alpar@9
|
313 note that due to Tomlin's modification new Z can be even
|
alpar@9
|
314 worse than in the adjacent basis */
|
alpar@9
|
315 delta_z = dk * delta_k;
|
alpar@9
|
316 skip: /* new Z is never better than old Z, therefore the change
|
alpar@9
|
317 delta Z is always non-negative (in case of minimization)
|
alpar@9
|
318 or non-positive (in case of maximization) */
|
alpar@9
|
319 switch (T->mip->dir)
|
alpar@9
|
320 { case GLP_MIN: xassert(delta_z >= 0.0); break;
|
alpar@9
|
321 case GLP_MAX: xassert(delta_z <= 0.0); break;
|
alpar@9
|
322 default: xassert(T != T);
|
alpar@9
|
323 }
|
alpar@9
|
324 /* save the change in the objective fnction for down- and
|
alpar@9
|
325 up-branches, respectively */
|
alpar@9
|
326 if (kase < 0) dz_dn = delta_z; else dz_up = delta_z;
|
alpar@9
|
327 }
|
alpar@9
|
328 /* thus, in down-branch no integer feasible solution can be
|
alpar@9
|
329 better than Z + dz_dn, and in up-branch no integer feasible
|
alpar@9
|
330 solution can be better than Z + dz_up, where Z is value of
|
alpar@9
|
331 the objective function in the current basis */
|
alpar@9
|
332 /* following the heuristic by Driebeck and Tomlin we choose a
|
alpar@9
|
333 column (i.e. structural variable) which provides largest
|
alpar@9
|
334 degradation of the objective function in some of branches;
|
alpar@9
|
335 besides, we select the branch with smaller degradation to
|
alpar@9
|
336 be solved next and keep other branch with larger degradation
|
alpar@9
|
337 in the active list hoping to minimize the number of further
|
alpar@9
|
338 backtrackings */
|
alpar@9
|
339 if (degrad < fabs(dz_dn) || degrad < fabs(dz_up))
|
alpar@9
|
340 { jj = j;
|
alpar@9
|
341 if (fabs(dz_dn) < fabs(dz_up))
|
alpar@9
|
342 { /* select down branch to be solved next */
|
alpar@9
|
343 next = GLP_DN_BRNCH;
|
alpar@9
|
344 degrad = fabs(dz_up);
|
alpar@9
|
345 }
|
alpar@9
|
346 else
|
alpar@9
|
347 { /* select up branch to be solved next */
|
alpar@9
|
348 next = GLP_UP_BRNCH;
|
alpar@9
|
349 degrad = fabs(dz_dn);
|
alpar@9
|
350 }
|
alpar@9
|
351 /* save the objective changes for printing */
|
alpar@9
|
352 dd_dn = dz_dn, dd_up = dz_up;
|
alpar@9
|
353 /* if down- or up-branch has no feasible solution, we does
|
alpar@9
|
354 not need to consider other candidates (in principle, the
|
alpar@9
|
355 corresponding branch could be pruned right now) */
|
alpar@9
|
356 if (degrad == DBL_MAX) break;
|
alpar@9
|
357 }
|
alpar@9
|
358 }
|
alpar@9
|
359 /* free working arrays */
|
alpar@9
|
360 xfree(ind);
|
alpar@9
|
361 xfree(val);
|
alpar@9
|
362 /* something must be chosen */
|
alpar@9
|
363 xassert(1 <= jj && jj <= n);
|
alpar@9
|
364 #if 1 /* 02/XI-2009 */
|
alpar@9
|
365 if (degrad < 1e-6 * (1.0 + 0.001 * fabs(mip->obj_val)))
|
alpar@9
|
366 { jj = branch_mostf(T, &next);
|
alpar@9
|
367 goto done;
|
alpar@9
|
368 }
|
alpar@9
|
369 #endif
|
alpar@9
|
370 if (T->parm->msg_lev >= GLP_MSG_DBG)
|
alpar@9
|
371 { xprintf("branch_drtom: column %d chosen to branch on\n", jj);
|
alpar@9
|
372 if (fabs(dd_dn) == DBL_MAX)
|
alpar@9
|
373 xprintf("branch_drtom: down-branch is infeasible\n");
|
alpar@9
|
374 else
|
alpar@9
|
375 xprintf("branch_drtom: down-branch bound is %.9e\n",
|
alpar@9
|
376 lpx_get_obj_val(mip) + dd_dn);
|
alpar@9
|
377 if (fabs(dd_up) == DBL_MAX)
|
alpar@9
|
378 xprintf("branch_drtom: up-branch is infeasible\n");
|
alpar@9
|
379 else
|
alpar@9
|
380 xprintf("branch_drtom: up-branch bound is %.9e\n",
|
alpar@9
|
381 lpx_get_obj_val(mip) + dd_up);
|
alpar@9
|
382 }
|
alpar@9
|
383 done: *_next = next;
|
alpar@9
|
384 return jj;
|
alpar@9
|
385 }
|
alpar@9
|
386
|
alpar@9
|
387 /**********************************************************************/
|
alpar@9
|
388
|
alpar@9
|
389 struct csa
|
alpar@9
|
390 { /* common storage area */
|
alpar@9
|
391 int *dn_cnt; /* int dn_cnt[1+n]; */
|
alpar@9
|
392 /* dn_cnt[j] is the number of subproblems, whose LP relaxations
|
alpar@9
|
393 have been solved and which are down-branches for variable x[j];
|
alpar@9
|
394 dn_cnt[j] = 0 means the down pseudocost is uninitialized */
|
alpar@9
|
395 double *dn_sum; /* double dn_sum[1+n]; */
|
alpar@9
|
396 /* dn_sum[j] is the sum of per unit degradations of the objective
|
alpar@9
|
397 over all dn_cnt[j] subproblems */
|
alpar@9
|
398 int *up_cnt; /* int up_cnt[1+n]; */
|
alpar@9
|
399 /* up_cnt[j] is the number of subproblems, whose LP relaxations
|
alpar@9
|
400 have been solved and which are up-branches for variable x[j];
|
alpar@9
|
401 up_cnt[j] = 0 means the up pseudocost is uninitialized */
|
alpar@9
|
402 double *up_sum; /* double up_sum[1+n]; */
|
alpar@9
|
403 /* up_sum[j] is the sum of per unit degradations of the objective
|
alpar@9
|
404 over all up_cnt[j] subproblems */
|
alpar@9
|
405 };
|
alpar@9
|
406
|
alpar@9
|
407 void *ios_pcost_init(glp_tree *tree)
|
alpar@9
|
408 { /* initialize working data used on pseudocost branching */
|
alpar@9
|
409 struct csa *csa;
|
alpar@9
|
410 int n = tree->n, j;
|
alpar@9
|
411 csa = xmalloc(sizeof(struct csa));
|
alpar@9
|
412 csa->dn_cnt = xcalloc(1+n, sizeof(int));
|
alpar@9
|
413 csa->dn_sum = xcalloc(1+n, sizeof(double));
|
alpar@9
|
414 csa->up_cnt = xcalloc(1+n, sizeof(int));
|
alpar@9
|
415 csa->up_sum = xcalloc(1+n, sizeof(double));
|
alpar@9
|
416 for (j = 1; j <= n; j++)
|
alpar@9
|
417 { csa->dn_cnt[j] = csa->up_cnt[j] = 0;
|
alpar@9
|
418 csa->dn_sum[j] = csa->up_sum[j] = 0.0;
|
alpar@9
|
419 }
|
alpar@9
|
420 return csa;
|
alpar@9
|
421 }
|
alpar@9
|
422
|
alpar@9
|
423 static double eval_degrad(glp_prob *P, int j, double bnd)
|
alpar@9
|
424 { /* compute degradation of the objective on fixing x[j] at given
|
alpar@9
|
425 value with a limited number of dual simplex iterations */
|
alpar@9
|
426 /* this routine fixes column x[j] at specified value bnd,
|
alpar@9
|
427 solves resulting LP, and returns a lower bound to degradation
|
alpar@9
|
428 of the objective, degrad >= 0 */
|
alpar@9
|
429 glp_prob *lp;
|
alpar@9
|
430 glp_smcp parm;
|
alpar@9
|
431 int ret;
|
alpar@9
|
432 double degrad;
|
alpar@9
|
433 /* the current basis must be optimal */
|
alpar@9
|
434 xassert(glp_get_status(P) == GLP_OPT);
|
alpar@9
|
435 /* create a copy of P */
|
alpar@9
|
436 lp = glp_create_prob();
|
alpar@9
|
437 glp_copy_prob(lp, P, 0);
|
alpar@9
|
438 /* fix column x[j] at specified value */
|
alpar@9
|
439 glp_set_col_bnds(lp, j, GLP_FX, bnd, bnd);
|
alpar@9
|
440 /* try to solve resulting LP */
|
alpar@9
|
441 glp_init_smcp(&parm);
|
alpar@9
|
442 parm.msg_lev = GLP_MSG_OFF;
|
alpar@9
|
443 parm.meth = GLP_DUAL;
|
alpar@9
|
444 parm.it_lim = 30;
|
alpar@9
|
445 parm.out_dly = 1000;
|
alpar@9
|
446 parm.meth = GLP_DUAL;
|
alpar@9
|
447 ret = glp_simplex(lp, &parm);
|
alpar@9
|
448 if (ret == 0 || ret == GLP_EITLIM)
|
alpar@9
|
449 { if (glp_get_prim_stat(lp) == GLP_NOFEAS)
|
alpar@9
|
450 { /* resulting LP has no primal feasible solution */
|
alpar@9
|
451 degrad = DBL_MAX;
|
alpar@9
|
452 }
|
alpar@9
|
453 else if (glp_get_dual_stat(lp) == GLP_FEAS)
|
alpar@9
|
454 { /* resulting basis is optimal or at least dual feasible,
|
alpar@9
|
455 so we have the correct lower bound to degradation */
|
alpar@9
|
456 if (P->dir == GLP_MIN)
|
alpar@9
|
457 degrad = lp->obj_val - P->obj_val;
|
alpar@9
|
458 else if (P->dir == GLP_MAX)
|
alpar@9
|
459 degrad = P->obj_val - lp->obj_val;
|
alpar@9
|
460 else
|
alpar@9
|
461 xassert(P != P);
|
alpar@9
|
462 /* degradation cannot be negative by definition */
|
alpar@9
|
463 /* note that the lower bound to degradation may be close
|
alpar@9
|
464 to zero even if its exact value is zero due to round-off
|
alpar@9
|
465 errors on computing the objective value */
|
alpar@9
|
466 if (degrad < 1e-6 * (1.0 + 0.001 * fabs(P->obj_val)))
|
alpar@9
|
467 degrad = 0.0;
|
alpar@9
|
468 }
|
alpar@9
|
469 else
|
alpar@9
|
470 { /* the final basis reported by the simplex solver is dual
|
alpar@9
|
471 infeasible, so we cannot determine a non-trivial lower
|
alpar@9
|
472 bound to degradation */
|
alpar@9
|
473 degrad = 0.0;
|
alpar@9
|
474 }
|
alpar@9
|
475 }
|
alpar@9
|
476 else
|
alpar@9
|
477 { /* the simplex solver failed */
|
alpar@9
|
478 degrad = 0.0;
|
alpar@9
|
479 }
|
alpar@9
|
480 /* delete the copy of P */
|
alpar@9
|
481 glp_delete_prob(lp);
|
alpar@9
|
482 return degrad;
|
alpar@9
|
483 }
|
alpar@9
|
484
|
alpar@9
|
485 void ios_pcost_update(glp_tree *tree)
|
alpar@9
|
486 { /* update history information for pseudocost branching */
|
alpar@9
|
487 /* this routine is called every time when LP relaxation of the
|
alpar@9
|
488 current subproblem has been solved to optimality with all lazy
|
alpar@9
|
489 and cutting plane constraints included */
|
alpar@9
|
490 int j;
|
alpar@9
|
491 double dx, dz, psi;
|
alpar@9
|
492 struct csa *csa = tree->pcost;
|
alpar@9
|
493 xassert(csa != NULL);
|
alpar@9
|
494 xassert(tree->curr != NULL);
|
alpar@9
|
495 /* if the current subproblem is the root, skip updating */
|
alpar@9
|
496 if (tree->curr->up == NULL) goto skip;
|
alpar@9
|
497 /* determine branching variable x[j], which was used in the
|
alpar@9
|
498 parent subproblem to create the current subproblem */
|
alpar@9
|
499 j = tree->curr->up->br_var;
|
alpar@9
|
500 xassert(1 <= j && j <= tree->n);
|
alpar@9
|
501 /* determine the change dx[j] = new x[j] - old x[j],
|
alpar@9
|
502 where new x[j] is a value of x[j] in optimal solution to LP
|
alpar@9
|
503 relaxation of the current subproblem, old x[j] is a value of
|
alpar@9
|
504 x[j] in optimal solution to LP relaxation of the parent
|
alpar@9
|
505 subproblem */
|
alpar@9
|
506 dx = tree->mip->col[j]->prim - tree->curr->up->br_val;
|
alpar@9
|
507 xassert(dx != 0.0);
|
alpar@9
|
508 /* determine corresponding change dz = new dz - old dz in the
|
alpar@9
|
509 objective function value */
|
alpar@9
|
510 dz = tree->mip->obj_val - tree->curr->up->lp_obj;
|
alpar@9
|
511 /* determine per unit degradation of the objective function */
|
alpar@9
|
512 psi = fabs(dz / dx);
|
alpar@9
|
513 /* update history information */
|
alpar@9
|
514 if (dx < 0.0)
|
alpar@9
|
515 { /* the current subproblem is down-branch */
|
alpar@9
|
516 csa->dn_cnt[j]++;
|
alpar@9
|
517 csa->dn_sum[j] += psi;
|
alpar@9
|
518 }
|
alpar@9
|
519 else /* dx > 0.0 */
|
alpar@9
|
520 { /* the current subproblem is up-branch */
|
alpar@9
|
521 csa->up_cnt[j]++;
|
alpar@9
|
522 csa->up_sum[j] += psi;
|
alpar@9
|
523 }
|
alpar@9
|
524 skip: return;
|
alpar@9
|
525 }
|
alpar@9
|
526
|
alpar@9
|
527 void ios_pcost_free(glp_tree *tree)
|
alpar@9
|
528 { /* free working area used on pseudocost branching */
|
alpar@9
|
529 struct csa *csa = tree->pcost;
|
alpar@9
|
530 xassert(csa != NULL);
|
alpar@9
|
531 xfree(csa->dn_cnt);
|
alpar@9
|
532 xfree(csa->dn_sum);
|
alpar@9
|
533 xfree(csa->up_cnt);
|
alpar@9
|
534 xfree(csa->up_sum);
|
alpar@9
|
535 xfree(csa);
|
alpar@9
|
536 tree->pcost = NULL;
|
alpar@9
|
537 return;
|
alpar@9
|
538 }
|
alpar@9
|
539
|
alpar@9
|
540 static double eval_psi(glp_tree *T, int j, int brnch)
|
alpar@9
|
541 { /* compute estimation of pseudocost of variable x[j] for down-
|
alpar@9
|
542 or up-branch */
|
alpar@9
|
543 struct csa *csa = T->pcost;
|
alpar@9
|
544 double beta, degrad, psi;
|
alpar@9
|
545 xassert(csa != NULL);
|
alpar@9
|
546 xassert(1 <= j && j <= T->n);
|
alpar@9
|
547 if (brnch == GLP_DN_BRNCH)
|
alpar@9
|
548 { /* down-branch */
|
alpar@9
|
549 if (csa->dn_cnt[j] == 0)
|
alpar@9
|
550 { /* initialize down pseudocost */
|
alpar@9
|
551 beta = T->mip->col[j]->prim;
|
alpar@9
|
552 degrad = eval_degrad(T->mip, j, floor(beta));
|
alpar@9
|
553 if (degrad == DBL_MAX)
|
alpar@9
|
554 { psi = DBL_MAX;
|
alpar@9
|
555 goto done;
|
alpar@9
|
556 }
|
alpar@9
|
557 csa->dn_cnt[j] = 1;
|
alpar@9
|
558 csa->dn_sum[j] = degrad / (beta - floor(beta));
|
alpar@9
|
559 }
|
alpar@9
|
560 psi = csa->dn_sum[j] / (double)csa->dn_cnt[j];
|
alpar@9
|
561 }
|
alpar@9
|
562 else if (brnch == GLP_UP_BRNCH)
|
alpar@9
|
563 { /* up-branch */
|
alpar@9
|
564 if (csa->up_cnt[j] == 0)
|
alpar@9
|
565 { /* initialize up pseudocost */
|
alpar@9
|
566 beta = T->mip->col[j]->prim;
|
alpar@9
|
567 degrad = eval_degrad(T->mip, j, ceil(beta));
|
alpar@9
|
568 if (degrad == DBL_MAX)
|
alpar@9
|
569 { psi = DBL_MAX;
|
alpar@9
|
570 goto done;
|
alpar@9
|
571 }
|
alpar@9
|
572 csa->up_cnt[j] = 1;
|
alpar@9
|
573 csa->up_sum[j] = degrad / (ceil(beta) - beta);
|
alpar@9
|
574 }
|
alpar@9
|
575 psi = csa->up_sum[j] / (double)csa->up_cnt[j];
|
alpar@9
|
576 }
|
alpar@9
|
577 else
|
alpar@9
|
578 xassert(brnch != brnch);
|
alpar@9
|
579 done: return psi;
|
alpar@9
|
580 }
|
alpar@9
|
581
|
alpar@9
|
582 static void progress(glp_tree *T)
|
alpar@9
|
583 { /* display progress of pseudocost initialization */
|
alpar@9
|
584 struct csa *csa = T->pcost;
|
alpar@9
|
585 int j, nv = 0, ni = 0;
|
alpar@9
|
586 for (j = 1; j <= T->n; j++)
|
alpar@9
|
587 { if (glp_ios_can_branch(T, j))
|
alpar@9
|
588 { nv++;
|
alpar@9
|
589 if (csa->dn_cnt[j] > 0 && csa->up_cnt[j] > 0) ni++;
|
alpar@9
|
590 }
|
alpar@9
|
591 }
|
alpar@9
|
592 xprintf("Pseudocosts initialized for %d of %d variables\n",
|
alpar@9
|
593 ni, nv);
|
alpar@9
|
594 return;
|
alpar@9
|
595 }
|
alpar@9
|
596
|
alpar@9
|
597 int ios_pcost_branch(glp_tree *T, int *_next)
|
alpar@9
|
598 { /* choose branching variable with pseudocost branching */
|
alpar@9
|
599 glp_long t = xtime();
|
alpar@9
|
600 int j, jjj, sel;
|
alpar@9
|
601 double beta, psi, d1, d2, d, dmax;
|
alpar@9
|
602 /* initialize the working arrays */
|
alpar@9
|
603 if (T->pcost == NULL)
|
alpar@9
|
604 T->pcost = ios_pcost_init(T);
|
alpar@9
|
605 /* nothing has been chosen so far */
|
alpar@9
|
606 jjj = 0, dmax = -1.0;
|
alpar@9
|
607 /* go through the list of branching candidates */
|
alpar@9
|
608 for (j = 1; j <= T->n; j++)
|
alpar@9
|
609 { if (!glp_ios_can_branch(T, j)) continue;
|
alpar@9
|
610 /* determine primal value of x[j] in optimal solution to LP
|
alpar@9
|
611 relaxation of the current subproblem */
|
alpar@9
|
612 beta = T->mip->col[j]->prim;
|
alpar@9
|
613 /* estimate pseudocost of x[j] for down-branch */
|
alpar@9
|
614 psi = eval_psi(T, j, GLP_DN_BRNCH);
|
alpar@9
|
615 if (psi == DBL_MAX)
|
alpar@9
|
616 { /* down-branch has no primal feasible solution */
|
alpar@9
|
617 jjj = j, sel = GLP_DN_BRNCH;
|
alpar@9
|
618 goto done;
|
alpar@9
|
619 }
|
alpar@9
|
620 /* estimate degradation of the objective for down-branch */
|
alpar@9
|
621 d1 = psi * (beta - floor(beta));
|
alpar@9
|
622 /* estimate pseudocost of x[j] for up-branch */
|
alpar@9
|
623 psi = eval_psi(T, j, GLP_UP_BRNCH);
|
alpar@9
|
624 if (psi == DBL_MAX)
|
alpar@9
|
625 { /* up-branch has no primal feasible solution */
|
alpar@9
|
626 jjj = j, sel = GLP_UP_BRNCH;
|
alpar@9
|
627 goto done;
|
alpar@9
|
628 }
|
alpar@9
|
629 /* estimate degradation of the objective for up-branch */
|
alpar@9
|
630 d2 = psi * (ceil(beta) - beta);
|
alpar@9
|
631 /* determine d = max(d1, d2) */
|
alpar@9
|
632 d = (d1 > d2 ? d1 : d2);
|
alpar@9
|
633 /* choose x[j] which provides maximal estimated degradation of
|
alpar@9
|
634 the objective either in down- or up-branch */
|
alpar@9
|
635 if (dmax < d)
|
alpar@9
|
636 { dmax = d;
|
alpar@9
|
637 jjj = j;
|
alpar@9
|
638 /* continue the search from a subproblem, where degradation
|
alpar@9
|
639 is less than in other one */
|
alpar@9
|
640 sel = (d1 <= d2 ? GLP_DN_BRNCH : GLP_UP_BRNCH);
|
alpar@9
|
641 }
|
alpar@9
|
642 /* display progress of pseudocost initialization */
|
alpar@9
|
643 if (T->parm->msg_lev >= GLP_ON)
|
alpar@9
|
644 { if (xdifftime(xtime(), t) >= 10.0)
|
alpar@9
|
645 { progress(T);
|
alpar@9
|
646 t = xtime();
|
alpar@9
|
647 }
|
alpar@9
|
648 }
|
alpar@9
|
649 }
|
alpar@9
|
650 if (dmax == 0.0)
|
alpar@9
|
651 { /* no degradation is indicated; choose a variable having most
|
alpar@9
|
652 fractional value */
|
alpar@9
|
653 jjj = branch_mostf(T, &sel);
|
alpar@9
|
654 }
|
alpar@9
|
655 done: *_next = sel;
|
alpar@9
|
656 return jjj;
|
alpar@9
|
657 }
|
alpar@9
|
658
|
alpar@9
|
659 /* eof */
|