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;
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 assert(0);
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 node = opennodes[n];
329
330 if( writesubmipdualbound )
331 {
332 SCIP* subscip;
333 SCIP_Bool valid;
334 SCIP_HASHMAP* varmap; /* mapping of SCIP variables to sub-SCIP variables */
335 SCIP_VAR** vars; /* original problem's variables */
336 int nvars;
337 SCIP_Real submipdb;
338 SCIP_Bool cutoff;
339
340 SCIP_CALL( SCIPcreate(&subscip) );
341
342 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
343
344 /* create the variable mapping hash map */
345 SCIP_CALL( SCIPhashmapCreate(&varmap, SCIPblkmem(subscip), nvars) );
346
347 submipdb = SCIP_INVALID;
348 valid = FALSE;
349 cutoff = FALSE;
350 SCIP_CALL( SCIPcopy(scip, subscip, varmap, NULL, "__boundwriting", TRUE, FALSE, FALSE, TRUE, &valid) );
351
352 if( valid )
353 {
354 SCIP_VAR** branchvars;
355 SCIP_Real* branchbounds;
356 SCIP_BOUNDTYPE* boundtypes;
357 int nbranchvars;
358 int size;
359
360 size = SCIPnodeGetDepth(node);
361
362 /* allocate memory for all branching decisions */
363 SCIP_CALL( SCIPallocBufferArray(scip, &branchvars, size) );
364 SCIP_CALL( SCIPallocBufferArray(scip, &branchbounds, size) );
365 SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, size) );
366
367 /* we assume that we only have one branching decision at each node */
368 SCIPnodeGetAncestorBranchings( node, branchvars, branchbounds, boundtypes, &nbranchvars, size );
369
370 /* check if did not have enough memory */
371 if( nbranchvars > size )
372 {
373 size = nbranchvars;
374 SCIP_CALL( SCIPallocBufferArray(scip, &branchvars, size) );
375 SCIP_CALL( SCIPallocBufferArray(scip, &branchbounds, size) );
376 SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, size) );
377
378 /* now getting all information */
379 SCIPnodeGetAncestorBranchings( node, branchvars, branchbounds, boundtypes, &nbranchvars, size );
380 }
381
382 /* apply all changes to the submip */
383 SCIP_CALL( applyDomainChanges(subscip, branchvars, branchbounds, boundtypes, nbranchvars, varmap) );
384
385 /* free memory for all branching decisions */
386 SCIPfreeBufferArray(scip, &boundtypes);
387 SCIPfreeBufferArray(scip, &branchbounds);
388 SCIPfreeBufferArray(scip, &branchvars);
389
390 /* do not abort subproblem on CTRL-C */
391 SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
392 /* disable output to console */
393 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
394 /* solve only root node */
395 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", 1LL) );
396
397 /* set cutoffbound as objective limit for subscip */
399
400 SCIP_CALL( SCIPsolve(subscip) );
401
402 cutoff = (SCIPgetStatus(subscip) == SCIP_STATUS_INFEASIBLE);
404 }
405
406#ifdef LONGSTATS
407 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)" : "");
408#else
409 SCIPinfoMessage(scip, file, "%"SCIP_LONGINT_FORMAT" %d %g %g %s\n", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), SCIPgetNodeDualbound(scip, node), submipdb, cutoff ? "(cutoff)" : "");
410#endif
411
412 /* free hash map */
413 SCIPhashmapFree(&varmap);
414
415 SCIP_CALL( SCIPfree(&subscip) );
416 }
417 else
418 {
419#ifdef LONGSTATS
420 SCIPinfoMessage(scip, file, "Node %"SCIP_LONGINT_FORMAT" (depth %d): dualbound: %g\n", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), SCIPgetNodeDualbound(scip, node));
421#else
423#endif
424 }
425 }
426 }
427
428#ifdef LONGSTATS
429 SCIPinfoMessage(scip, file, "\n");
430#endif
431
432 return SCIP_OKAY;
433}
434#endif
435
436/*
437 * Callback methods of event handler
438 */
439
440/** copy method for event handler plugins (called when SCIP copies plugins) */
441static
442SCIP_DECL_EVENTCOPY(eventCopyBoundwriting)
443{ /*lint --e{715}*/
444 assert(scip != NULL);
445 assert(eventhdlr != NULL);
446 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
447
448#ifdef SCIP_DISABLED_CODE
449 /* To copy and run this event handler in subMIPs, the following code block can be enabled. */
451#endif
452
453 return SCIP_OKAY;
454}
455
456/** destructor of event handler to free user data (called when SCIP is exiting) */
457static
458SCIP_DECL_EVENTFREE(eventFreeBoundwriting)
459{ /*lint --e{715}*/
460 SCIP_EVENTHDLRDATA* eventhdlrdata;
461
462 assert(scip != NULL);
463 assert(eventhdlr != NULL);
464
465 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
466 assert(eventhdlrdata != NULL);
467 assert(!eventhdlrdata->isopen);
468 assert(eventhdlrdata->file == NULL);
469
470 SCIPfreeBlockMemory(scip, &eventhdlrdata);
471
472 return SCIP_OKAY;
473}
474
475/** initialization method of event handler (called after problem was transformed) */
476static
477SCIP_DECL_EVENTINIT(eventInitBoundwriting)
478{ /*lint --e{715}*/
479 SCIP_EVENTHDLRDATA* eventhdlrdata;
480
481 assert(scip != NULL);
482 assert(eventhdlr != NULL);
483 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
484
485 /* notify SCIP that your event handler wants to react on the event type best solution found */
487
488 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
489 assert(eventhdlrdata != NULL);
490 eventhdlrdata->lastpb = SCIPinfinity(scip) * (SCIPgetObjsense(scip) == SCIP_OBJSENSE_MINIMIZE ? 1.0 : -1.0);
491
492 return SCIP_OKAY;
493}
494
495/** deinitialization method of event handler (called before transformed problem is freed) */
496static
497SCIP_DECL_EVENTEXIT(eventExitBoundwriting)
498{ /*lint --e{715}*/
499 SCIP_EVENTHDLRDATA* eventhdlrdata;
500
501 assert(scip != NULL);
502 assert(eventhdlr != NULL);
503 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
504
505 /* notify SCIP that your event handler wants to drop the event type best solution found */
507
508 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
509 assert(eventhdlrdata != NULL);
510
511 if( eventhdlrdata->isopen )
512 {
513 (void) fclose(eventhdlrdata->file);
514 eventhdlrdata->isopen = FALSE;
515 }
516 eventhdlrdata->file = NULL;
517 eventhdlrdata->oldfilename[0] = '\0';
518 eventhdlrdata->filenumber = 1;
519
520 return SCIP_OKAY;
521}
522
523/** execution method of event handler */
524static
525SCIP_DECL_EVENTEXEC(eventExecBoundwriting)
526{ /*lint --e{715}*/
527 SCIP_EVENTHDLRDATA* eventhdlrdata;
528
529 assert(scip != NULL);
530 assert(eventhdlr != NULL);
531 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
532 assert(event != NULL);
534
535 SCIPdebugMsg(scip, "exec method of event handler for writing primal- and dualbounds\n");
536
537 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
538 assert(eventhdlrdata != NULL);
539
540#ifdef ONEFILE
541 /* check if we need to open the file */
542 if( strlen(eventhdlrdata->filename) > 0 && !eventhdlrdata->isopen )
543 {
544 assert(eventhdlrdata->file == NULL);
545 assert(eventhdlrdata->oldfilename[0] == '\0');
546
547 eventhdlrdata->file = fopen(eventhdlrdata->filename, "w");
548 (void)SCIPstrncpy(eventhdlrdata->oldfilename, eventhdlrdata->filename, SCIP_MAXSTRLEN);
549
550 if( eventhdlrdata->file == NULL )
551 {
552 SCIPerrorMessage("cannot create file <%s> for writing\n", eventhdlrdata->filename);
553 SCIPprintSysError(eventhdlrdata->filename);
555 }
556 eventhdlrdata->isopen = TRUE;
557
558#ifdef LONGSTATS
559 SCIPinfoMessage(scip, eventhdlrdata->file, "Problem: %s (%d Original Constraints, %d Original Variables)\n", SCIPgetProbName(scip), SCIPgetNOrigConss(scip), SCIPgetNOrigVars(scip) );
560 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));
561 SCIPinfoMessage(scip, eventhdlrdata->file, "\n");
562#endif
563 }
564#endif
565
566 /* call writing only at right moment */
567 if( eventhdlrdata->freq == 0 || (SCIPgetNNodes(scip) % eventhdlrdata->freq) != 0 )
568 return SCIP_OKAY;
569
570#ifndef ONEFILE
571 if( strlen(eventhdlrdata->filename) > 0 )
572 {
573 char name[SCIP_MAXSTRLEN];
575 char* pch;
576 int n;
577
578 assert(eventhdlrdata->file == NULL);
579 assert(!eventhdlrdata->isopen);
580
581 if( eventhdlrdata->oldfilename[0] == '\0' )
582 (void)SCIPstrncpy(eventhdlrdata->oldfilename, eventhdlrdata->filename, SCIP_MAXSTRLEN);
583
584 /* find last '.' to append filenumber */
585 pch=strrchr(eventhdlrdata->filename,'.');
586
587 assert(eventhdlrdata->filenumber > 0);
588 n=sprintf(number, "%"SCIP_LONGINT_FORMAT"", eventhdlrdata->filenumber * eventhdlrdata->freq);
589 assert(n > 0);
590 assert(n < SCIP_MAXSTRLEN);
591
592 /* if no point is found, extend directly */
593 if( pch == NULL )
594 {
595 (void)SCIPstrncpy(name, eventhdlrdata->filename, SCIP_MAXSTRLEN - n);
596 strncat(name, number, (unsigned int)n);
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 strncat(name, number, (unsigned int)n);
609 assert(len+n < SCIP_MAXSTRLEN);
610 name[len+n] = '\0';
611
612 if( len + n + strlen(&(eventhdlrdata->filename[len])) < SCIP_MAXSTRLEN ) /*lint !e776*/
613 strcat(name, &(eventhdlrdata->filename[len]));
614 }
615
616 eventhdlrdata->file = fopen(name, "w");
617
618 if( eventhdlrdata->file == NULL )
619 {
620 SCIPerrorMessage("cannot create file <%s> for writing\n", eventhdlrdata->filename);
621 SCIPprintSysError(eventhdlrdata->filename);
623 }
624 eventhdlrdata->isopen = TRUE;
625
626#ifdef LONGSTATS
627 SCIPinfoMessage(scip, eventhdlrdata->file, "Problem: %s (%d Original Constraints, %d Original Variables)\n", SCIPgetProbName(scip), SCIPgetNOrigConss(scip), SCIPgetNOrigVars(scip) );
628 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));
629 SCIPinfoMessage(scip, eventhdlrdata->file, "\n");
630#endif
631 }
632#endif
633
634#ifndef NDEBUG
635 /* check the filename did not change during the solving */
636 if( strlen(eventhdlrdata->filename) > 0 && eventhdlrdata->isopen )
637 {
638 char tmp[SCIP_MAXSTRLEN];
639
640 (void)SCIPstrncpy(tmp, eventhdlrdata->filename, SCIP_MAXSTRLEN);
641
642 /* the name should stay the same */
643 assert(strcmp(tmp, eventhdlrdata->oldfilename) == 0);
644 }
645#endif
646
647#ifdef FOCUSNODE
648 /* call writing method */
649 SCIP_CALL( writeBoundsFocusNode(scip, eventhdlrdata) );
650#else
651 /* call writing method */
652 SCIP_CALL( writeBounds(scip, eventhdlrdata->file, eventhdlrdata->writesubmipdualbound) );
653#endif
654
655#ifndef ONEFILE
656 if( strlen(eventhdlrdata->filename) > 0 )
657 {
658 assert(eventhdlrdata->isopen);
659
660 (void) fclose(eventhdlrdata->file);
661 eventhdlrdata->isopen = FALSE;
662 eventhdlrdata->file = NULL;
663 ++(eventhdlrdata->filenumber);
664 }
665#endif
666
667 return SCIP_OKAY;
668}
669
670/** includes event handler for writing primal- and dualbound for all open nodes */
672 SCIP* scip /**< SCIP data structure */
673 )
674{
675 SCIP_EVENTHDLRDATA* eventhdlrdata;
676 SCIP_EVENTHDLR* eventhdlr;
677
678 /* create bounds reader data */
679 SCIP_CALL( SCIPallocBlockMemory(scip, &eventhdlrdata) );
680 initEventhdlrdata(eventhdlrdata);
681
682 eventhdlr = NULL;
683 /* create event handler for events on watched variables */
685 eventExecBoundwriting, eventhdlrdata) );
686 assert(eventhdlr != NULL);
687
688 SCIP_CALL( SCIPsetEventhdlrCopy(scip, eventhdlr, eventCopyBoundwriting) );
689 SCIP_CALL( SCIPsetEventhdlrFree(scip, eventhdlr, eventFreeBoundwriting) );
690 SCIP_CALL( SCIPsetEventhdlrInit(scip, eventhdlr, eventInitBoundwriting) );
691 SCIP_CALL( SCIPsetEventhdlrExit(scip, eventhdlr, eventExitBoundwriting) );
692
693 /* add boundwriting parameters */
695 "eventhdlr/"EVENTHDLR_NAME"/freq",
696 "in which frequency should all bounds be written(0: never)",
697 &eventhdlrdata->freq, FALSE, DEFAULT_FREQ, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
699 "eventhdlr/"EVENTHDLR_NAME"/filename",
700 "filename to write all bounds to",
701 &eventhdlrdata->filename, FALSE, DEFAULT_FILENAME, NULL, NULL) );
703 "eventhdlr/"EVENTHDLR_NAME"/writesubmipdualbound",
704 "should the dualbound of the submip-root which was created out of an open node be printed",
705 &eventhdlrdata->writesubmipdualbound, FALSE, DEFAULT_WRITESUBMIPDUALBOUND, NULL, NULL) );
706
707 return SCIP_OKAY;
708}
static long * number
#define NULL
Definition: def.h:262
#define SCIP_MAXSTRLEN
Definition: def.h:283
#define SCIP_Longint
Definition: def.h:157
#define SCIP_INVALID
Definition: def.h:192
#define SCIP_Bool
Definition: def.h:91
#define SCIP_Real
Definition: def.h:172
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define SCIP_LONGINT_FORMAT
Definition: def.h:164
#define SCIP_LONGINT_MAX
Definition: def.h:158
#define SCIP_CALL(x)
Definition: def.h:369
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:2877
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:734
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip_general.c:349
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip_general.c:317
SCIP_STATUS SCIPgetStatus(SCIP *scip)
Definition: scip_general.c:508
int SCIPgetNIntVars(SCIP *scip)
Definition: scip_prob.c:2082
int SCIPgetNImplVars(SCIP *scip)
Definition: scip_prob.c:2127
const char * SCIPgetProbName(SCIP *scip)
Definition: scip_prob.c:1067
int SCIPgetNContVars(SCIP *scip)
Definition: scip_prob.c:2172
SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
Definition: scip_prob.c:1422
SCIP_Real SCIPgetTransObjoffset(SCIP *scip)
Definition: scip_prob.c:1367
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip_prob.c:1866
int SCIPgetNOrigConss(SCIP *scip)
Definition: scip_prob.c:3135
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1992
int SCIPgetNConss(SCIP *scip)
Definition: scip_prob.c:3043
int SCIPgetNOrigVars(SCIP *scip)
Definition: scip_prob.c:2432
SCIP_OBJSENSE SCIPgetObjsense(SCIP *scip)
Definition: scip_prob.c:1225
int SCIPgetNBinVars(SCIP *scip)
Definition: scip_prob.c:2037
SCIP_Real SCIPgetTransObjscale(SCIP *scip)
Definition: scip_prob.c:1390
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3110
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3263
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3076
SCIP_Real SCIPgetNodeDualbound(SCIP *scip, SCIP_NODE *node)
Definition: scip_prob.c:3606
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:324
SCIP_EVENTHDLRDATA * SCIPeventhdlrGetData(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:334
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:1030
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:327
#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:7900
SCIP_NODETYPE SCIPnodeGetType(SCIP_NODE *node)
Definition: tree.c:7521
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:7531
int SCIPnodeGetDepth(SCIP_NODE *node)
Definition: tree.c:7541
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip_solve.c:2491
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:5066
SCIP_RETCODE SCIPchgVarUbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:5155
void SCIPprintSysError(const char *message)
Definition: misc.c:10770
int SCIPstrncpy(char *t, const char *s, int size)
Definition: misc.c:10948
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:57
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIP_EVENTTYPE_NODEFEASIBLE
Definition: type_event.h:93
#define SCIP_EVENTTYPE_NODEINFEASIBLE
Definition: type_event.h:94
struct SCIP_EventhdlrData SCIP_EVENTHDLRDATA
Definition: type_event.h:155
#define SCIP_EVENTTYPE_NODEBRANCHED
Definition: type_event.h:95
#define SCIP_EVENTTYPE_NODESOLVED
Definition: type_event.h:136
@ SCIP_BOUNDTYPE_UPPER
Definition: type_lp.h:57
@ SCIP_BOUNDTYPE_LOWER
Definition: type_lp.h:56
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:59
@ 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:62
@ SCIP_NODETYPE_PROBINGNODE
Definition: type_tree.h:42