Scippy

SCIP

Solving Constraint Integer Programs

branch_relpscost.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file branch_relpscost.c
26 * @ingroup DEFPLUGINS_BRANCH
27 * @brief reliable pseudo costs branching rule
28 * @author Tobias Achterberg
29 * @author Timo Berthold
30 * @author Gerald Gamrath
31 * @author Gioni Mexi
32 * @author Marc Pfetsch
33 * @author Krunal Patel
34 */
35
36/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
37
40#include "scip/treemodel.h"
41#include "scip/cons_and.h"
42#include "scip/pub_branch.h"
43#include "scip/pub_cons.h"
44#include "scip/scip_exact.h"
45#include "scip/pub_message.h"
46#include "scip/pub_misc.h"
47#include "scip/pub_sol.h"
48#include "scip/pub_tree.h"
49#include "scip/pub_var.h"
50#include "scip/scip_branch.h"
51#include "scip/scip_cons.h"
52#include "scip/scip_general.h"
53#include "scip/scip_lp.h"
54#include "scip/scip_mem.h"
55#include "scip/scip_message.h"
56#include "scip/scip_nlp.h"
57#include "scip/scip_numerics.h"
58#include "scip/scip_param.h"
59#include "scip/scip_prob.h"
61#include "scip/scip_sol.h"
63#include "scip/scip_tree.h"
64#include "scip/scip_var.h"
65#include "scip/prop_symmetry.h"
66#include "scip/symmetry.h"
67#include <string.h>
68
69#define BRANCHRULE_NAME "relpscost"
70#define BRANCHRULE_DESC "reliability branching on pseudo cost values"
71#define BRANCHRULE_PRIORITY 10000
72#define BRANCHRULE_MAXDEPTH -1
73#define BRANCHRULE_MAXBOUNDDIST 1.0
74
75#define DEFAULT_CONFLICTWEIGHT 0.01 /**< weight in score calculations for conflict score */
76#define DEFAULT_CONFLENGTHWEIGHT 0.0 /**< weight in score calculations for conflict length score*/
77#define DEFAULT_INFERENCEWEIGHT 0.0001 /**< weight in score calculations for inference score */
78#define DEFAULT_CUTOFFWEIGHT 0.0001 /**< weight in score calculations for cutoff score */
79#define DEFAULT_GMIAVGEFFWEIGHT 0.0 /**< weight in score calculations of average GMI cut normed efficacies */
80#define DEFAULT_GMILASTEFFWEIGHT 0.00001 /**< weight in score calculations of last GMI cut normed efficacy */
81#define DEFAULT_PSCOSTWEIGHT 1.0 /**< weight in score calculations for pseudo cost score */
82#define DEFAULT_NLSCOREWEIGHT 0.1 /**< weight in score calculations for nlcount score */
83#define DEFAULT_MINRELIABLE 1.0 /**< minimal value for minimum pseudo cost size to regard pseudo cost value as reliable */
84#define DEFAULT_MAXRELIABLE 5.0 /**< maximal value for minimum pseudo cost size to regard pseudo cost value as reliable */
85#define DEFAULT_SBITERQUOT 0.5 /**< maximal fraction of strong branching LP iterations compared to normal iterations */
86#define DEFAULT_DYNAMICLOOKAHEADQUOT 0.6 /**< apply dynamic lookahead after this fraction maxlookahead is reached */
87#define DEFAULT_SBITEROFS 100000 /**< additional number of allowed strong branching LP iterations */
88#define DEFAULT_MAXLOOKAHEAD 9 /**< maximal number of further variables evaluated without better score */
89#define DEFAULT_INITCAND 100 /**< maximal number of candidates initialized with strong branching per node */
90#define DEFAULT_INITITER 0 /**< iteration limit for strong branching initialization of pseudo cost entries (0: auto) */
91#define DEFAULT_MAXBDCHGS 5 /**< maximal number of bound tightenings before the node is reevaluated (-1: unlimited) */
92#define DEFAULT_MAXPROPROUNDS -2 /**< maximum number of propagation rounds to be performed during strong branching
93 * before solving the LP (-1: no limit, -2: parameter settings) */
94#define DEFAULT_PROBINGBOUNDS TRUE /**< should valid bounds be identified in a probing-like fashion during strong
95 * branching (only with propagation)? */
96#define DEFAULT_USERELERRORFORRELIABILITY FALSE /**< should reliability be based on relative errors? */
97#define DEFAULT_LOWERRORTOL 0.05 /**< lowest tolerance beneath which relative errors are reliable */
98#define DEFAULT_HIGHERRORTOL 1.0 /**< highest tolerance beneath which relative errors are reliable */
99#define DEFAULT_USEHYPTESTFORRELIABILITY FALSE /**< should the strong branching decision be based on a hypothesis test? */
100#define DEFAULT_USEDYNAMICCONFIDENCE FALSE /**< should the confidence level be adjusted dynamically? */
101#define DEFAULT_STORESEMIINITCOSTS FALSE /**< should strong branching result be considered for pseudo costs if the other direction was infeasible? */
102#define DEFAULT_USESBLOCALINFO FALSE /**< should the scoring function use only local cutoff and inference information obtained for strong branching candidates? */
103#define DEFAULT_CONFIDENCELEVEL 2 /**< The confidence level for statistical methods, between 0 (Min) and 4 (Max). */
104#define DEFAULT_SKIPBADINITCANDS TRUE /**< should branching rule skip candidates that have a low probability to be
105 * better than the best strong-branching or pseudo-candidate? */
106#define DEFAULT_STARTRANDSEED 5 /**< start random seed for random number generation */
107#define DEFAULT_DYNAMICLOOKAHEAD FALSE /**< should we use a dynamic lookahead based on a tree size estimation of further strong branchings? */
108#define DEFAULT_MINSAMPLESIZE 10 /**< minimum sample size to estimate the tree size for dynamic lookahead */
109#define DEFAULT_DYNAMICLOOKDISTRIBUTION 1 /**< which distribution should be used for dynamic lookahead? 0=exponential, 1=Pareto, 2=log-normal */
110#define DEFAULT_RANDINITORDER FALSE /**< should slight perturbation of scores be used to break ties in the prior scores? */
111#define DEFAULT_USESMALLWEIGHTSITLIM FALSE /**< should smaller weights be used for pseudo cost updates after hitting the LP iteration limit? */
112#define DEFAULT_DYNAMICWEIGHTS TRUE /**< should the weights of the branching rule be adjusted dynamically during solving based
113 * infeasible and objective leaf counters? */
114#define DEFAULT_DEGENERACYAWARE 1 /**< should degeneracy be taken into account to update weights and skip strong branching? (0: off, 1: after root, 2: always)*/
115
116/* symmetry handling */
117#define DEFAULT_FILTERCANDSSYM FALSE /**< Use symmetry to filter branching candidates? */
118#define DEFAULT_TRANSSYMPSCOST FALSE /**< Transfer pscost information to symmetric variables if filtering is performed? */
119
120/* distribution to use for lookahead strong branching */
121#define EXPONENTIALDISTRIBUTION 0
122#define PARETODISTRIBUTION 1
123#define LOGNORMALDISTRIBUTION 2
124
125/* shift for geometric mean of left and right gains */
126#define GEOMMEANSHIFT 0.01
127/* maximum gain with which we update the estimated left and right dual gains */
128#define MAXGAINTHRESHOLD 1e15
129/* minimum considered expected dual gain and probability for lookahead strong branching */
130#define MINGAINTHRESHOLD 1e-5
131
132/* discounted pseudo cost */
133#define BRANCHRULE_DISCOUNTFACTOR 0.2 /**< default discount factor for discounted pseudo costs.*/
134
135/** branching rule data */
136struct SCIP_BranchruleData
137{
138 SCIP_Real conflictweight; /**< weight in score calculations for conflict score */
139 SCIP_Real conflengthweight; /**< weight in score calculations for conflict length score */
140 SCIP_Real inferenceweight; /**< weight in score calculations for inference score */
141 SCIP_Real cutoffweight; /**< weight in score calculations for cutoff score */
142 SCIP_Real gmiavgeffweight; /**< weight in score calculations of average GMI normed cut efficacies */
143 SCIP_Real gmilasteffweight; /**< weight in score calculations of last GMI cut normalized efficacy */
144 SCIP_Real pscostweight; /**< weight in score calculations for pseudo cost score */
145 SCIP_Real nlscoreweight; /**< weight in score calculations for nlcount score */
146 SCIP_Real minreliable; /**< minimal value for minimum pseudo cost size to regard pseudo cost value as reliable */
147 SCIP_Real maxreliable; /**< maximal value for minimum pseudo cost size to regard pseudo cost value as reliable */
148 SCIP_Real sbiterquot; /**< maximal fraction of strong branching LP iterations compared to normal iterations */
149 SCIP_Real meandualgain; /**< mean dual gain of all strong branchings */
150 SCIP_Real currmeandualgain; /**< current mean dual gain in current node */
151 SCIP_Real maxmeangain; /**< maximal dual gain of all strong branchings */
152 SCIP_Real minmeangain; /**< minimal dual gain of all strong branchings */
153 SCIP_Real sumlogmeangains; /**< sum of logarithms of all means of the dual gains */
154 SCIP_Real logstdevgain; /**< logarithm of the standard deviation of the means of the dual gains */
155 SCIP_Real nzerogains; /**< number of zero dual gains */
156 int currndualgains; /**< number of dual gains used in the computation of the mean from current node */
157 int sbiterofs; /**< additional number of allowed strong branching LP iterations */
158 int maxlookahead; /**< maximal number of further variables evaluated without better score */
159 int initcand; /**< maximal number of candidates initialized with strong branching per node */
160 int inititer; /**< iteration limit for strong branching initialization of pseudo cost entries (0: auto) */
161 int maxbdchgs; /**< maximal number of bound tightenings before the node is reevaluated (-1: unlimited) */
162 int maxproprounds; /**< maximum number of propagation rounds to be performed during strong branching
163 * before solving the LP (-1: no limit, -2: parameter settings) */
164 SCIP_Bool probingbounds; /**< should valid bounds be identified in a probing-like fashion during strong
165 * branching (only with propagation)? */
166 SCIP_Bool userelerrorforreliability; /**< should reliability be based on relative errors? */
167 SCIP_Real lowerrortol; /**< lowest tolerance beneath which relative errors are reliable */
168 SCIP_Real higherrortol; /**< highest tolerance beneath which relative errors are reliable */
169 SCIP_Bool usehyptestforreliability; /**< should the strong branching decision be based on a hypothesis test? */
170 SCIP_Bool usedynamicconfidence; /**< should the confidence level be adjusted dynamically? */
171 SCIP_Bool storesemiinitcosts; /**< should strong branching result be considered for pseudo costs if the
172 * other direction was infeasible? */
173 SCIP_Bool usesblocalinfo; /**< should the scoring function disregard cutoffs for variable if sb-lookahead was feasible ? */
174 SCIP_Bool skipbadinitcands; /**< should branching rule skip candidates that have a low probability to be
175 * better than the best strong-branching or pseudo-candidate? */
176 SCIP_Bool dynamicweights; /**< should the weights of the branching rule be adjusted dynamically during
177 * solving based on objective and infeasible leaf counters? */
178 SCIP_Real dynamiclookaheadquot; /**< apply dynamic lookahead after this fraction maxlookahead is reached */
179 SCIP_Bool dynamiclookahead; /**< should we use a dynamic lookahead based on a tree size estimation of further strong branchings? */
180 int dynamiclookdistribution; /**< which distribution should be used for dynamic lookahead? 0=exponential, 1=Pareto, 2=log-normal */
181 int minsamplesize; /**< minimum sample size to estimate the tree size for dynamic lookahead */
182 int degeneracyaware; /**< should degeneracy be taken into account to update weights and skip strong branching? (0: off, 1: after root, 2: always) */
183 int confidencelevel; /**< The confidence level for statistical methods, between 0 (Min) and 4 (Max). */
184 int* nlcount; /**< array to store nonlinear count values */
185 int nlcountsize; /**< length of nlcount array */
186 int nlcountmax; /**< maximum entry in nlcount array or 1 if NULL */
187 SCIP_Bool randinitorder; /**< should slight perturbation of scores be used to break ties in the prior scores? */
188 SCIP_RANDNUMGEN* randnumgen; /**< random number generator */
189 int startrandseed; /**< start random seed for random number generation */
190 SCIP_Bool usesmallweightsitlim; /**< should smaller weights be used for pseudo cost updates after hitting the LP iteration limit? */
191 SCIP_TREEMODEL* treemodel; /**< Parameters for the Treemodel branching rules */
192
193 /* for symmetry */
194 SCIP_Bool filtercandssym; /**< Use symmetry to filter branching candidates? */
195 SCIP_Bool transsympscost; /**< Transfer pscost information to symmetric variables? */
196
197 SCIP_Bool nosymmetry; /**< No symmetry present? */
198 int* orbits; /**< array of non-trivial orbits */
199 int* orbitbegins; /**< array containing begin positions of new orbits in orbits array */
200 int norbits; /**< pointer to number of orbits currently stored in orbits */
201 int* varorbitmap; /**< array for storing indices of the containing orbit for each variable */
202 int* orbitrep; /**< representative variable of each orbit */
203 SCIP_VAR** permvars; /**< variables on which permutations act */
204 int npermvars; /**< number of variables for permutations */
205 SCIP_HASHMAP* permvarmap; /**< map of variables to indices in permvars array */
206
207 /* for discounted pseudo costs */
208 SCIP_Real discountfactor; /**< discount factor for discounted pseudo costs.*/
209};
210
211/*
212 * local methods
213 */
214
215/** initialize orbits */
216static
218 SCIP* scip, /**< SCIP data structure */
219 SCIP_BRANCHRULEDATA* branchruledata /**< branching rule data */
220 )
221{
222 int** permstrans = NULL;
223 int* components = NULL;
224 int* componentbegins = NULL;
225 int* vartocomponent = NULL;
226 int ncomponents = 0;
227 int nperms = -1;
228
229 assert( scip != NULL );
230 assert( branchruledata != NULL );
231 assert( branchruledata->filtercandssym );
232
233 /* exit if no symmetry or orbits already available */
234 if( branchruledata->nosymmetry || branchruledata->orbits != NULL )
235 return SCIP_OKAY;
236
237 assert( branchruledata->orbitbegins == NULL );
238 assert( branchruledata->varorbitmap == NULL );
239 assert( branchruledata->orbitrep == NULL );
240
241 /* obtain symmetry including permutations */
242 SCIP_CALL( SCIPgetSymmetry(scip, &branchruledata->npermvars, &branchruledata->permvars, &branchruledata->permvarmap,
243 &nperms, NULL, &permstrans, NULL, NULL, &components, &componentbegins, &vartocomponent, &ncomponents) );
244
245 /* turn off symmetry handling if there is no symmetry or the number of variables is not equal */
246 if( nperms <= 0 || branchruledata->npermvars != SCIPgetNVars(scip) )
247 {
248 branchruledata->nosymmetry = TRUE;
249 return SCIP_OKAY;
250 }
251 assert( branchruledata->permvars != NULL );
252 assert( branchruledata->permvarmap != NULL );
253 assert( branchruledata->npermvars > 0 );
254 assert( permstrans != NULL );
255 assert( components != NULL );
256 assert( componentbegins != NULL );
257 assert( vartocomponent != NULL );
258 assert( ncomponents > 0 );
259
260 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->orbits, branchruledata->npermvars) );
261 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->orbitbegins, branchruledata->npermvars) );
262 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->varorbitmap, branchruledata->npermvars) );
263 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->orbitrep, branchruledata->npermvars) );
264
265 /* Compute orbits on all variables, since this might help for branching and this computation is only done once. */
266 SCIP_CALL( SCIPcomputeOrbitsComponentsSym(scip, branchruledata->npermvars, permstrans, nperms,
267 components, componentbegins, vartocomponent, ncomponents,
268 branchruledata->orbits, branchruledata->orbitbegins, &branchruledata->norbits, branchruledata->varorbitmap) );
269 assert( branchruledata->norbits < branchruledata->npermvars );
270
271 return SCIP_OKAY;
272}
273
274/** filter out symmetric variables from branching variables */
275static
277 SCIP* scip, /**< SCIP data structure */
278 SCIP_BRANCHRULEDATA* branchruledata, /**< branching rule data */
279 SCIP_VAR** origbranchcands, /**< original branching candidates */
280 SCIP_Real* origbranchcandssol, /**< original solution value for the branching candidates */
281 SCIP_Real* origbranchcandsfrac,/**< original fractional part of the branching candidates */
282 int norigbranchcands, /**< original number of branching candidates */
283 SCIP_VAR** branchcands, /**< branching candidates */
284 SCIP_Real* branchcandssol, /**< solution value for the branching candidates */
285 SCIP_Real* branchcandsfrac, /**< fractional part of the branching candidates */
286 int* branchorbitidx, /**< array of indices of orbit of branching candidates */
287 int* nbranchcands /**< pointer to store number of branching candidates */
288 )
289{
290 int i;
291
292 assert( scip != NULL );
293 assert( branchruledata != NULL );
294 assert( origbranchcands != NULL );
295 assert( origbranchcandssol != NULL );
296 assert( origbranchcandsfrac != NULL );
297 assert( branchcands != NULL );
298 assert( branchcandssol != NULL );
299 assert( branchcandsfrac != NULL );
300 assert( nbranchcands != NULL );
301
302 assert( ! branchruledata->nosymmetry );
303 assert( branchruledata->orbitbegins != NULL );
304 assert( branchruledata->orbits != NULL );
305 assert( branchruledata->permvarmap != NULL );
306 assert( branchruledata->varorbitmap != NULL );
307 assert( branchruledata->orbitrep != NULL );
308 assert( branchruledata->norbits < branchruledata->npermvars );
309
310 /* init representatives (used to see whether variable is the first in an orbit) */
311 for( i = 0; i < branchruledata->norbits; ++i )
312 branchruledata->orbitrep[i] = -1;
313
314 /* loop through branching variables, determine orbit and whether they are the first ones */
315 *nbranchcands = 0;
316 for( i = 0; i < norigbranchcands; ++i )
317 {
318 int orbitidx = -1;
319 int varidx;
320
321 varidx = SCIPhashmapGetImageInt(branchruledata->permvarmap, (void*) origbranchcands[i]);
322 if( varidx != INT_MAX )
323 {
324 assert( 0 <= varidx && varidx < branchruledata->npermvars );
325 orbitidx = branchruledata->varorbitmap[varidx];
326 }
327 assert( -1 <= orbitidx && orbitidx < branchruledata->norbits );
328
329 /* Check whether the variable is not present (can happen if variable was added after computing symmetries or is in
330 * a singleton orbit). */
331 if( orbitidx == -1 )
332 {
333 branchcands[*nbranchcands] = origbranchcands[i];
334 branchcandssol[*nbranchcands] = origbranchcandssol[i];
335 branchcandsfrac[*nbranchcands] = origbranchcandsfrac[i];
336 branchorbitidx[*nbranchcands] = -1;
337 ++(*nbranchcands);
338 }
339 else if( branchruledata->orbitrep[orbitidx] == -1 )
340 {
341 /* if variable is the first in a nontrivial orbit */
342 assert( 0 <= varidx && varidx < branchruledata->npermvars );
343 branchruledata->orbitrep[orbitidx] = varidx;
344 branchcands[*nbranchcands] = origbranchcands[i];
345 branchcandssol[*nbranchcands] = origbranchcandssol[i];
346 branchcandsfrac[*nbranchcands] = origbranchcandsfrac[i];
347 branchorbitidx[*nbranchcands] = orbitidx;
348 ++(*nbranchcands);
349 }
350 }
351
352 SCIPdebugMsg(scip, "Filtered out %d variables by symmetry.\n", norigbranchcands - *nbranchcands);
353
354 return SCIP_OKAY;
355}
356
357/** updates the pseudo costs of the given variable and all its symmetric variables */
358static
360 SCIP* scip, /**< SCIP data structure */
361 SCIP_BRANCHRULEDATA* branchruledata, /**< branching rule data */
362 SCIP_VAR* branchvar, /**< branching variable candidate */
363 int* branchorbitidx, /**< array of orbit indices */
364 int branchvaridx, /**< index of variable in branchorbitidx */
365 SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
366 SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
367 SCIP_Real weight /**< weight in (0,1] of this update in pseudo cost sum */
368 )
369{
370 int orbitidx;
371 int j;
372 SCIP_Bool useancpscost;
373
374 assert( scip != NULL );
375 assert( branchruledata != NULL );
376
377 /* update the discounted pseudo cost of the current node branched variable */
378 SCIP_CALL( SCIPgetBoolParam(scip, "branching/collectancpscost", &useancpscost) );
379 if( useancpscost )
380 {
381 SCIP_NODE* currentnode;
382
383 currentnode = SCIPgetFocusNode(scip);
384 if( SCIPnodeGetDepth(currentnode) > 0 )
385 {
386 SCIP_DOMCHG* domchange;
387 SCIP_BOUNDCHG* boundchg;
388 int nboundchgs;
389 SCIP_VAR* var;
390 int i;
391 SCIP_Real parentlpsolval;
392 SCIP_Real parentsolvedelta;
393
394 domchange = SCIPnodeGetDomchg(currentnode);
395 nboundchgs = SCIPdomchgGetNBoundchgs(domchange);
396 for( i = 0; i < nboundchgs; ++i )
397 {
398 boundchg = SCIPdomchgGetBoundchg(domchange, i);
399 var = SCIPboundchgGetVar(boundchg);
400 assert(var != NULL);
401
403 {
404 parentlpsolval = SCIPboundchgGetLPSolVal(boundchg);
405 if( parentlpsolval >= SCIP_INVALID )
406 continue;
407 parentsolvedelta = SCIPboundchgGetNewbound(boundchg) - parentlpsolval;
408 SCIP_CALL( SCIPupdateVarAncPseudocost(scip, var, parentsolvedelta, objdelta, weight) );
409 }
410 }
411 }
412 }
413
414 if( branchruledata->nosymmetry || ! branchruledata->transsympscost || branchorbitidx == NULL )
415 {
416 /* use original update function */
417 SCIP_CALL( SCIPupdateVarPseudocost(scip, branchvar, solvaldelta, objdelta, weight) );
418 return SCIP_OKAY;
419 }
420
421 assert( branchruledata->orbitbegins != NULL );
422 assert( branchruledata->orbits != NULL );
423 assert( 0 <= branchvaridx && branchvaridx < branchruledata->npermvars );
424
425 orbitidx = branchorbitidx[branchvaridx];
426 if( orbitidx < 0 )
427 {
428 /* only update given variable */
429 SCIP_CALL( SCIPupdateVarPseudocost(scip, branchvar, solvaldelta, objdelta, weight) );
430 return SCIP_OKAY;
431 }
432 assert( 0 <= orbitidx && orbitidx < branchruledata->norbits );
433
434 /* loop through orbit containing variable and update pseudo costs for all variables */
435 for( j = branchruledata->orbitbegins[orbitidx]; j < branchruledata->orbitbegins[orbitidx+1]; ++j )
436 {
437 SCIP_VAR* var;
438 int idx;
439
440 idx = branchruledata->orbits[j];
441 assert( 0 <= idx && idx < branchruledata->npermvars );
442
443 var = branchruledata->permvars[idx];
444 assert( var != NULL );
445
446 if( SCIPvarIsActive(var) )
447 {
448 SCIP_CALL( SCIPupdateVarPseudocost(scip, var, solvaldelta, objdelta, weight) );
449 }
450 }
451
452 return SCIP_OKAY;
453}
454
455/**! [SnippetCodeStyleDeclaration] */
456
457/** counts number of nonlinear constraints in which each variable appears */
458static
460 SCIP* scip, /**< SCIP data structure */
461 int* nlcount, /**< pointer to array for storing count values */
462 int nlcountsize, /**< buffer for storing length of nlcount array */
463 int* nlcountmax /**< buffer for storing maximum value in nlcount array */
464 )
465{
466 SCIP_CONSHDLR* andconshdlr;
467 SCIP_VAR** vars;
468 int nvars;
469 int i;
470
471/**! [SnippetCodeStyleDeclaration] */
472
473 assert(scip != NULL);
474 assert(nlcount != NULL);
475 assert(nlcountmax != NULL);
476
477 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
478 assert(nlcountsize >= nvars);
479
480 /* get nonlinearity for constraints in NLP */
482 {
483 assert(SCIPgetNNLPVars(scip) == nvars);
485 }
486 else
487 {
488 BMSclearMemoryArray(nlcount, nvars);
489 }
490
491 /* increase counters for and constraints */
492 andconshdlr = SCIPfindConshdlr(scip, "and");
493 if( andconshdlr != NULL )
494 {
495 int c;
496
497 for( c = 0; c < SCIPconshdlrGetNActiveConss(andconshdlr); ++c )
498 {
499 SCIP_CONS* andcons;
500 SCIP_VAR** andvars;
501 SCIP_VAR* andres;
502 int probindex;
503 int nandvars;
504 int v;
505
506 /* get constraint and variables */
507 andcons = SCIPconshdlrGetConss(andconshdlr)[c];
508 nandvars = SCIPgetNVarsAnd(scip, andcons);
509 andvars = SCIPgetVarsAnd(scip, andcons);
510 andres = SCIPgetResultantAnd(scip, andcons);
511
512 /* get active index of resultant */
513 probindex = SCIPvarGetProbindex(SCIPvarGetProbvar(andres));
514
515 /* the resultant might be deleted */
516 if( probindex >= 0 )
517 ++nlcount[probindex];
518
519 /**! [SnippetCodeStyleIfFor] */
520 for( v = 0; v < nandvars; ++v )
521 {
522 /* get active index of operator */
523 probindex = SCIPvarGetProbindex(SCIPvarGetProbvar(andvars[v]));
524
525 /* the operator might be deleted */
526 if( probindex >= 0 )
527 ++nlcount[probindex];
528 }
529 /**! [SnippetCodeStyleIfFor] */
530 }
531 }
532
533 /* compute maximum count value */
534 *nlcountmax = 1;
535 for( i = 0; i < nvars; ++i )
536 {
537 if( *nlcountmax < nlcount[i] )
538 *nlcountmax = nlcount[i];
539 }
540
541 return SCIP_OKAY;
542}
543
544static
546 SCIP* scip, /**< SCIP data structure */
547 SCIP_BRANCHRULEDATA* branchruledata /**< branching rule data */
548 )
549{
550 int nvars;
551
552 assert(scip != NULL);
553 assert(branchruledata != NULL);
554
555 nvars = SCIPgetNVars(scip);
556
557 /**@todo test whether we want to apply this as if problem has only and constraints */
558 /**@todo update changes in and constraints */
559 if( branchruledata->nlscoreweight > 0.0 ) /* && SCIPisNLPConstructed(scip) */
560 {
561 if( branchruledata->nlcount == NULL )
562 {
563 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->nlcount, nvars) );
564 branchruledata->nlcountsize = nvars;
565
566 SCIP_CALL( countNonlinearities(scip, branchruledata->nlcount, branchruledata->nlcountsize, &branchruledata->nlcountmax) );
567 }
568 else if( branchruledata->nlcountsize < nvars )
569 {
570 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &branchruledata->nlcount, branchruledata->nlcountsize, nvars) );
571 /**@todo should we update nlcounts for new variables? */
572 BMSclearMemoryArray(&(branchruledata->nlcount[branchruledata->nlcountsize]), nvars - branchruledata->nlcountsize); /*lint !e866*/
573 branchruledata->nlcountsize = nvars;
574 }
575 assert(branchruledata->nlcount != NULL);
576 assert(branchruledata->nlcountsize == nvars);
577 assert(branchruledata->nlcountmax >= 1);
578 }
579 else
580 {
581 SCIPfreeBlockMemoryArrayNull(scip, &branchruledata->nlcount, branchruledata->nlcountsize);
582 branchruledata->nlcountsize = 0;
583 branchruledata->nlcountmax = 1;
584 }
585
586 return SCIP_OKAY;
587}
588
589
590/** calculates nlscore value between 0 and 1 */
591static
593 SCIP* scip, /**< SCIP data structure */
594 int* nlcount, /**< array to store count values */
595 int nlcountmax, /**< maximum value in nlcount array */
596 int probindex /**< index of branching candidate */
597 )
598{
599 if( nlcountmax >= 1 && nlcount != NULL )
600 {
601 SCIP_Real nlscore;
602
603 assert(scip != NULL);
604 assert(probindex >= 0);
605 assert(probindex < SCIPgetNVars(scip));
606
607 nlscore = nlcount[probindex] / (SCIP_Real)nlcountmax;
608
609 assert(nlscore >= 0.0);
610 assert(nlscore <= 1.0);
611 return nlscore;
612 }
613 else
614 return 0.0;
615}
616
617/** calculates an overall score value for the given individual score values */
618static
620 SCIP* scip, /**< SCIP data structure */
621 SCIP_BRANCHRULEDATA* branchruledata, /**< branching rule data */
622 SCIP_Real conflictscore, /**< conflict score of current variable */
623 SCIP_Real avgconflictscore, /**< average conflict score */
624 SCIP_Real conflengthscore, /**< conflict length score of current variable */
625 SCIP_Real avgconflengthscore, /**< average conflict length score */
626 SCIP_Real inferencescore, /**< inference score of current variable */
627 SCIP_Real avginferencescore, /**< average inference score */
628 SCIP_Real cutoffscore, /**< cutoff score of current variable */
629 SCIP_Real avgcutoffscore, /**< average cutoff score */
630 SCIP_Real gmieffscore, /**< normalized-eff of avg GMI cuts from row when var was frac and basic */
631 SCIP_Real lastgmieffscore, /**< last normalized gmieffscore when var was frac and basic */
632 SCIP_Real pscostscore, /**< pscost score of current variable */
633 SCIP_Real avgpscostscore, /**< average pscost score */
634 SCIP_Real nlscore, /**< nonlinear score of current variable between 0 and 1 */
635 SCIP_Real frac, /**< fractional value of variable in current solution */
636 SCIP_Real degeneracyfactor /**< factor to apply because of degeneracy */
637 )
638{
639 SCIP_Real score;
640 SCIP_Real dynamicfactor;
641
642 assert(branchruledata != NULL);
643 assert(0.0 < frac && frac < 1.0);
644
645 if( branchruledata->dynamicweights )
646 {
647 dynamicfactor = (SCIPgetNInfeasibleLeaves(scip) + 1.0) / (SCIPgetNObjlimLeaves(scip) + 1.0);
648 }
649 else
650 dynamicfactor = 1.0;
651
652 dynamicfactor *= degeneracyfactor;
653
654 score = dynamicfactor * (branchruledata->conflictweight * (1.0 - 1.0/(1.0+conflictscore/avgconflictscore))
655 + branchruledata->conflengthweight * (1.0 - 1.0/(1.0+conflengthscore/avgconflengthscore))
656 + branchruledata->inferenceweight * (1.0 - 1.0/(1.0+inferencescore/avginferencescore))
657 + branchruledata->cutoffweight * (1.0 - 1.0/(1.0+cutoffscore/avgcutoffscore))
658 + branchruledata->gmiavgeffweight * gmieffscore + branchruledata->gmilasteffweight * lastgmieffscore)
659 + branchruledata->pscostweight / dynamicfactor * (1.0 - 1.0/(1.0+pscostscore/avgpscostscore))
660 + branchruledata->nlscoreweight * nlscore;
661
662 /* avoid close to integral variables */
663 if( MIN(frac, 1.0 - frac) < 10.0 * SCIPfeastol(scip) )
664 score *= 1e-6;
665
666 return score;
667}
668
669/** adds given index and direction to bound change arrays */
670static
672 SCIP* scip, /**< SCIP data structure */
673 int** bdchginds, /**< pointer to bound change index array */
674 SCIP_BOUNDTYPE** bdchgtypes, /**< pointer to bound change types array */
675 SCIP_Real** bdchgbounds, /**< pointer to bound change new bounds array */
676 int* nbdchgs, /**< pointer to number of bound changes */
677 int ind, /**< index to store in bound change index array */
678 SCIP_BOUNDTYPE type, /**< type of the bound change to store in bound change type array */
679 SCIP_Real bound /**< new bound to store in bound change new bounds array */
680 )
681{
682 assert(bdchginds != NULL);
683 assert(bdchgtypes != NULL);
684 assert(bdchgbounds != NULL);
685 assert(nbdchgs != NULL);
686
687 SCIP_CALL( SCIPreallocBufferArray(scip, bdchginds, (*nbdchgs) + 1) );
688 SCIP_CALL( SCIPreallocBufferArray(scip, bdchgtypes, (*nbdchgs) + 1) );
689 SCIP_CALL( SCIPreallocBufferArray(scip, bdchgbounds, (*nbdchgs) + 1) );
690 assert(*bdchginds != NULL);
691 assert(*bdchgtypes != NULL);
692 assert(*bdchgbounds != NULL);
693
694 (*bdchginds)[*nbdchgs] = ind;
695 (*bdchgtypes)[*nbdchgs] = type;
696 (*bdchgbounds)[*nbdchgs] = bound;
697 (*nbdchgs)++;
698
699 return SCIP_OKAY;
700}
701
702/**! [SnippetCodeStyleStaticAsserts] */
703/** frees bound change arrays */
704static
706 SCIP* scip, /**< SCIP data structure */
707 int** bdchginds, /**< pointer to bound change index array */
708 SCIP_BOUNDTYPE** bdchgtypes, /**< pointer to bound change types array */
709 SCIP_Real** bdchgbounds, /**< pointer to bound change new bounds array */
710 int* nbdchgs /**< pointer to number of bound changes */
711 )
712{
713 assert(scip != NULL);
714 assert(bdchginds != NULL);
715 assert(bdchgtypes != NULL);
716 assert(bdchgbounds != NULL);
717 assert(nbdchgs != NULL);
718/**! [SnippetCodeStyleStaticAsserts] */
719
720 SCIPfreeBufferArrayNull(scip, bdchgbounds);
721 SCIPfreeBufferArrayNull(scip, bdchgtypes);
722 SCIPfreeBufferArrayNull(scip, bdchginds);
723 *nbdchgs = 0;
724}
725
726/** applies bound changes stored in bound change arrays */
727static
729 SCIP* scip, /**< SCIP data structure */
730 SCIP_VAR** vars, /**< problem variables */
731 int* bdchginds, /**< bound change index array */
732 SCIP_BOUNDTYPE* bdchgtypes, /**< bound change types array */
733 SCIP_Real* bdchgbounds, /**< bound change new bound array */
734 int nbdchgs, /**< number of bound changes */
735 SCIP_RESULT* result /**< result pointer */
736 )
737{
738#ifndef NDEBUG
739 SCIP_BRANCHRULE* branchrule;
740 SCIP_BRANCHRULEDATA* branchruledata;
741#endif
742 SCIP_Bool infeasible;
743 SCIP_Bool tightened;
744 int i;
745
746 assert(vars != NULL);
747
748#ifndef NDEBUG
749 /* find branching rule */
751 assert(branchrule != NULL);
752
753 /* get branching rule data */
754 branchruledata = SCIPbranchruleGetData(branchrule);
755 assert(branchruledata != NULL);
756#endif
757
758 SCIPdebugMsg(scip, "applying %d bound changes\n", nbdchgs);
759
760 for( i = 0; i < nbdchgs; ++i )
761 {
762 int v;
763
764 v = bdchginds[i];
765
766 SCIPdebugMsg(scip, " -> <%s> [%g,%g]\n",
767 SCIPvarGetName(vars[v]), SCIPvarGetLbLocal(vars[v]), SCIPvarGetUbLocal(vars[v]));
768
769 if( bdchgtypes[i] == SCIP_BOUNDTYPE_LOWER )
770 {
771 /* change lower bound of variable to given bound */
772 SCIP_CALL( SCIPtightenVarLb(scip, vars[v], bdchgbounds[i], TRUE, &infeasible, &tightened) );
773 if( infeasible )
774 {
775 *result = SCIP_CUTOFF;
776 return SCIP_OKAY;
777 }
778
779 /* if we did propagation, the bound change might already have been added */
780 assert(tightened || (branchruledata->maxproprounds != 0));
781 }
782 else
783 {
784 assert(bdchgtypes[i] == SCIP_BOUNDTYPE_UPPER);
785
786 /* change upper bound of variable to given bound */
787 SCIP_CALL( SCIPtightenVarUb(scip, vars[v], bdchgbounds[i], TRUE, &infeasible, &tightened) );
788 if( infeasible )
789 {
790 *result = SCIP_CUTOFF;
791 return SCIP_OKAY;
792 }
793
794 /* if we did propagation, the bound change might already have been added */
795 assert(tightened || (branchruledata->maxproprounds != 0));
796 }
797 SCIPdebugMsg(scip, " -> [%g,%g]\n", SCIPvarGetLbLocal(vars[v]), SCIPvarGetUbLocal(vars[v]));
798 }
799
800 return SCIP_OKAY;
801}
802
803/** Update the min/max gain, and the mean of all gains computed so far.
804 *
805 * This mean is used in the definition of the exponential distribution.
806 */
807static
809 SCIP* scip, /**< SCIP data structure */
810 SCIP_BRANCHRULE* branchrule, /**< branching rule */
811 SCIP_Real downgain, /**< gain for branching downwards */
812 SCIP_Real upgain /**< gain for branching upwards */
813 )
814{
815 SCIP_BRANCHRULEDATA* branchruledata = SCIPbranchruleGetData(branchrule);
816 SCIP_Real logmeangain;
817 /* initializing to avoid linter, value never used */
818 SCIP_Real oldlogstdevgain = -1.0;
819 SCIP_Real oldlogmeangain = -1.0;
820
821 assert(branchruledata != NULL);
822
823 /* in the case of very large gains, SCIP will already prioritize this variable */
825 return SCIP_OKAY;
826
827 SCIP_Real meangain = sqrt((downgain + GEOMMEANSHIFT) * (upgain + GEOMMEANSHIFT)) - GEOMMEANSHIFT;
828 assert(SCIPisGE(scip, meangain, 0.0));
829
830 if(meangain < MINGAINTHRESHOLD)
831 {
832 branchruledata->nzerogains++;
833 return SCIP_OKAY;
834 }
835
836 branchruledata->currmeandualgain = ((SCIP_Real) branchruledata->currndualgains / (branchruledata->currndualgains + 1) ) * branchruledata->currmeandualgain + meangain / ( branchruledata->currndualgains + 1 ) ;
837
838 ++branchruledata->currndualgains;
839
840 if(branchruledata->currndualgains > 1)
841 {
842 oldlogstdevgain = branchruledata->logstdevgain;
843 oldlogmeangain = branchruledata->sumlogmeangains / (branchruledata->currndualgains - 1);
844 }
845
846 branchruledata->sumlogmeangains += log(meangain);
847 /* update the max mean gain */
848 logmeangain = branchruledata->sumlogmeangains / branchruledata->currndualgains;
849
850 int ngains = branchruledata->currndualgains;
851
852 if (ngains == 1)
853 branchruledata->logstdevgain = pow((log(meangain) - logmeangain), 2.0 );
854 else
855 branchruledata->logstdevgain = ( (ngains - 2) * oldlogstdevgain + (ngains - 1) * pow( oldlogmeangain - logmeangain, 2.0) + pow((log(meangain) - logmeangain), 2.0 ) ) / (ngains - 1) ;
856
857 branchruledata->maxmeangain = MAX(branchruledata->maxmeangain, meangain);
858 branchruledata->minmeangain = MIN(branchruledata->minmeangain, meangain);
859 SCIPdebugMsg(scip, " -> downgain: %g upgain: %g minmeangain: %g maxmeangain: %g mean-of-two: %g mean-of-%d-dual-gains: %g\n",downgain, upgain, branchruledata->minmeangain, branchruledata->maxmeangain, meangain, branchruledata->currndualgains, branchruledata->currmeandualgain);
860
861 return SCIP_OKAY;
862}
863
864/** compute the depth of the tree with the assumption that left and right dual gains are equal */
865static
867 SCIP_Real gap, /**< gap to be closed */
868 SCIP_Real maxmeangain /**< maximum mean gain of the branching candidates */
869 )
870{
871 assert(maxmeangain >= 0.0);
872 /* using an epsilon value if maxmeangain is zero */
873 SCIP_Real depth = ceil(gap / MAX(maxmeangain, MINGAINTHRESHOLD));
874 assert(depth > 0);
875 return depth;
876}
877
878/** compute the size of the tree with the assumption that left and right dual gains are equal */
879static
881 SCIP_Real estimatedepth /**< estimated depth of the tree */
882 )
883{
884 return pow(2.0, estimatedepth + 1.0) - 1.0;
885}
886
887/** calculate the cumulative distribution function (CDF) value for a mixture of a Dirac at zero and a continuous distribution (depending on distributioncdf) */
888static
890 SCIP_Real rate, /**< rate of the distribution */
891 SCIP_Real zeroprob, /**< probability of zero gain */
892 SCIP_Real proposedgain, /**< proposed gain */
893 SCIP_Real mingain, /**< minimum gain */
894 SCIP_Real logmeangain, /**< logarithm og mean gain */
895 SCIP_Real logstdevgain, /**< logarithm of standard deviation of gain */
896 int distributioncdf /**< distribution type (PARETODISTRIBUTION, EXPONENTIALDISTRIBUTION, LOGNORMALDISTRIBUTION) */
897 )
898{
899 if(distributioncdf == PARETODISTRIBUTION)
900 {
901 if (proposedgain < mingain)
902 return 0.0;
903 else
904 return zeroprob + (1.0 - zeroprob) * (1.0 - pow(mingain / proposedgain, rate));
905 }
906 else if(distributioncdf == EXPONENTIALDISTRIBUTION)
907 {
908 assert(rate >= 0.0);
909 return zeroprob + (1.0 - zeroprob) * (1.0 - exp(-rate * proposedgain));
910 }
911 else
912 {
913 assert(distributioncdf == LOGNORMALDISTRIBUTION);
914 return zeroprob + (1.0 - zeroprob) * 0.5 * erfc(-(log(proposedgain) - logmeangain) / (logstdevgain * sqrt(2.0)));
915 }
916}
917
918/** calculate the expected size of a tree with one more iteration of strong branching */
919static
921 SCIP* scip, /**< SCIP data structure */
922 SCIP_Real gap, /**< gap to be closed */
923 SCIP_Real zeroprob, /**< probability of zero gain */
924 SCIP_Real currentdepth, /**< current depth of the tree */
925 SCIP_Real lambda, /**< rate of the distribution */
926 SCIP_Real mingain, /**< minimum gain */
927 SCIP_Real logmeangain, /**< logarithm of mean gain */
928 SCIP_Real logstdevgain, /**< logarithm of standard deviation of gain */
929 int distributioncdf /**< distribution type (PARETODISTRIBUTION, EXPONENTIALDISTRIBUTION, LOGNORMALDISTRIBUTION) */
930 )
931{
932 SCIP_Real ptotal = 0.0;
933 SCIP_Real totalimprovedtree = 0.0;
934
935 int depth = (int) currentdepth;
936 SCIP_Real currenttreesize = strongBranchingTreeSize(currentdepth);
937 SCIP_Real nexttreesize;
938 SCIP_Real improvedtree;
939 if (depth == 1)
940 {
941 nexttreesize = currenttreesize;
942 }
943 /* compute the expected size with one more strong branching iteration */
944 else if (depth == 2)
945 {
946 /* Probability of finding a better variable that would reduce the depth (smaller tree size). */
947 SCIP_Real p = 1.0 - cdfProbability(lambda, zeroprob, gap, mingain, logmeangain, logstdevgain, distributioncdf);
948 SCIPdebugMsg(scip, " -> Probability of finding a better variable that would reduce the depth: %g\n", p);
949 /* Size of the improved tree. */
950 improvedtree = strongBranchingTreeSize(currentdepth - 1);
951 nexttreesize = improvedtree * p + strongBranchingTreeSize(currentdepth) * (1.0 - p) + 2.0;
952 if( p < MINGAINTHRESHOLD )
953 return SCIPinfinity(scip);
954 }
955 else
956 {
957 /* Probability of not finding a better variable that would reduce the depth of the tree (size of the tree). */
958 SCIP_Real pnotbetter = cdfProbability(lambda, zeroprob, (gap / (depth - 1)), mingain, logmeangain, logstdevgain, distributioncdf);
959 /* Probability of finding a better variable that would reduce the depth (smaller tree size). */
960 SCIP_Real pbetter = 1.0 - cdfProbability(lambda, zeroprob, gap / (depth - 1), mingain, logmeangain, logstdevgain, distributioncdf);
961 SCIPdebugMsg(scip, " -> Probability of finding a better variable that would reduce the depth: %g\n", pbetter);
962
963 if( pbetter < MINGAINTHRESHOLD )
964 return SCIPinfinity(scip);
965
966 SCIP_Real p;
967 p = 0.0;
968 while (pbetter >= MINGAINTHRESHOLD && ptotal + pnotbetter < 1.0)
969 {
970 if (depth > 2)
971 {
972 p = cdfProbability(lambda, zeroprob, gap / (depth - 2), mingain, logmeangain, logstdevgain, distributioncdf) - cdfProbability(lambda, zeroprob, gap / (depth - 1), mingain, logmeangain, logstdevgain, distributioncdf);
973 ptotal += p;
974 pbetter = 1.0 - cdfProbability(lambda, zeroprob, gap / (depth - 2), mingain, logmeangain, logstdevgain, distributioncdf);
975 }
976
977 else if (depth == 2)
978 {
979 p = 1.0 - cdfProbability(lambda, zeroprob, gap, mingain, logmeangain, logstdevgain, distributioncdf);
980 ptotal += p;
981 pbetter = 0.0;
982 }
983 if (ptotal + pnotbetter <= 1.0)
984 {
985 /* Compute expected size of the improved tree based on improved depth, considering the probability of this improvement. */
986 improvedtree = strongBranchingTreeSize(currentdepth - 1) * p;
987 }
988 else
989 improvedtree = 0.0;
990 depth--;
991 totalimprovedtree += improvedtree;
992 }
993 /* Compute the expectation of the next tree size with one more iteration of strong branching */
994 nexttreesize = totalimprovedtree + pnotbetter * strongBranchingTreeSize(currentdepth) + 2.0;
995 }
996 return nexttreesize;
997}
998
999/** decide if we continue strong branching based based on lookahead */
1000static
1002 SCIP* scip, /**< SCIP data structure */
1003 int candidx, /**< index of the branching candidate */
1004 int ninitcands, /**< number of initial candidates */
1005 SCIP_Real lookahead, /**< lookahead value */
1006 SCIP_Real maxlookahead, /**< maximum lookahead value */
1007 int nbdchgs, /**< number of bound changes found */
1008 int nbdconflicts, /**< number of bound conflicts found */
1009 int maxbdchgs, /**< maximal number of bound tightenings before the node is reevaluated */
1010 SCIP_Longint maxnsblpiterations /**< maximal number of strong branching LP iterations */
1011 )
1012{
1013 return candidx < ninitcands && lookahead < maxlookahead && nbdchgs + nbdconflicts < maxbdchgs
1014 && (candidx < (int) maxlookahead || SCIPgetNStrongbranchLPIterations(scip) < maxnsblpiterations);
1015}
1016
1017/** Decide if we continue strong branching based on the estimation of the tree size given the current gains. */
1018static
1020 SCIP* scip, /**< SCIP data structure */
1021 SCIP_BRANCHRULEDATA* branchruledata, /**< branching rule data */
1022 SCIP_Real lookahead, /**< lookahead value */
1023 SCIP_Real maxlookahead /**< maximum lookahead value */
1024 )
1025{
1026 SCIP_Real lambda;
1027 SCIP_Real maxmeangain;
1028 SCIP_Real minmeangain;
1029 SCIP_Real nexttreesize;
1030 SCIP_Real currentdepth;
1031 SCIP_Real currenttreesize;
1032 SCIP_Real absdualgap;
1033 SCIP_Real gaptoclose = -1.0;
1034
1035 /* default values never used */
1036 SCIP_Real logmeangain = 0.0;
1037 SCIP_Real logstdevgain = -1.0;
1038
1039 if (!branchruledata->dynamiclookahead)
1040 return TRUE;
1041
1042 /* compute the expected tree size after reaching a min lookahaead */
1043 if( lookahead < branchruledata->dynamiclookaheadquot * maxlookahead)
1044 return TRUE;
1045
1046 /* if we do not have a large enough sample to estimate the tree size we continue with strong branching */
1047 if ( branchruledata->currndualgains < branchruledata->minsamplesize )
1048 return TRUE;
1049
1050 maxmeangain = branchruledata->maxmeangain;
1051 minmeangain = branchruledata->minmeangain;
1052
1053 /* Compute the absolute gap at the current node. If no upper bound available we continue strong branching as usual */
1056 else
1057 absdualgap = SCIPinfinity(scip);
1058
1059 if( !SCIPisInfinity(scip, absdualgap) && !SCIPisInfinity(scip, maxmeangain) && SCIPisGT(scip, maxmeangain, 0.0) )
1060 gaptoclose = absdualgap;
1061 else
1062 return TRUE;
1063
1064 assert(gaptoclose >= 0.0);
1065 assert(!SCIPisInfinity(scip, -maxmeangain));
1066
1067 SCIP_Real zeroprob = (SCIP_Real) branchruledata->nzerogains / (branchruledata->nzerogains + branchruledata->currndualgains);
1068 if(branchruledata->dynamiclookdistribution == PARETODISTRIBUTION)
1069 {
1070 assert(minmeangain > 0.0);
1071 assert(branchruledata->currndualgains > 0);
1072 SCIP_Real sumlambda = branchruledata->sumlogmeangains - branchruledata->currndualgains * log(minmeangain);
1073 if(SCIPisZero(scip, sumlambda))
1074 return TRUE;
1075 lambda = branchruledata->currndualgains / sumlambda;
1076 }
1077 else if (branchruledata->dynamiclookdistribution == EXPONENTIALDISTRIBUTION)
1078 {
1079 lambda = 1 / (branchruledata->currmeandualgain);
1080 }
1081 else
1082 {
1083 assert(branchruledata->dynamiclookdistribution == LOGNORMALDISTRIBUTION);
1084 logmeangain = branchruledata->sumlogmeangains / branchruledata->currndualgains;
1085 logstdevgain = branchruledata->logstdevgain;
1086 /* lambda value not used */
1087 lambda = -1.0;
1088 }
1089
1090 /* Continue strong branching since we do not have good enough gains in this case */
1091 currentdepth = strongBranchingDepth(gaptoclose, maxmeangain); /*lint !e644*/
1092
1093 if (currentdepth >= 50)
1094 return TRUE;
1095
1096 /* Compute the tree size if we branch on the best variable so far, including the strong branching already done. */
1097 currenttreesize = strongBranchingTreeSize(currentdepth);
1098
1099 /* Compute the expected size of the tree with one more strong branching */
1100 nexttreesize = expectedTreeSize(scip, gaptoclose, zeroprob, currentdepth, lambda, minmeangain, logmeangain, logstdevgain, branchruledata->dynamiclookdistribution);
1101
1102 if(SCIPisLE(scip, nexttreesize, currenttreesize - 1.0))
1103 return TRUE;
1104
1105 SCIPdebugMsg(scip," -> Stopped at lookahead %g, current tree size %g, next tree size %g\n", lookahead, currenttreesize, nexttreesize);
1106 return FALSE;
1107}
1108
1109/** determine if strong branching is needed on the given candidate variable */
1110static
1112 SCIP* scip, /**< SCIP data structure */
1113 SCIP_BRANCHRULE* branchrule, /**< branching rule */
1114 SCIP_VAR* branchcand, /**< branching candidate */
1115 SCIP_Real branchcandfrac, /**< fractional part of the branching candidate */
1116 SCIP_VAR* bestpscand, /**< best candidate as per pscost score, must be present if usehyptestforreliability is used */
1117 SCIP_Real bestpscandfrac, /**< fractional part of the best candidate as per pscost score, must be present if usehyptestforreliability is used */
1118 SCIP_Real reliable, /**< size threshold for reliability */
1119 SCIP_Real relerrorthreshold, /**< relative error threshold for reliability */
1120 SCIP_CONFIDENCELEVEL clevel, /**< confidence level */
1121 SCIP_Bool useancpscost /**< check reliability for ancpscost as well */
1122 )
1123{ /*lint --e{715}*/
1124 SCIP_BRANCHRULEDATA* branchruledata;
1125 SCIP_Real pscostdownsize;
1126 SCIP_Real pscostupsize;
1127 SCIP_Real pscostsize;
1128 SCIP_Real dpscostdownsize;
1129 SCIP_Real dpscostupsize;
1130 SCIP_Real dpscostsize;
1131
1132 /* get branching rule data */
1133 branchruledata = SCIPbranchruleGetData(branchrule);
1134 assert(branchruledata != NULL);
1135
1136 /* check, if the pseudo cost score and the discounted pseudocost score of the variable is reliable */
1139 pscostsize = MIN(pscostdownsize, pscostupsize);
1142 dpscostsize = MIN(dpscostdownsize, dpscostupsize);
1143
1144 /* determine if variable is considered reliable based on the current reliability setting */
1145 /* check fixed number threshold (aka original) reliability first */
1146 assert(!branchruledata->usehyptestforreliability || bestpscand != NULL );
1147 if( pscostsize < reliable || ( useancpscost && dpscostsize < reliable ) )
1148 return TRUE;
1149 if( branchruledata->userelerrorforreliability && branchruledata->usehyptestforreliability )
1150 {
1151 if( !SCIPisVarPscostRelerrorReliable(scip, branchcand, relerrorthreshold, clevel) &&
1152 !SCIPsignificantVarPscostDifference(scip, bestpscand, bestpscandfrac,
1153 branchcand, branchcandfrac, SCIP_BRANCHDIR_DOWNWARDS, clevel, TRUE) &&
1154 !SCIPsignificantVarPscostDifference(scip, bestpscand, 1 - bestpscandfrac,
1155 branchcand, 1 - branchcandfrac, SCIP_BRANCHDIR_UPWARDS, clevel, TRUE) )
1156 return TRUE;
1157 }
1158 /* check if relative error is tolerable */
1159 if( branchruledata->userelerrorforreliability &&
1160 !SCIPisVarPscostRelerrorReliable(scip, branchcand, relerrorthreshold, clevel))
1161 return TRUE;
1162 /* check if best pseudo-candidate is significantly better in both directions, use strong-branching otherwise */
1163 if( branchruledata->usehyptestforreliability &&
1164 !SCIPsignificantVarPscostDifference(scip, bestpscand, bestpscandfrac,
1165 branchcand, branchcandfrac, SCIP_BRANCHDIR_DOWNWARDS, clevel, TRUE) &&
1166 !SCIPsignificantVarPscostDifference(scip, bestpscand, 1 - bestpscandfrac,
1167 branchcand, 1 - branchcandfrac, SCIP_BRANCHDIR_UPWARDS, clevel, TRUE) )
1168 return TRUE;
1169 return FALSE;
1170}
1171
1172/** execute reliability pseudo cost branching */
1173static
1175 SCIP* scip, /**< SCIP data structure */
1176 SCIP_BRANCHRULE* branchrule, /**< branching rule */
1177 SCIP_VAR** branchcands, /**< branching candidates */
1178 SCIP_Real* branchcandssol, /**< solution value for the branching candidates */
1179 SCIP_Real* branchcandsfrac, /**< fractional part of the branching candidates */
1180 int* branchorbitidx, /**< indices of orbit (or NULL) */
1181 int nbranchcands, /**< number of branching candidates */
1182 SCIP_Bool executebranch, /**< execute a branching step or run probing only */
1183 SCIP_RESULT* result /**< pointer to the result of the execution */
1184 )
1185{ /*lint --e{715}*/
1186 SCIP_BRANCHRULEDATA* branchruledata;
1187 SCIP_Real lpobjval;
1188 SCIP_Real bestsbdown;
1189 SCIP_Real bestsbup;
1190 SCIP_Real provedbound;
1191 SCIP_Bool bestsbdownvalid;
1192 SCIP_Bool bestsbupvalid;
1193 SCIP_Bool bestsbdowncutoff;
1194 SCIP_Bool bestsbupcutoff;
1195 SCIP_Bool bestisstrongbranch;
1196 SCIP_Bool allcolsinlp;
1197 SCIP_Bool exactsolve;
1198 int ninitcands;
1199 int bestcand;
1200
1201 /* remember which variables strong branching is performed on, and the
1202 * recorded lp bound changes that are observed */
1203 SCIP_Real* sbdown = NULL;
1204 SCIP_Real* sbup = NULL;
1205 SCIP_Bool* sbdownvalid = NULL;
1206 SCIP_Bool* sbupvalid = NULL;
1207
1208 *result = SCIP_DIDNOTRUN;
1209
1211
1212 /* get branching rule data */
1213 branchruledata = SCIPbranchruleGetData(branchrule);
1214 assert(branchruledata != NULL);
1215
1216 /* get current LP objective bound of the local sub problem and global cutoff bound */
1217 lpobjval = SCIPgetLPObjval(scip);
1218
1219 /* check, if we want to solve the problem exactly, meaning that strong branching information is not useful
1220 * for cutting off sub problems and improving lower bounds of children
1221 */
1222 exactsolve = SCIPisExact(scip);
1223
1224 /* check, if all existing columns are in LP, and thus the strong branching results give lower bounds */
1225 allcolsinlp = SCIPallColsInLP(scip);
1226
1227 bestcand = -1;
1228 bestisstrongbranch = FALSE;
1229 bestsbdown = SCIP_INVALID;
1230 bestsbup = SCIP_INVALID;
1231 bestsbdownvalid = FALSE;
1232 bestsbupvalid = FALSE;
1233 bestsbdowncutoff = FALSE;
1234 bestsbupcutoff = FALSE;
1235 provedbound = lpobjval;
1236
1237 /* Allocate memory to store the lp bounds of the up and down children
1238 * for those of the variables that we performed sb on
1239 */
1240 SCIP_CALL( SCIPallocBufferArray(scip, &sbdown, nbranchcands) );
1241 SCIP_CALL( SCIPallocBufferArray(scip, &sbup, nbranchcands) );
1242 SCIP_CALL( SCIPallocBufferArray(scip, &sbdownvalid, nbranchcands) );
1243 SCIP_CALL( SCIPallocBufferArray(scip, &sbupvalid, nbranchcands) );
1244
1245 if( nbranchcands == 1 )
1246 {
1247 /* only one candidate: nothing has to be done */
1248 bestcand = 0;
1249 SCIPdebug(ninitcands = 0);
1250 sbdownvalid[0] = FALSE;
1251 sbupvalid[0] = FALSE;
1252 }
1253 else
1254 {
1255 SCIP_VAR** vars;
1256 int* initcands;
1257 SCIP_Real* initcandscores;
1258 SCIP_Real* newlbs = NULL;
1259 SCIP_Real* newubs = NULL;
1260 SCIP_Real* mingains = NULL;
1261 SCIP_Real* maxgains = NULL;
1262 /* scores computed from pseudocost branching */
1263 SCIP_Real* scores = NULL;
1264 SCIP_Real* scoresfrompc = NULL;
1265 SCIP_Real* scoresfromothers = NULL;
1266 int* bdchginds;
1267 SCIP_BOUNDTYPE* bdchgtypes;
1268 SCIP_Real* bdchgbounds;
1269 int maxninitcands;
1270 int nuninitcands;
1271 int nbdchgs;
1272 int nbdconflicts;
1273 SCIP_Real avgconflictscore;
1274 SCIP_Real avgconflengthscore;
1275 SCIP_Real avginferencescore;
1276 SCIP_Real avgcutoffscore;
1277 SCIP_Real avgpscostscore;
1278 SCIP_Real avgdpscostscore;
1279 SCIP_Real bestpsscore;
1280 SCIP_Real bestpsfracscore;
1281 SCIP_Real bestpsdomainscore;
1282 SCIP_Real bestsbscore;
1283 SCIP_Real bestuninitsbscore;
1284 SCIP_Real bestsbfracscore;
1285 SCIP_Real bestsbdomainscore;
1286 SCIP_Real prio;
1287 SCIP_Real reliable;
1288 SCIP_Real maxlookahead;
1289 SCIP_Real lookahead;
1290 SCIP_Real relerrorthreshold;
1291 SCIP_Bool initstrongbranching;
1292 SCIP_Bool propagate;
1293 SCIP_Bool probingbounds;
1294 SCIP_Longint nodenum;
1295 SCIP_Longint nlpiterationsquot;
1296 SCIP_Longint nsblpiterations;
1297 SCIP_Longint maxnsblpiterations;
1298 int bestsolidx;
1299 int maxbdchgs;
1300 int bestpscand;
1301 int bestsbcand;
1302 int bestuninitsbcand;
1303 int inititer;
1304 int nvars;
1305 int i;
1306 int c;
1307 SCIP_CONFIDENCELEVEL clevel;
1308 SCIP_Real degeneracyfactor = 1.0;
1309 SCIP_Bool useancpscost;
1310
1311 SCIP_CALL( SCIPgetBoolParam(scip, "branching/collectancpscost", &useancpscost) );
1312
1313 /* get LP degeneracy information and compute a factor to change weighting of pseudo cost score vs. other scores */
1314 if( branchruledata->degeneracyaware > 0 && (SCIPgetDepth(scip) > 0 || branchruledata->degeneracyaware > 1) )
1315 {
1316 SCIP_Real degeneracy;
1317 SCIP_Real varconsratio;
1318
1319 /* get LP degeneracy information */
1320 SCIP_CALL( SCIPgetLPDualDegeneracy(scip, &degeneracy, &varconsratio) );
1321
1322 assert(degeneracy >= 0.0);
1323 assert(degeneracy <= 1.0);
1324 assert(varconsratio >= 1.0);
1325
1326 /* increase factor for a degeneracy >= 80% */
1327 if( degeneracy >= 0.8 )
1328 {
1329 degeneracy = 10.0 * (degeneracy - 0.7);
1330 degeneracyfactor = degeneracyfactor * pow(10.0,degeneracy);
1331 }
1332 /* increase factor for a variable-constraint ratio >= 2.0 */
1333 if( varconsratio >= 2.0 )
1334 {
1335 degeneracyfactor *= 10.0 * varconsratio;
1336 }
1337 }
1338
1339 vars = SCIPgetVars(scip);
1340 nvars = SCIPgetNVars(scip);
1341
1342 bestsolidx = SCIPgetBestSol(scip) == NULL ? -1 : SCIPsolGetIndex(SCIPgetBestSol(scip));
1343
1344 /* get average conflict, inference, and pseudocost scores */
1345 avgconflictscore = SCIPgetAvgConflictScore(scip);
1346 avgconflictscore = MAX(avgconflictscore, 0.1);
1347 avgconflengthscore = SCIPgetAvgConflictlengthScore(scip);
1348 avgconflengthscore = MAX(avgconflengthscore, 0.1);
1349 avginferencescore = SCIPgetAvgInferenceScore(scip);
1350 avginferencescore = MAX(avginferencescore, 0.1);
1351 avgcutoffscore = SCIPgetAvgCutoffScore(scip);
1352 avgcutoffscore = MAX(avgcutoffscore, 0.1);
1353 avgpscostscore = SCIPgetAvgPseudocostScore(scip);
1354 avgpscostscore = MAX(avgpscostscore, 0.1);
1355 avgdpscostscore = SCIPgetAvgDPseudocostScore(scip, branchruledata->discountfactor);
1356 avgdpscostscore = MAX(avgdpscostscore, 0.1);
1357
1358 /* get nonlinear counts according to parameters */
1359 SCIP_CALL( branchruledataEnsureNlcount(scip, branchruledata) );
1360
1361 initstrongbranching = FALSE;
1362
1363 /* check whether propagation should be performed */
1364 propagate = (branchruledata->maxproprounds != 0) && !SCIPisExact(scip);
1365
1366 /* check whether valid bounds should be identified in probing-like fashion */
1367 probingbounds = propagate && branchruledata->probingbounds;
1368
1369 /* get maximal number of candidates to initialize with strong branching; if the current solutions is not basic,
1370 * we cannot warmstart the simplex algorithm and therefore don't initialize any candidates
1371 */
1372 maxninitcands = MIN(nbranchcands, branchruledata->initcand);
1373 if( !SCIPisLPSolBasic(scip) )
1374 maxninitcands = 0;
1375
1376 /* calculate maximal number of strong branching LP iterations; if we used too many, don't apply strong branching
1377 * any more; also, if degeneracy is too high, don't run strong branching at this node
1378 */
1379 nlpiterationsquot = (SCIP_Longint)(branchruledata->sbiterquot * SCIPgetNNodeLPIterations(scip));
1380 maxnsblpiterations = nlpiterationsquot + branchruledata->sbiterofs + SCIPgetNRootStrongbranchLPIterations(scip);
1381 nsblpiterations = SCIPgetNStrongbranchLPIterations(scip);
1382 if( nsblpiterations > maxnsblpiterations || degeneracyfactor >= 10.0 )
1383 maxninitcands = 0;
1384
1385 /* get buffer for storing the unreliable candidates */
1386 SCIP_CALL( SCIPallocBufferArray(scip, &initcands, maxninitcands+1) ); /* allocate one additional slot for convenience */
1387 SCIP_CALL( SCIPallocBufferArray(scip, &initcandscores, maxninitcands+1) );
1388 ninitcands = 0;
1389
1390 /* Allocate memory for the down and up gains, and the computed pseudocost scores */
1391 SCIP_CALL( SCIPallocBufferArray(scip, &mingains, nbranchcands) );
1392 SCIP_CALL( SCIPallocBufferArray(scip, &maxgains, nbranchcands) );
1393 SCIP_CALL( SCIPallocBufferArray(scip, &scores, nbranchcands) );
1394 SCIP_CALL( SCIPallocBufferArray(scip, &scoresfrompc, nbranchcands) );
1395 SCIP_CALL( SCIPallocBufferArray(scip, &scoresfromothers, nbranchcands) );
1396
1397 /* get current node number */
1398 nodenum = SCIPgetNNodes(scip);
1399
1400 /* initialize bound change arrays */
1401 bdchginds = NULL;
1402 bdchgtypes = NULL;
1403 bdchgbounds = NULL;
1404 nbdchgs = 0;
1405 nbdconflicts = 0;
1406 maxbdchgs = branchruledata->maxbdchgs;
1407 if( maxbdchgs == -1 )
1408 maxbdchgs = INT_MAX;
1409
1410 /* calculate value used as reliability */
1411 prio = (maxnsblpiterations - nsblpiterations)/(nsblpiterations + 1.0);
1412 prio = MIN(prio, 1.0);
1413 prio = MAX(prio, (nlpiterationsquot - nsblpiterations)/(nsblpiterations + 1.0));
1414 reliable = (1.0-prio) * branchruledata->minreliable + prio * branchruledata->maxreliable;
1415
1416 /* calculate the threshold for the relative error in the same way; low tolerance is more strict than higher tolerance */
1417 relerrorthreshold = (1.0 - prio) * branchruledata->higherrortol + prio * branchruledata->lowerrortol;
1418
1419 clevel = (SCIP_CONFIDENCELEVEL)branchruledata->confidencelevel;
1420 /* determine the confidence level for hypothesis testing based on value of prio */
1421 if( branchruledata->usedynamicconfidence )
1422 {
1423 /* with decreasing priority, use a less strict confidence level */
1424 if( prio >= 0.9 )
1425 clevel = SCIP_CONFIDENCELEVEL_MAX;
1426 else if( prio >= 0.7 )
1428 else if( prio >= 0.5 )
1430 else if( prio >= 0.3 )
1431 clevel = SCIP_CONFIDENCELEVEL_LOW;
1432 else
1433 clevel = SCIP_CONFIDENCELEVEL_MIN;
1434 }
1435
1436 /* search for the best pseudo cost candidate, while remembering unreliable candidates in a sorted buffer */
1437 nuninitcands = 0;
1438 bestpscand = -1;
1439 bestpsscore = -SCIPinfinity(scip);
1440 bestpsfracscore = -SCIPinfinity(scip);
1441 bestpsdomainscore = -SCIPinfinity(scip);
1442
1443 /* search for the best candidate first */
1444 if( branchruledata->usehyptestforreliability )
1445 {
1446 for( c = 0; c < nbranchcands; ++c )
1447 {
1448 SCIP_Real conflictscore;
1449 SCIP_Real conflengthscore;
1450 SCIP_Real inferencescore;
1451 SCIP_Real cutoffscore;
1452 SCIP_Real gmieffscore;
1453 SCIP_Real lastgmieffscore;
1454 SCIP_Real pscostscore;
1455 SCIP_Real nlscore;
1456 SCIP_Real score;
1457
1458 conflictscore = SCIPgetVarConflictScore(scip, branchcands[c]);
1459 conflengthscore = SCIPgetVarConflictlengthScore(scip, branchcands[c]);
1460 inferencescore = SCIPgetVarAvgInferenceScore(scip, branchcands[c]);
1461 cutoffscore = SCIPgetVarAvgCutoffScore(scip, branchcands[c]);
1462 gmieffscore = SCIPgetVarAvgGMIScore(scip, branchcands[c]);
1463 lastgmieffscore = SCIPgetVarLastGMIScore(scip, branchcands[c]);
1464 nlscore = calcNlscore(scip, branchruledata->nlcount, branchruledata->nlcountmax, SCIPvarGetProbindex(branchcands[c]));
1465 pscostscore = SCIPgetVarPseudocostScore(scip, branchcands[c], branchcandssol[c]);
1466
1467 /* replace the pseudo cost score with the already calculated one;
1468 * @todo: use old data for strong branching with propagation?
1469 */
1470 if( SCIPgetVarStrongbranchNode(scip, branchcands[c]) == nodenum )
1471 {
1472 SCIP_Real down;
1473 SCIP_Real up;
1474 SCIP_Real lastlpobjval;
1475 SCIP_Real downgain;
1476 SCIP_Real upgain;
1477
1478 /* use the score of the strong branching call at the current node */
1479 SCIP_CALL( SCIPgetVarStrongbranchLast(scip, branchcands[c], &down, &up, NULL, NULL, NULL, &lastlpobjval) );
1480 downgain = MAX(down - lastlpobjval, 0.0);
1481 upgain = MAX(up - lastlpobjval, 0.0);
1482 if( useancpscost )
1483 {
1484 /* add discounted gains as stored in dpscost */
1485 SCIP_Real downsol;
1486 SCIP_Real upsol;
1487 downsol = SCIPfeasCeil(scip, branchcandssol[c]-1.0);
1488 upsol = SCIPfeasFloor(scip, branchcandssol[c]+1.0);
1489 downgain += branchruledata->discountfactor * SCIPgetVarAncPseudocostVal(scip, branchcands[c], downsol-branchcandssol[c]);
1490 upgain += branchruledata->discountfactor * SCIPgetVarAncPseudocostVal(scip, branchcands[c], upsol-branchcandssol[c]);
1491 downgain /= (1 + branchruledata->discountfactor);
1492 upgain /= (1 + branchruledata->discountfactor);
1493 }
1494 pscostscore = SCIPgetBranchScore(scip, branchcands[c], downgain, upgain);
1495
1496 SCIPdebugMsg(scip, " -> strong branching on variable <%s> already performed (down=%g (%+g), up=%g (%+g), pscostscore=%g)\n",
1497 SCIPvarGetName(branchcands[c]), down, downgain, up, upgain, pscostscore);
1498 }
1499
1500 score = calcScore(scip, branchruledata, conflictscore, avgconflictscore, conflengthscore, avgconflengthscore,
1501 inferencescore, avginferencescore, cutoffscore, avgcutoffscore, gmieffscore, lastgmieffscore,
1502 pscostscore, avgpscostscore, nlscore, branchcandsfrac[c], degeneracyfactor);
1503
1504 /* check for better score of candidate */
1505 if( SCIPisSumGE(scip, score, bestpsscore) )
1506 {
1507 SCIP_Real fracscore;
1508 SCIP_Real domainscore;
1509
1510 fracscore = MIN(branchcandsfrac[c], 1.0 - branchcandsfrac[c]);
1511 domainscore = -(SCIPvarGetUbLocal(branchcands[c]) - SCIPvarGetLbLocal(branchcands[c]));
1512 if( SCIPisSumGT(scip, score, bestpsscore)
1513 || SCIPisSumGT(scip, fracscore, bestpsfracscore)
1514 || (SCIPisSumGE(scip, fracscore, bestpsfracscore) && domainscore > bestpsdomainscore) )
1515 {
1516 bestpscand = c;
1517 bestpsscore = score;
1518 bestpsfracscore = fracscore;
1519 bestpsdomainscore = domainscore;
1520 }
1521 }
1522 }
1523 }
1524
1525 /* use discounted pseudocosts only if all candidates are reliable. */
1526 if( useancpscost && maxninitcands > 0 )
1527 {
1528 /* look for at least one unreliable candidate */
1529 for( c = 0; c < nbranchcands; ++c )
1530 {
1531 if( needsStrongBranching(scip, branchrule, branchcands[c], branchcandsfrac[c],
1532 bestpscand >= 0 ? branchcands[bestpscand] : NULL,
1533 bestpscand >= 0 ? branchcandsfrac[bestpscand] : 0.0,
1534 reliable, relerrorthreshold, clevel, useancpscost) )
1535 {
1536 useancpscost = FALSE;
1537 break;
1538 }
1539 }
1540 }
1541
1542 if( useancpscost )
1543 avgpscostscore = avgdpscostscore;
1544
1545 for( c = 0; c < nbranchcands; ++c )
1546 {
1547 SCIP_Real conflictscore;
1548 SCIP_Real conflengthscore;
1549 SCIP_Real inferencescore;
1550 SCIP_Real cutoffscore;
1551 SCIP_Real gmieffscore;
1552 SCIP_Real lastgmieffscore;
1553 SCIP_Real pscostscore;
1554 SCIP_Real nlscore;
1555 SCIP_Real score;
1556 SCIP_Bool usesb;
1557 SCIP_Real downgain;
1558 SCIP_Real upgain;
1559 SCIP_Real fracpart;
1560
1561 assert(branchcands[c] != NULL);
1562 assert(!SCIPisFeasIntegral(scip, branchcandssol[c]) || SCIPisExact(scip));
1563 assert(!SCIPisFeasIntegral(scip, SCIPvarGetLPSol(branchcands[c])) || SCIPisExact(scip));
1564
1565 /* Record the variables current pseudocosts. These may be overwritten if
1566 * strong branching is performed.
1567 */
1568 sbdownvalid[c] = FALSE;
1569 sbupvalid[c] = FALSE;
1570 fracpart = SCIPfeasFrac(scip, SCIPvarGetLPSol(branchcands[c]));
1571 downgain = SCIPgetVarPseudocostVal(scip, branchcands[c], 0.0 - fracpart);
1572 upgain = SCIPgetVarPseudocostVal(scip, branchcands[c], 1.0 - fracpart);
1573 mingains[c] = MIN(downgain, upgain);
1574 maxgains[c] = MAX(downgain, upgain);
1575
1576 /* get conflict, inference, cutoff, nonlinear, and pseudo cost scores for candidate */
1577 conflictscore = SCIPgetVarConflictScore(scip, branchcands[c]);
1578 conflengthscore = SCIPgetVarConflictlengthScore(scip, branchcands[c]);
1579 inferencescore = SCIPgetVarAvgInferenceScore(scip, branchcands[c]);
1580 cutoffscore = SCIPgetVarAvgCutoffScore(scip, branchcands[c]);
1581 gmieffscore = SCIPgetVarAvgGMIScore(scip, branchcands[c]);
1582 lastgmieffscore = SCIPgetVarLastGMIScore(scip, branchcands[c]);
1583 nlscore = calcNlscore(scip, branchruledata->nlcount, branchruledata->nlcountmax, SCIPvarGetProbindex(branchcands[c]));
1584 pscostscore = SCIPgetVarPseudocostScore(scip, branchcands[c], branchcandssol[c]);
1585 usesb = FALSE;
1586 if( useancpscost )
1587 pscostscore = SCIPgetVarDPseudocostScore(scip, branchcands[c], branchcandssol[c],branchruledata->discountfactor);
1588
1589 /* don't use strong branching on variables that have already been initialized at the current node;
1590 * instead replace the pseudo cost score with the already calculated one;
1591 * @todo: use old data for strong branching with propagation?
1592 */
1593 if( SCIPgetVarStrongbranchNode(scip, branchcands[c]) == nodenum )
1594 {
1595 SCIP_Real down;
1596 SCIP_Real up;
1597 SCIP_Real lastlpobjval;
1598
1599 /* use the score of the strong branching call at the current node */
1600 SCIP_CALL( SCIPgetVarStrongbranchLast(scip, branchcands[c], &down, &up, NULL, NULL, NULL, &lastlpobjval) );
1601 downgain = MAX(down - lastlpobjval, 0.0);
1602 upgain = MAX(up - lastlpobjval, 0.0);
1603 /* add discounted gains as stored in anspscost */
1604 if( useancpscost ) {
1605 /* the anspscost must be reliable here */
1606 SCIP_Real downsol;
1607 SCIP_Real upsol;
1608 downsol = SCIPfeasCeil(scip, branchcandssol[c]-1.0);
1609 upsol = SCIPfeasFloor(scip, branchcandssol[c]+1.0);
1610 downgain += branchruledata->discountfactor * SCIPgetVarAncPseudocostVal(scip, branchcands[c], downsol-branchcandssol[c]);
1611 upgain += branchruledata->discountfactor * SCIPgetVarAncPseudocostVal(scip, branchcands[c], upsol-branchcandssol[c]);
1612 downgain /= (1 + branchruledata->discountfactor);
1613 upgain /= (1 + branchruledata->discountfactor);
1614 }
1615 pscostscore = SCIPgetBranchScore(scip, branchcands[c], downgain, upgain);
1616
1617 mingains[c] = MIN(downgain, upgain);
1618 maxgains[c] = MAX(downgain, upgain);
1619
1620 if( branchruledata->dynamiclookahead )
1621 SCIP_CALL( updateMinMaxMeanGain(scip, branchrule, downgain, upgain) );
1622
1623 SCIPdebugMsg(scip, " -> strong branching on variable <%s> already performed (down=%g (%+g), up=%g (%+g), pscostscore=%g)\n",
1624 SCIPvarGetName(branchcands[c]), down, downgain, up, upgain, pscostscore);
1625 }
1626 else if( maxninitcands > 0 )
1627 {
1628 SCIP_Real downsize;
1629 SCIP_Real upsize;
1630 SCIP_Real size;
1631
1632 /* check, if the pseudo cost score of the variable is reliable */
1635 size = MIN(downsize, upsize);
1636
1637 usesb = needsStrongBranching(scip, branchrule, branchcands[c], branchcandsfrac[c],
1638 bestpscand >= 0 ? branchcands[bestpscand] : NULL,
1639 bestpscand >= 0 ? branchcandsfrac[bestpscand] : 0.0,
1640 reliable, relerrorthreshold, clevel, FALSE);
1641
1642 /* count the number of variables that are completely uninitialized */
1643 if( size < 0.1 )
1644 nuninitcands++;
1645 }
1646
1647 /* combine the five score values */
1648 scoresfrompc[c] = calcScore(scip, branchruledata, 0.0, avgconflictscore, 0.0, avgconflengthscore,
1649 0.0, avginferencescore, 0.0, avgcutoffscore, 0.0, 0.0,
1650 pscostscore, avgpscostscore, 0.0, branchcandsfrac[c], degeneracyfactor);
1651 scoresfromothers[c] = calcScore(scip, branchruledata, conflictscore, avgconflictscore, conflengthscore, avgconflengthscore,
1652 inferencescore, avginferencescore, cutoffscore, avgcutoffscore, gmieffscore, lastgmieffscore,
1653 0.0, avgpscostscore, nlscore, branchcandsfrac[c], degeneracyfactor);
1654 score = scoresfrompc[c] + scoresfromothers[c];
1655 scores[c] = score;
1656 /*score = calcScore(scip, branchruledata, conflictscore, avgconflictscore, conflengthscore, avgconflengthscore,
1657 inferencescore, avginferencescore, cutoffscore, avgcutoffscore, gmieffscore, lastgmieffscore,
1658 pscostscore, avgpscostscore, nlscore, branchcandsfrac[c], degeneracyfactor);*/
1659 if( usesb )
1660 {
1661 int j;
1662
1663 mingains[c] = 0;
1664 maxgains[c] = 0;
1665 scoresfrompc[c] = 0;
1666 scoresfromothers[c] = 0;
1667
1668 /* assign a random score to this uninitialized candidate */
1669 if( branchruledata->randinitorder )
1670 score += SCIPrandomGetReal(branchruledata->randnumgen, 0.0, 1e-4);
1671
1672 /* pseudo cost of variable is not reliable: insert candidate in initcands buffer */
1673 for( j = ninitcands; j > 0 && score > initcandscores[j-1]; --j )
1674 {
1675 initcands[j] = initcands[j-1];
1676 initcandscores[j] = initcandscores[j-1];
1677 }
1678 initcands[j] = c;
1679 initcandscores[j] = score;
1680 ninitcands++;
1681 ninitcands = MIN(ninitcands, maxninitcands);
1682 }
1683 /* in the case of hypothesis reliability, the best pseudo candidate has been determined already */
1684 else if( !branchruledata->usehyptestforreliability )
1685 {
1686 /* variable will keep its pseudo cost value: check for better score of candidate */
1687 if( SCIPisSumGE(scip, score, bestpsscore) )
1688 {
1689 SCIP_Real fracscore;
1690 SCIP_Real domainscore;
1691
1692 fracscore = MIN(branchcandsfrac[c], 1.0 - branchcandsfrac[c]);
1693 domainscore = -(SCIPvarGetUbLocal(branchcands[c]) - SCIPvarGetLbLocal(branchcands[c]));
1694 if( SCIPisSumGT(scip, score, bestpsscore)
1695 || SCIPisSumGT(scip, fracscore, bestpsfracscore)
1696 || (SCIPisSumGE(scip, fracscore, bestpsfracscore) && domainscore > bestpsdomainscore) )
1697 {
1698 bestpscand = c;
1699 bestpsscore = score;
1700 bestpsfracscore = fracscore;
1701 bestpsdomainscore = domainscore;
1702 }
1703 }
1704 }
1705 }
1706
1707 /* in the special case that only the best pseudo candidate was selected for strong branching, skip the strong branching */
1708 if( branchruledata->usehyptestforreliability && ninitcands == 1 )
1709 {
1710 ninitcands = 0;
1711 SCIPdebugMsg(scip, "Only one single candidate for initialization-->Skipping strong branching\n");
1712 }
1713
1714 /* initialize unreliable candidates with strong branching until maxlookahead is reached,
1715 * search best strong branching candidate
1716 */
1717 maxlookahead = (SCIP_Real)branchruledata->maxlookahead * (1.0 + (SCIP_Real)nuninitcands/(SCIP_Real)nbranchcands);
1718 inititer = branchruledata->inititer;
1719 if( inititer == 0 )
1720 {
1721 SCIP_Longint nlpiterations;
1722 SCIP_Longint nlps;
1723
1724 /* iteration limit is set to twice the average number of iterations spent to resolve a dual feasible SCIP_LP;
1725 * at the first few nodes, this average is not very exact, so we better increase the iteration limit on
1726 * these very important nodes
1727 */
1728 nlpiterations = SCIPgetNDualResolveLPIterations(scip);
1730 if( nlps == 0 )
1731 {
1732 nlpiterations = SCIPgetNNodeInitLPIterations(scip);
1733 nlps = SCIPgetNNodeInitLPs(scip);
1734 if( nlps == 0 )
1735 {
1736 nlpiterations = 1000;
1737 nlps = 1;
1738 }
1739 }
1740 assert(nlps >= 1);
1741 inititer = (int)(2*nlpiterations / nlps);
1742 inititer = (int)((SCIP_Real)inititer * (1.0 + 20.0/nodenum));
1743 inititer = MAX(inititer, 10);
1744 inititer = MIN(inititer, 500);
1745 }
1746
1747 SCIPdebugMsg(scip, "strong branching (reliable=%g, %d/%d cands, %d uninit, maxcands=%d, maxlookahead=%g, maxbdchgs=%d, inititer=%d, iterations:%" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", basic:%u)\n",
1748 reliable, ninitcands, nbranchcands, nuninitcands, maxninitcands, maxlookahead, maxbdchgs, inititer,
1750
1751 bestsbcand = -1;
1752 bestsbscore = -SCIPinfinity(scip);
1753 bestsbfracscore = -SCIPinfinity(scip);
1754 bestsbdomainscore = -SCIPinfinity(scip);
1755 bestuninitsbscore = -SCIPinfinity(scip);
1756 bestuninitsbcand = -1;
1757 lookahead = 0.0;
1758
1759 for( i = 0; continueStrongBranchingLookahead(scip, i, ninitcands, lookahead, maxlookahead, nbdchgs, nbdconflicts, maxbdchgs, maxnsblpiterations) && continueStrongBranchingTreeSizeEstimation(scip, branchruledata, lookahead, maxlookahead); ++i )
1760 {
1761 SCIP_Real down;
1762 SCIP_Real up;
1763 SCIP_Real downgain;
1764 SCIP_Real upgain;
1765 SCIP_Bool downvalid;
1766 SCIP_Bool upvalid;
1767 SCIP_Longint ndomredsdown;
1768 SCIP_Longint ndomredsup;
1769 SCIP_Bool lperror;
1770 SCIP_Bool downinf;
1771 SCIP_Bool upinf;
1772 SCIP_Bool downconflict;
1773 SCIP_Bool upconflict;
1774
1775 /* get candidate number to initialize */
1776 c = initcands[i];
1777 assert(!SCIPisFeasIntegral(scip, branchcandssol[c]) || SCIPisExact(scip));
1778
1779 if( branchruledata->skipbadinitcands )
1780 {
1781 SCIP_Bool skipsb = FALSE;
1782 /* if the current best candidate is a candidate found by strong branching, determine if candidate pseudo-costs are
1783 * significantly smaller in at least one direction, in which case we safe the execution of strong-branching for now
1784 */
1785 if( bestsbscore > bestpsscore && bestsbscore > bestuninitsbscore && bestsbupvalid && bestsbdownvalid )
1786 {
1787 assert(bestsbcand != -1);
1788 assert(bestsbup != SCIP_INVALID && bestsbdown != SCIP_INVALID); /*lint !e777 lint doesn't like comparing floats */
1789
1790 /* test if the variable is unlikely to produce a better gain than the currently best one. Skip strong-branching
1791 * in such a case
1792 */
1793 if( SCIPpscostThresholdProbabilityTest(scip, branchcands[c], branchcandsfrac[c], bestsbdown,
1795 || SCIPpscostThresholdProbabilityTest(scip, branchcands[c], 1.0 - branchcandsfrac[c], bestsbup,
1796 SCIP_BRANCHDIR_UPWARDS, clevel) )
1797 skipsb = TRUE;
1798 }
1799 /* the currently best candidate is also a pseudo-candidate; apply significance test and skip candidate if it
1800 * is significantly worse in at least one direction
1801 */
1802 else if( bestpscand != -1 && bestpsscore > bestuninitsbscore )
1803 {
1804 if( SCIPsignificantVarPscostDifference(scip, branchcands[bestpscand], branchcandsfrac[bestpscand],
1805 branchcands[c], branchcandsfrac[c], SCIP_BRANCHDIR_DOWNWARDS, clevel, TRUE)
1806 || SCIPsignificantVarPscostDifference(scip, branchcands[bestpscand], 1.0 - branchcandsfrac[bestpscand],
1807 branchcands[c], 1.0 - branchcandsfrac[c], SCIP_BRANCHDIR_UPWARDS, clevel, TRUE) )
1808 skipsb = TRUE;
1809 }
1810 /* compare against the best init cand that has been skipped already */
1811 else if( bestuninitsbcand != -1 )
1812 {
1813 if( SCIPsignificantVarPscostDifference(scip, branchcands[bestuninitsbcand], branchcandsfrac[bestuninitsbcand],
1814 branchcands[c], branchcandsfrac[c], SCIP_BRANCHDIR_DOWNWARDS, clevel, TRUE)
1815 || SCIPsignificantVarPscostDifference(scip, branchcands[bestuninitsbcand], 1.0 - branchcandsfrac[bestuninitsbcand],
1816 branchcands[c], 1.0 - branchcandsfrac[c], SCIP_BRANCHDIR_UPWARDS, clevel, TRUE) )
1817 skipsb = TRUE;
1818 }
1819
1820 /* skip candidate, update the best score of an unitialized candidate */
1821 if( skipsb )
1822 {
1823 if( bestuninitsbcand == -1 )
1824 {
1825 bestuninitsbcand = c;
1826 bestuninitsbscore = initcandscores[i];
1827 }
1828 continue;
1829 }
1830 }
1831 SCIPdebugMsg(scip, "init pseudo cost (%g/%g) of <%s> at %g (score:%g) with strong branching (%d iterations) -- %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT " iterations\n",
1834 SCIPvarGetName(branchcands[c]), branchcandssol[c], initcandscores[i],
1835 inititer, SCIPgetNStrongbranchLPIterations(scip), maxnsblpiterations);
1836
1837 /* use strong branching on candidate */
1838 if( !initstrongbranching )
1839 {
1840 initstrongbranching = TRUE;
1841
1842 SCIP_CALL( SCIPstartStrongbranch(scip, propagate) );
1843
1844 /* create arrays for probing-like bound tightening */
1845 if( probingbounds )
1846 {
1847 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &newlbs, nvars) );
1848 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &newubs, nvars) );
1849 }
1850 }
1851
1852 if( propagate )
1853 {
1854 /* apply strong branching */
1855 SCIP_CALL( SCIPgetVarStrongbranchWithPropagation(scip, branchcands[c], branchcandssol[c], lpobjval, inititer,
1856 branchruledata->maxproprounds, &down, &up, &downvalid, &upvalid, &ndomredsdown, &ndomredsup, &downinf, &upinf,
1857 &downconflict, &upconflict, &lperror, newlbs, newubs) );
1858 }
1859 else
1860 {
1861 /* apply strong branching */
1862 SCIP_CALL( SCIPgetVarStrongbranchFrac(scip, branchcands[c], inititer, FALSE,
1863 &down, &up, &downvalid, &upvalid, &downinf, &upinf, &downconflict, &upconflict, &lperror) );
1864
1865 ndomredsdown = ndomredsup = 0;
1866 }
1867
1868 /* check for an error in strong branching */
1869 if( lperror )
1870 {
1871 if( !SCIPisStopped(scip) )
1872 {
1874 "(node %" SCIP_LONGINT_FORMAT ") error in strong branching call for variable <%s> with solution %g\n",
1875 SCIPgetNNodes(scip), SCIPvarGetName(branchcands[c]), branchcandssol[c]);
1876 }
1877 break;
1878 }
1879
1880 /* Strong branching might have found a new primal solution which updated the cutoff bound. In this case, the
1881 * provedbound computed before can be higher than the cutoffbound and the current node can be cut off.
1882 * Additionally, also if the value for the current best candidate is valid and exceeds the new cutoff bound,
1883 * we want to change the domain of this variable rather than branching on it.
1884 */
1885 if( SCIPgetBestSol(scip) != NULL && SCIPsolGetIndex(SCIPgetBestSol(scip)) != bestsolidx )
1886 {
1887 bestsolidx = SCIPsolGetIndex(SCIPgetBestSol(scip));
1888
1889 SCIPdebugMsg(scip, " -> strong branching on variable <%s> lead to a new incumbent\n",
1890 SCIPvarGetName(branchcands[c]));
1891
1892 /* proved bound for current node is larger than new cutoff bound -> cut off current node */
1893 if( SCIPisGE(scip, provedbound, SCIPgetCutoffbound(scip)) )
1894 {
1895 SCIPdebugMsg(scip, " -> node can be cut off (provedbound=%g, cutoff=%g)\n", provedbound, SCIPgetCutoffbound(scip));
1896
1897 *result = SCIP_CUTOFF;
1898 break; /* terminate initialization loop, because node is infeasible */
1899 }
1900 /* proved bound for down child of best candidate is larger than cutoff bound
1901 * -> increase lower bound of best candidate
1902 * we must only do this if the LP is complete, i.e., we are not doing column generation
1903 */
1904
1905 else if( bestsbcand != -1 && allcolsinlp )
1906 {
1907 if( !bestsbdowncutoff && bestsbdownvalid && SCIPisGE(scip, bestsbdown, SCIPgetCutoffbound(scip)) )
1908 {
1909 bestsbdowncutoff = TRUE;
1910
1911 SCIPdebugMsg(scip, " -> valid dual bound for down child of best candidate <%s> is higher than new cutoff bound (valid=%u, bestsbdown=%g, cutoff=%g)\n",
1912 SCIPvarGetName(branchcands[bestsbcand]), bestsbdownvalid, bestsbdown, SCIPgetCutoffbound(scip));
1913
1914 SCIPdebugMsg(scip, " -> increase lower bound of best candidate <%s> to %g\n",
1915 SCIPvarGetName(branchcands[bestsbcand]), SCIPfeasCeil(scip, branchcandssol[bestsbcand]));
1916
1917 SCIP_CALL( addBdchg(scip, &bdchginds, &bdchgtypes, &bdchgbounds, &nbdchgs, SCIPvarGetProbindex(branchcands[bestsbcand]),
1918 SCIP_BOUNDTYPE_LOWER, SCIPfeasCeil(scip, branchcandssol[bestsbcand])) );
1919 }
1920 /* proved bound for up child of best candidate is larger than cutoff bound -> decrease upper bound of best candidate */
1921 else if( !bestsbupcutoff && bestsbupvalid && SCIPisGE(scip, bestsbup, SCIPgetCutoffbound(scip)) )
1922 {
1923 bestsbupcutoff = TRUE;
1924
1925 SCIPdebugMsg(scip, " -> valid dual bound for up child of best candidate <%s> is higher than new cutoff bound (valid=%u, bestsbup=%g, cutoff=%g)\n",
1926 SCIPvarGetName(branchcands[bestsbcand]), bestsbupvalid, bestsbup, SCIPgetCutoffbound(scip));
1927
1928 SCIPdebugMsg(scip, " -> decrease upper bound of best candidate <%s> to %g\n",
1929 SCIPvarGetName(branchcands[bestsbcand]), SCIPfeasFloor(scip, branchcandssol[bestsbcand]));
1930
1931 SCIP_CALL( addBdchg(scip, &bdchginds, &bdchgtypes, &bdchgbounds, &nbdchgs, SCIPvarGetProbindex(branchcands[bestsbcand]),
1932 SCIP_BOUNDTYPE_UPPER, SCIPfeasFloor(scip, branchcandssol[bestsbcand])) );
1933 }
1934 }
1935 }
1936
1937 /* evaluate strong branching */
1938 down = MAX(down, lpobjval);
1939 up = MAX(up, lpobjval);
1940 downgain = down - lpobjval;
1941 upgain = up - lpobjval;
1942 assert(!useancpscost);
1943 assert(!allcolsinlp || exactsolve || !downvalid || downinf == SCIPisGE(scip, down, SCIPgetCutoffbound(scip)));
1944 assert(!allcolsinlp || exactsolve || !upvalid || upinf == SCIPisGE(scip, up, SCIPgetCutoffbound(scip)));
1945 assert(downinf || !downconflict);
1946 assert(upinf || !upconflict);
1947
1948 if( branchruledata->dynamiclookahead )
1949 SCIP_CALL( updateMinMaxMeanGain(scip, branchrule, downgain, upgain) );
1950
1951 /* @todo: store pseudo cost only for valid bounds?
1952 * depending on the user parameter choice of storesemiinitcosts, pseudo costs are also updated in single directions,
1953 * if the node in the other direction was infeasible or cut off
1954 */
1955 if( !downinf
1956#ifdef WITH_LPSOLSTAT
1958#endif
1959 && (!upinf || branchruledata->storesemiinitcosts) )
1960 {
1961 SCIP_Real weight;
1962
1963 /* smaller weights are given if the strong branching hit the time limit in the corresponding direction */
1964 if( branchruledata->usesmallweightsitlim )
1966 else
1967 weight = 1.0;
1968
1969 /* update pseudo cost values */
1970 SCIP_CALL( SCIPupdateVarPseudocostSymmetric(scip, branchruledata, branchcands[c], branchorbitidx, c, 0.0 - branchcandsfrac[c], downgain, weight) );
1971 }
1972 if( !upinf
1973#ifdef WITH_LPSOLSTAT
1975#endif
1976 && (!downinf || branchruledata->storesemiinitcosts) )
1977 {
1978 SCIP_Real weight;
1979
1980 /* smaller weights are given if the strong branching hit the time limit in the corresponding direction */
1981 if( branchruledata->usesmallweightsitlim )
1983 else
1984 weight = 1.0;
1985
1986 /* update pseudo cost values */
1987 SCIP_CALL( SCIPupdateVarPseudocostSymmetric(scip, branchruledata, branchcands[c], branchorbitidx, c, 1.0 - branchcandsfrac[c], upgain, weight) );
1988 }
1989
1990 /* the minimal lower bound of both children is a proved lower bound of the current subtree */
1991 if( allcolsinlp && !exactsolve && downvalid && upvalid )
1992 {
1993 SCIP_Real minbound;
1994
1995 minbound = MIN(down, up);
1996 provedbound = MAX(provedbound, minbound);
1997 assert((downinf && upinf) || SCIPisLT(scip, provedbound, SCIPgetCutoffbound(scip)));
1998
1999 /* save probing-like bounds detected during strong branching */
2000 if( probingbounds && ( !downinf || !upinf ) )
2001 {
2002 int v;
2003
2004 assert(newlbs != NULL);
2005 assert(newubs != NULL);
2006
2007 for( v = 0; v < nvars; ++v )
2008 {
2009 if( SCIPisGT(scip, newlbs[v], SCIPvarGetLbLocal(vars[v])) )
2010 {
2011 SCIPdebugMsg(scip, "better lower bound for variable <%s>: %.9g -> %.9g (by strongbranching on <%s>)\n",
2012 SCIPvarGetName(vars[v]), SCIPvarGetLbLocal(vars[v]), newlbs[v], SCIPvarGetName(branchcands[c]));
2013
2014 SCIP_CALL( addBdchg(scip, &bdchginds, &bdchgtypes, &bdchgbounds, &nbdchgs, v,
2015 SCIP_BOUNDTYPE_LOWER, newlbs[v]) );
2016 }
2017 if( SCIPisLT(scip, newubs[v], SCIPvarGetUbLocal(vars[v])) )
2018 {
2019 SCIPdebugMsg(scip, "better upper bound for variable <%s>: %.9g -> %.9g (by strongbranching on <%s>)\n",
2020 SCIPvarGetName(vars[v]), SCIPvarGetUbLocal(vars[v]), newubs[v], SCIPvarGetName(branchcands[c]));
2021
2022 SCIP_CALL( addBdchg(scip, &bdchginds, &bdchgtypes, &bdchgbounds, &nbdchgs, v,
2023 SCIP_BOUNDTYPE_UPPER, newubs[v]) );
2024 }
2025 }
2026 }
2027 }
2028
2029 /* check if there are infeasible roundings */
2030 if( (downinf || upinf) && !exactsolve )
2031 {
2032 assert(allcolsinlp || propagate);
2033
2034 if( downinf && upinf )
2035 {
2036 /* both roundings are infeasible -> node is infeasible */
2037 SCIPdebugMsg(scip, " -> variable <%s> is infeasible in both directions (conflict: %u/%u)\n",
2038 SCIPvarGetName(branchcands[c]), downconflict, upconflict);
2039 *result = SCIP_CUTOFF;
2040 break; /* terminate initialization loop, because node is infeasible */
2041 }
2042 else
2043 {
2044 /* rounding is infeasible in one direction -> round variable in other direction */
2045 SCIPdebugMsg(scip, " -> variable <%s> is infeasible in %s branch (conflict: %u/%u)\n",
2046 SCIPvarGetName(branchcands[c]), downinf ? "downward" : "upward", downconflict, upconflict);
2047 SCIP_CALL( addBdchg(scip, &bdchginds, &bdchgtypes, &bdchgbounds, &nbdchgs, SCIPvarGetProbindex(branchcands[c]),
2049 (downinf ? SCIPfeasCeil(scip, branchcandssol[c]) : SCIPfeasFloor(scip, branchcandssol[c]))) );
2050 if( nbdchgs + nbdconflicts >= maxbdchgs )
2051 break; /* terminate initialization loop, because enough roundings are performed */
2052 }
2053 }
2054 else
2055 {
2056 SCIP_Real conflictscore;
2057 SCIP_Real conflengthscore;
2058 SCIP_Real inferencescore;
2059 SCIP_Real cutoffscore;
2060 SCIP_Real gmieffscore;
2061 SCIP_Real lastgmieffscore;
2062 SCIP_Real pscostscore;
2063 SCIP_Real nlscore;
2064 SCIP_Real score;
2065
2066 mingains[c] = MIN(downgain, upgain);
2067 maxgains[c] = MAX(downgain, upgain);
2068
2069 sbdown[c] = down;
2070 sbup[c] = up;
2071 sbdownvalid[c] = downvalid;
2072 sbupvalid[c] = upvalid;
2073
2074 /* check for a better score */
2075 conflictscore = SCIPgetVarConflictScore(scip, branchcands[c]);
2076 conflengthscore = SCIPgetVarConflictlengthScore(scip, branchcands[c]);
2077 nlscore = calcNlscore(scip, branchruledata->nlcount, branchruledata->nlcountmax, SCIPvarGetProbindex(branchcands[c]));
2078
2079 /* optionally, use only local information obtained via strong branching for this candidate, i.e., local
2080 * domain reductions and no cutoff score
2081 */
2082 inferencescore = branchruledata->usesblocalinfo ? SCIPgetBranchScore(scip, branchcands[c], (SCIP_Real)ndomredsdown, (SCIP_Real)ndomredsup)
2083 : SCIPgetVarAvgInferenceScore(scip, branchcands[c]);
2084 cutoffscore = branchruledata->usesblocalinfo ? 0.0 : SCIPgetVarAvgCutoffScore(scip, branchcands[c]);
2085 gmieffscore = branchruledata->usesblocalinfo ? 0.0 : SCIPgetVarAvgGMIScore(scip, branchcands[c]);
2086 lastgmieffscore = branchruledata->usesblocalinfo ? 0.0 : SCIPgetVarLastGMIScore(scip, branchcands[c]);
2087 pscostscore = SCIPgetBranchScore(scip, branchcands[c], downgain, upgain);
2088
2089 scoresfrompc[c] = calcScore(scip, branchruledata, 0.0, avgconflictscore, 0.0, avgconflengthscore,
2090 0.0, avginferencescore, 0.0, avgcutoffscore, 0.0, 0.0, pscostscore,
2091 avgpscostscore, 0.0, branchcandsfrac[c], degeneracyfactor);
2092 scoresfromothers[c] = calcScore(scip, branchruledata, conflictscore, avgconflictscore, conflengthscore, avgconflengthscore,
2093 inferencescore, avginferencescore, cutoffscore, avgcutoffscore, gmieffscore,
2094 lastgmieffscore, 0.0, avgpscostscore, nlscore, branchcandsfrac[c],
2095 degeneracyfactor);
2096 score = scoresfrompc[c] + scoresfromothers[c];
2097 scores[c] = score;
2098 /*score = calcScore(scip, branchruledata, conflictscore, avgconflictscore, conflengthscore, avgconflengthscore,
2099 inferencescore, avginferencescore, cutoffscore, avgcutoffscore, gmieffscore, lastgmieffscore,
2100 pscostscore, avgpscostscore, nlscore, branchcandsfrac[c], degeneracyfactor);*/
2101
2102 if( SCIPisSumGE(scip, score, bestsbscore) )
2103 {
2104 SCIP_Real fracscore;
2105 SCIP_Real domainscore;
2106
2107 fracscore = MIN(branchcandsfrac[c], 1.0 - branchcandsfrac[c]);
2108 domainscore = -(SCIPvarGetUbLocal(branchcands[c]) - SCIPvarGetLbLocal(branchcands[c]));
2109 if( SCIPisSumGT(scip, score, bestsbscore)
2110 || SCIPisSumGT(scip, fracscore, bestsbfracscore)
2111 || (SCIPisSumGE(scip, fracscore, bestsbfracscore) && domainscore > bestsbdomainscore) )
2112 {
2113 bestsbcand = c;
2114 bestsbscore = score;
2115 bestsbdown = down;
2116 bestsbup = up;
2117 bestsbdownvalid = downvalid;
2118 bestsbupvalid = upvalid;
2119 bestsbdowncutoff = FALSE;
2120 bestsbupcutoff = FALSE;
2121 bestsbfracscore = fracscore;
2122 bestsbdomainscore = domainscore;
2123 lookahead = 0.0;
2124 }
2125 else
2126 lookahead += 0.5;
2127 }
2128 else
2129 lookahead += 1.0;
2130
2131 SCIPdebugMsg(scip, " -> variable <%s> (solval=%g, down=%g (%+g,valid=%u), up=%g (%+g,valid=%u), score=%g/ %g/%g %g/%g %g -> %g)\n",
2132 SCIPvarGetName(branchcands[c]), branchcandssol[c], down, downgain, downvalid, up, upgain, upvalid,
2133 pscostscore, conflictscore, conflengthscore, inferencescore, cutoffscore, gmieffscore, score);
2134 }
2135 }
2136#ifdef SCIP_DEBUG
2137 if( bestsbcand >= 0 )
2138 {
2139 SCIPdebugMsg(scip, " -> best: <%s> (%g / %g / %g), lookahead=%g/%g\n",
2140 SCIPvarGetName(branchcands[bestsbcand]), bestsbscore, bestsbfracscore, bestsbdomainscore,
2141 lookahead, maxlookahead);
2142 }
2143#endif
2144
2145 if( initstrongbranching )
2146 {
2147 if( probingbounds )
2148 {
2149 assert(newlbs != NULL);
2150 assert(newubs != NULL);
2151
2152 SCIPfreeBlockMemoryArray(scip, &newubs, nvars);
2153 SCIPfreeBlockMemoryArray(scip, &newlbs, nvars);
2154 }
2155
2157
2159 {
2160 assert(SCIPhasCurrentNodeLP(scip));
2161 *result = SCIP_CUTOFF;
2162 }
2163 }
2164
2165 if( *result != SCIP_CUTOFF )
2166 {
2167 /* get the score of the best uninitialized strong branching candidate */
2168 if( i < ninitcands && bestuninitsbcand == -1 )
2169 bestuninitsbscore = initcandscores[i];
2170
2171 /* if the best pseudo cost candidate is better than the best uninitialized strong branching candidate,
2172 * compare it to the best initialized strong branching candidate
2173 */
2174 if( bestpsscore > bestuninitsbscore && SCIPisSumGT(scip, bestpsscore, bestsbscore) )
2175 {
2176 bestcand = bestpscand;
2177 bestisstrongbranch = FALSE;
2178 }
2179 else if( bestsbcand >= 0 )
2180 {
2181 bestcand = bestsbcand;
2182 bestisstrongbranch = TRUE;
2183 }
2184 else
2185 {
2186 /* no candidate was initialized, and the best score is the one of the first candidate in the initialization
2187 * queue
2188 */
2189 assert(ninitcands >= 1);
2190 bestcand = initcands[0];
2191 bestisstrongbranch = FALSE;
2192 }
2193
2194 /* update lower bound of current node */
2195 if( allcolsinlp && !exactsolve )
2196 {
2197 assert(SCIPisLT(scip, provedbound, SCIPgetCutoffbound(scip)));
2198 SCIP_CALL( SCIPupdateLocalLowerbound(scip, provedbound) );
2199 assert(SCIPisGE(scip, SCIPgetLocalLowerbound(scip), provedbound));
2200 }
2201 }
2202
2203 /* apply domain reductions */
2204 if( nbdchgs > 0 )
2205 {
2206 if( *result != SCIP_CUTOFF )
2207 {
2208 SCIP_CALL( applyBdchgs(scip, vars, bdchginds, bdchgtypes, bdchgbounds, nbdchgs, result) );
2209 if( *result != SCIP_CUTOFF )
2210 *result = SCIP_REDUCEDDOM;
2211 }
2212 freeBdchgs(scip, &bdchginds, &bdchgtypes, &bdchgbounds, &nbdchgs);
2213 }
2214
2215 /* Apply the Treemodel branching rule to potentially select a better branching candidate than the current one. */
2216 if( *result != SCIP_CUTOFF && *result != SCIP_REDUCEDDOM && *result != SCIP_CONSADDED && SCIPtreemodelIsEnabled(scip, branchruledata->treemodel) )
2217 {
2218 SCIP_Real smallpscost;
2219 SCIP_Bool usetreemodel;
2220
2221 usetreemodel = TRUE;
2222
2223 /* If the pseudocosts are zero, use SCIPs best variable since the Treemodel is not applicable */
2224 if( SCIPisZero(scip, maxgains[bestcand]))
2225 {
2226 usetreemodel = FALSE;
2227 }
2228
2229 /* If SCIPs best candidate was selected due to hybrid branching scores
2230 * rather than because of pseudocosts, then we keep it.
2231 */
2232 SCIP_CALL( SCIPgetRealParam(scip, "branching/treemodel/smallpscost", &smallpscost) );
2233 if( usetreemodel == TRUE && avgpscostscore <= smallpscost )
2234 {
2235 int cand;
2236 for( cand = 0; cand < nbranchcands; ++cand )
2237 {
2238 if( scoresfrompc[cand] > scoresfrompc[bestcand] )
2239 {
2240 usetreemodel = FALSE;
2241 break;
2242 }
2243 }
2244 }
2245
2246 if( usetreemodel == TRUE )
2247 {
2249 scip, /* SCIP data structure */
2250 branchruledata->treemodel, /* branching rule */
2251 branchcands, /* branching candidate storage */
2252 mingains, /* minimum gain of rounding downwards or upwards */
2253 maxgains, /* maximum gain of rounding downwards or upwards */
2254 scoresfromothers, /* scores from other branching methods */
2255 nbranchcands, /* the number of branching candidates */
2256 &bestcand /* the best branching candidate found by SCIP */
2257 ) );
2258 }
2259 }
2260
2261 /* free buffer for the lp gains and pseudocost scores */
2262 SCIPfreeBufferArray(scip, &scoresfromothers);
2263 SCIPfreeBufferArray(scip, &scoresfrompc);
2264 SCIPfreeBufferArray(scip, &scores);
2265 SCIPfreeBufferArray(scip, &maxgains);
2266 SCIPfreeBufferArray(scip, &mingains);
2267
2268 /* free buffer for the unreliable candidates */
2269 SCIPfreeBufferArray(scip, &initcandscores);
2270 SCIPfreeBufferArray(scip, &initcands);
2271 }
2272
2273 /* if no domain could be reduced, create the branching */
2274 if( *result != SCIP_CUTOFF && *result != SCIP_REDUCEDDOM && *result != SCIP_CONSADDED && executebranch )
2275 {
2276 SCIP_NODE* downchild;
2277 SCIP_NODE* upchild;
2278 SCIP_VAR* var;
2279 SCIP_Real val;
2280
2281 assert(*result == SCIP_DIDNOTRUN);
2282 assert(0 <= bestcand && bestcand < nbranchcands);
2283 assert(!SCIPisFeasIntegral(scip, branchcandssol[bestcand]));
2284 assert(!allcolsinlp || SCIPisLT(scip, provedbound, SCIPgetCutoffbound(scip)) || exactsolve);
2285 assert(!bestsbdowncutoff && !bestsbupcutoff);
2286
2287 var = branchcands[bestcand];
2288 val = branchcandssol[bestcand];
2289
2290 /* perform the branching */
2291 SCIPdebugMsg(scip, " -> %d (%d) cands, sel cand %d: var <%s> (sol=%g, down=%g (%+g), up=%g (%+g), sb=%u, psc=%g/%g [%g])\n",
2292 nbranchcands, ninitcands, bestcand, SCIPvarGetName(var), branchcandssol[bestcand],
2293 bestsbdown, bestsbdown - lpobjval, bestsbup, bestsbup - lpobjval, bestisstrongbranch,
2296 SCIPgetVarPseudocostScoreCurrentRun(scip, var, branchcandssol[bestcand]));
2297 SCIP_UNUSED(bestisstrongbranch);
2298 SCIP_CALL( SCIPbranchVarVal(scip, var, val, &downchild, NULL, &upchild) );
2299 assert(downchild != NULL);
2300 assert(upchild != NULL);
2301
2302 /* update the lower bounds in the children */
2303 if( allcolsinlp && !exactsolve )
2304 {
2305 if( sbdownvalid[bestcand] )
2306 {
2307 assert(SCIPisLT(scip, sbdown[bestcand], SCIPgetCutoffbound(scip)));
2308 SCIP_CALL( SCIPupdateNodeLowerbound(scip, downchild, sbdown[bestcand]) );
2309 assert(SCIPisGE(scip, SCIPgetNodeLowerbound(scip, downchild), provedbound));
2310 }
2311 if( sbupvalid[bestcand] )
2312 {
2313 assert(SCIPisLT(scip, sbup[bestcand], SCIPgetCutoffbound(scip)));
2314 SCIP_CALL( SCIPupdateNodeLowerbound(scip, upchild, sbup[bestcand]) );
2315 assert(SCIPisGE(scip, SCIPgetNodeLowerbound(scip, upchild), provedbound));
2316 }
2317 }
2318
2319 SCIPdebugMsg(scip, " -> down child's lowerbound: %g\n", SCIPnodeGetLowerbound(downchild));
2320 SCIPdebugMsg(scip, " -> up child's lowerbound : %g\n", SCIPnodeGetLowerbound(upchild));
2321
2323
2324 *result = SCIP_BRANCHED;
2325 }
2326
2327 /* free buffer for the strong branching lp gains */
2328 SCIPfreeBufferArray(scip, &sbupvalid);
2329 SCIPfreeBufferArray(scip, &sbdownvalid);
2330 SCIPfreeBufferArray(scip, &sbup);
2331 SCIPfreeBufferArray(scip, &sbdown);
2332
2333 return SCIP_OKAY;
2334}
2335
2336
2337/*
2338 * Callback methods
2339 */
2340
2341/** copy method for branchrule plugins (called when SCIP copies plugins) */
2342static
2343SCIP_DECL_BRANCHCOPY(branchCopyRelpscost)
2344{ /*lint --e{715}*/
2345 assert(scip != NULL);
2346 assert(branchrule != NULL);
2347 assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
2348
2349 /* call inclusion method of branchrule */
2351
2352 return SCIP_OKAY;
2353}
2354
2355/** destructor of branching rule to free user data (called when SCIP is exiting) */
2356static
2357SCIP_DECL_BRANCHFREE(branchFreeRelpscost)
2358{ /*lint --e{715}*/
2359 SCIP_BRANCHRULEDATA* branchruledata;
2360 branchruledata = SCIPbranchruleGetData(branchrule);
2361
2362 /* free Treemodel parameter data structure */
2363 SCIP_CALL( SCIPtreemodelFree(scip, &branchruledata->treemodel) );
2364
2365 /* free branching rule data */
2366 SCIPfreeBlockMemory(scip, &branchruledata);
2367 SCIPbranchruleSetData(branchrule, NULL);
2368
2369 return SCIP_OKAY;
2370}
2371
2372
2373/** solving process initialization method of branching rule (called when branch and bound process is about to begin) */
2374static
2375SCIP_DECL_BRANCHINITSOL(branchInitsolRelpscost)
2376{ /*lint --e{715}*/
2377 SCIP_BRANCHRULEDATA* branchruledata;
2378
2379 /* initialize branching rule data */
2380 branchruledata = SCIPbranchruleGetData(branchrule);
2381 branchruledata->nlcount = NULL;
2382 branchruledata->nlcountsize = 0;
2383 branchruledata->nlcountmax = 1;
2384 assert(branchruledata->startrandseed >= 0);
2385
2386 /* create a random number generator */
2387 SCIP_CALL( SCIPcreateRandom(scip, &branchruledata->randnumgen,
2388 (unsigned int)branchruledata->startrandseed, TRUE) );
2389
2390 return SCIP_OKAY;
2391}
2392
2393
2394/** solving process deinitialization method of branching rule (called before branch and bound process data is freed) */
2395static
2396SCIP_DECL_BRANCHEXITSOL(branchExitsolRelpscost)
2397{ /*lint --e{715}*/
2398 SCIP_BRANCHRULEDATA* branchruledata;
2399
2400 /* free memory in branching rule data */
2401 branchruledata = SCIPbranchruleGetData(branchrule);
2402 SCIPfreeBlockMemoryArrayNull(scip, &branchruledata->nlcount, branchruledata->nlcountsize);
2403
2404 /* free random number generator */
2405 SCIPfreeRandom(scip, &branchruledata->randnumgen);
2406
2407 SCIPfreeBlockMemoryArrayNull(scip, &branchruledata->orbitrep, branchruledata->npermvars);
2408 SCIPfreeBlockMemoryArrayNull(scip, &branchruledata->varorbitmap, branchruledata->npermvars);
2409 SCIPfreeBlockMemoryArrayNull(scip, &branchruledata->orbitbegins, branchruledata->npermvars);
2410 SCIPfreeBlockMemoryArrayNull(scip, &branchruledata->orbits, branchruledata->npermvars);
2411 branchruledata->nosymmetry = FALSE;
2412 branchruledata->norbits = 0;
2413 branchruledata->permvars = NULL;
2414 branchruledata->permvarmap = NULL;
2415 branchruledata->npermvars = 0;
2416
2417 return SCIP_OKAY;
2418}
2419
2420
2421/** branching execution method for fractional LP solutions */
2422static
2423SCIP_DECL_BRANCHEXECLP(branchExeclpRelpscost)
2424{ /*lint --e{715}*/
2425 SCIP_BRANCHRULEDATA* branchruledata;
2426 SCIP_VAR** lpcands;
2427 SCIP_Real* lpcandssol;
2428 SCIP_Real* lpcandsfrac;
2429 SCIP_VAR** filteredlpcands;
2430 SCIP_Real* filteredlpcandssol;
2431 SCIP_Real* filteredlpcandsfrac;
2432 SCIP_Bool runfiltering;
2433 int* filteredlpcandsorbitidx = NULL;
2434 int nfilteredlpcands;
2435 int nlpcands;
2436
2437 assert(branchrule != NULL);
2438 assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
2439 assert(scip != NULL);
2440 assert(result != NULL);
2441
2442 SCIPdebugMsg(scip, "Execlp method of relpscost branching in node %" SCIP_LONGINT_FORMAT "\n", SCIPnodeGetNumber(SCIPgetCurrentNode(scip)));
2443
2445 {
2446 *result = SCIP_DIDNOTRUN;
2447 SCIPdebugMsg(scip, "Could not apply relpscost branching, as the current LP was not solved to optimality.\n");
2448
2449 return SCIP_OKAY;
2450 }
2451
2452 /* get branching candidates */
2453 SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, &lpcandssol, &lpcandsfrac, NULL, &nlpcands, NULL) );
2454 assert(nlpcands > 0);
2455
2456 branchruledata = SCIPbranchruleGetData(branchrule);
2457 assert(branchruledata != NULL);
2458
2459 branchruledata->maxmeangain = -SCIPinfinity(scip);
2460 branchruledata->minmeangain = SCIPinfinity(scip);
2461 branchruledata->sumlogmeangains = 0.0;
2462 branchruledata->logstdevgain = 0.0;
2463 branchruledata->nzerogains = 0;
2464
2465 /* determine whether we should run filtering */
2466 runfiltering = ! branchruledata->nosymmetry && branchruledata->filtercandssym && SCIPgetSubscipDepth(scip) == 0 && ! SCIPinDive(scip) && ! SCIPinProbing(scip);
2467
2468 /* init orbits if necessary */
2469 if( runfiltering )
2470 {
2471 SCIP_CALL( initOrbits(scip, branchruledata) );
2472 }
2473
2474 /* determine fractional variables (possibly filter by using symmetries) */
2475 if( runfiltering && branchruledata->norbits != 0 )
2476 {
2477 SCIP_CALL( SCIPallocBufferArray(scip, &filteredlpcands, nlpcands) );
2478 SCIP_CALL( SCIPallocBufferArray(scip, &filteredlpcandssol, nlpcands) );
2479 SCIP_CALL( SCIPallocBufferArray(scip, &filteredlpcandsfrac, nlpcands) );
2480 SCIP_CALL( SCIPallocBufferArray(scip, &filteredlpcandsorbitidx, nlpcands) );
2481
2482 /* determine filtered fractional variables */
2483 SCIP_CALL( filterSymmetricVariables(scip, branchruledata, lpcands, lpcandssol, lpcandsfrac, nlpcands,
2484 filteredlpcands, filteredlpcandssol, filteredlpcandsfrac, filteredlpcandsorbitidx, &nfilteredlpcands) );
2485 }
2486 else
2487 {
2488 /* No orbits available. Copy all (unfiltered) branching candidates, because they will be updated w.r.t. the strong branching LP solution */
2489 SCIP_CALL( SCIPduplicateBufferArray(scip, &filteredlpcands, lpcands, nlpcands) );
2490 SCIP_CALL( SCIPduplicateBufferArray(scip, &filteredlpcandssol, lpcandssol, nlpcands) );
2491 SCIP_CALL( SCIPduplicateBufferArray(scip, &filteredlpcandsfrac, lpcandsfrac, nlpcands) );
2492 nfilteredlpcands = nlpcands;
2493 }
2494
2495 /* execute branching rule */
2496 SCIP_CALL( execRelpscost(scip, branchrule, filteredlpcands, filteredlpcandssol, filteredlpcandsfrac, filteredlpcandsorbitidx, nfilteredlpcands, TRUE, result) );
2497
2498 SCIPfreeBufferArrayNull(scip, &filteredlpcandsorbitidx);
2499 SCIPfreeBufferArray(scip, &filteredlpcandsfrac);
2500 SCIPfreeBufferArray(scip, &filteredlpcandssol);
2501 SCIPfreeBufferArray(scip, &filteredlpcands);
2502
2503 return SCIP_OKAY;
2504}
2505
2506
2507/*
2508 * branching specific interface methods
2509 */
2510
2511/** creates the reliable pseudo cost branching rule and includes it in SCIP */
2513 SCIP* scip /**< SCIP data structure */
2514 )
2515{
2516 SCIP_BRANCHRULEDATA* branchruledata;
2517 SCIP_BRANCHRULE* branchrule;
2518
2519 /* create relpscost branching rule data */
2520 SCIP_CALL( SCIPallocBlockMemory(scip, &branchruledata) );
2521
2522 branchruledata->nosymmetry = FALSE;
2523 branchruledata->orbits = NULL;
2524 branchruledata->orbitbegins = NULL;
2525 branchruledata->orbitrep = NULL;
2526 branchruledata->varorbitmap = NULL;
2527 branchruledata->norbits = 0;
2528 branchruledata->permvars = NULL;
2529 branchruledata->npermvars = 0;
2530 branchruledata->permvarmap = NULL;
2531 branchruledata->meandualgain = 0.0;
2532 branchruledata->currmeandualgain = 0.0;
2533 branchruledata->currndualgains = 0;
2534 branchruledata->maxmeangain = -SCIPinfinity(scip);
2535 branchruledata->minmeangain = SCIPinfinity(scip);
2536 branchruledata->sumlogmeangains = 0.0;
2537 branchruledata->logstdevgain = 0.0;
2538 branchruledata->nzerogains = 0;
2539
2540 /* include branching rule */
2542 BRANCHRULE_MAXDEPTH, BRANCHRULE_MAXBOUNDDIST, branchruledata) );
2543
2544 assert(branchrule != NULL);
2545
2546 /* set non-fundamental callbacks via specific setter functions*/
2547 SCIP_CALL( SCIPsetBranchruleCopy(scip, branchrule, branchCopyRelpscost) );
2548 SCIP_CALL( SCIPsetBranchruleFree(scip, branchrule, branchFreeRelpscost) );
2549 SCIP_CALL( SCIPsetBranchruleInitsol(scip, branchrule, branchInitsolRelpscost) );
2550 SCIP_CALL( SCIPsetBranchruleExitsol(scip, branchrule, branchExitsolRelpscost) );
2551 SCIP_CALL( SCIPsetBranchruleExecLp(scip, branchrule, branchExeclpRelpscost) );
2552
2553 /* relpscost branching rule parameters */
2555 "branching/relpscost/conflictweight",
2556 "weight in score calculations for conflict score",
2557 &branchruledata->conflictweight, TRUE, DEFAULT_CONFLICTWEIGHT, SCIP_REAL_MIN, SCIP_REAL_MAX, NULL, NULL) );
2559 "branching/relpscost/conflictlengthweight",
2560 "weight in score calculations for conflict length score",
2561 &branchruledata->conflengthweight, TRUE, DEFAULT_CONFLENGTHWEIGHT, SCIP_REAL_MIN, SCIP_REAL_MAX, NULL, NULL) );
2563 "branching/relpscost/inferenceweight",
2564 "weight in score calculations for inference score",
2565 &branchruledata->inferenceweight, TRUE, DEFAULT_INFERENCEWEIGHT, SCIP_REAL_MIN, SCIP_REAL_MAX, NULL, NULL) );
2567 "branching/relpscost/cutoffweight",
2568 "weight in score calculations for cutoff score",
2569 &branchruledata->cutoffweight, TRUE, DEFAULT_CUTOFFWEIGHT, SCIP_REAL_MIN, SCIP_REAL_MAX, NULL, NULL) );
2571 "branching/relpscost/gmiavgeffweight",
2572 "weight in score calculations for average GMI cuts normalized efficacy",
2573 &branchruledata->gmiavgeffweight, TRUE, DEFAULT_GMIAVGEFFWEIGHT, SCIP_REAL_MIN, SCIP_REAL_MAX, NULL, NULL) );
2575 "branching/relpscost/gmilasteffweight",
2576 "weight in score calculations for last GMI cuts normalized efficacy",
2577 &branchruledata->gmilasteffweight, TRUE, DEFAULT_GMILASTEFFWEIGHT, SCIP_REAL_MIN, SCIP_REAL_MAX, NULL, NULL) );
2579 "branching/relpscost/pscostweight",
2580 "weight in score calculations for pseudo cost score",
2581 &branchruledata->pscostweight, TRUE, DEFAULT_PSCOSTWEIGHT, SCIP_REAL_MIN, SCIP_REAL_MAX, NULL, NULL) );
2583 "branching/relpscost/nlscoreweight",
2584 "weight in score calculations for nlcount score",
2585 &branchruledata->nlscoreweight, TRUE, DEFAULT_NLSCOREWEIGHT, SCIP_REAL_MIN, SCIP_REAL_MAX, NULL, NULL) );
2587 "branching/relpscost/minreliable",
2588 "minimal value for minimum pseudo cost size to regard pseudo cost value as reliable",
2589 &branchruledata->minreliable, TRUE, DEFAULT_MINRELIABLE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
2591 "branching/relpscost/maxreliable",
2592 "maximal value for minimum pseudo cost size to regard pseudo cost value as reliable",
2593 &branchruledata->maxreliable, TRUE, DEFAULT_MAXRELIABLE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
2595 "branching/relpscost/sbiterquot",
2596 "maximal fraction of strong branching LP iterations compared to node relaxation LP iterations",
2597 &branchruledata->sbiterquot, FALSE, DEFAULT_SBITERQUOT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
2599 "branching/relpscost/dynamiclookaheadquot",
2600 "apply dynamic lookahead after this fraction maxlookahead is reached",
2601 &branchruledata->dynamiclookaheadquot, TRUE, DEFAULT_DYNAMICLOOKAHEADQUOT , 0.0, 1.0, NULL, NULL) );
2603 "branching/relpscost/sbiterofs",
2604 "additional number of allowed strong branching LP iterations",
2605 &branchruledata->sbiterofs, FALSE, DEFAULT_SBITEROFS, 0, INT_MAX, NULL, NULL) );
2607 "branching/relpscost/maxlookahead",
2608 "maximal number of further variables evaluated without better score",
2609 &branchruledata->maxlookahead, TRUE, DEFAULT_MAXLOOKAHEAD, 1, INT_MAX, NULL, NULL) );
2610 SCIP_CALL( SCIPaddBoolParam(scip, "branching/relpscost/dynamiclookahead",
2611 "should we use a dynamic lookahead based on a tree size estimation of further strong branchings?",
2612 &branchruledata->dynamiclookahead, TRUE, DEFAULT_DYNAMICLOOKAHEAD, NULL, NULL) );
2614 "branching/relpscost/initcand",
2615 "maximal number of candidates initialized with strong branching per node",
2616 &branchruledata->initcand, FALSE, DEFAULT_INITCAND, 0, INT_MAX, NULL, NULL) );
2617 SCIP_CALL( SCIPaddIntParam(scip, "branching/relpscost/dynamiclookdistribution",
2618 "which distribution should be used for dynamic lookahead? 0=exponential, 1=Pareto, 2=log-normal?",
2619 &branchruledata->dynamiclookdistribution, TRUE, DEFAULT_DYNAMICLOOKDISTRIBUTION, EXPONENTIALDISTRIBUTION, LOGNORMALDISTRIBUTION, NULL, NULL) );
2621 "branching/relpscost/inititer",
2622 "iteration limit for strong branching initializations of pseudo cost entries (0: auto)",
2623 &branchruledata->inititer, FALSE, DEFAULT_INITITER, 0, INT_MAX, NULL, NULL) );
2625 "branching/relpscost/maxbdchgs",
2626 "maximal number of bound tightenings before the node is reevaluated (-1: unlimited)",
2627 &branchruledata->maxbdchgs, TRUE, DEFAULT_MAXBDCHGS, -1, INT_MAX, NULL, NULL) );
2629 "branching/relpscost/maxproprounds",
2630 "maximum number of propagation rounds to be performed during strong branching before solving the LP (-1: no limit, -2: parameter settings)",
2631 &branchruledata->maxproprounds, TRUE, SCIPisExact(scip) ? 0 : DEFAULT_MAXPROPROUNDS, -2, INT_MAX, NULL, NULL) );
2633 "branching/relpscost/probingbounds",
2634 "should valid bounds be identified in a probing-like fashion during strong branching (only with propagation)?",
2635 &branchruledata->probingbounds, TRUE, DEFAULT_PROBINGBOUNDS, NULL, NULL) );
2636
2637 SCIP_CALL( SCIPaddBoolParam(scip, "branching/relpscost/userelerrorreliability",
2638 "should reliability be based on relative errors?", &branchruledata->userelerrorforreliability, TRUE, DEFAULT_USERELERRORFORRELIABILITY,
2639 NULL, NULL) );
2640
2641 SCIP_CALL( SCIPaddRealParam(scip, "branching/relpscost/lowerrortol", "low relative error tolerance for reliability",
2642 &branchruledata->lowerrortol, TRUE, DEFAULT_LOWERRORTOL, 0.0, SCIP_REAL_MAX, NULL, NULL) );
2643
2644 SCIP_CALL( SCIPaddRealParam(scip, "branching/relpscost/higherrortol", "high relative error tolerance for reliability",
2645 &branchruledata->higherrortol, TRUE, DEFAULT_HIGHERRORTOL, 0.0, SCIP_REAL_MAX, NULL, NULL) );
2646
2647/**! [SnippetCodeStyleParenIndent] */
2648
2649 SCIP_CALL( SCIPaddBoolParam(scip, "branching/relpscost/storesemiinitcosts",
2650 "should strong branching result be considered for pseudo costs if the other direction was infeasible?",
2651 &branchruledata->storesemiinitcosts, TRUE, DEFAULT_STORESEMIINITCOSTS,
2652 NULL, NULL) );
2653
2654/**! [SnippetCodeStyleParenIndent] */
2655
2656 SCIP_CALL( SCIPaddBoolParam(scip, "branching/relpscost/usesblocalinfo",
2657 "should the scoring function use only local cutoff and inference information obtained for strong branching candidates?",
2658 &branchruledata->usesblocalinfo, TRUE, DEFAULT_USESBLOCALINFO,
2659 NULL, NULL) );
2660
2661 SCIP_CALL( SCIPaddBoolParam(scip, "branching/relpscost/usehyptestforreliability",
2662 "should the strong branching decision be based on a hypothesis test?",
2663 &branchruledata->usehyptestforreliability, TRUE, DEFAULT_USEHYPTESTFORRELIABILITY,
2664 NULL, NULL) );
2665
2666 SCIP_CALL( SCIPaddBoolParam(scip, "branching/relpscost/usedynamicconfidence",
2667 "should the confidence level be adjusted dynamically?",
2668 &branchruledata->usedynamicconfidence, TRUE, DEFAULT_USEDYNAMICCONFIDENCE,
2669 NULL, NULL) );
2670 SCIP_CALL( SCIPaddBoolParam(scip, "branching/relpscost/skipbadinitcands",
2671 "should branching rule skip candidates that have a low probability to "
2672 "be better than the best strong-branching or pseudo-candidate?",
2673 &branchruledata->skipbadinitcands, TRUE, DEFAULT_SKIPBADINITCANDS,
2674 NULL, NULL) );
2676 "branching/relpscost/confidencelevel",
2677 "the confidence level for statistical methods, between 0 (Min) and 4 (Max).",
2678 &branchruledata->confidencelevel, TRUE, DEFAULT_CONFIDENCELEVEL, 0, 4, NULL, NULL) );
2679
2680 SCIP_CALL( SCIPaddBoolParam(scip, "branching/relpscost/randinitorder",
2681 "should candidates be initialized in randomized order?",
2682 &branchruledata->randinitorder, TRUE, DEFAULT_RANDINITORDER,
2683 NULL, NULL) );
2684
2685 SCIP_CALL( SCIPaddBoolParam(scip, "branching/relpscost/usesmallweightsitlim",
2686 "should smaller weights be used for pseudo cost updates after hitting the LP iteration limit?",
2687 &branchruledata->usesmallweightsitlim, TRUE, DEFAULT_USESMALLWEIGHTSITLIM,
2688 NULL, NULL) );
2689
2690 SCIP_CALL( SCIPaddBoolParam(scip, "branching/relpscost/dynamicweights",
2691 "should the weights of the branching rule be adjusted dynamically during solving based on objective and infeasible leaf counters?",
2692 &branchruledata->dynamicweights, TRUE, DEFAULT_DYNAMICWEIGHTS,
2693 NULL, NULL) );
2694 SCIP_CALL( SCIPaddIntParam(scip, "branching/relpscost/degeneracyaware",
2695 "should degeneracy be taken into account to update weights and skip strong branching? (0: off, 1: after root, 2: always)",
2696 &branchruledata->degeneracyaware, TRUE, DEFAULT_DEGENERACYAWARE, 0, 2,
2697 NULL, NULL) );
2698 SCIP_CALL( SCIPaddIntParam(scip, "branching/relpscost/startrandseed", "start seed for random number generation",
2699 &branchruledata->startrandseed, TRUE, DEFAULT_STARTRANDSEED, 0, INT_MAX, NULL, NULL) );
2700 SCIP_CALL( SCIPaddIntParam(scip, "branching/relpscost/minsamplesize",
2701 "minimum sample size to estimate the tree size for dynamic lookahead",
2702 &branchruledata->minsamplesize, TRUE, DEFAULT_MINSAMPLESIZE, 0, INT_MAX, NULL, NULL) );
2703 SCIP_CALL( SCIPaddBoolParam(scip, "branching/relpscost/filtercandssym",
2704 "Use symmetry to filter branching candidates?",
2705 &branchruledata->filtercandssym, TRUE, DEFAULT_FILTERCANDSSYM, NULL, NULL) );
2706
2707 SCIP_CALL( SCIPaddBoolParam(scip, "branching/relpscost/transsympscost",
2708 "Transfer pscost information to symmetric variables?",
2709 &branchruledata->transsympscost, TRUE, DEFAULT_TRANSSYMPSCOST, NULL, NULL) );
2710
2711 SCIP_CALL( SCIPaddRealParam(scip, "branching/" BRANCHRULE_NAME "/discountfactor",
2712 "discount factor for ancestral pseudo costs (0.0: disable discounted pseudo costs)",
2713 &branchruledata->discountfactor, FALSE, BRANCHRULE_DISCOUNTFACTOR, 0.0, 1.0, NULL, NULL) );
2714
2715 /* relpcost is safe to use in exact solving mode */
2716 SCIPbranchruleMarkExact(branchrule);
2717
2718 /* initialise the Treemodel parameters */
2719 SCIP_CALL( SCIPtreemodelInit(scip, &branchruledata->treemodel) );
2720
2721 return SCIP_OKAY;
2722}
2723
2724/** execution reliability pseudo cost branching with the given branching candidates */
2726 SCIP* scip, /**< SCIP data structure */
2727 SCIP_VAR** branchcands, /**< branching candidates */
2728 SCIP_Real* branchcandssol, /**< solution value for the branching candidates */
2729 SCIP_Real* branchcandsfrac, /**< fractional part of the branching candidates */
2730 int nbranchcands, /**< number of branching candidates */
2731 SCIP_Bool executebranching, /**< perform a branching step after probing */
2732 SCIP_RESULT* result /**< pointer to the result of the execution */
2733 )
2734{
2735 SCIP_BRANCHRULE* branchrule;
2736
2737 assert(scip != NULL);
2738 assert(result != NULL);
2739
2740 /* find branching rule */
2742 assert(branchrule != NULL);
2743
2744 /* execute branching rule */
2745 SCIP_CALL( execRelpscost(scip, branchrule, branchcands, branchcandssol, branchcandsfrac, NULL, nbranchcands, executebranching, result) );
2746
2747 return SCIP_OKAY;
2748}
static long bound
#define BRANCHRULE_DESC
#define DEFAULT_DEGENERACYAWARE
#define DEFAULT_USESBLOCALINFO
#define DEFAULT_SKIPBADINITCANDS
#define DEFAULT_SBITERQUOT
#define LOGNORMALDISTRIBUTION
static SCIP_Real strongBranchingTreeSize(SCIP_Real estimatedepth)
static SCIP_Real calcNlscore(SCIP *scip, int *nlcount, int nlcountmax, int probindex)
#define DEFAULT_HIGHERRORTOL
#define BRANCHRULE_PRIORITY
#define DEFAULT_PROBINGBOUNDS
#define BRANCHRULE_DISCOUNTFACTOR
#define DEFAULT_INITITER
static SCIP_Real expectedTreeSize(SCIP *scip, SCIP_Real gap, SCIP_Real zeroprob, SCIP_Real currentdepth, SCIP_Real lambda, SCIP_Real mingain, SCIP_Real logmeangain, SCIP_Real logstdevgain, int distributioncdf)
#define DEFAULT_USESMALLWEIGHTSITLIM
#define DEFAULT_DYNAMICLOOKAHEADQUOT
static SCIP_RETCODE applyBdchgs(SCIP *scip, SCIP_VAR **vars, int *bdchginds, SCIP_BOUNDTYPE *bdchgtypes, SCIP_Real *bdchgbounds, int nbdchgs, SCIP_RESULT *result)
static SCIP_Real cdfProbability(SCIP_Real rate, SCIP_Real zeroprob, SCIP_Real proposedgain, SCIP_Real mingain, SCIP_Real logmeangain, SCIP_Real logstdevgain, int distributioncdf)
#define DEFAULT_STARTRANDSEED
#define MINGAINTHRESHOLD
#define DEFAULT_FILTERCANDSSYM
#define MAXGAINTHRESHOLD
#define DEFAULT_USEDYNAMICCONFIDENCE
#define DEFAULT_DYNAMICWEIGHTS
#define DEFAULT_MAXBDCHGS
#define DEFAULT_USEHYPTESTFORRELIABILITY
#define DEFAULT_GMIAVGEFFWEIGHT
#define GEOMMEANSHIFT
static SCIP_RETCODE SCIPupdateVarPseudocostSymmetric(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata, SCIP_VAR *branchvar, int *branchorbitidx, int branchvaridx, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
#define DEFAULT_INFERENCEWEIGHT
#define BRANCHRULE_NAME
#define DEFAULT_RANDINITORDER
static SCIP_RETCODE initOrbits(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata)
#define DEFAULT_MAXLOOKAHEAD
#define DEFAULT_SBITEROFS
static SCIP_DECL_BRANCHFREE(branchFreeRelpscost)
#define DEFAULT_NLSCOREWEIGHT
#define DEFAULT_CONFLICTWEIGHT
static SCIP_RETCODE filterSymmetricVariables(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata, SCIP_VAR **origbranchcands, SCIP_Real *origbranchcandssol, SCIP_Real *origbranchcandsfrac, int norigbranchcands, SCIP_VAR **branchcands, SCIP_Real *branchcandssol, SCIP_Real *branchcandsfrac, int *branchorbitidx, int *nbranchcands)
#define DEFAULT_GMILASTEFFWEIGHT
#define DEFAULT_USERELERRORFORRELIABILITY
#define PARETODISTRIBUTION
#define DEFAULT_CUTOFFWEIGHT
static SCIP_DECL_BRANCHCOPY(branchCopyRelpscost)
static SCIP_RETCODE countNonlinearities(SCIP *scip, int *nlcount, int nlcountsize, int *nlcountmax)
#define EXPONENTIALDISTRIBUTION
static SCIP_Bool needsStrongBranching(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_VAR *branchcand, SCIP_Real branchcandfrac, SCIP_VAR *bestpscand, SCIP_Real bestpscandfrac, SCIP_Real reliable, SCIP_Real relerrorthreshold, SCIP_CONFIDENCELEVEL clevel, SCIP_Bool useancpscost)
static SCIP_DECL_BRANCHINITSOL(branchInitsolRelpscost)
#define DEFAULT_TRANSSYMPSCOST
static SCIP_RETCODE addBdchg(SCIP *scip, int **bdchginds, SCIP_BOUNDTYPE **bdchgtypes, SCIP_Real **bdchgbounds, int *nbdchgs, int ind, SCIP_BOUNDTYPE type, SCIP_Real bound)
#define DEFAULT_LOWERRORTOL
static SCIP_RETCODE execRelpscost(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_VAR **branchcands, SCIP_Real *branchcandssol, SCIP_Real *branchcandsfrac, int *branchorbitidx, int nbranchcands, SCIP_Bool executebranch, SCIP_RESULT *result)
static SCIP_RETCODE branchruledataEnsureNlcount(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata)
static SCIP_Bool continueStrongBranchingTreeSizeEstimation(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata, SCIP_Real lookahead, SCIP_Real maxlookahead)
static SCIP_Real strongBranchingDepth(SCIP_Real gap, SCIP_Real maxmeangain)
#define DEFAULT_MINSAMPLESIZE
#define DEFAULT_CONFLENGTHWEIGHT
#define DEFAULT_CONFIDENCELEVEL
static SCIP_RETCODE updateMinMaxMeanGain(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_Real downgain, SCIP_Real upgain)
#define DEFAULT_MINRELIABLE
#define DEFAULT_DYNAMICLOOKAHEAD
static SCIP_Real calcScore(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata, SCIP_Real conflictscore, SCIP_Real avgconflictscore, SCIP_Real conflengthscore, SCIP_Real avgconflengthscore, SCIP_Real inferencescore, SCIP_Real avginferencescore, SCIP_Real cutoffscore, SCIP_Real avgcutoffscore, SCIP_Real gmieffscore, SCIP_Real lastgmieffscore, SCIP_Real pscostscore, SCIP_Real avgpscostscore, SCIP_Real nlscore, SCIP_Real frac, SCIP_Real degeneracyfactor)
#define DEFAULT_STORESEMIINITCOSTS
#define DEFAULT_MAXPROPROUNDS
static SCIP_DECL_BRANCHEXITSOL(branchExitsolRelpscost)
#define DEFAULT_INITCAND
static SCIP_Bool continueStrongBranchingLookahead(SCIP *scip, int candidx, int ninitcands, SCIP_Real lookahead, SCIP_Real maxlookahead, int nbdchgs, int nbdconflicts, int maxbdchgs, SCIP_Longint maxnsblpiterations)
#define BRANCHRULE_MAXDEPTH
#define DEFAULT_MAXRELIABLE
#define DEFAULT_DYNAMICLOOKDISTRIBUTION
#define DEFAULT_PSCOSTWEIGHT
#define BRANCHRULE_MAXBOUNDDIST
static void freeBdchgs(SCIP *scip, int **bdchginds, SCIP_BOUNDTYPE **bdchgtypes, SCIP_Real **bdchgbounds, int *nbdchgs)
static SCIP_DECL_BRANCHEXECLP(branchExeclpRelpscost)
reliable pseudo costs branching rule
Constraint handler for AND constraints, .
#define NULL
Definition: def.h:248
#define SCIP_Longint
Definition: def.h:141
#define SCIP_UNUSED(x)
Definition: def.h:409
#define SCIP_REAL_MAX
Definition: def.h:158
#define SCIP_INVALID
Definition: def.h:178
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:224
#define SCIP_Real
Definition: def.h:156
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:220
#define SCIP_LONGINT_FORMAT
Definition: def.h:148
#define SCIP_REAL_MIN
Definition: def.h:159
#define SCIP_CALL(x)
Definition: def.h:355
SCIP_RETCODE SCIPexecRelpscostBranching(SCIP *scip, SCIP_VAR **branchcands, SCIP_Real *branchcandssol, SCIP_Real *branchcandsfrac, int nbranchcands, SCIP_Bool executebranching, SCIP_RESULT *result)
SCIP_RETCODE SCIPincludeBranchruleRelpscost(SCIP *scip)
SCIP_VAR * SCIPgetResultantAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5248
int SCIPgetNVarsAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5199
SCIP_VAR ** SCIPgetVarsAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5223
int SCIPgetSubscipDepth(SCIP *scip)
Definition: scip_copy.c:2588
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:759
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip_prob.c:2115
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:2246
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:2201
int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3304
SCIP_RETCODE SCIPupdateNodeLowerbound(SCIP *scip, SCIP_NODE *node, SCIP_Real newbound)
Definition: scip_prob.c:4354
SCIP_RETCODE SCIPupdateLocalLowerbound(SCIP *scip, SCIP_Real newbound)
Definition: scip_prob.c:4289
SCIP_Real SCIPgetLocalLowerbound(SCIP *scip)
Definition: scip_prob.c:4178
SCIP_Real SCIPgetNodeLowerbound(SCIP *scip, SCIP_NODE *node)
Definition: scip_prob.c:4215
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip_message.c:225
#define SCIPdebugMsg
Definition: scip_message.h:78
SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
Definition: scip_param.c:250
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:83
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:139
SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
Definition: scip_param.c:307
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:57
SCIP_RETCODE SCIPsetBranchruleExecLp(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXECLP((*branchexeclp)))
Definition: scip_branch.c:256
SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
Definition: scip_branch.c:304
SCIP_RETCODE SCIPsetBranchruleCopy(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHCOPY((*branchcopy)))
Definition: scip_branch.c:160
SCIP_RETCODE SCIPincludeBranchruleBasic(SCIP *scip, SCIP_BRANCHRULE **branchruleptr, const char *name, const char *desc, int priority, int maxdepth, SCIP_Real maxbounddist, SCIP_BRANCHRULEDATA *branchruledata)
Definition: scip_branch.c:123
const char * SCIPbranchruleGetName(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:2018
SCIP_BRANCHRULEDATA * SCIPbranchruleGetData(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1886
SCIP_RETCODE SCIPsetBranchruleFree(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHFREE((*branchfree)))
Definition: scip_branch.c:176
void SCIPbranchruleMarkExact(SCIP_BRANCHRULE *branchrule)
Definition: branch.c:1907
SCIP_RETCODE SCIPsetBranchruleExitsol(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXITSOL((*branchexitsol)))
Definition: scip_branch.c:240
void SCIPbranchruleSetData(SCIP_BRANCHRULE *branchrule, SCIP_BRANCHRULEDATA *branchruledata)
Definition: branch.c:1896
SCIP_RETCODE SCIPsetBranchruleInitsol(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHINITSOL((*branchinitsol)))
Definition: scip_branch.c:224
SCIP_RETCODE SCIPbranchVarVal(SCIP *scip, SCIP_VAR *var, SCIP_Real val, SCIP_NODE **downchild, SCIP_NODE **eqchild, SCIP_NODE **upchild)
Definition: scip_branch.c:1134
SCIP_RETCODE SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
Definition: scip_branch.c:402
SCIP_Real SCIPgetBranchScore(SCIP *scip, SCIP_VAR *var, SCIP_Real downgain, SCIP_Real upgain)
Definition: scip_branch.c:857
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip_cons.c:940
int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4812
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4735
SCIP_Bool SCIPisExact(SCIP *scip)
Definition: scip_exact.c:193
SCIP_RETCODE SCIPgetLPDualDegeneracy(SCIP *scip, SCIP_Real *degeneracy, SCIP_Real *varconsratio)
Definition: scip_lp.c:2757
SCIP_Bool SCIPinDive(SCIP *scip)
Definition: scip_lp.c:2740
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip_lp.c:87
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip_lp.c:174
SCIP_Bool SCIPallColsInLP(SCIP *scip)
Definition: scip_lp.c:655
SCIP_Real SCIPgetLPObjval(SCIP *scip)
Definition: scip_lp.c:253
SCIP_Bool SCIPisLPSolBasic(SCIP *scip)
Definition: scip_lp.c:673
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:110
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:128
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip_mem.h:132
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:93
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip_mem.h:99
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip_mem.h:111
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip_mem.h:137
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip_nlp.c:110
int SCIPgetNNLPVars(SCIP *scip)
Definition: scip_nlp.c:201
SCIP_RETCODE SCIPgetNLPVarsNonlinearity(SCIP *scip, int *nlcount)
Definition: scip_nlp.c:223
SCIP_Real SCIPnodeGetLowerbound(SCIP_NODE *node)
Definition: tree.c:8503
SCIP_DOMCHG * SCIPnodeGetDomchg(SCIP_NODE *node)
Definition: tree.c:8588
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:8483
int SCIPnodeGetDepth(SCIP_NODE *node)
Definition: tree.c:8493
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip_probing.c:98
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip_sol.c:2981
int SCIPsolGetIndex(SCIP_SOL *sol)
Definition: sol.c:4290
SCIP_Real SCIPgetAvgInferenceScore(SCIP *scip)
SCIP_Real SCIPgetUpperbound(SCIP *scip)
SCIP_Real SCIPgetAvgConflictlengthScore(SCIP *scip)
SCIP_Longint SCIPgetNInfeasibleLeaves(SCIP *scip)
SCIP_Longint SCIPgetNNodes(SCIP *scip)
SCIP_Longint SCIPgetNNodeInitLPs(SCIP *scip)
SCIP_Longint SCIPgetNStrongbranchLPIterations(SCIP *scip)
SCIP_Longint SCIPgetNNodeLPIterations(SCIP *scip)
SCIP_Real SCIPgetAvgConflictScore(SCIP *scip)
SCIP_Longint SCIPgetNDualResolveLPIterations(SCIP *scip)
SCIP_Real SCIPgetAvgPseudocostScore(SCIP *scip)
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
SCIP_Longint SCIPgetNObjlimLeaves(SCIP *scip)
SCIP_Longint SCIPgetNNodeInitLPIterations(SCIP *scip)
SCIP_Real SCIPgetAvgDPseudocostScore(SCIP *scip, SCIP_Real discountfac)
SCIP_Longint SCIPgetNDualResolveLPs(SCIP *scip)
SCIP_Longint SCIPgetNRootStrongbranchLPIterations(SCIP *scip)
SCIP_Real SCIPgetAvgCutoffScore(SCIP *scip)
SCIP_RETCODE SCIPcomputeOrbitsComponentsSym(SCIP *scip, int npermvars, int **permstrans, int nperms, int *components, int *componentbegins, int *vartocomponent, int ncomponents, int *orbits, int *orbitbegins, int *norbits, int *varorbitmap)
Definition: symmetry.c:435
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPfeasFrac(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisRelGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeastol(SCIP *scip)
SCIP_Bool SCIPisSumGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisSumGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_NODE * SCIPgetFocusNode(SCIP *scip)
Definition: scip_tree.c:72
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:672
SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
Definition: scip_tree.c:91
SCIP_RETCODE SCIPgetVarStrongbranchFrac(SCIP *scip, SCIP_VAR *var, int itlim, SCIP_Bool idempotent, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, SCIP_Bool *downinf, SCIP_Bool *upinf, SCIP_Bool *downconflict, SCIP_Bool *upconflict, SCIP_Bool *lperror)
Definition: scip_var.c:3664
SCIP_Real SCIPgetVarAncPseudocostCountCurrentRun(SCIP *scip, SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: scip_var.c:11378
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:6401
SCIP_Bool SCIPpscostThresholdProbabilityTest(SCIP *scip, SCIP_VAR *var, SCIP_Real frac, SCIP_Real threshold, SCIP_BRANCHDIR dir, SCIP_CONFIDENCELEVEL clevel)
Definition: scip_var.c:11487
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:23642
SCIP_VAR * SCIPboundchgGetVar(SCIP_BOUNDCHG *boundchg)
Definition: var.c:23174
SCIP_Real SCIPgetVarPseudocostCountCurrentRun(SCIP *scip, SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: scip_var.c:11350
SCIP_Real SCIPgetVarAvgInferenceScore(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:11945
SCIP_RETCODE SCIPendStrongbranch(SCIP *scip)
Definition: scip_var.c:3488
SCIP_BOUNDCHG * SCIPdomchgGetBoundchg(SCIP_DOMCHG *domchg, int pos)
Definition: var.c:23222
SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:23184
SCIP_Real SCIPgetVarPseudocostCurrentRun(SCIP *scip, SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: scip_var.c:11296
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:24268
SCIP_Bool SCIPisVarPscostRelerrorReliable(SCIP *scip, SCIP_VAR *var, SCIP_Real threshold, SCIP_CONFIDENCELEVEL clevel)
Definition: scip_var.c:11506
SCIP_Real SCIPboundchgGetNewbound(SCIP_BOUNDCHG *boundchg)
Definition: var.c:23154
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:17550
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:6651
int SCIPdomchgGetNBoundchgs(SCIP_DOMCHG *domchg)
Definition: var.c:23214
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:23662
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:23267
SCIP_Longint SCIPgetVarStrongbranchNode(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:5019
SCIP_Real SCIPgetVarDPseudocostScore(SCIP *scip, SCIP_VAR *var, SCIP_Real solval, SCIP_Real discountfac)
Definition: scip_var.c:11570
SCIP_LPSOLSTAT SCIPgetLastStrongbranchLPSolStat(SCIP *scip, SCIP_BRANCHDIR branchdir)
Definition: scip_var.c:4847
SCIP_Real SCIPgetVarPseudocostVal(SCIP *scip, SCIP_VAR *var, SCIP_Real solvaldelta)
Definition: scip_var.c:11188
SCIP_Real SCIPgetVarConflictlengthScore(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:11775
SCIP_Bool SCIPsignificantVarPscostDifference(SCIP *scip, SCIP_VAR *varx, SCIP_Real fracx, SCIP_VAR *vary, SCIP_Real fracy, SCIP_BRANCHDIR dir, SCIP_CONFIDENCELEVEL clevel, SCIP_Bool onesided)
Definition: scip_var.c:11457
SCIP_RETCODE SCIPgetVarStrongbranchWithPropagation(SCIP *scip, SCIP_VAR *var, SCIP_Real solval, SCIP_Real lpobjval, int itlim, int maxproprounds, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, SCIP_Longint *ndomredsdown, SCIP_Longint *ndomredsup, SCIP_Bool *downinf, SCIP_Bool *upinf, SCIP_Bool *downconflict, SCIP_Bool *upconflict, SCIP_Bool *lperror, SCIP_Real *newlbs, SCIP_Real *newubs)
Definition: scip_var.c:4138
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:23490
SCIP_Real SCIPgetVarAncPseudocostVal(SCIP *scip, SCIP_VAR *var, SCIP_Real solvaldelta)
Definition: scip_var.c:11214
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:24664
SCIP_Real SCIPgetVarPseudocostScoreCurrentRun(SCIP *scip, SCIP_VAR *var, SCIP_Real solval)
Definition: scip_var.c:11613
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:24234
SCIP_RETCODE SCIPupdateVarPseudocost(SCIP *scip, SCIP_VAR *var, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: scip_var.c:11122
SCIP_Real SCIPgetVarAvgGMIScore(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:12349
SCIP_Real SCIPgetVarLastGMIScore(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:12403
SCIP_Real SCIPgetVarConflictScore(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:11713
SCIP_Real SCIPgetVarAvgCutoffScore(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:12199
SCIP_RETCODE SCIPupdateVarAncPseudocost(SCIP *scip, SCIP_VAR *var, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: scip_var.c:11154
SCIP_RETCODE SCIPgetVarStrongbranchLast(SCIP *scip, SCIP_VAR *var, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, SCIP_Real *solval, SCIP_Real *lpobjval)
Definition: scip_var.c:4869
SCIP_Real SCIPboundchgGetLPSolVal(SCIP_BOUNDCHG *boundchg)
Definition: var.c:23164
SCIP_Real SCIPgetVarPseudocostScore(SCIP *scip, SCIP_VAR *var, SCIP_Real solval)
Definition: scip_var.c:11531
SCIP_RETCODE SCIPstartStrongbranch(SCIP *scip, SCIP_Bool enablepropagation)
Definition: scip_var.c:3430
void SCIPfreeRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen)
SCIP_Real SCIPrandomGetReal(SCIP_RANDNUMGEN *randnumgen, SCIP_Real minrandval, SCIP_Real maxrandval)
Definition: misc.c:10245
SCIP_RETCODE SCIPcreateRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen, unsigned int initialseed, SCIP_Bool useglobalseed)
memory allocation routines
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
SCIP_RETCODE SCIPgetSymmetry(SCIP *scip, int *npermvars, SCIP_VAR ***permvars, SCIP_HASHMAP **permvarmap, int *nperms, int ***perms, int ***permstrans, SCIP_Real *log10groupsize, SCIP_Bool *binvaraffected, int **components, int **componentbegins, int **vartocomponent, int *ncomponents)
propagator for symmetry handling
public methods for branching rules
public methods for managing constraints
public methods for message output
#define SCIPdebug(x)
Definition: pub_message.h:93
public data structures and miscellaneous methods
public methods for primal CIP solutions
public methods for branch and bound tree
public methods for problem variables
public methods for branching rule plugins and branching
public methods for constraint handler plugins and constraints
public methods for exact solving
general public methods
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for nonlinear relaxation
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for random numbers
public methods for solutions
public methods for querying solving statistics
public methods for the branch-and-bound tree
public methods for SCIP variables
methods for handling symmetries
SCIP_RETCODE SCIPtreemodelSelectCandidate(SCIP *scip, SCIP_TREEMODEL *treemodel, SCIP_VAR **branchcands, SCIP_Real *mingains, SCIP_Real *maxgains, SCIP_Real *tiebreakerscore, int nbranchcands, int *bestcand)
Definition: treemodel.c:912
SCIP_RETCODE SCIPtreemodelInit(SCIP *scip, SCIP_TREEMODEL **treemodel)
Definition: treemodel.c:826
SCIP_RETCODE SCIPtreemodelFree(SCIP *scip, SCIP_TREEMODEL **treemodel)
Definition: treemodel.c:884
SCIP_Bool SCIPtreemodelIsEnabled(SCIP *scip, SCIP_TREEMODEL *treemodel)
Definition: treemodel.c:900
Branching rules based on the Single-Variable-Branching (SVB) model.
struct SCIP_BranchruleData SCIP_BRANCHRULEDATA
Definition: type_branch.h:57
@ SCIP_BRANCHDIR_DOWNWARDS
Definition: type_history.h:43
@ SCIP_BRANCHDIR_UPWARDS
Definition: type_history.h:44
@ SCIP_BOUNDTYPE_UPPER
Definition: type_lp.h:58
@ SCIP_BOUNDTYPE_LOWER
Definition: type_lp.h:57
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:60
@ SCIP_LPSOLSTAT_OPTIMAL
Definition: type_lp.h:44
@ SCIP_LPSOLSTAT_INFEASIBLE
Definition: type_lp.h:45
@ SCIP_LPSOLSTAT_OBJLIMIT
Definition: type_lp.h:47
@ SCIP_LPSOLSTAT_ITERLIMIT
Definition: type_lp.h:48
@ SCIP_VERBLEVEL_HIGH
Definition: type_message.h:61
@ SCIP_CONFIDENCELEVEL_MAX
Definition: type_misc.h:51
@ SCIP_CONFIDENCELEVEL_MEDIUM
Definition: type_misc.h:49
@ SCIP_CONFIDENCELEVEL_HIGH
Definition: type_misc.h:50
@ SCIP_CONFIDENCELEVEL_MIN
Definition: type_misc.h:47
@ SCIP_CONFIDENCELEVEL_LOW
Definition: type_misc.h:48
enum SCIP_Confidencelevel SCIP_CONFIDENCELEVEL
Definition: type_misc.h:53
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ SCIP_CUTOFF
Definition: type_result.h:48
@ SCIP_REDUCEDDOM
Definition: type_result.h:51
@ SCIP_CONSADDED
Definition: type_result.h:52
@ SCIP_BRANCHED
Definition: type_result.h:54
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:61
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_BOUNDCHGTYPE_BRANCHING
Definition: type_var.h:131