Scippy

SCIP

Solving Constraint Integer Programs

disp.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 disp.c
17  * @brief methods and datastructures for displaying runtime statistics
18  * @author Tobias Achterberg
19  * @author Timo Berthold
20  */
21 
22 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
23 
24 #include <stdio.h>
25 #include <assert.h>
26 #include <string.h>
27 
28 #include "scip/def.h"
29 #include "blockmemshell/memory.h"
30 #include "scip/set.h"
31 #include "scip/stat.h"
32 #include "scip/scip.h"
33 #include "scip/disp.h"
34 #include "scip/pub_message.h"
35 #include "scip/pub_misc.h"
36 
37 #include "scip/struct_disp.h"
38 
39 
40 
41 /*
42  * display column methods
43  */
44 
45 /** parameter change information method to autoselect display columns again */
46 SCIP_DECL_PARAMCHGD(SCIPparamChgdDispActive)
47 { /*lint --e{715}*/
48  /* automatically select the now active display columns */
50 
51  return SCIP_OKAY;
52 }
53 
54 /** copies the given display to a new scip */
56  SCIP_DISP* disp, /**< display column */
57  SCIP_SET* set /**< SCIP_SET of SCIP to copy to */
58  )
59 {
60  assert(disp != NULL);
61  assert(set != NULL);
62  assert(set->scip != NULL);
63 
64  if( disp->dispcopy != NULL )
65  {
66  SCIPdebugMessage("including display column %s in subscip %p\n", SCIPdispGetName(disp), (void*)set->scip);
67  SCIP_CALL( disp->dispcopy(set->scip, disp) );
68  }
69  return SCIP_OKAY;
70 }
71 
72 /** creates a display column */
74  SCIP_DISP** disp, /**< pointer to store display column */
75  SCIP_SET* set, /**< global SCIP settings */
76  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
77  BMS_BLKMEM* blkmem, /**< block memory for parameter settings */
78  const char* name, /**< name of display column */
79  const char* desc, /**< description of display column */
80  const char* header, /**< head line of display column */
81  SCIP_DISPSTATUS dispstatus, /**< display activation status of display column */
82  SCIP_DECL_DISPCOPY ((*dispcopy)), /**< copy method of display column or NULL if you don't want to copy your plugin into sub-SCIPs */
83  SCIP_DECL_DISPFREE ((*dispfree)), /**< destructor of display column */
84  SCIP_DECL_DISPINIT ((*dispinit)), /**< initialize display column */
85  SCIP_DECL_DISPEXIT ((*dispexit)), /**< deinitialize display column */
86  SCIP_DECL_DISPINITSOL ((*dispinitsol)), /**< solving process initialization method of display column */
87  SCIP_DECL_DISPEXITSOL ((*dispexitsol)), /**< solving process deinitialization method of display column */
88  SCIP_DECL_DISPOUTPUT ((*dispoutput)), /**< output method */
89  SCIP_DISPDATA* dispdata, /**< display column data */
90  int width, /**< width of display column (no. of chars used) */
91  int priority, /**< priority of display column */
92  int position, /**< relative position of display column */
93  SCIP_Bool stripline /**< should the column be separated with a line from its right neighbor? */
94  )
95 {
97  char paramdesc[SCIP_MAXSTRLEN];
98 
99  assert(disp != NULL);
100  assert(name != NULL);
101  assert(desc != NULL);
102  assert(header != NULL);
103  assert(dispoutput != NULL);
104  assert(width >= 0);
105 
106  SCIP_ALLOC( BMSallocMemory(disp) );
107  SCIP_ALLOC( BMSduplicateMemoryArray(&(*disp)->name, name, strlen(name)+1) );
108  SCIP_ALLOC( BMSduplicateMemoryArray(&(*disp)->desc, desc, strlen(desc)+1) );
109  SCIP_ALLOC( BMSduplicateMemoryArray(&(*disp)->header, header, strlen(header)+1) );
110  (*disp)->dispstatus = dispstatus;
111  (*disp)->dispcopy = dispcopy;
112  (*disp)->dispfree = dispfree;
113  (*disp)->dispinit = dispinit;
114  (*disp)->dispexit = dispexit;
115  (*disp)->dispinitsol = dispinitsol;
116  (*disp)->dispexitsol = dispexitsol;
117  (*disp)->dispoutput = dispoutput;
118  (*disp)->dispdata = dispdata;
119  (*disp)->width = width;
120  (*disp)->priority = priority;
121  (*disp)->position = position;
122  (*disp)->stripline = stripline;
123  (*disp)->initialized = FALSE;
124  (*disp)->active = (dispstatus == SCIP_DISPSTATUS_ON);
125 
126  /* add parameters */
127  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "display/%s/active", name);
128  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "display activation status of display column <%s> (0: off, 1: auto, 2:on)", name);
129  SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc,
130  (int*)(&(*disp)->dispstatus), FALSE, (int)dispstatus, 0, 2, SCIPparamChgdDispActive, NULL) );
131 
132  return SCIP_OKAY;
133 }
134 
135 /** frees memory of display column */
137  SCIP_DISP** disp, /**< pointer to display column data structure */
138  SCIP_SET* set /**< global SCIP settings */
139  )
140 {
141  assert(disp != NULL);
142  assert(*disp != NULL);
143  assert(!(*disp)->initialized);
144  assert(set != NULL);
145 
146  /* call destructor of display column */
147  if( (*disp)->dispfree != NULL )
148  {
149  SCIP_CALL( (*disp)->dispfree(set->scip, *disp) );
150  }
151 
152  BMSfreeMemoryArray(&(*disp)->name);
153  BMSfreeMemoryArray(&(*disp)->desc);
154  BMSfreeMemoryArray(&(*disp)->header);
155  BMSfreeMemory(disp);
156 
157  return SCIP_OKAY;
158 }
159 
160 /** initializes display column */
162  SCIP_DISP* disp, /**< display column */
163  SCIP_SET* set /**< global SCIP settings */
164  )
165 {
166  assert(disp != NULL);
167  assert(set != NULL);
168 
169  if( disp->initialized )
170  {
171  SCIPerrorMessage("display column <%s> already initialized\n", disp->name);
172  return SCIP_INVALIDCALL;
173  }
174 
175  if( disp->dispinit != NULL )
176  {
177  SCIP_CALL( disp->dispinit(set->scip, disp) );
178  }
179  disp->initialized = TRUE;
180 
181  return SCIP_OKAY;
182 }
183 
184 /** deinitializes display column */
186  SCIP_DISP* disp, /**< display column */
187  SCIP_SET* set /**< global SCIP settings */
188  )
189 {
190  assert(disp != NULL);
191  assert(set != NULL);
192 
193  if( !disp->initialized )
194  {
195  SCIPerrorMessage("display column <%s> not initialized\n", disp->name);
196  return SCIP_INVALIDCALL;
197  }
198 
199  if( disp->dispexit != NULL )
200  {
201  SCIP_CALL( disp->dispexit(set->scip, disp) );
202  }
203  disp->initialized = FALSE;
204 
205  return SCIP_OKAY;
206 }
207 
208 /** informs display column that the branch and bound process is being started */
210  SCIP_DISP* disp, /**< display column */
211  SCIP_SET* set /**< global SCIP settings */
212  )
213 {
214  assert(disp != NULL);
215  assert(set != NULL);
216 
217  /* call solving process initialization method of display column */
218  if( disp->dispinitsol != NULL )
219  {
220  SCIP_CALL( disp->dispinitsol(set->scip, disp) );
221  }
222 
223  return SCIP_OKAY;
224 }
225 
226 /** informs display column that the branch and bound process data is being freed */
228  SCIP_DISP* disp, /**< display column */
229  SCIP_SET* set /**< global SCIP settings */
230  )
231 {
232  assert(disp != NULL);
233  assert(set != NULL);
234 
235  /* call solving process deinitialization method of display column */
236  if( disp->dispexitsol != NULL )
237  {
238  SCIP_CALL( disp->dispexitsol(set->scip, disp) );
239  }
240 
241  return SCIP_OKAY;
242 }
243 
244 /** output display column to screen */
246  SCIP_DISP* disp, /**< display column */
247  SCIP_SET* set, /**< global SCIP settings */
248  FILE* file /**< output file (or NULL for standard output) */
249  )
250 {
251  assert(disp != NULL);
252  assert(disp->dispoutput != NULL);
253  assert(set != NULL);
254 
255  SCIP_CALL( disp->dispoutput(set->scip, disp, file) );
256 
257  return SCIP_OKAY;
258 }
259 
260 /** gets user data of display column */
262  SCIP_DISP* disp /**< display column */
263  )
264 {
265  assert(disp != NULL);
266 
267  return disp->dispdata;
268 }
269 
270 /** sets user data of display column; user has to free old data in advance! */
272  SCIP_DISP* disp, /**< display column */
273  SCIP_DISPDATA* dispdata /**< new display column user data */
274  )
275 {
276  assert(disp != NULL);
277 
278  disp->dispdata = dispdata;
279 }
280 
281 /** gets name of display column */
282 const char* SCIPdispGetName(
283  SCIP_DISP* disp /**< display column */
284  )
285 {
286  assert(disp != NULL);
287 
288  return disp->name;
289 }
290 
291 /** gets description of display column */
292 const char* SCIPdispGetDesc(
293  SCIP_DISP* disp /**< display column */
294  )
295 {
296  assert(disp != NULL);
297 
298  return disp->desc;
299 }
300 
301 /** gets head line of display column */
302 const char* SCIPdispGetHeader(
303  SCIP_DISP* disp /**< display column */
304  )
305 {
306  assert(disp != NULL);
307 
308  return disp->header;
309 }
310 
311 /** gets width of display column */
313  SCIP_DISP* disp /**< display column */
314  )
315 {
316  assert(disp != NULL);
317 
318  return disp->width;
319 }
320 
321 /** gets priority of display column */
323  SCIP_DISP* disp /**< display column */
324  )
325 {
326  assert(disp != NULL);
327 
328  return disp->priority;
329 }
330 
331 /** gets position of display column */
333  SCIP_DISP* disp /**< display column */
334  )
335 {
336  assert(disp != NULL);
337 
338  return disp->position;
339 }
340 
341 /** gets status of display column */
343  SCIP_DISP* disp /**< display column */
344  )
345 {
346  assert(disp != NULL);
347 
348  return disp->dispstatus;
349 }
350 
351 /** is display column initialized? */
353  SCIP_DISP* disp /**< display column */
354  )
355 {
356  assert(disp != NULL);
357 
358  return disp->initialized;
359 }
360 
361 /** prints one line of output with the active display columns */
363  SCIP_SET* set, /**< global SCIP settings */
364  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
365  SCIP_STAT* stat, /**< problem statistics data */
366  FILE* file, /**< output file (or NULL for standard output) */
367  SCIP_Bool forcedisplay, /**< should the line be printed without regarding frequency? */
368  SCIP_Bool endline /**< should the line be terminated with a newline symbol? */
369  )
370 {
371  assert(set != NULL);
372  assert(set->disp_freq >= -1);
373  assert(set->disp_headerfreq >= -1);
374  assert(stat != NULL);
375 
376  if( (SCIP_VERBLEVEL)set->disp_verblevel < SCIP_VERBLEVEL_NORMAL || set->disp_freq == -1 )
377  return SCIP_OKAY;
378 
379  if( forcedisplay
380  || (stat->nnodes != stat->lastdispnode
381  && set->disp_freq > 0
382  && (stat->nnodes % set->disp_freq == 0 || stat->nnodes == 1)) )
383  {
384  int i;
385  int j;
386  SCIP_Bool stripline;
387 
388  /* display header line */
389  if( (set->disp_headerfreq == 0 && stat->ndisplines == 0)
390  || (set->disp_headerfreq > 0 && stat->ndisplines % set->disp_headerfreq == 0) )
391  {
392  int fillspace;
393 
394  stripline = FALSE;
395  for( i = 0; i < set->ndisps; ++i )
396  {
397  assert(set->disps[i] != NULL);
398  if( set->disps[i]->active )
399  {
400  if( stripline )
401  SCIPmessageFPrintInfo(messagehdlr, file, "|");
402  fillspace = set->disps[i]->width - (int)strlen(set->disps[i]->header);
403  for( j = 0; j < (fillspace)/2; ++j )
404  SCIPmessageFPrintInfo(messagehdlr, file, " ");
405  SCIPmessageFPrintInfo(messagehdlr, file, "%s", (const char*)set->disps[i]->header);
406  for( j = 0; j < (fillspace+1)/2; ++j )
407  SCIPmessageFPrintInfo(messagehdlr, file, " ");
408  stripline = set->disps[i]->stripline;
409  }
410  }
411  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
412  }
413 
414  /* display node information line */
415  stripline = FALSE;
416  for( i = 0; i < set->ndisps; ++i )
417  {
418  assert(set->disps[i] != NULL);
419  if( set->disps[i]->active )
420  {
421  if( stripline )
422  SCIPmessageFPrintInfo(messagehdlr, file, "|");
423  SCIP_CALL( SCIPdispOutput(set->disps[i], set, file) );
424  stripline = set->disps[i]->stripline;
425  }
426  }
427  if( endline )
428  {
429  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
430  }
431  fflush(stdout);
432 
433  stat->lastdispnode = stat->nnodes;
434  stat->ndisplines++;
435  }
436 
437  return SCIP_OKAY;
438 }
439 
440 /** comparison method for display columns */
441 static
443 { /*lint --e{715}*/
444  return ((SCIP_DISP*)elem2)->priority - ((SCIP_DISP*)elem1)->priority;
445 }
446 
447 /** activates all display lines fitting in the display w.r. to priority */
449  SCIP_SET* set /**< global SCIP settings */
450  )
451 {
452  SCIP_DISP** disps;
453  int totalwidth;
454  int width;
455  int i;
456 
457  assert(set != NULL);
458 
459  /* sort display columns w.r. to their priority */
460  SCIP_ALLOC( BMSduplicateMemoryArray(&disps, set->disps, set->ndisps) );
461  SCIPsortPtr((void**)disps, dispComp, set->ndisps);
462 
463  totalwidth = 0;
464 
465  /* first activate all columns with display status ON */
466  for( i = 0; i < set->ndisps; ++i )
467  {
468  width = disps[i]->width;
469  if( disps[i]->stripline )
470  width++;
471  if( disps[i]->dispstatus == SCIP_DISPSTATUS_ON )
472  {
473  disps[i]->active = TRUE;
474  totalwidth += width;
475  }
476  else
477  disps[i]->active = FALSE;
478  }
479 
480  /* beginning with highest priority display column, activate AUTO columns as long as it fits into display width */
481  for( i = 0; i < set->ndisps; ++i )
482  {
483  if( disps[i]->dispstatus == SCIP_DISPSTATUS_AUTO )
484  {
485  assert(!disps[i]->active);
486 
487  width = disps[i]->width;
488  if( disps[i]->stripline )
489  width++;
490  if( totalwidth + width <= set->disp_width )
491  {
492  disps[i]->active = TRUE;
493  totalwidth += width;
494  }
495  }
496  }
497 
498  /* free temporary memory */
499  BMSfreeMemoryArray(&disps);
500 
501  return SCIP_OKAY;
502 }
503 
504 static
505 const char decpowerchar[] = {' ', 'k', 'M', 'G', 'T', 'P', 'E'};
506 #define MAXDECPOWER 6
507 
508 /** displays a long integer in decimal form fitting in a given width */
510  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
511  FILE* file, /**< output stream */
512  SCIP_Longint val, /**< value to display */
513  int width /**< width to fit into */
514  )
515 {
516  assert(width >= 1);
517 
518  if( width == 1 )
519  {
520  if( val < 0 )
521  SCIPmessageFPrintInfo(messagehdlr, file, "-");
522  else if( val < 10 )
523  SCIPmessageFPrintInfo(messagehdlr, file, "%"SCIP_LONGINT_FORMAT, val);
524  else
525  SCIPmessageFPrintInfo(messagehdlr, file, "+");
526  }
527  else
528  {
529  char format[SCIP_MAXSTRLEN];
530  SCIP_Longint maxval;
531  int decpower;
532  int i;
533 
534  maxval = 1;
535  for( i = 0; i < width-1; ++i )
536  maxval *= 10;
537  if( val < 0 )
538  maxval /= 10;
539  decpower = 0;
540  while( ABS(val) >= maxval && decpower < MAXDECPOWER )
541  {
542  decpower++;
543  val /= 1000;
544  }
545  (void) SCIPsnprintf(format, SCIP_MAXSTRLEN, "%%%d"SCIP_LONGINT_FORMAT"%c", width-1, decpowerchar[decpower]);
546 
547  if( width == 2 && val < 0 )
548  SCIPmessageFPrintInfo(messagehdlr, file, "-%c", decpowerchar[decpower]);
549  else
550  SCIPmessageFPrintInfo(messagehdlr, file, (const char*)format, val);
551  }
552 }
553 
554 /** displays an integer in decimal form fitting in a given width */
556  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
557  FILE* file, /**< output stream */
558  int val, /**< value to display */
559  int width /**< width to fit into */
560  )
561 {
562  SCIPdispLongint(messagehdlr, file, (SCIP_Longint)val, width);
563 }
564 
565 
566 static
567 const char timepowerchar[] = {'s', 'm', 'h', 'd', 'y'};
568 const SCIP_Real timepowerval[] = {1.0, 60.0, 60.0, 24.0, 365.0};
569 #define MAXTIMEPOWER 4
570 
571 /** displays a time value fitting in a given width */
573  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
574  FILE* file, /**< output stream */
575  SCIP_Real val, /**< value in seconds to display */
576  int width /**< width to fit into */
577  )
578 {
579  assert(width >= 1);
580 
581  if( width == 1 )
582  {
583  if( val < 0.0 )
584  SCIPmessageFPrintInfo(messagehdlr, file, "-");
585  else if( val < 10.0 )
586  SCIPmessageFPrintInfo(messagehdlr, file, "%.0f", val);
587  else
588  SCIPmessageFPrintInfo(messagehdlr, file, "+");
589  }
590  else
591  {
592  char format[SCIP_MAXSTRLEN];
593  SCIP_Longint maxval;
594  int timepower;
595  int i;
596 
597  maxval = 1;
598  for( i = 0; i < width-1; ++i )
599  maxval *= 10;
600  if( val < 0.0 )
601  maxval /= 10;
602  timepower = 0;
603  while( REALABS(val) + 0.5 >= maxval && timepower < MAXTIMEPOWER )
604  {
605  timepower++;
606  val /= timepowerval[timepower];
607  }
608  if( REALABS(val) + 0.05 < maxval/100 ) /*lint !e653*/
609  (void) SCIPsnprintf(format, SCIP_MAXSTRLEN, "%%%d.1f%c", width-1, timepowerchar[timepower]);
610  else
611  (void) SCIPsnprintf(format, SCIP_MAXSTRLEN, "%%%d.0f%c", width-1, timepowerchar[timepower]);
612 
613  if( width == 2 && val < 0.0 )
614  SCIPmessageFPrintInfo(messagehdlr, file, "-%c", timepowerchar[timepower]);
615  else
616  SCIPmessageFPrintInfo(messagehdlr, file, (const char*)format, val);
617  }
618 }
619