SCIP

    Solving Constraint Integer Programs

    branch_strongcoloring.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_strongcoloring.c
    26 * @brief branching rule performing strong branching for the vertex coloring problem
    27 * @author Gerald Gamrath
    28 *
    29 * This file implements an additional branching rule for the coloring algorithm.
    30 *
    31 * We are looking for two nodes v and w, which are not adjacent in the current graph, and consider
    32 * the following two constraints: SAME(v,w) and DIFFER(v,w). More information about the meaning of
    33 * these constraints can be found in the documentation of the branching rule in branch_coloring.c.
    34 *
    35 * This branching rule puts some more effort into the choice of the two nodes and performs a
    36 * strongbranching. This means that for every possible choice of two nodes, it solves the LPs of the
    37 * created children and computes a score with respect to the increase of the lower bound in both
    38 * nodes. After that, it takes the combination of nodes yielding the best score. The interesting
    39 * point is that the strongbranching is not performed for each variable, as it is done in some
    40 * default branching rules of SCIP and supported by the LP-solver, but is done for a constraint,
    41 * since we are branching on constraints. Look at executeStrongBranching() to see how it is
    42 * done. There are also some improvements, since testing all possible combination of nodes is very
    43 * expensive. The first possibility to avoid this is to stop the computation of scores once a
    44 * possible branching is found that has only one feasible child. This results in more restrictions
    45 * in this child without increasing the number of unprocessed nodes.
    46 *
    47 * The second improvement is to compute a priority for all possible combinations, w.r.t. the
    48 * fractional values of the variables. Then, only the first best k combinations are investigated by
    49 * strongbranching.
    50 *
    51 * This code is not optimized and in most cases inferior to the standard branching rule. It is only
    52 * a demonstration of how to perform strongbranching on constraints!
    53 */
    54
    55/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    56
    58#include "pricer_coloring.h"
    59
    60#define BRANCHRULE_NAME "strongcoloring"
    61#define BRANCHRULE_DESC "branching rule template"
    62#define BRANCHRULE_PRIORITY 15000
    63#define BRANCHRULE_MAXDEPTH -1
    64#define BRANCHRULE_MAXBOUNDDIST 1.0
    65
    66/* default values for parameters */
    67#define DEFAULT_BRANCHINGMODE 2
    68#define DEFAULT_FIXINGSSCOREMODE 3
    69#define DEFAULT_MAXPRICINGROUNDS -1
    70#define DEFAULT_USETCLIQUE TRUE
    71#define DEFAULT_LOOKAHEAD 10
    72
    73
    74
    75/*
    76 * Data structures
    77 */
    78
    79/** branching rule data */
    80struct SCIP_BranchruleData
    81{
    82 int branchingmode; /* determines the branchingmode, 0: for fullstrong branching,
    83 1: strong branching, take first possible branching with only one child-node
    84 2: strong branching with prior sorting of candidates w.r.t. the fractional value of concerned sets */
    85 int length; /* length of the arrays samevalue and differvalue, length = n*(n-1)/2 with n = NNodes*/
    86 SCIP_Real* samevalue; /* value of variables, that would be fixed to 0 for same(i,j), index = nodes2index(i,j) */
    87 SCIP_Real* differvalue; /* value of variables, that would be fixed to 0 for differ(i,j), index = nodes2index(i,j) */
    88 SCIP_Real* combinedvalue; /* combination of samevalue and differvalue, computed by computeScore*/
    89 int* permutation; /* permutation of the indexes of the array combinedvalue, s.t. it is sorted */
    90 SCIP_Bool usetclique; /* should the exact pricing with the tclique-algorithm be used for the strongbranchings? */
    91 int maxpricingrounds; /* maximal number of pricing rounds used for each probing node in the strongbranching */
    92 int lookahead; /* number of candidates to be considered in branchingmode 2 */
    93 int fixingsscoremode; /* determines the weightings of the two factors for prior sorting by fractional LP value */
    94
    95};
    96
    97
    98
    99
    100/*
    101 * Local methods
    102 */
    103
    104/** computes a score for the two improvements that are achieved in the two sons for a branching decision */
    105static
    107 SCIP_Real val1, /**< the first value */
    108 SCIP_Real val2 /**< the second value */
    109 )
    110{
    111 return 0.2 * MAX( val1, val2 ) + 0.8 * MIN( val1, val2 );
    112}
    113
    114/** computes a score for the fractional values of the variables that would be fixed to zero for a same- or differ-branching */
    115static
    117 SCIP_Real samevalue, /**< value of the fractional variables fixed to 0 for a same-branching*/
    118 SCIP_Real differvalue, /**< value of the fractional variables fixed to 0 for a differ-branching*/
    119 SCIP_BRANCHRULEDATA* branchruledata /**< branching rule data */
    120 )
    121{
    122 if ( branchruledata->fixingsscoremode == 1 )
    123 {
    124 return 3*samevalue+differvalue;
    125 }
    126 if ( branchruledata->fixingsscoremode == 2 )
    127 {
    128 return 2*samevalue+differvalue;
    129 }
    130 if ( branchruledata->fixingsscoremode == 3 )
    131 {
    132 return samevalue+10*differvalue;
    133 }
    134 if ( branchruledata->fixingsscoremode == 4 )
    135 {
    136 if ( samevalue == -1 && differvalue == -1 )
    137 return -1;
    138 return samevalue*differvalue;
    139 }
    140 return samevalue*differvalue;
    141}
    142
    143/** for given nodes node1, node2, compute the corresponding index in the arrays branchruledata->same-/differvalue */
    144static
    146 SCIP* scip, /**< SCIP data structure */
    147 int node1, /**< the first node */
    148 int node2 /**< the second node */
    149 )
    150{
    151 int ind;
    152 int nnodes;
    153 int i;
    154
    155 assert(scip != NULL);
    156 assert(node1 >= 0 && node2 >= 0);
    157
    158 /* node 1 has to be smaller than node 2 */
    159 if ( node1 > node2 )
    160 {
    161 ind = node1;
    162 node1 = node2;
    163 node2 = ind;
    164 }
    166 assert(node1 < nnodes && node2 < nnodes);
    167 ind = 0;
    168 for ( i = 0; i < node1; i++ )
    169 ind += (nnodes - i - 1);
    170 ind += ( node2-node1-1);
    171 return ind;
    172}
    173
    174/** for given index of the arrays branchruledata->same-/differvalue, compute the two nodes, the index represents */
    175static
    177 SCIP* scip, /**< SCIP data structure */
    178 int ind, /**< the given index in the arrays */
    179 int* node1, /**< return value: the first node */
    180 int* node2 /**< return value: the second node */
    181 )
    182{
    183 int nnodes;
    184 int value;
    185
    186 assert(scip != NULL);
    187 assert(node2 != NULL && node1 != NULL);
    188
    190 *node1 = 0;
    191 value = 0;
    192 while ( value + nnodes - 1 - *node1 <= ind )
    193 {
    194 value += (nnodes - 1 - *node1);
    195 *node1 = *node1 + 1;
    196 }
    197 *node2 = *node1 + 1 + (ind - value);
    198}
    199
    200/** computes for each pair of nodes (i,j) two values, one for same (i,j), the other for differ(i,j) which are the sum of
    201 the values of variables with fractional parts, that would be fixed for this decision
    202 asd */
    203static
    205 SCIP* scip, /**< SCIP data structure */
    206 SCIP_BRANCHRULEDATA* branchruledata /**< the data of the branching rule */
    207 )
    208{
    209 SCIP_VAR** lpcands;
    210 SCIP_Real* lpcandsfrac;
    211 TCLIQUE_GRAPH* graph;
    212 int nlpcands;
    213 int i;
    214 int j;
    215 int k;
    216 int node1;
    217 int node2;
    218 SCIP_VAR* var;
    219 int setindex;
    220 int* set;
    221 int setlength;
    222 int nnodes;
    223
    224 assert(scip != NULL);
    225 assert(branchruledata != NULL);
    226
    227 SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, NULL, &lpcandsfrac, &nlpcands, NULL, NULL) );
    230
    231 assert(graph != NULL);
    232 assert(nnodes >= 0);
    233
    234 /* fill array samevalue, differvalue with zeroes, or -1 for impossible branchings */
    235 for ( i = 0; i < branchruledata->length; i++ )
    236 {
    237 index2nodes(scip, i, &node1, &node2);
    238 /* there is an edge between node1 and node2 --> no branching possible --> set value to -1 */
    239 if ( tcliqueIsEdge(graph, node1, node2) )
    240 {
    241 branchruledata->samevalue[i] = -1;
    242 branchruledata->differvalue[i] = -1;
    243 continue;
    244 }
    245 branchruledata->samevalue[i] = 0;
    246 branchruledata->differvalue[i] = 0;
    247 }
    248
    249 /* for all branching candidates (variables with fractional value) check for which branching decisions they would be
    250 fixed to 0 and add the fractional part to the related entry in the array samevalue or differvalue */
    251 for ( i = 0; i < nlpcands; i++ )
    252 {
    253 assert(SCIPisFeasPositive(scip, lpcandsfrac[i]));
    254 var = lpcands[i];
    255 setindex = (int)(size_t) SCIPvarGetData(var);
    256 COLORprobGetStableSet(scip, setindex, &set, &setlength);
    257 for ( j = 0; j < setlength; j++ )
    258 {
    259 node1 = set[j];
    260 /* if node1 is part of a union and not its representant, continue */
    261 if ( COLORconsGetRepresentative(scip, node1) != node1 )
    262 {
    263 continue;
    264 }
    265 k = 0;
    266 for ( node2 = nnodes-1; node2 >= 0; node2-- )
    267 {
    268 /* if k is a node, which is part of, but not representant of a union, increment k */
    269 while ( k < setlength && COLORconsGetRepresentative(scip, set[k]) != set[k] )
    270 {
    271 k++;
    272 }
    273 /* node1 is equal to node2 -> increment k and continue */
    274 if ( node2 == node1 )
    275 {
    276 assert(k == j);
    277 k++;
    278 continue;
    279 }
    280 /* if node2 is part of a union and not its representant, continue */
    281 if ( COLORconsGetRepresentative(scip, node2) != node2 )
    282 continue;
    283 /* if there is an edge between node1 and node2 in the current graph, continue */
    284 if ( branchruledata->differvalue[nodes2index(scip, node1, node2)] == -1 )
    285 {
    286 continue;
    287 }
    288 /* node2 is also in the set --> the variable would be fixed to 0 for differ(node1, node2) */
    289 if ( k < setlength && node2 == set[k] )
    290 {
    291 branchruledata->differvalue[nodes2index(scip, node1, node2)] += lpcandsfrac[i];
    292 assert(COLORprobIsNodeInStableSet(scip, setindex, node1) && COLORprobIsNodeInStableSet(scip, setindex, node2));
    293 k++;
    294 }
    295 /* node2 is not in the set --> the variable would be fixed to 0 for same(node1, node2) */
    296 else
    297 {
    298 branchruledata->samevalue[nodes2index(scip, node1, node2)] += lpcandsfrac[i];
    299 assert(COLORprobIsNodeInStableSet(scip, setindex, node1) && !COLORprobIsNodeInStableSet(scip, setindex, node2));
    300 }
    301 }
    302 assert(k == setlength);
    303 }
    304 }
    305
    306 return SCIP_OKAY;
    307
    308}
    309
    310
    311
    312/** computes the lower bound that would a child node with the given branching decision would have */
    313static
    315 SCIP* scip, /**< SCIP data structure */
    316 COLOR_CONSTYPE constype, /**< the type of the contraint: SAME or DIFFER */
    317 int node1, /**< the first node for the branching constraint */
    318 int node2, /**< the second node for the branching constraint */
    319 SCIP_BRANCHRULEDATA* branchruledata, /**< the data of the branching rule */
    320 SCIP_Real* newlb /**< pointer to store the resulting value */
    321 )
    322{
    323 SCIP_NODE* newnode;
    324 SCIP_CONS* currentcons;
    325 SCIP_CONS* cons;
    326 SCIP_Bool cutoff;
    327 SCIP_Bool lperror;
    328
    329 assert(scip != NULL);
    330 assert(newlb != NULL);
    331
    332 /* get the constraint of the current Node in the B&B-Tree */
    334
    335 /* start Probing */
    337
    338 /* create new probing node and add store graph cons to it with same(node1, node2) */
    340 newnode = SCIPgetCurrentNode(scip);
    341 SCIP_CALL( COLORcreateConsStoreGraph(scip, &cons, "probingcons", currentcons, constype, node1, node2, newnode) );
    342 SCIP_CALL( SCIPaddConsNode(scip, newnode, cons, NULL) );
    343 /* propagate the new b&b-node, i.e. fix vars to 0 that don't contain both node1 and node2 */
    344 SCIP_CALL( SCIPpropagateProbing(scip, -1, &cutoff, NULL) );
    345 /* solve the LP using pricing */
    346 SCIP_CALL( SCIPsolveProbingLPWithPricing(scip, FALSE, FALSE, branchruledata->maxpricingrounds, &lperror, &cutoff) );
    347 assert(!lperror);
    348 assert(!cutoff);
    349 /* get the changed objective value */
    350 *newlb = SCIPgetLPObjval(scip);
    351
    352 SCIP_CALL( SCIPdelCons(scip, cons) );
    353 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
    355
    356 return SCIP_OKAY;
    357}
    358
    359
    360/** index comparison method two values in a real array */
    361static
    362SCIP_DECL_SORTINDCOMP(consdataCompValues)
    363{
    364 SCIP_Real* values;
    365
    366 values = (SCIP_Real*)dataptr;
    367
    368 assert(values != NULL);
    369
    370 if ( values[ind1] > values[ind2] )
    371 {
    372 return -1;
    373 }
    374 if ( values[ind1] < values[ind2] )
    375 {
    376 return 1;
    377 }
    378 return 0;
    379}
    380
    381
    382/*
    383 * Callback methods of branching rule
    384 */
    385
    386/** copy method for branchrule plugins (called when SCIP copies plugins) */
    387static
    388SCIP_DECL_BRANCHCOPY(branchCopyStrongcoloring)
    389{ /*lint --e{715}*/
    390 assert(scip != NULL);
    391 assert(branchrule != NULL);
    392
    394
    395 return SCIP_OKAY;
    396}
    397
    398
    399/** branching execution method for fractional LP solutions */
    400static
    401SCIP_DECL_BRANCHEXECLP(branchExeclpStrongcoloring)
    402{
    403 /* the 2 nodes, for which the branching is done by DIFFER and SAME */
    404 int node1;
    405 int node2;
    406 /* the nodes in the branch&bound-tree which are created */
    407 SCIP_NODE* childsame;
    408 SCIP_NODE* childdiffer;
    409 /* the constraints for the created b&b-nodes */
    410 SCIP_CONS* conssame;
    411 SCIP_CONS* consdiffer;
    412 /* the constraint of the processed b&b-node */
    413 SCIP_CONS* currentcons;
    414
    415 int i;
    416 int j;
    417 int nnodes;
    418
    419 SCIP_Bool* wasnode1;
    420 SCIP_Bool* wasnode2;
    421 SCIP_Bool start;
    422 TCLIQUE_GRAPH* graph;
    423 SCIP_Real currLb;
    424 SCIP_Real sameLb;
    425 SCIP_Real differLb;
    426
    427 SCIP_Real bestscore;
    428 SCIP_Real bestdiffer;
    429 SCIP_Real bestsame;
    430 SCIP_Real score;
    431 int bestnode2;
    432 int bestnode1;
    433
    434 SCIP_BRANCHRULEDATA* branchruledata;
    435
    436#ifndef NDEBUG
    437 SCIP_NODE* node;
    438#endif
    439
    440 assert(scip != NULL);
    441 assert(branchrule != NULL);
    442 assert(result != NULL);
    443
    445
    446 *result = SCIP_DIDNOTRUN;
    447
    448 /* get branching rule data */
    449 branchruledata = SCIPbranchruleGetData(branchrule);
    452
    453 if ( branchruledata->branchingmode == 2 )
    454 {
    455 SCIP_CALL( computeBranchingPriorities(scip, branchruledata) );
    456
    457 for ( i = 0; i < branchruledata->length; i++ )
    458 {
    459 branchruledata->combinedvalue[i] = computeFixingsScore(branchruledata->samevalue[i], branchruledata->differvalue[i], branchruledata);
    460 }
    461 /* get permutation of indexes, so that the array is sorted */
    462 /** @todo could be improved by only getting the k best indexes */
    463 SCIPsort(branchruledata->permutation, consdataCompValues, branchruledata->combinedvalue, branchruledata->length);
    464
    465 bestscore = -1;
    466 bestnode1 = -1;
    467 bestnode2 = -1;
    468 bestdiffer = -1;
    469 bestsame = -1;
    470
    471 for ( i = 0; i < branchruledata->lookahead && i < branchruledata->length; i++ )
    472 {
    473 index2nodes(scip, branchruledata->permutation[i], &node1, &node2);
    474 currLb = SCIPgetLPObjval(scip);
    475
    476 /* SAME */
    477 SCIP_CALL( executeStrongBranching(scip, COLOR_CONSTYPE_SAME, node1, node2, branchruledata, &sameLb) );
    478 if ( sameLb-currLb > 1000 )
    479 {
    480 sameLb = currLb + 1000;
    481 }
    482
    483 /* DIFFER */
    484 SCIP_CALL( executeStrongBranching(scip, COLOR_CONSTYPE_DIFFER, node1, node2, branchruledata, &differLb) );
    485 if ( differLb-currLb > 1000 )
    486 {
    487 differLb = currLb + 1000;
    488 }
    489
    490 score = computeScore( sameLb - currLb, differLb-currLb );
    491 assert( !SCIPisFeasZero(scip, score) || (SCIPisFeasZero(scip, 0.2 * (sameLb-currLb)) && SCIPisFeasZero(scip, 0.2 * (differLb-currLb))
    492 && (SCIPisFeasZero(scip, sameLb-currLb) || SCIPisFeasZero(scip, differLb-currLb))) );
    493
    494 if ( score > bestscore )
    495 {
    496 bestscore = score;
    497 bestnode1 = node1;
    498 bestnode2 = node2;
    499 bestdiffer = differLb-currLb;
    500 bestsame = sameLb-currLb;
    501 }
    502 if ( bestdiffer > 999 || bestsame > 999 )
    503 {
    504 break;
    505 }
    506 }
    507
    508 }
    509 else
    510 {
    511 assert(branchruledata->branchingmode == 0 || branchruledata->branchingmode == 1);
    512 /* create array wasnode1 and wasnode2 and fill them with FALSE */
    514 BMSclearMemoryArray(wasnode1, nnodes);
    516
    517 bestscore = -1;
    518 bestnode1 = -1;
    519 bestnode2 = -1;
    520 bestdiffer = -1;
    521 bestsame = -1;
    522
    523 SCIP_CALL( SCIPsetBoolParam(scip, "pricers/coloring/usetclique", branchruledata->usetclique) );
    524#ifndef NDEBUG
    525 node = SCIPgetCurrentNode(scip);
    526#endif
    528
    529 start = TRUE;
    530 for ( i = SCIPgetDepth(scip)%nnodes; (start || (i != SCIPgetDepth(scip)%nnodes)); i=((i+1)%nnodes) ) /*lint !e2840*/
    531 {
    532 start = FALSE;
    534 /* check whether node1 was already tested */
    535 if ( wasnode1[node1] == TRUE )
    536 {
    537 continue;
    538 }
    539 else
    540 {
    541 wasnode1[node1] = TRUE;
    542 }
    543 BMSclearMemoryArray(wasnode2, nnodes);
    544
    545 for ( j = i+1; j < nnodes; j++ )
    546 {
    548 if ( node2 == node1 || tcliqueIsEdge(graph, node1, node2) || node2 < i )
    549 {
    550 continue;
    551 }
    552 else
    553 {
    554 /* check whether node2 was already tested */
    555 if ( wasnode2[node2] == TRUE ) continue;
    556 else wasnode2[node2] = TRUE;
    557
    558 currLb = SCIPgetLPObjval(scip);
    559
    560 assert(currentcons == COLORconsGetActiveStoreGraphCons(scip));
    561 assert(node == SCIPgetCurrentNode(scip));
    562
    563 /* compute lower bounds for possible branchings */
    564
    565 /* SAME */
    566 SCIP_CALL( executeStrongBranching(scip, COLOR_CONSTYPE_SAME, node1, node2, branchruledata, &sameLb) );
    567 if ( sameLb-currLb > 1000 )
    568 {
    569 sameLb = currLb + 1000;
    570 }
    571
    572 /* DIFFER */
    573 SCIP_CALL( executeStrongBranching(scip, COLOR_CONSTYPE_DIFFER, node1, node2, branchruledata, &differLb) );
    574 if ( differLb-currLb > 1000 )
    575 {
    576 differLb = currLb + 1000;
    577 }
    578
    579 score = computeScore( sameLb-currLb, differLb-currLb );
    580 if ( score > bestscore )
    581 {
    582 bestscore = score;
    583 bestnode1 = node1;
    584 bestnode2 = node2;
    585 bestdiffer = differLb-currLb;
    586 bestsame = sameLb-currLb;
    587 }
    588 if ( (branchruledata->branchingmode == 1) && (bestdiffer > 999 || bestsame > 999) )
    589 {
    590 break;
    591 }
    592
    593 }
    594 }
    595 if ( (branchruledata->branchingmode == 1) && (bestdiffer > 999 || bestsame > 999) )
    596 {
    597 break;
    598 }
    599 }
    600
    601 SCIP_CALL( SCIPsetBoolParam(scip, "pricers/coloring/usetclique", TRUE) );
    602 assert(node == SCIPgetCurrentNode(scip));
    603 assert(currentcons == COLORconsGetActiveStoreGraphCons(scip));
    604
    605 SCIPfreeBufferArray(scip, &wasnode2);
    606 SCIPfreeBufferArray(scip, &wasnode1);
    607
    608 }
    609
    610 assert(!SCIPisSumNegative(scip, bestscore));
    611
    612 node1 = bestnode1;
    613 node2 = bestnode2;
    614
    615 /* branchingmode >= 1 --> only create nodes, that do not have a LP solution that is much bigger than the lower bound */
    616 if ( branchruledata->branchingmode >= 1 && branchruledata->usetclique == TRUE )
    617 {
    618 *result = SCIP_CUTOFF;
    620
    621 if ( bestdiffer <= 999 )
    622 {
    623 /* create the b&b-tree child-nodes of the current node */
    625
    626 /* create corresponding constraints */
    627 SCIP_CALL( COLORcreateConsStoreGraph(scip, &consdiffer, "differ", currentcons, COLOR_CONSTYPE_DIFFER, node1, node2, childdiffer) );
    628
    629 /* add constraints to nodes */
    630 SCIP_CALL( SCIPaddConsNode(scip, childdiffer, consdiffer, NULL) );
    631
    632 /* release constraints */
    633 SCIP_CALL( SCIPreleaseCons(scip, &consdiffer) );
    634
    635 *result = SCIP_BRANCHED;
    636 }
    637
    638 if ( bestsame <= 999 )
    639 {
    640 /* create the b&b-tree child-nodes of the current node */
    642
    643 /* create corresponding constraints */
    644 SCIP_CALL( COLORcreateConsStoreGraph(scip, &conssame, "same", currentcons, COLOR_CONSTYPE_SAME, node1, node2, childsame) );
    645
    646 /* add constraints to nodes */
    647 SCIP_CALL( SCIPaddConsNode(scip, childsame, conssame, NULL) );
    648
    649 /* release constraints */
    650 SCIP_CALL( SCIPreleaseCons(scip, &conssame) );
    651
    652 *result = SCIP_BRANCHED;
    653 }
    654 }
    655 /* create both children */
    656 else
    657 {
    660
    661 /* create the b&b-tree child-nodes of the current node */
    664
    665 /* create corresponding constraints */
    667 SCIP_CALL( COLORcreateConsStoreGraph(scip, &conssame, "same", currentcons, COLOR_CONSTYPE_SAME, node1, node2, childsame) );
    668 SCIP_CALL( COLORcreateConsStoreGraph(scip, &consdiffer, "differ", currentcons, COLOR_CONSTYPE_DIFFER, node1, node2, childdiffer) );
    669
    670 /* add constraints to nodes */
    671 SCIP_CALL( SCIPaddConsNode(scip, childsame, conssame, NULL) );
    672 SCIP_CALL( SCIPaddConsNode(scip, childdiffer, consdiffer, NULL) );
    673
    674 /* release constraints */
    675 SCIP_CALL( SCIPreleaseCons(scip, &conssame) );
    676 SCIP_CALL( SCIPreleaseCons(scip, &consdiffer) );
    677
    678 *result = SCIP_BRANCHED;
    679 }
    680
    681 return SCIP_OKAY;
    682}/*lint !e715*/
    683
    684
    685/** destructor of branching rule to free user data (called when SCIP is exiting) */
    686static
    687SCIP_DECL_BRANCHFREE(branchFreeStrongcoloring)
    688{
    689 SCIP_BRANCHRULEDATA* branchruledata;
    690
    691 /* free branching rule data */
    692 branchruledata = SCIPbranchruleGetData(branchrule);
    693 SCIPfreeBlockMemory(scip, &branchruledata);
    694 SCIPbranchruleSetData(branchrule, NULL);
    695
    696 return SCIP_OKAY;
    697}
    698
    699/** initialization method of branching rule (called after problem was transformed) */
    700static
    701SCIP_DECL_BRANCHINIT(branchInitStrongcoloring)
    702{
    703 SCIP_BRANCHRULEDATA* branchruledata;
    704
    705 /* get branching rule data */
    706 branchruledata = SCIPbranchruleGetData(branchrule);
    707 assert(branchruledata != NULL);
    708
    709 /* get memory for the arrays */
    710 branchruledata->length = (COLORprobGetNNodes(scip)*(COLORprobGetNNodes(scip)-1))/2;
    711 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(branchruledata->samevalue), branchruledata->length) );
    712 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(branchruledata->differvalue), branchruledata->length) );
    713 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(branchruledata->combinedvalue), branchruledata->length) );
    714 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(branchruledata->permutation), branchruledata->length) );
    715
    716 return SCIP_OKAY;
    717}
    718
    719/** deinitialization method of branching rule (called before transformed problem is freed) */
    720static
    721SCIP_DECL_BRANCHEXIT(branchExitStrongcoloring)
    722{
    723 SCIP_BRANCHRULEDATA* branchruledata;
    724
    725 /* get branching rule data */
    726 branchruledata = SCIPbranchruleGetData(branchrule);
    727 assert(branchruledata != NULL);
    728
    729 /* free arrays */
    730 SCIPfreeBlockMemoryArray(scip, &(branchruledata->samevalue), branchruledata->length);
    731 SCIPfreeBlockMemoryArray(scip, &(branchruledata->differvalue), branchruledata->length);
    732 SCIPfreeBlockMemoryArray(scip, &(branchruledata->combinedvalue), branchruledata->length);
    733 SCIPfreeBlockMemoryArray(scip, &(branchruledata->permutation), branchruledata->length);
    734
    735 return SCIP_OKAY;
    736}
    737
    738/*
    739 * branching rule specific interface methods
    740 */
    741
    742/** creates the coloring branching rule and includes it in SCIP */
    744 SCIP* scip /**< SCIP data structure */
    745 )
    746{
    747 SCIP_BRANCHRULEDATA* branchruledata;
    748 SCIP_BRANCHRULE* branchrule;
    749
    750 assert(scip != NULL);
    751
    752 /* create branching rule data */
    753 SCIP_CALL( SCIPallocBlockMemory(scip, &branchruledata) );
    754
    755 branchrule = NULL;
    756 /* include branching rule */
    758 BRANCHRULE_MAXBOUNDDIST, branchruledata) );
    759 assert(branchrule != NULL);
    760
    761 SCIP_CALL( SCIPsetBranchruleCopy(scip, branchrule, branchCopyStrongcoloring) );
    762 SCIP_CALL( SCIPsetBranchruleFree(scip, branchrule, branchFreeStrongcoloring) );
    763 SCIP_CALL( SCIPsetBranchruleExecLp(scip, branchrule, branchExeclpStrongcoloring) );
    764 SCIP_CALL( SCIPsetBranchruleInit(scip, branchrule, branchInitStrongcoloring) );
    765 SCIP_CALL( SCIPsetBranchruleExit(scip, branchrule, branchExitStrongcoloring) );
    766
    767
    769 "branching/strongcoloring/lookahead",
    770 "number of candidates to be considered in branchingmode 2",
    771 &branchruledata->lookahead, TRUE, DEFAULT_LOOKAHEAD, 0, INT_MAX, NULL, NULL) );
    772
    774 "branching/strongcoloring/usetclique",
    775 "should the exact pricing with the tclique-algorithm be used for the strongbranchings?",
    776 &branchruledata->usetclique, FALSE, DEFAULT_USETCLIQUE, NULL, NULL) );
    777
    779 "branching/strongcoloring/maxpricingrounds",
    780 "maximal number of pricing rounds used for each probing node in the strongbranching",
    781 &branchruledata->maxpricingrounds, TRUE, DEFAULT_MAXPRICINGROUNDS, -1, INT_MAX, NULL, NULL) );
    782
    784 "branching/strongcoloring/branchingmode",
    785 "determines the branchingmode, 0: fullstrong branching, 1: strong branching, take first possible branching with only one child-node, 2: strong branching with prior sorting of candidates w.r.t. the fractional value of concerned sets */",
    786 &branchruledata->branchingmode, FALSE, DEFAULT_BRANCHINGMODE, 0, 2, NULL, NULL) );
    787
    789 "branching/strongcoloring/fixingsscoremode",
    790 "determines the weightings of the two factors for prior sorting by fractional LP value",
    791 &branchruledata->fixingsscoremode, TRUE, DEFAULT_FIXINGSSCOREMODE, 0, 4, NULL, NULL) );
    792
    793 return SCIP_OKAY;
    794}
    #define BRANCHRULE_DESC
    static SCIP_DECL_SORTINDCOMP(consdataCompValues)
    #define BRANCHRULE_PRIORITY
    static double computeScore(SCIP_Real val1, SCIP_Real val2)
    static SCIP_RETCODE executeStrongBranching(SCIP *scip, COLOR_CONSTYPE constype, int node1, int node2, SCIP_BRANCHRULEDATA *branchruledata, SCIP_Real *newlb)
    SCIP_RETCODE SCIPincludeBranchruleStrongcoloring(SCIP *scip)
    static SCIP_DECL_BRANCHEXIT(branchExitStrongcoloring)
    static int nodes2index(SCIP *scip, int node1, int node2)
    static SCIP_DECL_BRANCHCOPY(branchCopyStrongcoloring)
    #define BRANCHRULE_NAME
    static void index2nodes(SCIP *scip, int ind, int *node1, int *node2)
    #define DEFAULT_MAXPRICINGROUNDS
    #define DEFAULT_USETCLIQUE
    static SCIP_DECL_BRANCHINIT(branchInitStrongcoloring)
    static SCIP_DECL_BRANCHFREE(branchFreeStrongcoloring)
    #define DEFAULT_BRANCHINGMODE
    #define DEFAULT_LOOKAHEAD
    static SCIP_DECL_BRANCHEXECLP(branchExeclpStrongcoloring)
    static SCIP_Real computeFixingsScore(SCIP_Real samevalue, SCIP_Real differvalue, SCIP_BRANCHRULEDATA *branchruledata)
    #define BRANCHRULE_MAXDEPTH
    static SCIP_RETCODE computeBranchingPriorities(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata)
    #define DEFAULT_FIXINGSSCOREMODE
    #define BRANCHRULE_MAXBOUNDDIST
    branching rule performing strong branching 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
    enum COLOR_ConsType COLOR_CONSTYPE
    #define NULL
    Definition: def.h:257
    #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 MAX(x, y)
    Definition: def.h:229
    #define SCIP_CALL(x)
    Definition: def.h:364
    #define nnodes
    Definition: gastrans.c:74
    SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3420
    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 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 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 SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
    Definition: scip_param.c:429
    SCIP_RETCODE SCIPsetBranchruleExit(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXIT((*branchexit)))
    Definition: scip_branch.c:208
    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
    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
    SCIP_RETCODE SCIPsetBranchruleInit(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHINIT((*branchinit)))
    Definition: scip_branch.c:192
    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
    SCIP_Real SCIPgetLPObjval(SCIP *scip)
    Definition: scip_lp.c:253
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    SCIP_RETCODE SCIPpropagateProbing(SCIP *scip, int maxproprounds, SCIP_Bool *cutoff, SCIP_Longint *ndomredsfound)
    Definition: scip_probing.c:581
    SCIP_RETCODE SCIPstartProbing(SCIP *scip)
    Definition: scip_probing.c:120
    SCIP_RETCODE SCIPnewProbingNode(SCIP *scip)
    Definition: scip_probing.c:166
    SCIP_RETCODE SCIPendProbing(SCIP *scip)
    Definition: scip_probing.c:261
    SCIP_RETCODE SCIPsolveProbingLPWithPricing(SCIP *scip, SCIP_Bool pretendroot, SCIP_Bool displayinfo, int maxpricerounds, SCIP_Bool *lperror, SCIP_Bool *cutoff)
    Definition: scip_probing.c:849
    SCIP_Bool SCIPisSumNegative(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
    int SCIPgetDepth(SCIP *scip)
    Definition: scip_tree.c:672
    SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
    Definition: scip_tree.c:91
    SCIP_VARDATA * SCIPvarGetData(SCIP_VAR *var)
    Definition: var.c:23319
    void SCIPsort(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
    Definition: misc.c:5581
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    variable pricer for the vertex coloring problem
    void COLORprobGetStableSet(SCIP *scip, int setindex, int **stableset, int *nelements)
    int COLORprobGetNNodes(SCIP *scip)
    SCIP_CONS * COLORprobGetConstraint(SCIP *scip, int node)
    SCIP_Bool COLORprobIsNodeInStableSet(SCIP *scip, int setindex, int node)
    Definition: heur_padm.c:132
    struct TCLIQUE_Graph TCLIQUE_GRAPH
    Definition: tclique.h:49
    struct SCIP_BranchruleData SCIP_BRANCHRULEDATA
    Definition: type_branch.h:57
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_CUTOFF
    Definition: type_result.h:48
    @ SCIP_BRANCHED
    Definition: type_result.h:54
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63