Scippy

    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-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_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#include <assert.h>
    57#include <string.h>
    58
    60#include "pricer_coloring.h"
    61
    62#define BRANCHRULE_NAME "strongcoloring"
    63#define BRANCHRULE_DESC "branching rule template"
    64#define BRANCHRULE_PRIORITY 15000
    65#define BRANCHRULE_MAXDEPTH -1
    66#define BRANCHRULE_MAXBOUNDDIST 1.0
    67
    68/* default values for parameters */
    69#define DEFAULT_BRANCHINGMODE 2
    70#define DEFAULT_FIXINGSSCOREMODE 3
    71#define DEFAULT_MAXPRICINGROUNDS -1
    72#define DEFAULT_USETCLIQUE TRUE
    73#define DEFAULT_LOOKAHEAD 10
    74
    75
    76
    77/*
    78 * Data structures
    79 */
    80
    81/** branching rule data */
    82struct SCIP_BranchruleData
    83{
    84 int branchingmode; /* determines the branchingmode, 0: for fullstrong branching,
    85 1: strong branching, take first possible branching with only one child-node
    86 2: strong branching with prior sorting of candidates w.r.t. the fractional value of concerned sets */
    87 int length; /* length of the arrays samevalue and differvalue, length = n*(n-1)/2 with n = NNodes*/
    88 SCIP_Real* samevalue; /* value of variables, that would be fixed to 0 for same(i,j), index = nodes2index(i,j) */
    89 SCIP_Real* differvalue; /* value of variables, that would be fixed to 0 for differ(i,j), index = nodes2index(i,j) */
    90 SCIP_Real* combinedvalue; /* combination of samevalue and differvalue, computed by computeScore*/
    91 int* permutation; /* permutation of the indexes of the array combinedvalue, s.t. it is sorted */
    92 SCIP_Bool usetclique; /* should the exact pricing with the tclique-algorithm be used for the strongbranchings? */
    93 int maxpricingrounds; /* maximal number of pricing rounds used for each probing node in the strongbranching */
    94 int lookahead; /* number of candidates to be considered in branchingmode 2 */
    95 int fixingsscoremode; /* determines the weightings of the two factors for prior sorting by fractional LP value */
    96
    97};
    98
    99
    100
    101
    102/*
    103 * Local methods
    104 */
    105
    106/** computes a score for the two improvements that are achieved in the two sons for a branching decision */
    107static
    109 SCIP_Real val1, /**< the first value */
    110 SCIP_Real val2 /**< the second value */
    111 )
    112{
    113 return 0.2 * MAX( val1, val2 ) + 0.8 * MIN( val1, val2 );
    114}
    115
    116/** computes a score for the fractional values of the variables that would be fixed to zero for a same- or differ-branching */
    117static
    119 SCIP_Real samevalue, /**< value of the fractional variables fixed to 0 for a same-branching*/
    120 SCIP_Real differvalue, /**< value of the fractional variables fixed to 0 for a differ-branching*/
    121 SCIP_BRANCHRULEDATA* branchruledata /**< branching rule data */
    122 )
    123{
    124 if ( branchruledata->fixingsscoremode == 1 )
    125 {
    126 return 3*samevalue+differvalue;
    127 }
    128 if ( branchruledata->fixingsscoremode == 2 )
    129 {
    130 return 2*samevalue+differvalue;
    131 }
    132 if ( branchruledata->fixingsscoremode == 3 )
    133 {
    134 return samevalue+10*differvalue;
    135 }
    136 if ( branchruledata->fixingsscoremode == 4 )
    137 {
    138 if ( samevalue == -1 && differvalue == -1 )
    139 return -1;
    140 return samevalue*differvalue;
    141 }
    142 return samevalue*differvalue;
    143}
    144
    145/** for given nodes node1, node2, compute the corresponding index in the arrays branchruledata->same-/differvalue */
    146static
    148 SCIP* scip, /**< SCIP data structure */
    149 int node1, /**< the first node */
    150 int node2 /**< the second node */
    151 )
    152{
    153 int ind;
    154 int nnodes;
    155 int i;
    156
    157 assert(scip != NULL);
    158 assert(node1 >= 0 && node2 >= 0);
    159
    160 /* node 1 has to be smaller than node 2 */
    161 if ( node1 > node2 )
    162 {
    163 ind = node1;
    164 node1 = node2;
    165 node2 = ind;
    166 }
    168 assert(node1 < nnodes && node2 < nnodes);
    169 ind = 0;
    170 for ( i = 0; i < node1; i++ )
    171 ind += (nnodes - i - 1);
    172 ind += ( node2-node1-1);
    173 return ind;
    174}
    175
    176/** for given index of the arrays branchruledata->same-/differvalue, compute the two nodes, the index represents */
    177static
    179 SCIP* scip, /**< SCIP data structure */
    180 int ind, /**< the given index in the arrays */
    181 int* node1, /**< return value: the first node */
    182 int* node2 /**< return value: the second node */
    183 )
    184{
    185 int nnodes;
    186 int value;
    187
    188 assert(scip != NULL);
    189 assert(node2 != NULL && node1 != NULL);
    190
    192 *node1 = 0;
    193 value = 0;
    194 while ( value + nnodes - 1 - *node1 <= ind )
    195 {
    196 value += (nnodes - 1 - *node1);
    197 *node1 = *node1 + 1;
    198 }
    199 *node2 = *node1 + 1 + (ind - value);
    200}
    201
    202/** 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
    203 the values of variables with fractional parts, that would be fixed for this decision
    204 asd */
    205static
    207 SCIP* scip, /**< SCIP data structure */
    208 SCIP_BRANCHRULEDATA* branchruledata /**< the data of the branching rule */
    209 )
    210{
    211 SCIP_VAR** lpcands;
    212 SCIP_Real* lpcandsfrac;
    213 TCLIQUE_GRAPH* graph;
    214 int nlpcands;
    215 int i;
    216 int j;
    217 int k;
    218 int node1;
    219 int node2;
    220 SCIP_VAR* var;
    221 int setindex;
    222 int* set;
    223 int setlength;
    224 int nnodes;
    225
    226 assert(scip != NULL);
    227 assert(branchruledata != NULL);
    228
    229 SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, NULL, &lpcandsfrac, &nlpcands, NULL, NULL) );
    232
    233 assert(graph != NULL);
    234 assert(nnodes >= 0);
    235
    236 /* fill array samevalue, differvalue with zeroes, or -1 for impossible branchings */
    237 for ( i = 0; i < branchruledata->length; i++ )
    238 {
    239 index2nodes(scip, i, &node1, &node2);
    240 /* there is an edge between node1 and node2 --> no branching possible --> set value to -1 */
    241 if ( tcliqueIsEdge(graph, node1, node2) )
    242 {
    243 branchruledata->samevalue[i] = -1;
    244 branchruledata->differvalue[i] = -1;
    245 continue;
    246 }
    247 branchruledata->samevalue[i] = 0;
    248 branchruledata->differvalue[i] = 0;
    249 }
    250
    251 /* for all branching candidates (variables with fractional value) check for which branching decisions they would be
    252 fixed to 0 and add the fractional part to the related entry in the array samevalue or differvalue */
    253 for ( i = 0; i < nlpcands; i++ )
    254 {
    255 assert(SCIPisFeasPositive(scip, lpcandsfrac[i]));
    256 var = lpcands[i];
    257 setindex = (int)(size_t) SCIPvarGetData(var);
    258 COLORprobGetStableSet(scip, setindex, &set, &setlength);
    259 for ( j = 0; j < setlength; j++ )
    260 {
    261 node1 = set[j];
    262 /* if node1 is part of a union and not its representant, continue */
    263 if ( COLORconsGetRepresentative(scip, node1) != node1 )
    264 {
    265 continue;
    266 }
    267 k = 0;
    268 for ( node2 = nnodes-1; node2 >= 0; node2-- )
    269 {
    270 /* if k is a node, which is part of, but not representant of a union, increment k */
    271 while ( k < setlength && COLORconsGetRepresentative(scip, set[k]) != set[k] )
    272 {
    273 k++;
    274 }
    275 /* node1 is equal to node2 -> increment k and continue */
    276 if ( node2 == node1 )
    277 {
    278 assert(k == j);
    279 k++;
    280 continue;
    281 }
    282 /* if node2 is part of a union and not its representant, continue */
    283 if ( COLORconsGetRepresentative(scip, node2) != node2 )
    284 continue;
    285 /* if there is an edge between node1 and node2 in the current graph, continue */
    286 if ( branchruledata->differvalue[nodes2index(scip, node1, node2)] == -1 )
    287 {
    288 continue;
    289 }
    290 /* node2 is also in the set --> the variable would be fixed to 0 for differ(node1, node2) */
    291 if ( k < setlength && node2 == set[k] )
    292 {
    293 branchruledata->differvalue[nodes2index(scip, node1, node2)] += lpcandsfrac[i];
    294 assert(COLORprobIsNodeInStableSet(scip, setindex, node1) && COLORprobIsNodeInStableSet(scip, setindex, node2));
    295 k++;
    296 }
    297 /* node2 is not in the set --> the variable would be fixed to 0 for same(node1, node2) */
    298 else
    299 {
    300 branchruledata->samevalue[nodes2index(scip, node1, node2)] += lpcandsfrac[i];
    301 assert(COLORprobIsNodeInStableSet(scip, setindex, node1) && !COLORprobIsNodeInStableSet(scip, setindex, node2));
    302 }
    303 }
    304 assert(k == setlength);
    305 }
    306 }
    307
    308 return SCIP_OKAY;
    309
    310}
    311
    312
    313
    314/** computes the lower bound that would a child node with the given branching decision would have */
    315static
    317 SCIP* scip, /**< SCIP data structure */
    318 COLOR_CONSTYPE constype, /**< the type of the contraint: SAME or DIFFER */
    319 int node1, /**< the first node for the branching constraint */
    320 int node2, /**< the second node for the branching constraint */
    321 SCIP_BRANCHRULEDATA* branchruledata, /**< the data of the branching rule */
    322 SCIP_Real* newlb /**< pointer to store the resulting value */
    323 )
    324{
    325 SCIP_NODE* newnode;
    326 SCIP_CONS* currentcons;
    327 SCIP_CONS* cons;
    328 SCIP_Bool cutoff;
    329 SCIP_Bool lperror;
    330
    331 assert(scip != NULL);
    332 assert(newlb != NULL);
    333
    334 /* get the constraint of the current Node in the B&B-Tree */
    336
    337 /* start Probing */
    339
    340 /* create new probing node and add store graph cons to it with same(node1, node2) */
    342 newnode = SCIPgetCurrentNode(scip);
    343 SCIP_CALL( COLORcreateConsStoreGraph(scip, &cons, "probingcons", currentcons, constype, node1, node2, newnode) );
    344 SCIP_CALL( SCIPaddConsNode(scip, newnode, cons, NULL) );
    345 /* propagate the new b&b-node, i.e. fix vars to 0 that don't contain both node1 and node2 */
    346 SCIP_CALL( SCIPpropagateProbing(scip, -1, &cutoff, NULL) );
    347 /* solve the LP using pricing */
    348 SCIP_CALL( SCIPsolveProbingLPWithPricing(scip, FALSE, FALSE, branchruledata->maxpricingrounds, &lperror, &cutoff) );
    349 assert(!lperror);
    350 assert(!cutoff);
    351 /* get the changed objective value */
    352 *newlb = SCIPgetLPObjval(scip);
    353
    354 SCIP_CALL( SCIPdelCons(scip, cons) );
    355 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
    357
    358 return SCIP_OKAY;
    359}
    360
    361
    362/** index comparison method two values in a real array */
    363static
    364SCIP_DECL_SORTINDCOMP(consdataCompValues)
    365{
    366 SCIP_Real* values;
    367
    368 values = (SCIP_Real*)dataptr;
    369
    370 assert(values != NULL);
    371
    372 if ( values[ind1] > values[ind2] )
    373 {
    374 return -1;
    375 }
    376 if ( values[ind1] < values[ind2] )
    377 {
    378 return 1;
    379 }
    380 return 0;
    381}
    382
    383
    384/*
    385 * Callback methods of branching rule
    386 */
    387
    388/** copy method for branchrule plugins (called when SCIP copies plugins) */
    389static
    390SCIP_DECL_BRANCHCOPY(branchCopyStrongcoloring)
    391{ /*lint --e{715}*/
    392 assert(scip != NULL);
    393 assert(branchrule != NULL);
    394 assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
    395
    396 return SCIP_OKAY;
    397}
    398
    399
    400/** branching execution method for fractional LP solutions */
    401static
    402SCIP_DECL_BRANCHEXECLP(branchExeclpStrongcoloring)
    403{
    404 /* the 2 nodes, for which the branching is done by DIFFER and SAME */
    405 int node1;
    406 int node2;
    407 /* the nodes in the branch&bound-tree which are created */
    408 SCIP_NODE* childsame;
    409 SCIP_NODE* childdiffer;
    410 /* the constraints for the created b&b-nodes */
    411 SCIP_CONS* conssame;
    412 SCIP_CONS* consdiffer;
    413 /* the constraint of the processed b&b-node */
    414 SCIP_CONS* currentcons;
    415
    416 int i;
    417 int j;
    418 int nnodes;
    419
    420 SCIP_Bool* wasnode1;
    421 SCIP_Bool* wasnode2;
    422 SCIP_Bool start;
    423 TCLIQUE_GRAPH* graph;
    424 SCIP_Real currLb;
    425 SCIP_Real sameLb;
    426 SCIP_Real differLb;
    427
    428 SCIP_Real bestscore;
    429 SCIP_Real bestdiffer;
    430 SCIP_Real bestsame;
    431 SCIP_Real score;
    432 int bestnode2;
    433 int bestnode1;
    434
    435 SCIP_BRANCHRULEDATA* branchruledata;
    436
    437#ifndef NDEBUG
    438 SCIP_NODE* node;
    439#endif
    440
    441 assert(scip != NULL);
    442 assert(branchrule != NULL);
    443 assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
    444 assert(result != NULL);
    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:248
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIP_CALL(x)
    Definition: def.h:355
    #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:8486
    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:23287
    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:135
    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
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63