Scippy

SCIP

Solving Constraint Integer Programs

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-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_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#include <assert.h>
54#include <string.h>
55
56#include "branch_coloring.h"
57
58#define BRANCHRULE_NAME "coloring"
59#define BRANCHRULE_DESC "branching rule template"
60#define BRANCHRULE_PRIORITY 50000
61#define BRANCHRULE_MAXDEPTH -1
62#define BRANCHRULE_MAXBOUNDDIST 1.0
63
64#define BRANCHRULE_STRATEGIES "ml" /**< possible variable selection strategies m=most fractional, l=least fractional */
65#define BRANCHRULE_STRATEGY_DEFAULT 'l' /**< default variable selection strategy */
66
67
68/*
69 * Data structures
70 */
71
72/** branching rule data */
73struct SCIP_BranchruleData
74{
75 char strategy; /* determines the variable selection,
76 l: for least fractional variable,
77 m: for most fractional variable */
78};
79
80
81/*
82 * Callback methods of branching rule
83 */
84
85/** branching execution method for fractional LP solutions */
86static
87SCIP_DECL_BRANCHEXECLP(branchExeclpColoring)
88{
89 /* array of candidates for branching + fractionalities of candidates + length of array */
90 SCIP_VAR** lpcands;
91 SCIP_Real* lpcandsfrac;
92 int nlpcands;
93 /* variables for finding the most fractional column */
94 SCIP_Real fractionality;
95 SCIP_Real bestfractionality;
96 int bestcand;
97 /* array of variables in a constraint + length of array */
98 SCIP_VAR** vars;
99 int nvars;
100 /* the variables for 2 stable sets, needed to find the two nodes for branching */
101 SCIP_VAR* s1;
102 SCIP_VAR* s2;
103 /* the 2 stable sets: array with all nodes and arraylength for each of them */
104 int* set1;
105 int setlength1;
106 int* set2;
107 int setlength2;
108 /* the 2 nodes, for which the branching is done by DIFFER and SAME */
109 int node1;
110 int node2;
111 /* the constraint belonging to node1 */
112 SCIP_CONS* cons1;
113 /* the nodes in the branch&bound-tree which are created */
114 SCIP_NODE* childsame;
115 SCIP_NODE* childdiffer;
116 /* the constraints for the created b&b-nodes */
117 SCIP_CONS* conssame;
118 SCIP_CONS* consdiffer;
119 /* the constraint of the processed b&b-node */
120 SCIP_CONS* currentcons;
121 /* the variable selection strategy */
122 char strategy;
123 /* the branching rule data */
124 SCIP_BRANCHRULEDATA* branchruledata;
125
126 int i;
127 int j;
128 int k;
129 int l;
130 int setindex;
131
132 assert(scip != NULL);
133 assert(branchrule != NULL);
134 assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
135 assert(result != NULL);
136
137 *result = SCIP_DIDNOTRUN;
138
139 /* get branching candidates */
140 SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, NULL, &lpcandsfrac, NULL, &nlpcands, NULL) );
141 assert(nlpcands > 0);
142
143 branchruledata = SCIPbranchruleGetData(branchrule);
144 strategy = branchruledata->strategy;
145
146 bestcand = -1;
147
148 switch( strategy )
149 {
150 case 'l':
151 /* search the least fractional candidate */
152 bestfractionality = 1;
153 for( i = 0; i < nlpcands; ++i )
154 {
155 assert(lpcands[i] != NULL);
156 fractionality = lpcandsfrac[i];
157 fractionality = MIN( fractionality, 1.0-fractionality );
158 if ( fractionality < bestfractionality )
159 {
160 bestfractionality = fractionality;
161 bestcand = i;
162 }
163 }
164 break;
165
166 case 'm':
167 /* search the most fractional candidate */
168 bestfractionality = 0;
169 for( i = 0; i < nlpcands; ++i ) {
170 assert(lpcands[i] != NULL);
171 fractionality = lpcandsfrac[i];
172 fractionality = MIN( fractionality, 1.0-fractionality );
173 if ( fractionality > bestfractionality )
174 {
175 bestfractionality = fractionality;
176 bestcand = i;
177 }
178 }
179 break;
180 default:
181 SCIPABORT();
183 }
184
185 assert(bestcand >= 0);
186 assert(SCIPisFeasPositive(scip, bestfractionality));
187
188 /* s1 = column belonging to bestcand */
189 s1 = lpcands[bestcand];
190 setindex = (int)(size_t) SCIPvarGetData(s1);
191
192 /* get stable set corresponding to variable s1 */
193 COLORprobGetStableSet(scip, setindex, &set1, &setlength1);
194
195 node1 = -1;
196 node2 = -1;
197 s2 = NULL;
198 /* search for two nodes node1, node2 and column s2 (s2 != s1) such that:
199 the node1-constraint is covered by s1 and s2
200 the node2-constraint is covered by exactly one of the columns s1,s2 */
201 for ( i = 0; ((i < setlength1) && (node2 == -1)); i++ )
202 {
203 node1 = COLORconsGetRepresentative(scip, set1[i]);
204 /* search for other set containing the node */
205 cons1 = COLORprobGetConstraint(scip, node1);
206 vars = SCIPgetVarsSetppc(scip, cons1);
207 nvars = SCIPgetNVarsSetppc(scip, cons1);
208 for ( j = 0; j < nvars; j++ )
209 {
210 if ( vars[j] != s1 && !SCIPisFeasZero(scip, SCIPvarGetUbLocal(vars[j])) )
211 {
212 s2 = vars[j];
213 setindex = (int)(size_t) SCIPvarGetData(s2);
214 /* get Stable Set corresponding to Variable s2 */
215 COLORprobGetStableSet(scip, setindex, &set2, &setlength2);
216 /* for all nodes in set1 */
217 for ( k = 0; k < setlength1; k++ )
218 {
219 /* set node2 = current node in set1 */
220 node2 = COLORconsGetRepresentative(scip, set1[k]);
221 if ( node2 == node1)
222 {
223 node2 = -1;
224 }
225 else
226 {
227 /* check whether node2 is in set2 */
228 for ( l = 0; l < setlength2; l++ )
229 {
230 if ( COLORconsGetRepresentative(scip, set2[l]) == node2 )
231 {
232 /* node2 is in both sets -> no branching-candidate */
233 node2 = -1;
234 break; /* for l */
235 }
236 }
237 /* if node2 found, get out of for-loops */
238 if ( node2 != -1 )
239 {
240 break; /* for k */
241 }
242 }
243 }
244 if ( node2 != -1 )
245 {
246 break; /* for j */
247 }
248 for ( k = 0; k < setlength2; k++ )
249 {
250 /* set node2 = current node in set1 */
251 node2 = COLORconsGetRepresentative(scip, set2[k]);
252 if ( node2 == node1)
253 {
254 node2 = -1;
255 }
256 else
257 {
258 /* check whether node2 is in set2 */
259 for ( l = 0; l < setlength1; l++ )
260 {
261 if ( COLORconsGetRepresentative(scip, set1[l]) == node2 )
262 {
263 /* node2 is in both sets -> no branching-candidate */
264 node2 = -1;
265 break; /* for l */
266 }
267 }
268 /* if node2 found, get out of for-loops */
269 if ( node2 != -1 )
270 {
271 break; /* for k */
272 }
273 }
274 }
275 if ( node2 != -1 )
276 {
277 break; /* for j */
278 }
279 }
280 }
281 }
282
283 assert(node2 != -1);
284 assert(node1 != -1);
285 assert(node1 == COLORconsGetRepresentative(scip, node1));
286 assert(node2 == COLORconsGetRepresentative(scip, node2));
289 assert(!tcliqueIsEdge(COLORconsGetCurrentGraph(scip), node1, node2));
290
291 /* create the b&b-tree child-nodes of the current node */
294
295 /* create corresponding constraints */
297 SCIP_CALL( COLORcreateConsStoreGraph(scip, &conssame, "same", currentcons, COLOR_CONSTYPE_SAME, node1, node2, childsame) );
298 SCIP_CALL( COLORcreateConsStoreGraph(scip, &consdiffer, "differ", currentcons, COLOR_CONSTYPE_DIFFER, node1, node2, childdiffer) );
299
300 /* add constraints to nodes */
301 SCIP_CALL( SCIPaddConsNode(scip, childsame, conssame, NULL) );
302 SCIP_CALL( SCIPaddConsNode(scip, childdiffer, consdiffer, NULL) );
303
304 /* release constraints */
305 SCIP_CALL( SCIPreleaseCons(scip, &conssame) );
306 SCIP_CALL( SCIPreleaseCons(scip, &consdiffer) );
307
308 *result = SCIP_BRANCHED;
309
310 return SCIP_OKAY;
311}/*lint !e715*/
312
313
314/** branching execution method for not completely fixed pseudo solutions */
315static
316SCIP_DECL_BRANCHEXECPS(branchExecpsColoring)
317{
318 /* the 2 nodes, for which the branching is done by DIFFER and SAME */
319 int node1;
320 int node2;
321 /* the nodes in the branch&bound-tree which are created */
322 SCIP_NODE* childsame;
323 SCIP_NODE* childdiffer;
324 /* the constraints for the created b&b-nodes */
325 SCIP_CONS* conssame;
326 SCIP_CONS* consdiffer;
327 /* the constraint of the processed b&b-node */
328 SCIP_CONS* currentcons;
329
330 assert(scip != NULL);
331 assert(branchrule != NULL);
332 assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
333 assert(result != NULL);
334
335 *result = SCIP_DIDNOTRUN;
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
370 *result = SCIP_BRANCHED;
371
372 return SCIP_OKAY;
373 }
374 }
375 }
376
378 *result = SCIP_BRANCHED;
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 assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
391
392 return SCIP_OKAY;
393}
394
395
396/** destructor of branching rule to free user data (called when SCIP is exiting) */
397static
398SCIP_DECL_BRANCHFREE(branchFreeColoring)
399{
400 SCIP_BRANCHRULEDATA* branchruledata;
401
402 /* free branching rule data */
403 branchruledata = SCIPbranchruleGetData(branchrule);
404 SCIPfreeBlockMemory(scip, &branchruledata);
405 SCIPbranchruleSetData(branchrule, NULL);
406
407 return SCIP_OKAY;
408}/*lint !e715*/
409
410
411
412/*
413 * branching rule specific interface methods
414 */
415
416/** creates the coloring branching rule and includes it in SCIP */
418 SCIP* scip /**< SCIP data structure */
419 )
420{
421 SCIP_BRANCHRULEDATA* branchruledata;
422 SCIP_BRANCHRULE* branchrule;
423
424 assert(scip != NULL);
425
426 /* create branching rule data */
427 SCIP_CALL( SCIPallocBlockMemory(scip, &branchruledata) );
428
429 branchrule = NULL;
430 /* include branching rule */
432 BRANCHRULE_MAXBOUNDDIST, branchruledata) );
433 assert(branchrule != NULL);
434
435 SCIP_CALL( SCIPsetBranchruleExecLp(scip, branchrule, branchExeclpColoring) );
436 SCIP_CALL( SCIPsetBranchruleExecPs(scip, branchrule, branchExecpsColoring) );
437 SCIP_CALL( SCIPsetBranchruleCopy(scip, branchrule, branchCopyColoring) );
438 SCIP_CALL( SCIPsetBranchruleFree(scip, branchrule, branchFreeColoring) );
439
440 SCIP_CALL( SCIPaddCharParam(scip, "branching/" BRANCHRULE_NAME "/strategy",
441 "variable selection strategy, 'l'east fractional or 'm'ost fractional variable",
442 &branchruledata->strategy, FALSE, BRANCHRULE_STRATEGY_DEFAULT, BRANCHRULE_STRATEGIES, NULL, NULL) );
443
444 return SCIP_OKAY;
445}
#define BRANCHRULE_DESC
#define BRANCHRULE_PRIORITY
static SCIP_DECL_BRANCHEXECLP(branchExeclpColoring)
static SCIP_DECL_BRANCHFREE(branchFreeColoring)
#define BRANCHRULE_NAME
static SCIP_DECL_BRANCHCOPY(branchCopyColoring)
SCIP_RETCODE SCIPincludeBranchruleColoring(SCIP *scip)
static SCIP_DECL_BRANCHEXECPS(branchExecpsColoring)
#define BRANCHRULE_STRATEGY_DEFAULT
#define BRANCHRULE_STRATEGIES
#define BRANCHRULE_MAXDEPTH
#define BRANCHRULE_MAXBOUNDDIST
default branching rule for the vertex coloring problem
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:248
#define MIN(x, y)
Definition: def.h:224
#define SCIP_Real
Definition: def.h:156
#define FALSE
Definition: def.h:94
#define SCIPABORT()
Definition: def.h:327
#define SCIP_CALL(x)
Definition: def.h:355
int SCIPgetNVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9596
SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9619
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 SCIPsetBranchruleExecLp(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXECLP((*branchexeclp)))
Definition: scip_branch.c:256
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
SCIP_RETCODE SCIPsetBranchruleExecPs(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXECPS((*branchexecps)))
Definition: scip_branch.c:288
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 SCIPbranchruleSetData(SCIP_BRANCHRULE *branchrule, SCIP_BRANCHRULEDATA *branchruledata)
Definition: branch.c:1896
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_RETCODE SCIPcreateChild(SCIP *scip, SCIP_NODE **node, SCIP_Real nodeselprio, SCIP_Real estimate)
Definition: scip_branch.c:1025
SCIP_Bool SCIPconsIsEnabled(SCIP_CONS *cons)
Definition: cons.c:8486
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:24268
SCIP_VARDATA * SCIPvarGetData(SCIP_VAR *var)
Definition: var.c:23287
void COLORprobGetStableSet(SCIP *scip, int setindex, int **stableset, int *nelements)
int COLORprobGetNNodes(SCIP *scip)
SCIP_CONS * COLORprobGetConstraint(SCIP *scip, int node)
struct SCIP_BranchruleData SCIP_BRANCHRULEDATA
Definition: type_branch.h:57
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ SCIP_BRANCHED
Definition: type_result.h:54
@ SCIP_PARAMETERWRONGVAL
Definition: type_retcode.h:57
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63