Scippy

SCIP

Solving Constraint Integer Programs

vbc.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-2014 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 email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file vbc.c
17  * @brief methods for VBC Tool output
18  * @author Tobias Achterberg
19  */
20 
21 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
22 
23 #include <stdio.h>
24 #include <assert.h>
25 
26 #include "blockmemshell/memory.h"
27 #include "scip/set.h"
28 #include "scip/stat.h"
29 #include "scip/clock.h"
30 #include "scip/var.h"
31 #include "scip/tree.h"
32 #include "scip/vbc.h"
33 #include "scip/struct_vbc.h"
34 
35 
36 /** returns the branching variable of the node, or NULL */
37 static
39  SCIP_NODE* node, /**< node */
40  SCIP_VAR** var, /**< pointer to store the branching variable */
41  SCIP_BOUNDTYPE* boundtype, /**< pointer to store the branching type: lower or upper bound */
42  SCIP_Real* bound /**< pointer to store the new bound of the branching variable */
43  )
44 {
45  SCIP_DOMCHGBOUND* domchgbound;
46 
47  (*var) = NULL;
48  (*bound) = 0.0;
49  (*boundtype) = SCIP_BOUNDTYPE_LOWER;
50 
51  assert(node != NULL);
52  if( node->domchg == NULL )
53  return;
54 
55  domchgbound = &node->domchg->domchgbound;
56  if( domchgbound->nboundchgs == 0 )
57  return;
58 
59  (*var) = domchgbound->boundchgs[0].var;
60  (*bound) = domchgbound->boundchgs[0].newbound;
61  (*boundtype) = (SCIP_BOUNDTYPE) domchgbound->boundchgs[0].boundtype;
62 }
63 
64 /** creates VBC Tool data structure */
66  SCIP_VBC** vbc, /**< pointer to store the VBC information */
67  SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
68  )
69 {
70  SCIP_ALLOC( BMSallocMemory(vbc) );
71 
72  (*vbc)->file = NULL;
73  (*vbc)->messagehdlr = messagehdlr;
74  (*vbc)->nodenum = NULL;
75  (*vbc)->timestep = 0;
76  (*vbc)->lastnode = NULL;
77  (*vbc)->lastcolor = SCIP_VBCCOLOR_NONE;
78  (*vbc)->userealtime = FALSE;
79 
80  return SCIP_OKAY;
81 }
82 
83 /** frees VBC Tool data structure */
85  SCIP_VBC** vbc /**< pointer to store the VBC information */
86  )
87 {
88  assert(vbc != NULL);
89  assert(*vbc != NULL);
90  assert((*vbc)->file == NULL);
91  assert((*vbc)->nodenum == NULL);
92 
93  BMSfreeMemory(vbc);
94 }
95 
96 /** initializes VBC information and creates a file for VBC output */
98  SCIP_VBC* vbc, /**< VBC information */
99  BMS_BLKMEM* blkmem, /**< block memory */
100  SCIP_SET* set, /**< global SCIP settings */
101  SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
102  )
103 {
104  assert(vbc != NULL);
105  assert(set != NULL);
106  assert(set->vbc_filename != NULL);
107 
108  if( set->vbc_filename[0] == '-' && set->vbc_filename[1] == '\0' )
109  return SCIP_OKAY;
110 
111  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_NORMAL,
112  "storing VBC information in file <%s>\n", set->vbc_filename);
113  vbc->file = fopen(set->vbc_filename, "w");
114  vbc->timestep = 0;
115  vbc->lastnode = NULL;
117  vbc->userealtime = set->vbc_realtime;
118 
119  if( vbc->file == NULL )
120  {
121  SCIPerrorMessage("error creating file <%s>\n", set->vbc_filename);
122  SCIPprintSysError(set->vbc_filename);
123  return SCIP_FILECREATEERROR;
124  }
125 
126  SCIPmessageFPrintInfo(vbc->messagehdlr, vbc->file, "#TYPE: COMPLETE TREE\n");
127  SCIPmessageFPrintInfo(vbc->messagehdlr, vbc->file, "#TIME: SET\n");
128  SCIPmessageFPrintInfo(vbc->messagehdlr, vbc->file, "#BOUNDS: SET\n");
129  SCIPmessageFPrintInfo(vbc->messagehdlr, vbc->file, "#INFORMATION: STANDARD\n");
130  SCIPmessageFPrintInfo(vbc->messagehdlr, vbc->file, "#NODE_NUMBER: NONE\n");
131 
133 
134  return SCIP_OKAY;
135 }
136 
137 /** closes the VBC output file */
139  SCIP_VBC* vbc, /**< VBC information */
140  SCIP_SET* set, /**< global SCIP settings */
141  SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
142  )
143 {
144  assert(vbc != NULL);
145  assert(set != NULL);
146 
147  if( vbc->file != NULL )
148  {
149  SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL, "closing VBC information file\n");
150 
151  fclose(vbc->file);
152  vbc->file = NULL;
153 
154  SCIPhashmapFree(&vbc->nodenum);
155  }
156 }
157 
158 /** prints current solution time to VBC output file */
159 static
161  SCIP_VBC* vbc, /**< VBC information */
162  SCIP_STAT* stat /**< problem statistics */
163  )
164 {
165  SCIP_Longint step;
166  int hours;
167  int mins;
168  int secs;
169  int hunds;
170 
171  assert(vbc != NULL);
172  assert(stat != NULL);
173 
174  if( vbc->userealtime )
175  {
176  double time;
177  time = SCIPclockGetTime(stat->solvingtime);
178  step = (SCIP_Longint)(time * 100.0);
179  }
180  else
181  {
182  step = vbc->timestep;
183  vbc->timestep++;
184  }
185  hours = (int)(step / (60*60*100));
186  step %= 60*60*100;
187  mins = (int)(step / (60*100));
188  step %= 60*100;
189  secs = (int)(step / 100);
190  step %= 100;
191  hunds = (int)step;
192 
193  SCIPmessageFPrintInfo(vbc->messagehdlr, vbc->file, "%02d:%02d:%02d.%02d ", hours, mins, secs, hunds);
194 }
195 
196 /** creates a new node entry in the VBC output file */
198  SCIP_VBC* vbc, /**< VBC information */
199  SCIP_STAT* stat, /**< problem statistics */
200  SCIP_NODE* node /**< new node, that was created */
201  )
202 {
203  SCIP_VAR* branchvar;
204  SCIP_BOUNDTYPE branchtype;
205  SCIP_Real branchbound;
206  size_t parentnodenum;
207  size_t nodenum;
208 
209  assert(vbc != NULL);
210  assert(stat != NULL);
211  assert(node != NULL);
212 
213  /* check, if VBC output should be created */
214  if( vbc->file == NULL )
215  return SCIP_OKAY;
216 
217  /* vbc is disabled on probing nodes */
219  return SCIP_OKAY;
220 
221  /* insert mapping node -> nodenum into hash map */
222  if( stat->ncreatednodesrun >= (SCIP_Longint)INT_MAX )
223  {
224  SCIPerrorMessage("too many nodes to store in the VBC file\n");
225  return SCIP_INVALIDDATA;
226  }
227 
228  nodenum = (size_t)stat->ncreatednodesrun;
229  assert(nodenum > 0);
230  SCIP_CALL( SCIPhashmapInsert(vbc->nodenum, node, (void*)nodenum) );
231 
232  /* get nodenum of parent node from hash map */
233  parentnodenum = (node->parent != NULL ? (size_t)SCIPhashmapGetImage(vbc->nodenum, node->parent) : 0);
234  assert(node->parent == NULL || parentnodenum > 0);
235 
236  /* get branching information */
237  getBranchInfo(node, &branchvar, &branchtype, &branchbound);
238 
239  printTime(vbc, stat);
240  SCIPmessageFPrintInfo(vbc->messagehdlr, vbc->file, "N %d %d %d\n", (int)parentnodenum, (int)nodenum, SCIP_VBCCOLOR_UNSOLVED);
241  printTime(vbc, stat);
242  if( branchvar != NULL )
243  {
244  SCIPmessageFPrintInfo(vbc->messagehdlr, vbc->file, "I %d \\inode:\\t%d (%p)\\idepth:\\t%d\\nvar:\\t%s [%g,%g] %s %f\\nbound:\\t%f\n",
245  (int)nodenum, (int)nodenum, node, SCIPnodeGetDepth(node),
246  SCIPvarGetName(branchvar), SCIPvarGetLbLocal(branchvar), SCIPvarGetUbLocal(branchvar),
247  branchtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", branchbound, SCIPnodeGetLowerbound(node));
248  }
249  else
250  {
251  SCIPmessageFPrintInfo(vbc->messagehdlr, vbc->file, "I %d \\inode:\\t%d (%p)\\idepth:\\t%d\\nvar:\\t-\\nbound:\\t%f\n",
252  (int)nodenum, (int)nodenum, node, SCIPnodeGetDepth(node), SCIPnodeGetLowerbound(node));
253  }
254 
255  return SCIP_OKAY;
256 }
257 
258 /** updates a node entry in the VBC output file */
260  SCIP_VBC* vbc, /**< VBC information */
261  SCIP_STAT* stat, /**< problem statistics */
262  SCIP_NODE* node /**< new node, that was created */
263  )
264 {
265  SCIP_VAR* branchvar;
266  SCIP_BOUNDTYPE branchtype;
267  SCIP_Real branchbound;
268  size_t nodenum;
269 
270  assert(vbc != NULL);
271  assert(stat != NULL);
272  assert(node != NULL);
273 
274  /* check, if VBC output should be created */
275  if( vbc->file == NULL )
276  return SCIP_OKAY;
277 
278  /* vbc is disabled on probing nodes */
280  return SCIP_OKAY;
281 
282  /* get node num from hash map */
283  nodenum = (size_t)SCIPhashmapGetImage(vbc->nodenum, node);
284  assert(nodenum > 0);
285 
286  /* get branching information */
287  getBranchInfo(node, &branchvar, &branchtype, &branchbound);
288 
289  printTime(vbc, stat);
290  if( branchvar != NULL )
291  {
292  SCIPmessageFPrintInfo(vbc->messagehdlr, vbc->file, "I %d \\inode:\\t%d (%p)\\idepth:\\t%d\\nvar:\\t%s [%g,%g] %s %f\\nbound:\\t%f\n",
293  (int)nodenum, (int)nodenum, node, SCIPnodeGetDepth(node),
294  SCIPvarGetName(branchvar), SCIPvarGetLbLocal(branchvar), SCIPvarGetUbLocal(branchvar),
295  branchtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", branchbound, SCIPnodeGetLowerbound(node));
296  }
297  else
298  {
299  SCIPmessageFPrintInfo(vbc->messagehdlr, vbc->file, "I %d \\inode:\\t%d (%p)\\idepth:\\t%d\\nvar:\\t-\\nbound:\\t%f\n",
300  (int)nodenum, (int)nodenum, node, SCIPnodeGetDepth(node), SCIPnodeGetLowerbound(node));
301  }
302 
303  return SCIP_OKAY;
304 }
305 
306 /** changes the color of the node to the given color */
307 static
309  SCIP_VBC* vbc, /**< VBC information */
310  SCIP_STAT* stat, /**< problem statistics */
311  SCIP_NODE* node, /**< node to change color for */
312  SCIP_VBCCOLOR color /**< new color of node, or SCIP_VBCCOLOR_NONE */
313  )
314 {
315  assert(vbc != NULL);
316  assert(node != NULL);
317 
318  if( vbc->file != NULL && color != SCIP_VBCCOLOR_NONE && (node != vbc->lastnode || color != vbc->lastcolor) )
319  {
320  size_t nodenum;
321 
322  nodenum = (size_t)SCIPhashmapGetImage(vbc->nodenum, node);
323  assert(nodenum > 0);
324  printTime(vbc, stat);
325  SCIPmessageFPrintInfo(vbc->messagehdlr, vbc->file, "P %d %d\n", (int)nodenum, color);
326  vbc->lastnode = node;
327  vbc->lastcolor = color;
328  }
329 }
330 
331 /** changes the color of the node to the color of solved nodes */
333  SCIP_VBC* vbc, /**< VBC information */
334  SCIP_STAT* stat, /**< problem statistics */
335  SCIP_NODE* node /**< node, that was solved */
336  )
337 {
338  SCIP_VAR* branchvar;
339  SCIP_BOUNDTYPE branchtype;
340  SCIP_Real branchbound;
341  size_t nodenum;
342 
343  assert(vbc != NULL);
344  assert(stat != NULL);
345  assert(node != NULL);
346 
347  /* check, if VBC output should be created */
348  if( vbc->file == NULL )
349  return;
350 
351  /* vbc is disabled on probing nodes */
353  return;
354 
355  /* get node num from hash map */
356  nodenum = (size_t)SCIPhashmapGetImage(vbc->nodenum, node);
357  assert(nodenum > 0);
358 
359  /* get branching information */
360  getBranchInfo(node, &branchvar, &branchtype, &branchbound);
361 
362  printTime(vbc, stat);
363 
364  if( branchvar != NULL )
365  {
366  SCIPmessageFPrintInfo(vbc->messagehdlr, vbc->file, "I %d \\inode:\\t%d (%p)\\idepth:\\t%d\\nvar:\\t%s [%g,%g] %s %f\\nbound:\\t%f\\nnr:\\t%"SCIP_LONGINT_FORMAT"\n",
367  (int)nodenum, (int)nodenum, node, SCIPnodeGetDepth(node),
368  SCIPvarGetName(branchvar), SCIPvarGetLbLocal(branchvar), SCIPvarGetUbLocal(branchvar),
369  branchtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", branchbound, SCIPnodeGetLowerbound(node), stat->nnodes);
370  }
371  else
372  {
373  SCIPmessageFPrintInfo(vbc->messagehdlr, vbc->file, "I %d \\inode:\\t%d (%p)\\idepth:\\t%d\\nvar:\\t-\\nbound:\\t%f\\nnr:\\t%"SCIP_LONGINT_FORMAT"\n",
374  (int)nodenum, (int)nodenum, node, SCIPnodeGetDepth(node), SCIPnodeGetLowerbound(node), stat->nnodes);
375  }
376 
377  vbcSetColor(vbc, stat, node, SCIP_VBCCOLOR_SOLVED);
378 }
379 
380 /** changes the color of the node to the color of cutoff nodes */
382  SCIP_VBC* vbc, /**< VBC information */
383  SCIP_STAT* stat, /**< problem statistics */
384  SCIP_NODE* node /**< node, that was cut off */
385  )
386 {
387  SCIP_VAR* branchvar;
388  SCIP_BOUNDTYPE branchtype;
389  SCIP_Real branchbound;
390  size_t nodenum;
391 
392  assert(vbc != NULL);
393  assert(stat != NULL);
394  assert(node != NULL);
395 
396  /* check, if VBC output should be created */
397  if( vbc->file == NULL )
398  return;
399 
400  /* vbc is disabled on probing nodes */
402  return;
403 
404  /* get node num from hash map */
405  nodenum = (size_t)SCIPhashmapGetImage(vbc->nodenum, node);
406  assert(nodenum > 0);
407 
408  /* get branching information */
409  getBranchInfo(node, &branchvar, &branchtype, &branchbound);
410 
411  printTime(vbc, stat);
412 
413  if( branchvar != NULL )
414  {
415  SCIPmessageFPrintInfo(vbc->messagehdlr, vbc->file, "I %d \\inode:\\t%d (%p)\\idepth:\\t%d\\nvar:\\t%s [%g,%g] %s %f\\nbound:\\t%f\\nnr:\\t%"SCIP_LONGINT_FORMAT"\n",
416  (int)nodenum, (int)nodenum, node, SCIPnodeGetDepth(node),
417  SCIPvarGetName(branchvar), SCIPvarGetLbLocal(branchvar), SCIPvarGetUbLocal(branchvar),
418  branchtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", branchbound, SCIPnodeGetLowerbound(node), stat->nnodes);
419  }
420  else
421  {
422  SCIPmessageFPrintInfo(vbc->messagehdlr, vbc->file, "I %d \\inode:\\t%d (%p)\\idepth:\\t%d\\nvar:\\t-\\nbound:\\t%f\\nnr:\\t%"SCIP_LONGINT_FORMAT"\n",
423  (int)nodenum, (int)nodenum, node, SCIPnodeGetDepth(node), SCIPnodeGetLowerbound(node), stat->nnodes);
424  }
425 
426  vbcSetColor(vbc, stat, node, SCIP_VBCCOLOR_CUTOFF);
427 }
428 
429 /** changes the color of the node to the color of nodes where a conflict constraint was found */
431  SCIP_VBC* vbc, /**< VBC information */
432  SCIP_STAT* stat, /**< problem statistics */
433  SCIP_NODE* node /**< node, where the conflict was found */
434  )
435 {
436  assert(node != NULL);
437 
438  /* vbc is disabled on probing nodes */
440  return;
441 
442  vbcSetColor(vbc, stat, node, SCIP_VBCCOLOR_CONFLICT);
443 }
444 
445 /** changes the color of the node to the color of nodes that were marked to be repropagated */
447  SCIP_VBC* vbc, /**< VBC information */
448  SCIP_STAT* stat, /**< problem statistics */
449  SCIP_NODE* node /**< node, that was marked to be repropagated */
450  )
451 {
452  assert(node != NULL);
453 
454  /* vbc is disabled on probing nodes */
456  return;
457 
458  /* if the node number is zero, then SCIP is currently in probing and wants to mark a probing node; however this node
459  * is not part of the search tree */
460  if( SCIPnodeGetNumber(node) > 0 )
461  vbcSetColor(vbc, stat, node, SCIP_VBCCOLOR_MARKREPROP);
462 }
463 
464 /** changes the color of the node to the color of repropagated nodes */
466  SCIP_VBC* vbc, /**< VBC information */
467  SCIP_STAT* stat, /**< problem statistics */
468  SCIP_NODE* node /**< node, that was repropagated */
469  )
470 {
471  assert(node != NULL);
472 
473  /* vbc is disabled on probing nodes */
475  return;
476 
477  vbcSetColor(vbc, stat, node, SCIP_VBCCOLOR_REPROP);
478 }
479 
480 /** changes the color of the node to the color of nodes with a primal solution */
482  SCIP_VBC* vbc, /**< VBC information */
483  SCIP_SET* set, /**< global SCIP settings */
484  SCIP_STAT* stat, /**< problem statistics */
485  SCIP_NODE* node /**< node where the solution was found, or NULL */
486  )
487 {
488  if( node != NULL && set->vbc_dispsols )
489  {
490  /* vbc is disabled on probing nodes */
492  return;
493 
494  vbcSetColor(vbc, stat, node, SCIP_VBCCOLOR_SOLUTION);
495  }
496 }
497 
498 /** outputs a new global lower bound to the VBC output file */
500  SCIP_VBC* vbc, /**< VBC information */
501  SCIP_STAT* stat, /**< problem statistics */
502  SCIP_Real lowerbound /**< new lower bound */
503  )
504 {
505  assert(vbc != NULL);
506 
507  /* check, if VBC output should be created */
508  if( vbc->file == NULL )
509  return;
510 
511  printTime(vbc, stat);
512  SCIPmessageFPrintInfo(vbc->messagehdlr, vbc->file, "L %f\n", lowerbound);
513 }
514 
515 /** outputs a new global upper bound to the VBC output file */
517  SCIP_VBC* vbc, /**< VBC information */
518  SCIP_STAT* stat, /**< problem statistics */
519  SCIP_Real upperbound /**< new upper bound */
520  )
521 {
522  assert(vbc != NULL);
523 
524  /* check, if VBC output should be created */
525  if( vbc->file == NULL )
526  return;
527 
528  printTime(vbc, stat);
529  SCIPmessageFPrintInfo(vbc->messagehdlr, vbc->file, "U %f\n", upperbound);
530 }
531 
532