Scippy

    SCIP

    Solving Constraint Integer Programs

    event_boundwriting.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 examples/Eventhdlr/src/event_boundwriting.c
    26 * @brief event handler for writing primal and dual bound for all open nodes
    27 * @author Michael Winkler
    28 *
    29 *
    30 * This event handler writes to a specified file at a given frequency the dual bounds of all open nodes and the current
    31 * primal bound.
    32 *
    33 * setting "set misc boundwriting freq 1000" will lead to write every 1000 nodes the primal bound and the dual bound
    34 * front of all open nodes
    35 *
    36 * setting "set misc boundwriting filename bounds.txt" will write the bounds to the files
    37 * ascending from bounds1.txt over bounds2.txt to boundsN.txt were N is the last number for writing bounds (no
    38 * filename means to write to standard out)
    39 *
    40 * setting "set misc writesubmipdualbound TRUE" will lead to resolve each open node in a subSCIP until the root in the
    41 * subSCIP is solved and as a result will print this resulting dual bound
    42 *
    43 * An output could look as follows (here writesubmipdualbound is set to TRUE):
    44 *
    45 * PB 201
    46 *
    47 * 5913 34 192.1 193.5
    48 *
    49 * 2884 26 162.1 162.1
    50 *
    51 * The first line above shows the Primalbound. All following lines will show first the node number, second the depth of
    52 * this open node, third the dual bound of the open node, and last the dual bound of the root node in a subSCIP of the
    53 * resolved node.
    54 *
    55 * @note you can write all bounds to a single file by adding the line
    56 * \code
    57 * #define ONEFILE
    58 * \endcode
    59 * and recompiling this example.
    60 *
    61 * @note If you want to get a better human readable format for printing, define
    62 * \code
    63 * #define LONGSTATS
    64 * \endcode
    65 * and recompile this example.
    66 */
    67
    68/*--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    69
    70
    71#include <string.h>
    72
    73#include "event_boundwriting.h"
    74
    75
    76#define EVENTHDLR_NAME "boundwriting"
    77#define EVENTHDLR_DESC "event handler for writing current primalbound and global dualbound and for all open nodes the dualbound"
    78
    79#define DEFAULT_FREQ 0LL /**< frequency for writing primal and dual bounds */
    80#define DEFAULT_FILENAME "" /**< filename to write to */
    81#define DEFAULT_WRITESUBMIPDUALBOUND FALSE /**< write dualbound after solving supmip root for all open node */
    82
    83/* should the printing be with more information */
    84/*#define LONGSTATS*/
    85
    86/* do we want to create for each printing new files or only one */
    87/*#define ONEFILE*/
    88
    89/* do we want to print the information only on the focusnode or for all open nodes */
    90/*#define FOCUSNODE*/
    91
    92/*
    93 * Data structures
    94 */
    95
    96/** LP reading data */
    97struct SCIP_EventhdlrData
    98{
    99 char oldfilename[SCIP_MAXSTRLEN];
    100 FILE* file;
    101 char* filename;
    102 SCIP_Real lastpb;
    103 SCIP_Longint freq;
    104 SCIP_Bool isopen;
    105 SCIP_Bool writesubmipdualbound;
    106 int filenumber;
    107};
    108
    109
    110/*
    111 * Local methods
    112 */
    113
    114/** initializes the reader data */
    115static
    117 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
    118 )
    119{
    120 assert(eventhdlrdata != NULL);
    121
    122 eventhdlrdata->filename = NULL;
    123 eventhdlrdata->file = NULL;
    124 eventhdlrdata->isopen = FALSE;
    125 eventhdlrdata->oldfilename[0] = '\0';
    126 eventhdlrdata->filenumber = 1;
    127}
    128
    129#ifndef FOCUSNODE
    130/* apply all changes to the submip */
    131static
    133 SCIP* subscip, /**< scip to apply domain changes */
    134 SCIP_VAR** vars, /**< variables in original scip instance */
    135 SCIP_Real* bounds, /**< bounds which should be applied */
    136 SCIP_BOUNDTYPE* boundtypes, /**< bound types for bounds which should be applied */
    137 int nvars, /**< number of variables */
    138 SCIP_HASHMAP* varmap /**< hashmap for identifiing the corresponding variables in subscip */
    139 )
    140{
    141 SCIP_VAR* subscipvar;
    142 int v;
    143
    144 assert(subscip != NULL);
    145 assert(vars != NULL);
    146 assert(bounds != NULL);
    147 assert(boundtypes != NULL);
    148 assert(nvars > 0);
    149 assert(varmap != NULL);
    150
    151 /* need to do a downwards loop, because ing decisions are collect from bottom to root and if we ed twice on a variable, then the weaker bound is behind the stronger in this array */
    152 for( v = nvars - 1; v >= 0; --v )
    153 {
    154 subscipvar = (SCIP_VAR*) SCIPhashmapGetImage(varmap, vars[v]);
    155 assert(subscipvar != NULL);
    156
    157 if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER )
    158 {
    159 SCIP_CALL( SCIPchgVarLbGlobal(subscip, subscipvar, bounds[v]) );
    160 }
    161 else
    162 {
    163 assert(boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
    164 SCIP_CALL( SCIPchgVarUbGlobal(subscip, subscipvar, bounds[v]) );
    165 }
    166 }
    167
    168 return SCIP_OKAY;
    169}
    170#endif
    171
    172#ifdef FOCUSNODE
    173/** call writing method */
    174static
    175SCIP_RETCODE writeBoundsFocusNode(
    176 SCIP* scip, /**< SCIP data structure */
    177 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
    178 )
    179{
    180 FILE* file;
    181 SCIP_Bool writesubmipdualbound;
    182 SCIP_NODE* node;
    183
    184 assert(scip != NULL);
    185 assert(eventhdlrdata != NULL);
    186
    187 file = eventhdlrdata->file;
    188 writesubmipdualbound = eventhdlrdata->writesubmipdualbound;
    189 node = SCIPgetCurrentNode(scip);
    190
    191 /* do not process probing nodes */
    193 return SCIP_OKAY;
    194
    195 /* do not process cutoff nodes */
    197 return SCIP_OKAY;
    198
    199 if( !SCIPisEQ(scip, eventhdlrdata->lastpb, SCIPgetPrimalbound(scip)) )
    200 {
    201#ifdef LONGSTATS
    202 SCIPinfoMessage(scip, file, "Status after %"SCIP_LONGINT_FORMAT" processed nodes (%d open)\n", SCIPgetNNodes(scip), SCIPgetNNodesLeft(scip));
    203
    204 SCIPinfoMessage(scip, file, "Primalbound: %g\n", SCIPgetPrimalbound(scip));
    205 SCIPinfoMessage(scip, file, "Dualbound: %g\n", SCIPgetDualbound(scip));
    206#else
    207 SCIPinfoMessage(scip, file, "PB %g\n", SCIPgetPrimalbound(scip));
    208#endif
    209 eventhdlrdata->lastpb = SCIPgetPrimalbound(scip);
    210 }
    211
    212 if( writesubmipdualbound )
    213 {
    214 SCIP* subscip;
    215 SCIP_Bool valid;
    216 SCIP_Real submipdb;
    217 SCIP_Bool cutoff;
    218
    219 SCIP_CALL( SCIPcreate(&subscip) );
    220
    221 submipdb = SCIP_INVALID;
    222 valid = FALSE;
    223 cutoff = FALSE;
    224 SCIP_CALL( SCIPcopy(scip, subscip, NULL, NULL, "__boundwriting", FALSE, FALSE, FALSE, TRUE, &valid) );
    225
    226 if( valid )
    227 {
    228 /* do not abort subproblem on CTRL-C */
    229 SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
    230 /* disable output to console */
    231 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
    232 /* solve only root node */
    233 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", 1LL) );
    234
    235#ifdef SCIP_DISABLED_CODE
    236 /* We could evaluate the pure impact of (node) presolve and cuts on the dual bound
    237 * for the current node by disabling all heuristics and therefore disregarding any sideeffects
    238 * that are introduced due to new solutions and their subsequent reductions. */
    240#endif
    241
    242 /* set cutoffbound as objective limit for subscip */
    244
    245 SCIP_CALL( SCIPsolve(subscip) );
    246
    247 cutoff = (SCIPgetStatus(subscip) == SCIP_STATUS_INFEASIBLE);
    249 }
    250
    251#ifdef LONGSTATS
    252 SCIPinfoMessage(scip, file, "Node %"SCIP_LONGINT_FORMAT" (depth %d): dualbound: %g, nodesubmiprootdualbound: %g %s\n", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), SCIPgetNodeDualbound(scip, node), submipdb, cutoff ? "(cutoff)" : "");
    253#else
    254 SCIPinfoMessage(scip, file, "%"SCIP_LONGINT_FORMAT" %d %g %g %s\n", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), SCIPgetNodeDualbound(scip, node), submipdb, cutoff ? "(cutoff)" : "");
    255#endif
    256
    257 SCIP_CALL( SCIPfree(&subscip) );
    258 }
    259 else
    260 {
    261#ifdef LONGSTATS
    262 SCIPinfoMessage(scip, file, "Node %"SCIP_LONGINT_FORMAT" (depth %d): dualbound: %g\n", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), SCIPgetNodeDualbound(scip, node));
    263#else
    265#endif
    266 }
    267
    268#ifdef LONGSTATS
    269 SCIPinfoMessage(scip, file, "\n");
    270#endif
    271
    272 return SCIP_OKAY;
    273}
    274
    275#else
    276
    277/** call writing method */
    278static
    280 SCIP* scip, /**< SCIP data structure */
    281 FILE* file, /**< file to write to or NULL */
    282 SCIP_Bool writesubmipdualbound/**< write dualbounds of submip roots for all open nodes */
    283 )
    284{
    285 SCIP_NODE** opennodes = NULL;
    286 int nopennodes;
    287 int n;
    288 int v;
    289
    290 assert(scip != NULL);
    291
    292 nopennodes = -1;
    293
    294#ifdef LONGSTATS
    295 SCIPinfoMessage(scip, file, "Status after %"SCIP_LONGINT_FORMAT" processed nodes (%d open)\n", SCIPgetNNodes(scip), SCIPgetNNodesLeft(scip));
    296
    297 SCIPinfoMessage(scip, file, "Primalbound: %g\n", SCIPgetPrimalbound(scip));
    298 SCIPinfoMessage(scip, file, "Dualbound: %g\n", SCIPgetDualbound(scip));
    299#else
    300 SCIPinfoMessage(scip, file, "PB %g\n", SCIPgetPrimalbound(scip));
    301#endif
    302
    303 /* get all open nodes and therefor print all dualbounds */
    304 for( v = 2; v >= 0; --v )
    305 {
    306 SCIP_NODE* node;
    307
    308 switch( v )
    309 {
    310 case 2:
    311 SCIP_CALL( SCIPgetChildren(scip, &opennodes, &nopennodes) );
    312 break;
    313 case 1:
    314 SCIP_CALL( SCIPgetSiblings(scip, &opennodes, &nopennodes) );
    315 break;
    316 case 0:
    317 SCIP_CALL( SCIPgetLeaves(scip, &opennodes, &nopennodes) );
    318 break;
    319 default:
    320 SCIPABORT();
    321 break;
    322 }
    323 assert(nopennodes >= 0);
    324
    325 /* print all node information */
    326 for( n = nopennodes - 1; n >= 0 && !SCIPisStopped(scip); --n )
    327 {
    328 assert( opennodes != NULL );
    329 node = opennodes[n];
    330
    331 if( writesubmipdualbound )
    332 {
    333 SCIP* subscip;
    334 SCIP_Bool valid;
    335 SCIP_HASHMAP* varmap; /* mapping of SCIP variables to sub-SCIP variables */
    336 SCIP_VAR** vars; /* original problem's variables */
    337 int nvars;
    338 SCIP_Real submipdb;
    339 SCIP_Bool cutoff;
    340
    341 SCIP_CALL( SCIPcreate(&subscip) );
    342
    343 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
    344
    345 /* create the variable mapping hash map */
    346 SCIP_CALL( SCIPhashmapCreate(&varmap, SCIPblkmem(subscip), nvars) );
    347
    348 submipdb = SCIP_INVALID;
    349 valid = FALSE;
    350 cutoff = FALSE;
    351 SCIP_CALL( SCIPcopy(scip, subscip, varmap, NULL, "__boundwriting", TRUE, FALSE, FALSE, TRUE, &valid) );
    352
    353 if( valid )
    354 {
    355 SCIP_VAR** branchvars;
    356 SCIP_Real* branchbounds;
    357 SCIP_BOUNDTYPE* boundtypes;
    358 int nbranchvars;
    359 int size;
    360
    361 size = SCIPnodeGetDepth(node);
    362
    363 /* allocate memory for all branching decisions */
    364 SCIP_CALL( SCIPallocBufferArray(scip, &branchvars, size) );
    365 SCIP_CALL( SCIPallocBufferArray(scip, &branchbounds, size) );
    366 SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, size) );
    367
    368 /* we assume that we only have one branching decision at each node */
    369 SCIPnodeGetAncestorBranchings( node, branchvars, branchbounds, boundtypes, &nbranchvars, size );
    370
    371 /* check if did not have enough memory */
    372 if( nbranchvars > size )
    373 {
    374 size = nbranchvars;
    375 SCIP_CALL( SCIPallocBufferArray(scip, &branchvars, size) );
    376 SCIP_CALL( SCIPallocBufferArray(scip, &branchbounds, size) );
    377 SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, size) );
    378
    379 /* now getting all information */
    380 SCIPnodeGetAncestorBranchings( node, branchvars, branchbounds, boundtypes, &nbranchvars, size );
    381 }
    382
    383 /* apply all changes to the submip */
    384 SCIP_CALL( applyDomainChanges(subscip, branchvars, branchbounds, boundtypes, nbranchvars, varmap) );
    385
    386 /* free memory for all branching decisions */
    387 SCIPfreeBufferArray(scip, &boundtypes);
    388 SCIPfreeBufferArray(scip, &branchbounds);
    389 SCIPfreeBufferArray(scip, &branchvars);
    390
    391 /* do not abort subproblem on CTRL-C */
    392 SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
    393 /* disable output to console */
    394 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
    395 /* solve only root node */
    396 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", 1LL) );
    397
    398 /* set cutoffbound as objective limit for subscip */
    400
    401 SCIP_CALL( SCIPsolve(subscip) );
    402
    403 cutoff = (SCIPgetStatus(subscip) == SCIP_STATUS_INFEASIBLE);
    405 }
    406
    407#ifdef LONGSTATS
    408 SCIPinfoMessage(scip, file, "Node %"SCIP_LONGINT_FORMAT" (depth %d): dualbound: %g, nodesubmiprootdualbound: %g %s\n", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), SCIPgetNodeDualbound(scip, node), submipdb, cutoff ? "(cutoff)" : "");
    409#else
    410 SCIPinfoMessage(scip, file, "%"SCIP_LONGINT_FORMAT" %d %g %g %s\n", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), SCIPgetNodeDualbound(scip, node), submipdb, cutoff ? "(cutoff)" : "");
    411#endif
    412
    413 /* free hash map */
    414 SCIPhashmapFree(&varmap);
    415
    416 SCIP_CALL( SCIPfree(&subscip) );
    417 }
    418 else
    419 {
    420#ifdef LONGSTATS
    421 SCIPinfoMessage(scip, file, "Node %"SCIP_LONGINT_FORMAT" (depth %d): dualbound: %g\n", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), SCIPgetNodeDualbound(scip, node));
    422#else
    424#endif
    425 }
    426 }
    427 }
    428
    429#ifdef LONGSTATS
    430 SCIPinfoMessage(scip, file, "\n");
    431#endif
    432
    433 return SCIP_OKAY;
    434}
    435#endif
    436
    437/*
    438 * Callback methods of event handler
    439 */
    440
    441/** copy method for event handler plugins (called when SCIP copies plugins) */
    442static
    443SCIP_DECL_EVENTCOPY(eventCopyBoundwriting)
    444{ /*lint --e{715}*/
    445 assert(scip != NULL);
    446 assert(eventhdlr != NULL);
    447 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
    448
    449#ifdef SCIP_DISABLED_CODE
    450 /* To copy and run this event handler in subMIPs, the following code block can be enabled. */
    452#endif
    453
    454 return SCIP_OKAY;
    455}
    456
    457/** destructor of event handler to free user data (called when SCIP is exiting) */
    458static
    459SCIP_DECL_EVENTFREE(eventFreeBoundwriting)
    460{ /*lint --e{715}*/
    461 SCIP_EVENTHDLRDATA* eventhdlrdata;
    462
    463 assert(scip != NULL);
    464 assert(eventhdlr != NULL);
    465
    466 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
    467 assert(eventhdlrdata != NULL);
    468 assert(!eventhdlrdata->isopen);
    469 assert(eventhdlrdata->file == NULL);
    470
    471 SCIPfreeBlockMemory(scip, &eventhdlrdata);
    472
    473 return SCIP_OKAY;
    474}
    475
    476/** initialization method of event handler (called after problem was transformed) */
    477static
    478SCIP_DECL_EVENTINIT(eventInitBoundwriting)
    479{ /*lint --e{715}*/
    480 SCIP_EVENTHDLRDATA* eventhdlrdata;
    481
    482 assert(scip != NULL);
    483 assert(eventhdlr != NULL);
    484 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
    485
    486 /* notify SCIP that your event handler wants to react on the event type best solution found */
    488
    489 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
    490 assert(eventhdlrdata != NULL);
    491 eventhdlrdata->lastpb = SCIPinfinity(scip) * (SCIPgetObjsense(scip) == SCIP_OBJSENSE_MINIMIZE ? 1.0 : -1.0);
    492
    493 return SCIP_OKAY;
    494}
    495
    496/** deinitialization method of event handler (called before transformed problem is freed) */
    497static
    498SCIP_DECL_EVENTEXIT(eventExitBoundwriting)
    499{ /*lint --e{715}*/
    500 SCIP_EVENTHDLRDATA* eventhdlrdata;
    501
    502 assert(scip != NULL);
    503 assert(eventhdlr != NULL);
    504 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
    505
    506 /* notify SCIP that your event handler wants to drop the event type best solution found */
    508
    509 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
    510 assert(eventhdlrdata != NULL);
    511
    512 if( eventhdlrdata->isopen )
    513 {
    514 (void) fclose(eventhdlrdata->file);
    515 eventhdlrdata->isopen = FALSE;
    516 }
    517 eventhdlrdata->file = NULL;
    518 eventhdlrdata->oldfilename[0] = '\0';
    519 eventhdlrdata->filenumber = 1;
    520
    521 return SCIP_OKAY;
    522}
    523
    524/** execution method of event handler */
    525static
    526SCIP_DECL_EVENTEXEC(eventExecBoundwriting)
    527{ /*lint --e{715}*/
    528 SCIP_EVENTHDLRDATA* eventhdlrdata;
    529
    530 assert(scip != NULL);
    531 assert(eventhdlr != NULL);
    532 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
    533 assert(event != NULL);
    535
    536 SCIPdebugMsg(scip, "exec method of event handler for writing primal- and dualbounds\n");
    537
    538 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
    539 assert(eventhdlrdata != NULL);
    540
    541#ifdef ONEFILE
    542 /* check if we need to open the file */
    543 if( strlen(eventhdlrdata->filename) > 0 && !eventhdlrdata->isopen )
    544 {
    545 assert(eventhdlrdata->file == NULL);
    546 assert(eventhdlrdata->oldfilename[0] == '\0');
    547
    548 eventhdlrdata->file = fopen(eventhdlrdata->filename, "w");
    549 (void)SCIPstrncpy(eventhdlrdata->oldfilename, eventhdlrdata->filename, SCIP_MAXSTRLEN);
    550
    551 if( eventhdlrdata->file == NULL )
    552 {
    553 SCIPerrorMessage("cannot create file <%s> for writing\n", eventhdlrdata->filename);
    554 SCIPprintSysError(eventhdlrdata->filename);
    556 }
    557 eventhdlrdata->isopen = TRUE;
    558
    559#ifdef LONGSTATS
    560 SCIPinfoMessage(scip, eventhdlrdata->file, "Problem: %s (%d Original Constraints, %d Original Variables)\n", SCIPgetProbName(scip), SCIPgetNOrigConss(scip), SCIPgetNOrigVars(scip) );
    561 SCIPinfoMessage(scip, eventhdlrdata->file, "\t (%d Presolved Constraints, %d Presolved Variables, (%d binary, %d integer, %d implicit integer, %d continuous))\n", SCIPgetNConss(scip), SCIPgetNVars(scip), SCIPgetNBinVars(scip), SCIPgetNIntVars(scip), SCIPgetNImplVars(scip), SCIPgetNContVars(scip));
    562 SCIPinfoMessage(scip, eventhdlrdata->file, "\n");
    563#endif
    564 }
    565#endif
    566
    567 /* call writing only at right moment */
    568 if( eventhdlrdata->freq == 0 || (SCIPgetNNodes(scip) % eventhdlrdata->freq) != 0 )
    569 return SCIP_OKAY;
    570
    571#ifndef ONEFILE
    572 if( strlen(eventhdlrdata->filename) > 0 )
    573 {
    574 char name[SCIP_MAXSTRLEN];
    576 char* pch;
    577 int n;
    578
    579 assert(eventhdlrdata->file == NULL);
    580 assert(!eventhdlrdata->isopen);
    581
    582 if( eventhdlrdata->oldfilename[0] == '\0' )
    583 (void)SCIPstrncpy(eventhdlrdata->oldfilename, eventhdlrdata->filename, SCIP_MAXSTRLEN);
    584
    585 /* find last '.' to append filenumber */
    586 pch = strrchr(eventhdlrdata->filename,'.');
    587
    588 assert(eventhdlrdata->filenumber > 0);
    589 n = sprintf(number, "%"SCIP_LONGINT_FORMAT"", eventhdlrdata->filenumber * eventhdlrdata->freq);
    590 assert(n > 0);
    591 assert(n < SCIP_MAXSTRLEN);
    592
    593 /* if no point is found, extend directly */
    594 if( pch == NULL )
    595 {
    596 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s%s", eventhdlrdata->filename, number);
    597 }
    598 else
    599 {
    600 int len;
    601
    602 if( (pch-(eventhdlrdata->filename)) >= (SCIP_MAXSTRLEN - n) ) /*lint !e776*/
    603 len = SCIP_MAXSTRLEN - n - 1;
    604 else
    605 len = (int) (pch-(eventhdlrdata->filename));
    606
    607 (void)SCIPstrncpy(name, eventhdlrdata->filename, len);
    608 (void)strncat(name, number, (size_t)n);
    609 assert(len+n >= 0);
    610 assert(len+n < SCIP_MAXSTRLEN);
    611 name[len+n] = '\0'; /*lint !e676*//*lint !e661*/
    612
    613 if( len + n + strlen(&(eventhdlrdata->filename[len])) < SCIP_MAXSTRLEN ) /*lint !e776*/
    614 strcat(name, &(eventhdlrdata->filename[len]));
    615 }
    616
    617 eventhdlrdata->file = fopen(name, "w");
    618
    619 if( eventhdlrdata->file == NULL )
    620 {
    621 SCIPerrorMessage("cannot create file <%s> for writing\n", eventhdlrdata->filename);
    622 SCIPprintSysError(eventhdlrdata->filename);
    624 }
    625 eventhdlrdata->isopen = TRUE;
    626
    627#ifdef LONGSTATS
    628 SCIPinfoMessage(scip, eventhdlrdata->file, "Problem: %s (%d Original Constraints, %d Original Variables)\n", SCIPgetProbName(scip), SCIPgetNOrigConss(scip), SCIPgetNOrigVars(scip) );
    629 SCIPinfoMessage(scip, eventhdlrdata->file, "\t (%d Active Constraints, %d Active Variables, (%d binary, %d integer, %d implicit integer, %d continuous))\n", SCIPgetNConss(scip), SCIPgetNVars(scip), SCIPgetNBinVars(scip), SCIPgetNIntVars(scip), SCIPgetNImplVars(scip), SCIPgetNContVars(scip));
    630 SCIPinfoMessage(scip, eventhdlrdata->file, "\n");
    631#endif
    632 }
    633#endif
    634
    635#ifndef NDEBUG
    636 /* check the filename did not change during the solving */
    637 if( strlen(eventhdlrdata->filename) > 0 && eventhdlrdata->isopen )
    638 {
    639 char tmp[SCIP_MAXSTRLEN];
    640
    641 (void)SCIPstrncpy(tmp, eventhdlrdata->filename, SCIP_MAXSTRLEN);
    642
    643 /* the name should stay the same */
    644 assert(strcmp(tmp, eventhdlrdata->oldfilename) == 0);
    645 }
    646#endif
    647
    648#ifdef FOCUSNODE
    649 /* call writing method */
    650 SCIP_CALL( writeBoundsFocusNode(scip, eventhdlrdata) );
    651#else
    652 /* call writing method */
    653 SCIP_CALL( writeBounds(scip, eventhdlrdata->file, eventhdlrdata->writesubmipdualbound) );
    654#endif
    655
    656#ifndef ONEFILE
    657 if( strlen(eventhdlrdata->filename) > 0 )
    658 {
    659 assert(eventhdlrdata->isopen);
    660
    661 (void) fclose(eventhdlrdata->file);
    662 eventhdlrdata->isopen = FALSE;
    663 eventhdlrdata->file = NULL;
    664 ++(eventhdlrdata->filenumber);
    665 }
    666#endif
    667
    668 return SCIP_OKAY;
    669}
    670
    671/** includes event handler for writing primal- and dualbound for all open nodes */
    673 SCIP* scip /**< SCIP data structure */
    674 )
    675{
    676 SCIP_EVENTHDLRDATA* eventhdlrdata;
    677 SCIP_EVENTHDLR* eventhdlr;
    678
    679 /* create bounds reader data */
    680 SCIP_CALL( SCIPallocBlockMemory(scip, &eventhdlrdata) );
    681 initEventhdlrdata(eventhdlrdata);
    682
    683 eventhdlr = NULL;
    684 /* create event handler for events on watched variables */
    686 eventExecBoundwriting, eventhdlrdata) );
    687 assert(eventhdlr != NULL);
    688
    689 SCIP_CALL( SCIPsetEventhdlrCopy(scip, eventhdlr, eventCopyBoundwriting) );
    690 SCIP_CALL( SCIPsetEventhdlrFree(scip, eventhdlr, eventFreeBoundwriting) );
    691 SCIP_CALL( SCIPsetEventhdlrInit(scip, eventhdlr, eventInitBoundwriting) );
    692 SCIP_CALL( SCIPsetEventhdlrExit(scip, eventhdlr, eventExitBoundwriting) );
    693
    694 /* add boundwriting parameters */
    696 "eventhdlr/"EVENTHDLR_NAME"/freq",
    697 "in which frequency should all bounds be written(0: never)",
    698 &eventhdlrdata->freq, FALSE, DEFAULT_FREQ, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    700 "eventhdlr/"EVENTHDLR_NAME"/filename",
    701 "filename to write all bounds to",
    702 &eventhdlrdata->filename, FALSE, DEFAULT_FILENAME, NULL, NULL) );
    704 "eventhdlr/"EVENTHDLR_NAME"/writesubmipdualbound",
    705 "should the dualbound of the submip-root which was created out of an open node be printed",
    706 &eventhdlrdata->writesubmipdualbound, FALSE, DEFAULT_WRITESUBMIPDUALBOUND, NULL, NULL) );
    707
    708 return SCIP_OKAY;
    709}
    static long * number
    #define NULL
    Definition: def.h:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #define SCIP_Longint
    Definition: def.h:141
    #define SCIP_INVALID
    Definition: def.h:178
    #define SCIP_Bool
    Definition: def.h:91
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:148
    #define SCIPABORT()
    Definition: def.h:327
    #define SCIP_LONGINT_MAX
    Definition: def.h:142
    #define SCIP_CALL(x)
    Definition: def.h:355
    static SCIP_DECL_EVENTCOPY(eventCopyBoundwriting)
    SCIP_RETCODE SCIPincludeEventHdlrBoundwriting(SCIP *scip)
    #define DEFAULT_FILENAME
    static SCIP_DECL_EVENTFREE(eventFreeBoundwriting)
    static SCIP_DECL_EVENTEXIT(eventExitBoundwriting)
    static SCIP_RETCODE applyDomainChanges(SCIP *subscip, SCIP_VAR **vars, SCIP_Real *bounds, SCIP_BOUNDTYPE *boundtypes, int nvars, SCIP_HASHMAP *varmap)
    static SCIP_DECL_EVENTINIT(eventInitBoundwriting)
    static void initEventhdlrdata(SCIP_EVENTHDLRDATA *eventhdlrdata)
    #define DEFAULT_FREQ
    static SCIP_DECL_EVENTEXEC(eventExecBoundwriting)
    #define EVENTHDLR_DESC
    #define DEFAULT_WRITESUBMIPDUALBOUND
    #define EVENTHDLR_NAME
    static SCIP_RETCODE writeBounds(SCIP *scip, FILE *file, SCIP_Bool writesubmipdualbound)
    event handler for writing primal- and dual bound for all open nodes
    SCIP_RETCODE SCIPcopy(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, const char *suffix, SCIP_Bool global, SCIP_Bool enablepricing, SCIP_Bool threadsafe, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
    Definition: scip_copy.c:2865
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:759
    SCIP_RETCODE SCIPfree(SCIP **scip)
    Definition: scip_general.c:402
    SCIP_RETCODE SCIPcreate(SCIP **scip)
    Definition: scip_general.c:370
    SCIP_STATUS SCIPgetStatus(SCIP *scip)
    Definition: scip_general.c:562
    int SCIPgetNIntVars(SCIP *scip)
    Definition: scip_prob.c:2340
    int SCIPgetNImplVars(SCIP *scip)
    Definition: scip_prob.c:2387
    const char * SCIPgetProbName(SCIP *scip)
    Definition: scip_prob.c:1242
    int SCIPgetNContVars(SCIP *scip)
    Definition: scip_prob.c:2569
    SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
    Definition: scip_prob.c:1661
    SCIP_Real SCIPgetTransObjoffset(SCIP *scip)
    Definition: scip_prob.c:1606
    SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
    Definition: scip_prob.c:2115
    int SCIPgetNOrigConss(SCIP *scip)
    Definition: scip_prob.c:3712
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    int SCIPgetNConss(SCIP *scip)
    Definition: scip_prob.c:3620
    int SCIPgetNOrigVars(SCIP *scip)
    Definition: scip_prob.c:2838
    SCIP_OBJSENSE SCIPgetObjsense(SCIP *scip)
    Definition: scip_prob.c:1400
    int SCIPgetNBinVars(SCIP *scip)
    Definition: scip_prob.c:2293
    SCIP_Real SCIPgetTransObjscale(SCIP *scip)
    Definition: scip_prob.c:1629
    void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
    Definition: misc.c:3095
    void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3284
    SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
    Definition: misc.c:3061
    SCIP_Real SCIPgetNodeDualbound(SCIP *scip, SCIP_NODE *node)
    Definition: scip_prob.c:4198
    void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:208
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    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 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 SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
    Definition: scip_param.c:545
    SCIP_RETCODE SCIPsetHeuristics(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
    Definition: scip_param.c:930
    SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
    Definition: scip_param.c:487
    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 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
    const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
    Definition: event.c:396
    SCIP_EVENTHDLRDATA * SCIPeventhdlrGetData(SCIP_EVENTHDLR *eventhdlr)
    Definition: event.c:406
    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_RETCODE SCIPdropEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
    Definition: scip_event.c:333
    BMS_BLKMEM * SCIPblkmem(SCIP *scip)
    Definition: scip_mem.c:57
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    void SCIPnodeGetAncestorBranchings(SCIP_NODE *node, SCIP_VAR **branchvars, SCIP_Real *branchbounds, SCIP_BOUNDTYPE *boundtypes, int *nbranchvars, int branchvarssize)
    Definition: tree.c:8856
    SCIP_NODETYPE SCIPnodeGetType(SCIP_NODE *node)
    Definition: tree.c:8473
    SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
    Definition: tree.c:8483
    int SCIPnodeGetDepth(SCIP_NODE *node)
    Definition: tree.c:8493
    SCIP_RETCODE SCIPsolve(SCIP *scip)
    Definition: scip_solve.c:2635
    SCIP_Real SCIPgetPrimalbound(SCIP *scip)
    SCIP_Longint SCIPgetNNodes(SCIP *scip)
    SCIP_Real SCIPgetDualbound(SCIP *scip)
    SCIP_Real SCIPgetCutoffbound(SCIP *scip)
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    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
    SCIP_RETCODE SCIPchgVarLbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_var.c:6141
    SCIP_RETCODE SCIPchgVarUbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_var.c:6230
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    void SCIPprintSysError(const char *message)
    Definition: misc.c:10719
    int SCIPstrncpy(char *t, const char *s, int size)
    Definition: misc.c:10897
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    #define SCIP_EVENTTYPE_NODEFEASIBLE
    Definition: type_event.h:94
    #define SCIP_EVENTTYPE_NODEINFEASIBLE
    Definition: type_event.h:95
    struct SCIP_EventhdlrData SCIP_EVENTHDLRDATA
    Definition: type_event.h:160
    #define SCIP_EVENTTYPE_NODEBRANCHED
    Definition: type_event.h:96
    #define SCIP_EVENTTYPE_NODESOLVED
    Definition: type_event.h:138
    @ SCIP_BOUNDTYPE_UPPER
    Definition: type_lp.h:58
    @ SCIP_BOUNDTYPE_LOWER
    Definition: type_lp.h:57
    enum SCIP_BoundType SCIP_BOUNDTYPE
    Definition: type_lp.h:60
    @ SCIP_PARAMSETTING_OFF
    Definition: type_paramset.h:63
    @ SCIP_OBJSENSE_MINIMIZE
    Definition: type_prob.h:48
    @ SCIP_FILECREATEERROR
    Definition: type_retcode.h:48
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STATUS_INFEASIBLE
    Definition: type_stat.h:44
    @ SCIP_NODETYPE_PROBINGNODE
    Definition: type_tree.h:42