Scippy

SCIP

Solving Constraint Integer Programs

event_solvingphase.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-2017 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 event_solvingphase.c
17  * @brief event handler for solving phase dependent parameter adjustment
18  * @author Gregor Hendel
19  *
20  * this event handler provides methods to support parameter adjustment at every new of the three solving phases:
21  * - Feasibility phase - before the first solution is found
22  * - Improvement phase - after the first solution was found until an optimal solution is found or believed to be found
23  * - Proof phase - the remaining time of the solution process after an optimal or believed-to-be optimal incumbent has been found.
24  *
25  * Of course, this event handler cannot detect by itself whether a given incumbent is optimal prior to termination of the
26  * solution process. It rather uses heuristic transitions based on properties of the search tree in order to
27  * determine the appropriate stage. Settings files can be passed to this event handler for each of the three phases.
28  *
29  * This approach of phase-based parameter adjustment was first presented in
30  *
31  * Gregor Hendel
32  * Empirical Analysis of Solving Phases in Mixed-Integer Programming
33  * Master thesis, Technical University Berlin (2014)
34  *
35  * with the main results also available from
36  *
37  * Gregor Hendel
38  * Exploiting solving phases in mixed-integer programs (2015)
39  */
40 
41 /*--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
42 
44 #include "string.h"
45 #include "scip/pub_misc.h"
46 
47 #define EVENTHDLR_NAME "solvingphase"
48 #define EVENTHDLR_DESC "event handler to adjust settings depending on current stage"
49 
50 #define EVENTHDLR_EVENT SCIP_EVENTTYPE_BESTSOLFOUND | SCIP_EVENTTYPE_NODEBRANCHED | SCIP_EVENTTYPE_NODEFOCUSED /**< the actual event to be caught */
51 #define TRANSITIONMETHODS "elor" /**< which heuristic transition method: (e)stimate based, (l)ogarithmic regression based, (o)ptimal value based (cheat!),
52  * (r)ank-1 node based? */
53 #define DEFAULT_SETNAME "-" /**< default settings file name for solving phase setting files */
54 #define DEFAULT_TRANSITIONMETHOD 'r' /**< the default transition method */
55 #define DEFAULT_NODEOFFSET 50L /**< default node offset before transition to proof phase is active */
56 #define DEFAULT_FALLBACK FALSE /**< should the phase transition fall back to suboptimal phase? */
57 #define DEFAULT_INTERRUPTOPTIMAL FALSE /**< should solving process be interrupted if optimal solution was found? */
58 
59 #define DEFAULT_ENABLED FALSE /**< should the event handler be executed? */
60 #define DEFAULT_TESTMODE FALSE /**< should the event handler test the criteria? */
61 
62 #define DEFAULT_USERESTART1TO2 FALSE /**< should a restart be applied between the feasibility and improvement phase? */
63 #define DEFAULT_USERESTART2TO3 FALSE /**< should a restart be applied between the improvement and the proof phase? */
64 #define DEFAULT_USEEMPHSETTINGS TRUE /**< should emphasis settings be used for the different solving phases, or settings files? */
65 
66 /* logarithmic regression settings */
67 #define DEFAULT_LOGREGRESSION_XTYPE 'n' /**< default type to use for log regression - (t)ime, (n)odes, (l)p iterations */
68 #define LOGREGRESSION_XTYPES "lnt" /**< available types for log regression - (t)ime, (n)odes, (l)p iterations */
69 /*
70  * Data structures
71  */
72 
73 /** enumerator to represent the current solving phase */
74 enum SolvingPhase
75 {
76  SOLVINGPHASE_UNINITIALIZED = -1, /**< solving phase has not been initialized yet */
77  SOLVINGPHASE_FEASIBILITY = 0, /**< no solution was found until now */
78  SOLVINGPHASE_IMPROVEMENT = 1, /**< current incumbent solution is suboptimal */
79  SOLVINGPHASE_PROOF = 2 /**< current incumbent is optimal */
80 };
81 typedef enum SolvingPhase SOLVINGPHASE;
82 
83 /** depth information structure */
84 struct DepthInfo
85 {
86  int nsolvednodes; /**< number of nodes that were solved so far at this depth */
87  SCIP_Real minestimate; /**< the minimum estimate of a solved node */
88  SCIP_NODE** minnodes; /**< points to the rank-1 nodes at this depth (open nodes whose estimate is lower than current
89  minimum estimate over solved nodes) */
90  int nminnodes; /**< the number of minimum nodes */
91  int minnodescapacity; /**< the capacity of the min nodes array */
92 };
93 
94 typedef struct DepthInfo DEPTHINFO;
95 
96 /** event handler data */
97 struct SCIP_EventhdlrData
98 {
99  char logregression_xtype;/**< type to use for log regression - (t)ime, (n)odes, (l)p iterations */
100  SCIP_Bool enabled; /**< should the event handler be executed? */
101  char* feassetname; /**< settings file parameter for the feasibility phase -- precedence over emphasis settings */
102  char* improvesetname; /**< settings file parameter for the improvement phase -- precedence over emphasis settings */
103  char* proofsetname; /**< settings file parameter for the proof phase -- precedence over emphasis settings */
104  SCIP_Real optimalvalue; /**< value of optimal solution of the problem */
105  SCIP_Longint nnodesleft; /**< store the number of open nodes that are considered internally to update data */
106  SOLVINGPHASE solvingphase; /**< the current solving phase */
107  char transitionmethod; /**< transition method from improvement phase -> proof phase?
108  * (e)stimate based, (l)ogarithmic regression based, (o)ptimal value based (cheat!),
109  * (r)ank-1 node based */
110  SCIP_Longint nodeoffset; /**< node offset for triggering rank-1 node based phased transition */
111  SCIP_Longint lastndelayedcutoffs;/**< the number of delayed cutoffs since the last update of a focus node */
112  SCIP_Bool fallback; /**< should the phase transition fall back to improvement phase? */
113  SCIP_Bool interruptoptimal; /**< interrupt after optimal solution was found */
114  SCIP_Bool userestart1to2; /**< should a restart be applied between the feasibility and improvement phase? */
115  SCIP_Bool userestart2to3; /**< should a restart be applied between the improvement and the proof phase? */
116  SCIP_Bool useemphsettings; /**< should emphasis settings for the solving phases be used, or settings files? */
117 
118  SCIP_Bool testmode; /**< should transitions be tested only, but not triggered? */
119  SCIP_Bool rank1reached; /**< has the rank-1 transition into proof phase been reached? */
120  SCIP_Bool estimatereached; /**< has the best-estimate transition been reached? */
121  SCIP_Bool optimalreached; /**< is the incumbent already optimal? */
122  SCIP_Bool logreached; /**< has a logarithmic phase transition been reached? */
123  SCIP_Bool newbestsol; /**< has a new incumbent been found since the last node was solved? */
124 
125  SCIP_REGRESSION* regression; /**< regression data for log linear regression of the incumbent solutions */
126  SCIP_Real lastx; /**< X-value of last observation */
127  SCIP_Real lasty; /**< Y-value of last observation */
128  SCIP_PARAM** nondefaultparams; /**< parameters with non-default values during problem initialization */
129  int nnondefaultparams; /**< number of parameters with non-default values during problem initialization */
130  int nondefaultparamssize;/**< capacity of the array of non-default parameters */
131  int eventfilterpos; /**< the event filter position, or -1, if event has not (yet) been caught */
132  DEPTHINFO** depthinfos; /**< array of depth infos for every depth of the search tree */
133  int maxdepth; /**< maximum depth so far */
134  int nrank1nodes; /**< number of rank-1 nodes */
135  int nnodesbelowincumbent;/**< number of open nodes with an estimate lower than the current incumbent */
136 };
137 
138 
139 /*
140  * methods for rank-1 and active estimate transition
141  */
142 
143 /** nodes are sorted first by their estimates, and if estimates are equal, by their number */
144 static
145 SCIP_DECL_SORTPTRCOMP(sortCompTreeinfo)
146 {
147  SCIP_NODE* node1;
148  SCIP_NODE* node2;
149  SCIP_Real estim1;
150  SCIP_Real estim2;
151  node1 = (SCIP_NODE*)elem1;
152  node2 = (SCIP_NODE*)elem2;
153 
154  estim1 = SCIPnodeGetEstimate(node1);
155  estim2 = SCIPnodeGetEstimate(node2);
156 
157  /* compare estimates */
158  if( estim1 < estim2 )
159  return -1;
160  else if( estim1 > estim2 )
161  return 1;
162  else
163  {
164  SCIP_Longint number1;
165  SCIP_Longint number2;
166 
167  number1 = SCIPnodeGetNumber(node1);
168  number2 = SCIPnodeGetNumber(node2);
169 
170  /* compare numbers */
171  if( number1 < number2 )
172  return -1;
173  else if( number1 > number2 )
174  return 1;
175  }
176 
177  return 0;
178 }
179 
180 /** insert an array of open nodes (leaves/siblings/children) into the event handler data structures and update the transition information */
181 static
183  SCIP* scip, /**< SCIP data structure */
184  SCIP_EVENTHDLRDATA* eventhdlrdata, /**< event handler data */
185  SCIP_NODE** nodes, /**< array of nodes */
186  int nnodes /**< number of nodes */
187  )
188 {
189  int n;
190 
191  assert(nnodes == 0 || nodes != NULL);
192  assert(scip != NULL);
193  assert(eventhdlrdata->depthinfos != NULL);
194 
195  /* store every relevant node in the data structure for its depth */
196  for( n = 0; n < nnodes; ++n )
197  {
198  SCIP_NODE* node = nodes[n];
199  DEPTHINFO* depthinfo = eventhdlrdata->depthinfos[SCIPnodeGetDepth(node)];
200  SCIP_Real estim = SCIPnodeGetEstimate(node);
201 
204 
205  /* an open node has rank 1 if it has an estimate at least as small as the best solved node at this depth */
206  if( depthinfo->nsolvednodes == 0 || SCIPisGE(scip, depthinfo->minestimate, SCIPnodeGetEstimate(node)) )
207  {
208  int pos;
209 
210  /* allocate additional memory to hold new node */
211  if( depthinfo->nminnodes == depthinfo->minnodescapacity )
212  {
213  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &depthinfo->minnodes, depthinfo->minnodescapacity,
214  2 * depthinfo->minnodescapacity) ); /*lint !e647*/
215  depthinfo->minnodescapacity *= 2;
216  }
217 
218  /* find correct insert position */
219  SCIPsortedvecInsertPtr((void **)depthinfo->minnodes, sortCompTreeinfo, (void*)node, &depthinfo->nminnodes, &pos);
220  assert(pos >= 0 && pos < depthinfo->nminnodes);
221  assert(depthinfo->minnodes[pos] == node);
222 
223  /* update rank 1 node information */
224  ++eventhdlrdata->nrank1nodes;
225  }
226 
227  /* update active estimate information by bookkeeping nodes with an estimate smaller than the current incumbent */
228  if( SCIPisLT(scip, estim, SCIPgetUpperbound(scip) ) )
229  ++eventhdlrdata->nnodesbelowincumbent;
230  }
231 
232  /* update the number of open search nodes */
233  eventhdlrdata->nnodesleft += nnodes;
234 
235  return SCIP_OKAY;
236 }
237 
238 /** remove a node from the data structures of the event handler */
239 static
240 void removeNode(
241  SCIP_NODE* node, /**< node that should be removed */
242  SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
243  )
244 {
245  DEPTHINFO* depthinfo;
246  int pos;
247  SCIP_Bool contained;
248 
249  assert(node != NULL);
250 
251  /* get depth information for the depth of this node */
252  depthinfo = eventhdlrdata->depthinfos[SCIPnodeGetDepth(node)];
253 
254  /* no node is saved at this depth */
255  if( depthinfo->nminnodes == 0 )
256  return;
257 
258  /* search for the node by using binary search */
259  contained = SCIPsortedvecFindPtr((void **)depthinfo->minnodes, sortCompTreeinfo, (void *)node, depthinfo->nminnodes, &pos);
260 
261  /* remove the node if it is contained */
262  if( contained )
263  {
264  SCIPsortedvecDelPosPtr((void **)depthinfo->minnodes, sortCompTreeinfo, pos, &(depthinfo->nminnodes));
265  --eventhdlrdata->nrank1nodes;
266  }
267 }
268 
269 /** returns the current number of rank 1 nodes in the tree */
270 static
271 int getNRank1Nodes(
272  SCIP* scip /**< SCIP data structure */
273  )
274 {
275  SCIP_EVENTHDLRDATA* eventhdlrdata;
276 
277  assert(scip != NULL);
278 
279  eventhdlrdata = SCIPeventhdlrGetData(SCIPfindEventhdlr(scip, EVENTHDLR_NAME));
280 
281  /* return the stored number of rank 1 nodes only during solving stage */
282  if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
283  return eventhdlrdata->nrank1nodes;
284  else
285  return -1;
286 }
287 
288 /** returns the current number of open nodes which have an estimate lower than the incumbent solution */
289 static
291  SCIP* scip /**< SCIP data structure */
292  )
293 {
294  SCIP_EVENTHDLRDATA* eventhdlrdata;
295 
296  assert(scip != NULL);
297 
298  eventhdlrdata = SCIPeventhdlrGetData(SCIPfindEventhdlr(scip, EVENTHDLR_NAME));
299 
300  /* return the stored number of nodes only during solving stage */
301  if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING )
302  return eventhdlrdata->nnodesbelowincumbent;
303  else
304  return -1;
305 }
306 
307 /** discards all previous node information and renews it */
308 static
310  SCIP* scip, /**< SCIP data structure */
311  SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
312  )
313 {
314  SCIP_NODE** leaves;
315  SCIP_NODE** children;
316  SCIP_NODE** siblings;
317 
318  int nleaves;
319  int nchildren;
320  int nsiblings;
321  int d;
322 
323  /* the required node information is only available after solving started */
324  if( SCIPgetStage(scip) != SCIP_STAGE_SOLVING )
325  return SCIP_OKAY;
326 
327  assert(eventhdlrdata != NULL);
328 
329  /* reset depth information */
330  for( d = 0; d < eventhdlrdata->maxdepth; ++d )
331  eventhdlrdata->depthinfos[d]->nminnodes = 0;
332 
333  eventhdlrdata->nrank1nodes = 0;
334  eventhdlrdata->nnodesbelowincumbent = 0;
335  eventhdlrdata->nnodesleft = 0;
336 
337  nleaves = nchildren = nsiblings = 0;
338 
339  /* get leaves, children, and sibling arrays and update the event handler data structures */
340  SCIP_CALL( SCIPgetOpenNodesData(scip, &leaves, &children, &siblings, &nleaves, &nchildren, &nsiblings) );
341 
342  SCIP_CALL ( addNodesInformation(scip, eventhdlrdata, children, nchildren) );
343 
344  SCIP_CALL ( addNodesInformation(scip, eventhdlrdata, siblings, nsiblings) );
345 
346  SCIP_CALL ( addNodesInformation(scip, eventhdlrdata, leaves, nleaves) );
347 
348  /* information needs to be recomputed from scratch if a new incumbent is found */
349  eventhdlrdata->newbestsol = FALSE;
350 
351  return SCIP_OKAY;
352 }
353 
354 /** allocates memory for a depth info */
355 static
357  SCIP* scip, /**< SCIP data structure */
358  DEPTHINFO** depthinfo /**< pointer to depth information structure */
359  )
360 {
361  assert(scip != NULL);
362  assert(depthinfo != NULL);
363 
364  /* allocate the necessary memory */
365  SCIP_CALL( SCIPallocBlockMemory(scip, depthinfo) );
366 
367  /* reset the depth information */
368  (*depthinfo)->minestimate = SCIPinfinity(scip);
369  (*depthinfo)->nsolvednodes = 0;
370  (*depthinfo)->nminnodes = 0;
371  (*depthinfo)->minnodescapacity = 2;
372 
373  /* allocate array to store nodes */
374  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*depthinfo)->minnodes, (*depthinfo)->minnodescapacity) );
375 
376  return SCIP_OKAY;
377 }
378 
379 /** frees depth information data structure */
380 static
382  SCIP* scip, /**< SCIP data structure */
383  DEPTHINFO** depthinfo /**< pointer to depth information structure */
384  )
385 {
386  assert(scip != NULL);
387  assert(depthinfo != NULL);
388  assert(*depthinfo != NULL);
389  assert((*depthinfo)->minnodes != NULL);
390 
391  /* free nodes data structure and then the structure itself */
392  SCIPfreeBlockMemoryArray(scip, &(*depthinfo)->minnodes, (*depthinfo)->minnodescapacity);
393  SCIPfreeBlockMemory(scip, depthinfo);
394 
395  return SCIP_OKAY;
396 }
397 
398 /** removes the node itself and updates the data if this node defined an active estimate globally or locally at its depth level */
399 static
401  SCIP* scip, /**< SCIP data structure */
402  SCIP_EVENTHDLRDATA* eventhdlrdata, /**< event handler data */
403  SCIP_NODE* node /**< node to be removed from the data structures of the event handler */
404  )
405 {
406  DEPTHINFO* depthinfo;
407 
408  assert(scip != NULL);
409  assert(node != NULL);
410  assert(eventhdlrdata != NULL);
411 
412  /* get the correct depth info at the node depth */
413  depthinfo = eventhdlrdata->depthinfos[SCIPnodeGetDepth(node)];
414  assert(depthinfo != NULL);
415 
416  /* remove the node from the data structures */
417  removeNode(node, eventhdlrdata);
418 
419  /* compare the node estimate to the minimum estimate of the particular depth */
420  if( SCIPisLT(scip, SCIPnodeGetEstimate(node), depthinfo->minestimate) )
421  depthinfo->minestimate = SCIPnodeGetEstimate(node);
422 
423  /* decrease counter of active estimate nodes if node has an estimate that is below the current incumbent */
424  if( SCIPisLT(scip, SCIPnodeGetEstimate(node), SCIPgetUpperbound(scip)) && SCIPnodeGetDepth(node) > 0 )
425  eventhdlrdata->nnodesbelowincumbent--;
426 
427  /* loop over remaining, unsolved nodes and decide whether they are still rank-1 nodes */
428  while( depthinfo->nminnodes > 0 && SCIPisGT(scip, SCIPnodeGetEstimate(depthinfo->minnodes[depthinfo->nminnodes - 1]), depthinfo->minestimate) )
429  {
430  /* forget about node */
431  --(depthinfo->nminnodes);
432  --(eventhdlrdata->nrank1nodes);
433  }
434 
435  /* increase the number of solved nodes at this depth */
436  ++(depthinfo->nsolvednodes);
437 
438  /* decrease the counter for the number of open nodes */
439  --eventhdlrdata->nnodesleft;
440 }
441 
442 /** ensures sufficient size for depthInfo array */
443 static
445  SCIP* scip, /**< SCIP data structure */
446  SCIP_EVENTHDLRDATA* eventhdlrdata, /**< event handler data */
447  SCIP_NODE* node /**< node to be removed from the data structures of the event handler */
448  )
449 {
450  int nodedepth;
451  int newsize;
452  int oldsize;
453  nodedepth = SCIPnodeGetDepth(node);
454  oldsize = eventhdlrdata->maxdepth;
455  newsize = oldsize;
456 
457  /* create depth info array with small initial size or enlarge the existing array if new node is deeper */
458  if( oldsize == 0 )
459  {
460  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &eventhdlrdata->depthinfos, 10) );
461  newsize = 10;
462  }
463  else if( nodedepth + 1 >= eventhdlrdata->maxdepth )
464  {
465  assert(nodedepth > 0);
466  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &eventhdlrdata->depthinfos, oldsize, 2 * nodedepth) ); /*lint !e647*/
467  newsize = 2 * nodedepth;
468  }
469 
470  /* create the according depth information pointers */
471  if( newsize > oldsize )
472  {
473  int c;
474 
475  for( c = oldsize; c < newsize; ++c )
476  {
477  SCIP_CALL( createDepthinfo(scip, &(eventhdlrdata->depthinfos[c])) );
478 
479  }
480 
481  eventhdlrdata->maxdepth = newsize;
482  }
483  assert(newsize > nodedepth);
484 
485  return SCIP_OKAY;
486 }
487 
488 /** ensures the capacity of the event handler data structures and removes the current node */
489 static
491  SCIP* scip, /**< SCIP data structure */
492  SCIP_EVENTHDLRDATA* eventhdlrdata, /**< event handler data */
493  SCIP_NODE* node /**< node to be removed from the data structures of the event handler */
494  )
495 {
496 
497  assert(scip != NULL);
498  assert(node != NULL);
499  assert(eventhdlrdata != NULL);
500 
501  /* ensure the depth info data structure can hold this node */
502  SCIP_CALL( ensureDepthInfoArraySize(scip, eventhdlrdata, node) );
503 
504 
505  /* in case that selected nodes were cut off in between two calls to this method, build data structures from scratch again */
506  if( SCIPgetNDelayedCutoffs(scip) > eventhdlrdata->lastndelayedcutoffs || eventhdlrdata->newbestsol
507  || eventhdlrdata->nnodesleft - 1 != SCIPgetNNodesLeft(scip) )
508  {
509  SCIP_CALL( recomputeNodeInformation(scip, eventhdlrdata) );
510 
511  eventhdlrdata->lastndelayedcutoffs = SCIPgetNDelayedCutoffs(scip);
512  }
513  else
514  {
515  /* remove the node from the data structures */
516  releaseNodeFromDepthInfo(scip, eventhdlrdata, node);
517  }
518 
519  assert(eventhdlrdata->nnodesleft == SCIPgetNNodesLeft(scip));
520 
521  return SCIP_OKAY;
522 }
523 
524 #ifndef NDEBUG
525 /** ensures correctness of counters by explicitly summing up all children, leaves, and siblings with small estimates */
526 static
528  SCIP* scip
529  )
530 {
531  SCIP_NODE** nodes;
532  SCIP_RETCODE retcode;
533  int nnodes;
534  int n;
535  SCIP_Real upperbound = SCIPgetUpperbound(scip);
536  int nodesbelow = 0;
537 
538  /* compare children estimate and current upper bound */
539  retcode = SCIPgetChildren(scip, &nodes, &nnodes);
540  assert(retcode == SCIP_OKAY);
541 
542  for( n = 0; n < nnodes; ++n )
543  {
544  if( SCIPisLT(scip, SCIPnodeGetEstimate(nodes[n]), upperbound) )
545  ++nodesbelow;
546  }
547 
548  /* compare sibling estimate and current upper bound */
549  retcode = SCIPgetSiblings(scip, &nodes, &nnodes);
550  assert(retcode == SCIP_OKAY);
551 
552  for( n = 0; n < nnodes; ++n )
553  {
554  if( SCIPisLT(scip, SCIPnodeGetEstimate(nodes[n]), upperbound) )
555  ++nodesbelow;
556  }
557 
558  /* compare leaf node and current upper bound */
559  retcode = SCIPgetLeaves(scip, &nodes, &nnodes);
560  assert(retcode == SCIP_OKAY);
561 
562  for( n = 0; n < nnodes; ++n )
563  {
564  if( SCIPisLT(scip, SCIPnodeGetEstimate(nodes[n]), upperbound) )
565  ++nodesbelow;
566  }
567 
568  assert(nodesbelow <= SCIPgetNNodesLeft(scip));
569  return nodesbelow;
570 }
571 #endif
572 
573 /** get the point of the X axis for the regression according to the user choice of X type (time/nodes/iterations)*/
574 static
576  SCIP* scip, /**< SCIP data structure */
577  SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
578  )
579 {
580  SCIP_Real x;
581 
582  switch( eventhdlrdata->logregression_xtype )
583  {
584  case 'l':
585  /* get number of LP iterations so far */
587  x = (SCIP_Real)SCIPgetNLPIterations(scip);
588  else
589  x = 1.0;
590  break;
591  case 'n':
592  /* get total number of solving nodes so far */
594  x = (SCIP_Real)SCIPgetNTotalNodes(scip);
595  else
596  x = 1.0;
597  break;
598  case 't':
599  /* get solving time */
600  x = SCIPgetSolvingTime(scip);
601  break;
602  default:
603  x = 1.0;
604  break;
605  }
606 
607  /* prevent the calculation of logarithm too close to zero */
608  x = MAX(x, .1);
609  x = log(x);
610 
611  return x;
612 }
613 
614 
615 
616 
617 
618 /** get axis intercept of current tangent to logarithmic regression curve */
619 static
621  SCIP* scip, /**< SCIP data structure */
622  SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data structure */
623  )
624 {
625  SCIP_REGRESSION* regression;
626  SCIP_Real currentx;
627  SCIP_Real regressionslope;
628 
629  assert(scip != NULL);
630  assert(eventhdlrdata != NULL);
631 
632  regression = eventhdlrdata->regression;
633  assert(regression != NULL);
634 
635  /* don't rely on too few (<= 2) observations */
636  if( SCIPregressionGetNObservations(regression) <= 2 )
637  return SCIPinfinity(scip);
638 
639  currentx = getX(scip, eventhdlrdata);
640  regressionslope = SCIPregressionGetSlope(regression);
641 
642  return regressionslope * currentx + SCIPregressionGetIntercept(regression) - regressionslope;
643 }
644 
645 /*
646  * Local methods
647  */
648 
649 /** checks if rank-1 transition has been reached, that is, when all open nodes have a best-estimate higher than the best
650  * previously checked node at this depth
651  */
652 static
654  SCIP* scip, /**< SCIP data structure */
655  SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
656  )
657 {
658  /* at least one solution is required for the transition */
659  if( SCIPgetNSols(scip) > 0 )
660  return (SCIPgetNNodes(scip) > eventhdlrdata->nodeoffset && getNRank1Nodes(scip) == 0);
661  else
662  return FALSE;
663 }
664 
665 /** check if Best-Estimate criterion was reached, that is, when the active estimate is not better than the current incumbent solution */
666 static
668  SCIP* scip, /**< SCIP data structure */
669  SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
670  )
671 {
672  assert(SCIPgetStage(scip) == SCIP_STAGE_SOLVING);
673 
674  if( SCIPgetNSols(scip) > 0 )
675  return ((SCIPgetNNodes(scip) > eventhdlrdata->nodeoffset) && (eventhdlrdata->nnodesbelowincumbent == 0));
676  else
677  return FALSE;
678 }
679 
680 /** check if logarithmic phase transition has been reached.
681  *
682  * the logarithmic phase transition is reached when the slope of the logarithmic primal progress (as a function of the number of
683  * LP iterations or solving nodes) becomes gentle. More concretely, we measure the slope by calculating the axis intercept of the tangent of
684  * the logarithmic primal progress. We then compare this axis intercept to the first and current primal bound and say that
685  * the logarithmic phase transition is reached as soon as the axis intercept passes the current primal bound so that the
686  * scalar becomes negative.
687  *
688  * While it would be enough to directly compare the primal bound and the axis intercept of the
689  * tangent to check the criterion, the scalar allows for a continuous indicator how far the phase transition is still ahead
690  */
691 static
693  SCIP* scip, /**< SCIP data structure */
694  SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
695  )
696 {
697  if( SCIPgetNSols(scip) > 0 )
698  {
699  SCIP_Real axisintercept = getCurrentRegressionTangentAxisIntercept(scip, eventhdlrdata);
700  if( !SCIPisInfinity(scip, axisintercept) )
701  {
702  SCIP_Real primalbound;
703  SCIP_Real lambda;
704  SCIP_Real firstprimalbound = SCIPgetFirstPrimalBound(scip);
705 
706  primalbound = SCIPgetPrimalbound(scip);
707 
708  /* lambda is the scalar to describe the axis intercept as a linear combination of the current and the first primal bound
709  * as intercept = pb_0 + lambda * (pb - pb_0) */
710  lambda = (axisintercept - primalbound) / (firstprimalbound - primalbound);
711 
712  if( SCIPisNegative(scip, lambda) )
713  return TRUE;
714  }
715  }
716  return FALSE;
717 }
718 
719 /** check if incumbent solution is nearly optimal; we allow a relative deviation of 10^-9 */
720 static
722  SCIP* scip, /**< SCIP data structure */
723  SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
724  )
725 {
726  SCIP_Real referencevalue;
727  SCIP_Real primalbound;
728 
729  referencevalue = eventhdlrdata->optimalvalue;
730  primalbound = SCIPgetPrimalbound(scip);
731 
732  if(!SCIPisInfinity(scip, REALABS(primalbound)) && !SCIPisInfinity(scip, referencevalue) )
733  {
734  SCIP_Real max = MAX3(1.0, REALABS(primalbound), REALABS(referencevalue)); /*lint !e666*/
735 
736  if( EPSZ((primalbound - referencevalue)/max, 1e-9) )
737  return TRUE;
738  }
739  return FALSE;
740 }
741 
742 /** check if we are in the proof phase */
743 static
745  SCIP* scip, /**< SCIP data structure */
746  SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
747  )
748 {
749  if( eventhdlrdata->solvingphase == SOLVINGPHASE_PROOF && !eventhdlrdata->fallback )
750  return TRUE;
751 
752  /* check criterion based on selected transition method */
753  switch( eventhdlrdata->transitionmethod )
754  {
755  case 'r':
756 
757  /* check rank-1 transition */
758  if( checkRankOneTransition(scip, eventhdlrdata) )
759  {
760  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "reached rank-1 transition: nodes: %lld, rank-1: %d bound: %9.5g time: %.2f\n",
762  return TRUE;
763  }
764  break;
765  case 'o':
766 
767  /* cheat and use knowledge about optimal solution */
768  if( checkOptimalSolution(scip, eventhdlrdata) )
769  {
770  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "optimal solution found: %lld, bound: %9.5g time: %.2f\n",
772  return TRUE;
773  }
774  break;
775  case 'e':
776 
777  /* check best-estimate transition */
778  if( checkEstimateCriterion(scip, eventhdlrdata) )
779  {
780  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "reached best-estimate transition: nodes: %lld, estimate: %d bound: %9.5g time: %.2f\n",
781  SCIPgetNNodes(scip), eventhdlrdata->nnodesbelowincumbent, SCIPgetPrimalbound(scip), SCIPgetSolvingTime(scip));
782  return TRUE;
783  }
784  return FALSE;
785  case 'l':
786 
787  /* check logarithmic transition */
788  if( checkLogCriterion(scip, eventhdlrdata) )
789  {
790  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "reached a logarithmic phase transition: %.2f\n", SCIPgetSolvingTime(scip));
791  return TRUE;
792  }
793  break;
794  default:
795  return FALSE;
796  }
797 
798  return FALSE;
799 }
800 
801 /* determine the solving phase: feasibility phase if no solution was found yet, otherwise improvement phase or proof phase
802  * depending on whether selected transition criterion was already reached and fallback is active or not
803  */
804 static
806  SCIP* scip, /**< SCIP data structure */
807  SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
808  )
809 {
810  /* without solution, we are in the feasibility phase */
811  if( SCIPgetNSols(scip) == 0 )
812  eventhdlrdata->solvingphase = SOLVINGPHASE_FEASIBILITY;
813  else if( eventhdlrdata->solvingphase != SOLVINGPHASE_PROOF || eventhdlrdata->fallback )
814  eventhdlrdata->solvingphase = SOLVINGPHASE_IMPROVEMENT;
815 
816  if( eventhdlrdata->solvingphase == SOLVINGPHASE_IMPROVEMENT && transitionPhase3(scip, eventhdlrdata) )
817  eventhdlrdata->solvingphase = SOLVINGPHASE_PROOF;
818 }
819 
820 /** changes parameters by using emphasis settings */
821 static
823  SCIP* scip, /**< SCIP data structure */
824  SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
825  )
826 {
827  SCIP_PARAMEMPHASIS paramemphasis;
828 
829  /* choose the appropriate emphasis settings for the new solving phase */
830  switch(eventhdlrdata->solvingphase)
831  {
833  paramemphasis = SCIP_PARAMEMPHASIS_PHASEFEAS;
834  break;
836  paramemphasis = SCIP_PARAMEMPHASIS_PHASEIMPROVE;
837  break;
838  case SOLVINGPHASE_PROOF:
839  paramemphasis = SCIP_PARAMEMPHASIS_PHASEPROOF;
840  break;
842  default:
843  SCIPdebugMsg(scip, "Unknown solving phase: %d -> ABORT!\n ", eventhdlrdata->solvingphase);
844  SCIPABORT();
845  paramemphasis = SCIP_PARAMEMPHASIS_DEFAULT;
846  break;
847  }
848 
849  SCIP_CALL( SCIPsetEmphasis(scip, paramemphasis, FALSE) );
850 
851  return SCIP_OKAY;
852 }
853 
854 /** change general solving strategy of SCIP depending on the phase by reading from settings file */
855 static
857  SCIP* scip, /**< SCIP data structure */
858  SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
859  )
860 {
861  FILE* file;
862  char* paramfilename = NULL;
863 
864  /* choose the settings file for the new solving phase */
865  switch(eventhdlrdata->solvingphase)
866  {
868  paramfilename = eventhdlrdata->feassetname;
869  break;
871  paramfilename = eventhdlrdata->improvesetname;
872  break;
873  case SOLVINGPHASE_PROOF:
874  paramfilename = eventhdlrdata->proofsetname;
875  break;
877  default:
878  SCIPdebugMsg(scip, "Unknown solving phase: %d -> ABORT!\n ", eventhdlrdata->solvingphase);
879  SCIPABORT();
880  break;
881  }
882 
883  assert(paramfilename != NULL);
884 
885  /* return if no there is no user-specified settings file for the current phase */
886  if( strcmp(paramfilename, DEFAULT_SETNAME) == 0 )
887  return SCIP_OKAY;
888 
889  file = fopen(paramfilename, "r");
890 
891  /* test if file could be found and print a warning if not */
892  if( file == NULL )
893  {
894  SCIPwarningMessage(scip, "Parameter file <%s> not found--keeping settings as before.\n", paramfilename);
895  }
896  else
897  {
898  /* we can close the file */
899  fclose(file);
900 
901  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Reading parameters from file <%s>\n", paramfilename);
902 
903  SCIP_CALL( SCIPreadParams(scip, paramfilename) );
904  }
905 
906  return SCIP_OKAY;
907 }
908 
909 /** fix/unfix relevant solving parameters that should not accidentally be set to default values */
910 static
912  SCIP* scip, /**< SCIP data structure */
913  SCIP_EVENTHDLRDATA* eventhdlrdata, /**< event handler data */
914  SCIP_Bool fix /**< should the parameters be fixed (true) or unfixed? */
915  )
916 {
917  int p;
918  const char* relevantparams[] = {
919  "limits/time",
920  "limits/nodes",
921  "limits/totalnodes",
922  "limits/stallnodes",
923  "limits/memory",
924  "limits/gap",
925  "limits/absgap",
926  "limits/solutions",
927  "limits/bestsol",
928  "limits/maxsol",
929  "limits/maxorigsol",
930  "limits/restarts",
931  "limits/autorestartnodes",
932  "limits/softtime",
933  "solvingphases/enabled",
934  "solvingphases/fallback",
935  "solvingphases/interruptoptimal",
936  "solvingphases/nodeoffset",
937  "solvingphases/feassetname",
938  "solvingphases/proofsetname",
939  "solvingphases/optimalvalue",
940  "solvingphases/improvesetname",
941  "solvingphases/testmode",
942  "solvingphases/transitionmethod",
943  "solvingphases/useemphsettings",
944  "solvingphases/userestart1to2",
945  "solvingphases/userestart2to3",
946  "solvingphases/xtype"
947  };
948  int nrelevantparams = 28;
949 
950  /* fix or unfix all specified limit parameters */
951  for( p = 0; p < nrelevantparams; ++p )
952  {
953  if( fix )
954  {
955  SCIP_CALL( SCIPfixParam(scip, relevantparams[p]) );
956  }
957  else
958  {
959  SCIP_CALL( SCIPunfixParam(scip, relevantparams[p]) );
960  }
961  }
962 
963  /* fix or unfix all collected, non-default parameters after problem transformation */
964  for( p = 0; p < eventhdlrdata->nnondefaultparams; ++p )
965  {
966  if( fix && ! SCIPparamIsFixed(eventhdlrdata->nondefaultparams[p]) )
967  {
968  SCIP_CALL( SCIPfixParam(scip, SCIPparamGetName(eventhdlrdata->nondefaultparams[p])) );
969  }
970  else if( ! fix && SCIPparamIsFixed(eventhdlrdata->nondefaultparams[p]) )
971  {
972  SCIP_CALL( SCIPunfixParam(scip, SCIPparamGetName(eventhdlrdata->nondefaultparams[p])) );
973  }
974  }
975 
976  return SCIP_OKAY;
977 }
978 
979 /** change settings depending whether emphasis settings should be used, or settings files */
980 static
982  SCIP* scip, /**< SCIP data structure */
983  SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
984  )
985 {
986  /* fix relevant parameters such that they are not overwritten */
987  SCIP_CALL( fixOrUnfixRelevantParameters(scip, eventhdlrdata, TRUE) );
988 
989  /* change settings using emphasis */
990  if( eventhdlrdata->useemphsettings )
991  {
992  SCIP_CALL( changeEmphasisParameters(scip, eventhdlrdata) );
993  }
994  else
995  {
996  /* reset to default settings; this happens automatically when using emphasis settings */
998  }
999 
1000  /* read optional, phase-specific settings */
1001  SCIP_CALL( changeParametersUsingSettingsFiles(scip, eventhdlrdata) );
1002 
1003  /* unfix relevant parameters that have been fixed for changing emphasis */
1004  SCIP_CALL( fixOrUnfixRelevantParameters(scip, eventhdlrdata, FALSE) );
1005 
1006  return SCIP_OKAY;
1007 }
1008 
1009 /* apply the user-specified phase-based settings: A phase transition invokes the read of phase-specific settings from a file */
1010 static
1012  SCIP* scip, /**< SCIP data structure */
1013  SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
1014  )
1015 {
1016  SOLVINGPHASE oldsolvingphase;
1017  SCIP_Bool restart;
1018 
1019  /* return immediately if we are in the proof phase */
1020  if( eventhdlrdata->solvingphase == SOLVINGPHASE_PROOF && !eventhdlrdata->fallback )
1021  return SCIP_OKAY;
1022 
1023  /* save current solving phase */
1024  oldsolvingphase = eventhdlrdata->solvingphase;
1025 
1026  /* determine current solving phase */
1027  determineSolvingPhase(scip, eventhdlrdata);
1028 
1029 
1030  /* nothing has changed */
1031  if( oldsolvingphase == eventhdlrdata->solvingphase )
1032  return SCIP_OKAY;
1033 
1034 
1035  /* check if the solving process should be interrupted when the current solution is optimal */
1036  if( eventhdlrdata->solvingphase == SOLVINGPHASE_PROOF && eventhdlrdata->transitionmethod == 'o' &&
1037  eventhdlrdata->interruptoptimal )
1038  {
1039  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Solution is optimal. Calling user interruption.\n");
1040 
1041  /* we call interrupt solve but do not return yet because user-specified settings for the proof phase are applied first */
1042  SCIP_CALL( SCIPinterruptSolve(scip) );
1043  }
1044 
1045  /* check if a restart should be performed after phase transition */
1046  if( eventhdlrdata->solvingphase == SOLVINGPHASE_IMPROVEMENT && eventhdlrdata->userestart1to2 )
1047  restart = TRUE;
1048  else if( eventhdlrdata->solvingphase == SOLVINGPHASE_PROOF && eventhdlrdata->userestart2to3 )
1049  restart = TRUE;
1050  else
1051  restart = FALSE;
1052 
1053  /* inform SCIP that a restart should be performed */
1054  if( restart )
1055  {
1056  SCIP_CALL( SCIPrestartSolve(scip) );
1057  }
1058 
1059  /* change general solving settings depending on solving strategy */
1060  SCIP_CALL( adaptSolverBehavior(scip, eventhdlrdata) );
1061 
1062  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL,"Changed solving phase to phase %d.\n", eventhdlrdata->solvingphase);
1063 
1064  return SCIP_OKAY;
1065 
1066 }
1067 
1068 /** update the logarithmic regression */
1069 static
1071  SCIP* scip, /**< SCIP data structure */
1072  SCIP_EVENTHDLRDATA* eventhdlrdata /**< data of event handler */
1073  )
1074 {
1075  SCIP_Real regressionx;
1076  SCIP_Real regressiony;
1077 
1078  regressionx = getX(scip, eventhdlrdata);
1079  regressiony = SCIPgetPrimalbound(scip);
1080 
1081  /* remove the last observation if it has been observed at the same x */
1082  if( SCIPisEQ(scip, eventhdlrdata->lastx, regressionx) )
1083  {
1084  SCIPregressionRemoveObservation(eventhdlrdata->regression, eventhdlrdata->lastx, eventhdlrdata->lasty);
1085  }
1086 
1087  /* add the new observation to the regression and save it if another update is necessary */
1088  SCIPregressionAddObservation(eventhdlrdata->regression, regressionx, regressiony);
1089  eventhdlrdata->lastx = regressionx;
1090  eventhdlrdata->lasty = regressiony;
1091 
1092  return SCIP_OKAY;
1093 }
1094 
1095 /** update data structures based on the event type caught */
1096 static
1098  SCIP* scip, /**< SCIP data structure */
1099  SCIP_EVENTHDLRDATA* eventhdlrdata, /**< data of event handler */
1100  SCIP_EVENTTYPE eventtype /**< type of the caught event */
1101  )
1102 {
1103  SCIP_NODE** children;
1104  int nchildren;
1105 
1106  switch( eventtype )
1107  {
1108  /* store that a new best solution was found, but delay the update of node information until a node was solved */
1110  eventhdlrdata->newbestsol = TRUE;
1111 
1112  /* update logarithmic regression of solution process */
1113  SCIP_CALL( updateLogRegression(scip, eventhdlrdata) );
1114 
1115  break;
1116 
1117  /* release the focus node from the open node data structures */
1119  assert(SCIPgetStage(scip) == SCIP_STAGE_SOLVING);
1120 
1121  SCIP_CALL( releaseNodeInformation(scip, eventhdlrdata, SCIPgetCurrentNode(scip)));
1122  assert(eventhdlrdata->nnodesbelowincumbent <= SCIPgetNNodesLeft(scip));
1123 
1124  break;
1125 
1126  /* store node information for child nodes */
1128  assert(SCIPgetStage(scip) == SCIP_STAGE_SOLVING);
1129 
1130  /* if we lost track of exact number of open search nodes, we recompute node information from scratch */
1131  if( eventhdlrdata->newbestsol || eventhdlrdata->nnodesleft + SCIPgetNChildren(scip) != SCIPgetNNodesLeft(scip) )
1132  {
1133  SCIP_CALL( recomputeNodeInformation(scip, eventhdlrdata) );
1134  eventhdlrdata->newbestsol = FALSE;
1135 
1136  return SCIP_OKAY;
1137  }
1138  else
1139  {
1140  SCIP_CALL( SCIPgetChildren(scip, &children, &nchildren) );
1141  SCIP_CALL( addNodesInformation(scip, eventhdlrdata, children, nchildren) );
1142  }
1143 
1144  assert(eventhdlrdata->nnodesleft == SCIPgetNNodesLeft(scip));
1145  break;
1146 
1147  default:
1148  break;
1149  }
1150 
1151  /* ensure that required tree information was correctly computed; only available in solving stage and at the beginning
1152  * or end of a node solution process because we delay the recomputation of the node information)
1153  */
1154  assert(SCIPgetStage(scip) != SCIP_STAGE_SOLVING ||
1155  (eventtype == SCIP_EVENTTYPE_BESTSOLFOUND) ||
1156  (eventhdlrdata->nnodesleft == SCIPgetNNodesLeft(scip) && eventhdlrdata->nnodesbelowincumbent == checkLeavesBelowIncumbent(scip)));
1157 
1158  return SCIP_OKAY;
1159 }
1160 
1161 /** test all criteria whether they have been reached */
1162 static
1163 void testCriteria(
1164  SCIP* scip, /**< SCIP data structure */
1165  SCIP_EVENTHDLRDATA* eventhdlrdata /**< data of event handler */
1166  )
1167 {
1168  assert(scip != NULL);
1169  assert(eventhdlrdata != NULL);
1170 
1171  if( ! eventhdlrdata->logreached && checkLogCriterion(scip, eventhdlrdata) )
1172  {
1173  eventhdlrdata->logreached = TRUE;
1174  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " Log criterion reached after %lld nodes, %.2f sec.\n",
1175  SCIPgetNNodes(scip), SCIPgetSolvingTime(scip));
1176  }
1177  if( ! eventhdlrdata->rank1reached && checkRankOneTransition(scip, eventhdlrdata) )
1178  {
1179  eventhdlrdata->rank1reached = TRUE;
1180  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " Rank 1 criterion reached after %lld nodes, %.2f sec.\n",
1181  SCIPgetNNodes(scip), SCIPgetSolvingTime(scip));
1182  }
1183 
1184  if( ! eventhdlrdata->estimatereached && checkEstimateCriterion(scip, eventhdlrdata) )
1185  {
1186  eventhdlrdata->estimatereached = TRUE;
1187  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " Estimate criterion reached after %lld nodes, %.2f sec.\n",
1188  SCIPgetNNodes(scip), SCIPgetSolvingTime(scip));
1189  }
1190 
1191  if( ! eventhdlrdata->optimalreached && checkOptimalSolution(scip, eventhdlrdata) )
1192  {
1193  eventhdlrdata->optimalreached = TRUE;
1194  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " Optimum reached after %lld nodes, %.2f sec.\n",
1195  SCIPgetNNodes(scip), SCIPgetSolvingTime(scip));
1196  }
1197 }
1198 
1199 /*
1200  * Callback methods of event handler
1201  */
1202 
1203 /** copy method for event handler (called when SCIP copies plugins) */
1204 /* todo this code needs to stay disabled as long as the soft limit event handler is not copied, because we save
1205  * the soft time limit parameter but this will crash as soon as we are in a SCIP copy */
1206 #ifdef SCIP_DISABLED_CODE
1207 static
1209 { /*lint --e{715}*/
1210  assert(scip != NULL);
1211  assert(eventhdlr != NULL);
1212  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
1213 
1214  /* call inclusion method of event handler */
1216 
1217  return SCIP_OKAY;
1218 }
1219 #else
1220 #define eventCopySolvingphase NULL
1221 #endif
1222 
1223 /** destructor of event handler to free user data (called when SCIP is exiting) */
1224 static
1225 SCIP_DECL_EVENTFREE(eventFreeSolvingphase)
1227  SCIP_EVENTHDLRDATA* eventhdlrdata;
1228 
1229  assert(scip != NULL);
1230  assert(eventhdlr != NULL);
1231  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
1232 
1233  eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
1234  assert(eventhdlrdata != NULL);
1235 
1236  SCIPregressionFree(&eventhdlrdata->regression);
1237 
1238  SCIPfreeBlockMemory(scip, &eventhdlrdata);
1239  SCIPeventhdlrSetData(eventhdlr, NULL);
1240 
1241  return SCIP_OKAY;
1242 }
1243 
1244 /** initialization method of event handler (called after problem was transformed) */
1245 static
1246 SCIP_DECL_EVENTINITSOL(eventInitsolSolvingphase)
1247 { /*lint --e{715}*/
1248 
1249  SCIP_EVENTHDLRDATA* eventhdlrdata;
1250  assert(scip != NULL);
1251  eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
1252  eventhdlrdata->depthinfos = NULL;
1253  eventhdlrdata->maxdepth = 0;
1254  eventhdlrdata->nnodesbelowincumbent = 0;
1255  eventhdlrdata->nnodesleft = 0;
1256  eventhdlrdata->nrank1nodes = 0;
1257  eventhdlrdata->lastndelayedcutoffs = SCIPgetNDelayedCutoffs(scip);
1258  eventhdlrdata->newbestsol = FALSE;
1259 
1260  return SCIP_OKAY;
1261 }
1262 
1263 /** solving process deinitialization method of event handler (called before branch and bound process data is freed) */
1264 static
1265 SCIP_DECL_EVENTEXITSOL(eventExitsolSolvingphase)
1267  SCIP_EVENTHDLRDATA* eventhdlrdata;
1268 
1269  assert(scip != NULL);
1270  eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
1271 
1272  /* free all data storage acquired during this branch-and-bound run */
1273  if( eventhdlrdata->maxdepth > 0 )
1274  {
1275  int c;
1276 
1277  /* free depth information */
1278  for( c = 0; c < eventhdlrdata->maxdepth; ++c )
1279  {
1280  SCIP_CALL( freeDepthinfo(scip, &(eventhdlrdata->depthinfos[c])) );
1281  }
1282 
1283  /* free depth information array */
1284  SCIPfreeBlockMemoryArray(scip, &eventhdlrdata->depthinfos, eventhdlrdata->maxdepth);
1285  eventhdlrdata->maxdepth = 0;
1286  }
1287 
1288  return SCIP_OKAY;
1289 }
1290 
1291 /** collects all parameters that are set to non-default values and stores them in eventhdlrdata */
1292 static
1294  SCIP* scip, /**< SCIP data structure */
1295  SCIP_EVENTHDLRDATA* eventhdlrdata /**< data of event handler */
1296  )
1297 {
1298  SCIP_PARAM** params;
1299  int nparams;
1300  int p;
1301 
1302  params = SCIPgetParams(scip);
1303  nparams = SCIPgetNParams(scip);
1304 
1305  eventhdlrdata->nnondefaultparams = 0;
1306  eventhdlrdata->nondefaultparams = NULL;
1307  eventhdlrdata->nondefaultparamssize = 0;
1308 
1309  /* loop over parameters and store the non-default ones */
1310  for( p = 0; p < nparams; ++p )
1311  {
1312  SCIP_PARAM* param = params[p];
1313 
1314  /* collect parameter if it is nondefault */
1315  if( ! SCIPparamIsDefault(param) )
1316  {
1317  if( eventhdlrdata->nnondefaultparams == 0 )
1318  {
1319  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &eventhdlrdata->nondefaultparams, 8) );
1320  eventhdlrdata->nondefaultparamssize = 8;
1321  }
1322  else if( eventhdlrdata->nnondefaultparams == eventhdlrdata->nondefaultparamssize )
1323  {
1324  eventhdlrdata->nondefaultparamssize *= 2;
1325  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &eventhdlrdata->nondefaultparams,
1326  eventhdlrdata->nnondefaultparams, eventhdlrdata->nondefaultparamssize) );
1327 
1328  }
1329 
1330  eventhdlrdata->nondefaultparams[eventhdlrdata->nnondefaultparams++] = param;
1331  }
1332  }
1333 
1334 
1335  return SCIP_OKAY;
1336 }
1337 
1338 /** initialization method of event handler (called after problem was transformed) */
1339 static
1340 SCIP_DECL_EVENTINIT(eventInitSolvingphase)
1341 { /*lint --e{715}*/
1342  SCIP_EVENTHDLRDATA* eventhdlrdata;
1343 
1344  assert(scip != NULL);
1345  assert(eventhdlr != NULL);
1346  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
1347 
1348  eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
1349  assert(eventhdlrdata != NULL);
1350 
1351  /* initialize the solving phase */
1352  eventhdlrdata->solvingphase = SOLVINGPHASE_UNINITIALIZED;
1353 
1354  /* none of the transitions is reached yet */
1355  eventhdlrdata->optimalreached = FALSE;
1356  eventhdlrdata->logreached = FALSE;
1357  eventhdlrdata->rank1reached = FALSE;
1358  eventhdlrdata->estimatereached = FALSE;
1359  eventhdlrdata->nnondefaultparams = 0;
1360  eventhdlrdata->nondefaultparams = NULL;
1361  eventhdlrdata->nondefaultparamssize = 0;
1362 
1363  /* apply solving phase for the first time after problem was transformed to apply settings for the feasibility phase */
1364  if( eventhdlrdata->enabled )
1365  {
1366  /* collect non-default parameters */
1367  SCIP_CALL( collectNondefaultParams(scip, eventhdlrdata) );
1368 
1369  SCIP_CALL( applySolvingPhase(scip, eventhdlrdata) );
1370  }
1371 
1372  /* only start catching events if event handler is enabled or in test mode */
1373  if( eventhdlrdata->enabled || eventhdlrdata->testmode )
1374  {
1375  SCIP_CALL( SCIPcatchEvent(scip, EVENTHDLR_EVENT, eventhdlr, NULL, &eventhdlrdata->eventfilterpos) );
1376  }
1377 
1378  /* reset solving regression */
1379  SCIPregressionReset(eventhdlrdata->regression);
1380  eventhdlrdata->lastx = SCIP_INVALID;
1381  eventhdlrdata->lasty = SCIP_INVALID;
1382 
1383  return SCIP_OKAY;
1384 }
1385 /** deinitialization method of event handler (called before problem is freed) */
1386 static
1387 SCIP_DECL_EVENTEXIT(eventExitSolvingphase)
1389  SCIP_EVENTHDLRDATA* eventhdlrdata;
1390 
1391  assert(scip != NULL);
1392  assert(eventhdlr != NULL);
1393  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
1394 
1395  eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
1396  assert(eventhdlrdata != NULL);
1397 
1398  /* free collected, non-default parameters */
1399  SCIPfreeBlockMemoryArrayNull(scip, &eventhdlrdata->nondefaultparams, eventhdlrdata->nondefaultparamssize);
1400 
1401  return SCIP_OKAY;
1402 }
1403 
1404 
1405 /** execution method of event handler */
1406 static
1407 SCIP_DECL_EVENTEXEC(eventExecSolvingphase)
1408 { /*lint --e{715}*/
1409  SCIP_EVENTHDLRDATA* eventhdlrdata;
1410  SCIP_EVENTTYPE eventtype;
1411 
1412  assert(scip != NULL);
1413  assert(eventhdlr != NULL);
1414 
1415  eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
1416  eventtype = SCIPeventGetType(event);
1417  assert(eventtype & (EVENTHDLR_EVENT));
1418  assert(eventtype != SCIP_EVENTTYPE_NODEFOCUSED || SCIPeventGetNode(event) == SCIPgetCurrentNode(scip));
1419 
1420 
1421  /* update data structures depending on the event */
1422  SCIP_CALL( updateDataStructures(scip, eventhdlrdata, eventtype) );
1423 
1424  /* if the phase-based solver is enabled, we check if a phase transition occurred and alter the settings accordingly */
1425  if( eventhdlrdata->enabled )
1426  {
1427  SCIP_CALL( applySolvingPhase(scip, eventhdlrdata) );
1428  }
1429 
1430 
1431  /* in test mode, we check every transition criterion */
1432  if( eventhdlrdata->testmode )
1433  {
1434  testCriteria(scip, eventhdlrdata);
1435  }
1436 
1437  return SCIP_OKAY;
1438 }
1439 
1440 /*
1441  * displays that come with this event handler
1442  */
1443 
1444 /* defines for the rank 1 node display */
1445 #define DISP_NAME_NRANK1NODES "nrank1nodes"
1446 #define DISP_DESC_NRANK1NODES "current number of rank1 nodes left"
1447 #define DISP_HEAD_NRANK1NODES "rank1"
1448 #define DISP_WIDT_NRANK1NODES 7
1449 #define DISP_PRIO_NRANK1NODES 40000
1450 #define DISP_POSI_NRANK1NODES 500
1451 #define DISP_STRI_NRANK1NODES TRUE
1453 /** output method of display column to output file stream 'file' */
1454 static
1455 SCIP_DECL_DISPOUTPUT(dispOutputNRank1Nodes)
1457  assert(disp != NULL);
1458  assert(strcmp(SCIPdispGetName(disp), DISP_NAME_NRANK1NODES) == 0);
1459  assert(scip != NULL);
1460 
1461  /* ouput number of rank 1 nodes */
1463 
1464  return SCIP_OKAY;
1465 }
1466 
1467 /* display for the number of nodes below the current incumbent */
1468 #define DISP_NAME_NNODESBELOWINC "nnodesbelowinc"
1469 #define DISP_DESC_NNODESBELOWINC "current number of nodes with an estimate better than the current incumbent"
1470 #define DISP_HEAD_NNODESBELOWINC "nbInc"
1471 #define DISP_WIDT_NNODESBELOWINC 6
1472 #define DISP_PRIO_NNODESBELOWINC 40000
1473 #define DISP_POSI_NNODESBELOWINC 550
1474 #define DISP_STRI_NNODESBELOWINC TRUE
1476 /** output method of display column to output file stream 'file' */
1477 static
1478 SCIP_DECL_DISPOUTPUT(dispOutputNnodesbelowinc)
1480  assert(disp != NULL);
1481  assert(strcmp(SCIPdispGetName(disp), DISP_NAME_NNODESBELOWINC) == 0);
1482  assert(scip != NULL);
1483 
1484  /* display the number of nodes with an estimate below the the current incumbent */
1486 
1487  return SCIP_OKAY;
1488 }
1489 
1490 /** creates event handler for Solvingphase event */
1492  SCIP* scip /**< SCIP data structure */
1493  )
1494 {
1495  SCIP_EVENTHDLRDATA* eventhdlrdata;
1496  SCIP_EVENTHDLR* eventhdlr;
1497 
1498  /* create solving phase event handler data */
1499  eventhdlrdata = NULL;
1500  SCIP_CALL( SCIPallocBlockMemory(scip, &eventhdlrdata) );
1501  assert(eventhdlrdata != NULL);
1502 
1503  eventhdlrdata->feassetname = NULL;
1504  eventhdlrdata->improvesetname = NULL;
1505  eventhdlrdata->proofsetname = NULL;
1506 
1507  eventhdlrdata->depthinfos = NULL;
1508  eventhdlrdata->maxdepth = 0;
1509  eventhdlrdata->eventfilterpos = -1;
1510 
1511  /* create a regression */
1512  eventhdlrdata->regression = NULL;
1513  SCIP_CALL( SCIPregressionCreate(&eventhdlrdata->regression) );
1514 
1515  eventhdlr = NULL;
1516 
1517  /* include event handler into SCIP */
1519  eventExecSolvingphase, eventhdlrdata) );
1520  assert(eventhdlr != NULL);
1521 
1522  /* include the new displays into scip */
1529 
1530  /* set non fundamental callbacks via setter functions */
1532  SCIP_CALL( SCIPsetEventhdlrFree(scip, eventhdlr, eventFreeSolvingphase) );
1533  SCIP_CALL( SCIPsetEventhdlrInit(scip, eventhdlr, eventInitSolvingphase) );
1534  SCIP_CALL( SCIPsetEventhdlrExit(scip, eventhdlr, eventExitSolvingphase) );
1535  SCIP_CALL( SCIPsetEventhdlrInitsol(scip, eventhdlr, eventInitsolSolvingphase) );
1536  SCIP_CALL( SCIPsetEventhdlrExitsol(scip, eventhdlr, eventExitsolSolvingphase) );
1537 
1538  /* add Solvingphase event handler parameters */
1539  SCIP_CALL( SCIPaddBoolParam(scip, EVENTHDLR_NAME "s/enabled", "should the event handler adapt the solver behavior?",
1540  &eventhdlrdata->enabled, FALSE, DEFAULT_ENABLED, NULL, NULL) );
1541 
1542  SCIP_CALL( SCIPaddBoolParam(scip, EVENTHDLR_NAME "s/testmode", "should the event handler test all phase transitions?",
1543  &eventhdlrdata->testmode, FALSE, DEFAULT_TESTMODE, NULL, NULL) );
1544 
1545  SCIP_CALL( SCIPaddStringParam(scip, EVENTHDLR_NAME "s/feassetname", "settings file for feasibility phase -- precedence over emphasis settings",
1546  &eventhdlrdata->feassetname, FALSE, DEFAULT_SETNAME, NULL, NULL) );
1547 
1548  SCIP_CALL( SCIPaddStringParam(scip, EVENTHDLR_NAME "s/improvesetname", "settings file for improvement phase -- precedence over emphasis settings",
1549  &eventhdlrdata->improvesetname, FALSE, DEFAULT_SETNAME, NULL, NULL) );
1550 
1551  SCIP_CALL( SCIPaddStringParam(scip, EVENTHDLR_NAME "s/proofsetname", "settings file for proof phase -- precedence over emphasis settings",
1552  &eventhdlrdata->proofsetname, FALSE, DEFAULT_SETNAME, NULL, NULL) );
1553 
1554  SCIP_CALL( SCIPaddLongintParam(scip, EVENTHDLR_NAME "s/nodeoffset", "node offset for rank-1 and estimate transitions", &eventhdlrdata->nodeoffset,
1556  SCIP_CALL( SCIPaddBoolParam(scip, EVENTHDLR_NAME "s/fallback", "should the event handler fall back from optimal phase?",
1557  &eventhdlrdata->fallback, FALSE, DEFAULT_FALLBACK, NULL, NULL) );
1558  SCIP_CALL( SCIPaddCharParam(scip ,EVENTHDLR_NAME "s/transitionmethod",
1559  "transition method: Possible options are 'e'stimate,'l'ogarithmic regression,'o'ptimal-value based,'r'ank-1",
1560  &eventhdlrdata->transitionmethod, FALSE, DEFAULT_TRANSITIONMETHOD, TRANSITIONMETHODS, NULL, NULL) );
1561  SCIP_CALL( SCIPaddBoolParam(scip, EVENTHDLR_NAME "s/interruptoptimal",
1562  "should the event handler interrupt the solving process after optimal solution was found?",
1563  &eventhdlrdata->interruptoptimal, FALSE, DEFAULT_INTERRUPTOPTIMAL, NULL, NULL) );
1564 
1565  SCIP_CALL( SCIPaddBoolParam(scip, EVENTHDLR_NAME "s/userestart1to2",
1566  "should a restart be applied between the feasibility and improvement phase?",
1567  &eventhdlrdata->userestart1to2, FALSE, DEFAULT_USERESTART1TO2, NULL, NULL) );
1568 
1569  SCIP_CALL( SCIPaddBoolParam(scip, EVENTHDLR_NAME "s/userestart2to3",
1570  "should a restart be applied between the improvement and the proof phase?",
1571  &eventhdlrdata->userestart2to3, FALSE, DEFAULT_USERESTART2TO3, NULL, NULL) );
1572 
1573  SCIP_CALL(SCIPaddRealParam(scip, EVENTHDLR_NAME "s/optimalvalue", "optimal solution value for problem",
1574  &eventhdlrdata->optimalvalue, FALSE, SCIP_INVALID, SCIP_REAL_MIN, SCIP_REAL_MAX, NULL, NULL) );
1575 
1576  /* add parameter for logarithmic regression */
1577  SCIP_CALL( SCIPaddCharParam(scip, EVENTHDLR_NAME "s/xtype", "x-type for logarithmic regression - (t)ime, (n)odes, (l)p iterations",
1578  &eventhdlrdata->logregression_xtype, FALSE, DEFAULT_LOGREGRESSION_XTYPE, LOGREGRESSION_XTYPES, NULL, NULL) );
1579 
1580  SCIP_CALL( SCIPaddBoolParam(scip, EVENTHDLR_NAME "s/useemphsettings",
1581  "should emphasis settings for the solving phases be used, or settings files?",
1582  &eventhdlrdata->useemphsettings, FALSE, DEFAULT_USEEMPHSETTINGS, NULL, NULL) );
1583 
1584  return SCIP_OKAY;
1585 }
static SCIP_RETCODE recomputeNodeInformation(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip.h:21909
static SCIP_RETCODE applySolvingPhase(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
#define DISP_HEAD_NRANK1NODES
SCIP_Real SCIPgetFirstPrimalBound(SCIP *scip)
Definition: scip.c:42426
SCIP_PARAM ** SCIPgetParams(SCIP *scip)
Definition: scip.c:5115
#define TRANSITIONMETHODS
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip.h:21898
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
Definition: scip.c:45137
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:21892
static SCIP_RETCODE fixOrUnfixRelevantParameters(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata, SCIP_Bool fix)
SCIP_RETCODE SCIPsetEventhdlrInitsol(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTINITSOL((*eventinitsol)))
Definition: scip.c:8614
#define DISP_HEAD_NNODESBELOWINC
SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
Definition: scip.c:40453
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:814
#define DISP_NAME_NRANK1NODES
static SCIP_Bool transitionPhase3(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
Definition: scip.c:41382
static void removeNode(SCIP_NODE *node, SCIP_EVENTHDLRDATA *eventhdlrdata)
static SCIP_RETCODE adaptSolverBehavior(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
static SCIP_Bool checkRankOneTransition(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
#define DISP_WIDT_NNODESBELOWINC
SCIP_Real SCIPgetPrimalbound(SCIP *scip)
Definition: scip.c:42448
static SCIP_RETCODE freeDepthinfo(SCIP *scip, DEPTHINFO **depthinfo)
SCIP_RETCODE SCIPgetLeaves(SCIP *scip, SCIP_NODE ***leaves, int *nleaves)
Definition: scip.c:40610
SCIP_RETCODE SCIPsetEventhdlrExitsol(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTEXITSOL((*eventexitsol)))
Definition: scip.c:8628
#define DEFAULT_USERESTART1TO2
SCIP_RETCODE SCIPsetEventhdlrExit(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTEXIT((*eventexit)))
Definition: scip.c:8600
#define DEFAULT_TESTMODE
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:45803
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:8526
struct SCIP_EventhdlrData SCIP_EVENTHDLRDATA
Definition: type_event.h:138
SCIP_RETCODE SCIPgetOpenNodesData(SCIP *scip, SCIP_NODE ***leaves, SCIP_NODE ***children, SCIP_NODE ***siblings, int *nleaves, int *nchildren, int *nsiblings)
Definition: scip.c:40760
#define FALSE
Definition: def.h:64
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:278
static SCIP_Real getCurrentRegressionTangentAxisIntercept(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
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.c:4230
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:45816
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:45888
#define TRUE
Definition: def.h:63
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
static SCIP_RETCODE addNodesInformation(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata, SCIP_NODE **nodes, int nnodes)
#define SCIP_EVENTTYPE_NODEFOCUSED
Definition: type_event.h:77
#define DEFAULT_FALLBACK
SCIP_Real minestimate
#define EVENTHDLR_NAME
const char * SCIPparamGetName(SCIP_PARAM *param)
Definition: paramset.c:641
SCIP_Real SCIPregressionGetIntercept(SCIP_REGRESSION *regression)
Definition: misc.c:262
int SCIPgetNNodesLeft(SCIP *scip)
Definition: scip.c:41227
void SCIPregressionAddObservation(SCIP_REGRESSION *regression, SCIP_Real x, SCIP_Real y)
Definition: misc.c:369
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:21907
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.c:4313
SCIP_Bool SCIPparamIsDefault(SCIP_PARAM *param)
Definition: paramset.c:918
SCIP_EVENTHDLR * SCIPfindEventhdlr(SCIP *scip, const char *name)
Definition: scip.c:8656
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip.c:1228
#define DEFAULT_NODEOFFSET
static SCIP_DECL_EVENTEXEC(eventExecSolvingphase)
#define DISP_POSI_NNODESBELOWINC
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:45751
int SCIPnodeGetDepth(SCIP_NODE *node)
Definition: tree.c:7153
#define DEFAULT_ENABLED
#define SCIP_LONGINT_MAX
Definition: def.h:121
static SCIP_RETCODE changeEmphasisParameters(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:21890
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1260
#define SCIPdebugMsg
Definition: scip.h:451
void SCIPdispInt(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, int val, int width)
Definition: disp.c:575
static int checkLeavesBelowIncumbent(SCIP *scip)
static SCIP_Bool checkEstimateCriterion(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
SCIP_RETCODE SCIPgetSiblings(SCIP *scip, SCIP_NODE ***siblings, int *nsiblings)
Definition: scip.c:40568
void SCIPeventhdlrSetData(SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: event.c:298
#define SCIP_EVENTTYPE_NODEBRANCHED
Definition: type_event.h:80
static SCIP_DECL_SORTPTRCOMP(sortCompTreeinfo)
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:7143
static SCIP_RETCODE ensureDepthInfoArraySize(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata, SCIP_NODE *node)
void SCIPregressionRemoveObservation(SCIP_REGRESSION *regression, SCIP_Real x, SCIP_Real y)
Definition: misc.c:337
void SCIPsortedvecDelPosPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int pos, int *len)
#define EVENTHDLR_DESC
SCIP_NODE ** minnodes
enum SolvingPhase SOLVINGPHASE
SCIP_RETCODE SCIPsetEventhdlrFree(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTFREE((*eventfree)))
Definition: scip.c:8572
SCIP_RETCODE SCIPsetEventhdlrCopy(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTCOPY((*eventcopy)))
Definition: scip.c:8558
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:45764
static SCIP_Real getX(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
SCIP_RETCODE SCIPgetChildren(SCIP *scip, SCIP_NODE ***children, int *nchildren)
Definition: scip.c:40526
SCIP_NODE * SCIPeventGetNode(SCIP_EVENT *event)
Definition: event.c:1186
SCIP_RETCODE SCIPsetEventhdlrInit(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTINIT((*eventinit)))
Definition: scip.c:8586
SCIP_Bool SCIPparamIsFixed(SCIP_PARAM *param)
Definition: paramset.c:681
SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
#define DISP_DESC_NNODESBELOWINC
int SCIPgetNChildren(SCIP *scip)
Definition: scip.c:40550
#define DISP_PRIO_NNODESBELOWINC
static SCIP_RETCODE collectNondefaultParams(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
SCIP_Longint SCIPgetNDelayedCutoffs(SCIP *scip)
Definition: scip.c:41336
#define NULL
Definition: lpi_spx1.cpp:137
static int getNNodesBelowIncumbent(SCIP *scip)
#define REALABS(x)
Definition: def.h:159
SCIP_RETCODE SCIPunfixParam(SCIP *scip, const char *name)
Definition: scip.c:4504
static SCIP_DECL_DISPOUTPUT(dispOutputNRank1Nodes)
#define DISP_POSI_NRANK1NODES
#define SCIP_CALL(x)
Definition: def.h:306
SCIP_Longint SCIPgetNTotalNodes(SCIP *scip)
Definition: scip.c:41209
SCIP_RETCODE SCIPsetEmphasis(SCIP *scip, SCIP_PARAMEMPHASIS paramemphasis, SCIP_Bool quiet)
Definition: scip.c:4998
static SCIP_RETCODE updateLogRegression(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip.c:1353
#define DEFAULT_SETNAME
void SCIPregressionFree(SCIP_REGRESSION **regression)
Definition: misc.c:420
#define DEFAULT_INTERRUPTOPTIMAL
public data structures and miscellaneous methods
#define DISP_STRI_NNODESBELOWINC
#define DEFAULT_LOGREGRESSION_XTYPE
#define SCIP_Bool
Definition: def.h:61
SCIP_RETCODE SCIPcatchEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:40207
static SCIP_DECL_EVENTFREE(eventFreeSolvingphase)
SCIP_RETCODE SCIPincludeDisp(SCIP *scip, const char *name, const char *desc, const char *header, SCIP_DISPSTATUS dispstatus, SCIP_DECL_DISPCOPY((*dispcopy)), SCIP_DECL_DISPFREE((*dispfree)), SCIP_DECL_DISPINIT((*dispinit)), SCIP_DECL_DISPEXIT((*dispexit)), SCIP_DECL_DISPINITSOL((*dispinitsol)), SCIP_DECL_DISPEXITSOL((*dispexitsol)), SCIP_DECL_DISPOUTPUT((*dispoutput)), SCIP_DISPDATA *dispdata, int width, int priority, int position, SCIP_Bool stripline)
Definition: scip.c:9266
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:959
static SCIP_DECL_EVENTINITSOL(eventInitsolSolvingphase)
SolvingPhase
#define MAX(x, y)
Definition: tclique_def.h:75
#define DISP_STRI_NRANK1NODES
static SCIP_RETCODE createDepthinfo(SCIP *scip, DEPTHINFO **depthinfo)
int SCIPgetNSols(SCIP *scip)
Definition: scip.c:38832
SCIPInterval log(const SCIPInterval &x)
void SCIPsortedvecInsertPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *keyval, int *len, int *pos)
eventhdlr for solving phase dependent parameter adjustment
SCIP_RETCODE SCIPfixParam(SCIP *scip, const char *name)
Definition: scip.c:4486
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:45827
static int getNRank1Nodes(SCIP *scip)
#define DEFAULT_USERESTART2TO3
static SCIP_DECL_EVENTEXIT(eventExitSolvingphase)
enum SCIP_ParamEmphasis SCIP_PARAMEMPHASIS
Definition: type_paramset.h:73
#define SCIP_REAL_MAX
Definition: def.h:136
SCIP_Real SCIPnodeGetEstimate(SCIP_NODE *node)
Definition: tree.c:7173
#define SCIP_REAL_MIN
Definition: def.h:137
#define DISP_WIDT_NRANK1NODES
#define SCIP_EVENTTYPE_BESTSOLFOUND
Definition: type_event.h:88
#define DISP_NAME_NNODESBELOWINC
static SCIP_RETCODE releaseNodeInformation(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata, SCIP_NODE *node)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:45790
SCIP_RETCODE SCIPaddCharParam(SCIP *scip, const char *name, const char *desc, char *valueptr, SCIP_Bool isadvanced, char defaultvalue, const char *allowedvalues, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4286
#define EVENTHDLR_EVENT
SCIP_RETCODE SCIPrestartSolve(SCIP *scip)
Definition: scip.c:16968
SCIP_RETCODE SCIPreadParams(SCIP *scip, const char *filename)
Definition: scip.c:4889
SCIP_Real SCIPregressionGetSlope(SCIP_REGRESSION *regression)
Definition: misc.c:252
SCIP_NODETYPE SCIPnodeGetType(SCIP_NODE *node)
Definition: tree.c:7133
#define SCIP_Real
Definition: def.h:135
#define DEFAULT_USEEMPHSETTINGS
#define SCIP_DECL_EVENTCOPY(x)
Definition: type_event.h:165
SCIP_RETCODE SCIPincludeEventHdlrSolvingphase(SCIP *scip)
#define SCIP_INVALID
Definition: def.h:155
static SCIP_RETCODE updateDataStructures(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata, SCIP_EVENTTYPE eventtype)
#define SCIP_Longint
Definition: def.h:120
void SCIPregressionReset(SCIP_REGRESSION *regression)
Definition: misc.c:388
static void determineSolvingPhase(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
#define nnodes
Definition: gastrans.c:65
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip.h:21910
#define eventCopySolvingphase
SCIP_RETCODE SCIPregressionCreate(SCIP_REGRESSION **regression)
Definition: misc.c:404
SCIP_RETCODE SCIPinterruptSolve(SCIP *scip)
Definition: scip.c:16942
SCIP_Real SCIPgetUpperbound(SCIP *scip)
Definition: scip.c:42472
#define DEFAULT_TRANSITIONMETHOD
static void releaseNodeFromDepthInfo(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata, SCIP_NODE *node)
static SCIP_RETCODE changeParametersUsingSettingsFiles(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
SCIP_EVENTHDLRDATA * SCIPeventhdlrGetData(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:288
#define DISP_DESC_NRANK1NODES
#define DISP_PRIO_NRANK1NODES
int SCIPregressionGetNObservations(SCIP_REGRESSION *regression)
Definition: misc.c:242
SCIP_Longint SCIPgetNNodes(SCIP *scip)
Definition: scip.c:41182
#define SCIPABORT()
Definition: def.h:278
const char * SCIPdispGetName(SCIP_DISP *disp)
Definition: disp.c:283
int SCIPgetNParams(SCIP *scip)
Definition: scip.c:5129
static SCIP_DECL_EVENTEXITSOL(eventExitsolSolvingphase)
static SCIP_DECL_EVENTINIT(eventInitSolvingphase)
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4258
static SCIP_Bool checkOptimalSolution(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
#define EPSZ(x, eps)
Definition: def.h:165
#define LOGREGRESSION_XTYPES
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.c:4176
static void testCriteria(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
static SCIP_Bool checkLogCriterion(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:134