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-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 */
    88 SCIP_VAR** lpcands;
    89 SCIP_Real* lpcandsfrac;
    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
    136 *result = SCIP_DIDNOTRUN;
    137
    138 /* get branching candidates */
    139 SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, NULL, &lpcandsfrac, NULL, &nlpcands, NULL) );
    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
    307 *result = SCIP_BRANCHED;
    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
    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
    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
    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: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)
    Definition: cons_setppc.c:9683
    SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
    Definition: cons_setppc.c:9701
    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: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
    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
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63