Scippy

SCIP

Solving Constraint Integer Programs

history.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 history.c
26 * @ingroup OTHER_CFILES
27 * @brief methods for branching and inference history
28 * @author Tobias Achterberg
29 */
30
31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32
33#include <assert.h>
34
35#include "scip/def.h"
36#include "scip/set.h"
37#include "scip/history.h"
38#include "scip/pub_misc.h"
39#include "scip/pub_history.h"
40#include "scip/pub_message.h"
41
42#ifndef NDEBUG
43#include "scip/struct_history.h"
44#endif
45
46/*
47 * methods for branching and inference history
48 */
49
50/** creates an empty history entry */
52 SCIP_HISTORY** history, /**< pointer to store branching and inference history */
53 BMS_BLKMEM* blkmem /**< block memory */
54 )
55{
56 assert(history != NULL);
57
58 SCIP_ALLOC( BMSallocBlockMemory(blkmem, history) );
59
60 SCIPhistoryReset(*history);
61
62 return SCIP_OKAY;
63}
64
65/** frees a history entry */
67 SCIP_HISTORY** history, /**< pointer to branching and inference history */
68 BMS_BLKMEM* blkmem /**< block memory */
69 )
70{
71 assert(history != NULL);
72 assert(*history != NULL);
73
74 BMSfreeBlockMemory(blkmem, history);
75}
76
77/** resets history entry to zero */
79 SCIP_HISTORY* history /**< branching and inference history */
80 )
81{
82 assert(history != NULL);
83
84 history->pscostcount[0] = 0.0;
85 history->pscostcount[1] = 0.0;
86 history->pscostweightedmean[0] = 0.0;
87 history->pscostweightedmean[1] = 0.0;
88 history->pscostvariance[0] = 0.0;
89 history->pscostvariance[1] = 0.0;
90 history->ancpscostcount[0] = 0.0;
91 history->ancpscostcount[1] = 0.0;
92 history->ancpscostweightedmean[0] = 0.0;
93 history->ancpscostweightedmean[1] = 0.0;
94 history->vsids[0] = 0.0;
95 history->vsids[1] = 0.0;
96 history->conflengthsum[0] = 0.0;
97 history->conflengthsum[1] = 0.0;
98 history->inferencesum[0] = 0.0;
99 history->inferencesum[1] = 0.0;
100 history->cutoffsum[0] = 0.0;
101 history->cutoffsum[1] = 0.0;
102 history->ratio = 0.0;
103 history->ratiovalid = FALSE;
104 history->balance = 0.0;
105 history->ngmi = 0;
106 history->gmieff = 0.0;
107 history->gmieffsum = 0.0;
108 history->nactiveconflicts[0] = 0;
109 history->nactiveconflicts[1] = 0;
110 history->nbranchings[0] = 0;
111 history->nbranchings[1] = 0;
112 history->branchdepthsum[0] = 0;
113 history->branchdepthsum[1] = 0;
114}
115
116/** unites two history entries by adding the values of the second one to the first one */
118 SCIP_HISTORY* history, /**< branching and inference history */
119 SCIP_HISTORY* addhistory, /**< history values to add to history */
120 SCIP_Bool switcheddirs /**< should the history entries be united with switched directories */
121 )
122{
123 int i;
124
125 assert(history != NULL);
126 assert(addhistory != NULL);
127
128 /* loop over both directions and combine the statistics */
129 for( i = 0; i <= 1; ++i )
130 {
131 int d;
132 d = (switcheddirs ? 1 - i : i);
133
134 history->pscostcount[i] += addhistory->pscostcount[d];
135 history->ancpscostcount[i] += addhistory->ancpscostcount[d];
136
137 /* if both histories a count of zero, there is nothing to do */
138 if( history->pscostcount[i] > 0.0 )
139 {
140 SCIP_Real oldmean;
141
142 oldmean = history->pscostweightedmean[i];
143
144 /* we update the mean as if the history was one observation with a large weight */
145 history->pscostweightedmean[i] += addhistory->pscostcount[d] * (addhistory->pscostweightedmean[d] - history->pscostweightedmean[i]) / history->pscostcount[i];
146
147 /* we update the variance of two sets A and B as S_A+B = S_A + (mu_A)^2 * count_A ...*/
148 /* @todo is there a numerically more stable variant for this merge? */
149 history->pscostvariance[i] = history->pscostvariance[i] + oldmean * oldmean * (history->pscostcount[i] - addhistory->pscostcount[d]) + \
150 /* S_B + (mu_B)^2 * count_B */
151 addhistory->pscostvariance[d] + addhistory->pscostcount[d] * addhistory->pscostweightedmean[d] * addhistory->pscostweightedmean[d] - \
152 /* - count_A+B * mu_A+B^ 2 */
153 history->pscostcount[i] * history->pscostweightedmean[i] * history->pscostweightedmean[i];
154
155 /* slight violations of nonnegativity are numerically possible */
156 history->pscostvariance[i] = MAX(history->pscostvariance[i], 0.0);
157 }
158#ifndef NDEBUG
159 else
160 {
161 assert(history->pscostweightedmean[i] == 0.0);
162 assert(history->pscostvariance[i] == 0.0);
163 }
164#endif
165 /* if both histories a discounted count of zero, there is nothing to do */
166 if( history->ancpscostcount[i] > 0.0 )
167 {
168 /* we update the mean as if the history was one observation with a large weight */
169 history->ancpscostweightedmean[i] += addhistory->ancpscostcount[d] * (addhistory->ancpscostweightedmean[d] - history->ancpscostweightedmean[i]) / history->ancpscostcount[i];
170 }
171#ifndef NDEBUG
172 else
173 {
174 assert(history->ancpscostweightedmean[i] == 0.0);
175 }
176#endif
177
178 history->vsids[i] += addhistory->vsids[d];
179 history->conflengthsum[i] += addhistory->conflengthsum[d];
180 history->inferencesum[i] += addhistory->inferencesum[d];
181 history->cutoffsum[i] += addhistory->cutoffsum[d];
182 history->nactiveconflicts[i] += addhistory->nactiveconflicts[d];
183 history->nbranchings[i] += addhistory->nbranchings[d];
184 history->branchdepthsum[i] += addhistory->branchdepthsum[d];
185 }
186}
187
188/** updates the pseudo costs for a change of "solvaldelta" in the variable's LP solution value and a change of "objdelta"
189 * in the LP's objective value
190 */
192 SCIP_HISTORY* history, /**< branching and inference history */
193 SCIP_SET* set, /**< global SCIP settings */
194 SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
195 SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
196 SCIP_Real weight /**< weight of this update in pseudo cost sum (added to pscostcount) */
197 )
198{
199 SCIP_Real distance;
201 SCIP_Real sumcontribution;
202 SCIP_Real olddelta;
203 int dir;
204
205 assert(history != NULL);
206 assert(set != NULL);
207 assert(!SCIPsetIsInfinity(set, REALABS(solvaldelta)));
208 assert(!SCIPsetIsInfinity(set, objdelta));
209 assert(!SCIPsetIsNegative(set, objdelta));
210 assert(0.0 < weight && weight <= 1.0);
211
212 if( SCIPsetIsPositive(set, solvaldelta) )
213 {
214 /* variable's solution value moved upwards */
215 dir = 1;
216 distance = solvaldelta;
217 }
218 else if( SCIPsetIsNegative(set, solvaldelta) )
219 {
220 /* variable's solution value moved downwards */
221 dir = 0;
222 distance = -solvaldelta;
223 }
224 else
225 {
226 /* the variable's solution value didn't change, and the pseudo costs cannot be updated */
227 return;
228 }
229 assert(dir == 0 || dir == 1);
230 assert(SCIPsetIsPositive(set, distance));
231
232 /* apply a lower limit on the distance to avoid numerical instabilities due to very large summands */
234 distance = MAX(distance, eps);
235
236 /* slightly increase objective delta, s.t. pseudo cost values are not zero, and fractionalities are
237 * always used at least a bit
238 */
239 objdelta += SCIPsetPseudocostdelta(set);
240
241 sumcontribution = objdelta/distance;
242 /* update the pseudo cost values */
243 olddelta = sumcontribution - history->pscostweightedmean[dir];
244 history->pscostcount[dir] += weight;
245 history->pscostweightedmean[dir] += weight * olddelta / history->pscostcount[dir];
246 history->pscostvariance[dir] = history->pscostvariance[dir] + weight * olddelta * (sumcontribution - history->pscostweightedmean[dir]);
247
248 SCIPsetDebugMsg(set, "updated pseudo costs of history %p: dir=%d, distance=%g, objdelta=%g, weight=%g -> %g/%g\n",
249 (void*)history, dir, distance, objdelta, weight, history->pscostcount[dir], history->pscostweightedmean[dir]);
250}
251
252/** updates the ancestral pseudo costs for a change of "solvaldelta" in the variable's LP solution value and a change of "objdelta"
253 * in the LP's objective value
254 */
256 SCIP_HISTORY* history, /**< branching and inference history */
257 SCIP_SET* set, /**< global SCIP settings */
258 SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
259 SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
260 SCIP_Real weight /**< weight of this update in discounted pseudo cost sum (added to pscostcount) */
261 )
262{
263 SCIP_Real distance;
265 SCIP_Real sumcontribution;
266 SCIP_Real olddelta;
267 int dir;
268
269 assert(history != NULL);
270 assert(set != NULL);
271 assert(!SCIPsetIsInfinity(set, REALABS(solvaldelta)));
272 assert(!SCIPsetIsInfinity(set, objdelta));
273 assert(!SCIPsetIsNegative(set, objdelta));
274 assert(0.0 < weight && weight <= 1.0);
275
276 if( SCIPsetIsPositive(set, solvaldelta) )
277 {
278 /* variable's solution value moved upwards */
279 dir = 1;
280 distance = solvaldelta;
281 }
282 else if( SCIPsetIsNegative(set, solvaldelta) )
283 {
284 /* variable's solution value moved downwards */
285 dir = 0;
286 distance = -solvaldelta;
287 }
288 else
289 {
290 /* the variable's solution value didn't change, and the pseudo costs cannot be updated */
291 return;
292 }
293 assert(dir == 0 || dir == 1);
294 assert(SCIPsetIsPositive(set, distance));
295
296 /* apply a lower limit on the distance to avoid numerical instabilities due to very large summands */
298 distance = MAX(distance, eps);
299
300 /* slightly increase objective delta, s.t. discounted pseudo cost values are not zero, and fractionalities are
301 * always used at least a bit
302 */
303 objdelta += SCIPsetPseudocostdelta(set);
304
305 sumcontribution = objdelta/distance;
306 /* update the pseudo cost values */
307 olddelta = sumcontribution - history->ancpscostweightedmean[dir];
308 history->ancpscostcount[dir] += weight;
309 history->ancpscostweightedmean[dir] += weight * olddelta / history->ancpscostcount[dir];
310
311 SCIPsetDebugMsg(set, "updated ancestor pseudo costs of history %p: dir=%d, distance=%g, objdelta=%g, weight=%g -> %g/%g\n",
312 (void*)history, dir, distance, objdelta, weight, history->ancpscostcount[dir], history->ancpscostweightedmean[dir]);
313}
314
315/**@name Value based history
316 *
317 * Value based history methods
318 *
319 * @{
320 */
321
322/** creates an empty value history */
324 SCIP_VALUEHISTORY** valuehistory, /**< pointer to store the value based branching and inference histories */
325 BMS_BLKMEM* blkmem /**< block memory */
326 )
327{
328 assert(valuehistory != NULL);
329
330 SCIP_ALLOC( BMSallocBlockMemory(blkmem, valuehistory) );
331
332 (*valuehistory)->nvalues = 0;
333 (*valuehistory)->sizevalues = 5;
334
335 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*valuehistory)->histories, (*valuehistory)->sizevalues) );
336 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*valuehistory)->values, (*valuehistory)->sizevalues) );
337
338 return SCIP_OKAY;
339}
340
341/** frees a value history */
343 SCIP_VALUEHISTORY** valuehistory, /**< pointer to value based history */
344 BMS_BLKMEM* blkmem /**< block memory */
345 )
346{
347 assert(valuehistory != NULL);
348
349 if( *valuehistory != NULL )
350 {
351 int i;
352
353 for( i = (*valuehistory)->nvalues-1; i >= 0; --i )
354 SCIPhistoryFree(&(*valuehistory)->histories[i], blkmem);
355
356 BMSfreeBlockMemoryArray(blkmem, &(*valuehistory)->histories, (*valuehistory)->sizevalues);
357 BMSfreeBlockMemoryArray(blkmem, &(*valuehistory)->values, (*valuehistory)->sizevalues);
358
359 BMSfreeBlockMemory(blkmem, valuehistory);
360 }
361}
362
363/** finds for the given domain value the history if it does not exist yet it will be created */
365 SCIP_VALUEHISTORY* valuehistory, /**< value based history */
366 BMS_BLKMEM* blkmem, /**< block memory */
367 SCIP_SET* set, /**< global SCIP settings */
368 SCIP_Real value, /**< domain value of interest */
369 SCIP_HISTORY** history /**< pointer to store the history for the given domain value */
370 )
371{
372 int pos;
373
374 assert(valuehistory != NULL);
375 assert(blkmem != NULL);
376 assert(set != NULL);
377 assert(history != NULL);
378
379 *history = NULL;
380
381 if( valuehistory->nvalues == 0 || !SCIPsortedvecFindReal(valuehistory->values, value, valuehistory->nvalues, &pos) )
382 {
383 /* check if we need to resize the history array */
384 if( valuehistory->nvalues == valuehistory->sizevalues )
385 {
386 int newsize;
387
388 newsize = SCIPsetCalcMemGrowSize(set, valuehistory->sizevalues + 1);
389 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &valuehistory->histories, valuehistory->nvalues, newsize) );
390 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &valuehistory->values, valuehistory->nvalues, newsize) );
391 valuehistory->sizevalues = newsize;
392 }
393
394 /* create new empty history entry */
395 SCIP_CALL( SCIPhistoryCreate(history, blkmem) );
396
397 /* insert new history into the value based history array */
398 SCIPsortedvecInsertRealPtr(valuehistory->values, (void**)valuehistory->histories, value, (void*)(*history), &valuehistory->nvalues, NULL);
399 }
400 else
401 (*history) = valuehistory->histories[pos]; /*lint !e530*/
402
403 assert(*history != NULL);
404
405 return SCIP_OKAY;
406}
407
408/** scales the conflict score values with the given scalar for each value history entry */
410 SCIP_VALUEHISTORY* valuehistory, /**< value based history */
411 SCIP_Real scalar /**< scalar to multiply the conflict scores with */
412 )
413{
414 if( valuehistory != NULL )
415 {
416 int i;
417
418 for( i = valuehistory->nvalues-1; i >= 0; --i )
419 {
420 SCIPhistoryScaleVSIDS(valuehistory->histories[i], scalar);
421 }
422 }
423}
424
425
426/*
427 * simple functions implemented as defines
428 */
429
430#ifndef NDEBUG
431
432/* In debug mode, the following methods are implemented as function calls to ensure
433 * type validity.
434 * In optimized mode, the methods are implemented as defines to improve performance.
435 * However, we want to have them in the library anyways, so we have to undef the defines.
436 */
437
438#undef SCIPvaluehistoryGetNValues
439#undef SCIPvaluehistoryGetHistories
440#undef SCIPvaluehistoryGetValues
441
442/** return the number of (domain) values for which a history exists */
444 SCIP_VALUEHISTORY* valuehistory /**< value based history */
445 )
446{
447 assert(valuehistory != NULL);
448
449 return valuehistory->nvalues;
450}
451
452/** return the array containing the histories for the individual (domain) values */
454 SCIP_VALUEHISTORY* valuehistory /**< value based history */
455 )
456{
457 assert(valuehistory != NULL);
458
459 return valuehistory->histories;
460}
461
462/** return the array containing the (domain) values for which a history exists */
464 SCIP_VALUEHISTORY* valuehistory /**< value based history */
465 )
466{
467 assert(valuehistory != NULL);
468
469 return valuehistory->values;
470}
471
472#endif
473
474/**@} */
475
476/*
477 * simple functions implemented as defines
478 */
479
480#ifndef NDEBUG
481
482/* In debug mode, the following methods are implemented as function calls to ensure
483 * type validity.
484 * In optimized mode, the methods are implemented as defines to improve performance.
485 * However, we want to have them in the library anyways, so we have to undef the defines.
486 */
487
488#undef SCIPbranchdirOpposite
489#undef SCIPhistoryGetPseudocost
490#undef SCIPhistoryGetPseudocostCount
491#undef SCIPhistoryIsPseudocostEmpty
492#undef SCIPhistoryGetAncPseudocost
493#undef SCIPhistoryGetAncPseudocostCount
494#undef SCIPhistoryIsAncPseudocostEmpty
495#undef SCIPhistoryIncVSIDS
496#undef SCIPhistoryScaleVSIDS
497#undef SCIPhistoryGetVSIDS
498#undef SCIPhistoryIncNActiveConflicts
499#undef SCIPhistoryGetNActiveConflicts
500#undef SCIPhistoryGetAvgConflictlength
501#undef SCIPhistoryIncNBranchings
502#undef SCIPhistoryIncInferenceSum
503#undef SCIPhistoryIncCutoffSum
504#undef SCIPhistoryGetNBranchings
505#undef SCIPhistoryGetInferenceSum
506#undef SCIPhistoryGetAvgInferences
507#undef SCIPhistoryGetCutoffSum
508#undef SCIPhistoryGetAvgCutoffs
509#undef SCIPhistoryGetAvgBranchdepth
510#undef SCIPhistoryIsRatioValid
511#undef SCIPhistoryGetLastRatio
512#undef SCIPhistorySetRatioHistory
513#undef SCIPhistoryGetLastBalance
514#undef SCIPhistorySetLastGMIeff
515#undef SCIPhistoryGetLastGMIeff
516#undef SCIPhistoryIncGMIeffSum
517#undef SCIPhistoryGetAvgGMIeff
518
519/** returns the opposite direction of the given branching direction */
521 SCIP_BRANCHDIR dir /**< branching direction */
522 )
523{
526}
527
528/** returns the expected dual gain for moving the corresponding variable by "solvaldelta" */
530 SCIP_HISTORY* history, /**< branching and inference history */
531 SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
532 )
533{
534 assert(history != NULL);
535
536 if( solvaldelta >= 0.0 )
537 return solvaldelta * (history->pscostcount[1] > 0.0 ? history->pscostweightedmean[1] : 1.0);
538 else
539 return -solvaldelta * (history->pscostcount[0] > 0.0 ? history->pscostweightedmean[0] : 1.0);
540}
541
542/** returns the expected ancestral dual gain for moving the corresponding variable by "solvaldelta" */
544 SCIP_HISTORY* history, /**< branching and inference history */
545 SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
546 )
547{
548 assert(history != NULL);
549
550 if( solvaldelta >= 0.0 )
551 return solvaldelta * (history->ancpscostcount[1] > 0.0 ? history->ancpscostweightedmean[1] : 1.0);
552 else
553 return -solvaldelta * (history->ancpscostcount[0] > 0.0 ? history->ancpscostweightedmean[0] : 1.0);
554}
555
556/** returns the variance of pseudo costs about the mean. */
558 SCIP_HISTORY* history, /**< branching and inference history */
559 SCIP_BRANCHDIR direction /**< direction of variable: 1 for upwards history, 0 for downwards history */
560 )
561{
562 int dir;
563 SCIP_Real correctionfactor;
564
565 assert(history != NULL);
566 assert(direction == SCIP_BRANCHDIR_UPWARDS || direction == SCIP_BRANCHDIR_DOWNWARDS);
567
568 dir = (direction == SCIP_BRANCHDIR_UPWARDS ? 1 : 0);
569 correctionfactor = history->pscostcount[dir] - 1.0;
570
571 /** @todo for an unbiased estimate of the weighted sample variance, we need a correction factor that uses the sum of squared weights */
572 if( correctionfactor > 0.9 )
573 return history->pscostvariance[dir] / correctionfactor;
574 else
575 return 0.0;
576}
577
578/** returns the (possible fractional) number of (partial) pseudo cost updates performed on this pseudo cost entry in
579 * the given branching direction
580 */
582 SCIP_HISTORY* history, /**< branching and inference history */
583 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
584 )
585{
586 assert(history != NULL);
587 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
588 assert((int)dir == 0 || (int)dir == 1);
589
590 return history->pscostcount[dir];
591}
592
593/** returns the (possible fractional) number of (partial) ancestral pseudo cost updates performed on this pseudo cost entry in
594 * the given branching direction
595 */
597 SCIP_HISTORY* history, /**< branching and inference history */
598 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
599 )
600{
601 assert(history != NULL);
602 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
603 assert((int)dir == 0 || (int)dir == 1);
604
605 return history->ancpscostcount[dir];
606}
607
608/** returns whether the pseudo cost entry is empty in the given branching direction (whether no value was added yet) */
610 SCIP_HISTORY* history, /**< branching and inference history */
611 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
612 )
613{
614 assert(history != NULL);
615 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
616 assert((int)dir == 0 || (int)dir == 1);
617
618 return (history->pscostcount[dir] == 0.0);
619}
620
621/** returns whether the ancestral pseudo cost entry is empty in the given branching direction (whether no value was added yet) */
623 SCIP_HISTORY* history, /**< branching and inference history */
624 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
625 )
626{
627 assert(history != NULL);
628 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
629 assert((int)dir == 0 || (int)dir == 1);
630
631 return (history->ancpscostcount[dir] == 0.0);
632}
633
634/** increases the conflict score of the history entry by the given weight */
636 SCIP_HISTORY* history, /**< branching and inference history */
637 SCIP_BRANCHDIR dir, /**< branching direction */
638 SCIP_Real weight /**< weight of this update in conflict score */
639 )
640{
641 assert(history != NULL);
642 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
643 assert((int)dir == 0 || (int)dir == 1);
644
645 history->vsids[dir] += weight;
646}
647
648/** scales the conflict score values with the given scalar */
650 SCIP_HISTORY* history, /**< branching and inference history */
651 SCIP_Real scalar /**< scalar to multiply the conflict scores with */
652 )
653{
654 assert(history != NULL);
655
656 history->vsids[0] *= scalar;
657 history->vsids[1] *= scalar;
658}
659
660/** gets the conflict score of the history entry */
662 SCIP_HISTORY* history, /**< branching and inference history */
663 SCIP_BRANCHDIR dir /**< branching direction */
664 )
665{
666 assert(history != NULL);
667 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
668 assert((int)dir == 0 || (int)dir == 1);
669
670 return history->vsids[dir];
671}
672
673/** increases the number of active conflicts by one and the overall length of the history entry by the given weight */
675 SCIP_HISTORY* history, /**< branching and inference history */
676 SCIP_BRANCHDIR dir, /**< branching direction */
677 SCIP_Real length /**< length of the conflict */
678 )
679{
680 assert(history != NULL);
681 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
682 assert((int)dir == 0 || (int)dir == 1);
683 assert(length >= 0.0);
684
685 history->nactiveconflicts[dir]++;
686 history->conflengthsum[dir] += length;
687}
688
689/** gets the number of active conflicts of the history entry */
691 SCIP_HISTORY* history, /**< branching and inference history */
692 SCIP_BRANCHDIR dir /**< branching direction */
693 )
694{
695 assert(history != NULL);
696 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
697 assert((int)dir == 0 || (int)dir == 1);
698
699 return history->nactiveconflicts[dir];
700}
701
702/** gets the average conflict length of the history entry */
704 SCIP_HISTORY* history, /**< branching and inference history */
705 SCIP_BRANCHDIR dir /**< branching direction */
706 )
707{
708 assert(history != NULL);
709 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
710 assert((int)dir == 0 || (int)dir == 1);
711
712 return history->conflengthsum[dir] > 0.0 ? (SCIP_Real)history->nactiveconflicts[dir]/(SCIP_Real)history->conflengthsum[dir] : 0.0;
713}
714
715/** increases the number of branchings counter */
717 SCIP_HISTORY* history, /**< branching and inference history */
718 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
719 int depth /**< depth at which the bound change took place */
720 )
721{
722 assert(history != NULL);
723 assert(depth >= 1);
724 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
725 assert((int)dir == 0 || (int)dir == 1);
726
727 history->nbranchings[dir]++;
728 history->branchdepthsum[dir] += depth;
729}
730
731/** increases the number of inferences counter by a certain value */
733 SCIP_HISTORY* history, /**< branching and inference history */
734 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
735 SCIP_Real weight /**< weight of this update in inference score */
736 )
737{
738 assert(history != NULL);
739 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
740 assert((int)dir == 0 || (int)dir == 1);
741 assert(history->nbranchings[dir] >= 1);
742 assert(weight >= 0.0);
743
744 history->inferencesum[dir] += weight;
745}
746
747/** increases the number of cutoffs counter */
749 SCIP_HISTORY* history, /**< branching and inference history */
750 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
751 SCIP_Real weight /**< weight of this update in cutoff score */
752 )
753{
754 assert(history != NULL);
755 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
756 assert((int)dir == 0 || (int)dir == 1);
757 assert(history->nbranchings[dir] >= 1);
758 assert(weight >= 0.0);
759
760 history->cutoffsum[dir] += weight;
761}
762
763/** get number of branchings counter */
765 SCIP_HISTORY* history, /**< branching and inference history */
766 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
767 )
768{
769 assert(history != NULL);
770 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
771 assert((int)dir == 0 || (int)dir == 1);
772
773 return history->nbranchings[dir];
774}
775
776/** get number of inferences counter */
778 SCIP_HISTORY* history, /**< branching and inference history */
779 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
780 )
781{
782 assert(history != NULL);
783 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
784 assert((int)dir == 0 || (int)dir == 1);
785
786 return history->inferencesum[dir];
787}
788
789/** returns the average number of inferences per branching */
791 SCIP_HISTORY* history, /**< branching and inference history */
792 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
793 )
794{
795 assert(history != NULL);
796 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
797 assert((int)dir == 0 || (int)dir == 1);
798
799 return history->nbranchings[dir] > 0 ? (SCIP_Real)history->inferencesum[dir]/(SCIP_Real)history->nbranchings[dir] : 0.0;
800}
801
802/** get number of cutoffs counter */
804 SCIP_HISTORY* history, /**< branching and inference history */
805 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
806 )
807{
808 assert(history != NULL);
809 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
810 assert((int)dir == 0 || (int)dir == 1);
811
812 return history->cutoffsum[dir];
813}
814
815/** returns the average number of cutoffs per branching */
817 SCIP_HISTORY* history, /**< branching and inference history */
818 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
819 )
820{
821 assert(history != NULL);
822 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
823 assert((int)dir == 0 || (int)dir == 1);
824
825 return history->nbranchings[dir] > 0 ? (SCIP_Real)history->cutoffsum[dir]/(SCIP_Real)history->nbranchings[dir] : 0.0;
826}
827
828/** returns the average depth of bound changes due to branching */
830 SCIP_HISTORY* history, /**< branching and inference history */
831 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
832 )
833{
834 assert(history != NULL);
835 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
836 assert((int)dir == 0 || (int)dir == 1);
837
838 return history->nbranchings[dir] > 0 ? (SCIP_Real)history->branchdepthsum[dir]/(SCIP_Real)history->nbranchings[dir] : 1.0;
839}
840
841/** returns true if the given history contains a valid ratio */
843 SCIP_HISTORY* history /**< branching and inference history */
844 )
845{
846 assert(history != NULL);
847
848 return history->ratiovalid;
849}
850
851/** returns the most recent ratio computed given the variable history */
853 SCIP_HISTORY* history /**< branching and inference history */
854 )
855{
856 assert(history != NULL);
857 assert(history->ratiovalid);
858
859 return history->ratio;
860}
861
862/** returns the most recent value of r/l used to compute this variable's ratio */
864 SCIP_HISTORY* history /**< branching and inference history */
865 )
866{
867 assert(history != NULL);
868 assert(history->ratiovalid);
869
870 return history->balance;
871}
872
873/** returns the average efficacy value for the GMI cut produced by this variable */
875 SCIP_HISTORY* history /**< branching and inference history */
876 )
877{
878 assert(history != NULL);
879
880 return history->ngmi > 0 ? history->gmieffsum / history->ngmi : 0.0;
881}
882
883/** increases the average efficacy value for the GMI cut produced by this variable */
885 SCIP_HISTORY* history, /**< branching and inference history */
886 SCIP_Real gmieff /**< normalized efficacy value of a cut which will increase gmieff */
887 )
888{
889 assert(history != NULL);
890 assert(gmieff >= 0.0);
891
892 history->gmieffsum += gmieff;
893 history->ngmi += 1;
894}
895
896/** returns the most recent efficacy value for the GMI cut produced by this variable */
898 SCIP_HISTORY* history /**< branching and inference history */
899 )
900{
901 assert(history != NULL);
902
903 return history->gmieff;
904}
905
906/** sets the new most recent efficacy value for the GMI cut produced by this variable */
908 SCIP_HISTORY* history, /**< branching and inference history */
909 SCIP_Real gmieff /**< Efficacy of GMI cut produced from simplex tableau row of this var */
910 )
911{
912 assert(history != NULL);
913
914 history->gmieff = gmieff;
915}
916
917/** sets the ratio history for a particular variable */
919 SCIP_HISTORY* history, /**< branching and inference history */
920 SCIP_Bool valid, /**< True iff the ratio computed is valid */
921 SCIP_Real ratio, /**< Ratio of the characteristic polynomial with gains (1, rightgain/leftgain) */
922 SCIP_Real balance /**< The value of rightgain/leftgain */
923 )
924{
925 assert(history != NULL);
926
927 history->ratiovalid = valid;
928 history->ratio = ratio;
929 history->balance = balance;
930}
931
932#endif
common defines and data types used in all packages of SCIP
#define NULL
Definition: def.h:248
#define SCIP_Longint
Definition: def.h:141
#define SCIP_Bool
Definition: def.h:91
#define SCIP_ALLOC(x)
Definition: def.h:366
#define SCIP_Real
Definition: def.h:156
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:220
#define REALABS(x)
Definition: def.h:182
#define SCIP_CALL(x)
Definition: def.h:355
SCIP_Bool SCIPsortedvecFindReal(SCIP_Real *realarray, SCIP_Real val, int len, int *pos)
void SCIPsortedvecInsertRealPtr(SCIP_Real *realarray, void **ptrarray, SCIP_Real keyval, void *field1val, int *len, int *pos)
int SCIPvaluehistoryGetNValues(SCIP_VALUEHISTORY *valuehistory)
Definition: history.c:443
SCIP_RETCODE SCIPvaluehistoryCreate(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:323
SCIP_HISTORY ** SCIPvaluehistoryGetHistories(SCIP_VALUEHISTORY *valuehistory)
Definition: history.c:453
SCIP_RETCODE SCIPvaluehistoryFind(SCIP_VALUEHISTORY *valuehistory, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real value, SCIP_HISTORY **history)
Definition: history.c:364
SCIP_Real * SCIPvaluehistoryGetValues(SCIP_VALUEHISTORY *valuehistory)
Definition: history.c:463
void SCIPvaluehistoryFree(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:342
void SCIPvaluehistoryScaleVSIDS(SCIP_VALUEHISTORY *valuehistory, SCIP_Real scalar)
Definition: history.c:409
void SCIPhistoryReset(SCIP_HISTORY *history)
Definition: history.c:78
SCIP_Real SCIPhistoryGetPseudocost(SCIP_HISTORY *history, SCIP_Real solvaldelta)
Definition: history.c:529
SCIP_Real SCIPhistoryGetAvgInferences(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:790
void SCIPhistorySetRatioHistory(SCIP_HISTORY *history, SCIP_Bool valid, SCIP_Real ratio, SCIP_Real balance)
Definition: history.c:918
SCIP_Longint SCIPhistoryGetNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:690
SCIP_Longint SCIPhistoryGetNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:764
SCIP_Real SCIPhistoryGetAvgConflictlength(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:703
SCIP_Real SCIPhistoryGetAvgCutoffs(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:816
SCIP_RETCODE SCIPhistoryCreate(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition: history.c:51
SCIP_Real SCIPhistoryGetAncPseudocostCount(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:596
void SCIPhistorySetLastGMIeff(SCIP_HISTORY *history, SCIP_Real gmieff)
Definition: history.c:907
void SCIPhistoryUpdateAncPseudocost(SCIP_HISTORY *history, SCIP_SET *set, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: history.c:255
SCIP_Real SCIPhistoryGetLastRatio(SCIP_HISTORY *history)
Definition: history.c:852
void SCIPhistoryIncInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:732
SCIP_Real SCIPhistoryGetAncPseudocost(SCIP_HISTORY *history, SCIP_Real solvaldelta)
Definition: history.c:543
SCIP_Real SCIPhistoryGetCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:803
SCIP_Real SCIPhistoryGetPseudocostCount(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:581
SCIP_Bool SCIPhistoryIsPseudocostEmpty(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:609
SCIP_Bool SCIPhistoryIsAncPseudocostEmpty(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:622
SCIP_Real SCIPhistoryGetPseudocostVariance(SCIP_HISTORY *history, SCIP_BRANCHDIR direction)
Definition: history.c:557
void SCIPhistoryIncNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real length)
Definition: history.c:674
void SCIPhistoryScaleVSIDS(SCIP_HISTORY *history, SCIP_Real scalar)
Definition: history.c:649
void SCIPhistoryIncCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:748
void SCIPhistoryIncNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, int depth)
Definition: history.c:716
void SCIPhistoryUpdatePseudocost(SCIP_HISTORY *history, SCIP_SET *set, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: history.c:191
SCIP_Real SCIPhistoryGetVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:661
SCIP_Bool SCIPhistoryIsRatioValid(SCIP_HISTORY *history)
Definition: history.c:842
SCIP_Real SCIPhistoryGetAvgBranchdepth(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:829
SCIP_Real SCIPhistoryGetLastBalance(SCIP_HISTORY *history)
Definition: history.c:863
SCIP_Real SCIPhistoryGetLastGMIeff(SCIP_HISTORY *history)
Definition: history.c:897
SCIP_Real SCIPhistoryGetAvgGMIeff(SCIP_HISTORY *history)
Definition: history.c:874
SCIP_Real SCIPhistoryGetInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:777
void SCIPhistoryFree(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition: history.c:66
void SCIPhistoryUnite(SCIP_HISTORY *history, SCIP_HISTORY *addhistory, SCIP_Bool switcheddirs)
Definition: history.c:117
void SCIPhistoryIncGMIeffSum(SCIP_HISTORY *history, SCIP_Real gmieff)
Definition: history.c:884
SCIP_BRANCHDIR SCIPbranchdirOpposite(SCIP_BRANCHDIR dir)
Definition: history.c:520
void SCIPhistoryIncVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:635
internal methods for branching and inference history
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:465
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:451
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition: memory.h:454
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:467
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:458
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:437
real eps
public methods for branching and inference history structure
public methods for message output
public data structures and miscellaneous methods
SCIP_Real SCIPsetPseudocosteps(SCIP_SET *set)
Definition: set.c:6460
SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6648
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6515
SCIP_Real SCIPsetPseudocostdelta(SCIP_SET *set)
Definition: set.c:6470
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:6080
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6659
internal methods for global SCIP settings
#define SCIPsetDebugMsg
Definition: set.h:1811
SCIP_Real ancpscostcount[2]
SCIP_Longint nbranchings[2]
SCIP_Real pscostweightedmean[2]
SCIP_Longint nactiveconflicts[2]
SCIP_Bool ratiovalid
SCIP_Real pscostvariance[2]
SCIP_Real vsids[2]
SCIP_Real pscostcount[2]
SCIP_Real ratio
SCIP_Real cutoffsum[2]
SCIP_Real ngmi
SCIP_Real inferencesum[2]
SCIP_Real balance
SCIP_Real gmieff
SCIP_Real conflengthsum[2]
SCIP_Real ancpscostweightedmean[2]
SCIP_Real gmieffsum
SCIP_Longint branchdepthsum[2]
SCIP_Real * values
SCIP_HISTORY ** histories
datastructures for branching and inference history
Definition: heur_padm.c:135
@ SCIP_BRANCHDIR_DOWNWARDS
Definition: type_history.h:43
@ SCIP_BRANCHDIR_AUTO
Definition: type_history.h:46
@ SCIP_BRANCHDIR_UPWARDS
Definition: type_history.h:44
enum SCIP_BranchDir SCIP_BRANCHDIR
Definition: type_history.h:48
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63