SCIP

    Solving Constraint Integer Programs

    event_solvingphase.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 event_solvingphase.c
    26 * @ingroup DEFPLUGINS_EVENT
    27 * @brief event handler for solving phase dependent parameter adjustment
    28 * @author Gregor Hendel
    29 *
    30 * this event handler provides methods to support parameter adjustment at every new of the three solving phases:
    31 * - Feasibility phase - before the first solution is found
    32 * - Improvement phase - after the first solution was found until an optimal solution is found or believed to be found
    33 * - Proof phase - the remaining time of the solution process after an optimal or believed-to-be optimal incumbent has been found.
    34 *
    35 * Of course, this event handler cannot detect by itself whether a given incumbent is optimal prior to termination of the
    36 * solution process. It rather uses heuristic transitions based on properties of the search tree in order to
    37 * determine the appropriate stage. Settings files can be passed to this event handler for each of the three phases.
    38 *
    39 * This approach of phase-based parameter adjustment was first presented in
    40 *
    41 * Gregor Hendel
    42 * Empirical Analysis of Solving Phases in Mixed-Integer Programming
    43 * Master thesis, Technical University Berlin (2014)
    44 *
    45 * with the main results also available from
    46 *
    47 * Gregor Hendel
    48 * Exploiting solving phases in mixed-integer programs (2015)
    49 */
    50
    51/*--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    52
    54#include "scip/pub_disp.h"
    55#include "scip/pub_event.h"
    56#include "scip/pub_message.h"
    57#include "scip/pub_misc.h"
    58#include "scip/pub_misc_sort.h"
    59#include "scip/pub_paramset.h"
    60#include "scip/pub_tree.h"
    61#include "scip/scip_disp.h"
    62#include "scip/scip_event.h"
    63#include "scip/scip_general.h"
    64#include "scip/scip_mem.h"
    65#include "scip/scip_message.h"
    66#include "scip/scip_numerics.h"
    67#include "scip/scip_param.h"
    68#include "scip/scip_sol.h"
    69#include "scip/scip_solve.h"
    71#include "scip/scip_timing.h"
    72#include "scip/scip_tree.h"
    73
    74
    75#define EVENTHDLR_NAME "solvingphase"
    76#define EVENTHDLR_DESC "event handler to adjust settings depending on current stage"
    77
    78#define EVENTHDLR_EVENT SCIP_EVENTTYPE_BESTSOLFOUND | SCIP_EVENTTYPE_NODEBRANCHED | SCIP_EVENTTYPE_NODEFOCUSED /**< the actual event to be caught */
    79#define TRANSITIONMETHODS "elor" /**< which heuristic transition method: (e)stimate based, (l)ogarithmic regression based, (o)ptimal value based (cheat!),
    80 * (r)ank-1 node based? */
    81#define DEFAULT_SETNAME "-" /**< default settings file name for solving phase setting files */
    82#define DEFAULT_TRANSITIONMETHOD 'r' /**< the default transition method */
    83#define DEFAULT_NODEOFFSET 50L /**< default node offset before transition to proof phase is active */
    84#define DEFAULT_FALLBACK FALSE /**< should the phase transition fall back to suboptimal phase? */
    85#define DEFAULT_INTERRUPTOPTIMAL FALSE /**< should solving process be interrupted if optimal solution was found? */
    86
    87#define DEFAULT_ENABLED FALSE /**< should the event handler be executed? */
    88#define DEFAULT_TESTMODE FALSE /**< should the event handler test the criteria? */
    89
    90#define DEFAULT_USERESTART1TO2 FALSE /**< should a restart be applied between the feasibility and improvement phase? */
    91#define DEFAULT_USERESTART2TO3 FALSE /**< should a restart be applied between the improvement and the proof phase? */
    92#define DEFAULT_USEEMPHSETTINGS TRUE /**< should emphasis settings be used for the different solving phases, or settings files? */
    93
    94/* logarithmic regression settings */
    95#define DEFAULT_LOGREGRESSION_XTYPE 'n' /**< default type to use for log regression - (t)ime, (n)odes, (l)p iterations */
    96#define LOGREGRESSION_XTYPES "lnt" /**< available types for log regression - (t)ime, (n)odes, (l)p iterations */
    97/*
    98 * Data structures
    99 */
    100
    101/** depth information structure */
    103{
    104 int nsolvednodes; /**< number of nodes that were solved so far at this depth */
    105 SCIP_Real minestimate; /**< the minimum estimate of a solved node */
    106 SCIP_NODE** minnodes; /**< points to the rank-1 nodes at this depth (open nodes whose estimate is lower than current
    107 minimum estimate over solved nodes) */
    108 int nminnodes; /**< the number of minimum nodes */
    109 int minnodescapacity; /**< the capacity of the min nodes array */
    110};
    111
    112typedef struct DepthInfo DEPTHINFO;
    113
    114/** event handler data */
    115struct SCIP_EventhdlrData
    116{
    117 char logregression_xtype;/**< type to use for log regression - (t)ime, (n)odes, (l)p iterations */
    118 SCIP_Bool enabled; /**< should the event handler be executed? */
    119 char* feassetname; /**< settings file parameter for the feasibility phase -- precedence over emphasis settings */
    120 char* improvesetname; /**< settings file parameter for the improvement phase -- precedence over emphasis settings */
    121 char* proofsetname; /**< settings file parameter for the proof phase -- precedence over emphasis settings */
    122 SCIP_Real optimalvalue; /**< value of optimal solution of the problem */
    123 SCIP_Longint nnodesleft; /**< store the number of open nodes that are considered internally to update data */
    124 SCIP_SOLVINGPHASE solvingphase; /**< the current solving phase */
    125 SCIP_SOLVINGPHASEFLAG phaseflags; /**< bit field of reached transition criteria */
    126 char transitionmethod; /**< transition method from improvement phase -> proof phase?
    127 * (e)stimate based, (l)ogarithmic regression based, (o)ptimal value based (cheat!),
    128 * (r)ank-1 node based */
    129 SCIP_Longint nodeoffset; /**< node offset for triggering rank-1 node based phased transition */
    130 SCIP_Longint lastndelayedcutoffs; /**< the number of delayed cutoffs since the last update of a focus node */
    131 SCIP_Bool fallback; /**< should the phase transition fall back to improvement phase? */
    132 SCIP_Bool interruptoptimal; /**< interrupt after optimal solution was found */
    133 SCIP_Bool userestart1to2; /**< should a restart be applied between the feasibility and improvement phase? */
    134 SCIP_Bool userestart2to3; /**< should a restart be applied between the improvement and the proof phase? */
    135 SCIP_Bool useemphsettings; /**< should emphasis settings for the solving phases be used, or settings files? */
    136 SCIP_Bool testmode; /**< should transitions be tested only, but not triggered? */
    137 SCIP_Bool newbestsol; /**< has a new incumbent been found since the last node was solved? */
    138
    139 SCIP_REGRESSION* regression; /**< regression data for log linear regression of the incumbent solutions */
    140 SCIP_Real lastx; /**< X-value of last observation */
    141 SCIP_Real lasty; /**< Y-value of last observation */
    142 SCIP_PARAM** nondefaultparams; /**< parameters with non-default values during problem initialization */
    143 int nnondefaultparams; /**< number of parameters with non-default values during problem initialization */
    144 int nondefaultparamssize;/**< capacity of the array of non-default parameters */
    145 int eventfilterpos; /**< the event filter position, or -1, if event has not (yet) been caught */
    146 DEPTHINFO** depthinfos; /**< array of depth infos for every depth of the search tree */
    147 int maxdepth; /**< maximum depth so far */
    148 int nrank1nodes; /**< number of rank-1 nodes */
    149 int nnodesbelowincumbent;/**< number of open nodes with an estimate lower than the current incumbent */
    150};
    151
    152
    153/*
    154 * methods for rank-1 and active estimate transition
    155 */
    156
    157/** nodes are sorted first by their estimates, and if estimates are equal, by their number */
    158static
    159SCIP_DECL_SORTPTRCOMP(sortCompTreeinfo)
    160{
    161 SCIP_NODE* node1;
    162 SCIP_NODE* node2;
    163 SCIP_Real estim1;
    164 SCIP_Real estim2;
    165 node1 = (SCIP_NODE*)elem1;
    166 node2 = (SCIP_NODE*)elem2;
    167
    168 estim1 = SCIPnodeGetEstimate(node1);
    169 estim2 = SCIPnodeGetEstimate(node2);
    170
    171 /* compare estimates */
    172 if( estim1 < estim2 )
    173 return -1;
    174 else if( estim1 > estim2 )
    175 return 1;
    176 else
    177 {
    178 SCIP_Longint number1;
    179 SCIP_Longint number2;
    180
    181 number1 = SCIPnodeGetNumber(node1);
    182 number2 = SCIPnodeGetNumber(node2);
    183
    184 /* compare numbers */
    185 if( number1 < number2 )
    186 return -1;
    187 else if( number1 > number2 )
    188 return 1;
    189 }
    190
    191 return 0;
    192}
    193
    194/** insert an array of open nodes (leaves/siblings/children) into the event handler data structures and update the transition information */
    195static
    197 SCIP* scip, /**< SCIP data structure */
    198 SCIP_EVENTHDLRDATA* eventhdlrdata, /**< event handler data */
    199 SCIP_NODE** nodes, /**< array of nodes */
    200 int nnodes /**< number of nodes */
    201 )
    202{
    203 int n;
    204
    205 assert(nnodes == 0 || nodes != NULL);
    206 assert(scip != NULL);
    207 assert(eventhdlrdata->depthinfos != NULL);
    208
    209 /* store every relevant node in the data structure for its depth */
    210 for( n = 0; n < nnodes; ++n )
    211 {
    212 SCIP_NODE* node = nodes[n];
    213 DEPTHINFO* depthinfo = eventhdlrdata->depthinfos[SCIPnodeGetDepth(node)];
    214 SCIP_Real estim = SCIPnodeGetEstimate(node);
    215
    218
    219 /* an open node has rank 1 if it has an estimate at least as small as the best solved node at this depth */
    220 if( depthinfo->nsolvednodes == 0 || SCIPisGE(scip, depthinfo->minestimate, SCIPnodeGetEstimate(node)) )
    221 {
    222 int pos;
    223
    224 /* allocate additional memory to hold new node */
    225 if( depthinfo->nminnodes == depthinfo->minnodescapacity )
    226 {
    227 int oldcapacity = depthinfo->minnodescapacity;
    228 depthinfo->minnodescapacity *= 2;
    229 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &depthinfo->minnodes, oldcapacity, depthinfo->minnodescapacity) );
    230 }
    231
    232 /* find correct insert position */
    233 SCIPsortedvecInsertPtr((void **)depthinfo->minnodes, sortCompTreeinfo, (void*)node, &depthinfo->nminnodes, &pos);
    234 assert(pos >= 0 && pos < depthinfo->nminnodes);
    235 assert(depthinfo->minnodes[pos] == node);
    236
    237 /* update rank 1 node information */
    238 ++eventhdlrdata->nrank1nodes;
    239 }
    240
    241 /* update active estimate information by bookkeeping nodes with an estimate smaller than the current incumbent */
    242 if( SCIPisLT(scip, estim, SCIPgetUpperbound(scip) ) )
    243 ++eventhdlrdata->nnodesbelowincumbent;
    244 }
    245
    246 /* update the number of open search nodes */
    247 eventhdlrdata->nnodesleft += nnodes;
    248
    249 return SCIP_OKAY;
    250}
    251
    252/** remove a node from the data structures of the event handler */
    253static
    255 SCIP_NODE* node, /**< node that should be removed */
    256 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
    257 )
    258{
    259 DEPTHINFO* depthinfo;
    260 int pos;
    261 SCIP_Bool contained;
    262
    263 assert(node != NULL);
    264
    265 /* get depth information for the depth of this node */
    266 depthinfo = eventhdlrdata->depthinfos[SCIPnodeGetDepth(node)];
    267
    268 /* no node is saved at this depth */
    269 if( depthinfo->nminnodes == 0 )
    270 return;
    271
    272 /* search for the node by using binary search */
    273 contained = SCIPsortedvecFindPtr((void **)depthinfo->minnodes, sortCompTreeinfo, (void *)node, depthinfo->nminnodes, &pos);
    274
    275 /* remove the node if it is contained */
    276 if( contained )
    277 {
    278 SCIPsortedvecDelPosPtr((void **)depthinfo->minnodes, sortCompTreeinfo, pos, &(depthinfo->nminnodes));
    279 --eventhdlrdata->nrank1nodes;
    280 }
    281}
    282
    283/** returns the current number of rank 1 nodes in the tree */
    284static
    286 SCIP* scip /**< SCIP data structure */
    287 )
    288{
    289 SCIP_EVENTHDLRDATA* eventhdlrdata;
    290
    291 assert(scip != NULL);
    292
    294
    295 /* return the stored number of rank 1 nodes only during solving stage */
    297 return eventhdlrdata->nrank1nodes;
    298 else
    299 return -1;
    300}
    301
    302/** returns the current number of open nodes which have an estimate lower than the incumbent solution */
    303static
    305 SCIP* scip /**< SCIP data structure */
    306 )
    307{
    308 SCIP_EVENTHDLRDATA* eventhdlrdata;
    309
    310 assert(scip != NULL);
    311
    313
    314 /* return the stored number of nodes only during solving stage */
    316 return eventhdlrdata->nnodesbelowincumbent;
    317 else
    318 return -1;
    319}
    320
    321/** discards all previous node information and renews it */
    322static
    324 SCIP* scip, /**< SCIP data structure */
    325 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
    326 )
    327{
    328 SCIP_NODE** leaves;
    329 SCIP_NODE** children;
    330 SCIP_NODE** siblings;
    331
    332 int nleaves;
    333 int nchildren;
    334 int nsiblings;
    335 int d;
    336
    337 /* the required node information is only available after solving started */
    339 return SCIP_OKAY;
    340
    341 assert(eventhdlrdata != NULL);
    342
    343 /* reset depth information */
    344 for( d = 0; d < eventhdlrdata->maxdepth; ++d )
    345 eventhdlrdata->depthinfos[d]->nminnodes = 0;
    346
    347 eventhdlrdata->nrank1nodes = 0;
    348 eventhdlrdata->nnodesbelowincumbent = 0;
    349 eventhdlrdata->nnodesleft = 0;
    350
    351 nleaves = nchildren = nsiblings = 0;
    352
    353 /* get leaves, children, and sibling arrays and update the event handler data structures */
    354 SCIP_CALL( SCIPgetOpenNodesData(scip, &leaves, &children, &siblings, &nleaves, &nchildren, &nsiblings) );
    355
    356 SCIP_CALL ( addNodesInformation(scip, eventhdlrdata, children, nchildren) );
    357
    358 SCIP_CALL ( addNodesInformation(scip, eventhdlrdata, siblings, nsiblings) );
    359
    360 SCIP_CALL ( addNodesInformation(scip, eventhdlrdata, leaves, nleaves) );
    361
    362 /* information needs to be recomputed from scratch if a new incumbent is found */
    363 eventhdlrdata->newbestsol = FALSE;
    364
    365 return SCIP_OKAY;
    366}
    367
    368/** allocates memory for a depth info */
    369static
    371 SCIP* scip, /**< SCIP data structure */
    372 DEPTHINFO** depthinfo /**< pointer to depth information structure */
    373 )
    374{
    375 assert(scip != NULL);
    376 assert(depthinfo != NULL);
    377
    378 /* allocate the necessary memory */
    379 SCIP_CALL( SCIPallocBlockMemory(scip, depthinfo) );
    380
    381 /* reset the depth information */
    382 (*depthinfo)->minestimate = SCIPinfinity(scip);
    383 (*depthinfo)->nsolvednodes = 0;
    384 (*depthinfo)->nminnodes = 0;
    385 (*depthinfo)->minnodescapacity = 2;
    386
    387 /* allocate array to store nodes */
    388 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*depthinfo)->minnodes, (*depthinfo)->minnodescapacity) );
    389
    390 return SCIP_OKAY;
    391}
    392
    393/** frees depth information data structure */
    394static
    396 SCIP* scip, /**< SCIP data structure */
    397 DEPTHINFO** depthinfo /**< pointer to depth information structure */
    398 )
    399{
    400 assert(scip != NULL);
    401 assert(depthinfo != NULL);
    402 assert(*depthinfo != NULL);
    403 assert((*depthinfo)->minnodes != NULL);
    404
    405 /* free nodes data structure and then the structure itself */
    406 SCIPfreeBlockMemoryArray(scip, &(*depthinfo)->minnodes, (*depthinfo)->minnodescapacity);
    407 SCIPfreeBlockMemory(scip, depthinfo);
    408
    409 return SCIP_OKAY;
    410}
    411
    412/** removes the node itself and updates the data if this node defined an active estimate globally or locally at its depth level */
    413static
    415 SCIP* scip, /**< SCIP data structure */
    416 SCIP_EVENTHDLRDATA* eventhdlrdata, /**< event handler data */
    417 SCIP_NODE* node /**< node to be removed from the data structures of the event handler */
    418 )
    419{
    420 DEPTHINFO* depthinfo;
    421
    422 assert(scip != NULL);
    423 assert(node != NULL);
    424 assert(eventhdlrdata != NULL);
    425
    426 /* get the correct depth info at the node depth */
    427 depthinfo = eventhdlrdata->depthinfos[SCIPnodeGetDepth(node)];
    428 assert(depthinfo != NULL);
    429
    430 /* remove the node from the data structures */
    431 removeNode(node, eventhdlrdata);
    432
    433 /* compare the node estimate to the minimum estimate of the particular depth */
    434 if( SCIPisLT(scip, SCIPnodeGetEstimate(node), depthinfo->minestimate) )
    435 depthinfo->minestimate = SCIPnodeGetEstimate(node);
    436
    437 /* decrease counter of active estimate nodes if node has an estimate that is below the current incumbent */
    439 eventhdlrdata->nnodesbelowincumbent--;
    440
    441 /* loop over remaining, unsolved nodes and decide whether they are still rank-1 nodes */
    442 while( depthinfo->nminnodes > 0 && SCIPisGT(scip, SCIPnodeGetEstimate(depthinfo->minnodes[depthinfo->nminnodes - 1]), depthinfo->minestimate) )
    443 {
    444 /* forget about node */
    445 --(depthinfo->nminnodes);
    446 --(eventhdlrdata->nrank1nodes);
    447 }
    448
    449 /* increase the number of solved nodes at this depth */
    450 ++(depthinfo->nsolvednodes);
    451
    452 /* decrease the counter for the number of open nodes */
    453 --eventhdlrdata->nnodesleft;
    454}
    455
    456/** ensures sufficient size for depthInfo array */
    457static
    459 SCIP* scip, /**< SCIP data structure */
    460 SCIP_EVENTHDLRDATA* eventhdlrdata, /**< event handler data */
    461 SCIP_NODE* node /**< node to be removed from the data structures of the event handler */
    462 )
    463{
    464 int nodedepth;
    465 int newsize;
    466 int oldsize;
    467 nodedepth = SCIPnodeGetDepth(node);
    468 oldsize = eventhdlrdata->maxdepth;
    469 newsize = oldsize;
    470
    471 /* create depth info array with small initial size or enlarge the existing array if new node is deeper */
    472 if( oldsize == 0 )
    473 {
    474 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &eventhdlrdata->depthinfos, 10) );
    475 newsize = 10;
    476 }
    477 else if( nodedepth + 1 >= eventhdlrdata->maxdepth )
    478 {
    479 assert(nodedepth > 0);
    480 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &eventhdlrdata->depthinfos, oldsize, 2 * nodedepth) ); /*lint !e647*/
    481 newsize = 2 * nodedepth;
    482 }
    483
    484 /* create the according depth information pointers */
    485 if( newsize > oldsize )
    486 {
    487 int c;
    488
    489 for( c = oldsize; c < newsize; ++c )
    490 {
    491 SCIP_CALL( createDepthinfo(scip, &(eventhdlrdata->depthinfos[c])) );
    492 }
    493
    494 eventhdlrdata->maxdepth = newsize;
    495 }
    496 assert(newsize > nodedepth);
    497
    498 return SCIP_OKAY;
    499}
    500
    501/** ensures the capacity of the event handler data structures and removes the current node */
    502static
    504 SCIP* scip, /**< SCIP data structure */
    505 SCIP_EVENTHDLRDATA* eventhdlrdata, /**< event handler data */
    506 SCIP_NODE* node /**< node to be removed from the data structures of the event handler */
    507 )
    508{
    509 assert(scip != NULL);
    510 assert(node != NULL);
    511 assert(eventhdlrdata != NULL);
    512
    513 /* ensure the depth info data structure can hold this node */
    514 SCIP_CALL( ensureDepthInfoArraySize(scip, eventhdlrdata, node) );
    515
    516 /* in case that selected nodes were cut off in between two calls to this method, build data structures from scratch again */
    517 if( SCIPgetNDelayedCutoffs(scip) > eventhdlrdata->lastndelayedcutoffs || eventhdlrdata->newbestsol
    518 || eventhdlrdata->nnodesleft - 1 != SCIPgetNNodesLeft(scip) )
    519 {
    520 SCIP_CALL( recomputeNodeInformation(scip, eventhdlrdata) );
    521
    522 eventhdlrdata->lastndelayedcutoffs = SCIPgetNDelayedCutoffs(scip);
    523 }
    524 else
    525 {
    526 /* remove the node from the data structures */
    527 releaseNodeFromDepthInfo(scip, eventhdlrdata, node);
    528 }
    529
    530 assert(eventhdlrdata->nnodesleft == SCIPgetNNodesLeft(scip));
    531
    532 return SCIP_OKAY;
    533}
    534
    535#ifndef NDEBUG
    536/** ensures correctness of counters by explicitly summing up all children, leaves, and siblings with small estimates */
    537static
    539 SCIP* scip
    540 )
    541{
    542 SCIP_NODE** nodes;
    543 SCIP_RETCODE retcode;
    544 int nnodes;
    545 int n;
    546 SCIP_Real upperbound = SCIPgetUpperbound(scip);
    547 int nodesbelow = 0;
    548
    549 /* compare children estimate and current upper bound */
    550 retcode = SCIPgetChildren(scip, &nodes, &nnodes);
    551 assert(retcode == SCIP_OKAY);
    552
    553 for( n = 0; n < nnodes; ++n )
    554 {
    555 if( SCIPisLT(scip, SCIPnodeGetEstimate(nodes[n]), upperbound) )
    556 ++nodesbelow;
    557 }
    558
    559 /* compare sibling estimate and current upper bound */
    560 retcode = SCIPgetSiblings(scip, &nodes, &nnodes);
    561 assert(retcode == SCIP_OKAY);
    562
    563 for( n = 0; n < nnodes; ++n )
    564 {
    565 if( SCIPisLT(scip, SCIPnodeGetEstimate(nodes[n]), upperbound) )
    566 ++nodesbelow;
    567 }
    568
    569 /* compare leaf node and current upper bound */
    570 retcode = SCIPgetLeaves(scip, &nodes, &nnodes);
    571 assert(retcode == SCIP_OKAY);
    572
    573 for( n = 0; n < nnodes; ++n )
    574 {
    575 if( SCIPisLT(scip, SCIPnodeGetEstimate(nodes[n]), upperbound) )
    576 ++nodesbelow;
    577 }
    578
    579 assert(nodesbelow <= SCIPgetNNodesLeft(scip));
    580 return nodesbelow;
    581}
    582#endif
    583
    584/** get the point of the X axis for the regression according to the user choice of X type (time/nodes/iterations)*/
    585static
    587 SCIP* scip, /**< SCIP data structure */
    588 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
    589 )
    590{
    591 SCIP_Real x;
    592
    593 switch( eventhdlrdata->logregression_xtype )
    594 {
    595 case 'l':
    596 /* get number of LP iterations so far */
    599 else
    600 x = 1.0;
    601 break;
    602 case 'n':
    603 /* get total number of solving nodes so far */
    606 else
    607 x = 1.0;
    608 break;
    609 case 't':
    610 /* get solving time */
    612 break;
    613 default:
    614 x = 1.0;
    615 break;
    616 }
    617
    618 /* prevent the calculation of logarithm too close to zero */
    619 x = MAX(x, .1);
    620 x = log(x);
    621
    622 return x;
    623}
    624
    625
    626
    627
    628
    629/** get axis intercept of current tangent to logarithmic regression curve */
    630static
    632 SCIP* scip, /**< SCIP data structure */
    633 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data structure */
    634 )
    635{
    636 SCIP_REGRESSION* regression;
    637 SCIP_Real currentx;
    638 SCIP_Real regressionslope;
    639
    640 assert(scip != NULL);
    641 assert(eventhdlrdata != NULL);
    642
    643 regression = eventhdlrdata->regression;
    644 assert(regression != NULL);
    645
    646 /* don't rely on too few (<= 2) observations */
    647 if( SCIPregressionGetNObservations(regression) <= 2 )
    648 return SCIPinfinity(scip);
    649
    650 currentx = getX(scip, eventhdlrdata);
    651 regressionslope = SCIPregressionGetSlope(regression);
    652
    653 return regressionslope * currentx + SCIPregressionGetIntercept(regression) - regressionslope;
    654}
    655
    656/*
    657 * Local methods
    658 */
    659
    660/** checks if rank-1 transition has been reached, that is, when all open nodes have a best-estimate higher than the best
    661 * previously checked node at this depth
    662 */
    663static
    665 SCIP* scip, /**< SCIP data structure */
    666 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
    667 )
    668{
    669 /* at least one solution is required for the transition */
    670 if( SCIPgetNSols(scip) > 0 )
    671 return (SCIPgetNNodes(scip) > eventhdlrdata->nodeoffset && getNRank1Nodes(scip) == 0);
    672 else
    673 return FALSE;
    674}
    675
    676/** check if Best-Estimate criterion was reached, that is, when the active estimate is not better than the current incumbent solution */
    677static
    679 SCIP* scip, /**< SCIP data structure */
    680 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
    681 )
    682{
    683 if( SCIPgetNSols(scip) > 0 )
    684 return ((SCIPgetNNodes(scip) > eventhdlrdata->nodeoffset) && (eventhdlrdata->nnodesbelowincumbent == 0));
    685 else
    686 return FALSE;
    687}
    688
    689/** check if logarithmic phase transition has been reached.
    690 *
    691 * the logarithmic phase transition is reached when the slope of the logarithmic primal progress (as a function of the number of
    692 * LP iterations or solving nodes) becomes gentle. More concretely, we measure the slope by calculating the axis intercept of the tangent of
    693 * the logarithmic primal progress. We then compare this axis intercept to the first and current primal bound and say that
    694 * the logarithmic phase transition is reached as soon as the axis intercept passes the current primal bound so that the
    695 * scalar becomes negative.
    696 *
    697 * While it would be enough to directly compare the primal bound and the axis intercept of the
    698 * tangent to check the criterion, the scalar allows for a continuous indicator how far the phase transition is still ahead
    699 */
    700static
    702 SCIP* scip, /**< SCIP data structure */
    703 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
    704 )
    705{
    706 if( SCIPgetNSols(scip) > 0 )
    707 {
    708 SCIP_Real axisintercept = getCurrentRegressionTangentAxisIntercept(scip, eventhdlrdata);
    709 if( !SCIPisInfinity(scip, axisintercept) )
    710 {
    711 SCIP_Real primalbound;
    712 SCIP_Real lambda;
    713 SCIP_Real firstprimalbound = SCIPgetFirstPrimalBound(scip);
    714
    715 primalbound = SCIPgetPrimalbound(scip);
    716
    717 /* lambda is the scalar to describe the axis intercept as a linear combination of the current and the first primal bound
    718 * as intercept = pb_0 + lambda * (pb - pb_0) */
    719 lambda = (axisintercept - primalbound) / (firstprimalbound - primalbound);
    720
    721 if( SCIPisNegative(scip, lambda) )
    722 return TRUE;
    723 }
    724 }
    725 return FALSE;
    726}
    727
    728/** check if incumbent solution is nearly optimal; we allow a relative deviation of 10^-9 */
    729static
    731 SCIP* scip, /**< SCIP data structure */
    732 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
    733 )
    734{
    735 SCIP_Real referencevalue;
    736 SCIP_Real primalbound;
    737
    738 referencevalue = eventhdlrdata->optimalvalue;
    739 primalbound = SCIPgetPrimalbound(scip);
    740
    741 if(!SCIPisInfinity(scip, REALABS(primalbound)) && !SCIPisInfinity(scip, referencevalue) )
    742 {
    743 SCIP_Real max = MAX3(1.0, REALABS(primalbound), REALABS(referencevalue)); /*lint !e666*/
    744
    745 if( EPSZ((primalbound - referencevalue)/max, 1e-9) )
    746 return TRUE;
    747 }
    748 return FALSE;
    749}
    750
    751/** check if we are in the proof phase */
    752static
    754 SCIP* scip, /**< SCIP data structure */
    755 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
    756 )
    757{
    758 if( eventhdlrdata->solvingphase == SCIP_SOLVINGPHASE_PROOF && !eventhdlrdata->fallback )
    759 return TRUE;
    760
    761 /* check criterion based on selected transition method */
    762 switch( eventhdlrdata->transitionmethod )
    763 {
    764 case 'r':
    765
    766 /* check rank-1 transition */
    767 if( checkRankOneTransition(scip, eventhdlrdata) )
    768 {
    769 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "reached rank-1 transition: nodes: %lld, rank-1: %d bound: %9.5g time: %.2f\n",
    771 return TRUE;
    772 }
    773 break;
    774 case 'o':
    775
    776 /* cheat and use knowledge about optimal solution */
    777 if( checkOptimalSolution(scip, eventhdlrdata) )
    778 {
    779 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "optimal solution found: %lld, bound: %9.5g time: %.2f\n",
    781 return TRUE;
    782 }
    783 break;
    784 case 'e':
    785
    786 /* check best-estimate transition */
    787 if( checkEstimateCriterion(scip, eventhdlrdata) )
    788 {
    789 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "reached best-estimate transition: nodes: %lld, estimate: %d bound: %9.5g time: %.2f\n",
    790 SCIPgetNNodes(scip), eventhdlrdata->nnodesbelowincumbent, SCIPgetPrimalbound(scip), SCIPgetSolvingTime(scip));
    791 return TRUE;
    792 }
    793 return FALSE;
    794 case 'l':
    795
    796 /* check logarithmic transition */
    797 if( checkLogCriterion(scip, eventhdlrdata) )
    798 {
    799 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "reached a logarithmic phase transition: %.2f\n", SCIPgetSolvingTime(scip));
    800 return TRUE;
    801 }
    802 break;
    803 default:
    804 return FALSE;
    805 }
    806
    807 return FALSE;
    808}
    809
    810/* determine the solving phase: feasibility phase if no solution was found yet, otherwise improvement phase or proof phase
    811 * depending on whether selected transition criterion was already reached and fallback is active or not
    812 */
    813static
    815 SCIP* scip, /**< SCIP data structure */
    816 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
    817 )
    818{
    819 /* without solution, we are in the feasibility phase */
    820 if( SCIPgetNSols(scip) == 0 )
    821 eventhdlrdata->solvingphase = SCIP_SOLVINGPHASE_FEASIBILITY;
    822 else if( eventhdlrdata->solvingphase != SCIP_SOLVINGPHASE_PROOF || eventhdlrdata->fallback )
    823 eventhdlrdata->solvingphase = SCIP_SOLVINGPHASE_IMPROVEMENT;
    824
    825 if( eventhdlrdata->solvingphase == SCIP_SOLVINGPHASE_IMPROVEMENT && transitionPhase3(scip, eventhdlrdata) )
    826 eventhdlrdata->solvingphase = SCIP_SOLVINGPHASE_PROOF;
    827}
    828
    829/** changes parameters by using emphasis settings */
    830static
    832 SCIP* scip, /**< SCIP data structure */
    833 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
    834 )
    835{
    836 SCIP_PARAMEMPHASIS paramemphasis;
    837
    838 /* choose the appropriate emphasis settings for the new solving phase */
    839 switch(eventhdlrdata->solvingphase)
    840 {
    842 paramemphasis = SCIP_PARAMEMPHASIS_PHASEFEAS;
    843 break;
    845 paramemphasis = SCIP_PARAMEMPHASIS_PHASEIMPROVE;
    846 break;
    848 paramemphasis = SCIP_PARAMEMPHASIS_PHASEPROOF;
    849 break;
    851 default:
    852 SCIPdebugMsg(scip, "Unknown solving phase: %d -> ABORT!\n ", eventhdlrdata->solvingphase);
    853 SCIPABORT();
    854 paramemphasis = SCIP_PARAMEMPHASIS_DEFAULT;
    855 break;
    856 }
    857
    858 SCIP_CALL( SCIPsetEmphasis(scip, paramemphasis, FALSE) );
    859
    860 return SCIP_OKAY;
    861}
    862
    863/** change general solving strategy of SCIP depending on the phase by reading from settings file */
    864static
    866 SCIP* scip, /**< SCIP data structure */
    867 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
    868 )
    869{
    870 FILE* file;
    871 char* paramfilename = NULL;
    872
    873 /* choose the settings file for the new solving phase */
    874 switch(eventhdlrdata->solvingphase)
    875 {
    877 paramfilename = eventhdlrdata->feassetname;
    878 break;
    880 paramfilename = eventhdlrdata->improvesetname;
    881 break;
    883 paramfilename = eventhdlrdata->proofsetname;
    884 break;
    886 default:
    887 SCIPdebugMsg(scip, "Unknown solving phase: %d -> ABORT!\n ", eventhdlrdata->solvingphase);
    888 return SCIP_INVALIDCALL;
    889 }
    890
    891 assert(paramfilename != NULL);
    892
    893 /* return if no there is no user-specified settings file for the current phase */
    894 if( strcmp(paramfilename, DEFAULT_SETNAME) == 0 )
    895 return SCIP_OKAY;
    896
    897 file = fopen(paramfilename, "r");
    898
    899 /* test if file could be found and print a warning if not */
    900 if( file == NULL )
    901 {
    902 SCIPwarningMessage(scip, "Parameter file <%s> not found--keeping settings as before.\n", paramfilename);
    903 }
    904 else
    905 {
    906 /* we can close the file */
    907 fclose(file);
    908
    909 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Reading parameters from file <%s>\n", paramfilename);
    910
    911 SCIP_CALL( SCIPreadParams(scip, paramfilename) );
    912 }
    913
    914 return SCIP_OKAY;
    915} /*lint !e593*/
    916
    917/** fix/unfix relevant solving parameters that should not accidentally be set to default values */
    918static
    920 SCIP* scip, /**< SCIP data structure */
    921 SCIP_EVENTHDLRDATA* eventhdlrdata, /**< event handler data */
    922 SCIP_Bool fix /**< should the parameters be fixed (true) or unfixed? */
    923 )
    924{
    925 int p;
    926 const char* relevantparams[] = {
    927 "limits/time",
    928 "limits/nodes",
    929 "limits/totalnodes",
    930 "limits/stallnodes",
    931 "limits/memory",
    932 "limits/gap",
    933 "limits/absgap",
    934 "limits/solutions",
    935 "limits/bestsol",
    936 "limits/maxsol",
    937 "limits/maxorigsol",
    938 "limits/restarts",
    939 "limits/autorestartnodes",
    940 "limits/softtime",
    941 "solvingphases/enabled",
    942 "solvingphases/fallback",
    943 "solvingphases/interruptoptimal",
    944 "solvingphases/nodeoffset",
    945 "solvingphases/feassetname",
    946 "solvingphases/proofsetname",
    947 "solvingphases/optimalvalue",
    948 "solvingphases/improvesetname",
    949 "solvingphases/testmode",
    950 "solvingphases/transitionmethod",
    951 "solvingphases/useemphsettings",
    952 "solvingphases/userestart1to2",
    953 "solvingphases/userestart2to3",
    954 "solvingphases/xtype"
    955 };
    956 int nrelevantparams = 28;
    957
    958 /* fix or unfix all specified limit parameters */
    959 for( p = 0; p < nrelevantparams; ++p )
    960 {
    961 if( fix )
    962 {
    963 SCIP_CALL( SCIPfixParam(scip, relevantparams[p]) );
    964 }
    965 else
    966 {
    967 SCIP_CALL( SCIPunfixParam(scip, relevantparams[p]) );
    968 }
    969 }
    970
    971 /* fix or unfix all collected, non-default parameters after problem transformation */
    972 for( p = 0; p < eventhdlrdata->nnondefaultparams; ++p )
    973 {
    974 if( fix && ! SCIPparamIsFixed(eventhdlrdata->nondefaultparams[p]) )
    975 {
    976 SCIP_CALL( SCIPfixParam(scip, SCIPparamGetName(eventhdlrdata->nondefaultparams[p])) );
    977 }
    978 else if( ! fix && SCIPparamIsFixed(eventhdlrdata->nondefaultparams[p]) )
    979 {
    980 SCIP_CALL( SCIPunfixParam(scip, SCIPparamGetName(eventhdlrdata->nondefaultparams[p])) );
    981 }
    982 }
    983
    984 return SCIP_OKAY;
    985}
    986
    987/** change settings depending whether emphasis settings should be used, or settings files */
    988static
    990 SCIP* scip, /**< SCIP data structure */
    991 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
    992 )
    993{
    994 /* fix relevant parameters such that they are not overwritten */
    996
    997 /* change settings using emphasis */
    998 if( eventhdlrdata->useemphsettings )
    999 {
    1000 SCIP_CALL( changeEmphasisParameters(scip, eventhdlrdata) );
    1001 }
    1002 else
    1003 {
    1004 /* reset to default settings; this happens automatically when using emphasis settings */
    1006 }
    1007
    1008 /* read optional, phase-specific settings */
    1010
    1011 /* unfix relevant parameters that have been fixed for changing emphasis */
    1013
    1014 return SCIP_OKAY;
    1015}
    1016
    1017/* apply the user-specified phase-based settings: A phase transition invokes the read of phase-specific settings from a file */
    1018static
    1020 SCIP* scip, /**< SCIP data structure */
    1021 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
    1022 )
    1023{
    1024 SCIP_SOLVINGPHASE oldsolvingphase;
    1025 SCIP_Bool restart;
    1026
    1027 /* return immediately if we are in the proof phase */
    1028 if( eventhdlrdata->solvingphase == SCIP_SOLVINGPHASE_PROOF && !eventhdlrdata->fallback )
    1029 return SCIP_OKAY;
    1030
    1031 /* save current solving phase */
    1032 oldsolvingphase = eventhdlrdata->solvingphase;
    1033
    1034 /* determine current solving phase */
    1035 determineSolvingPhase(scip, eventhdlrdata);
    1036
    1037 /* nothing has changed */
    1038 if( oldsolvingphase == eventhdlrdata->solvingphase )
    1039 return SCIP_OKAY;
    1040
    1041 /* check if the solving process should be interrupted when the current solution is optimal */
    1042 if( eventhdlrdata->solvingphase == SCIP_SOLVINGPHASE_PROOF && eventhdlrdata->transitionmethod == 'o' &&
    1043 eventhdlrdata->interruptoptimal )
    1044 {
    1045 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Solution is optimal. Calling user interruption.\n");
    1046
    1047 /* we call interrupt solve but do not return yet because user-specified settings for the proof phase are applied first */
    1049 }
    1050
    1051 /* check if a restart should be performed after phase transition */
    1052 if( eventhdlrdata->solvingphase == SCIP_SOLVINGPHASE_IMPROVEMENT && eventhdlrdata->userestart1to2 )
    1053 restart = TRUE;
    1054 else if( eventhdlrdata->solvingphase == SCIP_SOLVINGPHASE_PROOF && eventhdlrdata->userestart2to3 )
    1055 restart = TRUE;
    1056 else
    1057 restart = FALSE;
    1058
    1059 /* inform SCIP that a restart should be performed */
    1060 if( restart )
    1061 {
    1063 }
    1064
    1065 /* change general solving settings depending on solving strategy */
    1066 SCIP_CALL( adaptSolverBehavior(scip, eventhdlrdata) );
    1067
    1068 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL,"Changed solving phase to phase %d.\n", eventhdlrdata->solvingphase);
    1069
    1070 return SCIP_OKAY;
    1071}
    1072
    1073/** update the logarithmic regression */
    1074static
    1076 SCIP* scip, /**< SCIP data structure */
    1077 SCIP_EVENTHDLRDATA* eventhdlrdata /**< data of event handler */
    1078 )
    1079{
    1080 SCIP_Real regressionx;
    1081 SCIP_Real regressiony;
    1082
    1083 regressionx = getX(scip, eventhdlrdata);
    1084 regressiony = SCIPgetPrimalbound(scip);
    1085
    1086 /* remove the last observation if it has been observed at the same x */
    1087 if( SCIPisEQ(scip, eventhdlrdata->lastx, regressionx) )
    1088 {
    1089 SCIPregressionRemoveObservation(eventhdlrdata->regression, eventhdlrdata->lastx, eventhdlrdata->lasty);
    1090 }
    1091
    1092 /* add the new observation to the regression and save it if another update is necessary */
    1093 SCIPregressionAddObservation(eventhdlrdata->regression, regressionx, regressiony);
    1094 eventhdlrdata->lastx = regressionx;
    1095 eventhdlrdata->lasty = regressiony;
    1096
    1097 return SCIP_OKAY;
    1098}
    1099
    1100/** update data structures based on the event type caught */
    1101static
    1103 SCIP* scip, /**< SCIP data structure */
    1104 SCIP_EVENTHDLRDATA* eventhdlrdata, /**< data of event handler */
    1105 SCIP_EVENTTYPE eventtype /**< type of the caught event */
    1106 )
    1107{
    1108 SCIP_NODE** children;
    1109 int nchildren;
    1110
    1111 switch( eventtype )
    1112 {
    1113 /* store that a new best solution was found, but delay the update of node information until a node was solved */
    1115 eventhdlrdata->newbestsol = TRUE;
    1116
    1117 /* update logarithmic regression of solution process */
    1118 SCIP_CALL( updateLogRegression(scip, eventhdlrdata) );
    1119
    1120 break;
    1121
    1122 /* release the focus node from the open node data structures */
    1125
    1127 assert(eventhdlrdata->nnodesbelowincumbent <= SCIPgetNNodesLeft(scip));
    1128
    1129 break;
    1130
    1131 /* store node information for child nodes */
    1134
    1135 /* if we lost track of exact number of open search nodes, we recompute node information from scratch */
    1136 if( eventhdlrdata->newbestsol || eventhdlrdata->nnodesleft + SCIPgetNChildren(scip) != SCIPgetNNodesLeft(scip) )
    1137 {
    1138 SCIP_CALL( recomputeNodeInformation(scip, eventhdlrdata) );
    1139 eventhdlrdata->newbestsol = FALSE;
    1140
    1141 return SCIP_OKAY;
    1142 }
    1143 else
    1144 {
    1145 SCIP_CALL( SCIPgetChildren(scip, &children, &nchildren) );
    1146 SCIP_CALL( addNodesInformation(scip, eventhdlrdata, children, nchildren) );
    1147 }
    1148
    1149 assert(eventhdlrdata->nnodesleft == SCIPgetNNodesLeft(scip));
    1150 break;
    1151
    1152 default:
    1153 break;
    1154 }
    1155
    1156 /* ensure that required tree information was correctly computed; only available in solving stage and at the beginning
    1157 * or end of a node solution process because we delay the recomputation of the node information)
    1158 */
    1160 (eventtype == SCIP_EVENTTYPE_BESTSOLFOUND) ||
    1161 (eventhdlrdata->nnodesleft == SCIPgetNNodesLeft(scip) && eventhdlrdata->nnodesbelowincumbent == checkLeavesBelowIncumbent(scip)));
    1162
    1163 return SCIP_OKAY;
    1164}
    1165
    1166/** test all criteria whether they have been reached */
    1167static
    1169 SCIP* scip, /**< SCIP data structure */
    1170 SCIP_EVENTHDLRDATA* eventhdlrdata /**< data of event handler */
    1171 )
    1172{
    1173 assert(scip != NULL);
    1174 assert(eventhdlrdata != NULL);
    1175
    1176 if( !(eventhdlrdata->phaseflags & SCIP_SOLVINGPHASEFLAG_LOG) && checkLogCriterion(scip, eventhdlrdata) )
    1177 {
    1178 eventhdlrdata->phaseflags |= SCIP_SOLVINGPHASEFLAG_LOG;
    1179 if( eventhdlrdata->testmode )
    1180 {
    1181 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " Log criterion reached after %lld nodes, %.2f sec.\n",
    1183 }
    1184 }
    1185 if( !(eventhdlrdata->phaseflags & SCIP_SOLVINGPHASEFLAG_RANK1) && checkRankOneTransition(scip, eventhdlrdata) )
    1186 {
    1187 eventhdlrdata->phaseflags |= SCIP_SOLVINGPHASEFLAG_RANK1;
    1188 if( eventhdlrdata->testmode )
    1189 {
    1190 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " Rank 1 criterion reached after %lld nodes, %.2f sec.\n",
    1192 }
    1193 }
    1194
    1195 if( !(eventhdlrdata->phaseflags & SCIP_SOLVINGPHASEFLAG_ESTIMATE) && checkEstimateCriterion(scip, eventhdlrdata) )
    1196 {
    1197 eventhdlrdata->phaseflags |= SCIP_SOLVINGPHASEFLAG_ESTIMATE;
    1198 if( eventhdlrdata->testmode )
    1199 {
    1200 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " Estimate criterion reached after %lld nodes, %.2f sec.\n",
    1202 }
    1203 }
    1204
    1205 if( !(eventhdlrdata->phaseflags & SCIP_SOLVINGPHASEFLAG_OPTIMAL) && checkOptimalSolution(scip, eventhdlrdata) )
    1206 {
    1207 eventhdlrdata->phaseflags |= SCIP_SOLVINGPHASEFLAG_OPTIMAL;
    1208 if( eventhdlrdata->testmode )
    1209 {
    1210 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " Optimum reached after %lld nodes, %.2f sec.\n",
    1212 }
    1213 }
    1214}
    1215
    1216/*
    1217 * Callback methods of event handler
    1218 */
    1219
    1220/** copy method for event handler (called when SCIP copies plugins) */
    1221/* @todo: this code needs to stay disabled as long as the soft limit event handler is not copied, because we save
    1222 * the soft time limit parameter but this will crash as soon as we are in a SCIP copy */
    1223#ifdef SCIP_DISABLED_CODE
    1224static
    1226{ /*lint --e{715}*/
    1227 assert(scip != NULL);
    1228 assert(eventhdlr != NULL);
    1229
    1231
    1232 /* call inclusion method of event handler */
    1234
    1235 return SCIP_OKAY;
    1236}
    1237#else
    1238#define eventCopySolvingphase NULL
    1239#endif
    1240
    1241/** destructor of event handler to free user data (called when SCIP is exiting) */
    1242static
    1243SCIP_DECL_EVENTFREE(eventFreeSolvingphase)
    1244{
    1245 SCIP_EVENTHDLRDATA* eventhdlrdata;
    1246
    1247 assert(scip != NULL);
    1248 assert(eventhdlr != NULL);
    1249
    1251
    1252 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
    1253 assert(eventhdlrdata != NULL);
    1254
    1255 SCIPregressionFree(&eventhdlrdata->regression);
    1256
    1257 SCIPfreeBlockMemory(scip, &eventhdlrdata);
    1258 SCIPeventhdlrSetData(eventhdlr, NULL);
    1259
    1260 return SCIP_OKAY;
    1261}
    1262
    1263/** initialization method of event handler (called after problem was transformed) */
    1264static
    1265SCIP_DECL_EVENTINITSOL(eventInitsolSolvingphase)
    1266{ /*lint --e{715}*/
    1267 SCIP_EVENTHDLRDATA* eventhdlrdata;
    1268
    1269 assert(scip != NULL);
    1270 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
    1271 eventhdlrdata->depthinfos = NULL;
    1272 eventhdlrdata->maxdepth = 0;
    1273 eventhdlrdata->nnodesbelowincumbent = 0;
    1274 eventhdlrdata->nnodesleft = 0;
    1275 eventhdlrdata->nrank1nodes = 0;
    1276 eventhdlrdata->lastndelayedcutoffs = SCIPgetNDelayedCutoffs(scip);
    1277 eventhdlrdata->newbestsol = FALSE;
    1278
    1279 return SCIP_OKAY;
    1280}
    1281
    1282/** solving process deinitialization method of event handler (called before branch and bound process data is freed) */
    1283static
    1284SCIP_DECL_EVENTEXITSOL(eventExitsolSolvingphase)
    1285{
    1286 SCIP_EVENTHDLRDATA* eventhdlrdata;
    1287
    1288 assert(scip != NULL);
    1289 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
    1290
    1291 /* free all data storage acquired during this branch-and-bound run */
    1292 if( eventhdlrdata->maxdepth > 0 )
    1293 {
    1294 int c;
    1295
    1296 /* free depth information */
    1297 for( c = 0; c < eventhdlrdata->maxdepth; ++c )
    1298 {
    1299 SCIP_CALL( freeDepthinfo(scip, &(eventhdlrdata->depthinfos[c])) );
    1300 }
    1301
    1302 /* free depth information array */
    1303 SCIPfreeBlockMemoryArray(scip, &eventhdlrdata->depthinfos, eventhdlrdata->maxdepth);
    1304 eventhdlrdata->maxdepth = 0;
    1305 }
    1306
    1307 return SCIP_OKAY;
    1308}
    1309
    1310/** collects all parameters that are set to non-default values and stores them in eventhdlrdata */
    1311static
    1313 SCIP* scip, /**< SCIP data structure */
    1314 SCIP_EVENTHDLRDATA* eventhdlrdata /**< data of event handler */
    1315 )
    1316{
    1317 SCIP_PARAM** params;
    1318 int nparams;
    1319 int p;
    1320
    1321 params = SCIPgetParams(scip);
    1322 nparams = SCIPgetNParams(scip);
    1323
    1324 eventhdlrdata->nnondefaultparams = 0;
    1325 eventhdlrdata->nondefaultparams = NULL;
    1326 eventhdlrdata->nondefaultparamssize = 0;
    1327
    1328 /* loop over parameters and store the non-default ones */
    1329 for( p = 0; p < nparams; ++p )
    1330 {
    1331 SCIP_PARAM* param = params[p];
    1332
    1333 /* collect parameter if it is nondefault */
    1334 if( ! SCIPparamIsDefault(param) )
    1335 {
    1336 if( eventhdlrdata->nnondefaultparams == 0 )
    1337 {
    1338 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &eventhdlrdata->nondefaultparams, 8) );
    1339 eventhdlrdata->nondefaultparamssize = 8;
    1340 }
    1341 else if( eventhdlrdata->nnondefaultparams == eventhdlrdata->nondefaultparamssize )
    1342 {
    1343 eventhdlrdata->nondefaultparamssize *= 2;
    1344 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &eventhdlrdata->nondefaultparams, \
    1345 eventhdlrdata->nnondefaultparams, eventhdlrdata->nondefaultparamssize) );
    1346 }
    1347
    1348 eventhdlrdata->nondefaultparams[eventhdlrdata->nnondefaultparams++] = param;
    1349 }
    1350 }
    1351
    1352 return SCIP_OKAY;
    1353}
    1354
    1355/** initialization method of event handler (called after problem was transformed) */
    1356static
    1357SCIP_DECL_EVENTINIT(eventInitSolvingphase)
    1358{ /*lint --e{715}*/
    1359 SCIP_EVENTHDLRDATA* eventhdlrdata;
    1360
    1361 assert(scip != NULL);
    1362 assert(eventhdlr != NULL);
    1363
    1365
    1366 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
    1367 assert(eventhdlrdata != NULL);
    1368
    1369 /* initialize the solving phase */
    1370 eventhdlrdata->solvingphase = SCIP_SOLVINGPHASE_UNINITIALIZED;
    1371
    1372 /* none of the transitions is reached yet */
    1373 eventhdlrdata->phaseflags = SCIP_SOLVINGPHASEFLAG_NONE;
    1374 eventhdlrdata->nnondefaultparams = 0;
    1375 eventhdlrdata->nondefaultparams = NULL;
    1376 eventhdlrdata->nondefaultparamssize = 0;
    1377
    1378 /* in test mode we only determine the phase without changing solver settings */
    1379 if( eventhdlrdata->testmode )
    1380 determineSolvingPhase(scip, eventhdlrdata);
    1381 else if( eventhdlrdata->enabled )
    1382 {
    1383 /* collect non-default parameters */
    1384 SCIP_CALL( collectNondefaultParams(scip, eventhdlrdata) );
    1385
    1386 SCIP_CALL( applySolvingPhase(scip, eventhdlrdata) );
    1387 }
    1388
    1389 /* only start catching events if event handler is enabled or in test mode */
    1390 if( eventhdlrdata->enabled || eventhdlrdata->testmode )
    1391 {
    1392 SCIP_CALL( SCIPcatchEvent(scip, EVENTHDLR_EVENT, eventhdlr, NULL, &eventhdlrdata->eventfilterpos) );
    1393 }
    1394
    1395 /* reset solving regression */
    1396 SCIPregressionReset(eventhdlrdata->regression);
    1397 eventhdlrdata->lastx = SCIP_INVALID;
    1398 eventhdlrdata->lasty = SCIP_INVALID;
    1399
    1400 return SCIP_OKAY;
    1401}
    1402/** deinitialization method of event handler (called before problem is freed) */
    1403static
    1404SCIP_DECL_EVENTEXIT(eventExitSolvingphase)
    1405{
    1406 SCIP_EVENTHDLRDATA* eventhdlrdata;
    1407
    1408 assert(scip != NULL);
    1409 assert(eventhdlr != NULL);
    1410
    1412
    1413 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
    1414 assert(eventhdlrdata != NULL);
    1415
    1416 /* free collected, non-default parameters */
    1417 SCIPfreeBlockMemoryArrayNull(scip, &eventhdlrdata->nondefaultparams, eventhdlrdata->nondefaultparamssize);
    1418
    1419 return SCIP_OKAY;
    1420}
    1421
    1422
    1423/** execution method of event handler */
    1424static
    1425SCIP_DECL_EVENTEXEC(eventExecSolvingphase)
    1426{ /*lint --e{715}*/
    1427 SCIP_EVENTHDLRDATA* eventhdlrdata;
    1428 SCIP_EVENTTYPE eventtype;
    1429
    1430 assert(scip != NULL);
    1431 assert(eventhdlr != NULL);
    1432
    1433 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
    1434 assert(eventhdlrdata != NULL);
    1435 eventtype = SCIPeventGetType(event);
    1436 assert(eventtype & (EVENTHDLR_EVENT));
    1437 assert(eventtype != SCIP_EVENTTYPE_NODEFOCUSED || SCIPeventGetNode(event) == SCIPgetCurrentNode(scip));
    1438
    1439 /* update data structures depending on the event */
    1440 SCIP_CALL( updateDataStructures(scip, eventhdlrdata, eventtype) );
    1441
    1442 /* in test mode we only determine the phase without changing solver settings */
    1443 if( eventhdlrdata->testmode )
    1444 determineSolvingPhase(scip, eventhdlrdata);
    1445 else
    1446 {
    1447 assert(eventhdlrdata->enabled);
    1448 SCIP_CALL( applySolvingPhase(scip, eventhdlrdata) );
    1449 }
    1450
    1451 /* update the bit field of reached transition criteria */
    1452 testCriteria(scip, eventhdlrdata);
    1453
    1454 return SCIP_OKAY;
    1455}
    1456
    1457/*
    1458 * displays that come with this event handler
    1459 */
    1460
    1461/* defines for the rank 1 node display */
    1462#define DISP_NAME_NRANK1NODES "nrank1nodes"
    1463#define DISP_DESC_NRANK1NODES "current number of rank1 nodes left"
    1464#define DISP_HEAD_NRANK1NODES "rank1"
    1465#define DISP_WIDT_NRANK1NODES 7
    1466#define DISP_PRIO_NRANK1NODES 40000
    1467#define DISP_POSI_NRANK1NODES 500
    1468#define DISP_STRI_NRANK1NODES TRUE
    1469
    1470/** output method of display column to output file stream 'file' */
    1471static
    1472SCIP_DECL_DISPOUTPUT(dispOutputNRank1Nodes)
    1473{
    1474 assert(disp != NULL);
    1475 assert(scip != NULL);
    1476
    1478
    1479 /* ouput number of rank 1 nodes */
    1481
    1482 return SCIP_OKAY;
    1483}
    1484
    1485/* display for the number of nodes below the current incumbent */
    1486#define DISP_NAME_NNODESBELOWINC "nnodesbelowinc"
    1487#define DISP_DESC_NNODESBELOWINC "current number of nodes with an estimate better than the current incumbent"
    1488#define DISP_HEAD_NNODESBELOWINC "nbInc"
    1489#define DISP_WIDT_NNODESBELOWINC 6
    1490#define DISP_PRIO_NNODESBELOWINC 40000
    1491#define DISP_POSI_NNODESBELOWINC 550
    1492#define DISP_STRI_NNODESBELOWINC TRUE
    1493
    1494/** output method of display column to output file stream 'file' */
    1495static
    1496SCIP_DECL_DISPOUTPUT(dispOutputNnodesbelowinc)
    1497{
    1498 assert(disp != NULL);
    1499 assert(scip != NULL);
    1500
    1502
    1503 /* display the number of nodes with an estimate below the the current incumbent */
    1505
    1506 return SCIP_OKAY;
    1507}
    1508
    1509/** creates event handler for Solvingphase event */
    1511 SCIP* scip /**< SCIP data structure */
    1512 )
    1513{
    1514 SCIP_EVENTHDLRDATA* eventhdlrdata;
    1515 SCIP_EVENTHDLR* eventhdlr;
    1516
    1517 /* create solving phase event handler data */
    1518 eventhdlrdata = NULL;
    1519 SCIP_CALL( SCIPallocBlockMemory(scip, &eventhdlrdata) );
    1520 assert(eventhdlrdata != NULL);
    1521
    1522 eventhdlrdata->feassetname = NULL;
    1523 eventhdlrdata->improvesetname = NULL;
    1524 eventhdlrdata->proofsetname = NULL;
    1525
    1526 eventhdlrdata->depthinfos = NULL;
    1527 eventhdlrdata->maxdepth = 0;
    1528 eventhdlrdata->eventfilterpos = -1;
    1529
    1530 /* create a regression */
    1531 eventhdlrdata->regression = NULL;
    1532 SCIP_CALL( SCIPregressionCreate(&eventhdlrdata->regression) );
    1533
    1534 eventhdlr = NULL;
    1535
    1536 /* include event handler into SCIP */
    1538 eventExecSolvingphase, eventhdlrdata) );
    1539 assert(eventhdlr != NULL);
    1540
    1541 /* include the new displays into scip */
    1548
    1549 /* set non fundamental callbacks via setter functions */
    1551 SCIP_CALL( SCIPsetEventhdlrFree(scip, eventhdlr, eventFreeSolvingphase) );
    1552 SCIP_CALL( SCIPsetEventhdlrInit(scip, eventhdlr, eventInitSolvingphase) );
    1553 SCIP_CALL( SCIPsetEventhdlrExit(scip, eventhdlr, eventExitSolvingphase) );
    1554 SCIP_CALL( SCIPsetEventhdlrInitsol(scip, eventhdlr, eventInitsolSolvingphase) );
    1555 SCIP_CALL( SCIPsetEventhdlrExitsol(scip, eventhdlr, eventExitsolSolvingphase) );
    1556
    1557 /* add Solvingphase event handler parameters */
    1558 SCIP_CALL( SCIPaddBoolParam(scip, EVENTHDLR_NAME "s/enabled", "is the event handler enabled?",
    1559 &eventhdlrdata->enabled, FALSE, DEFAULT_ENABLED, NULL, NULL) );
    1560
    1561 SCIP_CALL( SCIPaddBoolParam(scip, EVENTHDLR_NAME "s/testmode", "should the event handler only determine phase transitions, suppressing settings changes?",
    1562 &eventhdlrdata->testmode, FALSE, DEFAULT_TESTMODE, NULL, NULL) );
    1563
    1564 SCIP_CALL( SCIPaddStringParam(scip, EVENTHDLR_NAME "s/feassetname", "settings file for feasibility phase -- precedence over emphasis settings",
    1565 &eventhdlrdata->feassetname, FALSE, DEFAULT_SETNAME, NULL, NULL) );
    1566
    1567 SCIP_CALL( SCIPaddStringParam(scip, EVENTHDLR_NAME "s/improvesetname", "settings file for improvement phase -- precedence over emphasis settings",
    1568 &eventhdlrdata->improvesetname, FALSE, DEFAULT_SETNAME, NULL, NULL) );
    1569
    1570 SCIP_CALL( SCIPaddStringParam(scip, EVENTHDLR_NAME "s/proofsetname", "settings file for proof phase -- precedence over emphasis settings",
    1571 &eventhdlrdata->proofsetname, FALSE, DEFAULT_SETNAME, NULL, NULL) );
    1572
    1573 SCIP_CALL( SCIPaddLongintParam(scip, EVENTHDLR_NAME "s/nodeoffset", "node offset for rank-1 and estimate transitions", &eventhdlrdata->nodeoffset,
    1575 SCIP_CALL( SCIPaddBoolParam(scip, EVENTHDLR_NAME "s/fallback", "should the event handler fall back from optimal phase?",
    1576 &eventhdlrdata->fallback, FALSE, DEFAULT_FALLBACK, NULL, NULL) );
    1577 SCIP_CALL( SCIPaddCharParam(scip ,EVENTHDLR_NAME "s/transitionmethod",
    1578 "transition method: Possible options are 'e'stimate,'l'ogarithmic regression,'o'ptimal-value based,'r'ank-1",
    1579 &eventhdlrdata->transitionmethod, FALSE, DEFAULT_TRANSITIONMETHOD, TRANSITIONMETHODS, NULL, NULL) );
    1580 SCIP_CALL( SCIPaddBoolParam(scip, EVENTHDLR_NAME "s/interruptoptimal",
    1581 "should the event handler interrupt the solving process after optimal solution was found?",
    1582 &eventhdlrdata->interruptoptimal, FALSE, DEFAULT_INTERRUPTOPTIMAL, NULL, NULL) );
    1583
    1584 SCIP_CALL( SCIPaddBoolParam(scip, EVENTHDLR_NAME "s/userestart1to2",
    1585 "should a restart be applied between the feasibility and improvement phase?",
    1586 &eventhdlrdata->userestart1to2, FALSE, DEFAULT_USERESTART1TO2, NULL, NULL) );
    1587
    1588 SCIP_CALL( SCIPaddBoolParam(scip, EVENTHDLR_NAME "s/userestart2to3",
    1589 "should a restart be applied between the improvement and the proof phase?",
    1590 &eventhdlrdata->userestart2to3, FALSE, DEFAULT_USERESTART2TO3, NULL, NULL) );
    1591
    1592 SCIP_CALL( SCIPaddRealParam(scip, EVENTHDLR_NAME "s/optimalvalue", "optimal solution value for problem",
    1593 &eventhdlrdata->optimalvalue, FALSE, SCIP_INVALID, SCIP_REAL_MIN, SCIP_REAL_MAX, NULL, NULL) );
    1594
    1595 /* add parameter for logarithmic regression */
    1596 SCIP_CALL( SCIPaddCharParam(scip, EVENTHDLR_NAME "s/xtype", "x-type for logarithmic regression - (t)ime, (n)odes, (l)p iterations",
    1597 &eventhdlrdata->logregression_xtype, FALSE, DEFAULT_LOGREGRESSION_XTYPE, LOGREGRESSION_XTYPES, NULL, NULL) );
    1598
    1599 SCIP_CALL( SCIPaddBoolParam(scip, EVENTHDLR_NAME "s/useemphsettings",
    1600 "should emphasis settings for the solving phases be used, or settings files?",
    1601 &eventhdlrdata->useemphsettings, FALSE, DEFAULT_USEEMPHSETTINGS, NULL, NULL) );
    1602
    1603 return SCIP_OKAY;
    1604}
    1605
    1606/** returns the current solving phase tracked by the solvingphase event handler */
    1608 SCIP* scip /**< SCIP data structure */
    1609 )
    1610{
    1611 SCIP_EVENTHDLR* eventhdlr;
    1612 SCIP_EVENTHDLRDATA* eventhdlrdata;
    1613
    1614 assert(scip != NULL);
    1615
    1617 if( eventhdlr == NULL )
    1619
    1620 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
    1621 assert(eventhdlrdata != NULL);
    1622
    1623 return eventhdlrdata->solvingphase;
    1624}
    1625
    1626/** returns the bit field of reached transition criteria */
    1628 SCIP* scip /**< SCIP data structure */
    1629 )
    1630{
    1631 SCIP_EVENTHDLR* eventhdlr;
    1632 SCIP_EVENTHDLRDATA* eventhdlrdata;
    1633
    1634 assert(scip != NULL);
    1635
    1637 if( eventhdlr == NULL )
    1639
    1640 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
    1641 assert(eventhdlrdata != NULL);
    1642
    1643 return eventhdlrdata->phaseflags;
    1644}
    SCIP_VAR ** x
    Definition: circlepacking.c:63
    #define NULL
    Definition: def.h:257
    #define SCIP_Longint
    Definition: def.h:150
    #define SCIP_REAL_MAX
    Definition: def.h:167
    #define SCIP_INVALID
    Definition: def.h:187
    #define SCIP_Bool
    Definition: def.h:100
    #define MAX3(x, y, z)
    Definition: def.h:237
    #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 SCIPABORT()
    Definition: def.h:336
    #define SCIP_REAL_MIN
    Definition: def.h:168
    #define REALABS(x)
    Definition: def.h:191
    #define SCIP_LONGINT_MAX
    Definition: def.h:151
    #define EPSZ(x, eps)
    Definition: def.h:197
    #define SCIP_CALL(x)
    Definition: def.h:364
    #define DEFAULT_USEEMPHSETTINGS
    static SCIP_Bool checkRankOneTransition(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
    static SCIP_RETCODE releaseNodeInformation(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata, SCIP_NODE *node)
    #define DISP_PRIO_NNODESBELOWINC
    #define DEFAULT_LOGREGRESSION_XTYPE
    #define DISP_POSI_NRANK1NODES
    #define DEFAULT_USERESTART1TO2
    static SCIP_DECL_EVENTINIT(eventInitSolvingphase)
    #define DEFAULT_INTERRUPTOPTIMAL
    static SCIP_DECL_EVENTEXEC(eventExecSolvingphase)
    static SCIP_Bool transitionPhase3(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
    static SCIP_RETCODE applySolvingPhase(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
    #define DISP_DESC_NRANK1NODES
    static SCIP_Bool checkEstimateCriterion(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
    SCIP_SOLVINGPHASEFLAG SCIPgetSolvingPhaseFlags(SCIP *scip)
    static SCIP_RETCODE adaptSolverBehavior(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
    #define DISP_HEAD_NNODESBELOWINC
    static SCIP_RETCODE addNodesInformation(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata, SCIP_NODE **nodes, int nnodes)
    #define EVENTHDLR_EVENT
    #define DEFAULT_TESTMODE
    #define LOGREGRESSION_XTYPES
    static SCIP_Bool checkLogCriterion(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
    static void testCriteria(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
    #define DEFAULT_SETNAME
    static int getNRank1Nodes(SCIP *scip)
    static SCIP_DECL_SORTPTRCOMP(sortCompTreeinfo)
    static SCIP_Real getX(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
    static SCIP_DECL_EVENTFREE(eventFreeSolvingphase)
    #define DISP_NAME_NNODESBELOWINC
    #define DISP_WIDT_NNODESBELOWINC
    SCIP_SOLVINGPHASE SCIPgetSolvingPhase(SCIP *scip)
    static SCIP_DECL_EVENTINITSOL(eventInitsolSolvingphase)
    #define DEFAULT_NODEOFFSET
    static SCIP_DECL_EVENTEXIT(eventExitSolvingphase)
    static SCIP_RETCODE collectNondefaultParams(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
    static SCIP_DECL_EVENTEXITSOL(eventExitsolSolvingphase)
    static void releaseNodeFromDepthInfo(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata, SCIP_NODE *node)
    static SCIP_RETCODE fixOrUnfixRelevantParameters(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata, SCIP_Bool fix)
    #define DEFAULT_FALLBACK
    static void determineSolvingPhase(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
    #define DISP_HEAD_NRANK1NODES
    #define DEFAULT_TRANSITIONMETHOD
    #define DISP_STRI_NRANK1NODES
    static int getNNodesBelowIncumbent(SCIP *scip)
    static void removeNode(SCIP_NODE *node, SCIP_EVENTHDLRDATA *eventhdlrdata)
    #define DISP_PRIO_NRANK1NODES
    SCIP_RETCODE SCIPincludeEventHdlrSolvingphase(SCIP *scip)
    static SCIP_RETCODE changeEmphasisParameters(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
    #define DISP_WIDT_NRANK1NODES
    static SCIP_RETCODE createDepthinfo(SCIP *scip, DEPTHINFO **depthinfo)
    static SCIP_DECL_DISPOUTPUT(dispOutputNRank1Nodes)
    static int checkLeavesBelowIncumbent(SCIP *scip)
    static SCIP_Real getCurrentRegressionTangentAxisIntercept(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
    #define EVENTHDLR_DESC
    #define DEFAULT_USERESTART2TO3
    #define DISP_POSI_NNODESBELOWINC
    #define DISP_NAME_NRANK1NODES
    #define eventCopySolvingphase
    #define DISP_DESC_NNODESBELOWINC
    static SCIP_RETCODE updateLogRegression(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
    static SCIP_RETCODE freeDepthinfo(SCIP *scip, DEPTHINFO **depthinfo)
    static SCIP_RETCODE recomputeNodeInformation(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
    #define DISP_STRI_NNODESBELOWINC
    #define DEFAULT_ENABLED
    static SCIP_RETCODE updateDataStructures(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata, SCIP_EVENTTYPE eventtype)
    #define EVENTHDLR_NAME
    static SCIP_RETCODE ensureDepthInfoArraySize(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata, SCIP_NODE *node)
    static SCIP_RETCODE changeParametersUsingSettingsFiles(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
    static SCIP_Bool checkOptimalSolution(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
    #define TRANSITIONMETHODS
    eventhdlr for solving phase dependent parameter adjustment
    #define SCIP_SOLVINGPHASEFLAG_OPTIMAL
    #define SCIP_SOLVINGPHASEFLAG_LOG
    @ SCIP_SOLVINGPHASE_IMPROVEMENT
    @ SCIP_SOLVINGPHASE_PROOF
    @ SCIP_SOLVINGPHASE_FEASIBILITY
    @ SCIP_SOLVINGPHASE_UNINITIALIZED
    #define SCIP_SOLVINGPHASEFLAG_NONE
    #define SCIP_SOLVINGPHASEFLAG_ESTIMATE
    #define SCIP_SOLVINGPHASEFLAG_RANK1
    uint8_t SCIP_SOLVINGPHASEFLAG
    enum SCIP_SolvingPhase SCIP_SOLVINGPHASE
    #define nnodes
    Definition: gastrans.c:74
    SCIP_STAGE SCIPgetStage(SCIP *scip)
    Definition: scip_general.c:444
    void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:225
    SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
    Definition: scip_message.c:88
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
    Definition: scip_message.c:120
    SCIP_RETCODE SCIPaddLongintParam(SCIP *scip, const char *name, const char *desc, SCIP_Longint *valueptr, SCIP_Bool isadvanced, SCIP_Longint defaultvalue, SCIP_Longint minvalue, SCIP_Longint maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:111
    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
    int SCIPgetNParams(SCIP *scip)
    Definition: scip_param.c:1019
    SCIP_RETCODE SCIPaddStringParam(SCIP *scip, const char *name, const char *desc, char **valueptr, SCIP_Bool isadvanced, const char *defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:194
    SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:139
    SCIP_RETCODE SCIPreadParams(SCIP *scip, const char *filename)
    Definition: scip_param.c:772
    SCIP_RETCODE SCIPunfixParam(SCIP *scip, const char *name)
    Definition: scip_param.c:385
    SCIP_RETCODE SCIPsetEmphasis(SCIP *scip, SCIP_PARAMEMPHASIS paramemphasis, SCIP_Bool quiet)
    Definition: scip_param.c:882
    SCIP_PARAM ** SCIPgetParams(SCIP *scip)
    Definition: scip_param.c:1005
    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 SCIPfixParam(SCIP *scip, const char *name)
    Definition: scip_param.c:367
    const char * SCIPdispGetName(SCIP_DISP *disp)
    Definition: disp.c:335
    void SCIPdispInt(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, int val, int width)
    Definition: disp.c:627
    SCIP_RETCODE SCIPincludeDisp(SCIP *scip, const char *name, const char *desc, const char *header, SCIP_DISPSTATUS dispstatus, SCIP_DECL_DISPCOPY((*dispcopy)), SCIP_DECL_DISPFREE((*dispfree)), SCIP_DECL_DISPINIT((*dispinit)), SCIP_DECL_DISPEXIT((*dispexit)), SCIP_DECL_DISPINITSOL((*dispinitsol)), SCIP_DECL_DISPEXITSOL((*dispexitsol)), SCIP_DECL_DISPOUTPUT((*dispoutput)), SCIP_DISPDATA *dispdata, int width, int priority, int position, SCIP_Bool stripline)
    Definition: scip_disp.c:55
    SCIP_RETCODE SCIPsetEventhdlrInitsol(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTINITSOL((*eventinitsol)))
    Definition: scip_event.c:199
    SCIP_RETCODE SCIPsetEventhdlrCopy(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTCOPY((*eventcopy)))
    Definition: scip_event.c:143
    SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
    Definition: scip_event.c:111
    SCIP_EVENTHDLR * SCIPfindEventhdlr(SCIP *scip, const char *name)
    Definition: scip_event.c:241
    const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
    Definition: event.c:396
    SCIP_EVENTHDLRDATA * SCIPeventhdlrGetData(SCIP_EVENTHDLR *eventhdlr)
    Definition: event.c:406
    SCIP_RETCODE SCIPsetEventhdlrExitsol(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTEXITSOL((*eventexitsol)))
    Definition: scip_event.c:213
    void SCIPeventhdlrSetData(SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTHDLRDATA *eventhdlrdata)
    Definition: event.c:416
    SCIP_RETCODE SCIPsetEventhdlrFree(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTFREE((*eventfree)))
    Definition: scip_event.c:157
    SCIP_RETCODE SCIPsetEventhdlrExit(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTEXIT((*eventexit)))
    Definition: scip_event.c:185
    SCIP_RETCODE SCIPsetEventhdlrInit(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTINIT((*eventinit)))
    Definition: scip_event.c:171
    SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
    Definition: event.c:1194
    SCIP_RETCODE SCIPcatchEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
    Definition: scip_event.c:293
    SCIP_NODE * SCIPeventGetNode(SCIP_EVENT *event)
    Definition: event.c:1530
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    #define SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
    Definition: scip_mem.h:99
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
    Definition: scip_mem.h:111
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    SCIP_NODETYPE SCIPnodeGetType(SCIP_NODE *node)
    Definition: tree.c:8503
    SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
    Definition: tree.c:8513
    SCIP_Real SCIPnodeGetEstimate(SCIP_NODE *node)
    Definition: tree.c:8553
    int SCIPnodeGetDepth(SCIP_NODE *node)
    Definition: tree.c:8523
    int SCIPgetNSols(SCIP *scip)
    Definition: scip_sol.c:2887
    SCIP_RETCODE SCIPrestartSolve(SCIP *scip)
    Definition: scip_solve.c:3616
    SCIP_RETCODE SCIPinterruptSolve(SCIP *scip)
    Definition: scip_solve.c:3561
    SCIP_Real SCIPgetPrimalbound(SCIP *scip)
    SCIP_Real SCIPgetUpperbound(SCIP *scip)
    SCIP_Longint SCIPgetNNodes(SCIP *scip)
    SCIP_Real SCIPgetFirstPrimalBound(SCIP *scip)
    SCIP_Longint SCIPgetNTotalNodes(SCIP *scip)
    SCIP_Longint SCIPgetNDelayedCutoffs(SCIP *scip)
    SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
    SCIP_Real SCIPgetSolvingTime(SCIP *scip)
    Definition: scip_timing.c:378
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    int SCIPgetNChildren(SCIP *scip)
    Definition: scip_tree.c:188
    SCIP_RETCODE SCIPgetOpenNodesData(SCIP *scip, SCIP_NODE ***leaves, SCIP_NODE ***children, SCIP_NODE ***siblings, int *nleaves, int *nchildren, int *nsiblings)
    Definition: scip_tree.c:398
    SCIP_RETCODE SCIPgetChildren(SCIP *scip, SCIP_NODE ***children, int *nchildren)
    Definition: scip_tree.c:164
    int SCIPgetNNodesLeft(SCIP *scip)
    Definition: scip_tree.c:646
    SCIP_RETCODE SCIPgetLeaves(SCIP *scip, SCIP_NODE ***leaves, int *nleaves)
    Definition: scip_tree.c:248
    SCIP_RETCODE SCIPgetSiblings(SCIP *scip, SCIP_NODE ***siblings, int *nsiblings)
    Definition: scip_tree.c:206
    SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
    Definition: scip_tree.c:91
    void SCIPregressionRemoveObservation(SCIP_REGRESSION *regression, SCIP_Real x, SCIP_Real y)
    Definition: misc.c:353
    void SCIPregressionAddObservation(SCIP_REGRESSION *regression, SCIP_Real x, SCIP_Real y)
    Definition: misc.c:385
    SCIP_Real SCIPregressionGetIntercept(SCIP_REGRESSION *regression)
    Definition: misc.c:278
    int SCIPregressionGetNObservations(SCIP_REGRESSION *regression)
    Definition: misc.c:258
    void SCIPregressionFree(SCIP_REGRESSION **regression)
    Definition: misc.c:436
    SCIP_RETCODE SCIPregressionCreate(SCIP_REGRESSION **regression)
    Definition: misc.c:420
    void SCIPregressionReset(SCIP_REGRESSION *regression)
    Definition: misc.c:404
    SCIP_Real SCIPregressionGetSlope(SCIP_REGRESSION *regression)
    Definition: misc.c:268
    SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
    void SCIPsortedvecInsertPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *keyval, int *len, int *pos)
    void SCIPsortedvecDelPosPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int pos, int *len)
    INLINE Rational & max(Rational &r1, Rational &r2)
    SCIP_Bool SCIPparamIsDefault(SCIP_PARAM *param)
    Definition: paramset.c:933
    const char * SCIPparamGetName(SCIP_PARAM *param)
    Definition: paramset.c:656
    SCIP_Bool SCIPparamIsFixed(SCIP_PARAM *param)
    Definition: paramset.c:696
    public methods for displaying runtime statistics
    public methods for managing events
    public methods for message output
    public data structures and miscellaneous methods
    methods for sorting joint arrays of various types
    public methods for handling parameter settings
    public methods for branch and bound tree
    public methods for display handler plugins
    public methods for event handler plugins and event handlers
    general public methods
    public methods for memory management
    public methods for message handling
    public methods for numerical tolerances
    public methods for SCIP parameter handling
    public methods for solutions
    public solving methods
    public methods for querying solving statistics
    public methods for timing
    public methods for the branch-and-bound tree
    SCIP_NODE ** minnodes
    SCIP_Real minestimate
    @ SCIP_DISPSTATUS_OFF
    Definition: type_disp.h:60
    #define SCIP_EVENTTYPE_NODEFOCUSED
    Definition: type_event.h:93
    struct SCIP_EventhdlrData SCIP_EVENTHDLRDATA
    Definition: type_event.h:160
    #define SCIP_EVENTTYPE_NODEBRANCHED
    Definition: type_event.h:96
    #define SCIP_DECL_EVENTCOPY(x)
    Definition: type_event.h:189
    #define SCIP_EVENTTYPE_BESTSOLFOUND
    Definition: type_event.h:106
    uint64_t SCIP_EVENTTYPE
    Definition: type_event.h:156
    @ SCIP_VERBLEVEL_NORMAL
    Definition: type_message.h:60
    @ SCIP_PARAMEMPHASIS_DEFAULT
    Definition: type_paramset.h:70
    @ SCIP_PARAMEMPHASIS_PHASEIMPROVE
    Definition: type_paramset.h:79
    @ SCIP_PARAMEMPHASIS_PHASEPROOF
    Definition: type_paramset.h:80
    @ SCIP_PARAMEMPHASIS_PHASEFEAS
    Definition: type_paramset.h:78
    enum SCIP_ParamEmphasis SCIP_PARAMEMPHASIS
    Definition: type_paramset.h:84
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STAGE_SOLVED
    Definition: type_set.h:54
    @ SCIP_STAGE_SOLVING
    Definition: type_set.h:53
    @ SCIP_NODETYPE_CHILD
    Definition: type_tree.h:44
    @ SCIP_NODETYPE_SIBLING
    Definition: type_tree.h:43
    @ SCIP_NODETYPE_LEAF
    Definition: type_tree.h:45