SCIP Doxygen Documentation
Loading...
Searching...
No Matches
branch_mostinf.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-2026 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_mostinf.c
26 * @ingroup DEFPLUGINS_BRANCH
27 * @brief most infeasible LP branching rule
28 * @author Tobias Achterberg
29 */
30
31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32
33#include "scip/branch_mostinf.h"
34#include "scip/pub_branch.h"
35#include "scip/pub_message.h"
36#include "scip/pub_var.h"
37#include "scip/scip_branch.h"
38#include "scip/scip_message.h"
39#include "scip/scip_numerics.h"
40#include "scip/scip_var.h"
41
42
43#define BRANCHRULE_NAME "mostinf"
44#define BRANCHRULE_DESC "most infeasible branching"
45#define BRANCHRULE_PRIORITY 100
46#define BRANCHRULE_MAXDEPTH -1
47#define BRANCHRULE_MAXBOUNDDIST 1.0
48
49/*
50 * Local methods
51 */
52
53/** compares the so far best branching candidate with a new candidate and updates best candidate, if new candidate is better */
54static
56 SCIP* scip, /**< SCIP data structure */
57 SCIP_VAR** bestvar, /**< best branching candidate */
58 SCIP_Real* bestscore, /**< score of best branching candidate */
59 SCIP_Real* bestobj, /**< absolute objective value of best branching candidate */
60 SCIP_Real* bestsol, /**< proposed branching point of best branching candidate */
61 SCIP_VAR* cand, /**< branching candidate to consider */
62 SCIP_Real candscore, /**< scoring of branching candidate */
63 SCIP_Real candsol /**< proposed branching point of branching candidate */
64 )
65{
67
68 assert(scip != NULL);
69 assert(bestvar != NULL);
70 assert(bestscore != NULL);
71 assert(bestobj != NULL);
72 assert(*bestobj >= 0.0);
73 assert(cand != NULL);
74
75 /* a branching variable candidate should either be an active problem variable or a multi-aggregated variable */
78
80 {
81 /* for a multi-aggregated variable, we call updateBestCandidate function recursively with all variables in the multi-aggregation */
82 SCIP_VAR** multvars;
83 int nmultvars;
84 int i;
85 SCIP_Bool success;
86 SCIP_Real multvarlb;
87 SCIP_Real multvarub;
88
89 cand = SCIPvarGetProbvar(cand);
90 multvars = SCIPvarGetMultaggrVars(cand);
91 nmultvars = SCIPvarGetMultaggrNVars(cand);
92
93 /* if we have a candidate branching point, then first register only aggregation variables
94 * for which we can compute a corresponding branching point too (see also comments below)
95 * if this fails, then register all (unfixed) aggregation variables, thereby forgetting about candsol
96 */
97 success = FALSE;
98 if( candsol != SCIP_INVALID ) /*lint !e777*/
99 {
100 SCIP_Real* multscalars;
101 SCIP_Real minact;
102 SCIP_Real maxact;
103 SCIP_Real aggrvarsol;
104 SCIP_Real aggrvarsol1;
105 SCIP_Real aggrvarsol2;
106
107 multscalars = SCIPvarGetMultaggrScalars(cand);
108
109 /* for computing the branching point, we need the current bounds of the multi-aggregated variable */
110 minact = SCIPcomputeVarLbLocal(scip, cand);
111 maxact = SCIPcomputeVarUbLocal(scip, cand);
112
113 for( i = 0; i < nmultvars; ++i )
114 {
115 /* skip fixed variables */
116 multvarlb = SCIPcomputeVarLbLocal(scip, multvars[i]);
117 multvarub = SCIPcomputeVarUbLocal(scip, multvars[i]);
118 if( SCIPisEQ(scip, multvarlb, multvarub) )
119 continue;
120
121 assert(multscalars != NULL);
122 assert(multscalars[i] != 0.0);
123
124 /* we cannot ensure that both the upper bound in the left node and the lower bound in the right node
125 * will be candsol by a clever choice for the branching point of multvars[i],
126 * but we can try to ensure that at least one of them will be at candsol
127 */
128 if( multscalars[i] > 0.0 )
129 {
130 /* cand >= candsol
131 * if multvars[i] >= (candsol - (maxact - multscalars[i] * ub(multvars[i]))) / multscalars[i]
132 * = (candsol - maxact) / multscalars[i] + ub(multvars[i])
133 */
134 aggrvarsol1 = (candsol - maxact) / multscalars[i] + multvarub;
135
136 /* cand <= candsol
137 * if multvars[i] <= (candsol - (minact - multscalar[i] * lb(multvars[i]))) / multscalars[i]
138 * = (candsol - minact) / multscalars[i] + lb(multvars[i])
139 */
140 aggrvarsol2 = (candsol - minact) / multscalars[i] + multvarlb;
141 }
142 else
143 {
144 /* cand >= candsol
145 * if multvars[i] <= (candsol - (maxact - multscalars[i] * lb(multvars[i]))) / multscalars[i]
146 * = (candsol - maxact) / multscalars[i] + lb(multvars[i])
147 */
148 aggrvarsol2 = (candsol - maxact) / multscalars[i] + multvarlb;
149
150 /* cand <= candsol
151 * if multvars[i] >= (candsol - (minact - multscalar[i] * ub(multvars[i]))) / multscalars[i]
152 * = (candsol - minact) / multscalars[i] + ub(multvars[i])
153 */
154 aggrvarsol1 = (candsol - minact) / multscalars[i] + multvarub;
155 }
156
157 /* by the above choice, aggrvarsol1 <= ub(multvars[i]) and aggrvarsol2 >= lb(multvars[i])
158 * if aggrvarsol1 <= lb(multvars[i]) or aggrvarsol2 >= ub(multvars[i]), then choose the other one
159 * if both are out of bounds, then give up
160 * if both are inside bounds, then choose the one closer to 0.0 (someone has better idea???)
161 */
162 if( SCIPisFeasLE(scip, aggrvarsol1, multvarlb) )
163 {
164 if( SCIPisFeasGE(scip, aggrvarsol2, multvarub) )
165 continue;
166 else
167 aggrvarsol = aggrvarsol2;
168 }
169 else
170 {
171 if( SCIPisFeasGE(scip, aggrvarsol2, multvarub) )
172 aggrvarsol = aggrvarsol1;
173 else
174 aggrvarsol = REALABS(aggrvarsol1) < REALABS(aggrvarsol2) ? aggrvarsol1 : aggrvarsol2;
175 }
176 success = TRUE;
177
178 updateBestCandidate(scip, bestvar, bestscore, bestobj, bestsol,
179 multvars[i], candscore, aggrvarsol);
180 }
181 }
182
183 if( !success )
184 for( i = 0; i < nmultvars; ++i )
185 {
186 /* skip fixed variables */
187 multvarlb = SCIPcomputeVarLbLocal(scip, multvars[i]);
188 multvarub = SCIPcomputeVarUbLocal(scip, multvars[i]);
189 if( SCIPisEQ(scip, multvarlb, multvarub) )
190 continue;
191
192 updateBestCandidate(scip, bestvar, bestscore, bestobj, bestsol,
193 multvars[i], candscore, SCIP_INVALID);
194 }
195
196 assert(*bestvar != NULL); /* if all variables were fixed, something is strange */
197
198 return;
199 }
200
201 candscore *= SCIPvarGetBranchFactor(cand);
202 obj = SCIPvarGetObj(cand);
203 obj = REALABS(obj);
204 if( SCIPisInfinity(scip, candscore)
205 || (!SCIPisInfinity(scip, *bestscore) &&
206 (SCIPisGT(scip, candscore, *bestscore) || (SCIPisGE(scip, candscore, *bestscore) && obj > *bestobj))) )
207 {
208 *bestvar = cand;
209 *bestscore = candscore;
210 *bestobj = obj;
211 *bestsol = candsol;
212 }
213}
214
215/*
216 * Callback methods
217 */
218
219/** copy method for branchrule plugins (called when SCIP copies plugins) */
220static
221SCIP_DECL_BRANCHCOPY(branchCopyMostinf)
222{ /*lint --e{715}*/
223 assert(scip != NULL);
224 assert(branchrule != NULL);
225
227
228 /* call inclusion method of branchrule */
230
231 return SCIP_OKAY;
232}
233
234
235/** branching execution method for fractional LP solutions */
236static
237SCIP_DECL_BRANCHEXECLP(branchExeclpMostinf)
238{ /*lint --e{715}*/
241 int nlpcands;
242 SCIP_Real infeasibility;
243 SCIP_Real score;
245 SCIP_Real bestscore;
246 SCIP_Real bestobj;
247 int bestcand;
248 int i;
249
250 assert(branchrule != NULL);
251 assert(scip != NULL);
252 assert(result != NULL);
253
255
256 SCIPdebugMsg(scip, "Execlp method of mostinf branching\n");
257
258 /* get branching candidates */
260 assert(nlpcands > 0);
261
262 /* search the most infeasible candidate */
263 bestscore = SCIP_REAL_MIN;
264 bestobj = 0.0;
265 bestcand = -1;
266 for( i = 0; i < nlpcands; ++i )
267 {
268 assert(lpcands[i] != NULL);
269
270 infeasibility = lpcandsfrac[i];
271 infeasibility = MIN(infeasibility, 1.0-infeasibility);
272 score = infeasibility;
275 obj = REALABS(obj);
276 if( SCIPisGT(scip, score, bestscore)
277 || (SCIPisGE(scip, score, bestscore) && obj > bestobj) )
278 {
279 bestscore = score;
280 bestobj = obj;
281 bestcand = i;
282 }
283 }
284 assert(bestcand >= 0);
285
286 SCIPdebugMsg(scip, " -> %d candidates, selected candidate %d: variable <%s> (frac=%g, obj=%g, factor=%g, score=%g)\n",
289
290 /* perform the branching */
293
294 return SCIP_OKAY;
295}
296
297/** branching execution method for external candidates */
298static
299SCIP_DECL_BRANCHEXECEXT(branchExecextMostinf)
300{ /*lint --e{715}*/
301 SCIP_VAR** externcands;
302 SCIP_Real* externcandssol;
303 SCIP_Real* externcandsscore;
304 int nexterncands;
306 SCIP_Real bestscore;
307 SCIP_Real bestobj;
308 SCIP_Real bestsol;
309 SCIP_Real brpoint;
310 int i;
311 SCIP_NODE* downchild;
312 SCIP_NODE* eqchild;
313 SCIP_NODE* upchild;
314
315 assert(branchrule != NULL);
316 assert(scip != NULL);
317 assert(result != NULL);
318
320
321 SCIPdebugMsg(scip, "Execext method of mostinf branching\n");
322
323 /* get branching candidates */
324 SCIP_CALL( SCIPgetExternBranchCands(scip, &externcands, &externcandssol, &externcandsscore, NULL, &nexterncands, NULL, NULL, NULL) );
325 assert(nexterncands > 0);
326
327 /* search the most infeasible candidate */
328 bestscore = SCIP_REAL_MIN;
329 bestobj = 0.0;
330 bestcand = NULL;
331 bestsol = SCIP_INVALID;
332 for( i = 0; i < nexterncands; ++i )
333 {
334 updateBestCandidate(scip, &bestcand, &bestscore, &bestobj, &bestsol, externcands[i], externcandsscore[i], externcandssol[i]);
335 }
336
337 if( bestcand == NULL )
338 {
339 SCIPerrorMessage("branchExecextMostinf failed to select a branching variable from %d candidates\n", nexterncands);
341 return SCIP_OKAY;
342 }
343
344 brpoint = SCIPgetBranchingPoint(scip, bestcand, bestsol);
345
346 SCIPdebugMsg(scip, " -> %d candidates, selected variable <%s> (sol=%g, locdom=[%g,%g], obj=%g, factor=%g, score=%g), branching point=%g\n",
347 nexterncands, SCIPvarGetName(bestcand), bestsol, SCIPvarGetLbLocal(bestcand), SCIPvarGetUbLocal(bestcand), bestobj,
348 SCIPvarGetBranchFactor(bestcand), bestscore, brpoint);
349
350 /* perform the branching */
351 SCIP_CALL( SCIPbranchVarVal(scip, bestcand, brpoint, &downchild, &eqchild, &upchild) );
352
353 if( downchild != NULL || eqchild != NULL || upchild != NULL )
354 {
356 }
357 else
358 {
359 /* if there are no children, then variable should have been fixed by SCIPbranchVarVal */
362 }
363
364 return SCIP_OKAY;
365}
366
367
368/*
369 * branching specific interface methods
370 */
371
372/** creates the most infeasible LP branching rule and includes it in SCIP */
374 SCIP* scip /**< SCIP data structure */
375 )
376{
377 SCIP_BRANCHRULE* branchrule;
378
379 /* include branching rule */
382
383 assert(branchrule != NULL);
384
385 /* set non-fundamental callbacks via specific setter functions*/
386 SCIP_CALL( SCIPsetBranchruleCopy(scip, branchrule, branchCopyMostinf) );
387 SCIP_CALL( SCIPsetBranchruleExecLp(scip, branchrule, branchExeclpMostinf) );
388 SCIP_CALL( SCIPsetBranchruleExecExt(scip, branchrule, branchExecextMostinf) );
389
390 return SCIP_OKAY;
391}
#define BRANCHRULE_DESC
#define BRANCHRULE_PRIORITY
#define BRANCHRULE_NAME
#define BRANCHRULE_MAXDEPTH
#define BRANCHRULE_MAXBOUNDDIST
static void updateBestCandidate(SCIP *scip, SCIP_VAR **bestvar, SCIP_Real *bestscore, SCIP_Real *bestobj, SCIP_Real *bestsol, SCIP_VAR *cand, SCIP_Real candscore, SCIP_Real candsol)
most infeasible LP branching rule
#define NULL
Definition def.h:257
#define SCIP_INVALID
Definition def.h:187
#define SCIP_Bool
Definition def.h:100
#define MIN(x, y)
Definition def.h:233
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define SCIP_REAL_MIN
Definition def.h:168
#define REALABS(x)
Definition def.h:191
#define SCIP_CALL(x)
Definition def.h:364
SCIP_RETCODE SCIPincludeBranchruleMostinf(SCIP *scip)
#define SCIPdebugMsg
SCIP_RETCODE SCIPincludeBranchruleBasic(SCIP *scip, SCIP_BRANCHRULE **branchruleptr, const char *name, const char *desc, int priority, int maxdepth, SCIP_Real maxbounddist, SCIP_BRANCHRULEDATA *branchruledata)
const char * SCIPbranchruleGetName(SCIP_BRANCHRULE *branchrule)
Definition branch.c:2018
SCIP_RETCODE SCIPsetBranchruleExecExt(SCIP *scip, SCIP_BRANCHRULE *branchrule,)
SCIP_RETCODE SCIPsetBranchruleCopy(SCIP *scip, SCIP_BRANCHRULE *branchrule,)
SCIP_RETCODE SCIPsetBranchruleExecLp(SCIP *scip, SCIP_BRANCHRULE *branchrule,)
SCIP_RETCODE SCIPgetExternBranchCands(SCIP *scip, SCIP_VAR ***externcands, SCIP_Real **externcandssol, SCIP_Real **externcandsscore, int *nexterncands, int *nprioexterncands, int *nprioexternbins, int *nprioexternints, int *nprioexternimpls)
SCIP_Real SCIPgetBranchingPoint(SCIP *scip, SCIP_VAR *var, SCIP_Real suggestion)
SCIP_RETCODE SCIPbranchVarVal(SCIP *scip, SCIP_VAR *var, SCIP_Real val, SCIP_NODE **downchild, SCIP_NODE **eqchild, SCIP_NODE **upchild)
SCIP_RETCODE SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
SCIP_RETCODE SCIPbranchVar(SCIP *scip, SCIP_VAR *var, SCIP_NODE **downchild, SCIP_NODE **eqchild, SCIP_NODE **upchild)
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition var.c:23674
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition var.c:23418
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition var.c:23932
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition var.c:17595
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23299
SCIP_Real SCIPvarGetBranchFactor(SCIP_VAR *var)
Definition var.c:24482
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition var.c:23838
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition var.c:23826
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24266
SCIP_Real SCIPcomputeVarLbLocal(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:8417
SCIP_Real SCIPcomputeVarUbLocal(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:8462
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition var.c:23850
return SCIP_OKAY
int nlpcands
SCIP_Real obj
SCIP_VAR ** lpcands
assert(minobj< SCIPgetCutoffbound(scip))
int bestcand
SCIP_Real * lpcandsfrac
public methods for branching rules
public methods for message output
#define SCIPerrorMessage
Definition pub_message.h:64
public methods for problem variables
public methods for branching rule plugins and branching
public methods for message handling
public methods for numerical tolerances
public methods for SCIP variables
#define SCIP_DECL_BRANCHEXECLP(x)
#define SCIP_DECL_BRANCHEXECEXT(x)
#define SCIP_DECL_BRANCHCOPY(x)
Definition type_branch.h:67
struct SCIP_Branchrule SCIP_BRANCHRULE
Definition type_branch.h:56
@ SCIP_DIDNOTRUN
Definition type_result.h:42
@ SCIP_REDUCEDDOM
Definition type_result.h:51
@ SCIP_BRANCHED
Definition type_result.h:54
@ SCIP_INVALIDCALL
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
struct SCIP_Node SCIP_NODE
Definition type_tree.h:63
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
@ SCIP_VARSTATUS_MULTAGGR
Definition type_var.h:56