SCIP Doxygen Documentation
Loading...
Searching...
No Matches
branch_coloring.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_coloring.c
26 * @brief default branching rule for the vertex coloring problem
27 * @author Gerald Gamrath
28 * @author Julian Meffert
29 *
30 * This file implements the standard branching rule for the coloring algorithm.
31 *
32 * As we use column generation, we may not branch on the variables themselves,
33 * but on some sort of constraints that we introduce in the pricing problem.
34 *
35 * In our case, we choose two nodes v and w, which are not adjacent in the current graph, and
36 * consider the following two constraints: SAME(v,w) and DIFFER(v,w). SAME(v,w) requires that both
37 * nodes v and w get the same color, whereas DIFFER(v,w) forbids this. For each pair of nodes, each
38 * feasible solution fulfills exactly one of these constraints. Hence, splitting the solution space
39 * into two parts, one fulfilling SAME(v,w) and the other DIFFER(v,w), does not cut off any feasible
40 * solution and can therefore be used as the branching rule.
41 *
42 * The branching is done as follows: Given the optimal (fractional) solution of the current
43 * branch-and-bound node, choose the least/most fractional variable and the corresponding stable set
44 * s1. Now choose two nodes v, w and another stable set s2, such that v is part of both stable sets,
45 * whereas w is part of exactly one of the stable sets. Create two children of the current node,
46 * one with the restriction SAME(v,w), the other one with restriction DIFFER(v,w). Therefore, each
47 * node gets a constraint of type @c cons_storeGraph, which enforces the branching decision and
48 * assures that each coloring of the nodes in the respective subgraph assigns to both nodes the same
49 * color/different colors by fixing stable sets to 0 that violate this constraint.
50 */
51
52/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
53
54#include "branch_coloring.h"
55
56#define BRANCHRULE_NAME "coloring"
57#define BRANCHRULE_DESC "branching rule template"
58#define BRANCHRULE_PRIORITY 50000
59#define BRANCHRULE_MAXDEPTH -1
60#define BRANCHRULE_MAXBOUNDDIST 1.0
61
62#define BRANCHRULE_STRATEGIES "ml" /**< possible variable selection strategies m=most fractional, l=least fractional */
63#define BRANCHRULE_STRATEGY_DEFAULT 'l' /**< default variable selection strategy */
64
65
66/*
67 * Data structures
68 */
69
70/** branching rule data */
71struct SCIP_BranchruleData
72{
73 char strategy; /* determines the variable selection,
74 l: for least fractional variable,
75 m: for most fractional variable */
76};
77
78
79/*
80 * Callback methods of branching rule
81 */
82
83/** branching execution method for fractional LP solutions */
84static
85SCIP_DECL_BRANCHEXECLP(branchExeclpColoring)
86{
87 /* array of candidates for branching + fractionalities of candidates + length of array */
90 int nlpcands;
91 /* variables for finding the most fractional column */
92 SCIP_Real fractionality;
93 SCIP_Real bestfractionality;
94 int bestcand;
95 /* array of variables in a constraint + length of array */
96 SCIP_VAR** vars;
97 int nvars;
98 /* the variables for 2 stable sets, needed to find the two nodes for branching */
99 SCIP_VAR* s1;
100 SCIP_VAR* s2;
101 /* the 2 stable sets: array with all nodes and arraylength for each of them */
102 int* set1;
103 int setlength1;
104 int* set2;
105 int setlength2;
106 /* the 2 nodes, for which the branching is done by DIFFER and SAME */
107 int node1;
108 int node2;
109 /* the constraint belonging to node1 */
110 SCIP_CONS* cons1;
111 /* the nodes in the branch&bound-tree which are created */
112 SCIP_NODE* childsame;
113 SCIP_NODE* childdiffer;
114 /* the constraints for the created b&b-nodes */
115 SCIP_CONS* conssame;
116 SCIP_CONS* consdiffer;
117 /* the constraint of the processed b&b-node */
118 SCIP_CONS* currentcons;
119 /* the variable selection strategy */
120 char strategy;
121 /* the branching rule data */
122 SCIP_BRANCHRULEDATA* branchruledata;
123
124 int i;
125 int j;
126 int k;
127 int l;
128 int setindex;
129
130 assert(scip != NULL);
131 assert(branchrule != NULL);
132 assert(result != NULL);
133
135
137
138 /* get branching candidates */
140 assert(nlpcands > 0);
141
142 branchruledata = SCIPbranchruleGetData(branchrule);
143 strategy = branchruledata->strategy;
144
145 bestcand = -1;
146
147 switch( strategy )
148 {
149 case 'l':
150 /* search the least fractional candidate */
151 bestfractionality = 1;
152 for( i = 0; i < nlpcands; ++i )
153 {
154 assert(lpcands[i] != NULL);
155 fractionality = lpcandsfrac[i];
156 fractionality = MIN( fractionality, 1.0-fractionality );
157 if ( fractionality < bestfractionality )
158 {
159 bestfractionality = fractionality;
160 bestcand = i;
161 }
162 }
163 break;
164
165 case 'm':
166 /* search the most fractional candidate */
167 bestfractionality = 0;
168 for( i = 0; i < nlpcands; ++i ) {
169 assert(lpcands[i] != NULL);
170 fractionality = lpcandsfrac[i];
171 fractionality = MIN( fractionality, 1.0-fractionality );
172 if ( fractionality > bestfractionality )
173 {
174 bestfractionality = fractionality;
175 bestcand = i;
176 }
177 }
178 break;
179 default:
180 SCIPABORT();
182 }
183
184 assert(bestcand >= 0);
185 assert(SCIPisFeasPositive(scip, bestfractionality));
186
187 /* s1 = column belonging to bestcand */
188 s1 = lpcands[bestcand];
189 setindex = (int)(size_t) SCIPvarGetData(s1);
190
191 /* get stable set corresponding to variable s1 */
192 COLORprobGetStableSet(scip, setindex, &set1, &setlength1);
193
194 node1 = -1;
195 node2 = -1;
196 s2 = NULL;
197 /* search for two nodes node1, node2 and column s2 (s2 != s1) such that:
198 the node1-constraint is covered by s1 and s2
199 the node2-constraint is covered by exactly one of the columns s1,s2 */
200 for ( i = 0; ((i < setlength1) && (node2 == -1)); i++ )
201 {
202 node1 = COLORconsGetRepresentative(scip, set1[i]);
203 /* search for other set containing the node */
204 cons1 = COLORprobGetConstraint(scip, node1);
205 vars = SCIPgetVarsSetppc(scip, cons1);
206 nvars = SCIPgetNVarsSetppc(scip, cons1);
207 for ( j = 0; j < nvars; j++ )
208 {
209 if ( vars[j] != s1 && !SCIPisFeasZero(scip, SCIPvarGetUbLocal(vars[j])) )
210 {
211 s2 = vars[j];
212 setindex = (int)(size_t) SCIPvarGetData(s2);
213 /* get Stable Set corresponding to Variable s2 */
214 COLORprobGetStableSet(scip, setindex, &set2, &setlength2);
215 /* for all nodes in set1 */
216 for ( k = 0; k < setlength1; k++ )
217 {
218 /* set node2 = current node in set1 */
219 node2 = COLORconsGetRepresentative(scip, set1[k]);
220 if ( node2 == node1)
221 {
222 node2 = -1;
223 }
224 else
225 {
226 /* check whether node2 is in set2 */
227 for ( l = 0; l < setlength2; l++ )
228 {
229 if ( COLORconsGetRepresentative(scip, set2[l]) == node2 )
230 {
231 /* node2 is in both sets -> no branching-candidate */
232 node2 = -1;
233 break; /* for l */
234 }
235 }
236 /* if node2 found, get out of for-loops */
237 if ( node2 != -1 )
238 {
239 break; /* for k */
240 }
241 }
242 }
243 if ( node2 != -1 )
244 {
245 break; /* for j */
246 }
247 for ( k = 0; k < setlength2; k++ )
248 {
249 /* set node2 = current node in set1 */
250 node2 = COLORconsGetRepresentative(scip, set2[k]);
251 if ( node2 == node1)
252 {
253 node2 = -1;
254 }
255 else
256 {
257 /* check whether node2 is in set2 */
258 for ( l = 0; l < setlength1; l++ )
259 {
260 if ( COLORconsGetRepresentative(scip, set1[l]) == node2 )
261 {
262 /* node2 is in both sets -> no branching-candidate */
263 node2 = -1;
264 break; /* for l */
265 }
266 }
267 /* if node2 found, get out of for-loops */
268 if ( node2 != -1 )
269 {
270 break; /* for k */
271 }
272 }
273 }
274 if ( node2 != -1 )
275 {
276 break; /* for j */
277 }
278 }
279 }
280 }
281
282 assert(node2 != -1);
283 assert(node1 != -1);
284 assert(node1 == COLORconsGetRepresentative(scip, node1));
285 assert(node2 == COLORconsGetRepresentative(scip, node2));
288 assert(!tcliqueIsEdge(COLORconsGetCurrentGraph(scip), node1, node2));
289
290 /* create the b&b-tree child-nodes of the current node */
293
294 /* create corresponding constraints */
296 SCIP_CALL( COLORcreateConsStoreGraph(scip, &conssame, "same", currentcons, COLOR_CONSTYPE_SAME, node1, node2, childsame) );
297 SCIP_CALL( COLORcreateConsStoreGraph(scip, &consdiffer, "differ", currentcons, COLOR_CONSTYPE_DIFFER, node1, node2, childdiffer) );
298
299 /* add constraints to nodes */
300 SCIP_CALL( SCIPaddConsNode(scip, childsame, conssame, NULL) );
301 SCIP_CALL( SCIPaddConsNode(scip, childdiffer, consdiffer, NULL) );
302
303 /* release constraints */
304 SCIP_CALL( SCIPreleaseCons(scip, &conssame) );
305 SCIP_CALL( SCIPreleaseCons(scip, &consdiffer) );
306
308
309 return SCIP_OKAY;
310}/*lint !e715*/
311
312
313/** branching execution method for not completely fixed pseudo solutions */
314static
315SCIP_DECL_BRANCHEXECPS(branchExecpsColoring)
316{
317 /* the 2 nodes, for which the branching is done by DIFFER and SAME */
318 int node1;
319 int node2;
320 /* the nodes in the branch&bound-tree which are created */
321 SCIP_NODE* childsame;
322 SCIP_NODE* childdiffer;
323 /* the constraints for the created b&b-nodes */
324 SCIP_CONS* conssame;
325 SCIP_CONS* consdiffer;
326 /* the constraint of the processed b&b-node */
327 SCIP_CONS* currentcons;
328
329 assert(scip != NULL);
330 assert(branchrule != NULL);
331 assert(result != NULL);
332
334
336
337 /* search for two nodes node1, node2 such that:
338 node1 and node2 are neither in the same union nor adjacent */
339 for ( node1 = 0; node1 < COLORprobGetNNodes(scip); ++node1 )
340 {
341 if ( node1 != COLORconsGetRepresentative(scip, node1) )
342 {
343 continue;
344 }
345 for ( node2 = node1+1; node2 < COLORprobGetNNodes(scip); ++node2 )
346 {
347 if ( node2 != COLORconsGetRepresentative(scip, node2) )
348 {
349 continue;
350 }
351 if ( (node2 != node1) && !tcliqueIsEdge(COLORconsGetCurrentGraph(scip), node1, node2))
352 {
353 /* create the b&b-tree child-nodes of the current node */
356
357 /* create corresponding constraints */
359 SCIP_CALL( COLORcreateConsStoreGraph(scip, &conssame, "same", currentcons, COLOR_CONSTYPE_SAME, node1, node2, childsame) );
360 SCIP_CALL( COLORcreateConsStoreGraph(scip, &consdiffer, "differ", currentcons, COLOR_CONSTYPE_DIFFER, node1, node2, childdiffer) );
361
362 /* add constraints to nodes */
363 SCIP_CALL( SCIPaddConsNode(scip, childsame, conssame, NULL) );
364 SCIP_CALL( SCIPaddConsNode(scip, childdiffer, consdiffer, NULL) );
365
366 /* release constraints */
367 SCIP_CALL( SCIPreleaseCons(scip, &conssame) );
368 SCIP_CALL( SCIPreleaseCons(scip, &consdiffer) );
369
371
372 return SCIP_OKAY;
373 }
374 }
375 }
376
379
380 return SCIP_OKAY;
381}
382
383
384/** copy method for branchrule plugins (called when SCIP copies plugins) */
385static
386SCIP_DECL_BRANCHCOPY(branchCopyColoring)
387{ /*lint --e{715}*/
388 assert(scip != NULL);
389 assert(branchrule != NULL);
390
392
393 return SCIP_OKAY;
394}
395
396
397/** destructor of branching rule to free user data (called when SCIP is exiting) */
398static
399SCIP_DECL_BRANCHFREE(branchFreeColoring)
400{
401 SCIP_BRANCHRULEDATA* branchruledata;
402
403 /* free branching rule data */
404 branchruledata = SCIPbranchruleGetData(branchrule);
405 SCIPfreeBlockMemory(scip, &branchruledata);
406 SCIPbranchruleSetData(branchrule, NULL);
407
408 return SCIP_OKAY;
409}/*lint !e715*/
410
411
412
413/*
414 * branching rule specific interface methods
415 */
416
417/** creates the coloring branching rule and includes it in SCIP */
419 SCIP* scip /**< SCIP data structure */
420 )
421{
422 SCIP_BRANCHRULEDATA* branchruledata;
423 SCIP_BRANCHRULE* branchrule;
424
425 assert(scip != NULL);
426
427 /* create branching rule data */
428 SCIP_CALL( SCIPallocBlockMemory(scip, &branchruledata) );
429
430 branchrule = NULL;
431 /* include branching rule */
433 BRANCHRULE_MAXBOUNDDIST, branchruledata) );
434 assert(branchrule != NULL);
435
436 SCIP_CALL( SCIPsetBranchruleExecLp(scip, branchrule, branchExeclpColoring) );
437 SCIP_CALL( SCIPsetBranchruleExecPs(scip, branchrule, branchExecpsColoring) );
438 SCIP_CALL( SCIPsetBranchruleCopy(scip, branchrule, branchCopyColoring) );
439 SCIP_CALL( SCIPsetBranchruleFree(scip, branchrule, branchFreeColoring) );
440
441 SCIP_CALL( SCIPaddCharParam(scip, "branching/" BRANCHRULE_NAME "/strategy",
442 "variable selection strategy, 'l'east fractional or 'm'ost fractional variable",
443 &branchruledata->strategy, FALSE, BRANCHRULE_STRATEGY_DEFAULT, BRANCHRULE_STRATEGIES, NULL, NULL) );
444
445 return SCIP_OKAY;
446}
#define BRANCHRULE_DESC
#define BRANCHRULE_PRIORITY
#define BRANCHRULE_NAME
#define BRANCHRULE_MAXDEPTH
#define BRANCHRULE_MAXBOUNDDIST
SCIP_RETCODE SCIPincludeBranchruleColoring(SCIP *scip)
default branching rule for the vertex coloring problem
#define BRANCHRULE_STRATEGY_DEFAULT
#define BRANCHRULE_STRATEGIES
TCLIQUE_GRAPH * COLORconsGetCurrentGraph(SCIP *scip)
SCIP_RETCODE COLORcreateConsStoreGraph(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONS *fatherconstraint, COLOR_CONSTYPE type, int node1, int node2, SCIP_NODE *stickingnode)
int COLORconsGetRepresentative(SCIP *scip, int node)
SCIP_CONS * COLORconsGetActiveStoreGraphCons(SCIP *scip)
@ COLOR_CONSTYPE_DIFFER
@ COLOR_CONSTYPE_SAME
#define NULL
Definition def.h:257
#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 FALSE
Definition def.h:103
#define SCIPABORT()
Definition def.h:336
#define SCIP_CALL(x)
Definition def.h:364
int SCIPgetNVarsSetppc(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPaddConsNode(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition scip_prob.c:3901
SCIP_Real SCIPgetLocalTransEstimate(SCIP *scip)
Definition scip_prob.c:4139
SCIP_RETCODE SCIPaddCharParam(SCIP *scip, const char *name, const char *desc, char *valueptr, SCIP_Bool isadvanced, char defaultvalue, const char *allowedvalues, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:167
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_BRANCHRULEDATA * SCIPbranchruleGetData(SCIP_BRANCHRULE *branchrule)
Definition branch.c:1886
SCIP_RETCODE SCIPsetBranchruleCopy(SCIP *scip, SCIP_BRANCHRULE *branchrule,)
SCIP_RETCODE SCIPsetBranchruleExecLp(SCIP *scip, SCIP_BRANCHRULE *branchrule,)
void SCIPbranchruleSetData(SCIP_BRANCHRULE *branchrule, SCIP_BRANCHRULEDATA *branchruledata)
Definition branch.c:1896
SCIP_RETCODE SCIPsetBranchruleFree(SCIP *scip, SCIP_BRANCHRULE *branchrule,)
SCIP_RETCODE SCIPsetBranchruleExecPs(SCIP *scip, SCIP_BRANCHRULE *branchrule,)
SCIP_RETCODE SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
SCIP_RETCODE SCIPcreateChild(SCIP *scip, SCIP_NODE **node, SCIP_Real nodeselprio, SCIP_Real estimate)
SCIP_Bool SCIPconsIsEnabled(SCIP_CONS *cons)
Definition cons.c:8490
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition scip_cons.c:1173
#define SCIPfreeBlockMemory(scip, ptr)
Definition scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition scip_mem.h:89
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
SCIP_VARDATA * SCIPvarGetData(SCIP_VAR *var)
Definition var.c:23319
return SCIP_OKAY
int nlpcands
SCIP_VAR ** lpcands
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
int bestcand
SCIP_Real * lpcandsfrac
static SCIP_VAR ** vars
void COLORprobGetStableSet(SCIP *scip, int setindex, int **stableset, int *nelements)
int COLORprobGetNNodes(SCIP *scip)
SCIP_CONS * COLORprobGetConstraint(SCIP *scip, int node)
#define SCIP_DECL_BRANCHEXECPS(x)
#define SCIP_DECL_BRANCHEXECLP(x)
#define SCIP_DECL_BRANCHCOPY(x)
Definition type_branch.h:67
#define SCIP_DECL_BRANCHFREE(x)
Definition type_branch.h:75
struct SCIP_Branchrule SCIP_BRANCHRULE
Definition type_branch.h:56
struct SCIP_BranchruleData SCIP_BRANCHRULEDATA
Definition type_branch.h:57
struct SCIP_Cons SCIP_CONS
Definition type_cons.h:63
@ SCIP_DIDNOTRUN
Definition type_result.h:42
@ SCIP_BRANCHED
Definition type_result.h:54
@ SCIP_PARAMETERWRONGVAL
@ 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