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-2018 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  int oldcapacity = depthinfo->minnodescapacity;
214  depthinfo->minnodescapacity *= 2;
215  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &depthinfo->minnodes, oldcapacity, depthinfo->minnodescapacity) );
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  return SCIP_INVALIDCALL;
880  }
881 
882  assert(paramfilename != NULL);
883 
884  /* return if no there is no user-specified settings file for the current phase */
885  if( strcmp(paramfilename, DEFAULT_SETNAME) == 0 )
886  return SCIP_OKAY;
887 
888  file = fopen(paramfilename, "r");
889 
890  /* test if file could be found and print a warning if not */
891  if( file == NULL )
892  {
893  SCIPwarningMessage(scip, "Parameter file <%s> not found--keeping settings as before.\n", paramfilename);
894  }
895  else
896  {
897  /* we can close the file */
898  fclose(file);
899 
900  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Reading parameters from file <%s>\n", paramfilename);
901 
902  SCIP_CALL( SCIPreadParams(scip, paramfilename) );
903  }
904 
905  return SCIP_OKAY;
906 }
907 
908 /** fix/unfix relevant solving parameters that should not accidentally be set to default values */
909 static
911  SCIP* scip, /**< SCIP data structure */
912  SCIP_EVENTHDLRDATA* eventhdlrdata, /**< event handler data */
913  SCIP_Bool fix /**< should the parameters be fixed (true) or unfixed? */
914  )
915 {
916  int p;
917  const char* relevantparams[] = {
918  "limits/time",
919  "limits/nodes",
920  "limits/totalnodes",
921  "limits/stallnodes",
922  "limits/memory",
923  "limits/gap",
924  "limits/absgap",
925  "limits/solutions",
926  "limits/bestsol",
927  "limits/maxsol",
928  "limits/maxorigsol",
929  "limits/restarts",
930  "limits/autorestartnodes",
931  "limits/softtime",
932  "solvingphases/enabled",
933  "solvingphases/fallback",
934  "solvingphases/interruptoptimal",
935  "solvingphases/nodeoffset",
936  "solvingphases/feassetname",
937  "solvingphases/proofsetname",
938  "solvingphases/optimalvalue",
939  "solvingphases/improvesetname",
940  "solvingphases/testmode",
941  "solvingphases/transitionmethod",
942  "solvingphases/useemphsettings",
943  "solvingphases/userestart1to2",
944  "solvingphases/userestart2to3",
945  "solvingphases/xtype"
946  };
947  int nrelevantparams = 28;
948 
949  /* fix or unfix all specified limit parameters */
950  for( p = 0; p < nrelevantparams; ++p )
951  {
952  if( fix )
953  {
954  SCIP_CALL( SCIPfixParam(scip, relevantparams[p]) );
955  }
956  else
957  {
958  SCIP_CALL( SCIPunfixParam(scip, relevantparams[p]) );
959  }
960  }
961 
962  /* fix or unfix all collected, non-default parameters after problem transformation */
963  for( p = 0; p < eventhdlrdata->nnondefaultparams; ++p )
964  {
965  if( fix && ! SCIPparamIsFixed(eventhdlrdata->nondefaultparams[p]) )
966  {
967  SCIP_CALL( SCIPfixParam(scip, SCIPparamGetName(eventhdlrdata->nondefaultparams[p])) );
968  }
969  else if( ! fix && SCIPparamIsFixed(eventhdlrdata->nondefaultparams[p]) )
970  {
971  SCIP_CALL( SCIPunfixParam(scip, SCIPparamGetName(eventhdlrdata->nondefaultparams[p])) );
972  }
973  }
974 
975  return SCIP_OKAY;
976 }
977 
978 /** change settings depending whether emphasis settings should be used, or settings files */
979 static
981  SCIP* scip, /**< SCIP data structure */
982  SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
983  )
984 {
985  /* fix relevant parameters such that they are not overwritten */
986  SCIP_CALL( fixOrUnfixRelevantParameters(scip, eventhdlrdata, TRUE) );
987 
988  /* change settings using emphasis */
989  if( eventhdlrdata->useemphsettings )
990  {
991  SCIP_CALL( changeEmphasisParameters(scip, eventhdlrdata) );
992  }
993  else
994  {
995  /* reset to default settings; this happens automatically when using emphasis settings */
997  }
998 
999  /* read optional, phase-specific settings */
1000  SCIP_CALL( changeParametersUsingSettingsFiles(scip, eventhdlrdata) );
1001 
1002  /* unfix relevant parameters that have been fixed for changing emphasis */
1003  SCIP_CALL( fixOrUnfixRelevantParameters(scip, eventhdlrdata, FALSE) );
1004 
1005  return SCIP_OKAY;
1006 }
1007 
1008 /* apply the user-specified phase-based settings: A phase transition invokes the read of phase-specific settings from a file */
1009 static
1011  SCIP* scip, /**< SCIP data structure */
1012  SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
1013  )
1014 {
1015  SOLVINGPHASE oldsolvingphase;
1016  SCIP_Bool restart;
1017 
1018  /* return immediately if we are in the proof phase */
1019  if( eventhdlrdata->solvingphase == SOLVINGPHASE_PROOF && !eventhdlrdata->fallback )
1020  return SCIP_OKAY;
1021 
1022  /* save current solving phase */
1023  oldsolvingphase = eventhdlrdata->solvingphase;
1024 
1025  /* determine current solving phase */
1026  determineSolvingPhase(scip, eventhdlrdata);
1027 
1028 
1029  /* nothing has changed */
1030  if( oldsolvingphase == eventhdlrdata->solvingphase )
1031  return SCIP_OKAY;
1032 
1033 
1034  /* check if the solving process should be interrupted when the current solution is optimal */
1035  if( eventhdlrdata->solvingphase == SOLVINGPHASE_PROOF && eventhdlrdata->transitionmethod == 'o' &&
1036  eventhdlrdata->interruptoptimal )
1037  {
1038  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Solution is optimal. Calling user interruption.\n");
1039 
1040  /* we call interrupt solve but do not return yet because user-specified settings for the proof phase are applied first */
1041  SCIP_CALL( SCIPinterruptSolve(scip) );
1042  }
1043 
1044  /* check if a restart should be performed after phase transition */
1045  if( eventhdlrdata->solvingphase == SOLVINGPHASE_IMPROVEMENT && eventhdlrdata->userestart1to2 )
1046  restart = TRUE;
1047  else if( eventhdlrdata->solvingphase == SOLVINGPHASE_PROOF && eventhdlrdata->userestart2to3 )
1048  restart = TRUE;
1049  else
1050  restart = FALSE;
1051 
1052  /* inform SCIP that a restart should be performed */
1053  if( restart )
1054  {
1055  SCIP_CALL( SCIPrestartSolve(scip) );
1056  }
1057 
1058  /* change general solving settings depending on solving strategy */
1059  SCIP_CALL( adaptSolverBehavior(scip, eventhdlrdata) );
1060 
1061  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL,"Changed solving phase to phase %d.\n", eventhdlrdata->solvingphase);
1062 
1063  return SCIP_OKAY;
1064 
1065 }
1066 
1067 /** update the logarithmic regression */
1068 static
1070  SCIP* scip, /**< SCIP data structure */
1071  SCIP_EVENTHDLRDATA* eventhdlrdata /**< data of event handler */
1072  )
1073 {
1074  SCIP_Real regressionx;
1075  SCIP_Real regressiony;
1076 
1077  regressionx = getX(scip, eventhdlrdata);
1078  regressiony = SCIPgetPrimalbound(scip);
1079 
1080  /* remove the last observation if it has been observed at the same x */
1081  if( SCIPisEQ(scip, eventhdlrdata->lastx, regressionx) )
1082  {
1083  SCIPregressionRemoveObservation(eventhdlrdata->regression, eventhdlrdata->lastx, eventhdlrdata->lasty);
1084  }
1085 
1086  /* add the new observation to the regression and save it if another update is necessary */
1087  SCIPregressionAddObservation(eventhdlrdata->regression, regressionx, regressiony);
1088  eventhdlrdata->lastx = regressionx;
1089  eventhdlrdata->lasty = regressiony;
1090 
1091  return SCIP_OKAY;
1092 }
1093 
1094 /** update data structures based on the event type caught */
1095 static
1097  SCIP* scip, /**< SCIP data structure */
1098  SCIP_EVENTHDLRDATA* eventhdlrdata, /**< data of event handler */
1099  SCIP_EVENTTYPE eventtype /**< type of the caught event */
1100  )
1101 {
1102  SCIP_NODE** children;
1103  int nchildren;
1104 
1105  switch( eventtype )
1106  {
1107  /* store that a new best solution was found, but delay the update of node information until a node was solved */
1109  eventhdlrdata->newbestsol = TRUE;
1110 
1111  /* update logarithmic regression of solution process */
1112  SCIP_CALL( updateLogRegression(scip, eventhdlrdata) );
1113 
1114  break;
1115 
1116  /* release the focus node from the open node data structures */
1118  assert(SCIPgetStage(scip) == SCIP_STAGE_SOLVING);
1119 
1120  SCIP_CALL( releaseNodeInformation(scip, eventhdlrdata, SCIPgetCurrentNode(scip)));
1121  assert(eventhdlrdata->nnodesbelowincumbent <= SCIPgetNNodesLeft(scip));
1122 
1123  break;
1124 
1125  /* store node information for child nodes */
1127  assert(SCIPgetStage(scip) == SCIP_STAGE_SOLVING);
1128 
1129  /* if we lost track of exact number of open search nodes, we recompute node information from scratch */
1130  if( eventhdlrdata->newbestsol || eventhdlrdata->nnodesleft + SCIPgetNChildren(scip) != SCIPgetNNodesLeft(scip) )
1131  {
1132  SCIP_CALL( recomputeNodeInformation(scip, eventhdlrdata) );
1133  eventhdlrdata->newbestsol = FALSE;
1134 
1135  return SCIP_OKAY;
1136  }
1137  else
1138  {
1139  SCIP_CALL( SCIPgetChildren(scip, &children, &nchildren) );
1140  SCIP_CALL( addNodesInformation(scip, eventhdlrdata, children, nchildren) );
1141  }
1142 
1143  assert(eventhdlrdata->nnodesleft == SCIPgetNNodesLeft(scip));
1144  break;
1145 
1146  default:
1147  break;
1148  }
1149 
1150  /* ensure that required tree information was correctly computed; only available in solving stage and at the beginning
1151  * or end of a node solution process because we delay the recomputation of the node information)
1152  */
1153  assert(SCIPgetStage(scip) != SCIP_STAGE_SOLVING ||
1154  (eventtype == SCIP_EVENTTYPE_BESTSOLFOUND) ||
1155  (eventhdlrdata->nnodesleft == SCIPgetNNodesLeft(scip) && eventhdlrdata->nnodesbelowincumbent == checkLeavesBelowIncumbent(scip)));
1156 
1157  return SCIP_OKAY;
1158 }
1159 
1160 /** test all criteria whether they have been reached */
1161 static
1162 void testCriteria(
1163  SCIP* scip, /**< SCIP data structure */
1164  SCIP_EVENTHDLRDATA* eventhdlrdata /**< data of event handler */
1165  )
1166 {
1167  assert(scip != NULL);
1168  assert(eventhdlrdata != NULL);
1169 
1170  if( ! eventhdlrdata->logreached && checkLogCriterion(scip, eventhdlrdata) )
1171  {
1172  eventhdlrdata->logreached = TRUE;
1173  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " Log criterion reached after %lld nodes, %.2f sec.\n",
1174  SCIPgetNNodes(scip), SCIPgetSolvingTime(scip));
1175  }
1176  if( ! eventhdlrdata->rank1reached && checkRankOneTransition(scip, eventhdlrdata) )
1177  {
1178  eventhdlrdata->rank1reached = TRUE;
1179  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " Rank 1 criterion reached after %lld nodes, %.2f sec.\n",
1180  SCIPgetNNodes(scip), SCIPgetSolvingTime(scip));
1181  }
1182 
1183  if( ! eventhdlrdata->estimatereached && checkEstimateCriterion(scip, eventhdlrdata) )
1184  {
1185  eventhdlrdata->estimatereached = TRUE;
1186  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " Estimate criterion reached after %lld nodes, %.2f sec.\n",
1187  SCIPgetNNodes(scip), SCIPgetSolvingTime(scip));
1188  }
1189 
1190  if( ! eventhdlrdata->optimalreached && checkOptimalSolution(scip, eventhdlrdata) )
1191  {
1192  eventhdlrdata->optimalreached = TRUE;
1193  SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " Optimum reached after %lld nodes, %.2f sec.\n",
1194  SCIPgetNNodes(scip), SCIPgetSolvingTime(scip));
1195  }
1196 }
1197 
1198 /*
1199  * Callback methods of event handler
1200  */
1201 
1202 /** copy method for event handler (called when SCIP copies plugins) */
1203 /* todo this code needs to stay disabled as long as the soft limit event handler is not copied, because we save
1204  * the soft time limit parameter but this will crash as soon as we are in a SCIP copy */
1205 #ifdef SCIP_DISABLED_CODE
1206 static
1208 { /*lint --e{715}*/
1209  assert(scip != NULL);
1210  assert(eventhdlr != NULL);
1211  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
1212 
1213  /* call inclusion method of event handler */
1215 
1216  return SCIP_OKAY;
1217 }
1218 #else
1219 #define eventCopySolvingphase NULL
1220 #endif
1221 
1222 /** destructor of event handler to free user data (called when SCIP is exiting) */
1223 static
1224 SCIP_DECL_EVENTFREE(eventFreeSolvingphase)
1226  SCIP_EVENTHDLRDATA* eventhdlrdata;
1227 
1228  assert(scip != NULL);
1229  assert(eventhdlr != NULL);
1230  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
1231 
1232  eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
1233  assert(eventhdlrdata != NULL);
1234 
1235  SCIPregressionFree(&eventhdlrdata->regression);
1236 
1237  SCIPfreeBlockMemory(scip, &eventhdlrdata);
1238  SCIPeventhdlrSetData(eventhdlr, NULL);
1239 
1240  return SCIP_OKAY;
1241 }
1242 
1243 /** initialization method of event handler (called after problem was transformed) */
1244 static
1245 SCIP_DECL_EVENTINITSOL(eventInitsolSolvingphase)
1246 { /*lint --e{715}*/
1247 
1248  SCIP_EVENTHDLRDATA* eventhdlrdata;
1249  assert(scip != NULL);
1250  eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
1251  eventhdlrdata->depthinfos = NULL;
1252  eventhdlrdata->maxdepth = 0;
1253  eventhdlrdata->nnodesbelowincumbent = 0;
1254  eventhdlrdata->nnodesleft = 0;
1255  eventhdlrdata->nrank1nodes = 0;
1256  eventhdlrdata->lastndelayedcutoffs = SCIPgetNDelayedCutoffs(scip);
1257  eventhdlrdata->newbestsol = FALSE;
1258 
1259  return SCIP_OKAY;
1260 }
1261 
1262 /** solving process deinitialization method of event handler (called before branch and bound process data is freed) */
1263 static
1264 SCIP_DECL_EVENTEXITSOL(eventExitsolSolvingphase)
1266  SCIP_EVENTHDLRDATA* eventhdlrdata;
1267 
1268  assert(scip != NULL);
1269  eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
1270 
1271  /* free all data storage acquired during this branch-and-bound run */
1272  if( eventhdlrdata->maxdepth > 0 )
1273  {
1274  int c;
1275 
1276  /* free depth information */
1277  for( c = 0; c < eventhdlrdata->maxdepth; ++c )
1278  {
1279  SCIP_CALL( freeDepthinfo(scip, &(eventhdlrdata->depthinfos[c])) );
1280  }
1281 
1282  /* free depth information array */
1283  SCIPfreeBlockMemoryArray(scip, &eventhdlrdata->depthinfos, eventhdlrdata->maxdepth);
1284  eventhdlrdata->maxdepth = 0;
1285  }
1286 
1287  return SCIP_OKAY;
1288 }
1289 
1290 /** collects all parameters that are set to non-default values and stores them in eventhdlrdata */
1291 static
1293  SCIP* scip, /**< SCIP data structure */
1294  SCIP_EVENTHDLRDATA* eventhdlrdata /**< data of event handler */
1295  )
1296 {
1297  SCIP_PARAM** params;
1298  int nparams;
1299  int p;
1300 
1301  params = SCIPgetParams(scip);
1302  nparams = SCIPgetNParams(scip);
1303 
1304  eventhdlrdata->nnondefaultparams = 0;
1305  eventhdlrdata->nondefaultparams = NULL;
1306  eventhdlrdata->nondefaultparamssize = 0;
1307 
1308  /* loop over parameters and store the non-default ones */
1309  for( p = 0; p < nparams; ++p )
1310  {
1311  SCIP_PARAM* param = params[p];
1312 
1313  /* collect parameter if it is nondefault */
1314  if( ! SCIPparamIsDefault(param) )
1315  {
1316  if( eventhdlrdata->nnondefaultparams == 0 )
1317  {
1318  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &eventhdlrdata->nondefaultparams, 8) );
1319  eventhdlrdata->nondefaultparamssize = 8;
1320  }
1321  else if( eventhdlrdata->nnondefaultparams == eventhdlrdata->nondefaultparamssize )
1322  {
1323  eventhdlrdata->nondefaultparamssize *= 2;
1324  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &eventhdlrdata->nondefaultparams, \
1325  eventhdlrdata->nnondefaultparams, eventhdlrdata->nondefaultparamssize) );
1326 
1327  }
1328 
1329  eventhdlrdata->nondefaultparams[eventhdlrdata->nnondefaultparams++] = param;
1330  }
1331  }
1332 
1333 
1334  return SCIP_OKAY;
1335 }
1336 
1337 /** initialization method of event handler (called after problem was transformed) */
1338 static
1339 SCIP_DECL_EVENTINIT(eventInitSolvingphase)
1340 { /*lint --e{715}*/
1341  SCIP_EVENTHDLRDATA* eventhdlrdata;
1342 
1343  assert(scip != NULL);
1344  assert(eventhdlr != NULL);
1345  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
1346 
1347  eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
1348  assert(eventhdlrdata != NULL);
1349 
1350  /* initialize the solving phase */
1351  eventhdlrdata->solvingphase = SOLVINGPHASE_UNINITIALIZED;
1352 
1353  /* none of the transitions is reached yet */
1354  eventhdlrdata->optimalreached = FALSE;
1355  eventhdlrdata->logreached = FALSE;
1356  eventhdlrdata->rank1reached = FALSE;
1357  eventhdlrdata->estimatereached = FALSE;
1358  eventhdlrdata->nnondefaultparams = 0;
1359  eventhdlrdata->nondefaultparams = NULL;
1360  eventhdlrdata->nondefaultparamssize = 0;
1361 
1362  /* apply solving phase for the first time after problem was transformed to apply settings for the feasibility phase */
1363  if( eventhdlrdata->enabled )
1364  {
1365  /* collect non-default parameters */
1366  SCIP_CALL( collectNondefaultParams(scip, eventhdlrdata) );
1367 
1368  SCIP_CALL( applySolvingPhase(scip, eventhdlrdata) );
1369  }
1370 
1371  /* only start catching events if event handler is enabled or in test mode */
1372  if( eventhdlrdata->enabled || eventhdlrdata->testmode )
1373  {
1374  SCIP_CALL( SCIPcatchEvent(scip, EVENTHDLR_EVENT, eventhdlr, NULL, &eventhdlrdata->eventfilterpos) );
1375  }
1376 
1377  /* reset solving regression */
1378  SCIPregressionReset(eventhdlrdata->regression);
1379  eventhdlrdata->lastx = SCIP_INVALID;
1380  eventhdlrdata->lasty = SCIP_INVALID;
1381 
1382  return SCIP_OKAY;
1383 }
1384 /** deinitialization method of event handler (called before problem is freed) */
1385 static
1386 SCIP_DECL_EVENTEXIT(eventExitSolvingphase)
1388  SCIP_EVENTHDLRDATA* eventhdlrdata;
1389 
1390  assert(scip != NULL);
1391  assert(eventhdlr != NULL);
1392  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
1393 
1394  eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
1395  assert(eventhdlrdata != NULL);
1396 
1397  /* free collected, non-default parameters */
1398  SCIPfreeBlockMemoryArrayNull(scip, &eventhdlrdata->nondefaultparams, eventhdlrdata->nondefaultparamssize);
1399 
1400  return SCIP_OKAY;
1401 }
1402 
1403 
1404 /** execution method of event handler */
1405 static
1406 SCIP_DECL_EVENTEXEC(eventExecSolvingphase)
1407 { /*lint --e{715}*/
1408  SCIP_EVENTHDLRDATA* eventhdlrdata;
1409  SCIP_EVENTTYPE eventtype;
1410 
1411  assert(scip != NULL);
1412  assert(eventhdlr != NULL);
1413 
1414  eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
1415  eventtype = SCIPeventGetType(event);
1416  assert(eventtype & (EVENTHDLR_EVENT));
1417  assert(eventtype != SCIP_EVENTTYPE_NODEFOCUSED || SCIPeventGetNode(event) == SCIPgetCurrentNode(scip));
1418 
1419 
1420  /* update data structures depending on the event */
1421  SCIP_CALL( updateDataStructures(scip, eventhdlrdata, eventtype) );
1422 
1423  /* if the phase-based solver is enabled, we check if a phase transition occurred and alter the settings accordingly */
1424  if( eventhdlrdata->enabled )
1425  {
1426  SCIP_CALL( applySolvingPhase(scip, eventhdlrdata) );
1427  }
1428 
1429 
1430  /* in test mode, we check every transition criterion */
1431  if( eventhdlrdata->testmode )
1432  {
1433  testCriteria(scip, eventhdlrdata);
1434  }
1435 
1436  return SCIP_OKAY;
1437 }
1438 
1439 /*
1440  * displays that come with this event handler
1441  */
1442 
1443 /* defines for the rank 1 node display */
1444 #define DISP_NAME_NRANK1NODES "nrank1nodes"
1445 #define DISP_DESC_NRANK1NODES "current number of rank1 nodes left"
1446 #define DISP_HEAD_NRANK1NODES "rank1"
1447 #define DISP_WIDT_NRANK1NODES 7
1448 #define DISP_PRIO_NRANK1NODES 40000
1449 #define DISP_POSI_NRANK1NODES 500
1450 #define DISP_STRI_NRANK1NODES TRUE
1452 /** output method of display column to output file stream 'file' */
1453 static
1454 SCIP_DECL_DISPOUTPUT(dispOutputNRank1Nodes)
1456  assert(disp != NULL);
1457  assert(strcmp(SCIPdispGetName(disp), DISP_NAME_NRANK1NODES) == 0);
1458  assert(scip != NULL);
1459 
1460  /* ouput number of rank 1 nodes */
1462 
1463  return SCIP_OKAY;
1464 }
1465 
1466 /* display for the number of nodes below the current incumbent */
1467 #define DISP_NAME_NNODESBELOWINC "nnodesbelowinc"
1468 #define DISP_DESC_NNODESBELOWINC "current number of nodes with an estimate better than the current incumbent"
1469 #define DISP_HEAD_NNODESBELOWINC "nbInc"
1470 #define DISP_WIDT_NNODESBELOWINC 6
1471 #define DISP_PRIO_NNODESBELOWINC 40000
1472 #define DISP_POSI_NNODESBELOWINC 550
1473 #define DISP_STRI_NNODESBELOWINC TRUE
1475 /** output method of display column to output file stream 'file' */
1476 static
1477 SCIP_DECL_DISPOUTPUT(dispOutputNnodesbelowinc)
1479  assert(disp != NULL);
1480  assert(strcmp(SCIPdispGetName(disp), DISP_NAME_NNODESBELOWINC) == 0);
1481  assert(scip != NULL);
1482 
1483  /* display the number of nodes with an estimate below the the current incumbent */
1485 
1486  return SCIP_OKAY;
1487 }
1488 
1489 /** creates event handler for Solvingphase event */
1491  SCIP* scip /**< SCIP data structure */
1492  )
1493 {
1494  SCIP_EVENTHDLRDATA* eventhdlrdata;
1495  SCIP_EVENTHDLR* eventhdlr;
1496 
1497  /* create solving phase event handler data */
1498  eventhdlrdata = NULL;
1499  SCIP_CALL( SCIPallocBlockMemory(scip, &eventhdlrdata) );
1500  assert(eventhdlrdata != NULL);
1501 
1502  eventhdlrdata->feassetname = NULL;
1503  eventhdlrdata->improvesetname = NULL;
1504  eventhdlrdata->proofsetname = NULL;
1505 
1506  eventhdlrdata->depthinfos = NULL;
1507  eventhdlrdata->maxdepth = 0;
1508  eventhdlrdata->eventfilterpos = -1;
1509 
1510  /* create a regression */
1511  eventhdlrdata->regression = NULL;
1512  SCIP_CALL( SCIPregressionCreate(&eventhdlrdata->regression) );
1513 
1514  eventhdlr = NULL;
1515 
1516  /* include event handler into SCIP */
1518  eventExecSolvingphase, eventhdlrdata) );
1519  assert(eventhdlr != NULL);
1520 
1521  /* include the new displays into scip */
1523  NULL, NULL, NULL, NULL, NULL, NULL, dispOutputNRank1Nodes, NULL, DISP_WIDT_NRANK1NODES, DISP_PRIO_NRANK1NODES, DISP_POSI_NRANK1NODES,
1526  NULL, NULL, NULL, NULL, NULL, NULL, dispOutputNnodesbelowinc, NULL, DISP_WIDT_NNODESBELOWINC, DISP_PRIO_NNODESBELOWINC, DISP_POSI_NNODESBELOWINC,
1528 
1529  /* set non fundamental callbacks via setter functions */
1531  SCIP_CALL( SCIPsetEventhdlrFree(scip, eventhdlr, eventFreeSolvingphase) );
1532  SCIP_CALL( SCIPsetEventhdlrInit(scip, eventhdlr, eventInitSolvingphase) );
1533  SCIP_CALL( SCIPsetEventhdlrExit(scip, eventhdlr, eventExitSolvingphase) );
1534  SCIP_CALL( SCIPsetEventhdlrInitsol(scip, eventhdlr, eventInitsolSolvingphase) );
1535  SCIP_CALL( SCIPsetEventhdlrExitsol(scip, eventhdlr, eventExitsolSolvingphase) );
1536 
1537  /* add Solvingphase event handler parameters */
1538  SCIP_CALL( SCIPaddBoolParam(scip, EVENTHDLR_NAME "s/enabled", "should the event handler adapt the solver behavior?",
1539  &eventhdlrdata->enabled, FALSE, DEFAULT_ENABLED, NULL, NULL) );
1540 
1541  SCIP_CALL( SCIPaddBoolParam(scip, EVENTHDLR_NAME "s/testmode", "should the event handler test all phase transitions?",
1542  &eventhdlrdata->testmode, FALSE, DEFAULT_TESTMODE, NULL, NULL) );
1543 
1544  SCIP_CALL( SCIPaddStringParam(scip, EVENTHDLR_NAME "s/feassetname", "settings file for feasibility phase -- precedence over emphasis settings",
1545  &eventhdlrdata->feassetname, FALSE, DEFAULT_SETNAME, NULL, NULL) );
1546 
1547  SCIP_CALL( SCIPaddStringParam(scip, EVENTHDLR_NAME "s/improvesetname", "settings file for improvement phase -- precedence over emphasis settings",
1548  &eventhdlrdata->improvesetname, FALSE, DEFAULT_SETNAME, NULL, NULL) );
1549 
1550  SCIP_CALL( SCIPaddStringParam(scip, EVENTHDLR_NAME "s/proofsetname", "settings file for proof phase -- precedence over emphasis settings",
1551  &eventhdlrdata->proofsetname, FALSE, DEFAULT_SETNAME, NULL, NULL) );
1552 
1553  SCIP_CALL( SCIPaddLongintParam(scip, EVENTHDLR_NAME "s/nodeoffset", "node offset for rank-1 and estimate transitions", &eventhdlrdata->nodeoffset,
1554  FALSE, DEFAULT_NODEOFFSET, 1L, SCIP_LONGINT_MAX, NULL, NULL) );
1555  SCIP_CALL( SCIPaddBoolParam(scip, EVENTHDLR_NAME "s/fallback", "should the event handler fall back from optimal phase?",
1556  &eventhdlrdata->fallback, FALSE, DEFAULT_FALLBACK, NULL, NULL) );
1557  SCIP_CALL( SCIPaddCharParam(scip ,EVENTHDLR_NAME "s/transitionmethod",
1558  "transition method: Possible options are 'e'stimate,'l'ogarithmic regression,'o'ptimal-value based,'r'ank-1",
1559  &eventhdlrdata->transitionmethod, FALSE, DEFAULT_TRANSITIONMETHOD, TRANSITIONMETHODS, NULL, NULL) );
1560  SCIP_CALL( SCIPaddBoolParam(scip, EVENTHDLR_NAME "s/interruptoptimal",
1561  "should the event handler interrupt the solving process after optimal solution was found?",
1562  &eventhdlrdata->interruptoptimal, FALSE, DEFAULT_INTERRUPTOPTIMAL, NULL, NULL) );
1563 
1564  SCIP_CALL( SCIPaddBoolParam(scip, EVENTHDLR_NAME "s/userestart1to2",
1565  "should a restart be applied between the feasibility and improvement phase?",
1566  &eventhdlrdata->userestart1to2, FALSE, DEFAULT_USERESTART1TO2, NULL, NULL) );
1567 
1568  SCIP_CALL( SCIPaddBoolParam(scip, EVENTHDLR_NAME "s/userestart2to3",
1569  "should a restart be applied between the improvement and the proof phase?",
1570  &eventhdlrdata->userestart2to3, FALSE, DEFAULT_USERESTART2TO3, NULL, NULL) );
1571 
1572  SCIP_CALL(SCIPaddRealParam(scip, EVENTHDLR_NAME "s/optimalvalue", "optimal solution value for problem",
1573  &eventhdlrdata->optimalvalue, FALSE, SCIP_INVALID, SCIP_REAL_MIN, SCIP_REAL_MAX, NULL, NULL) );
1574 
1575  /* add parameter for logarithmic regression */
1576  SCIP_CALL( SCIPaddCharParam(scip, EVENTHDLR_NAME "s/xtype", "x-type for logarithmic regression - (t)ime, (n)odes, (l)p iterations",
1577  &eventhdlrdata->logregression_xtype, FALSE, DEFAULT_LOGREGRESSION_XTYPE, LOGREGRESSION_XTYPES, NULL, NULL) );
1578 
1579  SCIP_CALL( SCIPaddBoolParam(scip, EVENTHDLR_NAME "s/useemphsettings",
1580  "should emphasis settings for the solving phases be used, or settings files?",
1581  &eventhdlrdata->useemphsettings, FALSE, DEFAULT_USEEMPHSETTINGS, NULL, NULL) );
1582 
1583  return SCIP_OKAY;
1584 }
static SCIP_RETCODE recomputeNodeInformation(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip.h:22604
static SCIP_RETCODE applySolvingPhase(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
#define DISP_HEAD_NRANK1NODES
SCIP_Real SCIPgetFirstPrimalBound(SCIP *scip)
Definition: scip.c:43380
SCIP_PARAM ** SCIPgetParams(SCIP *scip)
Definition: scip.c:5178
#define TRANSITIONMETHODS
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip.h:22593
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
Definition: scip.c:46306
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:22587
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:8699
#define DISP_HEAD_NNODESBELOWINC
SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
Definition: scip.c:41404
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:821
#define DISP_NAME_NRANK1NODES
static SCIP_Bool transitionPhase3(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
Definition: scip.c:42333
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:43402
static SCIP_RETCODE freeDepthinfo(SCIP *scip, DEPTHINFO **depthinfo)
SCIP_RETCODE SCIPgetLeaves(SCIP *scip, SCIP_NODE ***leaves, int *nleaves)
Definition: scip.c:41561
SCIP_RETCODE SCIPsetEventhdlrExitsol(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTEXITSOL((*eventexitsol)))
Definition: scip.c:8713
#define DEFAULT_USERESTART1TO2
SCIP_RETCODE SCIPsetEventhdlrExit(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTEXIT((*eventexit)))
Definition: scip.c:8685
#define DEFAULT_TESTMODE
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47015
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:8611
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:41711
#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:4293
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:47028
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:47100
#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:42178
void SCIPregressionAddObservation(SCIP_REGRESSION *regression, SCIP_Real x, SCIP_Real y)
Definition: misc.c:369
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:22602
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:4376
SCIP_Bool SCIPparamIsDefault(SCIP_PARAM *param)
Definition: paramset.c:918
SCIP_EVENTHDLR * SCIPfindEventhdlr(SCIP *scip, const char *name)
Definition: scip.c:8741
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip.c:1235
#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:46963
int SCIPnodeGetDepth(SCIP_NODE *node)
Definition: tree.c:7352
#define DEFAULT_ENABLED
#define SCIP_LONGINT_MAX
Definition: def.h:135
static SCIP_RETCODE changeEmphasisParameters(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:22585
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1267
#define SCIPdebugMsg
Definition: scip.h:455
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:41519
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:7342
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:8657
SCIP_RETCODE SCIPsetEventhdlrCopy(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTCOPY((*eventcopy)))
Definition: scip.c:8643
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46976
static SCIP_Real getX(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
SCIP_RETCODE SCIPgetChildren(SCIP *scip, SCIP_NODE ***children, int *nchildren)
Definition: scip.c:41477
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:8671
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:41501
#define DISP_PRIO_NNODESBELOWINC
static SCIP_RETCODE collectNondefaultParams(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
SCIP_Longint SCIPgetNDelayedCutoffs(SCIP *scip)
Definition: scip.c:42287
static int getNNodesBelowIncumbent(SCIP *scip)
#define REALABS(x)
Definition: def.h:173
SCIP_RETCODE SCIPunfixParam(SCIP *scip, const char *name)
Definition: scip.c:4567
static SCIP_DECL_DISPOUTPUT(dispOutputNRank1Nodes)
#define DISP_POSI_NRANK1NODES
#define SCIP_CALL(x)
Definition: def.h:350
SCIP_Longint SCIPgetNTotalNodes(SCIP *scip)
Definition: scip.c:42160
SCIP_RETCODE SCIPsetEmphasis(SCIP *scip, SCIP_PARAMEMPHASIS paramemphasis, SCIP_Bool quiet)
Definition: scip.c:5061
static SCIP_RETCODE updateLogRegression(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip.c:1360
#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:41158
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:9351
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:39783
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:4549
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:47039
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:150
SCIP_Real SCIPnodeGetEstimate(SCIP_NODE *node)
Definition: tree.c:7372
#define SCIP_REAL_MIN
Definition: def.h:151
#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:47002
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:4349
#define EVENTHDLR_EVENT
SCIP_RETCODE SCIPrestartSolve(SCIP *scip)
Definition: scip.c:17350
SCIP_RETCODE SCIPreadParams(SCIP *scip, const char *filename)
Definition: scip.c:4952
SCIP_Real SCIPregressionGetSlope(SCIP_REGRESSION *regression)
Definition: misc.c:252
SCIP_NODETYPE SCIPnodeGetType(SCIP_NODE *node)
Definition: tree.c:7332
#define SCIP_Real
Definition: def.h:149
#define DEFAULT_USEEMPHSETTINGS
#define SCIP_DECL_EVENTCOPY(x)
Definition: type_event.h:165
SCIP_RETCODE SCIPincludeEventHdlrSolvingphase(SCIP *scip)
#define SCIP_INVALID
Definition: def.h:169
static SCIP_RETCODE updateDataStructures(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata, SCIP_EVENTTYPE eventtype)
#define SCIP_Longint
Definition: def.h:134
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:22605
#define eventCopySolvingphase
SCIP_RETCODE SCIPregressionCreate(SCIP_REGRESSION **regression)
Definition: misc.c:404
SCIP_RETCODE SCIPinterruptSolve(SCIP *scip)
Definition: scip.c:17324
SCIP_Real SCIPgetUpperbound(SCIP *scip)
Definition: scip.c:43426
#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:42133
#define SCIPABORT()
Definition: def.h:322
const char * SCIPdispGetName(SCIP_DISP *disp)
Definition: disp.c:283
int SCIPgetNParams(SCIP *scip)
Definition: scip.c:5192
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:4321
static SCIP_Bool checkOptimalSolution(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
#define EPSZ(x, eps)
Definition: def.h:179
#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:4239
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