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-2024 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  * @ingroup EVENTHDLR
27  * @brief event handler for writing primal and dual bound for all open nodes
28  * @author Michael Winkler
29  *
30  *
31  * This event handler writes to a specified file at a given frequency the dual bounds of all open nodes and the current
32  * primal bound.
33  *
34  * setting "set misc boundwriting freq 1000" will lead to write every 1000 nodes the primal bound and the dual bound
35  * front of all open nodes
36  *
37  * setting "set misc boundwriting filename bounds.txt" will write the bounds to the files
38  * ascending from bounds1.txt over bounds2.txt to boundsN.txt were N is the last number for writing bounds (no
39  * filename means to write to standard out)
40  *
41  * setting "set misc writesubmipdualbound TRUE" will lead to resolve each open node in a subSCIP until the root in the
42  * subSCIP is solved and as a result will print this resulting dual bound
43  *
44  * An output could look as follows (here writesubmipdualbound is set to TRUE):
45  *
46  * PB 201
47  *
48  * 5913 34 192.1 193.5
49  *
50  * 2884 26 162.1 162.1
51  *
52  * The first line above shows the Primalbound. All following lines will show first the node number, second the depth of
53  * 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
54  * resolved node.
55  *
56  * @note you can write all bounds to a single file by adding the line
57  * \code
58  * #define ONEFILE
59  * \endcode
60  * and recompiling this example.
61  *
62  * @note If you want to get a better human readable format for printing, define
63  * \code
64  * #define LONGSTATS
65  * \endcode
66  * and recompile this example.
67  */
68 
69 /*--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
70 
71 
72 #include <string.h>
73 
74 #include "event_boundwriting.h"
75 
76 
77 #define EVENTHDLR_NAME "boundwriting"
78 #define EVENTHDLR_DESC "event handler for writing current primalbound and global dualbound and for all open nodes the dualbound"
79 
80 #define DEFAULT_FREQ 0LL /**< frequency for writing primal and dual bounds */
81 #define DEFAULT_FILENAME "" /**< filename to write to */
82 #define DEFAULT_WRITESUBMIPDUALBOUND FALSE /**< write dualbound after solving supmip root for all open node */
83 
84 /* should the printing be with more information */
85 /*#define LONGSTATS*/
86 
87 /* do we want to create for each printing new files or only one */
88 /*#define ONEFILE*/
89 
90 /* do we want to print the information only on the focusnode or for all open nodes */
91 /*#define FOCUSNODE*/
92 
93 /*
94  * Data structures
95  */
96 
97 /** LP reading data */
98 struct SCIP_EventhdlrData
99 {
100  char oldfilename[SCIP_MAXSTRLEN];
101  FILE* file;
102  char* filename;
103  SCIP_Real lastpb;
104  SCIP_Longint freq;
105  SCIP_Bool isopen;
106  SCIP_Bool writesubmipdualbound;
107  int filenumber;
108 };
109 
110 
111 /*
112  * Local methods
113  */
114 
115 /** initializes the reader data */
116 static
118  SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
119  )
120 {
121  assert(eventhdlrdata != NULL);
122 
123  eventhdlrdata->filename = NULL;
124  eventhdlrdata->file = NULL;
125  eventhdlrdata->isopen = FALSE;
126  eventhdlrdata->oldfilename[0] = '\0';
127  eventhdlrdata->filenumber = 1;
128 }
129 
130 #ifndef FOCUSNODE
131 /* apply all changes to the submip */
132 static
134  SCIP* subscip, /**< scip to apply domain changes */
135  SCIP_VAR** vars, /**< variables in original scip instance */
136  SCIP_Real* bounds, /**< bounds which should be applied */
137  SCIP_BOUNDTYPE* boundtypes, /**< bound types for bounds which should be applied */
138  int nvars, /**< number of variables */
139  SCIP_HASHMAP* varmap /**< hashmap for identifiing the corresponding variables in subscip */
140  )
141 {
142  SCIP_VAR* subscipvar;
143  int v;
144 
145  assert(subscip != NULL);
146  assert(vars != NULL);
147  assert(bounds != NULL);
148  assert(boundtypes != NULL);
149  assert(nvars > 0);
150  assert(varmap != NULL);
151 
152  /* 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 */
153  for( v = nvars - 1; v >= 0; --v )
154  {
155  subscipvar = (SCIP_VAR*) SCIPhashmapGetImage(varmap, vars[v]);
156  assert(subscipvar != NULL);
157 
158  if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER )
159  {
160  SCIP_CALL( SCIPchgVarLbGlobal(subscip, subscipvar, bounds[v]) );
161  }
162  else
163  {
164  assert(boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
165  SCIP_CALL( SCIPchgVarUbGlobal(subscip, subscipvar, bounds[v]) );
166  }
167  }
168 
169  return SCIP_OKAY;
170 }
171 #endif
172 
173 #ifdef FOCUSNODE
174 /** call writing method */
175 static
176 SCIP_RETCODE writeBoundsFocusNode(
177  SCIP* scip, /**< SCIP data structure */
178  SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
179  )
180 {
181  FILE* file;
182  SCIP_Bool writesubmipdualbound;
183  SCIP_NODE* node;
184 
185  assert(scip != NULL);
186  assert(eventhdlrdata != NULL);
187 
188  file = eventhdlrdata->file;
189  writesubmipdualbound = eventhdlrdata->writesubmipdualbound;
190  node = SCIPgetCurrentNode(scip);
191 
192  /* do not process probing nodes */
194  return SCIP_OKAY;
195 
196  /* do not process cutoff nodes */
197  if( SCIPisInfinity(scip, SCIPgetNodeDualbound(scip, node)) )
198  return SCIP_OKAY;
199 
200  if( !SCIPisEQ(scip, eventhdlrdata->lastpb, SCIPgetPrimalbound(scip)) )
201  {
202 #ifdef LONGSTATS
203  SCIPinfoMessage(scip, file, "Status after %"SCIP_LONGINT_FORMAT" processed nodes (%d open)\n", SCIPgetNNodes(scip), SCIPgetNNodesLeft(scip));
204 
205  SCIPinfoMessage(scip, file, "Primalbound: %g\n", SCIPgetPrimalbound(scip));
206  SCIPinfoMessage(scip, file, "Dualbound: %g\n", SCIPgetDualbound(scip));
207 #else
208  SCIPinfoMessage(scip, file, "PB %g\n", SCIPgetPrimalbound(scip));
209 #endif
210  eventhdlrdata->lastpb = SCIPgetPrimalbound(scip);
211  }
212 
213  if( writesubmipdualbound )
214  {
215  SCIP* subscip;
216  SCIP_Bool valid;
217  SCIP_Real submipdb;
218  SCIP_Bool cutoff;
219 
220  SCIP_CALL( SCIPcreate(&subscip) );
221 
222  submipdb = SCIP_INVALID;
223  valid = FALSE;
224  cutoff = FALSE;
225  SCIP_CALL( SCIPcopy(scip, subscip, NULL, NULL, "__boundwriting", FALSE, FALSE, FALSE, TRUE, &valid) );
226 
227  if( valid )
228  {
229  /* do not abort subproblem on CTRL-C */
230  SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
231  /* disable output to console */
232  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
233  /* solve only root node */
234  SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", 1LL) );
235 
236 #ifdef SCIP_DISABLED_CODE
237  /* We could evaluate the pure impact of (node) presolve and cuts on the dual bound
238  * for the current node by disabling all heuristics and therefore disregarding any sideeffects
239  * that are introduced due to new solutions and their subsequent reductions. */
241 #endif
242 
243  /* set cutoffbound as objective limit for subscip */
244  SCIP_CALL( SCIPsetObjlimit(subscip, SCIPgetCutoffbound(scip)) );
245 
246  SCIP_CALL( SCIPsolve(subscip) );
247 
248  cutoff = (SCIPgetStatus(subscip) == SCIP_STATUS_INFEASIBLE);
249  submipdb = SCIPgetDualbound(subscip) * SCIPgetTransObjscale(scip) + SCIPgetTransObjoffset(scip);
250  }
251 
252 #ifdef LONGSTATS
253  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)" : "");
254 #else
255  SCIPinfoMessage(scip, file, "%"SCIP_LONGINT_FORMAT" %d %g %g %s\n", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), SCIPgetNodeDualbound(scip, node), submipdb, cutoff ? "(cutoff)" : "");
256 #endif
257 
258  SCIP_CALL( SCIPfree(&subscip) );
259  }
260  else
261  {
262 #ifdef LONGSTATS
263  SCIPinfoMessage(scip, file, "Node %"SCIP_LONGINT_FORMAT" (depth %d): dualbound: %g\n", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), SCIPgetNodeDualbound(scip, node));
264 #else
265  SCIPinfoMessage(scip, file, "%"SCIP_LONGINT_FORMAT" %d %g\n", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), SCIPgetNodeDualbound(scip, node));
266 #endif
267  }
268 
269 #ifdef LONGSTATS
270  SCIPinfoMessage(scip, file, "\n");
271 #endif
272 
273  return SCIP_OKAY;
274 }
275 
276 #else
277 
278 /** call writing method */
279 static
281  SCIP* scip, /**< SCIP data structure */
282  FILE* file, /**< file to write to or NULL */
283  SCIP_Bool writesubmipdualbound/**< write dualbounds of submip roots for all open nodes */
284  )
285 {
286  SCIP_NODE** opennodes;
287  int nopennodes;
288  int n;
289  int v;
290 
291  assert(scip != NULL);
292 
293  nopennodes = -1;
294 
295 #ifdef LONGSTATS
296  SCIPinfoMessage(scip, file, "Status after %"SCIP_LONGINT_FORMAT" processed nodes (%d open)\n", SCIPgetNNodes(scip), SCIPgetNNodesLeft(scip));
297 
298  SCIPinfoMessage(scip, file, "Primalbound: %g\n", SCIPgetPrimalbound(scip));
299  SCIPinfoMessage(scip, file, "Dualbound: %g\n", SCIPgetDualbound(scip));
300 #else
301  SCIPinfoMessage(scip, file, "PB %g\n", SCIPgetPrimalbound(scip));
302 #endif
303 
304  /* get all open nodes and therefor print all dualbounds */
305  for( v = 2; v >= 0; --v )
306  {
307  SCIP_NODE* node;
308 
309  switch( v )
310  {
311  case 2:
312  SCIP_CALL( SCIPgetChildren(scip, &opennodes, &nopennodes) );
313  break;
314  case 1:
315  SCIP_CALL( SCIPgetSiblings(scip, &opennodes, &nopennodes) );
316  break;
317  case 0:
318  SCIP_CALL( SCIPgetLeaves(scip, &opennodes, &nopennodes) );
319  break;
320  default:
321  assert(0);
322  break;
323  }
324  assert(nopennodes >= 0);
325 
326  /* print all node information */
327  for( n = nopennodes - 1; n >= 0 && !SCIPisStopped(scip); --n )
328  {
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 */
399  SCIP_CALL( SCIPsetObjlimit(subscip, SCIPgetCutoffbound(scip)) );
400 
401  SCIP_CALL( SCIPsolve(subscip) );
402 
403  cutoff = (SCIPgetStatus(subscip) == SCIP_STATUS_INFEASIBLE);
404  submipdb = SCIPgetDualbound(subscip) * SCIPgetTransObjscale(scip) + SCIPgetTransObjoffset(scip);
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
423  SCIPinfoMessage(scip, file, "%"SCIP_LONGINT_FORMAT" %d %g\n", SCIPnodeGetNumber(node), SCIPnodeGetDepth(node), SCIPgetNodeDualbound(scip, node));
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) */
442 static
443 SCIP_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) */
458 static
459 SCIP_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) */
477 static
478 SCIP_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) */
497 static
498 SCIP_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 */
507  SCIP_CALL( SCIPdropEvent(scip, SCIP_EVENTTYPE_NODESOLVED, eventhdlr, NULL, -1) );
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 */
525 static
526 SCIP_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);
534  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));
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);
555  return SCIP_FILECREATEERROR;
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];
575  char number[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)SCIPstrncpy(name, eventhdlrdata->filename, SCIP_MAXSTRLEN - n);
597  strncat(name, number, (unsigned int)n);
598  }
599  else
600  {
601  int len;
602 
603  if( (pch-(eventhdlrdata->filename)) >= (SCIP_MAXSTRLEN - n) ) /*lint !e776*/
604  len = SCIP_MAXSTRLEN - n - 1;
605  else
606  len = (int) (pch-(eventhdlrdata->filename));
607 
608  (void)SCIPstrncpy(name, eventhdlrdata->filename, len);
609  strncat(name, number, (unsigned int)n);
610  assert(len+n < SCIP_MAXSTRLEN);
611  name[len+n] = '\0';
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);
623  return SCIP_FILECREATEERROR;
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 SCIP_DECL_EVENTEXEC(eventExecBoundwriting)
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:59
int SCIPgetNIntVars(SCIP *scip)
Definition: scip_prob.c:2082
static SCIP_RETCODE writeBounds(SCIP *scip, FILE *file, SCIP_Bool writesubmipdualbound)
SCIP_RETCODE SCIPchgVarLbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:4942
#define NULL
Definition: def.h:267
SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
Definition: scip_tree.c:91
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
SCIP_Real SCIPgetPrimalbound(SCIP *scip)
#define SCIP_MAXSTRLEN
Definition: def.h:288
static SCIP_DECL_EVENTEXIT(eventExitBoundwriting)
SCIP_RETCODE SCIPgetLeaves(SCIP *scip, SCIP_NODE ***leaves, int *nleaves)
Definition: scip_tree.c:248
SCIP_RETCODE SCIPsetEventhdlrExit(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTEXIT((*eventexit)))
Definition: scip_event.c:178
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:2875
int SCIPgetNOrigVars(SCIP *scip)
Definition: scip_prob.c:2432
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:104
struct SCIP_EventhdlrData SCIP_EVENTHDLRDATA
Definition: type_event.h:155
static SCIP_DECL_EVENTFREE(eventFreeBoundwriting)
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip_prob.c:1866
SCIP_RETCODE SCIPsetHeuristics(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip_param.c:927
#define FALSE
Definition: def.h:94
#define EVENTHDLR_DESC
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3074
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:324
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_Real SCIPinfinity(SCIP *scip)
#define TRUE
Definition: def.h:93
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
int SCIPgetNNodesLeft(SCIP *scip)
Definition: scip_tree.c:644
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
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
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3261
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
int SCIPnodeGetDepth(SCIP_NODE *node)
Definition: tree.c:7500
#define SCIP_LONGINT_MAX
Definition: def.h:159
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
static SCIP_DECL_EVENTCOPY(eventCopyBoundwriting)
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip_general.c:307
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
static void initEventhdlrdata(SCIP_EVENTHDLRDATA *eventhdlrdata)
SCIP_RETCODE SCIPchgVarUbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:5031
#define SCIPdebugMsg
Definition: scip_message.h:78
int SCIPstrncpy(char *t, const char *s, int size)
Definition: misc.c:10919
static SCIP_DECL_EVENTINIT(eventInitBoundwriting)
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:208
int SCIPgetNContVars(SCIP *scip)
Definition: scip_prob.c:2172
SCIP_RETCODE SCIPgetSiblings(SCIP *scip, SCIP_NODE ***siblings, int *nsiblings)
Definition: scip_tree.c:206
void SCIPnodeGetAncestorBranchings(SCIP_NODE *node, SCIP_VAR **branchvars, SCIP_Real *branchbounds, SCIP_BOUNDTYPE *boundtypes, int *nbranchvars, int branchvarssize)
Definition: tree.c:7844
const char * SCIPgetProbName(SCIP *scip)
Definition: scip_prob.c:1067
#define SCIP_EVENTTYPE_NODEFEASIBLE
Definition: type_event.h:93
#define SCIP_EVENTTYPE_NODEBRANCHED
Definition: type_event.h:95
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:7490
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip_solve.c:2498
#define SCIPerrorMessage
Definition: pub_message.h:64
SCIP_RETCODE SCIPsetEventhdlrFree(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTFREE((*eventfree)))
Definition: scip_event.c:150
SCIP_RETCODE SCIPsetEventhdlrCopy(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTCOPY((*eventcopy)))
Definition: scip_event.c:136
SCIP_RETCODE SCIPincludeEventHdlrBoundwriting(SCIP *scip)
SCIP_RETCODE SCIPgetChildren(SCIP *scip, SCIP_NODE ***children, int *nchildren)
Definition: scip_tree.c:164
SCIP_Real SCIPgetDualbound(SCIP *scip)
SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
Definition: scip_param.c:429
SCIP_STATUS SCIPgetStatus(SCIP *scip)
Definition: scip_general.c:498
SCIP_RETCODE SCIPsetEventhdlrInit(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTINIT((*eventinit)))
Definition: scip_event.c:164
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:57
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3108
SCIP_Real SCIPgetNodeDualbound(SCIP *scip, SCIP_NODE *node)
Definition: scip_prob.c:3605
#define SCIP_CALL(x)
Definition: def.h:380
int SCIPgetNOrigConss(SCIP *scip)
Definition: scip_prob.c:3134
event handler for writing primal- and dual bound for all open nodes
#define DEFAULT_FREQ
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIP_Bool
Definition: def.h:91
SCIP_RETCODE SCIPcatchEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip_event.c:286
int SCIPgetNImplVars(SCIP *scip)
Definition: scip_prob.c:2127
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:1030
void SCIPprintSysError(const char *message)
Definition: misc.c:10769
SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
Definition: scip_prob.c:1422
SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition: scip_param.c:487
#define SCIP_EVENTTYPE_NODEINFEASIBLE
Definition: type_event.h:94
SCIP_RETCODE SCIPdropEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip_event.c:320
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
static long * number
SCIP_Real SCIPgetTransObjscale(SCIP *scip)
Definition: scip_prob.c:1390
int SCIPgetNBinVars(SCIP *scip)
Definition: scip_prob.c:2037
#define SCIP_EVENTTYPE_NODESOLVED
Definition: type_event.h:136
#define EVENTHDLR_NAME
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1992
#define SCIP_LONGINT_FORMAT
Definition: def.h:165
SCIP_Real SCIPgetTransObjoffset(SCIP *scip)
Definition: scip_prob.c:1367
int SCIPgetNConss(SCIP *scip)
Definition: scip_prob.c:3042
SCIP_NODETYPE SCIPnodeGetType(SCIP_NODE *node)
Definition: tree.c:7480
#define SCIP_Real
Definition: def.h:173
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:724
#define SCIP_INVALID
Definition: def.h:193
static SCIP_RETCODE applyDomainChanges(SCIP *subscip, SCIP_VAR **vars, SCIP_Real *bounds, SCIP_BOUNDTYPE *boundtypes, int nvars, SCIP_HASHMAP *varmap)
#define SCIP_Longint
Definition: def.h:158
SCIP_OBJSENSE SCIPgetObjsense(SCIP *scip)
Definition: scip_prob.c:1225
#define DEFAULT_WRITESUBMIPDUALBOUND
SCIP_EVENTHDLRDATA * SCIPeventhdlrGetData(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:334
SCIP_Longint SCIPgetNNodes(SCIP *scip)
#define DEFAULT_FILENAME
SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
Definition: scip_param.c:545
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 SCIPfree(SCIP **scip)
Definition: scip_general.c:339