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