Scippy

SCIP

Solving Constraint Integer Programs

event_estim.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-2025 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file event_estim.c
26 * @ingroup DEFPLUGINS_EVENT
27 * @brief event handler for tree size estimation and restarts
28 *
29 * This event handler plugin provides different methods for approximating the current fraction of the search
30 * that has already been completed and for estimating the total tree size at completion.
31 * It can trigger restarts of the current run if the current run seems hopeless.
32 *
33 * For details about the available approximations of search completion, please see
34 *
35 * Anderson, Hendel, Le Bodic, Pfetsch
36 * Estimating The Size of Branch-and-Bound Trees
37 * under preparation
38 *
39 * This code is a largely enriched version of a code that was used for clairvoyant restarts, see
40 *
41 * Anderson, Hendel, Le Bodic, Viernickel
42 * Clairvoyant Restarts in Branch-and-Bound Search Using Online Tree-Size Estimation
43 * AAAI-19: Proceedings of the Thirty-Third AAAI Conference on Artificial Intelligence, 2018
44 *
45 * @author Gregor Hendel
46 */
47
48/*--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
49
50#include <string.h>
52#include "scip/event_estim.h"
53#include "scip/prop_symmetry.h"
54#include "scip/pub_disp.h"
55#include "scip/pub_event.h"
56#include "scip/pub_fileio.h"
57#include "scip/pub_message.h"
58#include "scip/pub_misc.h"
59#include "scip/pub_tree.h"
60#include "scip/scip_disp.h"
61#include "scip/scip_event.h"
62#include "scip/scip_general.h"
63#include "scip/scip_mem.h"
64#include "scip/scip_message.h"
65#include "scip/scip_nlp.h"
66#include "scip/scip_numerics.h"
67#include "scip/scip_param.h"
68#include "scip/scip_pricer.h"
69#include "scip/scip_sol.h"
70#include "scip/scip_solve.h"
72#include "scip/scip_table.h"
73#include "scip/scip_timing.h"
74#include "scip/scip_tree.h"
75#include "scip/type_disp.h"
76#include "scip/type_event.h"
77#include "scip/type_message.h"
78#include "scip/type_misc.h"
79#include "scip/type_retcode.h"
80#include "scip/type_stat.h"
81#include "scip/type_table.h"
82
83#define EVENTHDLR_NAME "estim"
84#define EVENTHDLR_DESC "event handler for tree size estimation and restarts"
85#define EVENTTYPE_ESTIM (SCIP_EVENTTYPE_NODEDELETE | SCIP_EVENTTYPE_NODEBRANCHED)
86
87/*
88 * Data structures
89 */
90
91/** enumerator for available restart policies */
93{
94 RESTARTPOLICY_NEVER = 0, /**< never restart (disable this event handler) */
95 RESTARTPOLICY_ALWAYS = 1, /**< always restart (can be fine tuned by using minimum number of nodes and restart limit) */
96 RESTARTPOLICY_ESTIMATION = 2, /**< base restart on the estimation method */
97 RESTARTPOLICY_COMPLETION = 3 /**< trigger restart based on search completion approximation */
98};
99
101
102#define RESTARTPOLICY_CHAR_NEVER 'n'
103#define RESTARTPOLICY_CHAR_ALWAYS 'a'
104#define RESTARTPOLICY_CHAR_COMPLETION 'c'
105#define RESTARTPOLICY_CHAR_ESTIMATION 'e'
106
107#define DES_USETRENDINLEVEL TRUE /**< Should the trend be used in the level update? */
108
109/* constants for the table estimation */
110#define TABLE_NAME "estim"
111#define TABLE_DESC "tree size estimations statistics table"
112#define TABLE_POSITION 18500 /**< the position of the statistics table */
113#define TABLE_EARLIEST_STAGE SCIP_STAGE_INIT /**< output of the statistics table is only printed from this stage onwards */
114
115/* constants for the search completion display column */
116#define DISP_NAME "completed"
117#define DISP_DESC "completion of search in percent (based on tree size estimation)"
118#define DISP_HEADER "compl."
119#define DISP_WIDTH 8 /**< the width of the display column */
120#define DISP_PRIORITY 110000 /**< the priority of the display column */
121#define DISP_POSITION 30100 /**< the relative position of the display column */
122#define DISP_STRIPLINE TRUE /**< the default for whether the display column should be separated
123 * with a line from its right neighbor */
124#define INITIALSIZE 100
125#define SESCOEFF 0.75 /**< coefficient of single exponential smoothing of estimation */
126
127/* double exponential smoothing parameters for different time series */
128#define DES_ALPHA_TREEWEIGHT 0.65
129#define DES_BETA_TREEWEIGHT 0.15
130
131#define DES_ALPHA_GAP 0.6
132#define DES_BETA_GAP 0.15
133
134#define DES_ALPHA_LEAFFREQUENCY 0.3
135#define DES_BETA_LEAFFREQUENCY 0.33
136
137#define DES_ALPHA_SSG 0.6
138#define DES_BETA_SSG 0.15
139
140#define DES_ALPHA_OPENNODES 0.6
141#define DES_BETA_OPENNODES 0.15
142
143#define MAX_REGFORESTSIZE 10000000 /**< size limit (number of nodes) for regression forest */
144
145
146
147/* computation of search completion */
148#define COMPLETIONTYPE_AUTO 'a' /**< automatic (regression forest if available, else monotone regression on binary and SSG on nonbinary trees) */
149#define COMPLETIONTYPE_REGFOREST 'r' /**< regression forest (must be provided by user) */
150#define COMPLETIONTYPE_MONOREG 'm' /**< monotone regression (using tree weight and SSG) */
151#define COMPLETIONTYPE_TREEWEIGHT 'w' /**< use tree weight value as approximation of search tree completion */
152#define COMPLETIONTYPE_SSG 's' /**< use SSG value as approximation of search tree completion */
153#define COMPLETIONTYPE_GAP 'g' /**< use gap value as approximation of search tree completion */
154
155
156/* tree size estimation method */
157#define ESTIMMETHOD_COMPL 'c' /**< estimation based on projection of current search completion */
158#define ESTIMMETHOD_WBE 'b' /**< weighted backtrack estimation */
159#define ESTIMMETHOD_ENSMBL 'e' /**< estimation based on an ensemble of the individual estimations */
160#define ESTIMMETHOD_GAP 'g' /**< estimation based on double exponential smoothing for open nodes */
161#define ESTIMMETHOD_LFREQ 'l' /**< estimation based on double exponential smoothing for leaf frequency */
162#define ESTIMMETHOD_OPEN 'o' /**< estimation based on double exponential smoothing for open nodes */
163#define ESTIMMETHOD_SSG 's' /**< estimation based on double exponential smoothing for sum of subtree gaps */
164#define ESTIMMETHOD_TPROF 't' /**< estimation based on tree profile method */
165#define ESTIMMETHOD_TREEWEIGHT 'w' /**< estimation based on double exponential smoothing for tree weight */
166
167#define ESTIMMETHODS "bceglostw"
168
169/* constants and default values for treeprofile parameters */
170#define TREEPROFILE_MINSIZE 512 /**< minimum size (depth) that tree profile can hold */
171#define SSG_STARTPRIMBOUND SCIP_INVALID /**< initial value of primal bound used within SSG */
172
173/** double exponential smoothing data structure */
175{
176 SCIP_Real alpha; /**< level smoothing constant */
177 SCIP_Real beta; /**< trend smoothing constant */
178 SCIP_Real level; /**< estimation of the current level used for smoothing */
179 SCIP_Real trend; /**< estimation of the current trend (slope) */
180 SCIP_Real initialvalue; /**< the level value at 0 observations */
181 SCIP_Bool usetrendinlevel; /**< Should the trend be used in the level update? */
182 int n; /**< number of observations */
183};
185
186/** time series data structure for leaf time series
187 *
188 * These time series are the basic ingredient for tree size estimation via forecasting.
189 *
190 * This general class represents concrete time series such as the closed gap, tree weight, and leaf frequency.
191 * Through callbacks for data (de-)initialization and value queries, it provides a common interface
192 * to which double exponential smoothing or window forecasts can be applied.
193 */
194typedef struct TimeSeries TIMESERIES;
195
196/** data structure for convenient access of tree information */
197typedef struct TreeData TREEDATA;
198
199
200#define NTIMESERIES 5
201
202/** time series position in event handler time series array */
204{
205 TSPOS_NONE = -1, /**< invalid array position */
206 TSPOS_GAP = 0, /**< time series position of gap */
207 TSPOS_TREEWEIGHT = 1, /**< time series position of tree weight */
208 TSPOS_LFREQ = 2, /**< time series position of leaf frequency */
209 TSPOS_SSG = 3, /**< time series position of SSG */
210 TSPOS_OPEN = 4 /**< time series position of open nodes */
212
213typedef enum TsPos TSPOS;
214
215/** regression forest data structure */
217
218/** statistics collected from profile used for prediction */
220{
221 int maxdepth; /**< maximum node depth encountered */
222 int lastfulldepth; /**< deepest layer for which all nodes have been explored */
223 int minwaistdepth; /**< minimum depth of the waist, i.e. the widest part of the tree */
224 int maxwaistdepth; /**< maximum depth of the waist, i.e. the widest part of the tree */
225};
226
228
229
230/** profile data structure for tree */
232{
233 SCIP_Longint* profile; /**< array to store the tree profile */
234 int profilesize; /**< size of the profile array */
235 TREEPROFILESTATS stats; /**< statistics collected from profile used for prediction */
236 SCIP_Real lastestimate; /**< the last estimate predicted by predictTotalSizeTreeprofile() */
237 TREEPROFILESTATS lastestimatestats; /**< tree profile statistics at last estimation */
238};
239
241
242/* default values of user parameters */
243#define DEFAULT_USELEAFTS TRUE /**< Use leaf nodes as basic observations for time series, or all nodes? */
244#define DEFAULT_REPORTFREQ -1 /**< report frequency on estimation: -1: never, 0: always, k >= 1: k times evenly during search */
245#define DEFAULT_REGFORESTFILENAME "-" /**< default file name of user regression forest in RFCSV format */
246#define DEFAULT_COEFMONOWEIGHT 0.3667 /**< coefficient of tree weight in monotone approximation of search completion */
247#define DEFAULT_COEFMONOSSG 0.6333 /**< coefficient of 1 - SSG in monotone approximation of search completion */
248#define DEFAULT_COMPLETIONTYPE COMPLETIONTYPE_AUTO /**< default computation of search tree completion */
249#define DEFAULT_ESTIMMETHOD ESTIMMETHOD_TREEWEIGHT /**< default tree size estimation method: (c)ompletion, (e)nsemble, time series forecasts on either
250 * (g)ap, (l)eaf frequency, (o)open nodes,
251 * tree (w)eight, (s)sg, or (t)ree profile or w(b)e */
252#define DEFAULT_TREEPROFILE_ENABLED FALSE /**< Should the event handler collect data? */
253#define DEFAULT_TREEPROFILE_MINNODESPERDEPTH 20.0 /**< minimum average number of nodes at each depth before producing estimations */
254#define DEFAULT_RESTARTPOLICY 'e' /**< default restart policy: (a)lways, (c)ompletion, (e)stimation, (n)ever */
255#define DEFAULT_RESTARTLIMIT 1 /**< default restart limit */
256#define DEFAULT_MINNODES 1000L /**< minimum number of nodes before restart */
257#define DEFAULT_COUNTONLYLEAVES FALSE /**< should only leaves count for the minnodes parameter? */
258#define DEFAULT_RESTARTFACTOR 50.0 /**< factor by which the estimated number of nodes should exceed the current number of nodes */
259#define DEFAULT_RESTARTNONLINEAR FALSE /**< whether to apply a restart when nonlinear constraints are present */
260#define DEFAULT_RESTARTACTPRICERS FALSE /**< whether to apply a restart when active pricers are used */
261#define DEFAULT_HITCOUNTERLIM 50 /**< limit on the number of successive samples to really trigger a restart */
262#define DEFAULT_SSG_NMAXSUBTREES -1 /**< the maximum number of individual SSG subtrees; the old split is kept if
263 * a new split exceeds this number of subtrees ; -1: no limit */
264#define DEFAULT_SSG_NMINNODESLASTSPLIT 0L /**< minimum number of nodes to process between two consecutive SSG splits */
265#define DEFAULT_SHOWSTATS FALSE /**< should statistics be shown at the end? */
266
267/** event handler data */
268struct SCIP_EventhdlrData
269{
270 SCIP_REGFOREST* regforest; /**< regression forest data structure */
271 TIMESERIES* timeseries[NTIMESERIES]; /**< array of time series slots */
272 TREEDATA* treedata; /**< tree data */
273 TREEPROFILE* treeprofile; /**< tree profile data structure */
274 char* regforestfilename; /**< file name of user regression forest in RFCSV format */
275 SCIP_Real restartfactor; /**< factor by which the estimated number of nodes should exceed the current number of nodes */
276 SCIP_Real weightlastreport; /**< tree weight at which last report was printed */
277 SCIP_Real treeprofile_minnodesperdepth;/**< minimum average number of nodes at each depth before producing estimations */
278 SCIP_Real coefmonoweight; /**< coefficient of tree weight in monotone approximation of search completion */
279 SCIP_Real coefmonossg; /**< coefficient of 1 - SSG in monotone approximation of search completion */
280 SCIP_Longint minnodes; /**< minimum number of nodes in a run before restart is triggered */
281 int restartlimit; /**< How often should a restart be triggered? (-1 for no limit) */
282 int nrestartsperformed; /**< number of restarts performed so far */
283 int restarthitcounter; /**< the number of successive samples that would trigger a restart */
284 int hitcounterlim; /**< limit on the number of successive samples to really trigger a restart */
285 int nreports; /**< the number of reports already printed */
286 int reportfreq; /**< report frequency on estimation: -1: never, 0:always, k >= 1: k times evenly during search */
287 int lastrestartrun; /**< the last run at which this event handler triggered restart */
288 char restartpolicyparam; /**< restart policy parameter */
289 char estimmethod; /**< tree size estimation method: (c)ompletion, (e)nsemble, time series forecasts on either
290 * (g)ap, (l)eaf frequency, (o)open nodes,
291 * tree (w)eight, (s)sg, or (t)ree profile or w(b)e */
292 char completiontypeparam;/**< approximation of search tree completion:
293 * (a)uto, (g)ap, tree (w)eight, (m)onotone regression, (r)egression forest, (s)sg */
294 SCIP_Bool countonlyleaves; /**< Should only leaves count for the minnodes parameter? */
295 SCIP_Bool useleafts; /**< Use leaf nodes as basic observations for time series, or all nodes? */
296 SCIP_Bool treeprofile_enabled;/**< Should the event handler collect treeprofile data? */
297 SCIP_Bool treeisbinary; /**< internal flag if all branching decisions produced 2 children */
298 SCIP_Bool restartnonlinear; /**< whether to apply a restart when nonlinear constraints are present */
299 SCIP_Bool restartactpricers; /**< whether to apply a restart when active pricers are used */
300 SCIP_Bool showstats; /**< should statistics be shown at the end? */
301};
302
304
306{
307 SCIP_Longint nnodes; /**< the total number of nodes */
308 SCIP_Longint nopen; /**< the current number of open nodes */
309 SCIP_Longint ninner; /**< the number of inner nodes */
310 SCIP_Longint nleaves; /**< the number of final leaf nodes */
311 SCIP_Longint nvisited; /**< the number of visited nodes */
312 long double weight; /**< the current tree weight (sum of leaf weights) */
313 SUBTREESUMGAP* ssg; /**< subtree sum gap data structure */
314};
315
317{
318 SCIP_Real value; /**< the current subtree sum gap */
319 SCIP_HASHMAP* nodes2info; /**< map between nodes and their subtree indices */
320 SCIP_PQUEUE** subtreepqueues; /**< array of priority queues, one for each subtree */
321 SCIP_Real scalingfactor; /**< the current scaling factor */
322 SCIP_Real pblastsplit; /**< primal bound when last split occurred */
323 SCIP_Longint nodelastsplit; /**< last node at which a subtree split occurred */
324 SCIP_Longint nminnodeslastsplit; /**< minimum number of nodes to process between two consecutive SSG splits */
325 int nmaxsubtrees; /**< the maximum number of individual SSG subtrees; the old split is kept if
326 * a new split exceeds this number of subtrees ; -1: no limit */
327 int nsubtrees; /**< the current number n of subtrees labeled 0 .. n - 1 */
328};
329
330/** update callback of time series */
331#define DECL_TIMESERIESUPDATE(x) SCIP_RETCODE x (\
332 SCIP* scip, \
333 TIMESERIES* ts, \
334 TREEDATA* treedata, \
335 SCIP_Real* value \
336 )
337
338/** time series data structure for leaf time series */
340{
341 DOUBLEEXPSMOOTH des; /**< double exponential smoothing data structure */
342 char* name; /**< name of this time series */
343 SCIP_Real* vals; /**< value array of this time series */
344 SCIP_Real* estimation; /**< array of estimations of this time series */
345 SCIP_Real smoothestimation; /**< smoothened estimation value */
346 SCIP_Real targetvalue; /**< target value of this time series */
347 SCIP_Real currentvalue; /**< current value of time series */
348 SCIP_Real initialvalue; /**< the initial value of time series */
349 SCIP_Longint nobs; /**< total number of observations */
350 int valssize; /**< size of value array */
351 int nvals; /**< number of values */
352 int resolution; /**< current (inverse of) resolution */
353 SCIP_Bool useleafts; /**< Should this time series be recorded at leaf nodes, or at every node? */
354 DECL_TIMESERIESUPDATE((*timeseriesupdate));/**< update callback at nodes */
355};
356
357/** extended node information for SSG priority queue */
359{
360 SCIP_NODE* node; /**< search tree node */
361 SCIP_Real lowerbound; /**< lower bound of the node at insertion into priority queue */
362 int pos; /**< position of this node in priority queue */
363 int subtreeidx; /**< subtree index of this node */
364};
365typedef struct NodeInfo NODEINFO;
366
368{
369 int ntrees; /**< number of trees in this forest */
370 int dim; /**< feature dimension */
371 int* nbegin; /**< array of root node indices of each tree */
372 int* child; /**< child index pair of each internal node, or (-1, -1) for leaves */
373 int* splitidx; /**< data index for split at node, or -1 at a leaf */
374 SCIP_Real* value; /**< split position at internal nodes, prediction at leaves */
375 int size; /**< length of node arrays */
376};
377
378/*
379 * Local methods
380 */
381
382/** convert number to string and treat SCIP_INVALID as '-' */
383static
385 SCIP_Real num, /**< number to convert to string */
386 char* buf, /**< string buffer */
387 int digits /**< number of decimal digits */
388 )
389{
390 if( num == SCIP_INVALID )/*lint !e777*/
391 (void) SCIPsnprintf(buf, 1, "-");
392 else if( num >= 1e+20 ) /*lint !e777*/
393 (void) SCIPsnprintf(buf, 3, "inf");
394 else
395 (void) SCIPsnprintf(buf, SCIP_MAXSTRLEN, "%10.*f", digits, num);
396
397 return buf;
398}
399
400/** free a regression forest data structure */
401static
403 SCIP_REGFOREST** regforest /**< regression forest data structure */
404 )
405{
406 SCIP_REGFOREST* regforestptr;
407
408 assert(regforest != NULL);
409
410 if( *regforest == NULL )
411 return;
412 regforestptr = *regforest;
413
414 BMSfreeMemoryArrayNull(&regforestptr->nbegin);
415 BMSfreeMemoryArrayNull(&regforestptr->child);
416 BMSfreeMemoryArrayNull(&regforestptr->splitidx);
417 BMSfreeMemoryArrayNull(&regforestptr->value);
418
419 BMSfreeMemory(regforest);
420}
421
422/** make a prediction with regression forest */
423static
425 SCIP_REGFOREST* regforest, /**< regression forest data structure */
426 SCIP_Real* datapoint /**< a data point that matches the dimension of this regression forest */
427 )
428{
429 int treeidx;
430 SCIP_Real value = 0.0;
431
432 assert(regforest != NULL);
433 assert(datapoint != NULL);
434
435 SCIPdebugMessage("Start prediction method of regression forest\n");
436
437 /* loop through the trees */
438 for( treeidx = 0; treeidx < regforest->ntrees; ++treeidx )
439 {
440 int treepos = regforest->nbegin[treeidx];
441 int* childtree = &(regforest->child[2 * treepos]);
442 int* splitidxtree = &(regforest->splitidx[treepos]);
443 int pos = 0;
444 SCIP_Real* valuetree = &(regforest->value[treepos]);
445
446 SCIPdebugMessage("Tree %d at position %d\n", treeidx, treepos);
447
448 /* find the correct leaf */
449 while( splitidxtree[pos] != - 1 )
450 {
451 int goright;
452
453 assert(splitidxtree[pos] < regforest->dim);
454
455 goright = (datapoint[splitidxtree[pos]] > valuetree[pos]) ? 1 : 0;
456 pos = childtree[2 * pos + goright];
457 }
458
459 value += valuetree[pos];
460 }
461
462 /* return the average value that the trees predict */
463 return value / (SCIP_Real)(regforest->ntrees);
464}
465
466/** read a regression forest from an rfcsv file
467 *
468 * TODO improve this parser to better capture wrong user input, e.g., if the dimension is wrong
469 */
470static
472 SCIP_REGFOREST** regforest, /**< regression forest data structure */
473 const char* filename /**< name of file with the regression forest data */
474 )
475{
476 SCIP_RETCODE retcode = SCIP_OKAY;
477 SCIP_FILE* file;
478 SCIP_REGFOREST* regforestptr;
479 char buffer[SCIP_MAXSTRLEN];
480 char firstlineformat[SCIP_MAXSTRLEN];
481 char dataformat[SCIP_MAXSTRLEN];
482 char valuestr[SCIP_MAXSTRLEN];
483 SCIP_Bool error = FALSE;
484 int ntrees;
485 int dim;
486 int size;
487 int sscanret;
488 int pos;
489 int treepos;
490
491 /* try to open file */
492 file = SCIPfopen(filename, "r");
493
494 if( file == NULL )
495 return SCIP_NOFILE;
496
497 /* parse read the first line that contains the number of trees, feature dimension, and total number of nodes */
498 (void) SCIPsnprintf(firstlineformat, SCIP_MAXSTRLEN, "### NTREES=%%10d FEATURE_DIM=%%10d LENGTH=%%10d\n");
499 if( SCIPfgets(buffer, (int) sizeof(buffer), file) == NULL )
500 {
501 error = TRUE;
502 SCIPerrorMessage("Could not read first line of regression file '%s'\n", filename);
503 goto CLOSEFILE;
504 }
505
506 /* coverity[secure_coding] */
507 sscanret = sscanf(buffer, firstlineformat, &ntrees, &dim, &size);
508
509 if( sscanret != 3 )
510 {
511 error = TRUE;
512 SCIPerrorMessage("Could not extract tree information from buffer line [%s]\n", buffer);
513 goto CLOSEFILE;
514 }
515
516 SCIPdebugMessage("Read ntrees=%d, dim=%d, size=%d (return value %d)\n", ntrees, dim, size, sscanret);
517
518 /* check if the tree is too big, or numbers are negative */
519 if( size > MAX_REGFORESTSIZE )
520 {
521 error = TRUE;
522 SCIPerrorMessage("Requested size %d exceeds size limit %d for regression trees", size, MAX_REGFORESTSIZE);
523 goto CLOSEFILE;
524 }
525
526 if( dim <= 0 || ntrees <= 0 || size <= 0 )
527 {
528 error = TRUE;
529 SCIPerrorMessage("Cannot create regression tree with negative size, dimension, or number of trees\n");
530 goto CLOSEFILE;
531 }
532
533 /* allocate memory in regression forest data structure */
534 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemory(regforest), FREEFOREST );
535 BMSclearMemory(*regforest);
536 regforestptr = *regforest;
537
538 /* coverity[tainted_data] */
539 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&regforestptr->nbegin, ntrees), FREEFOREST );
540 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&regforestptr->child, 2 * size), FREEFOREST ); /*lint !e647*/
541 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&regforestptr->splitidx, size), FREEFOREST );
542 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&regforestptr->value, size), FREEFOREST );
543
544 regforestptr->dim = dim;
545 regforestptr->size = size;
546 regforestptr->ntrees = ntrees;
547
548 SCIPdebugMessage("Random Forest allocated\n");
549
550 /* loop through the rest of the file, which contains the comma separated node data */
551 (void) SCIPsnprintf(dataformat, SCIP_MAXSTRLEN, "%%10d,%%10d,%%10d,%%10d,%%%ds\n", SCIP_MAXSTRLEN);
552
553 pos = 0;
554 treepos = 0;
555 while( !SCIPfeof(file) && !error )
556 {
557 int node;
558 char* endptr;
559
560 /* get next line */
561 if( SCIPfgets(buffer, (int) sizeof(buffer), file) == NULL )
562 break;
563
564 sscanret = sscanf(buffer, dataformat,
565 &node,
566 &regforestptr->child[2 * pos],
567 &regforestptr->child[2 * pos + 1],
568 &regforestptr->splitidx[pos],
569 valuestr);
570
571 if( sscanret != 5 )
572 {
573 SCIPerrorMessage("Something wrong with line %d '%s'", pos + 1, buffer);
574 error = TRUE;
575 }
576
577 (void)SCIPstrToRealValue(valuestr, &regforestptr->value[pos], &endptr);
578
579 /* new root node - increase the tree index position */
580 if( node == 0 )
581 {
582 assert(treepos < regforestptr->ntrees);
583
584 regforestptr->nbegin[treepos++] = pos;
585 }
586
587 ++pos;
588 }
589
590 goto CLOSEFILE;
591
592/* insufficient memory for allocating regression forest */
593FREEFOREST:
594 assert(retcode == SCIP_NOMEMORY);
595 SCIPregForestFree(regforest);
596
597CLOSEFILE:
598 SCIPfclose(file);
599
600 if( error )
601 retcode = SCIP_INVALIDDATA;
602
603 return retcode;
604}
605
606/** compare two tree profile statistics for equality */
607static
609 TREEPROFILESTATS* stats, /**< first tree profile statistics */
610 TREEPROFILESTATS* other /**< other tree profile statistics */
611 )
612{
613 assert(stats != NULL);
614 assert(other != NULL);
615
616 return stats->maxdepth == other->maxdepth &&
617 stats->lastfulldepth == other->lastfulldepth &&
618 stats->minwaistdepth == other->minwaistdepth &&
619 stats->maxwaistdepth == other->maxwaistdepth;
620}
621
622/** copy source tree profile into destination */
623static
625 TREEPROFILESTATS* dest, /**< destination tree profile statistics */
626 TREEPROFILESTATS* src /**< source tree profile statistics */
627 )
628{
629 assert(dest != NULL);
630 assert(src != NULL);
631
632 dest->maxdepth = src->maxdepth;
633 dest->lastfulldepth = src->lastfulldepth;
634 dest->minwaistdepth = src->minwaistdepth;
635 dest->maxwaistdepth = src->maxwaistdepth;
636}
637
638/** reset tree profile statistics */
639static
641 TREEPROFILESTATS* treeprofilestats /**< tree profile statistics */
642 )
643{
644 assert(treeprofilestats != NULL);
645
646 BMSclearMemory(treeprofilestats);
647}
648
649
650/** extend tree profile to deeper tree */
651static
653 SCIP* scip, /**< SCIP data structure */
654 TREEPROFILE* treeprofile, /**< tree profile data structure */
655 int mindepth /**< minimum depth that the tree profile should hold */
656 )
657{
658 if( mindepth < treeprofile->profilesize )
659 return SCIP_OKAY;
660
661 if( treeprofile->profile == NULL )
662 {
663 SCIP_CALL( SCIPallocClearMemoryArray(scip, &treeprofile->profile, mindepth) );
664 treeprofile->profilesize = mindepth;
665 }
666 else
667 {
668 int newsize;
669 int nnewelems;
670 SCIP_Longint* newprofile;
671
672 newsize = SCIPcalcMemGrowSize(scip, mindepth + 1);
673 nnewelems = newsize - treeprofile->profilesize;
674 assert(newsize > treeprofile->profilesize);
675
676 SCIP_CALL( SCIPreallocMemoryArray(scip, &treeprofile->profile, newsize) );
677 newprofile = &treeprofile->profile[treeprofile->profilesize];
678 BMSclearMemoryArray(newprofile, nnewelems);
679 treeprofile->profilesize = newsize;
680 }
681
682 return SCIP_OKAY;
683}
684
685/** create a tree profile */
686static
688 SCIP* scip, /**< SCIP data structure */
689 TREEPROFILE** treeprofile /**< pointer to store tree profile data structure */
690 )
691{
692 assert(scip != NULL);
693 assert(treeprofile != NULL);
694
695 SCIP_CALL( SCIPallocMemory(scip, treeprofile) );
696
697 (*treeprofile)->profile = NULL;
698 (*treeprofile)->profilesize = 0;
700
701 resetTreeProfileStats(&(*treeprofile)->stats);
702 resetTreeProfileStats(&(*treeprofile)->lastestimatestats);
703
704 (*treeprofile)->lastestimate = -1.0;
705
706 return SCIP_OKAY;
707}
708
709/** free a tree profile */
710static
712 SCIP* scip, /**< SCIP data structure */
713 TREEPROFILE** treeprofile /**< pointer to tree profile data structure */
714 )
715{
716 assert(scip != NULL);
717 assert(treeprofile != NULL);
718
719 if( *treeprofile == NULL )
720 return;
721
722 SCIPfreeMemoryArray(scip, &(*treeprofile)->profile);
723
724 SCIPfreeMemory(scip, treeprofile);
725
726 *treeprofile = NULL;
727}
728
729/** update tree profile */
730static
732 SCIP* scip, /**< SCIP data structure */
733 TREEPROFILE* treeprofile, /**< tree profile data structure */
734 SCIP_NODE* node /**< node that should be added to the profile */
735 )
736{
737 int nodedepth;
738 unsigned long nbits;
739 SCIP_Longint nodedepthcnt;
740 SCIP_Longint maxnodes;
741
742 assert(scip != NULL);
743 assert(node != NULL);
744
745 if( treeprofile == NULL )
746 return SCIP_OKAY;
747
748 nodedepth = SCIPnodeGetDepth(node);
749 assert(nodedepth >= 0);
750 maxnodes = treeprofile->profile[treeprofile->stats.minwaistdepth];
751 assert(treeprofile->stats.minwaistdepth == treeprofile->stats.maxwaistdepth ||
752 maxnodes == treeprofile->profile[treeprofile->stats.maxwaistdepth]);
753
754 /* ensure that the memory can hold at least this depth */
755 SCIP_CALL( extendMemoryTreeProfile(scip, treeprofile, nodedepth) );
756
757 nodedepthcnt = ++treeprofile->profile[nodedepth];
758
759 /* Is this level fully explored? We assume binary branching. The first condition ensures that the bit shift operation
760 * of the second condition represents a feasible power of unsigned int. The largest power of 2 representable
761 * by unsigned int is 2^{8*sizeof(unsigned int) - 1}. */
762 nbits = 8*sizeof(unsigned int);
763 /* coverity[overflow_before_widen] */
764 if( (unsigned int)nodedepth < nbits && nodedepthcnt == (1U << nodedepth) )/*lint !e647*/
765 {
766 SCIPdebugMsg(scip, "Level %d fully explored: %" SCIP_LONGINT_FORMAT " nodes\n", nodedepth, nodedepthcnt);
767
768 treeprofile->stats.lastfulldepth = nodedepth;
769 }
770
771 /* update maximum depth */
772 if( treeprofile->stats.maxdepth < nodedepth )
773 {
774 treeprofile->stats.maxdepth = nodedepth;
775 SCIPdebugMsg(scip, "Maximum depth increased to %d\n", treeprofile->stats.maxdepth);
776 }
777
778 /* minimum and maximum waist now coincide */
779 if( nodedepthcnt > maxnodes )
780 {
781 treeprofile->stats.minwaistdepth = treeprofile->stats.maxwaistdepth = nodedepth;
782 SCIPdebugMsg(scip, "Updating depth of tree waist: %d (%" SCIP_LONGINT_FORMAT " nodes)\n",
783 treeprofile->stats.minwaistdepth, nodedepthcnt);
784 }
785 else if( nodedepthcnt == maxnodes )
786 {
787 /* enlarge the interval in which the waist lies */
788 if( treeprofile->stats.minwaistdepth > nodedepth )
789 treeprofile->stats.minwaistdepth = nodedepth;
790 else if( treeprofile->stats.maxwaistdepth < nodedepth )
791 treeprofile->stats.maxwaistdepth = nodedepth;
792 }
793 assert(treeprofile->stats.minwaistdepth <= treeprofile->stats.maxwaistdepth);
794
795 return SCIP_OKAY;
796}
797
798/** make a prediction of the total tree size based on the current tree profile */
799static
801 SCIP* scip, /**< SCIP data structure */
802 TREEPROFILE* treeprofile, /**< tree profile data structure */
803 SCIP_Real minnodesperdepth /**< minimum number of average nodes per depth to make a prediction */
804 )
805{
806 SCIP_Real estimate;
807 SCIP_Real growthfac;
808 int d;
809 int waist;
810
811 /* prediction is disabled */
812 if( treeprofile == NULL )
813 return -1.0;
814
815 /* two few nodes to make a prediction */
816 if( minnodesperdepth * treeprofile->stats.maxdepth > SCIPgetNNodes(scip) )
817 return -1.0;
818
819 /* reuse previous estimation if tree profile hasn't changed */
820 if( isEqualTreeProfileStats(&treeprofile->lastestimatestats, &treeprofile->stats) )
821 {
822 SCIPdebugMsg(scip, "Reusing previous estimation result %g\n", treeprofile->lastestimate);
823
824 return treeprofile->lastestimate;
825 }
826
827 /* compute the (depth of the) waist as convex combination between the minimum and maximum waist depths */
828 waist = (2 * treeprofile->stats.maxwaistdepth + treeprofile->stats.minwaistdepth) / 3;
829
830 growthfac = 2;
831 estimate = 1;
832
833 /* loop over all full levels */
834 for( d = 1; d < treeprofile->stats.lastfulldepth; ++d )
835 {
836 SCIP_Real gamma_d = 2.0;
837
838 estimate += growthfac;
839 growthfac *= gamma_d;
840 }
841
842 /* loop until the waist is reached */
843 for( ; d < waist; ++d )
844 {
845 SCIP_Real gamma_d = 2.0 - (d - treeprofile->stats.lastfulldepth + 1.0)/(waist - treeprofile->stats.lastfulldepth + 1.0);
846
847 assert(1.0 <= gamma_d && gamma_d <= 2.0);
848 estimate += growthfac;
849 growthfac *= gamma_d;
850 }
851
852 /* loop over the remaining levels */
853 for( ; d <= treeprofile->stats.maxdepth; ++d )
854 {
855 SCIP_Real gamma_d = (1.0 - (d - waist + 1.0)/(treeprofile->stats.maxdepth - waist + 1.0));
856 assert(0.0 <= gamma_d && gamma_d <= 1.0);
857
858 estimate += growthfac;
859 growthfac *= gamma_d;
860 }
861
862 /* copy tree profile statistics */
863 copyTreeProfileStats(&treeprofile->lastestimatestats, &treeprofile->stats);
864
865 treeprofile->lastestimate = estimate;
866
867 return estimate;
868}
869
870/** clean subtrees stored as priority queues */
871static
873 SCIP* scip, /**< SCIP data structure */
874 SUBTREESUMGAP* ssg /**< subtree sum gap data structure */
875 )
876{
877 assert(ssg->nsubtrees <= 1 || ssg->subtreepqueues != NULL);
878
879 /* free all previous priority queues */
880 if( ssg->nsubtrees > 1 )
881 {
882 int s;
883
884 for( s = 0; s < ssg->nsubtrees; ++s )
885 {
886 int i;
887 SCIP_PQUEUE* pqueue = ssg->subtreepqueues[s];
888 NODEINFO** nodeinfos;
889
890 assert(pqueue != NULL);
891 nodeinfos = (NODEINFO**)SCIPpqueueElems(pqueue);
892
893 /* free all remaining elements in reverse order */
894 for( i = SCIPpqueueNElems(pqueue); --i >= 0; )
895 {
896 NODEINFO* nodeinfo = nodeinfos[i];
897 assert(nodeinfo != NULL);
898 SCIPfreeBlockMemory(scip, &nodeinfo);
899 }
900
901 SCIPpqueueFree(&pqueue);
902 }
903
905 }
906
907 ssg->subtreepqueues = NULL;
908}
909
910/** reset subtree sum gap */
911static
913 SCIP* scip, /**< SCIP data structure */
914 SUBTREESUMGAP* ssg /**< subtree sum gap data structure */
915 )
916{
917 assert(ssg != NULL);
918 assert(ssg->nodes2info != NULL);
919
921
923
924 ssg->value = 1.0;
925 ssg->scalingfactor = 1.0;
926 ssg->nsubtrees = 1;
927 ssg->subtreepqueues = NULL;
929 ssg->nodelastsplit = -1L;
930
931 return SCIP_OKAY;
932}
933
934/** create a subtree sum gap */
935static
937 SCIP* scip, /**< SCIP data structure */
938 SUBTREESUMGAP** ssg /**< pointer to store subtree sum gap data structure */
939 )
940{
941 assert(scip != NULL);
942 assert(ssg != NULL);
943
944 /* allocate storage */
946 SCIP_CALL( SCIPhashmapCreate(&(*ssg)->nodes2info, SCIPblkmem(scip), INITIALSIZE) );
947
948 /* explicitly set this to skip removal of subtrees during reset */
949 (*ssg)->nsubtrees = 0;
950
951 /* reset ssg */
953
954 return SCIP_OKAY;
955}
956
957/** free a subtree sum gap */
958static
960 SCIP* scip, /**< SCIP data structure */
961 SUBTREESUMGAP** ssg /**< pointer to store subtree sum gap data structure */
962 )
963{
964 assert(scip != NULL);
965
966 if( *ssg == NULL )
967 return;
968
969 if( (*ssg)->nodes2info != NULL )
970 {
971 SCIPhashmapFree(&(*ssg)->nodes2info);
972 }
973
974 /* delete all subtree data */
976
977 SCIPfreeMemory(scip, ssg);
978}
979
980/** compare two node infos by comparing their lower bound */
981static
982SCIP_DECL_SORTPTRCOMP(compareNodeInfos)
983{
984 NODEINFO* nodeinfo1 = (NODEINFO*)elem1;
985 NODEINFO* nodeinfo2 = (NODEINFO*)elem2;
986
987 if( nodeinfo1->lowerbound < nodeinfo2->lowerbound )
988 return -1;
989 else if( nodeinfo1->lowerbound > nodeinfo2->lowerbound )
990 return 1;
991
992 return 0;
993}
994
995/** position change callback of element in priority queue */
996static
997SCIP_DECL_PQUEUEELEMCHGPOS(elemChgPosNodeInfo)
998{
999 NODEINFO* nodeinfo = (NODEINFO*)elem;
1000
1001 assert(oldpos == -1 || oldpos == nodeinfo->pos);
1002 nodeinfo->pos = newpos;
1003}
1004
1005/** store node in SSG data structure */
1006static
1008 SCIP* scip, /**< SCIP data structure */
1009 SUBTREESUMGAP* ssg, /**< subtree sum gap data structure */
1010 SCIP_NODE* node, /**< node that should be stored */
1011 int subtreeidx /**< subtree index of that node */
1012 )
1013{
1014 NODEINFO* nodeinfo;
1015
1016 assert(scip != NULL);
1017 assert(ssg != NULL);
1018 assert(node != NULL);
1019
1020 /* create a new node info */
1021 SCIP_CALL( SCIPallocBlockMemory(scip, &nodeinfo) );
1022
1023 /* store node information in data structure and insert into priority queue */
1024 nodeinfo->node = node;
1025 nodeinfo->subtreeidx = subtreeidx;
1026 nodeinfo->pos = -1;
1027 nodeinfo->lowerbound = SCIPnodeGetLowerbound(node);
1028
1029 SCIPdebugMsg(scip, "Inserting label %d for node number %" SCIP_LONGINT_FORMAT " (%p)\n",
1030 subtreeidx, SCIPnodeGetNumber(node), (void*)node);
1031
1032 assert(!SCIPhashmapExists(ssg->nodes2info, (void*)node));
1033 /* store node information in Hash Map */
1034 SCIP_CALL( SCIPhashmapInsert(ssg->nodes2info, (void*)node, (void*)nodeinfo) );
1035
1036 /* create the corresponding priority queue, if it does not exist yet */
1037 assert(subtreeidx >= 0);
1038 assert(subtreeidx < ssg->nsubtrees);
1039
1040 if( ssg->subtreepqueues[subtreeidx] == NULL )
1041 {
1042 SCIP_CALL( SCIPpqueueCreate(&ssg->subtreepqueues[subtreeidx], 5, 1.2, compareNodeInfos, elemChgPosNodeInfo) );
1043 }
1044
1045 /* insert node and ensure that its position is up to date */
1046 SCIP_CALL( SCIPpqueueInsert(ssg->subtreepqueues[subtreeidx], (void*)nodeinfo) );
1047 assert(0 <= nodeinfo->pos);
1048 assert(SCIPpqueueNElems(ssg->subtreepqueues[subtreeidx]) > nodeinfo->pos);
1049 assert(SCIPpqueueElems(ssg->subtreepqueues[subtreeidx])[nodeinfo->pos] == (void*)nodeinfo);
1050
1051 return SCIP_OKAY;
1052}
1053
1054/** split the open nodes of the current tree */
1055static
1057 SCIP* scip, /**< SCIP data structure */
1058 SUBTREESUMGAP* ssg, /**< subtree sum gap data structure */
1059 SCIP_Bool addfocusnode /**< should the focus node be a subtree, too? */
1060 )
1061{
1062 SCIP_NODE** opennodes[3];
1063 int nopennodes[3];
1064 int label;
1065 int t;
1066 int nnewsubtrees;
1067
1068 assert(scip != NULL);
1069 assert(ssg != NULL);
1070
1071 /* query the open nodes of SCIP */
1072 SCIP_CALL( SCIPgetOpenNodesData(scip, &opennodes[0], &opennodes[1], &opennodes[2], &nopennodes[0], &nopennodes[1], &nopennodes[2]) );
1073
1074 nnewsubtrees = nopennodes[0] + nopennodes[1] + nopennodes[2] + (addfocusnode ? 1 : 0);
1075
1076 /* clear hash map from entries */
1078
1079 /* delete all subtrees */
1081
1082 ssg->nsubtrees = nnewsubtrees;
1083 SCIPdebugMsg(scip, "Splitting tree into %d subtrees\n", ssg->nsubtrees);
1084
1085 /* create priority queue array */
1086 if( ssg->nsubtrees > 1 )
1087 {
1089 }
1090 else
1091 {
1092 ssg->subtreepqueues = NULL;
1093
1094 return SCIP_OKAY;
1095 }
1096
1097 /* loop over node types (leaves, siblings, children) */
1098 label = 0;
1099 for( t = 0; t < 3; ++t )
1100 {
1101 SCIP_NODE** nodes = opennodes[t];
1102 int nnodes = nopennodes[t];
1103 int n;
1104
1105 /* label each open node as new, separate subtree */
1106 for( n = 0; n < nnodes; ++n )
1107 {
1108 SCIP_NODE* node = nodes[n];
1109 SCIP_CALL( subtreeSumGapStoreNode(scip, ssg, node, label++) );
1110 }
1111 }
1112
1113 if( addfocusnode )
1114 {
1115 assert(SCIPgetFocusNode(scip) != NULL);
1117 }
1118
1119 return SCIP_OKAY;
1120}
1121
1122/** compute a gap between a lower bound and the current upper bound */
1123static
1125 SCIP* scip, /**< SCIP data structure */
1126 SCIP_Real lowerbound /**< lower bound value */
1127 )
1128{
1129 SCIP_Real db;
1130 SCIP_Real pb;
1131 SCIP_Real abspb;
1132 SCIP_Real absdb;
1133 SCIP_Real gap;
1134
1135 if( SCIPisInfinity(scip, lowerbound) || lowerbound >= SCIPgetUpperbound(scip) )
1136 return 0.0;
1137
1139 return 1.0;
1140
1141 db = SCIPretransformObj(scip, lowerbound);
1143
1144 if( SCIPisEQ(scip, db, pb) )
1145 return 0.0;
1146
1147 abspb = REALABS(pb);
1148 absdb = REALABS(db);
1149 gap = REALABS(pb - db)/MAX(abspb,absdb);
1150 gap = MIN(gap, 1.0);
1151
1152 return gap;
1153}
1154
1155/** remove node from the subtree sum gap (because it has been solved by branching or is a leaf) */
1156static
1158 SCIP* scip, /**< SCIP data structure */
1159 SUBTREESUMGAP* ssg, /**< subtree sum gap data structure */
1160 SCIP_NODE* node /**< node that should be removed */
1161 )
1162{
1163 NODEINFO* nodeinfo;
1164 int subtreeidx;
1165 int pos;
1166 SCIP_PQUEUE* pqueue;
1167
1168 if( ssg->nsubtrees <= 1 )
1169 return SCIP_OKAY;
1170
1171 nodeinfo = (NODEINFO*)SCIPhashmapGetImage(ssg->nodes2info, (void*)node);
1172
1173 /* it can happen that the node was not created via branching; search for the most recent ancestor in the queue */
1174 if( nodeinfo == NULL )
1175 {
1176 do
1177 {
1178 node = SCIPnodeGetParent(node);
1179 } while( node != NULL && (nodeinfo = (NODEINFO*)SCIPhashmapGetImage(ssg->nodes2info, (void*)node)) == NULL);
1180
1181 /* no ancestor found */
1182 if( nodeinfo == NULL )
1183 return SCIP_OKAY;
1184 }
1185
1186 /* get open nodes of this subtree stored as priority queue */
1187 subtreeidx = nodeinfo->subtreeidx;
1188 pqueue = ssg->subtreepqueues[subtreeidx];
1189 assert(pqueue != NULL);
1190
1191 /* delete the element from the priority queue */
1192 pos = nodeinfo->pos;
1193 assert(pos >= 0);
1194 assert(pos < SCIPpqueueNElems(pqueue));
1195 assert(SCIPpqueueElems(pqueue)[pos] == (void *)nodeinfo);
1196 SCIPpqueueDelPos(pqueue, pos);
1197
1198 /* update ssg if removed node was the lower bound defining node of its subtree */
1199 if( pos == 0 )
1200 {
1201 NODEINFO* nodeinfofirst;
1202 SCIP_Real oldgap;
1203 SCIP_Real newgap;
1204
1205 oldgap = calcGap(scip, nodeinfo->lowerbound);
1206 nodeinfofirst = (NODEINFO*)SCIPpqueueFirst(ssg->subtreepqueues[subtreeidx]);
1207 assert(nodeinfofirst == NULL || subtreeidx == nodeinfofirst->subtreeidx);
1208 newgap = calcGap(scip, nodeinfofirst != NULL ? nodeinfofirst->lowerbound : SCIPinfinity(scip) );
1209
1210 assert(SCIPisLE(scip, newgap, oldgap));
1211
1212 /* the SSG value is always up-to-date because it is recomputed when the primal bound changes */
1213 ssg->value += ssg->scalingfactor * MIN(newgap - oldgap, 0.0);
1214 }
1215
1216 SCIP_CALL( SCIPhashmapRemove(ssg->nodes2info, (void*)node) );
1217
1218 SCIPdebugMsg(scip, "Removed node %" SCIP_LONGINT_FORMAT " from open nodes of SSG\n",
1219 SCIPnodeGetNumber(node));
1220
1221 SCIPfreeBlockMemory(scip, &nodeinfo);
1222
1223 return SCIP_OKAY;
1224}
1225
1226/** insert children into subtree sum gap */
1227static
1229 SCIP* scip, /**< SCIP data structure */
1230 SUBTREESUMGAP* ssg /**< subtree sum gap data structure */
1231 )
1232{
1233 int nchildren;
1234 SCIP_NODE** children;
1235 SCIP_NODE* focusnode;
1236 SCIP_NODE* parentnode;
1237 NODEINFO* parentnodeinfo;
1238 int parentnodelabel;
1239 int n;
1240
1241 assert(scip != NULL);
1242 assert(ssg != NULL);
1243
1244 if( ssg->nsubtrees == 1 )
1245 return SCIP_OKAY;
1246
1247 SCIP_CALL( SCIPgetChildren(scip, &children, &nchildren) );
1248
1249 if( nchildren == 0 )
1250 return SCIP_OKAY;
1251
1252 focusnode = SCIPgetFocusNode(scip);
1253
1254 /* a rare case: the search has been stopped at some point, and the current focus node is the only descendant
1255 * of its parent node
1256 */
1257 if( !SCIPhashmapExists(ssg->nodes2info, (void*)focusnode) )
1258 {
1259 parentnode = focusnode;
1260 do
1261 {
1262 parentnode = SCIPnodeGetParent(parentnode);
1263 } while( parentnode != NULL && !SCIPhashmapExists(ssg->nodes2info, (void *)parentnode));
1264
1265 assert(parentnode != NULL && SCIPhashmapExists(ssg->nodes2info, (void *)parentnode));
1266 }
1267 else
1268 parentnode = focusnode;
1269
1270 parentnodeinfo = (NODEINFO*)SCIPhashmapGetImage(ssg->nodes2info, (void *)parentnode);
1271 parentnodelabel = parentnodeinfo->subtreeidx;
1272
1273 /* loop over children and insert the focus node label */
1274 for( n = 0; n < nchildren; ++n )
1275 {
1276 assert(SCIPnodeGetParent(children[n]) == focusnode);
1277
1279 "Inserting label %d for node number %" SCIP_LONGINT_FORMAT " (parent %" SCIP_LONGINT_FORMAT ")\n",
1280 parentnodelabel, SCIPnodeGetNumber(children[n]), SCIPnodeGetNumber(parentnode));
1281
1282 SCIP_CALL( subtreeSumGapStoreNode(scip, ssg, children[n], parentnodelabel) );
1283 }
1284
1285 /* remove focus node from hash map */
1286 SCIP_CALL( subtreeSumGapRemoveNode(scip, ssg, parentnode) );
1287
1288 return SCIP_OKAY;
1289}
1290
1291/* this function is inefficient because it loops over all open nodes, but can be used for debugging */
1292#ifdef SCIP_DISABLED_CODE
1293/** compute subtree sum gap from scratch (inefficiently because loop over all open nodes) */
1294static
1295SCIP_RETCODE subtreesumgapComputeFromScratch(
1296 SCIP* scip, /**< SCIP data structure */
1297 SUBTREESUMGAP* ssg, /**< subtree sum gap data structure */
1298 SCIP_Bool updatescaling /**< should the scaling factor be updated? */
1299 )
1300{
1301 SCIP_Real* lowerbounds;
1302 SCIP_NODE** opennodes[3];
1303 SCIP_Real gapsum = 0;
1304 SCIP_Real pb;
1305 int nopennodes[3];
1306 int l;
1307 int t;
1308
1309 /* treat trivial cases: only 1 subtree, no incumbent solution */
1311 {
1312 ssg->value = 1.0;
1313
1314 return SCIP_OKAY;
1315 }
1316
1317 /* simply use normal gap in trivial case */
1318 if( ssg->nsubtrees == 1 )
1319 {
1321
1322 return SCIP_OKAY;
1323 }
1324
1325 /* allocate temporary memory to store lower bound for every subtree */
1326 SCIP_CALL( SCIPallocBufferArray(scip, &lowerbounds, ssg->nsubtrees) );
1327
1328 /* initialize lower bounds as SCIPinfinity(scip) */
1329 for( l = 0; l < ssg->nsubtrees; ++l )
1330 lowerbounds[l] = SCIPinfinity(scip);
1331
1332 /* loop over children, siblings, and leaves to update subtree lower bounds */
1333 SCIP_CALL( SCIPgetOpenNodesData(scip, &opennodes[0], &opennodes[1], &opennodes[2], &nopennodes[0], &nopennodes[1], &nopennodes[2]) );
1334
1335 /* loop over the three types leaves, siblings, leaves */
1336 for( t = 0; t < 3; ++t )
1337 {
1338 int n;
1339 /* loop over nodes of this type */
1340 for( n = 0; n < nopennodes[t]; ++n )
1341 {
1342 SCIP_NODE* node = opennodes[t][n];
1343 NODEINFO* nodeinfo;
1344 SCIP_Real lowerbound;
1345 int label;
1346 nodeinfo = (NODEINFO*)SCIPhashmapGetImage(ssg->nodes2info, (void *)node);
1347 label = nodeinfo->subtreeidx;
1348 lowerbound = nodeinfo->lowerbound;
1349
1350 assert(label >= 0 && label < ssg->nsubtrees);
1351 lowerbounds[label] = MIN(lowerbounds[label], lowerbound);
1352 }
1353 }
1354
1355 /* compute subtree gaps in original space; sum them up */
1357 for( l = 0; l < ssg->nsubtrees; ++l )
1358 {
1359 SCIP_Real subtreedualbound;
1360 SCIP_Real subtreegap;
1361 /* skip subtrees with infinite lower bound; they are empty and contribute 0.0 to the gap sum term */
1362 if( SCIPisInfinity(scip, lowerbounds[l]) )
1363 continue;
1364
1365 subtreedualbound = SCIPretransformObj(scip, lowerbounds[l]);
1366
1367 if( SCIPisEQ(scip, subtreedualbound, pb) )
1368 continue;
1369
1370 subtreegap = REALABS(pb - subtreedualbound)/MAX(REALABS(pb),REALABS(subtreedualbound));
1371 subtreegap = MIN(subtreegap, 1.0);
1372
1373 gapsum += subtreegap;
1374 }
1375
1376 /* update the scaling factor by using the previous SSG value divided by the current gapsum */
1377 if( updatescaling )
1378 {
1379 ssg->scalingfactor = ssg->value / MAX(gapsum, 1e-6);
1380 }
1381
1382 /* update and store SSG value by considering scaling factor */
1383 ssg->value = ssg->scalingfactor * gapsum;
1384
1385 SCIPfreeBufferArray(scip, &lowerbounds);
1386
1387 return SCIP_OKAY;
1388}
1389#endif
1390
1391/** compute subtree sum gap from scratch efficiently (linear effort in the number of subtrees) */
1392static
1394 SCIP* scip, /**< SCIP data structure */
1395 SUBTREESUMGAP* ssg, /**< subtree sum gap data structure */
1396 SCIP_Bool updatescaling /**< should the scaling factor be updated? */
1397 )
1398{
1399 SCIP_Real gapsum = 0.0;
1400 int l;
1401
1402 /* treat trivial cases: only 1 subtree, no incumbent solution */
1404 {
1405 ssg->value = 1.0;
1406
1407 return SCIP_OKAY;
1408 }
1409
1410 if( ssg->nsubtrees == 1 )
1411 {
1413
1414 return SCIP_OKAY;
1415 }
1416
1417 /* compute subtree gaps in original space; sum them up */
1418 for( l = 0; l < ssg->nsubtrees; ++l )
1419 {
1420 SCIP_Real subtreegap;
1421 NODEINFO* nodeinfo;
1422
1423 assert(ssg->subtreepqueues[l] != NULL);
1424
1425 nodeinfo = (NODEINFO*)SCIPpqueueFirst(ssg->subtreepqueues[l]);
1426
1427 /* skip subtrees with infinite lower bound; they are empty and contribute 0.0 to the gap sum term */
1428 if( nodeinfo == NULL || SCIPisInfinity(scip, nodeinfo->lowerbound) )
1429 continue;
1430
1431 subtreegap = calcGap(scip, nodeinfo->lowerbound);
1432
1433 gapsum += subtreegap;
1434 }
1435
1436 /* update the scaling factor by using the previous SSG value divided by the current gapsum */
1437 if( updatescaling )
1438 {
1439 ssg->scalingfactor = ssg->value / MAX(gapsum, 1e-6);
1440 }
1441
1442 /* update and store SSG value by considering scaling factor */
1443 ssg->value = ssg->scalingfactor * gapsum;
1444
1445 return SCIP_OKAY;
1446}
1447
1448/** update the subtree sum gap after a node event (branching or deletion of a node) */
1449static
1451 SCIP* scip, /**< SCIP data structure */
1452 SUBTREESUMGAP* ssg, /**< subtree sum gap data structure */
1453 SCIP_NODE* node, /**< the corresponding node */
1454 int nchildren, /**< number of children */
1455 SCIP_Longint nsolvednodes /**< number of solved nodes so far, used as a time stamp */
1456 )
1457{
1458 SCIP_Bool insertchildren = (ssg->nsubtrees > 1 && nchildren > 0);
1459
1460 /* if the instance is solved or a node is cutoff at the initsolve stage or we are unbounded, the ssg is 0 */
1462 {
1463 ssg->value = 0.0;
1464
1465 return SCIP_OKAY;
1466 }
1467
1468 /* make a new tree split if the primal bound has changed. */
1470 {
1471 int nnewsubtrees;
1472 SCIP_Bool addfocusnode;
1473
1475 nnewsubtrees = SCIPgetNSiblings(scip) + SCIPgetNLeaves(scip) + SCIPgetNChildren(scip) + (addfocusnode ? 1 : 0);
1476
1477 /* check if number of new subtrees does not exceed maximum number of subtrees; always split if no split happened, yet */
1478 if( ssg->nsubtrees <= 1 ||
1479 ((ssg->nmaxsubtrees == -1 || nnewsubtrees <= ssg->nmaxsubtrees) &&
1480 (nsolvednodes - ssg->nodelastsplit >= ssg->nminnodeslastsplit)) )
1481 {
1482 SCIP_CALL( subtreeSumGapSplit(scip, ssg, addfocusnode) );
1483
1484 /* remember time stamp */
1485 ssg->nodelastsplit = nsolvednodes;
1486 }
1487 else
1488 {
1489 if( ssg->nmaxsubtrees != -1 && nnewsubtrees >= ssg->nmaxsubtrees )
1490 {
1491 SCIPdebugMsg(scip, "Keep split into %d subtrees because new split into %d subtrees exceeds limit %d\n",
1492 ssg->nsubtrees, nnewsubtrees, ssg->nmaxsubtrees);
1493 }
1494 else
1495 {
1496 SCIPdebugMsg(scip, "Keep split into %d subtrees from %" SCIP_LONGINT_FORMAT " nodes ago\n",
1497 ssg->nsubtrees, nsolvednodes - ssg->nodelastsplit);
1498 }
1499
1500 /* no new split has happened; insert the new children to their SSG subtree */
1501 if( insertchildren )
1502 {
1504 }
1505 }
1506
1508
1509 /* compute the current SSG value from scratch */
1511 }
1512 /* otherwise, if new children have been created, label them */
1513 else if( insertchildren )
1514 {
1516 }
1517
1518 /* remove the node from the hash map if it is a leaf */
1519 if( nchildren == 0 )
1520 {
1521 SCIP_CALL( subtreeSumGapRemoveNode(scip, ssg, node) );
1522 }
1523
1524 return SCIP_OKAY;
1525}
1526
1527/** reset tree data */
1528static
1530 SCIP* scip, /**< SCIP data structure */
1531 TREEDATA* treedata /**< tree data */
1532 )
1533{
1534 /* simply set everything to 0 */
1535 treedata->ninner = treedata->nleaves = treedata->nvisited = 0L;
1536 treedata->weight = 0.0;
1537
1538 /* set up root node */
1539 treedata->nnodes = 1;
1540 treedata->nopen = 1;
1541
1542 SCIP_CALL( subtreeSumGapReset(scip, treedata->ssg) );
1543
1544 return SCIP_OKAY;
1545}
1546
1547/** create tree data structure */
1548static
1550 SCIP* scip, /**< SCIP data structure */
1551 TREEDATA** treedata /**< pointer to store tree data */
1552 )
1553{
1554 assert(treedata != NULL);
1555 assert(scip != NULL);
1556
1557 SCIP_CALL( SCIPallocMemory(scip, treedata) );
1558
1559 SCIP_CALL( subtreeSumGapCreate(scip, &(*treedata)->ssg) );
1560
1561 SCIP_CALL( resetTreeData(scip, *treedata) );
1562
1563 return SCIP_OKAY;
1564}
1565
1566/** free tree data structure */
1567static
1569 SCIP* scip, /**< SCIP data structure */
1570 TREEDATA** treedata /**< pointer to tree data */
1571 )
1572{
1573 assert(scip != NULL);
1574
1575 if( *treedata == NULL )
1576 return;
1577
1578 subtreeSumGapFree(scip, &(*treedata)->ssg);
1579
1580 SCIPfreeMemory(scip, treedata);
1581 *treedata = NULL;
1582}
1583
1584/** update tree data structure after a node has been solved/is about to be deleted */
1585static
1587 SCIP* scip, /**< SCIP data structure */
1588 TREEDATA* treedata, /**< tree data */
1589 SCIP_NODE* node, /**< the corresponding node */
1590 int nchildren /**< the number of children */
1591 )
1592{
1593 assert(node != NULL);
1594
1595 ++treedata->nvisited;
1596 treedata->nopen--;
1597
1598 if( nchildren == 0 )
1599 {
1600 int depth = SCIPnodeGetDepth(node);
1601 treedata->nleaves++;
1602 treedata->weight += pow(0.5, (SCIP_Real)depth);
1603 }
1604 else
1605 {
1606 treedata->nnodes += nchildren;
1607 treedata->nopen += nchildren;
1608 ++treedata->ninner;
1609 }
1610
1611 /* update the subtree sum gap */
1612 if( ! SCIPisInRestart(scip) )
1613 {
1614 SCIP_CALL( subtreeSumGapUpdate(scip, treedata->ssg, node, nchildren, treedata->nvisited) );
1615 }
1616
1617 return SCIP_OKAY;
1618}
1619
1620/** get weighted backtrack estimation from this tree data */
1621static
1623 TREEDATA* treedata /**< tree data */
1624 )
1625{
1626 if( treedata->weight <= 0.0 || treedata->nleaves == 0 )
1627 return -1.0;
1628
1629 return 2.0 * treedata->nleaves / (SCIP_Real)treedata->weight - 1.0;
1630}
1631
1632#ifdef SCIP_DEBUG
1633/* print method for tree data */
1634static
1635char* treeDataPrint(
1636 TREEDATA* treedata, /**< tree data */
1637 char* strbuf /**< string buffer */
1638 )
1639{
1640 (void )SCIPsnprintf(strbuf, SCIP_MAXSTRLEN,
1641 "Tree Data: %" SCIP_LONGINT_FORMAT " nodes ("
1642 "%" SCIP_LONGINT_FORMAT " visited, "
1643 "%" SCIP_LONGINT_FORMAT " inner, "
1644 "%" SCIP_LONGINT_FORMAT " leaves, "
1645 "%" SCIP_LONGINT_FORMAT " open), "
1646 "weight: %.4Lf, ssg %.4f",
1647 treedata->nnodes,
1648 treedata->nvisited,
1649 treedata->ninner,
1650 treedata->nleaves,
1651 treedata->nopen,
1652 treedata->weight,
1653 treedata->ssg->value
1654 );
1655 return strbuf;
1656}
1657#endif
1658
1659/** reset double exponential smoothing */
1660static
1662 DOUBLEEXPSMOOTH* des, /**< double exponential smoothing data structure */
1663 SCIP_Real initialvalue /**< the initial value */
1664 )
1665{
1666 des->n = 0;
1667 des->level = SCIP_INVALID;
1668 des->trend = SCIP_INVALID;
1669 des->initialvalue = initialvalue;
1670}
1671
1672/** initialize a double exponential smoothing data structure */
1673static
1675 DOUBLEEXPSMOOTH* des, /**< double exponential smoothing data structure */
1676 SCIP_Real x1 /**< the first sample value */
1677 )
1678{
1679 assert(des != NULL);
1680
1681 des->n = 1;
1682 des->level = x1;
1683 des->trend = x1 - des->initialvalue;
1684
1686
1687 return;
1688}
1689
1690/** update a double exponential smoothing data structure */
1691static
1693 DOUBLEEXPSMOOTH* des, /**< double exponential smoothing data structure */
1694 SCIP_Real xnew /**< new sample value */
1695 )
1696{
1697 if( des->n == 0 )
1698 doubleExpSmoothInit(des, xnew);
1699 else
1700 {
1701 SCIP_Real newlevel;
1702 SCIP_Real newtrend;
1703
1704 newlevel = des->alpha * xnew + (1.0 - des->alpha) * (des->level + (des->usetrendinlevel ? des->trend : 0.0));
1705 newtrend = des->beta * (newlevel - des->level) + (1.0 - des->beta) * des->trend;
1706
1707 des->level = newlevel;
1708 des->trend = newtrend;
1709 }
1710}
1711
1712/** get the current trend (slope) computed by this double exponential smoothing */
1713static
1715 DOUBLEEXPSMOOTH* des /**< double exponential smoothing data structure */
1716 )
1717{
1718 assert(des != NULL);
1719
1720 if( des->n == 0 )
1721 return SCIP_INVALID;
1722
1723 return des->trend;
1724}
1725
1726/** reset time series */
1727static
1729 TIMESERIES* timeseries /**< pointer to store time series */
1730 )
1731{
1732 timeseries->resolution = 1;
1733 timeseries->nvals = 0;
1734 timeseries->nobs = 0L;
1735 timeseries->currentvalue = timeseries->initialvalue;
1736 timeseries->smoothestimation = SCIP_INVALID;
1737
1738 doubleExpSmoothReset(&timeseries->des, timeseries->initialvalue);
1739}
1740
1741/** create a time series object */
1742static
1744 SCIP* scip, /**< SCIP data structure */
1745 TIMESERIES** timeseries, /**< pointer to store time series */
1746 const char* name, /**< name of this time series */
1747 SCIP_Real targetvalue, /**< target value of this time series */
1748 SCIP_Real initialvalue, /**< the initial value of time series */
1749 SCIP_Real alpha, /**< alpha parameter (level weight) for double exponential smoothing */
1750 SCIP_Real beta, /**< beta parameter (level weight) for double exponential smoothing */
1751 DECL_TIMESERIESUPDATE ((*timeseriesupdate)) /**< update callback at nodes, or NULL */
1752 )
1753{
1754 TIMESERIES* timeseriesptr;
1755 assert(scip != NULL);
1756 assert(timeseries != NULL);
1757 assert(name != NULL);
1758 assert(alpha >= 0.0 && alpha <= 1);
1759 assert(beta >= 0.0 && beta <= 1);
1760
1761 SCIP_CALL( SCIPallocMemory(scip, timeseries) );
1762
1763 timeseriesptr = *timeseries;
1764 assert(timeseriesptr != NULL);
1765
1766 /* copy name */
1767 SCIP_ALLOC( BMSduplicateMemoryArray(&timeseriesptr->name, name, strlen(name)+1) );
1768
1769 /* copy callbacks */
1770 assert(timeseriesupdate != NULL);
1771 timeseriesptr->timeseriesupdate = timeseriesupdate;
1772
1773 timeseriesptr->targetvalue = targetvalue;
1774 timeseriesptr->valssize = 1024;
1775 timeseriesptr->initialvalue = initialvalue;
1776
1777 SCIP_CALL( SCIPallocMemoryArray(scip, &timeseriesptr->vals, timeseriesptr->valssize) );
1778 SCIP_CALL( SCIPallocMemoryArray(scip, &timeseriesptr->estimation, timeseriesptr->valssize) );
1779
1780 timeSeriesReset(timeseriesptr);
1781
1782 timeseriesptr->des.alpha = alpha;
1783 timeseriesptr->des.beta = beta;
1784
1785 SCIPdebugMsg(scip, "Finished creation of time series '%s'\n", timeseriesptr->name);
1786
1787 return SCIP_OKAY;
1788}
1789
1790/** free a time series */
1791static
1793 SCIP* scip, /**< SCIP data structure */
1794 TIMESERIES** timeseries /**< pointer to time series */
1795 )
1796{
1797 assert(scip != NULL);
1798 assert(timeseries != NULL);
1799
1800 BMSfreeMemoryArray(&(*timeseries)->name);
1801
1802 SCIPfreeMemoryArray(scip, &(*timeseries)->vals);
1803 SCIPfreeMemoryArray(scip, &(*timeseries)->estimation);
1804
1805 SCIPfreeMemory(scip, timeseries);
1806
1807 *timeseries = NULL;
1808}
1809
1810/** get current value of time series */
1811static
1813 TIMESERIES* timeseries /**< time series */
1814 )
1815{
1816 assert(timeseries != NULL);
1817
1818 return timeseries->currentvalue;
1819}
1820
1821/** get target value (which this time series reaches at the end of the solution process) */
1822static
1824 TIMESERIES* timeseries /**< time series */
1825 )
1826{
1827 return timeseries->targetvalue;
1828}
1829
1830/** get resolution of time series */
1831static
1833 TIMESERIES* timeseries /**< time series */
1834 )
1835{
1836 return timeseries->resolution;
1837}
1838
1839/** estimate tree size at which time series reaches target value */
1840static
1842 TIMESERIES* timeseries, /**< time series */
1843 TREEDATA* treedata /**< tree data for fallback estimation */
1844 )
1845{
1846 SCIP_Real val;
1847 SCIP_Real targetval;
1848 SCIP_Real trend;
1849 SCIP_Real estimated;
1850 const SCIP_Real tolerance = 1e-6;
1851
1852 /* if no observations have been made yet, return infinity */
1853 if( timeseries->nobs == 0L )
1854 return -1.0;
1855
1856 val = timeSeriesGetValue(timeseries);
1857 targetval = timeSeriesGetTargetValue(timeseries);
1858
1859 /* if the value has reached the target value already, return the number of observations */
1860 if( EPSZ(val - targetval, tolerance) )
1861 return treedata->nnodes;
1862
1863 trend = doubleExpSmoothGetTrend(&timeseries->des);
1864
1865 /* Get current value and trend. The linear trend estimation may point into the wrong direction
1866 * In this case, we use the fallback mechanism that we will need twice as many nodes.
1867 */
1868 if( (targetval > val && trend < tolerance) || (targetval < val && trend > -tolerance) )
1869 {
1870 return 2.0 * treedata->nvisited;
1871 }
1872
1873 /* compute after how many additional steps the current trend reaches the target value; multiply by resolution */
1874 estimated = timeSeriesGetResolution(timeseries) * (timeseries->nvals + (targetval - val) / (SCIP_Real)trend);
1875 return timeseries->useleafts ? 2.0 * estimated - 1.0 : estimated;
1876}
1877
1878/** update time series smoothened estimation */
1879static
1881 TIMESERIES* timeseries, /**< time series */
1882 SCIP_Real estimation /**< estimation value */
1883 )
1884{
1885 if( timeseries->smoothestimation == SCIP_INVALID )/*lint !e777*/
1886 timeseries->smoothestimation = estimation;
1887 else
1888 {
1889 timeseries->smoothestimation *= (1.0 - SESCOEFF);
1890 timeseries->smoothestimation += SESCOEFF * estimation;
1891 }
1892}
1893
1894/** get smooth estimation of time series */
1895static
1897 TIMESERIES* timeseries /**< time series */
1898 )
1899{
1900 return timeseries->smoothestimation;
1901}
1902
1903/** resample to lower resolution */
1904static
1906 TIMESERIES* timeseries /**< time series */
1907 )
1908{
1909 DOUBLEEXPSMOOTH* des;
1910 int i;
1911
1912 assert(timeseries->nvals % 2 == 0);
1913
1914 des = &timeseries->des;
1915 doubleExpSmoothReset(des, timeseries->initialvalue);
1916
1917 /* compress vals array to store only every second entry */
1918 for( i = 0; i < timeseries->nvals / 2; ++i )
1919 {
1920 timeseries->vals[i] = timeseries->vals[2 * i];
1921 timeseries->estimation[i] = timeseries->estimation[2 * i];
1922 doubleExpSmoothUpdate(des, timeseries->vals[i]);
1923 timeSeriesUpdateSmoothEstimation(timeseries, timeseries->estimation[i]);
1924 }
1925
1926 timeseries->resolution *= 2;
1927 timeseries->nvals = timeseries->nvals / 2;
1928}
1929
1930/** update time series */
1931static
1933 SCIP* scip, /**< SCIP data structure */
1934 TIMESERIES* timeseries, /**< time series */
1935 TREEDATA* treedata, /**< tree data */
1936 SCIP_Bool isleaf /**< are we at a leaf node? */
1937 )
1938{
1939 SCIP_Real value;
1940
1941 assert(scip != NULL);
1942 assert(timeseries != NULL);
1943 assert(treedata != NULL);
1944
1945 /* call update callback */
1946 assert(timeseries->timeseriesupdate != NULL);
1947 SCIP_CALL( timeseries->timeseriesupdate(scip, timeseries, treedata, &value) );
1948
1949 /* store the value as current value */
1950 timeseries->currentvalue = value;
1951
1952 if( timeseries->useleafts && ! isleaf )
1953 return SCIP_OKAY;
1954
1955 timeseries->nobs++;
1956
1957 /* if this is a leaf that matches the time series resolution, store the value */
1958 if( timeseries->nobs % timeseries->resolution == 0 )
1959 {
1960 int tspos;
1961 SCIP_Real estimate;
1962
1963 assert(timeseries->nvals < timeseries->valssize);
1964 tspos = timeseries->nvals++;
1965 timeseries->vals[tspos] = value;
1966 doubleExpSmoothUpdate(&timeseries->des, value);
1967 estimate = timeSeriesEstimate(timeseries, treedata);
1968 timeseries->estimation[tspos] = estimate;
1969 timeSeriesUpdateSmoothEstimation(timeseries, estimate);
1970 }
1971
1972 /* if the time series has reached its capacity, resample and increase the resolution */
1973 if( timeseries->nvals == timeseries->valssize )
1974 timeSeriesResample(timeseries);
1975
1976 return SCIP_OKAY;
1977}
1978
1979/** get name of time series */
1980static
1982 TIMESERIES* timeseries /**< time series */
1983 )
1984{
1985 return timeseries->name;
1986}
1987
1988/** reset all time series */
1989static
1991 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
1992 )
1993{
1994 TIMESERIES** tss = eventhdlrdata->timeseries;
1995 int t;
1996
1997 /* loop over time series and reset them */
1998 for( t = 0; t < NTIMESERIES; ++t )
1999 {
2000 assert(tss[t] != NULL);
2001 timeSeriesReset(tss[t]);
2002
2003 tss[t]->useleafts = eventhdlrdata->useleafts;
2004 }
2005}
2006
2007/*
2008 * Callback methods of event handler
2009 */
2010
2011/** free all time series */
2012static
2014 SCIP* scip, /**< SCIP data structure */
2015 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
2016 )
2017{
2018 TIMESERIES** tss = eventhdlrdata->timeseries;
2019 int t;
2020
2021 /* loop over time series and reset them */
2022 for( t = 0; t < NTIMESERIES; ++t )
2023 {
2024 assert(tss[t] != NULL);
2025 timeSeriesFree(scip, &tss[t]);
2026 }
2027}
2028
2029/** get ensemble tree size estimation as a combination of the individual time series estimations
2030 *
2031 * the coefficients have been computed based on a nonlinear fit on a broad set of publicly available
2032 * MIP instances; please refer to the publication at the top of this file for further details.
2033 */
2034static
2036 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
2037 )
2038{
2039 TREEDATA* treedata;
2040 SCIP_Real* coeffs;
2041 SCIP_Real estim;
2042 int t;
2043
2044 TSPOS tsposs[] = {
2045 TSPOS_GAP,
2048 TSPOS_SSG,
2050 };
2051
2052 /* coefficients for the early stage (tree weight <= 0.3) */
2053 SCIP_Real coeffs_early[] = {
2054 0.002, /* gap */
2055 0.381, /* tree weight */
2056 0.469, /* leaf-frequency */
2057 0.292, /* SSG */
2058 0.004 /* open-nodes */
2059 };
2060
2061 /* coefficients for the intermediate stage (0.3 < tree weight <= 0.6) */
2062 SCIP_Real coeffs_intermediate[] = {
2063 0.011, /* gap */
2064 0.193, /* tree weight */
2065 0.351, /* leaf-frequency */
2066 0.012, /* SSG */
2067 0.051 /* open-nodes */
2068 };
2069
2070 /* coefficients for the late stage (tree weight > 0.6) */
2071 SCIP_Real coeffs_late[] = {
2072 0.000, /* gap */
2073 0.033, /* tree weight */
2074 0.282, /* leaf-frequency */
2075 0.003, /* SSG */
2076 0.024 /* open-nodes */
2077 };
2078
2079 assert(eventhdlrdata != NULL);
2080 treedata = eventhdlrdata->treedata;
2081
2082 /* assign coeffs based on stage */
2083 if( treedata->weight <= 0.3 )
2084 {
2085 estim = 0.0;
2086 coeffs = coeffs_early;
2087 /* ensure that coeffs and time series are still aligned */
2088 assert(sizeof(coeffs_early)/sizeof(SCIP_Real) == NTIMESERIES); /*lint !e506*/
2089 }
2090 else if( treedata->weight <= 0.6 )
2091 {
2092 coeffs = coeffs_intermediate;
2093 /* ensure that coeffs and time series are still aligned */
2094 assert(sizeof(coeffs_intermediate)/sizeof(SCIP_Real) == NTIMESERIES); /*lint !e506*/
2095
2096 /* initialize by intermediate WBE coefficient */
2097 estim = 0.156 * treeDataGetWbe(treedata);
2098 }
2099 else
2100 {
2101 coeffs = coeffs_late;
2102 /* ensure that coeffs and time series are still aligned */
2103 assert(sizeof(coeffs_late)/sizeof(SCIP_Real) == NTIMESERIES); /*lint !e506*/
2104
2105 /* initialize by late WBE coefficient */
2106 estim = 0.579 * treeDataGetWbe(treedata);
2107 }
2108
2109 /* combine estimation using the stage-dependent coefficients */
2110 for( t = 0; t < NTIMESERIES; ++t )
2111 {
2112 SCIP_Real testim;
2113 TSPOS tspos = tsposs[t];
2114 testim = timeSeriesEstimate(eventhdlrdata->timeseries[tspos], treedata);
2115
2116 if( testim < 0.0 )
2117 testim = treedata->nnodes;
2118
2119 estim += coeffs[t] * testim;
2120 }
2121
2122 if( estim < treedata->nnodes )
2123 return (SCIP_Real)treedata->nnodes;
2124 else
2125 return estim;
2126}
2127
2128/** get approximation of search tree completion depending on the selected method */
2129static
2131 SCIP_EVENTHDLRDATA* eventhdlrdata, /**< event handler data */
2132 SCIP_Real* completed /**< pointer to store the search tree completion */
2133 )
2134{
2135 SCIP_Real values[9];
2136 TREEDATA* treedata;
2137 char completiontype;
2138
2139 assert(eventhdlrdata != NULL);
2140 treedata = eventhdlrdata->treedata;
2141 completiontype = eventhdlrdata->completiontypeparam;
2142
2143 /* infer automatic completion type
2144 *
2145 * use regression forest if available,
2146 * or
2147 * use monotone regression if both SSG and tree weight are meaningful;
2148 * or
2149 * use tree weight or SSG, depending which one is available,
2150 * or
2151 * use gap, which is always available
2152 */
2153 if( completiontype == COMPLETIONTYPE_AUTO )
2154 {
2155 SCIP_Bool useweight = eventhdlrdata->treeisbinary;
2156 SCIP_Bool usessg = treedata->ssg->pblastsplit != SSG_STARTPRIMBOUND;/*lint !e777*/
2157
2158 if( eventhdlrdata->regforest != NULL )
2159 completiontype = COMPLETIONTYPE_REGFOREST;
2160 else if( useweight && usessg )
2161 completiontype = COMPLETIONTYPE_MONOREG;
2162 else if( useweight )
2163 completiontype = COMPLETIONTYPE_TREEWEIGHT;
2164 else if( usessg )
2165 completiontype = COMPLETIONTYPE_SSG;
2166 else
2167 completiontype = COMPLETIONTYPE_GAP;
2168 }
2169
2170 /* compute the search tree completion based on the selected method */
2171 switch (completiontype)
2172 {
2173 /* use regression forest */
2175 values[0] = timeSeriesGetValue(eventhdlrdata->timeseries[TSPOS_TREEWEIGHT]);
2176 values[1] = doubleExpSmoothGetTrend(&eventhdlrdata->timeseries[TSPOS_TREEWEIGHT]->des);
2177 values[2] = timeSeriesGetValue(eventhdlrdata->timeseries[TSPOS_SSG]);
2178 values[3] = doubleExpSmoothGetTrend(&eventhdlrdata->timeseries[TSPOS_SSG]->des);
2179 values[4] = timeSeriesGetValue(eventhdlrdata->timeseries[TSPOS_LFREQ]);
2180 values[5] = doubleExpSmoothGetTrend(&eventhdlrdata->timeseries[TSPOS_LFREQ]->des);
2181 values[6] = timeSeriesGetValue(eventhdlrdata->timeseries[TSPOS_GAP]);
2182 values[7] = doubleExpSmoothGetTrend(&eventhdlrdata->timeseries[TSPOS_GAP]->des);
2183 values[8] = doubleExpSmoothGetTrend(&eventhdlrdata->timeseries[TSPOS_OPEN]->des) < 0 ? 1.0 : 0.0;
2184
2185 *completed = SCIPregForestPredict(eventhdlrdata->regforest, values);
2186 break;
2187
2188 /* interpolate between ssg and tree weight */
2190 *completed = eventhdlrdata->coefmonoweight * (SCIP_Real)treedata->weight +
2191 eventhdlrdata->coefmonossg * (1.0 - treedata->ssg->value);
2192 break;
2193
2195 *completed = (SCIP_Real)treedata->weight;
2196 break;
2197
2198 case COMPLETIONTYPE_GAP:
2199 *completed = timeSeriesGetValue(eventhdlrdata->timeseries[TSPOS_GAP]); /* gap is stored as 1 - gap */
2200 break;
2201
2202 case COMPLETIONTYPE_SSG:
2203 *completed = 1.0 - treedata->ssg->value; /* ssg is decreasing */
2204 break;
2205
2206 default:
2207 SCIPerrorMessage("Unsupported completion type '%c'\n", completiontype);
2208 SCIPABORT();
2210 }
2211 return SCIP_OKAY;
2212}
2213
2214/** tree size estimation based on search tree completion */
2215static
2217 SCIP* scip, /**< SCIP data structure */
2218 SCIP_EVENTHDLRDATA* eventhdlrdata, /**< event handler data */
2219 SCIP_Real* estim /**< pointer to store the estimation value */
2220 )
2221{
2222 SCIP_Real completed;
2223
2224 *estim = -1.0;
2225
2226 SCIP_CALL( getSearchCompletion(eventhdlrdata, &completed) );
2227
2228 completed = MIN(completed, 1.0);
2229
2230 if( completed > 0.0 )
2231 *estim = SCIPgetNNodes(scip) / completed;
2232
2233 return SCIP_OKAY;
2234}
2235
2236/** update callback at nodes */
2237static
2238DECL_TIMESERIESUPDATE(timeseriesUpdateGap)
2239{ /*lint --e{715}*/
2240 SCIP_Real primalbound;
2241 SCIP_Real dualbound;
2242
2243 assert(scip != NULL);
2244 assert(ts != NULL);
2245 assert(value != NULL);
2246
2247 /* avoid to call SCIPgetDualbound during a restart where the queue is simply emptied */
2248 if( SCIPisInRestart(scip) )
2249 {
2250 *value = timeSeriesGetValue(ts);
2251
2252 return SCIP_OKAY;
2253 }
2254
2255 primalbound = SCIPgetPrimalbound(scip);
2256 dualbound = SCIPgetDualbound(scip);
2257 if( SCIPisInfinity(scip, REALABS(primalbound)) || SCIPisInfinity(scip, REALABS(dualbound)) )
2258 *value = 0;
2259 else if( SCIPisEQ(scip, primalbound, dualbound) )
2260 *value = 1.0;
2261 else
2262 {
2263 SCIP_Real abspb;
2264 SCIP_Real absdb;
2265
2266 abspb = REALABS(primalbound);
2267 absdb = REALABS(dualbound);
2268 *value = 1.0 - REALABS(primalbound - dualbound)/MAX(abspb, absdb);
2269 }
2270
2271 /* using this max, we set the closed gap to 0 in the case where the primal and dual bound differ in their sign */
2272 *value = MAX(*value, 0.0);
2273
2274 return SCIP_OKAY;
2275}
2276
2277/** update callback at nodes */
2278static
2279DECL_TIMESERIESUPDATE(timeseriesUpdateTreeWeight)
2280{ /*lint --e{715}*/
2281 *value = (SCIP_Real)treedata->weight;
2282
2283 return SCIP_OKAY;
2284}
2285
2286/** update callback at nodes */
2287static
2288DECL_TIMESERIESUPDATE(timeseriesUpdateLeafFreq)
2289{ /*lint --e{715}*/
2290 if( treedata->nvisited == 0 )
2291 *value = -0.5;
2292 else
2293 *value = (treedata->nleaves - 0.5)/(SCIP_Real)treedata->nvisited;
2294
2295 return SCIP_OKAY;
2296}
2297
2298/** update callback at nodes */
2299static
2300DECL_TIMESERIESUPDATE(timeseriesUpdateSsg)
2301{ /*lint --e{715}*/
2302 if( treedata->nvisited == 0 )
2303 *value = 1.0;
2304 else
2305 *value = treedata->ssg->value;
2306
2307 return SCIP_OKAY;
2308}
2309
2310/** update callback at nodes */
2311static
2312DECL_TIMESERIESUPDATE(timeseriesUpdateOpenNodes)
2313{ /*lint --e{715}*/
2314 if( treedata->nvisited == 0 )
2315 *value = 0.0;
2316 else
2317 *value = (SCIP_Real)treedata->nopen;
2318
2319 return SCIP_OKAY;
2320}
2321
2322/** include time series to forecast into event handler */
2323static
2325 SCIP* scip, /**< SCIP data structure */
2326 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
2327 )
2328{
2329 assert(scip != NULL);
2330 assert(eventhdlrdata != NULL);
2331
2332 /* include gap time series */
2333 SCIP_CALL( timeSeriesCreate(scip, &eventhdlrdata->timeseries[TSPOS_GAP], "gap", 1.0, 0.0,
2334 DES_ALPHA_GAP, DES_BETA_GAP, timeseriesUpdateGap) );
2335
2336 /* include tree weight time series */
2337 SCIP_CALL( timeSeriesCreate(scip, &eventhdlrdata->timeseries[TSPOS_TREEWEIGHT], "tree-weight", 1.0, 0.0,
2338 DES_ALPHA_TREEWEIGHT, DES_BETA_TREEWEIGHT, timeseriesUpdateTreeWeight) );
2339
2340 /* include leaf time series */
2341 SCIP_CALL( timeSeriesCreate(scip, &eventhdlrdata->timeseries[TSPOS_LFREQ], "leaf-frequency", 0.5, -0.5,
2342 DES_ALPHA_LEAFFREQUENCY, DES_BETA_LEAFFREQUENCY, timeseriesUpdateLeafFreq) );
2343
2344 /* include SSG time series */
2345 SCIP_CALL( timeSeriesCreate(scip, &eventhdlrdata->timeseries[TSPOS_SSG], "ssg", 0.0, 1.0,
2346 DES_ALPHA_SSG, DES_BETA_SSG, timeseriesUpdateSsg) );
2347
2348 /* include open nodes time series */
2349 SCIP_CALL( timeSeriesCreate(scip, &eventhdlrdata->timeseries[TSPOS_OPEN], "open-nodes", 0.0, 0.0,
2350 DES_ALPHA_OPENNODES, DES_BETA_OPENNODES, timeseriesUpdateOpenNodes) );
2351
2352 return SCIP_OKAY;
2353}
2354
2355/** get restartpolicy based on the value of the restart parameter */
2356static
2358 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
2359 )
2360{
2361 switch (eventhdlrdata->restartpolicyparam)
2362 {
2364 return RESTARTPOLICY_ALWAYS;
2366 return RESTARTPOLICY_NEVER;
2371 default:
2372 SCIPerrorMessage("Unknown restart policy %c\n", eventhdlrdata->restartpolicyparam);
2373 break;
2374 }
2375
2376 return RESTARTPOLICY_NEVER;
2377}
2378
2379/** check if a restart is applicable considering limit and threshold user parameters */
2380static
2382 SCIP* scip, /**< SCIP data structure */
2383 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
2384 )
2385{
2387
2388 /* if there are no root node integer fixings, restart is usually not helpful */
2390 return FALSE;
2391
2392 /* check whether to apply restarts when there are active pricers available */
2393 if( SCIPgetNActivePricers(scip) > 0 && ! eventhdlrdata->restartactpricers )
2394 return FALSE;
2395
2396 /* check whether to apply a restart when nonlinear constraints are present */
2397 if( SCIPisNLPConstructed(scip) && ! eventhdlrdata->restartnonlinear )
2398 return FALSE;
2399
2400 /* check if max number of restarts has been reached */
2401 if( eventhdlrdata->restartlimit != -1 && eventhdlrdata->nrestartsperformed >= eventhdlrdata->restartlimit )
2402 return FALSE;
2403
2404 /* check if number of nodes exceeds the minimum number of nodes */
2405 if( eventhdlrdata->countonlyleaves )
2406 nnodes = eventhdlrdata->treedata->nleaves;
2407 else
2408 nnodes = eventhdlrdata->treedata->nvisited;
2409
2410 if( nnodes < eventhdlrdata->minnodes )
2411 return FALSE;
2412
2413 return TRUE;
2414}
2415
2416/** should a restart be applied based on the value of the selected completion method? */ /*lint --e{715}*/
2417static
2419 SCIP* scip, /**< SCIP data structure */
2420 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
2421 )
2422{ /*lint --e{715}*/
2423 SCIP_Real completion;
2424
2425 SCIP_CALL_ABORT( getSearchCompletion(eventhdlrdata, &completion) );
2426
2427 /* if the estimation exceeds the current number of nodes by a dramatic factor, restart */
2428 if( completion < 1.0 / eventhdlrdata->restartfactor )
2429 {
2432 "Completion %.5f less than restart threshold %.5f\n",
2433 completion, 1.0 / eventhdlrdata->restartfactor);
2434 )
2435
2436 return TRUE;
2437 }
2438
2439 return FALSE;
2440}
2441
2442/** should a restart be applied based on the value of the selected completion method? */
2443static
2445 SCIP* scip, /**< SCIP data structure */
2446 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
2447 )
2448{
2449 SCIP_Real estimation;
2450
2451 estimation = SCIPgetTreesizeEstimation(scip);
2452
2453 if( estimation < 0.0 )
2454 {
2457 "Estimation %g is still unavailable\n",
2458 estimation);
2459 )
2460
2461 return TRUE;
2462 }
2463
2464 /* if the estimation exceeds the current number of nodes by a dramatic factor, restart */
2465 if( estimation > eventhdlrdata->treedata->nnodes * eventhdlrdata->restartfactor )
2466 {
2469 "Estimation %g exceeds number of estimation tree nodes %" SCIP_LONGINT_FORMAT " by a factor of %.1f\n",
2470 estimation, eventhdlrdata->treedata->nnodes, estimation / eventhdlrdata->treedata->nnodes);
2471 )
2472
2473 return TRUE;
2474 }
2475
2476 return FALSE;
2477}
2478
2479/** check if a restart should be performed based on the given restart policy */
2480static
2482 SCIP* scip, /**< SCIP data structure */
2483 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
2484 )
2485{
2486 SCIP_Bool applyrestart = FALSE;
2487
2488 switch (getRestartPolicy(eventhdlrdata))
2489 {
2491 applyrestart = TRUE;
2492 break;
2494 applyrestart = FALSE;
2495 break;
2497 applyrestart = shouldApplyRestartCompletion(scip, eventhdlrdata);
2498 break;
2500 applyrestart = shouldApplyRestartEstimation(scip, eventhdlrdata);
2501 break;
2502 default:
2503 break;
2504 }
2505
2506 return applyrestart;
2507}
2508
2509/** update all time series */
2510static
2512 SCIP* scip, /**< SCIP data structure */
2513 SCIP_EVENTHDLRDATA* eventhdlrdata, /**< event handler data */
2514 TREEDATA* treedata, /**< tree data */
2515 SCIP_Bool isleaf /**< are we at a leaf node? */
2516 )
2517{
2518 TIMESERIES** tss = eventhdlrdata->timeseries;
2519 int t;
2520
2521 /* loop over time series */
2522 for( t = 0; t < NTIMESERIES; ++t )
2523 {
2524 assert(tss[t] != NULL);
2525 SCIP_CALL( timeSeriesUpdate(scip, tss[t], treedata, isleaf) );
2526
2527#ifdef SCIP_MORE_DEBUG
2529 "Update of time series '%s', current value %.4f (%" SCIP_LONGINT_FORMAT " observations)\n",
2530 timeSeriesGetName(tss[t]), timeSeriesGetValue(tss[t]), tss[t]->nobs);
2531#endif
2532 }
2533
2534 return SCIP_OKAY;
2535}
2536
2537/** print a treesize estimation report into the string buffer */
2538static
2540 SCIP* scip, /**< SCIP data structure */
2541 SCIP_EVENTHDLRDATA* eventhdlrdata, /**< event handler data */
2542 char* strbuf, /**< string buffer */
2543 int reportnum /**< report number, or 0 to omit number */
2544 )
2545{
2546 TREEDATA* treedata = eventhdlrdata->treedata;
2547 char* ptr = strbuf;
2548 SCIP_Real completed;
2549 SCIP_Real wbeestim;
2550 char wbeestimstr[SCIP_MAXSTRLEN];
2551 int t;
2552
2553 /* print report number */
2554 if( reportnum > 0 )
2555 ptr += SCIPsnprintf(ptr, SCIP_MAXSTRLEN, "Report %d\nTime Elapsed: %.2f\n", reportnum, SCIPgetSolvingTime(scip));
2556
2557 ptr += SCIPsnprintf(ptr, SCIP_MAXSTRLEN,
2558 "Estim. Tree Size :%11" SCIP_LONGINT_FORMAT "\n",
2560
2561 SCIP_CALL_ABORT( getSearchCompletion(eventhdlrdata, &completed) );
2562
2563 completed = MIN(1.0, completed);
2564 completed = MAX(0.0, completed);
2565
2566 /* print tree data */
2567 ptr += SCIPsnprintf(ptr, SCIP_MAXSTRLEN,
2568 "%-19s: %" SCIP_LONGINT_FORMAT " nodes ("
2569 "%" SCIP_LONGINT_FORMAT " visited, "
2570 "%" SCIP_LONGINT_FORMAT " internal, "
2571 "%" SCIP_LONGINT_FORMAT " leaves, "
2572 "%" SCIP_LONGINT_FORMAT " open), "
2573 "weight: %.4Lf completed %.4f\n",
2574 "Estimation Tree",
2575 treedata->nnodes,
2576 treedata->nvisited,
2577 treedata->ninner,
2578 treedata->nleaves,
2579 treedata->nopen,
2580 treedata->weight,
2581 completed
2582 );
2583
2584 /* print estimations */
2585 ptr += SCIPsnprintf(ptr, SCIP_MAXSTRLEN, "Estimations : %10s %10s %10s %10s %10s",
2586 "estim", "value", "trend", "resolution", "smooth");
2587 ptr += SCIPsnprintf(ptr, SCIP_MAXSTRLEN, "\n");
2588
2589 wbeestim = treeDataGetWbe(eventhdlrdata->treedata);
2590 ptr += SCIPsnprintf(ptr, SCIP_MAXSTRLEN, " wbe : %10s %10s %10s %10s %10s\n",
2591 real2String(wbeestim, wbeestimstr, 0), "-", "-", "-", "-");
2592
2593 ptr += SCIPsnprintf(ptr, SCIP_MAXSTRLEN, " tree-profile : %10.0f %10s %10s %10s %10s\n",
2594 predictTotalSizeTreeProfile(scip, eventhdlrdata->treeprofile, eventhdlrdata->treeprofile_minnodesperdepth),
2595 "-", "-", "-", "-");
2596
2597 /* print time series forecasts */
2598 for( t = 0; t < NTIMESERIES; ++t )
2599 {
2600 SCIP_Real trend;
2601 SCIP_Real smoothestim;
2602 TIMESERIES* ts = eventhdlrdata->timeseries[t];
2603 char trendstr[SCIP_MAXSTRLEN];
2604 char smoothestimstr[SCIP_MAXSTRLEN];
2605
2606 trend = doubleExpSmoothGetTrend(&ts->des);
2607 smoothestim = timeSeriesGetSmoothEstimation(ts);
2608
2609 ptr += SCIPsnprintf(ptr, SCIP_MAXSTRLEN, " %-17s: %10.0f %10.5f %10s %10d %10s\n",
2611 timeSeriesEstimate(ts, eventhdlrdata->treedata),
2613 real2String(trend, trendstr, 5),
2615 real2String(smoothestim, smoothestimstr, 0));
2616 }
2617
2618 if( reportnum > 0 )
2619 (void) SCIPsnprintf(ptr, SCIP_MAXSTRLEN, "End of Report %d\n", reportnum);
2620}
2621
2622
2623/** copy method for event handler plugins (called when SCIP copies plugins) */
2624static
2625SCIP_DECL_EVENTCOPY(eventCopyEstim)
2626{ /*lint --e{715}*/
2627 assert(scip != NULL);
2628
2630
2631 return SCIP_OKAY;
2632}
2633
2634/** destructor of event handler to free user data (called when SCIP is exiting) */
2635static
2636SCIP_DECL_EVENTFREE(eventFreeEstim)
2637{ /*lint --e{715}*/
2638 SCIP_EVENTHDLRDATA* eventhdlrdata;
2639
2640 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
2641 assert(eventhdlrdata != NULL);
2642
2643 freeTreeData(scip, &eventhdlrdata->treedata);
2644
2645 freeTimeSeries(scip, eventhdlrdata);
2646
2647 SCIPfreeMemory(scip, &eventhdlrdata);
2648
2649 return SCIP_OKAY;
2650}
2651
2652/** initialization method of event handler (called after problem was transformed) */
2653static
2654SCIP_DECL_EVENTINIT(eventInitEstim)
2655{ /*lint --e{715}*/
2656 SCIP_EVENTHDLRDATA* eventhdlrdata;
2657
2658 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
2659 assert(eventhdlrdata != NULL);
2660
2661 /* test if user specified a regression forest */
2662 if( 0 != strncmp(eventhdlrdata->regforestfilename, DEFAULT_REGFORESTFILENAME, strlen(DEFAULT_REGFORESTFILENAME)) )
2663 {
2664 SCIP_CALL( SCIPregForestFromFile(&eventhdlrdata->regforest, eventhdlrdata->regforestfilename) );
2665 }
2666
2667 eventhdlrdata->lastrestartrun = 0;
2668 eventhdlrdata->nrestartsperformed = 0;
2669
2670 return SCIP_OKAY;
2671}
2672
2673/** deinitialization method of event handler (called before transformed problem is freed) */
2674static
2675SCIP_DECL_EVENTEXIT(eventExitEstim)
2676{ /*lint --e{715}*/
2677 SCIP_EVENTHDLRDATA* eventhdlrdata;
2678
2679 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
2680 assert(eventhdlrdata != NULL);
2681
2682 SCIPregForestFree(&eventhdlrdata->regforest);
2683
2684 return SCIP_OKAY;
2685}
2686
2687/** solving process initialization method of event handler (called when branch and bound process is about to begin) */
2688static
2689SCIP_DECL_EVENTINITSOL(eventInitsolEstim)
2690{ /*lint --e{715}*/
2691 SCIP_EVENTHDLRDATA* eventhdlrdata;
2692
2693 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
2694 assert(eventhdlrdata != NULL);
2695
2696 eventhdlrdata->restarthitcounter = 0;
2697 eventhdlrdata->weightlastreport = 0.0;
2698 eventhdlrdata->nreports = 0;
2699
2700 /* reset tree data */
2701 SCIP_CALL( resetTreeData(scip, eventhdlrdata->treedata) );
2702
2703 resetTimeSeries(eventhdlrdata);
2704
2706
2707 if( eventhdlrdata->treeprofile_enabled )
2708 {
2709 SCIP_CALL( createTreeProfile(scip, &eventhdlrdata->treeprofile) );
2710 }
2711
2712 eventhdlrdata->treeisbinary = TRUE;
2713
2714 return SCIP_OKAY;
2715}
2716
2717/** solving process deinitialization method of event handler (called before branch and bound process data is freed) */
2718static
2719SCIP_DECL_EVENTEXITSOL(eventExitsolEstim)
2720{ /*lint --e{715}*/
2721 SCIP_EVENTHDLRDATA* eventhdlrdata;
2722
2723 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
2724 assert(eventhdlrdata != NULL);
2725
2726 if( eventhdlrdata->treeprofile != NULL )
2727 freeTreeProfile(scip, &eventhdlrdata->treeprofile);
2728
2729 SCIP_CALL( SCIPdropEvent(scip, EVENTTYPE_ESTIM, eventhdlr, NULL, -1) );
2730
2731 return SCIP_OKAY;
2732}
2733
2734/** execution method of event handler */
2735static
2736SCIP_DECL_EVENTEXEC(eventExecEstim)
2737{ /*lint --e{715}*/
2738 SCIP_EVENTHDLRDATA* eventhdlrdata;
2739 SCIP_Bool isleaf;
2740 SCIP_EVENTTYPE eventtype;
2741 TREEDATA* treedata;
2742 char strbuf[SCIP_MAXSTRLEN];
2743
2744 assert(scip != NULL);
2745 assert(eventhdlr != NULL);
2746
2747 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
2748 assert(eventhdlrdata != NULL);
2749 eventtype = SCIPeventGetType(event);
2750 treedata = eventhdlrdata->treedata;
2751
2752 if( SCIPisExact(scip) )
2753 return SCIP_OKAY;
2754
2755 /* actual leaf nodes for our tree data are children/siblings/leaves or the focus node itself (deadend)
2756 * if it has not been branched on
2757 */
2758 isleaf = (eventtype == SCIP_EVENTTYPE_NODEDELETE) &&
2763
2764 if( eventtype == SCIP_EVENTTYPE_NODEBRANCHED || isleaf )
2765 {
2766 SCIP_NODE* eventnode;
2767 int nchildren = 0;
2768
2769 if( eventtype == SCIP_EVENTTYPE_NODEBRANCHED )
2770 {
2771 nchildren = SCIPgetNChildren(scip);
2772
2773 /* update whether the tree is still binary */
2774 if( nchildren != 2 )
2775 eventhdlrdata->treeisbinary = FALSE;
2776 }
2777
2778 eventnode = SCIPeventGetNode(event);
2779 SCIP_CALL( updateTreeData(scip, treedata, eventnode, nchildren) );
2780 SCIP_CALL( updateTreeProfile(scip, eventhdlrdata->treeprofile, eventnode) );
2781
2782#ifdef SCIP_DEBUG
2783 SCIPdebugMsg(scip, "%s\n", treeDataPrint(treedata, strbuf));
2784#endif
2785
2786 SCIP_CALL( updateTimeseries(scip, eventhdlrdata, treedata, nchildren == 0) );
2787
2788 /* should a new report be printed? */
2789 if( eventhdlrdata->reportfreq >= 0 && SCIPgetStatus(scip) == SCIP_STATUS_UNKNOWN &&
2790 (eventhdlrdata->reportfreq == 0
2791 || treedata->weight >= eventhdlrdata->weightlastreport + 1.0 / (SCIP_Real)eventhdlrdata->reportfreq) )
2792 {
2793 printReport(scip, eventhdlrdata, strbuf, ++eventhdlrdata->nreports);
2794 SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "%s\n", strbuf);
2795
2796 if( eventhdlrdata->reportfreq > 0 )
2797 eventhdlrdata->weightlastreport = 1 / (SCIP_Real)eventhdlrdata->reportfreq * SCIPfloor(scip, ((SCIP_Real)treedata->weight * eventhdlrdata->reportfreq));
2798 else
2799 eventhdlrdata->weightlastreport = (SCIP_Real)treedata->weight;
2800 }
2801 }
2802
2803 /* if nodes have been pruned, things are progressing, don't restart right now */
2804 if( isleaf )
2805 return SCIP_OKAY;
2806
2807 /* check if all conditions are met such that the event handler should run */
2808 if( !isRestartApplicable(scip, eventhdlrdata) )
2809 return SCIP_OKAY;
2810
2811 /* test if a restart should be applied */
2812 if( shouldApplyRestart(scip, eventhdlrdata) )
2813 {
2814 eventhdlrdata->restarthitcounter++;
2815
2816 if( eventhdlrdata->restarthitcounter >= eventhdlrdata->hitcounterlim )
2817 {
2818 /* safe that we triggered a restart at this run */
2819 if( !SCIPisExact(scip) && SCIPgetNRuns(scip) > eventhdlrdata->lastrestartrun )
2820 {
2821 eventhdlrdata->nrestartsperformed++;
2822
2824 "Restart triggered after %d consecutive estimations that the remaining tree will be large\n",
2825 eventhdlrdata->restarthitcounter);
2826 }
2827
2828 eventhdlrdata->lastrestartrun = SCIPgetNRuns(scip);
2829
2831 }
2832 }
2833 else
2834 {
2835 eventhdlrdata->restarthitcounter = 0;
2836 }
2837
2838 return SCIP_OKAY;
2839}
2840
2841/** output method of statistics table to output file stream 'file' */
2842static
2843SCIP_DECL_TABLEOUTPUT(tableOutputEstim)
2844{ /*lint --e{715}*/
2845 SCIP_EVENTHDLR* eventhdlr;
2846 SCIP_EVENTHDLRDATA* eventhdlrdata;
2847
2849 assert(eventhdlr != NULL);
2850
2851 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
2852 assert(eventhdlrdata != NULL);
2853
2854 if( eventhdlrdata->showstats )
2855 {
2856 char strbuf[SCIP_MAXSTRLEN];
2857 printReport(scip, eventhdlrdata, strbuf, 0);
2858 SCIPinfoMessage(scip, file, "%s", strbuf);
2859 }
2860
2861 return SCIP_OKAY;
2862}
2863
2864/** output method of search tree completion display column to output file stream 'file' */
2865static
2866SCIP_DECL_DISPOUTPUT(dispOutputCompleted)
2867{ /*lint --e{715}*/
2868 SCIP_EVENTHDLR* eventhdlr;
2869 SCIP_EVENTHDLRDATA* eventhdlrdata;
2870 TREEDATA* treedata;
2871 SCIP_Real completed;
2872
2873 assert(disp != NULL);
2874 assert(strcmp(SCIPdispGetName(disp), DISP_NAME) == 0);
2875 assert(scip != NULL);
2876
2878 assert(eventhdlr != NULL);
2879 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
2880 assert(eventhdlrdata != NULL);
2881 treedata = eventhdlrdata->treedata;
2882
2883 SCIP_CALL( getSearchCompletion(eventhdlrdata, &completed) );
2884
2885 completed = MIN(completed, 1.0);
2886
2887 if( treedata->weight >= 0.005 && completed > 0 )
2888 SCIPinfoMessage(scip, file, "%7.2f%%", 100.0 * completed);
2889 else
2890 SCIPinfoMessage(scip, file, " unknown");
2891
2892 return SCIP_OKAY;
2893}
2894
2895/** creates event handler for tree size estimation */
2897 SCIP* scip /**< SCIP data structure */
2898 )
2899{
2900 SCIP_RETCODE retcode;
2901 SCIP_EVENTHDLRDATA* eventhdlrdata = NULL;
2902 SCIP_EVENTHDLR* eventhdlr = NULL;
2903
2904 /* create estim event handler data */
2905 SCIP_CALL( SCIPallocMemory(scip, &eventhdlrdata) );
2906 BMSclearMemory(eventhdlrdata);
2907
2908 SCIP_CALL_TERMINATE( retcode, createTreeData(scip, &eventhdlrdata->treedata), TERMINATE );
2909
2911 eventExecEstim, eventhdlrdata) );
2912 assert(eventhdlr != NULL);
2913
2914 /* set non fundamental callbacks via setter functions */
2915 SCIP_CALL( SCIPsetEventhdlrCopy(scip, eventhdlr, eventCopyEstim) );
2916 SCIP_CALL( SCIPsetEventhdlrFree(scip, eventhdlr, eventFreeEstim) );
2917 SCIP_CALL( SCIPsetEventhdlrInit(scip, eventhdlr, eventInitEstim) );
2918 SCIP_CALL( SCIPsetEventhdlrExit(scip, eventhdlr, eventExitEstim) );
2919 SCIP_CALL( SCIPsetEventhdlrInitsol(scip, eventhdlr, eventInitsolEstim) );
2920 SCIP_CALL( SCIPsetEventhdlrExitsol(scip, eventhdlr, eventExitsolEstim) );
2921
2922 /* add estimation event handler parameters */
2923 SCIP_CALL( SCIPaddCharParam(scip, "estimation/restarts/restartpolicy", "restart policy: (a)lways, (c)ompletion, (e)stimation, (n)ever",
2924 &eventhdlrdata->restartpolicyparam, FALSE, DEFAULT_RESTARTPOLICY, "acen", NULL, NULL) );
2925
2926 SCIP_CALL( SCIPaddCharParam(scip, "estimation/method",
2927 "tree size estimation method: (c)ompletion, (e)nsemble, "
2928 "time series forecasts on either (g)ap, (l)eaf frequency, (o)open nodes, tree (w)eight, (s)sg, "
2929 "or (t)ree profile or w(b)e",
2930 &eventhdlrdata->estimmethod, FALSE, DEFAULT_ESTIMMETHOD, ESTIMMETHODS, NULL, NULL) );
2931
2932 SCIP_CALL( SCIPaddIntParam(scip, "estimation/restarts/restartlimit", "restart limit",
2933 &eventhdlrdata->restartlimit, FALSE, DEFAULT_RESTARTLIMIT, -1, INT_MAX, NULL, NULL) );
2934
2935 SCIP_CALL( SCIPaddLongintParam(scip, "estimation/restarts/minnodes", "minimum number of nodes before restart",
2936 &eventhdlrdata->minnodes, FALSE, DEFAULT_MINNODES, -1L, SCIP_LONGINT_MAX, NULL, NULL) );
2937
2938 SCIP_CALL( SCIPaddBoolParam(scip, "estimation/restarts/countonlyleaves", "should only leaves count for the minnodes parameter?",
2939 &eventhdlrdata->countonlyleaves, DEFAULT_COUNTONLYLEAVES, FALSE, NULL, NULL) );
2940
2941 SCIP_CALL( SCIPaddRealParam(scip, "estimation/restarts/restartfactor",
2942 "factor by which the estimated number of nodes should exceed the current number of nodes",
2943 &eventhdlrdata->restartfactor, FALSE, DEFAULT_RESTARTFACTOR, 1.0, SCIP_REAL_MAX, NULL, NULL) );
2944
2945 SCIP_CALL( SCIPaddBoolParam(scip, "estimation/restarts/restartnonlinear",
2946 "whether to apply a restart when nonlinear constraints are present",
2947 &eventhdlrdata->restartnonlinear, FALSE, DEFAULT_RESTARTNONLINEAR, NULL, NULL) );
2948
2949 SCIP_CALL( SCIPaddBoolParam(scip, "estimation/restarts/restartactpricers",
2950 "whether to apply a restart when active pricers are used",
2951 &eventhdlrdata->restartactpricers, FALSE, DEFAULT_RESTARTACTPRICERS, NULL, NULL) );
2952
2953 SCIP_CALL( SCIPaddRealParam(scip, "estimation/coefmonoweight",
2954 "coefficient of tree weight in monotone approximation of search completion",
2955 &eventhdlrdata->coefmonoweight, FALSE, DEFAULT_COEFMONOWEIGHT, 0.0, 1.0, NULL, NULL) );
2956
2957 SCIP_CALL( SCIPaddRealParam(scip, "estimation/coefmonossg",
2958 "coefficient of 1 - SSG in monotone approximation of search completion",
2959 &eventhdlrdata->coefmonossg, FALSE, DEFAULT_COEFMONOSSG, 0.0, 1.0, NULL, NULL) );
2960
2961 SCIP_CALL( SCIPaddIntParam(scip, "estimation/restarts/hitcounterlim", "limit on the number of successive samples to really trigger a restart",
2962 &eventhdlrdata->hitcounterlim, FALSE, DEFAULT_HITCOUNTERLIM, 1, INT_MAX, NULL, NULL) );
2963
2964 SCIP_CALL( SCIPaddIntParam(scip, "estimation/reportfreq",
2965 "report frequency on estimation: -1: never, 0:always, k >= 1: k times evenly during search",
2966 &eventhdlrdata->reportfreq, TRUE, DEFAULT_REPORTFREQ, -1, INT_MAX / 2, NULL, NULL) );
2967
2968 SCIP_CALL( SCIPaddStringParam(scip, "estimation/regforestfilename", "user regression forest in RFCSV format",
2969 &eventhdlrdata->regforestfilename, FALSE, DEFAULT_REGFORESTFILENAME, NULL, NULL) );
2970
2971 SCIP_CALL( SCIPaddCharParam(scip, "estimation/completiontype",
2972 "approximation of search tree completion: (a)uto, (g)ap, tree (w)eight, (m)onotone regression, (r)egression forest, (s)sg",
2973 &eventhdlrdata->completiontypeparam, FALSE, DEFAULT_COMPLETIONTYPE, "agmrsw", NULL, NULL) );
2974
2975 SCIP_CALL( SCIPaddBoolParam(scip, "estimation/treeprofile/enabled",
2976 "should the event handler collect data?",
2977 &eventhdlrdata->treeprofile_enabled, FALSE, DEFAULT_TREEPROFILE_ENABLED, NULL, NULL) );
2978
2979 SCIP_CALL( SCIPaddRealParam(scip, "estimation/treeprofile/minnodesperdepth",
2980 "minimum average number of nodes at each depth before producing estimations",
2981 &eventhdlrdata->treeprofile_minnodesperdepth, FALSE, DEFAULT_TREEPROFILE_MINNODESPERDEPTH, 1.0, SCIP_REAL_MAX, NULL, NULL) );
2982
2983 SCIP_CALL( SCIPaddBoolParam(scip, "estimation/useleafts",
2984 "use leaf nodes as basic observations for time series, or all nodes?",
2985 &eventhdlrdata->useleafts, TRUE, DEFAULT_USELEAFTS, NULL, NULL) );
2986
2987 SCIP_CALL( SCIPaddBoolParam(scip, "estimation/showstats",
2988 "should statistics be shown at the end?",
2989 &eventhdlrdata->showstats, TRUE, DEFAULT_SHOWSTATS, NULL, NULL) );
2990
2991 /* SSG parameters */
2992 SCIP_CALL( SCIPaddIntParam(scip, "estimation/ssg/nmaxsubtrees",
2993 "the maximum number of individual SSG subtrees; -1: no limit",
2994 &eventhdlrdata->treedata->ssg->nmaxsubtrees, FALSE, DEFAULT_SSG_NMAXSUBTREES, -1, INT_MAX / 2, NULL, NULL) );
2995
2996 SCIP_CALL( SCIPaddLongintParam(scip, "estimation/ssg/nminnodeslastsplit",
2997 "minimum number of nodes to process between two consecutive SSG splits",
2998 &eventhdlrdata->treedata->ssg->nminnodeslastsplit, FALSE, DEFAULT_SSG_NMINNODESLASTSPLIT, 0L, SCIP_LONGINT_MAX, NULL, NULL) );
2999
3000 /* include statistics table */
3002 NULL, NULL, NULL, NULL, NULL, NULL, tableOutputEstim, NULL,
3004
3005 /* include time series into event handler */
3006 SCIP_CALL( includeTimeseries(scip, eventhdlrdata) );
3007
3008 /* include display column */
3010 NULL, NULL, NULL, NULL, NULL, NULL, dispOutputCompleted,
3012
3013TERMINATE:
3014 if( retcode != SCIP_OKAY )
3015 {
3016 freeTreeData(scip, &eventhdlrdata->treedata);
3017 SCIPfreeMemory(scip, &eventhdlrdata);
3018 }
3019
3020 return retcode;
3021}
3022
3023/** return an estimation of the final tree size */
3025 SCIP* scip /**< SCIP data structure */
3026 )
3027{
3028 SCIP_EVENTHDLR* eventhdlr;
3029 SCIP_EVENTHDLRDATA* eventhdlrdata;
3030 TSPOS tspos = TSPOS_NONE;
3031 SCIP_Real estim;
3032
3033 assert(scip != NULL);
3034
3036 if( eventhdlr == NULL )
3037 {
3038 SCIPwarningMessage(scip, "SCIPgetTreesizeEstimation() called, but event handler " EVENTHDLR_NAME " is missing.\n");
3039 return -1.0;
3040 }
3041
3042 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
3043 assert(eventhdlrdata != NULL);
3044
3045 switch (eventhdlrdata->estimmethod)
3046 {
3047 case ESTIMMETHOD_COMPL:
3048 SCIP_CALL_ABORT( getEstimCompletion(scip, eventhdlrdata, &estim) );
3049 return estim;
3050
3051 case ESTIMMETHOD_ENSMBL:
3052 return getEnsembleEstimation(eventhdlrdata);
3053
3054 /* for the requested time series methods, we specify the array position */
3055 case ESTIMMETHOD_GAP:
3056 tspos = TSPOS_GAP;
3057 break;
3058
3059 case ESTIMMETHOD_LFREQ:
3060 tspos = TSPOS_LFREQ;
3061 break;
3062
3063 case ESTIMMETHOD_OPEN:
3064 tspos = TSPOS_OPEN;
3065 break;
3066
3068 tspos = TSPOS_TREEWEIGHT;
3069 break;
3070
3071 case ESTIMMETHOD_SSG:
3072 tspos = TSPOS_SSG;
3073 break;
3074
3075 /* tree profile estimation */
3076 case ESTIMMETHOD_TPROF:
3077 return predictTotalSizeTreeProfile(scip, eventhdlrdata->treeprofile, eventhdlrdata->treeprofile_minnodesperdepth);
3078
3079 /* Weighted backtrack estimation */
3080 case ESTIMMETHOD_WBE:
3081 return treeDataGetWbe(eventhdlrdata->treedata);
3082
3083 default:
3084 SCIPerrorMessage("Unknown estimation '%c' method specified, should be one of [%s]\n",
3085 eventhdlrdata->estimmethod, ESTIMMETHODS);
3086 SCIPABORT();
3087 break;
3088 }
3089
3090 assert(tspos != TSPOS_NONE);
3091 return (tspos == TSPOS_NONE ? -1.0 : timeSeriesEstimate(eventhdlrdata->timeseries[tspos], eventhdlrdata->treedata));
3092}
#define NULL
Definition: def.h:248
#define SCIP_MAXSTRLEN
Definition: def.h:269
#define SCIP_Longint
Definition: def.h:141
#define SCIP_REAL_MAX
Definition: def.h:158
#define SCIP_INVALID
Definition: def.h:178
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:224
#define SCIP_ALLOC(x)
Definition: def.h:366
#define SCIP_ALLOC_TERMINATE(retcode, x, TERM)
Definition: def.h:386
#define SCIP_Real
Definition: def.h:156
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:220
#define SCIP_CALL_ABORT(x)
Definition: def.h:334
#define SCIP_CALL_TERMINATE(retcode, x, TERM)
Definition: def.h:376
#define SCIP_LONGINT_FORMAT
Definition: def.h:148
#define SCIPABORT()
Definition: def.h:327
#define REALABS(x)
Definition: def.h:182
#define SCIP_LONGINT_MAX
Definition: def.h:142
#define EPSZ(x, eps)
Definition: def.h:188
#define SCIP_CALL(x)
Definition: def.h:355
static void SCIPregForestFree(SCIP_REGFOREST **regforest)
Definition: event_estim.c:402
static char * timeSeriesGetName(TIMESERIES *timeseries)
Definition: event_estim.c:1981
static SCIP_RETCODE subtreeSumGapComputeFromScratchEfficiently(SCIP *scip, SUBTREESUMGAP *ssg, SCIP_Bool updatescaling)
Definition: event_estim.c:1393
enum RestartPolicy RESTARTPOLICY
Definition: event_estim.c:100
#define DEFAULT_COEFMONOWEIGHT
Definition: event_estim.c:246
static SCIP_RETCODE timeSeriesCreate(SCIP *scip, TIMESERIES **timeseries, const char *name, SCIP_Real targetvalue, SCIP_Real initialvalue, SCIP_Real alpha, SCIP_Real beta, DECL_TIMESERIESUPDATE((*timeseriesupdate)))
Definition: event_estim.c:1743
static SCIP_RETCODE subtreeSumGapSplit(SCIP *scip, SUBTREESUMGAP *ssg, SCIP_Bool addfocusnode)
Definition: event_estim.c:1056
static SCIP_DECL_PQUEUEELEMCHGPOS(elemChgPosNodeInfo)
Definition: event_estim.c:997
#define DES_BETA_TREEWEIGHT
Definition: event_estim.c:129
static void freeTreeProfile(SCIP *scip, TREEPROFILE **treeprofile)
Definition: event_estim.c:711
static SCIP_DECL_EVENTEXIT(eventExitEstim)
Definition: event_estim.c:2675
static SCIP_RETCODE updateTreeData(SCIP *scip, TREEDATA *treedata, SCIP_NODE *node, int nchildren)
Definition: event_estim.c:1586
#define DEFAULT_SHOWSTATS
Definition: event_estim.c:265
#define DEFAULT_RESTARTLIMIT
Definition: event_estim.c:255
static SCIP_Real getEnsembleEstimation(SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: event_estim.c:2035
static SCIP_Bool shouldApplyRestart(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: event_estim.c:2481
#define DES_ALPHA_TREEWEIGHT
Definition: event_estim.c:128
#define DES_ALPHA_OPENNODES
Definition: event_estim.c:140
#define MAX_REGFORESTSIZE
Definition: event_estim.c:143
#define RESTARTPOLICY_CHAR_ALWAYS
Definition: event_estim.c:103
TsPos
Definition: event_estim.c:204
@ TSPOS_TREEWEIGHT
Definition: event_estim.c:207
@ TSPOS_GAP
Definition: event_estim.c:206
@ TSPOS_NONE
Definition: event_estim.c:205
@ TSPOS_OPEN
Definition: event_estim.c:210
@ TSPOS_SSG
Definition: event_estim.c:209
@ TSPOS_LFREQ
Definition: event_estim.c:208
#define RESTARTPOLICY_CHAR_NEVER
Definition: event_estim.c:102
#define INITIALSIZE
Definition: event_estim.c:124
static SCIP_Bool isRestartApplicable(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: event_estim.c:2381
#define DEFAULT_REPORTFREQ
Definition: event_estim.c:244
static void printReport(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata, char *strbuf, int reportnum)
Definition: event_estim.c:2539
static SCIP_Real timeSeriesGetSmoothEstimation(TIMESERIES *timeseries)
Definition: event_estim.c:1896
static SCIP_RETCODE subtreeSumGapCreate(SCIP *scip, SUBTREESUMGAP **ssg)
Definition: event_estim.c:936
static void doubleExpSmoothUpdate(DOUBLEEXPSMOOTH *des, SCIP_Real xnew)
Definition: event_estim.c:1692
static void copyTreeProfileStats(TREEPROFILESTATS *dest, TREEPROFILESTATS *src)
Definition: event_estim.c:624
#define DEFAULT_SSG_NMAXSUBTREES
Definition: event_estim.c:262
#define DES_BETA_LEAFFREQUENCY
Definition: event_estim.c:135
#define TABLE_NAME
Definition: event_estim.c:110
#define ESTIMMETHOD_GAP
Definition: event_estim.c:160
static SCIP_DECL_EVENTEXEC(eventExecEstim)
Definition: event_estim.c:2736
#define DEFAULT_SSG_NMINNODESLASTSPLIT
Definition: event_estim.c:264
#define DISP_PRIORITY
Definition: event_estim.c:120
#define DEFAULT_MINNODES
Definition: event_estim.c:256
#define COMPLETIONTYPE_REGFOREST
Definition: event_estim.c:149
#define DES_USETRENDINLEVEL
Definition: event_estim.c:107
#define COMPLETIONTYPE_MONOREG
Definition: event_estim.c:150
#define ESTIMMETHOD_TREEWEIGHT
Definition: event_estim.c:165
#define COMPLETIONTYPE_TREEWEIGHT
Definition: event_estim.c:151
#define ESTIMMETHOD_LFREQ
Definition: event_estim.c:161
static SCIP_RETCODE timeSeriesUpdate(SCIP *scip, TIMESERIES *timeseries, TREEDATA *treedata, SCIP_Bool isleaf)
Definition: event_estim.c:1932
#define DEFAULT_TREEPROFILE_ENABLED
Definition: event_estim.c:252
static SCIP_DECL_EVENTCOPY(eventCopyEstim)
Definition: event_estim.c:2625
static SCIP_Real SCIPregForestPredict(SCIP_REGFOREST *regforest, SCIP_Real *datapoint)
Definition: event_estim.c:424
static void freeTreeData(SCIP *scip, TREEDATA **treedata)
Definition: event_estim.c:1568
static SCIP_RETCODE resetTreeData(SCIP *scip, TREEDATA *treedata)
Definition: event_estim.c:1529
static SCIP_Real timeSeriesEstimate(TIMESERIES *timeseries, TREEDATA *treedata)
Definition: event_estim.c:1841
enum TsPos TSPOS
Definition: event_estim.c:213
static SCIP_RETCODE includeTimeseries(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: event_estim.c:2324
#define ESTIMMETHOD_ENSMBL
Definition: event_estim.c:159
#define COMPLETIONTYPE_GAP
Definition: event_estim.c:153
#define COMPLETIONTYPE_SSG
Definition: event_estim.c:152
static void timeSeriesUpdateSmoothEstimation(TIMESERIES *timeseries, SCIP_Real estimation)
Definition: event_estim.c:1880
#define DEFAULT_COUNTONLYLEAVES
Definition: event_estim.c:257
static SCIP_RETCODE subtreeSumGapRemoveNode(SCIP *scip, SUBTREESUMGAP *ssg, SCIP_NODE *node)
Definition: event_estim.c:1157
static void timeSeriesResample(TIMESERIES *timeseries)
Definition: event_estim.c:1905
static SCIP_RETCODE subtreeSumGapReset(SCIP *scip, SUBTREESUMGAP *ssg)
Definition: event_estim.c:912
static SCIP_RETCODE updateTreeProfile(SCIP *scip, TREEPROFILE *treeprofile, SCIP_NODE *node)
Definition: event_estim.c:731
static SCIP_RETCODE createTreeData(SCIP *scip, TREEDATA **treedata)
Definition: event_estim.c:1549
static SCIP_RETCODE getEstimCompletion(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata, SCIP_Real *estim)
Definition: event_estim.c:2216
#define DEFAULT_HITCOUNTERLIM
Definition: event_estim.c:261
#define DISP_POSITION
Definition: event_estim.c:121
#define DES_ALPHA_SSG
Definition: event_estim.c:137
#define DES_BETA_OPENNODES
Definition: event_estim.c:141
static SCIP_Real calcGap(SCIP *scip, SCIP_Real lowerbound)
Definition: event_estim.c:1124
#define ESTIMMETHOD_OPEN
Definition: event_estim.c:162
#define DEFAULT_RESTARTACTPRICERS
Definition: event_estim.c:260
SCIP_Real SCIPgetTreesizeEstimation(SCIP *scip)
Definition: event_estim.c:3024
static SCIP_DECL_EVENTINIT(eventInitEstim)
Definition: event_estim.c:2654
static void timeSeriesFree(SCIP *scip, TIMESERIES **timeseries)
Definition: event_estim.c:1792
#define NTIMESERIES
Definition: event_estim.c:200
#define DEFAULT_RESTARTFACTOR
Definition: event_estim.c:258
#define SESCOEFF
Definition: event_estim.c:125
#define DISP_NAME
Definition: event_estim.c:116
static SCIP_DECL_SORTPTRCOMP(compareNodeInfos)
Definition: event_estim.c:982
#define DEFAULT_USELEAFTS
Definition: event_estim.c:243
SCIP_RETCODE SCIPincludeEventHdlrEstim(SCIP *scip)
Definition: event_estim.c:2896
#define DES_ALPHA_LEAFFREQUENCY
Definition: event_estim.c:134
#define DES_BETA_GAP
Definition: event_estim.c:132
static SCIP_RETCODE subtreeSumGapInsertChildren(SCIP *scip, SUBTREESUMGAP *ssg)
Definition: event_estim.c:1228
static SCIP_Real timeSeriesGetValue(TIMESERIES *timeseries)
Definition: event_estim.c:1812
RestartPolicy
Definition: event_estim.c:93
@ RESTARTPOLICY_COMPLETION
Definition: event_estim.c:97
@ RESTARTPOLICY_ALWAYS
Definition: event_estim.c:95
@ RESTARTPOLICY_ESTIMATION
Definition: event_estim.c:96
@ RESTARTPOLICY_NEVER
Definition: event_estim.c:94
static SCIP_Bool shouldApplyRestartCompletion(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: event_estim.c:2418
static SCIP_RETCODE extendMemoryTreeProfile(SCIP *scip, TREEPROFILE *treeprofile, int mindepth)
Definition: event_estim.c:652
static void subtreeSumGapFree(SCIP *scip, SUBTREESUMGAP **ssg)
Definition: event_estim.c:959
#define DISP_HEADER
Definition: event_estim.c:118
#define DECL_TIMESERIESUPDATE(x)
Definition: event_estim.c:331
static void timeSeriesReset(TIMESERIES *timeseries)
Definition: event_estim.c:1728
static SCIP_DECL_EVENTFREE(eventFreeEstim)
Definition: event_estim.c:2636
#define RESTARTPOLICY_CHAR_COMPLETION
Definition: event_estim.c:104
#define DISP_DESC
Definition: event_estim.c:117
#define DISP_WIDTH
Definition: event_estim.c:119
#define ESTIMMETHOD_WBE
Definition: event_estim.c:158
#define TABLE_EARLIEST_STAGE
Definition: event_estim.c:113
#define ESTIMMETHOD_TPROF
Definition: event_estim.c:164
static void doubleExpSmoothInit(DOUBLEEXPSMOOTH *des, SCIP_Real x1)
Definition: event_estim.c:1674
#define DEFAULT_COEFMONOSSG
Definition: event_estim.c:247
static SCIP_Bool isEqualTreeProfileStats(TREEPROFILESTATS *stats, TREEPROFILESTATS *other)
Definition: event_estim.c:608
static int timeSeriesGetResolution(TIMESERIES *timeseries)
Definition: event_estim.c:1832
#define ESTIMMETHODS
Definition: event_estim.c:167
static SCIP_RETCODE createTreeProfile(SCIP *scip, TREEPROFILE **treeprofile)
Definition: event_estim.c:687
#define DISP_STRIPLINE
Definition: event_estim.c:122
static void subtreeSumGapDelSubtrees(SCIP *scip, SUBTREESUMGAP *ssg)
Definition: event_estim.c:872
static SCIP_DECL_TABLEOUTPUT(tableOutputEstim)
Definition: event_estim.c:2843
static SCIP_RETCODE updateTimeseries(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata, TREEDATA *treedata, SCIP_Bool isleaf)
Definition: event_estim.c:2511
static void resetTreeProfileStats(TREEPROFILESTATS *treeprofilestats)
Definition: event_estim.c:640
#define TABLE_POSITION
Definition: event_estim.c:112
static SCIP_Real treeDataGetWbe(TREEDATA *treedata)
Definition: event_estim.c:1622
static void resetTimeSeries(SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: event_estim.c:1990
#define DEFAULT_COMPLETIONTYPE
Definition: event_estim.c:248
static SCIP_DECL_EVENTINITSOL(eventInitsolEstim)
Definition: event_estim.c:2689
#define EVENTHDLR_DESC
Definition: event_estim.c:84
#define EVENTTYPE_ESTIM
Definition: event_estim.c:85
static SCIP_RETCODE SCIPregForestFromFile(SCIP_REGFOREST **regforest, const char *filename)
Definition: event_estim.c:471
static RESTARTPOLICY getRestartPolicy(SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: event_estim.c:2357
static SCIP_Real doubleExpSmoothGetTrend(DOUBLEEXPSMOOTH *des)
Definition: event_estim.c:1714
static void doubleExpSmoothReset(DOUBLEEXPSMOOTH *des, SCIP_Real initialvalue)
Definition: event_estim.c:1661
static char * real2String(SCIP_Real num, char *buf, int digits)
Definition: event_estim.c:384
#define ESTIMMETHOD_SSG
Definition: event_estim.c:163
static SCIP_RETCODE subtreeSumGapUpdate(SCIP *scip, SUBTREESUMGAP *ssg, SCIP_NODE *node, int nchildren, SCIP_Longint nsolvednodes)
Definition: event_estim.c:1450
static void freeTimeSeries(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: event_estim.c:2013
static SCIP_Real predictTotalSizeTreeProfile(SCIP *scip, TREEPROFILE *treeprofile, SCIP_Real minnodesperdepth)
Definition: event_estim.c:800
#define DES_ALPHA_GAP
Definition: event_estim.c:131
#define ESTIMMETHOD_COMPL
Definition: event_estim.c:157
#define TREEPROFILE_MINSIZE
Definition: event_estim.c:170
#define COMPLETIONTYPE_AUTO
Definition: event_estim.c:148
static SCIP_DECL_DISPOUTPUT(dispOutputCompleted)
Definition: event_estim.c:2866
#define EVENTHDLR_NAME
Definition: event_estim.c:83
static SCIP_RETCODE subtreeSumGapStoreNode(SCIP *scip, SUBTREESUMGAP *ssg, SCIP_NODE *node, int subtreeidx)
Definition: event_estim.c:1007
static SCIP_RETCODE getSearchCompletion(SCIP_EVENTHDLRDATA *eventhdlrdata, SCIP_Real *completed)
Definition: event_estim.c:2130
#define RESTARTPOLICY_CHAR_ESTIMATION
Definition: event_estim.c:105
static SCIP_Real timeSeriesGetTargetValue(TIMESERIES *timeseries)
Definition: event_estim.c:1823
#define DEFAULT_ESTIMMETHOD
Definition: event_estim.c:249
#define SSG_STARTPRIMBOUND
Definition: event_estim.c:171
#define DEFAULT_RESTARTNONLINEAR
Definition: event_estim.c:259
#define DEFAULT_RESTARTPOLICY
Definition: event_estim.c:254
#define TABLE_DESC
Definition: event_estim.c:111
static SCIP_Bool shouldApplyRestartEstimation(SCIP *scip, SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: event_estim.c:2444
#define DEFAULT_TREEPROFILE_MINNODESPERDEPTH
Definition: event_estim.c:253
static SCIP_DECL_EVENTEXITSOL(eventExitsolEstim)
Definition: event_estim.c:2719
#define DES_BETA_SSG
Definition: event_estim.c:138
#define DEFAULT_REGFORESTFILENAME
Definition: event_estim.c:245
event handler for tree size estimation and restarts
SCIP_FILE * SCIPfopen(const char *path, const char *mode)
Definition: fileio.c:153
int SCIPfeof(SCIP_FILE *stream)
Definition: fileio.c:227
int SCIPfclose(SCIP_FILE *fp)
Definition: fileio.c:232
char * SCIPfgets(char *s, int size, SCIP_FILE *stream)
Definition: fileio.c:200
#define nnodes
Definition: gastrans.c:74
SCIP_STATUS SCIPgetStatus(SCIP *scip)
Definition: scip_general.c:562
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:444
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3095
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3284
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:3143
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3061
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3466
SCIP_RETCODE SCIPhashmapRemoveAll(SCIP_HASHMAP *hashmap)
Definition: misc.c:3676
SCIP_RETCODE SCIPhashmapRemove(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3482
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:208
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip_message.c:225
#define SCIPdebugMsg
Definition: scip_message.h:78
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:120
SCIP_RETCODE SCIPaddLongintParam(SCIP *scip, const char *name, const char *desc, SCIP_Longint *valueptr, SCIP_Bool isadvanced, SCIP_Longint defaultvalue, SCIP_Longint minvalue, SCIP_Longint maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:111
SCIP_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_param.c:167
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:83
SCIP_RETCODE SCIPaddStringParam(SCIP *scip, const char *name, const char *desc, char **valueptr, SCIP_Bool isadvanced, const char *defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:194
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_param.c:139
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:57
void ** SCIPpqueueElems(SCIP_PQUEUE *pqueue)
Definition: misc.c:1540
void SCIPpqueueDelPos(SCIP_PQUEUE *pqueue, int pos)
Definition: misc.c:1435
void SCIPpqueueFree(SCIP_PQUEUE **pqueue)
Definition: misc.c:1324
SCIP_RETCODE SCIPpqueueInsert(SCIP_PQUEUE *pqueue, void *elem)
Definition: misc.c:1396
int SCIPpqueueNElems(SCIP_PQUEUE *pqueue)
Definition: misc.c:1529
SCIP_RETCODE SCIPpqueueCreate(SCIP_PQUEUE **pqueue, int initsize, SCIP_Real sizefac, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), SCIP_DECL_PQUEUEELEMCHGPOS((*elemchgpos)))
Definition: misc.c:1297
void * SCIPpqueueFirst(SCIP_PQUEUE *pqueue)
Definition: misc.c:1515
const char * SCIPdispGetName(SCIP_DISP *disp)
Definition: disp.c:335
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_disp.c:55
SCIP_RETCODE SCIPsetEventhdlrInitsol(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTINITSOL((*eventinitsol)))
Definition: scip_event.c:199
SCIP_RETCODE SCIPsetEventhdlrCopy(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTCOPY((*eventcopy)))
Definition: scip_event.c:143
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip_event.c:111
SCIP_EVENTHDLR * SCIPfindEventhdlr(SCIP *scip, const char *name)
Definition: scip_event.c:241
SCIP_EVENTHDLRDATA * SCIPeventhdlrGetData(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:406
SCIP_RETCODE SCIPsetEventhdlrExitsol(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTEXITSOL((*eventexitsol)))
Definition: scip_event.c:213
SCIP_RETCODE SCIPsetEventhdlrFree(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTFREE((*eventfree)))
Definition: scip_event.c:157
SCIP_RETCODE SCIPsetEventhdlrExit(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTEXIT((*eventexit)))
Definition: scip_event.c:185
SCIP_RETCODE SCIPsetEventhdlrInit(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTINIT((*eventinit)))
Definition: scip_event.c:171
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:1194
SCIP_RETCODE SCIPcatchEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip_event.c:293
SCIP_NODE * SCIPeventGetNode(SCIP_EVENT *event)
Definition: event.c:1530
SCIP_RETCODE SCIPdropEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip_event.c:333
SCIP_Bool SCIPisExact(SCIP *scip)
Definition: scip_exact.c:193
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:110
#define SCIPreallocMemoryArray(scip, ptr, newnum)
Definition: scip_mem.h:70
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:57
#define SCIPallocMemoryArray(scip, ptr, num)
Definition: scip_mem.h:64
#define SCIPallocClearBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:97
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip_mem.c:139
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPallocClearMemoryArray(scip, ptr, num)
Definition: scip_mem.h:66
#define SCIPallocMemory(scip, ptr)
Definition: scip_mem.h:60
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
#define SCIPfreeMemoryArray(scip, ptr)
Definition: scip_mem.h:80
#define SCIPfreeMemory(scip, ptr)
Definition: scip_mem.h:78
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip_nlp.c:110
SCIP_NODETYPE SCIPnodeGetType(SCIP_NODE *node)
Definition: tree.c:8473
SCIP_Real SCIPnodeGetLowerbound(SCIP_NODE *node)
Definition: tree.c:8503
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:8483
SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
Definition: tree.c:8782
int SCIPnodeGetDepth(SCIP_NODE *node)
Definition: tree.c:8493
int SCIPgetNActivePricers(SCIP *scip)
Definition: scip_pricer.c:348
SCIP_Real SCIPretransformObj(SCIP *scip, SCIP_Real obj)
Definition: scip_sol.c:2132
SCIP_RETCODE SCIPrestartSolve(SCIP *scip)
Definition: scip_solve.c:3603
SCIP_Bool SCIPisInRestart(SCIP *scip)
Definition: scip_solve.c:3709
SCIP_Real SCIPgetPrimalbound(SCIP *scip)
SCIP_Real SCIPgetUpperbound(SCIP *scip)
SCIP_Longint SCIPgetNNodes(SCIP *scip)
SCIP_Real SCIPgetDualbound(SCIP *scip)
SCIP_Real SCIPgetLowerbound(SCIP *scip)
int SCIPgetNRuns(SCIP *scip)
int SCIPgetNRootIntFixingsRun(SCIP *scip)
SCIP_RETCODE SCIPincludeTable(SCIP *scip, const char *name, const char *desc, SCIP_Bool active, SCIP_DECL_TABLECOPY((*tablecopy)), SCIP_DECL_TABLEFREE((*tablefree)), SCIP_DECL_TABLEINIT((*tableinit)), SCIP_DECL_TABLEEXIT((*tableexit)), SCIP_DECL_TABLEINITSOL((*tableinitsol)), SCIP_DECL_TABLEEXITSOL((*tableexitsol)), SCIP_DECL_TABLEOUTPUT((*tableoutput)), SCIP_DECL_TABLECOLLECT((*tablecollect)), SCIP_TABLEDATA *tabledata, int position, SCIP_STAGE earlieststage)
Definition: scip_table.c:62
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
Definition: scip_timing.c:378
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
int SCIPgetNSiblings(SCIP *scip)
Definition: scip_tree.c:230
int SCIPgetNChildren(SCIP *scip)
Definition: scip_tree.c:188
SCIP_RETCODE SCIPgetOpenNodesData(SCIP *scip, SCIP_NODE ***leaves, SCIP_NODE ***children, SCIP_NODE ***siblings, int *nleaves, int *nchildren, int *nsiblings)
Definition: scip_tree.c:398
SCIP_RETCODE SCIPgetChildren(SCIP *scip, SCIP_NODE ***children, int *nchildren)
Definition: scip_tree.c:164
SCIP_NODE * SCIPgetFocusNode(SCIP *scip)
Definition: scip_tree.c:72
int SCIPgetNLeaves(SCIP *scip)
Definition: scip_tree.c:272
SCIP_Bool SCIPwasNodeLastBranchParent(SCIP *scip, SCIP_NODE *node)
Definition: scip_tree.c:733
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10827
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:10955
memory allocation routines
#define BMSfreeMemory(ptr)
Definition: memory.h:145
#define BMSduplicateMemoryArray(ptr, source, num)
Definition: memory.h:143
#define BMSclearMemory(ptr)
Definition: memory.h:129
#define BMSallocMemoryArray(ptr, num)
Definition: memory.h:123
#define BMSfreeMemoryArray(ptr)
Definition: memory.h:147
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
#define BMSfreeMemoryArrayNull(ptr)
Definition: memory.h:148
#define BMSallocMemory(ptr)
Definition: memory.h:118
propagator for symmetry handling
public methods for displaying runtime statistics
public methods for managing events
wrapper functions to map file i/o to standard or zlib file i/o
struct SCIP_File SCIP_FILE
Definition: pub_fileio.h:43
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPdebugMessage
Definition: pub_message.h:96
#define SCIPstatistic(x)
Definition: pub_message.h:120
public data structures and miscellaneous methods
public methods for branch and bound tree
public methods for display handler plugins
public methods for event handler plugins and event handlers
general public methods
public methods for memory management
public methods for message handling
public methods for nonlinear relaxation
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for variable pricer plugins
public methods for solutions
public solving methods
public methods for querying solving statistics
public methods for statistics table plugins
public methods for timing
public methods for the branch-and-bound tree
SCIP_Real initialvalue
Definition: event_estim.c:180
SCIP_Real trend
Definition: event_estim.c:179
SCIP_Bool usetrendinlevel
Definition: event_estim.c:181
SCIP_Real level
Definition: event_estim.c:178
SCIP_Real alpha
Definition: event_estim.c:176
SCIP_Real beta
Definition: event_estim.c:177
SCIP_Real lowerbound
Definition: event_estim.c:361
SCIP_NODE * node
Definition: event_estim.c:360
int subtreeidx
Definition: event_estim.c:363
SCIP_Real * value
Definition: event_estim.c:374
SCIP_Longint nodelastsplit
Definition: event_estim.c:323
SCIP_Real scalingfactor
Definition: event_estim.c:321
SCIP_Real value
Definition: event_estim.c:318
SCIP_PQUEUE ** subtreepqueues
Definition: event_estim.c:320
SCIP_HASHMAP * nodes2info
Definition: event_estim.c:319
SCIP_Longint nminnodeslastsplit
Definition: event_estim.c:324
SCIP_Real pblastsplit
Definition: event_estim.c:322
SCIP_Longint nobs
Definition: event_estim.c:349
SCIP_Real * vals
Definition: event_estim.c:343
SCIP_Real * estimation
Definition: event_estim.c:344
int resolution
Definition: event_estim.c:352
SCIP_Real currentvalue
Definition: event_estim.c:347
DOUBLEEXPSMOOTH des
Definition: event_estim.c:341
char * name
Definition: event_estim.c:342
SCIP_Bool useleafts
Definition: event_estim.c:353
SCIP_Real initialvalue
Definition: event_estim.c:348
DECL_TIMESERIESUPDATE((*timeseriesupdate))
SCIP_Real smoothestimation
Definition: event_estim.c:345
SCIP_Real targetvalue
Definition: event_estim.c:346
SCIP_Longint nvisited
Definition: event_estim.c:311
SCIP_Longint nopen
Definition: event_estim.c:308
SCIP_Longint nleaves
Definition: event_estim.c:310
long double weight
Definition: event_estim.c:312
SUBTREESUMGAP * ssg
Definition: event_estim.c:313
SCIP_Longint ninner
Definition: event_estim.c:309
SCIP_Longint nnodes
Definition: event_estim.c:307
SCIP_Longint * profile
Definition: event_estim.c:233
TREEPROFILESTATS lastestimatestats
Definition: event_estim.c:237
SCIP_Real lastestimate
Definition: event_estim.c:236
TREEPROFILESTATS stats
Definition: event_estim.c:235
type definitions for displaying runtime statistics
@ SCIP_DISPSTATUS_AUTO
Definition: type_disp.h:61
type definitions for managing events
struct SCIP_EventhdlrData SCIP_EVENTHDLRDATA
Definition: type_event.h:160
#define SCIP_EVENTTYPE_NODEBRANCHED
Definition: type_event.h:96
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:156
#define SCIP_EVENTTYPE_NODEDELETE
Definition: type_event.h:97
type definitions for message output methods
@ SCIP_VERBLEVEL_HIGH
Definition: type_message.h:61
@ SCIP_VERBLEVEL_FULL
Definition: type_message.h:62
type definitions for miscellaneous datastructures
type definitions for return codes for SCIP methods
@ SCIP_NOFILE
Definition: type_retcode.h:47
@ SCIP_INVALIDDATA
Definition: type_retcode.h:52
@ SCIP_PARAMETERWRONGVAL
Definition: type_retcode.h:57
@ SCIP_NOMEMORY
Definition: type_retcode.h:44
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_STAGE_SOLVED
Definition: type_set.h:54
@ SCIP_STAGE_INITSOLVE
Definition: type_set.h:52
type definitions for problem statistics
@ SCIP_STATUS_UNKNOWN
Definition: type_stat.h:42
type definitions for displaying statistics tables
@ SCIP_NODETYPE_CHILD
Definition: type_tree.h:44
@ SCIP_NODETYPE_DEADEND
Definition: type_tree.h:46
@ SCIP_NODETYPE_SIBLING
Definition: type_tree.h:43
@ SCIP_NODETYPE_LEAF
Definition: type_tree.h:45