Scippy

SCIP

Solving Constraint Integer Programs

misc.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 misc.c
26 * @ingroup OTHER_CFILES
27 * @brief miscellaneous methods
28 * @author Tobias Achterberg
29 * @author Gerald Gamrath
30 * @author Stefan Heinz
31 * @author Michael Winkler
32 * @author Kati Wolter
33 * @author Gregor Hendel
34 */
35
36/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
37
38#define _USE_MATH_DEFINES /* to get M_SQRT2 on Windows */ /*lint !750 */
39
40#include <assert.h>
41#include <string.h>
42#include <stdarg.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <errno.h>
46#include <ctype.h>
47#include <math.h>
48#ifndef _MSC_VER
49#include <strings.h>
50#endif
51
52#include "scip/def.h"
53#include "scip/pub_message.h"
54#include "scip/misc.h"
55#include "scip/intervalarith.h"
56#include "scip/pub_misc.h"
57#include "scip/rational.h"
58
59#ifndef NDEBUG
60#include "scip/struct_misc.h"
61#endif
62
63/*
64 * methods for statistical tests
65 */
66
67/**< contains all critical values for a one-sided two sample t-test up to 15 degrees of freedom
68 * a critical value represents a threshold for rejecting the null-hypothesis in hypothesis testing at
69 * a certain confidence level;
70 *
71 * access through method SCIPstudentTGetCriticalValue()
72 *
73 * source: German Wikipedia
74 *
75 * for confidence levels
76 * c =
77 * 0.75 0.875 0.90 0.95 0.975 (one-sided)
78 * 0.50 0.750 0.80 0.90 0.950 (two-sided)
79 *
80 */
81static const SCIP_Real studentt_quartiles[] = { /* df:*/
82 1.000, 2.414, 3.078, 6.314, 12.706, /* 1 */
83 0.816, 1.604, 1.886, 2.920, 4.303, /* 2 */
84 0.765, 1.423, 1.638, 2.353, 3.182, /* 3 */
85 0.741, 1.344, 1.533, 2.132, 2.776, /* 4 */
86 0.727, 1.301, 1.476, 2.015, 2.571, /* 5 */
87 0.718, 1.273, 1.440, 1.943, 2.447, /* 6 */
88 0.711, 1.254, 1.415, 1.895, 2.365, /* 7 */
89 0.706, 1.240, 1.397, 1.860, 2.306, /* 8 */
90 0.703, 1.230, 1.383, 1.833, 2.262, /* 9 */
91 0.700, 1.221, 1.372, 1.812, 2.228, /* 10 */
92 0.697, 1.214, 1.363, 1.796, 2.201, /* 11 */
93 0.695, 1.209, 1.356, 1.782, 2.179, /* 12 */
94 0.694, 1.204, 1.350, 1.771, 2.160, /* 13 */
95 0.692, 1.200, 1.345, 1.761, 2.145, /* 14 */
96 0.691, 1.197, 1.341, 1.753, 2.131 /* 15 */
97};
98
99/**< critical values for higher degrees of freedom of Student-T distribution for the same error probabilities; infact,
100 * these are critical values of the standard normal distribution with mean 0 and variance 1
101 */
103 0.674, 1.150, 1.282, 1.645, 1.960
104};
105
106/** the maximum degrees of freedom represented before switching to normal approximation */
107static const int studentt_maxdf = sizeof(studentt_quartiles)/(5 * sizeof(SCIP_Real));
108
109/** get critical value of a Student-T distribution for a given number of degrees of freedom at a confidence level */
111 SCIP_CONFIDENCELEVEL clevel, /**< (one-sided) confidence level */
112 int df /**< degrees of freedom */
113 )
114{
115 if( df > studentt_maxdf )
116 return studentt_quartilesabove[(int)clevel];
117 else
118 return studentt_quartiles[(int)clevel + 5 * (df - 1)];
119}
120
121/** compute a t-value for the hypothesis that x and y are from the same population; Assuming that
122 * x and y represent normally distributed random samples with equal variance, the returned value
123 * comes from a Student-T distribution with countx + county - 2 degrees of freedom; this
124 * value can be compared with a critical value (see also SCIPstudentTGetCriticalValue()) at
125 * a predefined confidence level for checking if x and y significantly differ in location
126 */
128 SCIP_Real meanx, /**< the mean of the first distribution */
129 SCIP_Real meany, /**< the mean of the second distribution */
130 SCIP_Real variancex, /**< the variance of the x-distribution */
131 SCIP_Real variancey, /**< the variance of the y-distribution */
132 SCIP_Real countx, /**< number of samples of x */
133 SCIP_Real county /**< number of samples of y */
134 )
135{
136 SCIP_Real pooledvariance;
137 SCIP_Real tresult;
138
139 /* too few samples */
140 if( countx < 1.9 || county < 1.9 )
141 return SCIP_INVALID;
142
143 /* pooled variance is the weighted average of the two variances */
144 pooledvariance = (countx - 1) * variancex + (county - 1) * variancey;
145 pooledvariance /= (countx + county - 2);
146
147 /* a variance close to zero means the distributions are basically constant */
148 pooledvariance = MAX(pooledvariance, 1e-9);
149
150 /* tresult can be understood as realization of a Student-T distributed variable with
151 * countx + county - 2 degrees of freedom
152 */
153 tresult = (meanx - meany) / sqrt(pooledvariance);
154 tresult *= sqrt(countx * county / (countx + county));
155
156 return tresult;
157}
158
159/** returns the value of the Gauss error function evaluated at a given point */
161 SCIP_Real x /**< value to evaluate */
162 )
163{
164#ifdef _WIN32
165 SCIP_Real a1, a2, a3, a4, a5, p, t, y;
166 int sign;
167
168 a1 = 0.254829592;
169 a2 = -0.284496736;
170 a3 = 1.421413741;
171 a4 = -1.453152027;
172 a5 = 1.061405429;
173 p = 0.3275911;
174
175 sign = (x >= 0) ? 1 : -1;
176 x = REALABS(x);
177
178 t = 1.0/(1.0 + p*x);
179 y = 1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*exp(-x*x);
180 return sign * y;
181#else
182 return erf(x);
183#endif
184}
185
186/** get critical value of a standard normal distribution at a given confidence level */
188 SCIP_CONFIDENCELEVEL clevel /**< (one-sided) confidence level */
189 )
190{
191 return studentt_quartilesabove[(int)clevel];
192}
193
194/** calculates the cumulative distribution P(-infinity <= x <= value) that a normally distributed
195 * random variable x takes a value between -infinity and parameter \p value.
196 *
197 * The distribution is given by the respective mean and deviation. This implementation
198 * uses the error function SCIPerf().
199 */
201 SCIP_Real mean, /**< the mean value of the distribution */
202 SCIP_Real variance, /**< the square of the deviation of the distribution */
203 SCIP_Real value /**< the upper limit of the calculated distribution integral */
204 )
205{
206 SCIP_Real normvalue;
208
209 /* we need to calculate the standard deviation from the variance */
210 assert(variance >= -1e-9);
211 if( variance < 1e-9 )
212 std = 0.0;
213 else
214 std = sqrt(variance);
215
216 /* special treatment for zero variance */
217 if( std < 1e-9 )
218 {
219 if( value < mean + 1e-9 )
220 return 1.0;
221 else
222 return 0.0;
223 }
224 assert( std != 0.0 ); /* for lint */
225
226 /* scale and translate to standard normal distribution. Factor sqrt(2) is needed for SCIPerf() function */
227 normvalue = (value - mean)/(std * M_SQRT2);
228
229 SCIPdebugMessage(" Normalized value %g = ( %g - %g ) / (%g * 1.4142136)\n", normvalue, value, mean, std);
230
231 /* calculate the cumulative distribution function for normvalue. For negative normvalues, we negate the normvalue and
232 * use the oddness of the SCIPerf()-function; special treatment for values close to zero.
233 */
234 if( normvalue < 1e-9 && normvalue > -1e-9 )
235 return .5;
236 else if( normvalue > 0 )
237 {
238 SCIP_Real erfresult;
239
240 erfresult = SCIPerf(normvalue);
241 return erfresult / 2.0 + 0.5;
242 }
243 else
244 {
245 SCIP_Real erfresult;
246
247 erfresult = SCIPerf(-normvalue);
248
249 return 0.5 - erfresult / 2.0;
250 }
251}
252
253/*
254 * SCIP regression methods
255 */
256
257/** returns the number of observations of this regression */
259 SCIP_REGRESSION* regression /**< regression data structure */
260 )
261{
262 assert(regression != NULL);
263
264 return regression->nobservations;
265}
266
267/** return the current slope of the regression */
269 SCIP_REGRESSION* regression /**< regression data structure */
270 )
271{
272 assert(regression != NULL);
273
274 return regression->slope;
275}
276
277/** get the current y-intercept of the regression */
279 SCIP_REGRESSION* regression /**< regression data structure */
280 )
281{
282 assert(regression != NULL);
283
284 return regression->intercept;
285}
286
287/** recomputes regression coefficients from available observation data */
288static
290 SCIP_REGRESSION* regression /**< regression data structure */
291 )
292{
293 /* regression coefficients require two or more observations and variance in x */
294 if( regression->nobservations <= 1 || EPSZ(regression->variancesumx, 1e-9) )
295 {
296 regression->slope = SCIP_INVALID;
297 regression->intercept = SCIP_INVALID;
298 regression->corrcoef = SCIP_INVALID;
299 }
300 else if( EPSZ(regression->variancesumy, 1e-9) )
301 {
302 /* if there is no variance in the y's (but in the x's), the regression line is horizontal with y-intercept through the mean y */
303 regression->slope = 0.0;
304 regression->corrcoef = 0.0;
305 regression->intercept = regression->meany;
306 }
307 else
308 {
309 /* we ruled this case out already, but to please some compilers... */
310 assert(regression->variancesumx > 0.0);
311 assert(regression->variancesumy > 0.0);
312
313 /* compute slope */
314 regression->slope = (regression->sumxy - regression->nobservations * regression->meanx * regression->meany) / regression->variancesumx;
315
316 /* compute y-intercept */
317 regression->intercept = regression->meany - regression->slope * regression->meanx;
318
319 /* compute empirical correlation coefficient */
320 regression->corrcoef = (regression->sumxy - regression->nobservations * regression->meanx * regression->meany) /
321 sqrt(regression->variancesumx * regression->variancesumy);
322 }
323}
324
325/* incremental update of statistics describing mean and variance */
326static
328 SCIP_Real value, /**< current value to be added to incremental statistics */
329 SCIP_Real* meanptr, /**< pointer to value of current mean */
330 SCIP_Real* sumvarptr, /**< pointer to the value of the current variance sum term */
331 int nobservations, /**< total number of observations */
332 SCIP_Bool add /**< TRUE if the value should be added, FALSE for removing it */
333 )
334{
335 SCIP_Real oldmean;
336 SCIP_Real addfactor;
337 assert(meanptr != NULL);
338 assert(sumvarptr != NULL);
339 assert(nobservations > 0 || add);
340
341 addfactor = add ? 1.0 : -1.0;
342
343 oldmean = *meanptr;
344 *meanptr = oldmean + addfactor * (value - oldmean)/(SCIP_Real)nobservations;
345 *sumvarptr += addfactor * (value - oldmean) * (value - (*meanptr));
346
347 /* it may happen that *sumvarptr is slightly negative, especially after a series of add/removal operations */
348 assert(*sumvarptr >= -1e-4);
349 *sumvarptr = MAX(0.0, *sumvarptr);
350}
351
352/** removes an observation (x,y) from the regression */
354 SCIP_REGRESSION* regression, /**< regression data structure */
355 SCIP_Real x, /**< X of observation */
356 SCIP_Real y /**< Y of the observation */
357 )
358{
359 assert(regression != NULL);
360 assert(regression->nobservations > 0);
361
362 /* simply call the reset function in the case of a single remaining observation to avoid numerical troubles */
363 if( regression->nobservations == 1 )
364 {
365 SCIPregressionReset(regression);
366 }
367 else
368 {
369 SCIP_Bool add = FALSE;
370 --regression->nobservations;
371
372 /* decrement individual means and variances */
373 incrementalStatsUpdate(x, &regression->meanx, &regression->variancesumx, regression->nobservations, add);
374 incrementalStatsUpdate(y, &regression->meany, &regression->variancesumy, regression->nobservations, add);
375
376 /* decrement product sum */
377 regression->sumxy -= (x * y);
378 }
379
380 /* recompute regression parameters */
381 regressionRecompute(regression);
382}
383
384/** update regression by a new observation (x,y) */
386 SCIP_REGRESSION* regression, /**< regression data structure */
387 SCIP_Real x, /**< X of observation */
388 SCIP_Real y /**< Y of the observation */
389 )
390{
391 SCIP_Bool add = TRUE;
392 assert(regression != NULL);
393
394 ++(regression->nobservations);
395 incrementalStatsUpdate(x, &regression->meanx, &regression->variancesumx, regression->nobservations, add);
396 incrementalStatsUpdate(y, &regression->meany, &regression->variancesumy, regression->nobservations, add);
397
398 regression->sumxy += x * y;
399
400 regressionRecompute(regression);
401}
402
403/** reset regression data structure */
405 SCIP_REGRESSION* regression /**< regression data structure */
406 )
407{
408 regression->intercept = SCIP_INVALID;
409 regression->slope = SCIP_INVALID;
410 regression->corrcoef = SCIP_INVALID;
411 regression->meanx = 0;
412 regression->variancesumx = 0;
413 regression->sumxy = 0;
414 regression->meany = 0;
415 regression->variancesumy = 0;
416 regression->nobservations = 0;
417}
418
419/** creates and resets a regression */
421 SCIP_REGRESSION** regression /**< regression data structure */
422 )
423{
424 assert(regression != NULL);
425
426 /* allocate necessary memory */
427 SCIP_ALLOC (BMSallocMemory(regression) );
428
429 /* reset the regression */
430 SCIPregressionReset(*regression);
431
432 return SCIP_OKAY;
433}
434
435/** creates and resets a regression */
437 SCIP_REGRESSION** regression /**< regression data structure */
438 )
439{
440 BMSfreeMemory(regression);
441}
442
443/** calculate memory size for dynamically allocated arrays (copied from scip/set.c) */
444static
446 int initsize, /**< initial size of array */
447 SCIP_Real growfac, /**< growing factor of array */
448 int num /**< minimum number of entries to store */
449 )
450{
451 int size;
452
453 assert(initsize >= 0);
454 assert(growfac >= 1.0);
455 assert(num >= 0);
456
457 if( growfac == 1.0 )
458 size = MAX(initsize, num);
459 else
460 {
461 int oldsize;
462
463 /* calculate the size with this loop, such that the resulting numbers are always the same (-> block memory) */
464 initsize = MAX(initsize, 4);
465 size = initsize;
466 oldsize = size - 1;
467
468 /* second condition checks against overflow */
469 while( size < num && size > oldsize )
470 {
471 oldsize = size;
472 size = (int)(growfac * size + initsize);
473 }
474
475 /* if an overflow happened, set the correct value */
476 if( size <= oldsize )
477 size = num;
478 }
479
480 assert(size >= initsize);
481 assert(size >= num);
482
483 return size;
484}
485
486/*
487 * GML graphical printing methods
488 * For a detailed format decription see http://docs.yworks.com/yfiles/doc/developers-guide/gml.html
489 */
490
491#define GMLNODEWIDTH 120.0
492#define GMLNODEHEIGTH 30.0
493#define GMLFONTSIZE 13
494#define GMLNODETYPE "rectangle"
495#define GMLNODEFILLCOLOR "#ff0000"
496#define GMLEDGECOLOR "black"
497#define GMLNODEBORDERCOLOR "#000000"
498
499
500/** writes a node section to the given graph file */
502 FILE* file, /**< file to write to */
503 unsigned int id, /**< id of the node */
504 const char* label, /**< label of the node */
505 const char* nodetype, /**< type of the node, or NULL */
506 const char* fillcolor, /**< color of the node's interior, or NULL */
507 const char* bordercolor /**< color of the node's border, or NULL */
508 )
509{
510 assert(file != NULL);
511 assert(label != NULL);
512
513 fprintf(file, " node\n");
514 fprintf(file, " [\n");
515 fprintf(file, " id %u\n", id);
516 fprintf(file, " label \"%s\"\n", label);
517 fprintf(file, " graphics\n");
518 fprintf(file, " [\n");
519 fprintf(file, " w %g\n", GMLNODEWIDTH);
520 fprintf(file, " h %g\n", GMLNODEHEIGTH);
521
522 if( nodetype != NULL )
523 fprintf(file, " type \"%s\"\n", nodetype);
524 else
525 fprintf(file, " type \"%s\"\n", GMLNODETYPE);
526
527 if( fillcolor != NULL )
528 fprintf(file, " fill \"%s\"\n", fillcolor);
529 else
530 fprintf(file, " fill \"%s\"\n", GMLNODEFILLCOLOR);
531
532 if( bordercolor != NULL )
533 fprintf(file, " outline \"%s\"\n", bordercolor);
534 else
535 fprintf(file, " outline \"%s\"\n", GMLNODEBORDERCOLOR);
536
537 fprintf(file, " ]\n");
538 fprintf(file, " LabelGraphics\n");
539 fprintf(file, " [\n");
540 fprintf(file, " text \"%s\"\n", label);
541 fprintf(file, " fontSize %d\n", GMLFONTSIZE);
542 fprintf(file, " fontName \"Dialog\"\n");
543 fprintf(file, " anchor \"c\"\n");
544 fprintf(file, " ]\n");
545 fprintf(file, " ]\n");
546}
547
548/** writes a node section including weight to the given graph file */
550 FILE* file, /**< file to write to */
551 unsigned int id, /**< id of the node */
552 const char* label, /**< label of the node */
553 const char* nodetype, /**< type of the node, or NULL */
554 const char* fillcolor, /**< color of the node's interior, or NULL */
555 const char* bordercolor, /**< color of the node's border, or NULL */
556 SCIP_Real weight /**< weight of node */
557 )
558{
559 assert(file != NULL);
560 assert(label != NULL);
561
562 fprintf(file, " node\n");
563 fprintf(file, " [\n");
564 fprintf(file, " id %u\n", id);
565 fprintf(file, " label \"%s\"\n", label);
566 fprintf(file, " weight %g\n", weight);
567 fprintf(file, " graphics\n");
568 fprintf(file, " [\n");
569 fprintf(file, " w %g\n", GMLNODEWIDTH);
570 fprintf(file, " h %g\n", GMLNODEHEIGTH);
571
572 if( nodetype != NULL )
573 fprintf(file, " type \"%s\"\n", nodetype);
574 else
575 fprintf(file, " type \"%s\"\n", GMLNODETYPE);
576
577 if( fillcolor != NULL )
578 fprintf(file, " fill \"%s\"\n", fillcolor);
579 else
580 fprintf(file, " fill \"%s\"\n", GMLNODEFILLCOLOR);
581
582 if( bordercolor != NULL )
583 fprintf(file, " outline \"%s\"\n", bordercolor);
584 else
585 fprintf(file, " outline \"%s\"\n", GMLNODEBORDERCOLOR);
586
587 fprintf(file, " ]\n");
588 fprintf(file, " LabelGraphics\n");
589 fprintf(file, " [\n");
590 fprintf(file, " text \"%s\"\n", label);
591 fprintf(file, " fontSize %d\n", GMLFONTSIZE);
592 fprintf(file, " fontName \"Dialog\"\n");
593 fprintf(file, " anchor \"c\"\n");
594 fprintf(file, " ]\n");
595 fprintf(file, " ]\n");
596}
597
598/** writes an edge section to the given graph file */
600 FILE* file, /**< file to write to */
601 unsigned int source, /**< source node id of the node */
602 unsigned int target, /**< target node id of the edge */
603 const char* label, /**< label of the edge, or NULL */
604 const char* color /**< color of the edge, or NULL */
605 )
606{
607 assert(file != NULL);
608
609 fprintf(file, " edge\n");
610 fprintf(file, " [\n");
611 fprintf(file, " source %u\n", source);
612 fprintf(file, " target %u\n", target);
613
614 if( label != NULL)
615 fprintf(file, " label \"%s\"\n", label);
616
617 fprintf(file, " graphics\n");
618 fprintf(file, " [\n");
619
620 if( color != NULL )
621 fprintf(file, " fill \"%s\"\n", color);
622 else
623 fprintf(file, " fill \"%s\"\n", GMLEDGECOLOR);
624
625 /* fprintf(file, " arrow \"both\"\n"); */
626 fprintf(file, " ]\n");
627
628 if( label != NULL)
629 {
630 fprintf(file, " LabelGraphics\n");
631 fprintf(file, " [\n");
632 fprintf(file, " text \"%s\"\n", label);
633 fprintf(file, " fontSize %d\n", GMLFONTSIZE);
634 fprintf(file, " fontName \"Dialog\"\n");
635 fprintf(file, " anchor \"c\"\n");
636 fprintf(file, " ]\n");
637 }
638
639 fprintf(file, " ]\n");
640}
641
642/** writes an arc section to the given graph file */
644 FILE* file, /**< file to write to */
645 unsigned int source, /**< source node id of the node */
646 unsigned int target, /**< target node id of the edge */
647 const char* label, /**< label of the edge, or NULL */
648 const char* color /**< color of the edge, or NULL */
649 )
650{
651 assert(file != NULL);
652
653 fprintf(file, " edge\n");
654 fprintf(file, " [\n");
655 fprintf(file, " source %u\n", source);
656 fprintf(file, " target %u\n", target);
657
658 if( label != NULL)
659 fprintf(file, " label \"%s\"\n", label);
660
661 fprintf(file, " graphics\n");
662 fprintf(file, " [\n");
663
664 if( color != NULL )
665 fprintf(file, " fill \"%s\"\n", color);
666 else
667 fprintf(file, " fill \"%s\"\n", GMLEDGECOLOR);
668
669 fprintf(file, " targetArrow \"standard\"\n");
670 fprintf(file, " ]\n");
671
672 if( label != NULL)
673 {
674 fprintf(file, " LabelGraphics\n");
675 fprintf(file, " [\n");
676 fprintf(file, " text \"%s\"\n", label);
677 fprintf(file, " fontSize %d\n", GMLFONTSIZE);
678 fprintf(file, " fontName \"Dialog\"\n");
679 fprintf(file, " anchor \"c\"\n");
680 fprintf(file, " ]\n");
681 }
682
683 fprintf(file, " ]\n");
684}
685
686/** writes the starting line to a GML graph file, does not open a file */
688 FILE* file, /**< file to write to */
689 SCIP_Bool directed /**< is the graph directed */
690 )
691{
692 assert(file != NULL);
693
694 fprintf(file, "graph\n");
695 fprintf(file, "[\n");
696 fprintf(file, " hierarchic 1\n");
697
698 if( directed )
699 fprintf(file, " directed 1\n");
700}
701
702/** writes the ending lines to a GML graph file, does not close a file */
704 FILE* file /**< file to close */
705 )
706{
707 assert(file != NULL);
708
709 fprintf(file, "]\n");
710}
711
712/**
713 * writes the opening line to a dot graph file, does not open a file
714 */
716 FILE* file /**< file to write to */
717 )
718{
719 assert(file != NULL);
720
721 fprintf(file, "digraph G {\n");
722}
723
724/** adds a node to the dot graph */
726 FILE* file, /**< file to write to */
727 int node, /**< node id */
728 const char* label, /**< node label */
729 const char* nodetype, /**< type of the node, or NULL */
730 const char* fillcolor, /**< color of the node's interior, or NULL */
731 const char* bordercolor /**< color of the node's border, or NULL */
732 )
733{
734 assert(file != NULL);
735
736 fprintf(file, "\t%d [shape=\"%s\", label=\"%s\", style=\"filled\", fillcolor=\"%s\", color=\"%s\"];\n", node, nodetype, label, fillcolor, bordercolor);
737}
738
739/** adds an arc (edge) between two nodes in the dot graph */
741 FILE* file, /**< file to write to */
742 int source, /**< source node id of the node */
743 int target, /**< target node id of the edge */
744 const char* color /**< color of the edge, or NULL */
745 )
746{
747 assert(file != NULL);
748
749 fprintf(file, "\t%d -> %d [color=\"%s\"];\n", source, target, color);
750}
751
752/** writes the closing line to a dot graph file, does not close a file */
754 FILE* file /**< file to write to */
755 )
756{
757 assert(file != NULL);
758
759 fprintf(file, "}\n");
760}
761
762/*
763 * Sparse solution
764 */
765
766/** creates a sparse solution */
768 SCIP_SPARSESOL** sparsesol, /**< pointer to store the created sparse solution */
769 SCIP_VAR** vars, /**< variables in the sparse solution, must not contain continuous
770 * variables
771 */
772 int nvars, /**< number of variables to store, size of the lower and upper bound
773 * arrays
774 */
775 SCIP_Bool cleared /**< should the lower and upper bound arrays be cleared (entries set to 0) */
776 )
777{
778 assert(sparsesol != NULL);
779 assert(nvars == 0 || vars != NULL);
780 assert(nvars >= 0);
781
782 SCIP_ALLOC( BMSallocMemory(sparsesol) );
783
784#ifndef NDEBUG
785 {
786 int v;
787
788 for( v = nvars - 1; v >= 0; --v )
789 {
790 assert(vars[v] != NULL);
791 /* assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS); */
792 }
793 }
794#endif
795
796 /* copy variables */
797 SCIP_ALLOC( BMSduplicateMemoryArray(&((*sparsesol)->vars), vars, nvars) );
798
799 /* create bound arrays */
800 if( cleared )
801 {
802 SCIP_ALLOC( BMSallocClearMemoryArray(&((*sparsesol)->lbvalues), nvars) );
803 SCIP_ALLOC( BMSallocClearMemoryArray(&((*sparsesol)->ubvalues), nvars) );
804 }
805 else
806 {
807 SCIP_ALLOC( BMSallocMemoryArray(&((*sparsesol)->lbvalues), nvars) );
808 SCIP_ALLOC( BMSallocMemoryArray(&((*sparsesol)->ubvalues), nvars) );
809 }
810
811 (*sparsesol)->nvars = nvars;
812
813 return SCIP_OKAY;
814}
815
816/** frees sparse solution */
818 SCIP_SPARSESOL** sparsesol /**< pointer to a sparse solution */
819 )
820{
821 assert(sparsesol != NULL);
822 assert(*sparsesol != NULL);
823
824 BMSfreeMemoryArray(&((*sparsesol)->vars));
825 BMSfreeMemoryArray(&((*sparsesol)->ubvalues));
826 BMSfreeMemoryArray(&((*sparsesol)->lbvalues));
827 BMSfreeMemory(sparsesol);
828}
829
830/** returns the variables stored in the given sparse solution */
832 SCIP_SPARSESOL* sparsesol /**< a sparse solution */
833 )
834{
835 assert(sparsesol != NULL);
836
837 return sparsesol->vars;
838}
839
840/** returns the number of variables stored in the given sparse solution */
842 SCIP_SPARSESOL* sparsesol /**< a sparse solution */
843 )
844{
845 assert(sparsesol != NULL);
846
847 return sparsesol->nvars;
848}
849
850/** returns the lower bound array for all variables for a given sparse solution */
852 SCIP_SPARSESOL* sparsesol /**< a sparse solution */
853 )
854{
855 assert(sparsesol != NULL);
856
857 return sparsesol->lbvalues;
858}
859
860/** returns the upper bound array for all variables for a given sparse solution */
862 SCIP_SPARSESOL* sparsesol /**< a sparse solution */
863 )
864{
865 assert(sparsesol != NULL);
866
867 return sparsesol->ubvalues;
868}
869
870/** constructs the first solution of sparse solution (all variables are set to their lower bound value */
872 SCIP_SPARSESOL* sparsesol, /**< sparse solutions */
873 SCIP_Longint* sol, /**< array to store the first solution */
874 int nvars /**< number of variables */
875 )
876{
877 SCIP_Longint* lbvalues;
878 int v;
879
880 assert(sparsesol != NULL);
881 assert(sol != NULL);
882 assert(nvars == SCIPsparseSolGetNVars(sparsesol));
883
884 lbvalues = SCIPsparseSolGetLbs(sparsesol);
885 assert(lbvalues != NULL);
886
887 /* copy the lower bounds */
888 for( v = 0; v < nvars; ++v )
889 sol[v] = lbvalues[v];
890}
891
892
893/** constructs the next solution of the sparse solution and return whether there was one more or not */
895 SCIP_SPARSESOL* sparsesol, /**< sparse solutions */
896 SCIP_Longint* sol, /**< current solution array which get changed to the next solution */
897 int nvars /**< number of variables */
898 )
899{
900 SCIP_Longint* lbvalues;
901 SCIP_Longint* ubvalues;
902 SCIP_Longint lbvalue;
903 SCIP_Longint ubvalue;
904 SCIP_Bool singular;
905 SCIP_Bool carryflag;
906 int v;
907
908 assert(sparsesol != NULL);
909 assert(sol != NULL);
910
911 if( nvars == 0 )
912 return FALSE;
913
914 assert(nvars > 0);
915 assert(nvars == SCIPsparseSolGetNVars(sparsesol));
916
917 lbvalues = SCIPsparseSolGetLbs(sparsesol);
918 ubvalues = SCIPsparseSolGetUbs(sparsesol);
919 assert(lbvalues != NULL);
920 assert(ubvalues != NULL);
921
922 singular = TRUE;
923 carryflag = FALSE;
924
925 for( v = 0; v < nvars; ++v )
926 {
927 lbvalue = lbvalues[v];
928 ubvalue = ubvalues[v];
929
930 if( lbvalue < ubvalue )
931 {
932 singular = FALSE;
933
934 if( carryflag == FALSE )
935 {
936 if( sol[v] < ubvalue )
937 {
938 sol[v]++;
939 break;
940 }
941 else
942 {
943 /* in the last solution the variables v was set to its upper bound value */
944 assert(sol[v] == ubvalue);
945 sol[v] = lbvalue;
946 carryflag = TRUE;
947 }
948 }
949 else
950 {
951 if( sol[v] < ubvalue )
952 {
953 sol[v]++;
954 carryflag = FALSE;
955 break;
956 }
957 else
958 {
959 assert(sol[v] == ubvalue);
960 sol[v] = lbvalue;
961 }
962 }
963 }
964 }
965
966 return (!carryflag && !singular);
967}
968
969
970/*
971 * Queue
972 */
973
974/** resizes element memory to hold at least the given number of elements */
975static
977 SCIP_QUEUE* queue, /**< pointer to a queue */
978 int minsize /**< minimal number of storable elements */
979 )
980{
981 assert(queue != NULL);
982 assert(minsize > 0);
983
984 if( minsize <= queue->size )
985 return SCIP_OKAY;
986
987 queue->size = MAX(minsize, (int)(queue->size * queue->sizefac));
988 SCIP_ALLOC( BMSreallocMemoryArray(&queue->slots, queue->size) );
989
990 return SCIP_OKAY;
991}
992
993
994/** creates a (circular) queue, best used if the size will be fixed or will not be increased that much */
996 SCIP_QUEUE** queue, /**< pointer to the new queue */
997 int initsize, /**< initial number of available element slots */
998 SCIP_Real sizefac /**< memory growing factor applied, if more element slots are needed */
999 )
1000{
1001 assert(queue != NULL);
1002
1003 initsize = MAX(1, initsize);
1004 sizefac = MAX(1.0, sizefac);
1005
1006 SCIP_ALLOC( BMSallocMemory(queue) );
1007 (*queue)->firstfree = 0;
1008 (*queue)->firstused = -1;
1009 (*queue)->size = 0;
1010 (*queue)->sizefac = sizefac;
1011 (*queue)->slots = NULL;
1012
1013 SCIP_CALL( queueResize(*queue, initsize) );
1014
1015 return SCIP_OKAY;
1016}
1017
1018/** frees queue, but not the data elements themselves */
1020 SCIP_QUEUE** queue /**< pointer to a queue */
1021 )
1022{
1023 assert(queue != NULL);
1024
1025 BMSfreeMemoryArray(&(*queue)->slots);
1026 BMSfreeMemory(queue);
1027}
1028
1029/** clears the queue, but doesn't free the data elements themselves */
1031 SCIP_QUEUE* queue /**< queue */
1032 )
1033{
1034 assert(queue != NULL);
1035
1036 queue->firstfree = 0;
1037 queue->firstused = -1;
1038}
1039
1040/** reallocates slots if queue is necessary */
1041static
1043 SCIP_QUEUE* queue /**< queue */
1044 )
1045{
1046 if( queue->firstfree == queue->firstused )
1047 {
1048 int sizediff;
1049 int oldsize = queue->size;
1050
1051 SCIP_CALL( queueResize(queue, queue->size+1) );
1052 assert(oldsize < queue->size);
1053
1054 sizediff = queue->size - oldsize;
1055
1056 /* move the used memory at the slots to the end */
1057 BMSmoveMemoryArray(&(queue->slots[queue->firstused + sizediff]), &(queue->slots[queue->firstused]), oldsize - queue->firstused); /*lint !e866*/
1058 queue->firstused += sizediff;
1059 }
1060 assert(queue->firstfree != queue->firstused);
1061
1062 return SCIP_OKAY;
1063}
1064
1065/** checks and adjusts marker of first free and first used slot */
1066static
1068 SCIP_QUEUE* queue /**< queue */
1069 )
1070{
1071 /* if we saved the value at the last position we need to reset the firstfree position */
1072 if( queue->firstfree == queue->size )
1073 queue->firstfree = 0;
1074
1075 /* if a first element was added, we need to update the firstused counter */
1076 if( queue->firstused == -1 )
1077 queue->firstused = 0;
1078}
1079
1080/** inserts pointer element at the end of the queue */
1082 SCIP_QUEUE* queue, /**< queue */
1083 void* elem /**< element to be inserted */
1084 )
1085{
1086 assert(queue != NULL);
1087 assert(queue->slots != NULL);
1088 assert(queue->firstused >= -1 && queue->firstused < queue->size);
1089 assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1090 assert(queue->firstused > -1 || queue->firstfree == 0);
1091 assert(elem != NULL);
1092
1093 /* check allocated memory */
1094 SCIP_CALL( queueCheckSize(queue) );
1095
1096 /* insert element at the first free slot */
1097 queue->slots[queue->firstfree].ptr = elem;
1098 ++(queue->firstfree);
1099
1100 /* check and adjust marker */
1101 queueCheckMarker(queue);
1102
1103 return SCIP_OKAY;
1104}
1105
1106/** inserts unsigned integer element at the end of the queue */
1108 SCIP_QUEUE* queue, /**< queue */
1109 unsigned int elem /**< element to be inserted */
1110 )
1111{
1112 assert(queue != NULL);
1113 assert(queue->slots != NULL);
1114 assert(queue->firstused >= -1 && queue->firstused < queue->size);
1115 assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1116 assert(queue->firstused > -1 || queue->firstfree == 0);
1117
1118 /* check allocated memory */
1119 SCIP_CALL( queueCheckSize(queue) );
1120
1121 /* insert element at the first free slot */
1122 queue->slots[queue->firstfree].uinteger = elem;
1123 ++(queue->firstfree);
1124
1125 /* check and adjust marker */
1126 queueCheckMarker(queue);
1127
1128 return SCIP_OKAY;
1129}
1130
1131/** removes and returns the first pointer element of the queue, or NULL if no element exists */
1133 SCIP_QUEUE* queue /**< queue */
1134 )
1135{
1136 int pos;
1137
1138 assert(queue != NULL);
1139 assert(queue->firstused >= -1 && queue->firstused < queue->size);
1140 assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1141 assert(queue->firstused > -1 || queue->firstfree == 0);
1142
1143 if( queue->firstused == -1 )
1144 return NULL;
1145
1146 assert(queue->slots != NULL);
1147
1148 pos = queue->firstused;
1149 ++(queue->firstused);
1150
1151 /* if we removed the value at the last position we need to reset the firstused position */
1152 if( queue->firstused == queue->size )
1153 queue->firstused = 0;
1154
1155 /* if we reached the first free position we can reset both, firstused and firstused, positions */
1156 if( queue->firstused == queue->firstfree )
1157 {
1158 queue->firstused = -1;
1159 queue->firstfree = 0; /* this is not necessary but looks better if we have an empty list to reset this value */
1160 }
1161
1162 return (queue->slots[pos].ptr);
1163}
1164
1165/** removes and returns the first unsigned integer element of the queue, or UINT_MAX if no element exists */
1167 SCIP_QUEUE* queue /**< queue */
1168 )
1169{
1170 int pos;
1171
1172 assert(queue != NULL);
1173 assert(queue->firstused >= -1 && queue->firstused < queue->size);
1174 assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1175 assert(queue->firstused > -1 || queue->firstfree == 0);
1176
1177 if( queue->firstused == -1 )
1178 return UINT_MAX;
1179
1180 assert(queue->slots != NULL);
1181
1182 pos = queue->firstused;
1183 ++(queue->firstused);
1184
1185 /* if we removed the value at the last position we need to reset the firstused position */
1186 if( queue->firstused == queue->size )
1187 queue->firstused = 0;
1188
1189 /* if we reached the first free position we can reset both, firstused and firstused, positions */
1190 if( queue->firstused == queue->firstfree )
1191 {
1192 queue->firstused = -1;
1193 queue->firstfree = 0; /* this is not necessary but looks better if we have an empty list to reset this value */
1194 }
1195
1196 return (queue->slots[pos].uinteger);
1197}
1198
1199/** returns the first element of the queue without removing it, or NULL if no element exists */
1201 SCIP_QUEUE* queue /**< queue */
1202 )
1203{
1204 assert(queue != NULL);
1205 assert(queue->firstused >= -1 && queue->firstused < queue->size);
1206 assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1207 assert(queue->firstused > -1 || queue->firstfree == 0);
1208
1209 if( queue->firstused == -1 )
1210 return NULL;
1211
1212 assert(queue->slots != NULL);
1213
1214 return queue->slots[queue->firstused].ptr;
1215}
1216
1217/** returns the first unsigned integer element of the queue without removing it, or UINT_MAX if no element exists */
1219 SCIP_QUEUE* queue /**< queue */
1220 )
1221{
1222 assert(queue != NULL);
1223 assert(queue->firstused >= -1 && queue->firstused < queue->size);
1224 assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1225 assert(queue->firstused > -1 || queue->firstfree == 0);
1226
1227 if( queue->firstused == -1 )
1228 return UINT_MAX;
1229
1230 assert(queue->slots != NULL);
1231
1232 return queue->slots[queue->firstused].uinteger;
1233}
1234
1235/** returns whether the queue is empty */
1237 SCIP_QUEUE* queue /**< queue */
1238 )
1239{
1240 assert(queue != NULL);
1241 assert(queue->firstused >= -1 && queue->firstused < queue->size);
1242 assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1243 assert(queue->firstused > -1 || queue->firstfree == 0);
1244
1245 return (queue->firstused == -1);
1246}
1247
1248/** returns the number of elements in the queue */
1250 SCIP_QUEUE* queue /**< queue */
1251 )
1252{
1253 assert(queue != NULL);
1254 assert(queue->firstused >= -1 && queue->firstused < queue->size);
1255 assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1256 assert(queue->firstused > -1 || queue->firstfree == 0);
1257
1258 if( queue->firstused == -1 )
1259 return 0;
1260 else if( queue->firstused < queue->firstfree )
1261 return queue->firstfree - queue->firstused;
1262 else if( queue->firstused == queue->firstfree )
1263 return queue->size;
1264 else
1265 return queue->firstfree + (queue->size - queue->firstused);
1266}
1267
1268
1269/*
1270 * Priority Queue
1271 */
1272
1273#define PQ_PARENT(q) (((q)+1)/2-1)
1274#define PQ_LEFTCHILD(p) (2*(p)+1)
1275#define PQ_RIGHTCHILD(p) (2*(p)+2)
1276
1277
1278/** resizes element memory to hold at least the given number of elements */
1279static
1281 SCIP_PQUEUE* pqueue, /**< pointer to a priority queue */
1282 int minsize /**< minimal number of storable elements */
1283 )
1284{
1285 assert(pqueue != NULL);
1286
1287 if( minsize <= pqueue->size )
1288 return SCIP_OKAY;
1289
1290 pqueue->size = MAX(minsize, (int)(pqueue->size * pqueue->sizefac));
1291 SCIP_ALLOC( BMSreallocMemoryArray(&pqueue->slots, pqueue->size) );
1292
1293 return SCIP_OKAY;
1294}
1295
1296/** creates priority queue */
1298 SCIP_PQUEUE** pqueue, /**< pointer to a priority queue */
1299 int initsize, /**< initial number of available element slots */
1300 SCIP_Real sizefac, /**< memory growing factor applied, if more element slots are needed */
1301 SCIP_DECL_SORTPTRCOMP((*ptrcomp)), /**< data element comparator */
1302 SCIP_DECL_PQUEUEELEMCHGPOS((*elemchgpos)) /**< callback to act on position change of elem in priority queue, or NULL */
1303 )
1304{
1305 assert(pqueue != NULL);
1306 assert(ptrcomp != NULL);
1307
1308 initsize = MAX(1, initsize);
1309 sizefac = MAX(1.0, sizefac);
1310
1311 SCIP_ALLOC( BMSallocMemory(pqueue) );
1312 (*pqueue)->len = 0;
1313 (*pqueue)->size = 0;
1314 (*pqueue)->sizefac = sizefac;
1315 (*pqueue)->slots = NULL;
1316 (*pqueue)->ptrcomp = ptrcomp;
1317 (*pqueue)->elemchgpos = elemchgpos;
1318 SCIP_CALL( pqueueResize(*pqueue, initsize) );
1319
1320 return SCIP_OKAY;
1321}
1322
1323/** frees priority queue, but not the data elements themselves */
1325 SCIP_PQUEUE** pqueue /**< pointer to a priority queue */
1326 )
1327{
1328 assert(pqueue != NULL);
1329
1330 BMSfreeMemoryArray(&(*pqueue)->slots);
1331 BMSfreeMemory(pqueue);
1332}
1333
1334/** clears the priority queue, but doesn't free the data elements themselves */
1336 SCIP_PQUEUE* pqueue /**< priority queue */
1337 )
1338{
1339 assert(pqueue != NULL);
1340
1341 pqueue->len = 0;
1342}
1343
1344/** assign element to new slot in priority queue */
1345static
1347 SCIP_PQUEUE* pqueue, /**< priority queue */
1348 void* elem, /**< element whose position changes */
1349 int oldpos, /**< old position or -1 if elem is newly inserted */
1350 int newpos /**< new position */
1351 )
1352{
1353 pqueue->slots[newpos] = elem;
1354
1355 /* act on position change */
1356 if( pqueue->elemchgpos != NULL )
1357 {
1358 pqueue->elemchgpos(elem, oldpos, newpos);
1359 }
1360}
1361
1362#ifdef SCIP_MORE_DEBUG
1363/** ensure that the priority queue still has the heap property */
1364static
1365SCIP_Bool pqueueHasHeapProperty(
1366 SCIP_PQUEUE* pqueue /**< priority queue */
1367 )
1368{
1369 int i;
1370
1371 if( SCIPpqueueNElems(pqueue) == 0 )
1372 return TRUE;
1373
1374 /* check local heap property between parents and children */
1375 for( i = 0; i < SCIPpqueueNElems(pqueue); ++i )
1376 {
1377 if( i > 0 && pqueue->ptrcomp(pqueue->slots[i], pqueue->slots[PQ_PARENT(i)]) < 0 )
1378 return FALSE;
1379 if( i < PQ_PARENT(SCIPpqueueNElems(pqueue)) )
1380 {
1381 int leftchild = PQ_LEFTCHILD(i);
1382 int rightchild = PQ_RIGHTCHILD(i);
1383 assert(leftchild < SCIPpqueueNElems(pqueue));
1384 assert(rightchild <= SCIPpqueueNElems(pqueue));
1385 if( pqueue->ptrcomp(pqueue->slots[i], pqueue->slots[leftchild]) > 0 )
1386 return FALSE;
1387 if( rightchild < SCIPpqueueNElems(pqueue) && pqueue->ptrcomp(pqueue->slots[i], pqueue->slots[rightchild]) > 0)
1388 return FALSE;
1389 }
1390 }
1391 return TRUE;
1392}
1393#endif
1394
1395/** inserts element into priority queue */
1397 SCIP_PQUEUE* pqueue, /**< priority queue */
1398 void* elem /**< element to be inserted */
1399 )
1400{
1401 int pos;
1402 int parentpos;
1403
1404 assert(pqueue != NULL);
1405 assert(pqueue->len >= 0);
1406 assert(elem != NULL);
1407
1408 SCIP_CALL( pqueueResize(pqueue, pqueue->len+1) );
1409
1410 /* insert element as leaf in the tree, move it towards the root as long it is better than its parent */
1411 pos = pqueue->len;
1412 pqueue->len++;
1413 parentpos = PQ_PARENT(pos);
1414 while( pos > 0 && (*pqueue->ptrcomp)(elem, pqueue->slots[parentpos]) < 0 )
1415 {
1416 assert((*pqueue->ptrcomp)(pqueue->slots[parentpos], elem) >= 0);
1417 pqueueElemChgPos(pqueue, pqueue->slots[parentpos], parentpos, pos);
1418
1419 pos = parentpos;
1420 parentpos = PQ_PARENT(pos);
1421 }
1422
1423 /* insert element at the found position */
1424 pqueueElemChgPos(pqueue, elem, -1, pos);
1425
1426#ifdef SCIP_MORE_DEBUG
1427 assert(pqueueHasHeapProperty(pqueue));
1428#endif
1429
1430 return SCIP_OKAY;
1431}
1432
1433
1434/** delete element at specified position, maintaining the heap property */
1436 SCIP_PQUEUE* pqueue, /**< priority queue */
1437 int pos /**< position of element that should be deleted */
1438 )
1439{
1440 void* last;
1441
1442 assert(pqueue != NULL);
1443 assert(pos >= 0);
1444 assert(pos < SCIPpqueueNElems(pqueue));
1445
1446 /* remove element at specified position of the tree, move the better child to its parents position until the last element
1447 * of the queue could be placed in the empty slot
1448 */
1449 pqueue->len--;
1450
1451 /* everything in place */
1452 if( pos == pqueue->len )
1453 return;
1454
1455 last = pqueue->slots[pqueue->len];
1456
1457 /* last element is brought to pos. it may now violate the heap property compared to its parent, or to its children.
1458 * In the first case, move it up, otherwise, move it down.
1459 */
1460 while( pos > 0 && (*pqueue->ptrcomp)(last, pqueue->slots[PQ_PARENT(pos)]) < 0 )
1461 {
1462 pqueueElemChgPos(pqueue, pqueue->slots[PQ_PARENT(pos)], PQ_PARENT(pos), pos);
1463 pos = PQ_PARENT(pos);
1464 }
1465
1466 while( pos <= PQ_PARENT(pqueue->len-1) )
1467 {
1468 int childpos = PQ_LEFTCHILD(pos);
1469 int brotherpos = PQ_RIGHTCHILD(pos);
1470
1471 /* determine better of the two children */
1472 if( brotherpos < pqueue->len && (*pqueue->ptrcomp)(pqueue->slots[brotherpos], pqueue->slots[childpos]) < 0 )
1473 childpos = brotherpos;
1474
1475 if( (*pqueue->ptrcomp)(last, pqueue->slots[childpos]) <= 0 )
1476 break;
1477
1478 /* move better element from childpos to pos */
1479 pqueueElemChgPos(pqueue, pqueue->slots[childpos], childpos, pos);
1480
1481 pos = childpos;
1482 }
1483
1484 /* pos must point into a valid position */
1485 assert(pos <= pqueue->len - 1);
1486
1487 pqueueElemChgPos(pqueue, last, pqueue->len, pos);
1488
1489#ifdef SCIP_MORE_DEBUG
1490 assert(pqueueHasHeapProperty(pqueue));
1491#endif
1492}
1493
1494/** removes and returns best element from the priority queue */
1496 SCIP_PQUEUE* pqueue /**< priority queue */
1497 )
1498{
1499 void* root;
1500
1501 assert(pqueue != NULL);
1502 assert(pqueue->len >= 0);
1503
1504 if( pqueue->len == 0 )
1505 return NULL;
1506
1507 root = pqueue->slots[0];
1508
1509 SCIPpqueueDelPos(pqueue, 0);
1510
1511 return root;
1512}
1513
1514/** returns the best element of the queue without removing it */
1516 SCIP_PQUEUE* pqueue /**< priority queue */
1517 )
1518{
1519 assert(pqueue != NULL);
1520 assert(pqueue->len >= 0);
1521
1522 if( pqueue->len == 0 )
1523 return NULL;
1524
1525 return pqueue->slots[0];
1526}
1527
1528/** returns the number of elements in the queue */
1530 SCIP_PQUEUE* pqueue /**< priority queue */
1531 )
1532{
1533 assert(pqueue != NULL);
1534 assert(pqueue->len >= 0);
1535
1536 return pqueue->len;
1537}
1538
1539/** returns the elements of the queue; changing the returned array may destroy the queue's ordering! */
1541 SCIP_PQUEUE* pqueue /**< priority queue */
1542 )
1543{
1544 assert(pqueue != NULL);
1545 assert(pqueue->len >= 0);
1546
1547 return pqueue->slots;
1548}
1549
1550/** return the position of @p elem in the priority queue, or -1 if element is not found */
1552 SCIP_PQUEUE* pqueue, /**< priority queue */
1553 void* elem /**< element to be inserted */
1554 )
1555{
1556 int pos = -1;
1557
1558 while( ++pos < SCIPpqueueNElems(pqueue) )
1559 {
1560 if( pqueue->slots[pos] == elem )
1561 return pos;
1562 }
1563
1564 return -1;
1565}
1566
1567
1568
1569
1570/*
1571 * Hash Table
1572 */
1573
1574/** table of some prime numbers */
1575static int primetable[] = {
1576 2,
1577 7,
1578 19,
1579 31,
1580 59,
1581 227,
1582 617,
1583 1523,
1584 3547,
1585 8011,
1586 17707,
1587 38723,
1588 83833,
1589 180317,
1590 385897,
1591 821411,
1592 1742369,
1593 3680893,
1594 5693959,
1595 7753849,
1596 9849703,
1597 11973277,
1598 14121853,
1599 17643961,
1600 24273817,
1601 32452843,
1602 49979687,
1603 67867967,
1604 86028121,
1605 104395301,
1606 122949823,
1607 141650939,
1608 160481183,
1609 179424673,
1610 198491317,
1611 217645177,
1612 256203161,
1613 314606869,
1614 373587883,
1615 433024223,
1616 492876847,
1617 553105243,
1618 613651349,
1619 694847533,
1620 756065159,
1621 817504243,
1622 879190747,
1623 941083981,
1624 982451653,
1625 INT_MAX
1626};
1627static const int primetablesize = sizeof(primetable)/sizeof(int);
1628
1629/** simple and fast 2-universal hash function using multiply and shift */
1630static
1631uint32_t hashvalue(
1632 uint64_t input /**< key value */
1633 )
1634{
1635 return ( (uint32_t) ((UINT64_C(0x9e3779b97f4a7c15) * input)>>32) ) | 1u;
1636}
1637
1638/** returns a reasonable hash table size (a prime number) that is at least as large as the specified value */
1640 int minsize /**< minimal size of the hash table */
1641 )
1642{
1643 int pos;
1644
1645 (void) SCIPsortedvecFindInt(primetable, minsize, primetablesize, &pos);
1646 assert(0 <= pos && pos < primetablesize);
1647
1648 return primetable[pos];
1649}
1650
1651/** appends element to the multihash list */
1652static
1654 SCIP_MULTIHASHLIST** multihashlist, /**< pointer to hash list */
1655 BMS_BLKMEM* blkmem, /**< block memory */
1656 void* element /**< element to append to the list */
1657 )
1658{
1659 SCIP_MULTIHASHLIST* newlist;
1660
1661 assert(multihashlist != NULL);
1662 assert(blkmem != NULL);
1663 assert(element != NULL);
1664
1665 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &newlist) );
1666 newlist->element = element;
1667 newlist->next = *multihashlist;
1668 *multihashlist = newlist;
1669
1670 return SCIP_OKAY;
1671}
1672
1673/** frees a multihash list entry and all its successors */
1674static
1676 SCIP_MULTIHASHLIST** multihashlist, /**< pointer to multihash list to free */
1677 BMS_BLKMEM* blkmem /**< block memory */
1678 )
1679{
1680 SCIP_MULTIHASHLIST* list;
1681 SCIP_MULTIHASHLIST* nextlist;
1682
1683 assert(multihashlist != NULL);
1684 assert(blkmem != NULL);
1685
1686 list = *multihashlist;
1687 while( list != NULL )
1688 {
1689 nextlist = list->next;
1690 BMSfreeBlockMemory(blkmem, &list);
1691 list = nextlist;
1692 }
1693
1694 *multihashlist = NULL;
1695}
1696
1697/** finds multihash list entry pointing to element with given key in the multihash list, returns NULL if not found */
1698static
1700 SCIP_MULTIHASHLIST* multihashlist, /**< multihash list */
1701 SCIP_DECL_HASHGETKEY((*hashgetkey)), /**< gets the key of the given element */
1702 SCIP_DECL_HASHKEYEQ ((*hashkeyeq)), /**< returns TRUE iff both keys are equal */
1703 SCIP_DECL_HASHKEYVAL((*hashkeyval)), /**< returns the hash value of the key */
1704 void* userptr, /**< user pointer */
1705 uint64_t keyval, /**< hash value of key */
1706 void* key /**< key to retrieve */
1707 )
1708{
1709 uint64_t currentkeyval;
1710 void* currentkey;
1711
1712 assert(hashkeyeq != NULL);
1713 assert(key != NULL);
1714
1715 while( multihashlist != NULL )
1716 {
1717 currentkey = hashgetkey(userptr, multihashlist->element);
1718 currentkeyval = hashkeyval(userptr, currentkey);
1719 if( currentkeyval == keyval && hashkeyeq(userptr, currentkey, key) )
1720 return multihashlist;
1721
1722 multihashlist = multihashlist->next;
1723 }
1724
1725 return NULL;
1726}
1727
1728/** retrieves element with given key from the multihash list, or NULL */
1729static
1731 SCIP_MULTIHASHLIST* multihashlist, /**< hash list */
1732 SCIP_DECL_HASHGETKEY((*hashgetkey)), /**< gets the key of the given element */
1733 SCIP_DECL_HASHKEYEQ ((*hashkeyeq)), /**< returns TRUE iff both keys are equal */
1734 SCIP_DECL_HASHKEYVAL((*hashkeyval)), /**< returns the hash value of the key */
1735 void* userptr, /**< user pointer */
1736 uint64_t keyval, /**< hash value of key */
1737 void* key /**< key to retrieve */
1738 )
1739{
1741
1742 /* find hash list entry */
1743 h = multihashlistFind(multihashlist, hashgetkey, hashkeyeq, hashkeyval, userptr, keyval, key);
1744
1745 /* return element */
1746 if( h != NULL )
1747 {
1748#ifndef NDEBUG
1750
1751 h2 = multihashlistFind(h->next, hashgetkey, hashkeyeq, hashkeyval, userptr, keyval, key);
1752
1753 if( h2 != NULL )
1754 {
1755 void* key1;
1756 void* key2;
1757
1758 key1 = hashgetkey(userptr, h->element);
1759 key2 = hashgetkey(userptr, h2->element);
1760 assert(hashkeyval(userptr, key1) == hashkeyval(userptr, key2));
1761
1762 if( hashkeyeq(userptr, key1, key2) )
1763 {
1764 SCIPerrorMessage("WARNING: hashkey with same value exists multiple times (e.g. duplicate constraint/variable names), so the return value is maybe not correct\n");
1765 }
1766 }
1767#endif
1768
1769 return h->element;
1770 }
1771 else
1772 return NULL;
1773}
1774
1775
1776/** retrieves element with given key from the multihash list, or NULL
1777 * returns pointer to multihash table list entry
1778 */
1779static
1781 SCIP_MULTIHASHLIST** multihashlist, /**< on input: hash list to search; on exit: hash list entry corresponding
1782 * to element after retrieved one, or NULL */
1783 SCIP_DECL_HASHGETKEY((*hashgetkey)), /**< gets the key of the given element */
1784 SCIP_DECL_HASHKEYEQ ((*hashkeyeq)), /**< returns TRUE iff both keys are equal */
1785 SCIP_DECL_HASHKEYVAL((*hashkeyval)), /**< returns the hash value of the key */
1786 void* userptr, /**< user pointer */
1787 uint64_t keyval, /**< hash value of key */
1788 void* key /**< key to retrieve */
1789 )
1790{
1792
1793 assert(multihashlist != NULL);
1794
1795 /* find hash list entry */
1796 h = multihashlistFind(*multihashlist, hashgetkey, hashkeyeq, hashkeyval, userptr, keyval, key);
1797
1798 /* return element */
1799 if( h != NULL )
1800 {
1801 *multihashlist = h->next;
1802
1803 return h->element;
1804 }
1805
1806 *multihashlist = NULL;
1807
1808 return NULL;
1809}
1810
1811/** removes element from the multihash list */
1812static
1814 SCIP_MULTIHASHLIST** multihashlist, /**< pointer to hash list */
1815 BMS_BLKMEM* blkmem, /**< block memory */
1816 void* element /**< element to remove from the list */
1817 )
1818{
1819 SCIP_MULTIHASHLIST* nextlist;
1820
1821 assert(multihashlist != NULL);
1822 assert(blkmem != NULL);
1823 assert(element != NULL);
1824
1825 while( *multihashlist != NULL && (*multihashlist)->element != element )
1826 multihashlist = &(*multihashlist)->next;
1827
1828 if( *multihashlist != NULL )
1829 {
1830 nextlist = (*multihashlist)->next;
1831 BMSfreeBlockMemory(blkmem, multihashlist);
1832 *multihashlist = nextlist;
1833
1834 return TRUE;
1835 }
1836
1837 return FALSE;
1838}
1839
1840#define SCIP_MULTIHASH_MAXSIZE 33554431 /* 2^25 - 1*/
1841#define SCIP_MULTIHASH_RESIZE_PERCENTAGE 65
1842#define SCIP_MULTIHASH_GROW_FACTOR 1.31
1843
1844/** resizing(increasing) the given multihash */
1845static
1847 SCIP_MULTIHASH* multihash /**< hash table */
1848 )
1849{
1850 SCIP_MULTIHASHLIST** newlists;
1851 SCIP_MULTIHASHLIST* multihashlist;
1852 SCIP_Longint nelements;
1853 int nnewlists;
1854 int l;
1855
1856 assert(multihash != NULL);
1857 assert(multihash->lists != NULL);
1858 assert(multihash->nlists > 0);
1859 assert(multihash->hashgetkey != NULL);
1860 assert(multihash->hashkeyeq != NULL);
1861 assert(multihash->hashkeyval != NULL);
1862
1863 /* get new memeory for hash table lists */
1864 nnewlists = (int) MIN((unsigned int)(multihash->nlists * SCIP_MULTIHASH_GROW_FACTOR), SCIP_MULTIHASH_MAXSIZE);
1865 nnewlists = MAX(nnewlists, multihash->nlists);
1866
1867 SCIPdebugMessage("load = %g, nelements = %" SCIP_LONGINT_FORMAT ", nlists = %d, nnewlist = %d\n", SCIPmultihashGetLoad(multihash), multihash->nelements, multihash->nlists, nnewlists);
1868
1869 if( nnewlists > multihash->nlists )
1870 {
1871 SCIP_Bool onlyone;
1872 void* key;
1873 uint64_t keyval;
1874 unsigned int hashval;
1875
1876 SCIP_ALLOC( BMSallocClearBlockMemoryArray(multihash->blkmem, &newlists, nnewlists) );
1877
1878 /* move all lists */
1879 for( l = multihash->nlists - 1; l >= 0; --l )
1880 {
1881 multihashlist = multihash->lists[l];
1882 onlyone = TRUE;
1883
1884 /* move all elements frmm the old lists into the new lists */
1885 while( multihashlist != NULL )
1886 {
1887 /* get the hash key and its hash value */
1888 key = multihash->hashgetkey(multihash->userptr, multihashlist->element);
1889 keyval = multihash->hashkeyval(multihash->userptr, key);
1890 hashval = (unsigned int) (keyval % (unsigned) nnewlists); /*lint !e573*/
1891
1892 /* if the old hash table list consists of only one entry, we still can use this old memory block instead
1893 * of creating a new one
1894 */
1895 if( multihashlist->next == NULL && onlyone )
1896 {
1897 /* the new list is also empty, we can directly copy the entry */
1898 if( newlists[hashval] == NULL )
1899 newlists[hashval] = multihashlist;
1900 /* the new list is not empty, so we need to find the first empty spot */
1901 else
1902 {
1903 SCIP_MULTIHASHLIST* lastnext = newlists[hashval];
1904 SCIP_MULTIHASHLIST* next = lastnext->next;
1905
1906 while( next != NULL )
1907 {
1908 lastnext = next;
1909 next = next->next;
1910 }
1911
1912 lastnext->next = multihashlist;
1913 }
1914
1915 multihash->lists[l] = NULL;
1916 }
1917 else
1918 {
1919 /* append old element to the list at the hash position */
1920 SCIP_CALL( multihashlistAppend(&(newlists[hashval]), multihash->blkmem, multihashlist->element) );
1921 }
1922
1923 onlyone = FALSE;
1924 multihashlist = multihashlist->next;
1925 }
1926 }
1927
1928 /* remember number of elements */
1929 nelements = multihash->nelements;
1930 /* clear old lists */
1931 SCIPmultihashRemoveAll(multihash);
1932 /* free old lists */
1933 BMSfreeBlockMemoryArray(multihash->blkmem, &(multihash->lists), multihash->nlists);
1934
1935 /* set new data */
1936 multihash->lists = newlists;
1937 multihash->nlists = nnewlists;
1938 multihash->nelements = nelements;
1939
1940#ifdef SCIP_MORE_DEBUG
1941 {
1942 SCIP_Longint sumslotsize = 0;
1943
1944 for( l = 0; l < multihash->nlists; ++l )
1945 {
1946 multihashlist = multihash->lists[l];
1947 while( multihashlist != NULL )
1948 {
1949 sumslotsize++;
1950 multihashlist = multihashlist->next;
1951 }
1952 }
1953 assert(sumslotsize == multihash->nelements);
1954 }
1955#endif
1956 }
1957
1958 return SCIP_OKAY;
1959}
1960
1961/** creates a multihash table */
1963 SCIP_MULTIHASH** multihash, /**< pointer to store the created multihash table */
1964 BMS_BLKMEM* blkmem, /**< block memory used to store multihash table entries */
1965 int tablesize, /**< size of the hash table */
1966 SCIP_DECL_HASHGETKEY((*hashgetkey)), /**< gets the key of the given element */
1967 SCIP_DECL_HASHKEYEQ ((*hashkeyeq)), /**< returns TRUE iff both keys are equal */
1968 SCIP_DECL_HASHKEYVAL((*hashkeyval)), /**< returns the hash value of the key */
1969 void* userptr /**< user pointer */
1970 )
1971{
1972 /* only assert non negative to catch overflow errors
1973 * but not zeros due to integer divison
1974 */
1975 assert(tablesize >= 0);
1976 assert(multihash != NULL);
1977 assert(hashgetkey != NULL);
1978 assert(hashkeyeq != NULL);
1979 assert(hashkeyval != NULL);
1980
1981 SCIP_ALLOC( BMSallocBlockMemory(blkmem, multihash) );
1982 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*multihash)->lists, tablesize) );
1983 (*multihash)->blkmem = blkmem;
1984 (*multihash)->nlists = tablesize;
1985 (*multihash)->hashgetkey = hashgetkey;
1986 (*multihash)->hashkeyeq = hashkeyeq;
1987 (*multihash)->hashkeyval = hashkeyval;
1988 (*multihash)->userptr = userptr;
1989 (*multihash)->nelements = 0;
1990
1991 return SCIP_OKAY;
1992}
1993
1994/** frees the multihash table */
1996 SCIP_MULTIHASH** multihash /**< pointer to the multihash table */
1997 )
1998{
1999 int i;
2000 SCIP_MULTIHASH* table;
2001 BMS_BLKMEM* blkmem;
2002 SCIP_MULTIHASHLIST** lists;
2003
2004 assert(multihash != NULL);
2005 assert(*multihash != NULL);
2006
2007 table = (*multihash);
2008 blkmem = table->blkmem;
2009 lists = table->lists;
2010
2011 /* free hash lists */
2012 for( i = table->nlists - 1; i >= 0; --i )
2013 multihashlistFree(&lists[i], blkmem);
2014
2015 /* free main hash table data structure */
2016 BMSfreeBlockMemoryArray(blkmem, &table->lists, table->nlists);
2017 BMSfreeBlockMemory(blkmem, multihash);
2018}
2019
2020
2021/** inserts element in multihash table (multiple inserts of same element possible)
2022 *
2023 * @note A pointer to a multihashlist returned by SCIPmultihashRetrieveNext() might get invalid when adding an element
2024 * to the hash table, due to dynamic resizing.
2025 */
2027 SCIP_MULTIHASH* multihash, /**< multihash table */
2028 void* element /**< element to insert into the table */
2029 )
2030{
2031 void* key;
2032 uint64_t keyval;
2033 unsigned int hashval;
2034
2035 assert(multihash != NULL);
2036 assert(multihash->lists != NULL);
2037 assert(multihash->nlists > 0);
2038 assert(multihash->hashgetkey != NULL);
2039 assert(multihash->hashkeyeq != NULL);
2040 assert(multihash->hashkeyval != NULL);
2041 assert(element != NULL);
2042
2043 /* dynamically resizing the hashtables */
2045 {
2046 SCIP_CALL( multihashResize(multihash) );
2047 }
2048
2049 /* get the hash key and its hash value */
2050 key = multihash->hashgetkey(multihash->userptr, element);
2051 keyval = multihash->hashkeyval(multihash->userptr, key);
2052 hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
2053
2054 /* append element to the list at the hash position */
2055 SCIP_CALL( multihashlistAppend(&multihash->lists[hashval], multihash->blkmem, element) );
2056
2057 ++(multihash->nelements);
2058
2059 return SCIP_OKAY;
2060}
2061
2062/** inserts element in multihash table (multiple insertion of same element is checked and results in an error)
2063 *
2064 * @note A pointer to a multihashlist returned by SCIPmultihashRetrieveNext() might get invalid when adding a new
2065 * element to the multihash table, due to dynamic resizing.
2066 */
2068 SCIP_MULTIHASH* multihash, /**< multihash table */
2069 void* element /**< element to insert into the table */
2070 )
2071{
2072 assert(multihash != NULL);
2073 assert(multihash->hashgetkey != NULL);
2074
2075 /* check, if key is already existing */
2076 if( SCIPmultihashRetrieve(multihash, multihash->hashgetkey(multihash->userptr, element)) != NULL )
2078
2079 /* insert element in hash table */
2080 SCIP_CALL( SCIPmultihashInsert(multihash, element) );
2081
2082 return SCIP_OKAY;
2083}
2084
2085/** retrieve element with key from multihash table, returns NULL if not existing */
2087 SCIP_MULTIHASH* multihash, /**< multihash table */
2088 void* key /**< key to retrieve */
2089 )
2090{
2091 uint64_t keyval;
2092 unsigned int hashval;
2093
2094 assert(multihash != NULL);
2095 assert(multihash->lists != NULL);
2096 assert(multihash->nlists > 0);
2097 assert(multihash->hashgetkey != NULL);
2098 assert(multihash->hashkeyeq != NULL);
2099 assert(multihash->hashkeyval != NULL);
2100 assert(key != NULL);
2101
2102 /* get the hash value of the key */
2103 keyval = multihash->hashkeyval(multihash->userptr, key);
2104 hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
2105
2106 return multihashlistRetrieve(multihash->lists[hashval], multihash->hashgetkey, multihash->hashkeyeq,
2107 multihash->hashkeyval, multihash->userptr, keyval, key);
2108}
2109
2110/** retrieve element with key from multihash table, returns NULL if not existing
2111 * can be used to retrieve all entries with the same key (one-by-one)
2112 *
2113 * @note The returned multimultihashlist pointer might get invalid when adding a new element to the multihash table.
2114 */
2116 SCIP_MULTIHASH* multihash, /**< multihash table */
2117 SCIP_MULTIHASHLIST** multihashlist, /**< input: entry in hash table list from which to start searching, or NULL
2118 * output: entry in hash table list corresponding to element after
2119 * retrieved one, or NULL */
2120 void* key /**< key to retrieve */
2121 )
2122{
2123 uint64_t keyval;
2124
2125 assert(multihash != NULL);
2126 assert(multihash->lists != NULL);
2127 assert(multihash->nlists > 0);
2128 assert(multihash->hashgetkey != NULL);
2129 assert(multihash->hashkeyeq != NULL);
2130 assert(multihash->hashkeyval != NULL);
2131 assert(multihashlist != NULL);
2132 assert(key != NULL);
2133
2134 keyval = multihash->hashkeyval(multihash->userptr, key);
2135
2136 if( *multihashlist == NULL )
2137 {
2138 unsigned int hashval;
2139
2140 /* get the hash value of the key */
2141 hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
2142
2143 *multihashlist = multihash->lists[hashval];
2144 }
2145
2146 return multihashlistRetrieveNext(multihashlist, multihash->hashgetkey, multihash->hashkeyeq,
2147 multihash->hashkeyval, multihash->userptr, keyval, key);
2148}
2149
2150/** returns whether the given element exists in the multihash table */
2152 SCIP_MULTIHASH* multihash, /**< multihash table */
2153 void* element /**< element to search in the table */
2154 )
2155{
2156 void* key;
2157 uint64_t keyval;
2158 unsigned int hashval;
2159
2160 assert(multihash != NULL);
2161 assert(multihash->lists != NULL);
2162 assert(multihash->nlists > 0);
2163 assert(multihash->hashgetkey != NULL);
2164 assert(multihash->hashkeyeq != NULL);
2165 assert(multihash->hashkeyval != NULL);
2166 assert(element != NULL);
2167
2168 /* get the hash key and its hash value */
2169 key = multihash->hashgetkey(multihash->userptr, element);
2170 keyval = multihash->hashkeyval(multihash->userptr, key);
2171 hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
2172
2173 return (multihashlistFind(multihash->lists[hashval], multihash->hashgetkey, multihash->hashkeyeq,
2174 multihash->hashkeyval, multihash->userptr, keyval, key) != NULL);
2175}
2176
2177/** removes element from the multihash table, if it exists */
2179 SCIP_MULTIHASH* multihash, /**< multihash table */
2180 void* element /**< element to remove from the table */
2181 )
2182{
2183 void* key;
2184 uint64_t keyval;
2185 unsigned int hashval;
2186
2187 assert(multihash != NULL);
2188 assert(multihash->lists != NULL);
2189 assert(multihash->nlists > 0);
2190 assert(multihash->hashgetkey != NULL);
2191 assert(multihash->hashkeyeq != NULL);
2192 assert(multihash->hashkeyval != NULL);
2193 assert(element != NULL);
2194
2195 /* get the hash key and its hash value */
2196 key = multihash->hashgetkey(multihash->userptr, element);
2197 keyval = multihash->hashkeyval(multihash->userptr, key);
2198 hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
2199
2200 /* remove element from the list at the hash position */
2201 if( multihashlistRemove(&multihash->lists[hashval], multihash->blkmem, element) )
2202 --(multihash->nelements);
2203
2204 return SCIP_OKAY;
2205}
2206
2207/** removes all elements of the multihash table
2208 *
2209 * @note From a performance point of view you should not fill and clear a hash table too often since the clearing can
2210 * be expensive. Clearing is done by looping over all buckets and removing the hash table lists one-by-one.
2211 */
2213 SCIP_MULTIHASH* multihash /**< multihash table */
2214 )
2215{
2216 BMS_BLKMEM* blkmem;
2217 SCIP_MULTIHASHLIST** lists;
2218 int i;
2219
2220 assert(multihash != NULL);
2221
2222 blkmem = multihash->blkmem;
2223 lists = multihash->lists;
2224
2225 /* free hash lists */
2226 for( i = multihash->nlists - 1; i >= 0; --i )
2227 multihashlistFree(&lists[i], blkmem);
2228
2229 multihash->nelements = 0;
2230}
2231
2232/** returns number of multihash table elements */
2234 SCIP_MULTIHASH* multihash /**< multihash table */
2235 )
2236{
2237 assert(multihash != NULL);
2238
2239 return multihash->nelements;
2240}
2241
2242/** returns the load of the given multihash table in percentage */
2244 SCIP_MULTIHASH* multihash /**< multihash table */
2245 )
2246{
2247 assert(multihash != NULL);
2248
2249 return ((SCIP_Real)(multihash->nelements) / (multihash->nlists) * 100.0);
2250}
2251
2252/** prints statistics about multihash table usage */
2254 SCIP_MULTIHASH* multihash, /**< multihash table */
2255 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
2256 )
2257{
2258 SCIP_MULTIHASHLIST* multihashlist;
2259 int usedslots;
2260 int maxslotsize;
2261 int sumslotsize;
2262 int slotsize;
2263 int i;
2264
2265 assert(multihash != NULL);
2266
2267 usedslots = 0;
2268 maxslotsize = 0;
2269 sumslotsize = 0;
2270 for( i = 0; i < multihash->nlists; ++i )
2271 {
2272 multihashlist = multihash->lists[i];
2273 if( multihashlist != NULL )
2274 {
2275 usedslots++;
2276 slotsize = 0;
2277 while( multihashlist != NULL )
2278 {
2279 slotsize++;
2280 multihashlist = multihashlist->next;
2281 }
2282 maxslotsize = MAX(maxslotsize, slotsize);
2283 sumslotsize += slotsize;
2284 }
2285 }
2286 assert(sumslotsize == multihash->nelements);
2287 SCIP_UNUSED(sumslotsize);
2288
2289 SCIPmessagePrintInfo(messagehdlr, "%" SCIP_LONGINT_FORMAT " multihash entries, used %d/%d slots (%.1f%%)",
2290 multihash->nelements, usedslots, multihash->nlists, 100.0*(SCIP_Real)usedslots/(SCIP_Real)(multihash->nlists));
2291 if( usedslots > 0 )
2292 SCIPmessagePrintInfo(messagehdlr, ", avg. %.1f entries/used slot, max. %d entries in slot",
2293 (SCIP_Real)(multihash->nelements)/(SCIP_Real)usedslots, maxslotsize);
2294 SCIPmessagePrintInfo(messagehdlr, "\n");
2295}
2296
2297/** creates a hash table */
2299 SCIP_HASHTABLE** hashtable, /**< pointer to store the created hash table */
2300 BMS_BLKMEM* blkmem, /**< block memory used to store hash table entries */
2301 int tablesize, /**< size of the hash table */
2302 SCIP_DECL_HASHGETKEY((*hashgetkey)), /**< gets the key of the given element */
2303 SCIP_DECL_HASHKEYEQ ((*hashkeyeq)), /**< returns TRUE iff both keys are equal */
2304 SCIP_DECL_HASHKEYVAL((*hashkeyval)), /**< returns the hash value of the key */
2305 void* userptr /**< user pointer */
2306 )
2307{
2308 unsigned int nslots;
2309
2310 /* only assert non negative to catch overflow errors
2311 * but not zeros due to integer divison
2312 */
2313 assert(tablesize >= 0);
2314 assert(hashtable != NULL);
2315 assert(hashgetkey != NULL);
2316 assert(hashkeyeq != NULL);
2317 assert(hashkeyval != NULL);
2318 assert(blkmem != NULL);
2319
2320 SCIP_ALLOC( BMSallocBlockMemory(blkmem, hashtable) );
2321
2322 /* dont create too small hashtables, i.e. at least size 32, and increase
2323 * the given size by divinding it by 0.9, since then no rebuilding will
2324 * be necessary if the given number of elements are inserted. Finally round
2325 * to the next power of two.
2326 */
2327 (*hashtable)->shift = 32;
2328 (*hashtable)->shift -= (unsigned int)ceil(LOG2(MAX(32.0, tablesize / 0.9)));
2329
2330 /* compute size from shift */
2331 nslots = 1u << (32 - (*hashtable)->shift);
2332
2333 /* compute mask to do a fast modulo by nslots using bitwise and */
2334 (*hashtable)->mask = nslots - 1;
2335 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*hashtable)->slots, nslots) );
2336 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*hashtable)->hashes, nslots) );
2337 (*hashtable)->blkmem = blkmem;
2338 (*hashtable)->hashgetkey = hashgetkey;
2339 (*hashtable)->hashkeyeq = hashkeyeq;
2340 (*hashtable)->hashkeyval = hashkeyval;
2341 (*hashtable)->userptr = userptr;
2342 (*hashtable)->nelements = 0;
2343
2344 return SCIP_OKAY;
2345}
2346
2347/** frees the hash table */
2349 SCIP_HASHTABLE** hashtable /**< pointer to the hash table */
2350 )
2351{
2352 uint32_t nslots;
2353 SCIP_HASHTABLE* table;
2354
2355 assert(hashtable != NULL);
2356 assert(*hashtable != NULL);
2357 table = *hashtable;
2358 nslots = (*hashtable)->mask + 1;
2359#ifdef SCIP_DEBUG
2360 {
2361 uint32_t maxprobelen = 0;
2362 uint64_t probelensum = 0;
2363 uint32_t i;
2364
2365 assert(table != NULL);
2366
2367 for( i = 0; i < nslots; ++i )
2368 {
2369 if( table->hashes[i] != 0 )
2370 {
2371 uint32_t probelen = ((i + table->mask + 1 - (table->hashes[i]>>(table->shift))) & table->mask) + 1;
2372 probelensum += probelen;
2373 maxprobelen = MAX(probelen, maxprobelen);
2374 }
2375 }
2376
2377 SCIPdebugMessage("%u hash table entries, used %u/%u slots (%.1f%%)",
2378 (unsigned int)table->nelements, (unsigned int)table->nelements, (unsigned int)nslots,
2379 100.0*(SCIP_Real)table->nelements/(SCIP_Real)(nslots));
2380 if( table->nelements > 0 )
2381 SCIPdebugMessage(", avg. probe length is %.1f, max. probe length is %u",
2382 (SCIP_Real)(probelensum)/(SCIP_Real)table->nelements, (unsigned int)maxprobelen);
2383 SCIPdebugMessage("\n");
2384 }
2385#endif
2386
2387 /* free main hash table data structure */
2388 BMSfreeBlockMemoryArray((*hashtable)->blkmem, &table->hashes, nslots);
2389 BMSfreeBlockMemoryArray((*hashtable)->blkmem, &table->slots, nslots);
2390 BMSfreeBlockMemory((*hashtable)->blkmem, hashtable);
2391}
2392
2393/* computes the distance from it's desired position for the element stored at pos */
2394#define ELEM_DISTANCE(pos) (((pos) + hashtable->mask + 1 - (hashtable->hashes[(pos)]>>(hashtable->shift))) & hashtable->mask)
2395
2396/** inserts element in hash table (multiple inserts of same element overrides previous one) */
2397static
2399 SCIP_HASHTABLE* hashtable, /**< hash table */
2400 void* element, /**< element to insert into the table */
2401 void* key, /**< key of element */
2402 uint32_t hashval, /**< hash value of element */
2403 SCIP_Bool override /**< should element be overridden or an error be returned if already existing */
2404 )
2405{
2406 uint32_t elemdistance;
2407 uint32_t pos;
2408#ifndef NDEBUG
2409 SCIP_Bool swapped = FALSE;
2410#endif
2411
2412 assert(hashtable != NULL);
2413 assert(hashtable->slots != NULL);
2414 assert(hashtable->hashes != NULL);
2415 assert(hashtable->mask > 0);
2416 assert(hashtable->hashgetkey != NULL);
2417 assert(hashtable->hashkeyeq != NULL);
2418 assert(hashtable->hashkeyval != NULL);
2419 assert(element != NULL);
2420
2421 pos = hashval>>(hashtable->shift);
2422 elemdistance = 0;
2423 while( TRUE ) /*lint !e716*/
2424 {
2425 uint32_t distance;
2426
2427 /* if position is empty or key equal insert element */
2428 if( hashtable->hashes[pos] == 0 )
2429 {
2430 hashtable->slots[pos] = element;
2431 hashtable->hashes[pos] = hashval;
2432 ++hashtable->nelements;
2433 return SCIP_OKAY;
2434 }
2435
2436 if( hashtable->hashes[pos] == hashval && hashtable->hashkeyeq(hashtable->userptr,
2437 hashtable->hashgetkey(hashtable->userptr, hashtable->slots[pos]), key) )
2438 {
2439 if( override )
2440 {
2441#ifndef NDEBUG
2442 assert(! swapped);
2443#endif
2444 hashtable->slots[pos] = element;
2445 hashtable->hashes[pos] = hashval;
2446 return SCIP_OKAY;
2447 }
2448 else
2449 {
2451 }
2452 }
2453
2454 /* otherwise check if the current element at this position is closer to its hashvalue */
2455 distance = ELEM_DISTANCE(pos);
2456 if( distance < elemdistance )
2457 {
2458 uint32_t tmp;
2459
2460 /* if this is the case we insert the new element here and find a new position for the old one */
2461 elemdistance = distance;
2462 SCIPswapPointers(&hashtable->slots[pos], &element);
2463 tmp = hashval;
2464 hashval = hashtable->hashes[pos];
2465 hashtable->hashes[pos] = tmp;
2466 key = hashtable->hashgetkey(hashtable->userptr, element);
2467
2468 /* after doing a swap the case that other elements are replaced must not happen anymore */
2469#ifndef NDEBUG
2470 swapped = TRUE;
2471#endif
2472 }
2473
2474 /* continue until we have found an empty position */
2475 pos = (pos + 1) & hashtable->mask;
2476 ++elemdistance;
2477 }
2478}
2479
2480/** check if the load factor of the hashtable is too high and rebuild if necessary */
2481static
2483 SCIP_HASHTABLE* hashtable /**< hash table */
2484 )
2485{
2486 assert(hashtable != NULL);
2487 assert(hashtable->shift < 32);
2488
2489 /* use integer arithmetic to approximately check if load factor is above 90% */
2490 if( ((((uint64_t)hashtable->nelements)<<10)>>(32-hashtable->shift) > 921) )
2491 {
2492 void** slots;
2493 uint32_t* hashes;
2494 uint32_t nslots;
2495 uint32_t newnslots;
2496 uint32_t i;
2497
2498 /* calculate new size (always power of two) */
2499 nslots = hashtable->mask + 1;
2500 newnslots = 2*nslots;
2501 hashtable->mask = newnslots-1;
2502 --hashtable->shift;
2503
2504 /* reallocate array */
2505 SCIP_ALLOC( BMSallocBlockMemoryArray(hashtable->blkmem, &slots, newnslots) );
2506 SCIP_ALLOC( BMSallocClearBlockMemoryArray(hashtable->blkmem, &hashes, newnslots) );
2507
2508 SCIPswapPointers((void**) &slots, (void**) &hashtable->slots);
2509 SCIPswapPointers((void**) &hashes, (void**) &hashtable->hashes);
2510 hashtable->nelements = 0;
2511
2512 /* reinsert all elements */
2513 for( i = 0; i < nslots; ++i )
2514 {
2515 /* using SCIP_CALL_ABORT since there are no allocations or duplicates
2516 * and thus no bad return codes when inserting the elements
2517 */
2518 if( hashes[i] != 0 )
2519 {
2520 SCIP_CALL_ABORT( hashtableInsert(hashtable, slots[i], hashtable->hashgetkey(hashtable->userptr, slots[i]), hashes[i], FALSE) );
2521 }
2522 }
2523 BMSfreeBlockMemoryArray(hashtable->blkmem, &hashes, nslots);
2524 BMSfreeBlockMemoryArray(hashtable->blkmem, &slots, nslots);
2525 }
2526
2527 return SCIP_OKAY;
2528}
2529
2530
2531/** inserts element in hash table
2532 *
2533 * @note multiple inserts of same element overrides previous one
2534 */
2536 SCIP_HASHTABLE* hashtable, /**< hash table */
2537 void* element /**< element to insert into the table */
2538 )
2539{
2540 void* key;
2541 uint64_t keyval;
2542 uint32_t hashval;
2543
2544 assert(hashtable != NULL);
2545 assert(hashtable->slots != NULL);
2546 assert(hashtable->hashes != NULL);
2547 assert(hashtable->mask > 0);
2548 assert(hashtable->hashgetkey != NULL);
2549 assert(hashtable->hashkeyeq != NULL);
2550 assert(hashtable->hashkeyval != NULL);
2551 assert(element != NULL);
2552
2553 SCIP_CALL( hashtableCheckLoad(hashtable) );
2554
2555 /* get the hash key and its hash value */
2556 key = hashtable->hashgetkey(hashtable->userptr, element);
2557 keyval = hashtable->hashkeyval(hashtable->userptr, key);
2558 hashval = hashvalue(keyval);
2559
2560 return hashtableInsert(hashtable, element, key, hashval, TRUE);
2561}
2562
2563/** inserts element in hash table
2564 *
2565 * @note multiple insertion of same element is checked and results in an error
2566 */
2568 SCIP_HASHTABLE* hashtable, /**< hash table */
2569 void* element /**< element to insert into the table */
2570 )
2571{
2572 void* key;
2573 uint64_t keyval;
2574 uint32_t hashval;
2575
2576 assert(hashtable != NULL);
2577 assert(hashtable->slots != NULL);
2578 assert(hashtable->hashes != NULL);
2579 assert(hashtable->mask > 0);
2580 assert(hashtable->hashgetkey != NULL);
2581 assert(hashtable->hashkeyeq != NULL);
2582 assert(hashtable->hashkeyval != NULL);
2583 assert(element != NULL);
2584
2585 SCIP_CALL( hashtableCheckLoad(hashtable) );
2586
2587 /* get the hash key and its hash value */
2588 key = hashtable->hashgetkey(hashtable->userptr, element);
2589 keyval = hashtable->hashkeyval(hashtable->userptr, key);
2590 hashval = hashvalue(keyval);
2591
2592 return hashtableInsert(hashtable, element, key, hashval, FALSE);
2593}
2594
2595/** retrieve element with key from hash table, returns NULL if not existing */
2597 SCIP_HASHTABLE* hashtable, /**< hash table */
2598 void* key /**< key to retrieve */
2599 )
2600{
2601 uint64_t keyval;
2602 uint32_t hashval;
2603 uint32_t pos;
2604 uint32_t elemdistance;
2605
2606 assert(hashtable != NULL);
2607 assert(hashtable->slots != NULL);
2608 assert(hashtable->hashes != NULL);
2609 assert(hashtable->mask > 0);
2610 assert(hashtable->hashgetkey != NULL);
2611 assert(hashtable->hashkeyeq != NULL);
2612 assert(hashtable->hashkeyval != NULL);
2613 assert(key != NULL);
2614
2615 /* get the hash value of the key */
2616 keyval = hashtable->hashkeyval(hashtable->userptr, key);
2617 hashval = hashvalue(keyval);
2618
2619 pos = hashval>>(hashtable->shift);
2620 elemdistance = 0;
2621
2622 while( TRUE ) /*lint !e716*/
2623 {
2624 uint32_t distance;
2625
2626 /* slots is empty so element cannot be contained */
2627 if( hashtable->hashes[pos] == 0 )
2628 return NULL;
2629
2630 distance = ELEM_DISTANCE(pos);
2631
2632 /* element cannot be contained since otherwise we would have swapped it with this one during insert */
2633 if( elemdistance > distance )
2634 return NULL;
2635
2636 /* found element */
2637 if( hashtable->hashes[pos] == hashval && hashtable->hashkeyeq(hashtable->userptr,
2638 hashtable->hashgetkey(hashtable->userptr, hashtable->slots[pos]), key) )
2639 return hashtable->slots[pos];
2640
2641 pos = (pos + 1) & hashtable->mask;
2642 ++elemdistance;
2643 }
2644}
2645
2646/** returns whether the given element exists in the table */
2648 SCIP_HASHTABLE* hashtable, /**< hash table */
2649 void* element /**< element to search in the table */
2650 )
2651{
2652 assert(hashtable != NULL);
2653 assert(hashtable->slots != NULL);
2654 assert(hashtable->hashes != NULL);
2655 assert(hashtable->mask > 0);
2656 assert(hashtable->hashgetkey != NULL);
2657 assert(hashtable->hashkeyeq != NULL);
2658 assert(hashtable->hashkeyval != NULL);
2659 assert(element != NULL);
2660
2661 return (SCIPhashtableRetrieve(hashtable, hashtable->hashgetkey(hashtable->userptr, element)) != NULL);
2662}
2663
2664/** removes element from the hash table, if it exists */
2666 SCIP_HASHTABLE* hashtable, /**< hash table */
2667 void* element /**< element to remove from the table */
2668 )
2669{
2670 void* key;
2671 uint64_t keyval;
2672 uint32_t hashval;
2673 uint32_t elemdistance;
2674 uint32_t distance;
2675 uint32_t pos;
2676
2677 assert(hashtable != NULL);
2678 assert(hashtable->slots != NULL);
2679 assert(hashtable->hashes != NULL);
2680 assert(hashtable->mask > 0);
2681 assert(hashtable->hashgetkey != NULL);
2682 assert(hashtable->hashkeyeq != NULL);
2683 assert(hashtable->hashkeyval != NULL);
2684 assert(element != NULL);
2685
2686 /* get the hash key and its hash value */
2687 key = hashtable->hashgetkey(hashtable->userptr, element);
2688 keyval = hashtable->hashkeyval(hashtable->userptr, key);
2689 hashval = hashvalue(keyval);
2690
2691 elemdistance = 0;
2692 pos = hashval>>(hashtable->shift);
2693 while( TRUE ) /*lint !e716*/
2694 {
2695 /* slots empty so element not contained */
2696 if( hashtable->hashes[pos] == 0 )
2697 return SCIP_OKAY;
2698
2699 distance = ELEM_DISTANCE(pos);
2700
2701 /* element can not be contained since otherwise we would have swapped it with this one */
2702 if( elemdistance > distance )
2703 return SCIP_OKAY;
2704
2705 if( hashtable->hashes[pos] == hashval && hashtable->hashkeyeq(hashtable->userptr,
2706 hashtable->hashgetkey(hashtable->userptr, hashtable->slots[pos]), key) )
2707 {
2708 /* element exists at pos so break out of loop */
2709 break;
2710 }
2711
2712 pos = (pos + 1) & hashtable->mask;
2713 ++elemdistance;
2714 }
2715
2716 /* remove element */
2717 hashtable->hashes[pos] = 0;
2718 --hashtable->nelements;
2719 while( TRUE ) /*lint !e716*/
2720 {
2721 uint32_t nextpos = (pos + 1) & hashtable->mask;
2722
2723 /* nothing to do since there is no chain that needs to be moved */
2724 if( hashtable->hashes[nextpos] == 0 )
2725 break;
2726
2727 /* check if the element is the start of a new chain and return if that is the case */
2728 if( (hashtable->hashes[nextpos]>>(hashtable->shift)) == nextpos )
2729 break;
2730
2731 /* element should be moved to the left and next element needs to be checked */
2732 hashtable->slots[pos] = hashtable->slots[nextpos];
2733 hashtable->hashes[pos] = hashtable->hashes[nextpos];
2734 hashtable->hashes[nextpos] = 0;
2735
2736 pos = nextpos;
2737 }
2738
2739 return SCIP_OKAY;
2740}
2741
2742/** removes all elements of the hash table */
2744 SCIP_HASHTABLE* hashtable /**< hash table */
2745 )
2746{
2747 assert(hashtable != NULL);
2748
2749 BMSclearMemoryArray(hashtable->hashes, hashtable->mask + 1);
2750
2751 hashtable->nelements = 0;
2752}
2753
2754/** returns number of hash table elements */
2756 SCIP_HASHTABLE* hashtable /**< hash table */
2757 )
2758{
2759 assert(hashtable != NULL);
2760
2761 return hashtable->nelements;
2762}
2763
2764/** gives the number of entries in the internal arrays of a hash table */
2766 SCIP_HASHTABLE* hashtable /**< hash table */
2767 )
2768{
2769 return (int) hashtable->mask + 1;
2770}
2771
2772/** gives the element at the given index or NULL if entry at that index has no element */
2774 SCIP_HASHTABLE* hashtable, /**< hash table */
2775 int entryidx /**< index of hash table entry */
2776 )
2777{
2778 return hashtable->hashes[entryidx] == 0 ? NULL : hashtable->slots[entryidx];
2779}
2780
2781/** returns the load of the given hash table in percentage */
2783 SCIP_HASHTABLE* hashtable /**< hash table */
2784 )
2785{
2786 assert(hashtable != NULL);
2787
2788 return ((SCIP_Real)(hashtable->nelements) / (hashtable->mask + 1) * 100.0);
2789}
2790
2791/** prints statistics about hash table usage */
2793 SCIP_HASHTABLE* hashtable, /**< hash table */
2794 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
2795 )
2796{
2797 uint32_t maxprobelen = 0;
2798 uint64_t probelensum = 0;
2799 uint32_t nslots;
2800 uint32_t i;
2801
2802 assert(hashtable != NULL);
2803
2804 nslots = hashtable->mask + 1;
2805
2806 /* compute the maximum and average probe length */
2807 for( i = 0; i < nslots; ++i )
2808 {
2809 if( hashtable->hashes[i] != 0 )
2810 {
2811 uint32_t probelen = ELEM_DISTANCE(i) + 1;
2812 probelensum += probelen;
2813 maxprobelen = MAX(probelen, maxprobelen);
2814 }
2815 }
2816
2817 /* print general hash table statistics */
2818 SCIPmessagePrintInfo(messagehdlr, "%u hash entries, used %u/%u slots (%.1f%%)",
2819 (unsigned int)hashtable->nelements, (unsigned int)hashtable->nelements,
2820 (unsigned int)nslots, 100.0*(SCIP_Real)hashtable->nelements/(SCIP_Real)(nslots));
2821
2822 /* if not empty print average and maximum probe length */
2823 if( hashtable->nelements > 0 )
2824 SCIPmessagePrintInfo(messagehdlr, ", avg. probe length is %.1f, max. probe length is %u",
2825 (SCIP_Real)(probelensum)/(SCIP_Real)hashtable->nelements, (unsigned int)maxprobelen);
2826 SCIPmessagePrintInfo(messagehdlr, "\n");
2827}
2828
2829/** returns TRUE iff both keys (i.e. strings) are equal */
2830SCIP_DECL_HASHKEYEQ(SCIPhashKeyEqString)
2831{ /*lint --e{715}*/
2832 const char* string1 = (const char*)key1;
2833 const char* string2 = (const char*)key2;
2834
2835 return (strcmp(string1, string2) == 0);
2836}
2837
2838/** returns the hash value of the key (i.e. string) */
2839SCIP_DECL_HASHKEYVAL(SCIPhashKeyValString)
2840{ /*lint --e{715}*/
2841 const char* str;
2842 uint64_t hash;
2843
2844 str = (const char*)key;
2845 hash = 37;
2846 while( *str != '\0' )
2847 {
2848 hash *= 11;
2849 hash += (unsigned int)(*str); /*lint !e571*/
2850 str++;
2851 }
2852
2853 return hash;
2854}
2855
2856
2857/** gets the element as the key */
2858SCIP_DECL_HASHGETKEY(SCIPhashGetKeyStandard)
2859{ /*lint --e{715}*/
2860 /* the key is the element itself */
2861 return elem;
2862}
2863
2864/** returns TRUE iff both keys(pointer) are equal */
2865SCIP_DECL_HASHKEYEQ(SCIPhashKeyEqPtr)
2866{ /*lint --e{715}*/
2867 return (key1 == key2);
2868}
2869
2870/** returns the hash value of the key */
2871SCIP_DECL_HASHKEYVAL(SCIPhashKeyValPtr)
2872{ /*lint --e{715}*/
2873 /* the key is used as the keyvalue too */
2874 return (uint64_t) (uintptr_t) key;
2875}
2876
2877
2878
2879/*
2880 * Hash Map
2881 */
2882
2883/* redefine ELEM_DISTANCE macro for hashmap */
2884#undef ELEM_DISTANCE
2885/* computes the distance from it's desired position for the element stored at pos */
2886#define ELEM_DISTANCE(pos) (((pos) + hashmap->mask + 1 - (hashmap->hashes[(pos)]>>(hashmap->shift))) & hashmap->mask)
2887
2888/** inserts element in hash table */
2889static
2891 SCIP_HASHMAP* hashmap, /**< hash map */
2892 void* origin, /**< element to insert into the table */
2893 SCIP_HASHMAPIMAGE image, /**< key of element */
2894 uint32_t hashval, /**< hash value of element */
2895 SCIP_Bool override /**< should element be overridden or error be returned if already existing */
2896 )
2897{
2898 uint32_t elemdistance;
2899 uint32_t pos;
2900
2901 assert(hashmap != NULL);
2902 assert(hashmap->slots != NULL);
2903 assert(hashmap->hashes != NULL);
2904 assert(hashmap->mask > 0);
2905 assert(hashval != 0);
2906
2907 pos = hashval>>(hashmap->shift);
2908 elemdistance = 0;
2909 while( TRUE ) /*lint !e716*/
2910 {
2911 uint32_t distance;
2912
2913 /* if position is empty or key equal insert element */
2914 if( hashmap->hashes[pos] == 0 )
2915 {
2916 hashmap->slots[pos].origin = origin;
2917 hashmap->slots[pos].image = image;
2918 hashmap->hashes[pos] = hashval;
2919 ++hashmap->nelements;
2920 return SCIP_OKAY;
2921 }
2922
2923 if( hashval == hashmap->hashes[pos] && origin == hashmap->slots[pos].origin )
2924 {
2925 if( override )
2926 {
2927 hashmap->slots[pos].image = image;
2928 hashmap->hashes[pos] = hashval;
2929 return SCIP_OKAY;
2930 }
2931 else
2932 {
2934 }
2935 }
2936
2937 /* otherwise check if the current element at this position is closer to its hashvalue */
2938 distance = ELEM_DISTANCE(pos);
2939 if( distance < elemdistance )
2940 {
2942 uint32_t tmphash;
2943
2944 /* if this is the case we insert the new element here and find a new position for the old one */
2945 elemdistance = distance;
2946 tmphash = hashval;
2947 hashval = hashmap->hashes[pos];
2948 hashmap->hashes[pos] = tmphash;
2949 SCIPswapPointers(&hashmap->slots[pos].origin, &origin);
2950 tmp = image;
2951 image = hashmap->slots[pos].image;
2952 hashmap->slots[pos].image = tmp;
2953 }
2954
2955 /* continue until we have found an empty position */
2956 pos = (pos + 1) & hashmap->mask;
2957 ++elemdistance;
2958 }
2959}
2960
2961/** lookup origin in the hashmap. If element is found returns true and the position of the element,
2962 * otherwise returns FALSE.
2963 */
2964static
2966 SCIP_HASHMAP* hashmap, /**< hash table */
2967 void* origin, /**< origin to lookup */
2968 uint32_t* pos /**< pointer to store position of element, if exists */
2969 )
2970{
2971 uint32_t hashval;
2972 uint32_t elemdistance;
2973
2974 assert(hashmap != NULL);
2975 assert(hashmap->slots != NULL);
2976 assert(hashmap->hashes != NULL);
2977 assert(hashmap->mask > 0);
2978
2979 /* get the hash value */
2980 hashval = hashvalue((size_t)origin);
2981 assert(hashval != 0);
2982
2983 *pos = hashval>>(hashmap->shift);
2984 elemdistance = 0;
2985
2986 while( TRUE ) /*lint !e716*/
2987 {
2988 uint32_t distance;
2989
2990 /* slots is empty so element cannot be contained */
2991 if( hashmap->hashes[*pos] == 0 )
2992 return FALSE;
2993
2994 distance = ELEM_DISTANCE(*pos);
2995 /* element can not be contained since otherwise we would have swapped it with this one during insert */
2996 if( elemdistance > distance )
2997 return FALSE;
2998
2999 /* found element */
3000 if( hashmap->hashes[*pos] == hashval && hashmap->slots[*pos].origin == origin )
3001 return TRUE;
3002
3003 *pos = (*pos + 1) & hashmap->mask;
3004 ++elemdistance;
3005 }
3006}
3007
3008/** check if the load factor of the hashmap is too high and rebuild if necessary */
3009static
3011 SCIP_HASHMAP* hashmap /**< hash table */
3012 )
3013{
3014 assert(hashmap != NULL);
3015 assert(hashmap->shift < 32);
3016
3017 /* use integer arithmetic to approximately check if load factor is above 90% */
3018 if( ((((uint64_t)hashmap->nelements)<<10)>>(32-hashmap->shift) > 921) )
3019 {
3020 SCIP_HASHMAPENTRY* slots;
3021 uint32_t* hashes;
3022 uint32_t nslots;
3023 uint32_t newnslots;
3024 uint32_t i;
3025
3026 /* calculate new size (always power of two) */
3027 nslots = hashmap->mask + 1;
3028 --hashmap->shift;
3029 newnslots = 2*nslots;
3030 hashmap->mask = newnslots-1;
3031
3032 /* reallocate array */
3033 SCIP_ALLOC( BMSallocBlockMemoryArray(hashmap->blkmem, &slots, newnslots) );
3034 SCIP_ALLOC( BMSallocClearBlockMemoryArray(hashmap->blkmem, &hashes, newnslots) );
3035
3036 SCIPswapPointers((void**) &slots, (void**) &hashmap->slots);
3037 SCIPswapPointers((void**) &hashes, (void**) &hashmap->hashes);
3038 hashmap->nelements = 0;
3039
3040 /* reinsert all elements */
3041 for( i = 0; i < nslots; ++i )
3042 {
3043 /* using SCIP_CALL_ABORT since there are no allocations or duplicates
3044 * and thus no bad return codes when inserting the elements
3045 */
3046 if( hashes[i] != 0 )
3047 {
3048 SCIP_CALL_ABORT( hashmapInsert(hashmap, slots[i].origin, slots[i].image, hashes[i], FALSE) );
3049 }
3050 }
3051
3052 /* free old arrays */
3053 BMSfreeBlockMemoryArray(hashmap->blkmem, &hashes, nslots);
3054 BMSfreeBlockMemoryArray(hashmap->blkmem, &slots, nslots);
3055 }
3056
3057 return SCIP_OKAY;
3058}
3059
3060/** creates a hash map mapping pointers to pointers */
3062 SCIP_HASHMAP** hashmap, /**< pointer to store the created hash map */
3063 BMS_BLKMEM* blkmem, /**< block memory used to store hash map entries */
3064 int mapsize /**< size of the hash map */
3065 )
3066{
3067 uint32_t nslots;
3068
3069 assert(hashmap != NULL);
3070 assert(mapsize >= 0);
3071 assert(blkmem != NULL);
3072
3073 SCIP_ALLOC( BMSallocBlockMemory(blkmem, hashmap) );
3074
3075 /* dont create too small hashtables, i.e. at least size 32, and increase
3076 * the given size by divinding it by 0.9, since then no rebuilding will
3077 * be necessary if the given number of elements are inserted. Finally round
3078 * to the next power of two.
3079 */
3080 (*hashmap)->shift = 32;
3081 (*hashmap)->shift -= (unsigned int)ceil(log(MAX(32, mapsize / 0.9)) / log(2.0));
3082 nslots = 1u << (32 - (*hashmap)->shift);
3083 (*hashmap)->mask = nslots - 1;
3084 (*hashmap)->blkmem = blkmem;
3085 (*hashmap)->nelements = 0;
3086 (*hashmap)->hashmaptype = SCIP_HASHMAPTYPE_UNKNOWN;
3087
3088 SCIP_ALLOC( BMSallocBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->slots, nslots) );
3089 SCIP_ALLOC( BMSallocClearBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->hashes, nslots) );
3090
3091 return SCIP_OKAY;
3092}
3093
3094/** frees the hash map */
3096 SCIP_HASHMAP** hashmap /**< pointer to the hash map */
3097 )
3098{
3099 uint32_t nslots;
3100
3101 assert(hashmap != NULL);
3102 assert(*hashmap != NULL);
3103
3104 nslots = (*hashmap)->mask + 1;
3105#ifdef SCIP_DEBUG
3106 {
3107 uint32_t maxprobelen = 0;
3108 uint64_t probelensum = 0;
3109 uint32_t i;
3110
3111 assert(hashmap != NULL);
3112
3113 for( i = 0; i < nslots; ++i )
3114 {
3115 if( (*hashmap)->hashes[i] != 0 )
3116 {
3117 uint32_t probelen = ((i + (*hashmap)->mask + 1 - ((*hashmap)->hashes[i]>>((*hashmap)->shift))) & (*hashmap)->mask) + 1;
3118 probelensum += probelen;
3119 maxprobelen = MAX(probelen, maxprobelen);
3120 }
3121 }
3122
3123 SCIPdebugMessage("%u hash map entries, used %u/%u slots (%.1f%%)",
3124 (unsigned int)(*hashmap)->nelements, (unsigned int)(*hashmap)->nelements, (unsigned int)nslots,
3125 100.0*(SCIP_Real)(*hashmap)->nelements/(SCIP_Real)(nslots));
3126 if( (*hashmap)->nelements > 0 )
3127 SCIPdebugPrintf(", avg. probe length is %.1f, max. probe length is %u",
3128 (SCIP_Real)(probelensum)/(SCIP_Real)(*hashmap)->nelements, (unsigned int)maxprobelen);
3129 SCIPdebugPrintf("\n");
3130 }
3131#endif
3132
3133 /* free main hash map data structure */
3134 BMSfreeBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->hashes, nslots);
3135 BMSfreeBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->slots, nslots);
3136 BMSfreeBlockMemory((*hashmap)->blkmem, hashmap);
3137}
3138
3139/** inserts new origin->image pair in hash map
3140 *
3141 * @note multiple insertion of same element is checked and results in an error
3142 */
3144 SCIP_HASHMAP* hashmap, /**< hash map */
3145 void* origin, /**< origin to set image for */
3146 void* image /**< new image for origin */
3147 )
3148{
3149 uint32_t hashval;
3151
3152 assert(hashmap != NULL);
3153 assert(hashmap->slots != NULL);
3154 assert(hashmap->hashes != NULL);
3155 assert(hashmap->mask > 0);
3157
3158#ifndef NDEBUG
3159 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3161#endif
3162
3163 SCIP_CALL( hashmapCheckLoad(hashmap) );
3164
3165 /* get the hash value */
3166 hashval = hashvalue((size_t)origin);
3167
3168 /* append origin->image pair to hash map */
3169 img.ptr = image;
3170 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, FALSE) );
3171
3172 return SCIP_OKAY;
3173}
3174
3175/** inserts new origin->image pair in hash map
3176 *
3177 * @note multiple insertion of same element is checked and results in an error
3178 */
3180 SCIP_HASHMAP* hashmap, /**< hash map */
3181 void* origin, /**< origin to set image for */
3182 int image /**< new image for origin */
3183 )
3184{
3185 uint32_t hashval;
3187
3188 assert(hashmap != NULL);
3189 assert(hashmap->slots != NULL);
3190 assert(hashmap->hashes != NULL);
3191 assert(hashmap->mask > 0);
3192 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_INT);
3193
3194#ifndef NDEBUG
3195 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3197#endif
3198
3199 SCIP_CALL( hashmapCheckLoad(hashmap) );
3200
3201 /* get the hash value */
3202 hashval = hashvalue((size_t)origin);
3203
3204 /* append origin->image pair to hash map */
3205 img.integer = image;
3206 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, FALSE) );
3207
3208 return SCIP_OKAY;
3209}
3210
3211/** inserts new origin->image pair in hash map
3212 *
3213 * @note multiple insertion of same element is checked and results in an error
3214 */
3216 SCIP_HASHMAP* hashmap, /**< hash map */
3217 void* origin, /**< origin to set image for */
3218 SCIP_Longint image /**< new image for origin */
3219 )
3220{
3221 uint32_t hashval;
3223
3224 assert(hashmap != NULL);
3225 assert(hashmap->slots != NULL);
3226 assert(hashmap->hashes != NULL);
3227 assert(hashmap->mask > 0);
3228 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_LONG);
3229
3230#ifndef NDEBUG
3231 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3233#endif
3234
3235 SCIP_CALL( hashmapCheckLoad(hashmap) );
3236
3237 /* get the hash value */
3238 hashval = hashvalue((size_t)origin);
3239
3240 /* append origin->image pair to hash map */
3241 img.longint = image;
3242 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, FALSE) );
3243
3244 return SCIP_OKAY;
3245}
3246
3247/** inserts new origin->image pair in hash map
3248 *
3249 * @note multiple insertion of same element is checked and results in an error
3250 */
3252 SCIP_HASHMAP* hashmap, /**< hash map */
3253 void* origin, /**< origin to set image for */
3254 SCIP_Real image /**< new image for origin */
3255 )
3256{
3257 uint32_t hashval;
3259
3260 assert(hashmap != NULL);
3261 assert(hashmap->slots != NULL);
3262 assert(hashmap->hashes != NULL);
3263 assert(hashmap->mask > 0);
3264 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_REAL);
3265
3266#ifndef NDEBUG
3267 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3269#endif
3270
3271 SCIP_CALL( hashmapCheckLoad(hashmap) );
3272
3273 /* get the hash value */
3274 hashval = hashvalue((size_t)origin);
3275
3276 /* append origin->image pair to hash map */
3277 img.real = image;
3278 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, FALSE) );
3279
3280 return SCIP_OKAY;
3281}
3282
3283/** retrieves image of given origin from the hash map, or NULL if no image exists */
3285 SCIP_HASHMAP* hashmap, /**< hash map */
3286 void* origin /**< origin to retrieve image for */
3287 )
3288{
3289 uint32_t pos;
3290
3291 assert(hashmap != NULL);
3292 assert(hashmap->slots != NULL);
3293 assert(hashmap->hashes != NULL);
3294 assert(hashmap->mask > 0);
3296
3297 if( hashmapLookup(hashmap, origin, &pos) )
3298 return hashmap->slots[pos].image.ptr;
3299
3300 return NULL;
3301}
3302
3303/** retrieves image of given origin from the hash map, or INT_MAX if no image exists */
3305 SCIP_HASHMAP* hashmap, /**< hash map */
3306 void* origin /**< origin to retrieve image for */
3307 )
3308{
3309 uint32_t pos;
3310
3311 assert(hashmap != NULL);
3312 assert(hashmap->slots != NULL);
3313 assert(hashmap->hashes != NULL);
3314 assert(hashmap->mask > 0);
3315 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_INT);
3316
3317 if( hashmapLookup(hashmap, origin, &pos) )
3318 return hashmap->slots[pos].image.integer;
3319
3320 return INT_MAX;
3321}
3322
3323/** retrieves image of given origin from the hash map, or SCIP_LONGINT_MAX if no image exists */
3325 SCIP_HASHMAP* hashmap, /**< hash map */
3326 void* origin /**< origin to retrieve image for */
3327 )
3328{
3329 uint32_t pos;
3330
3331 assert(hashmap != NULL);
3332 assert(hashmap->slots != NULL);
3333 assert(hashmap->hashes != NULL);
3334 assert(hashmap->mask > 0);
3335 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_LONG);
3336
3337 if( hashmapLookup(hashmap, origin, &pos) )
3338 return hashmap->slots[pos].image.longint;
3339
3340 return SCIP_LONGINT_MAX;
3341}
3342
3343/** retrieves image of given origin from the hash map, or SCIP_INVALID if no image exists */
3345 SCIP_HASHMAP* hashmap, /**< hash map */
3346 void* origin /**< origin to retrieve image for */
3347 )
3348{
3349 uint32_t pos;
3350
3351 assert(hashmap != NULL);
3352 assert(hashmap->slots != NULL);
3353 assert(hashmap->hashes != NULL);
3354 assert(hashmap->mask > 0);
3355 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_REAL);
3356
3357 if( hashmapLookup(hashmap, origin, &pos) )
3358 return hashmap->slots[pos].image.real;
3359
3360 return SCIP_INVALID;
3361}
3362
3363/** sets image for given origin in the hash map, either by modifying existing origin->image pair
3364 * or by appending a new origin->image pair
3365 */
3367 SCIP_HASHMAP* hashmap, /**< hash map */
3368 void* origin, /**< origin to set image for */
3369 void* image /**< new image for origin */
3370 )
3371{
3372 uint32_t hashval;
3374
3375 assert(hashmap != NULL);
3376 assert(hashmap->slots != NULL);
3377 assert(hashmap->mask > 0);
3379
3380#ifndef NDEBUG
3381 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3383#endif
3384
3385 SCIP_CALL( hashmapCheckLoad(hashmap) );
3386
3387 /* get the hash value */
3388 hashval = hashvalue((size_t)origin);
3389
3390 /* append origin->image pair to hash map */
3391 img.ptr = image;
3392 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, TRUE) );
3393
3394 return SCIP_OKAY;
3395}
3396
3397/** sets image for given origin in the hash map, either by modifying existing origin->image pair
3398 * or by appending a new origin->image pair
3399 */
3401 SCIP_HASHMAP* hashmap, /**< hash map */
3402 void* origin, /**< origin to set image for */
3403 int image /**< new image for origin */
3404 )
3405{
3406 uint32_t hashval;
3408
3409 assert(hashmap != NULL);
3410 assert(hashmap->slots != NULL);
3411 assert(hashmap->mask > 0);
3412 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_INT);
3413
3414#ifndef NDEBUG
3415 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3417#endif
3418
3419 SCIP_CALL( hashmapCheckLoad(hashmap) );
3420
3421 /* get the hash value */
3422 hashval = hashvalue((size_t)origin);
3423
3424 /* append origin->image pair to hash map */
3425 img.integer = image;
3426 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, TRUE) );
3427
3428 return SCIP_OKAY;
3429}
3430
3431/** sets image for given origin in the hash map, either by modifying existing origin->image pair
3432 * or by appending a new origin->image pair
3433 */
3435 SCIP_HASHMAP* hashmap, /**< hash map */
3436 void* origin, /**< origin to set image for */
3437 SCIP_Real image /**< new image for origin */
3438 )
3439{
3440 uint32_t hashval;
3442
3443 assert(hashmap != NULL);
3444 assert(hashmap->slots != NULL);
3445 assert(hashmap->mask > 0);
3446 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_REAL);
3447
3448#ifndef NDEBUG
3449 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3451#endif
3452
3453 SCIP_CALL( hashmapCheckLoad(hashmap) );
3454
3455 /* get the hash value */
3456 hashval = hashvalue((size_t)origin);
3457
3458 /* append origin->image pair to hash map */
3459 img.real = image;
3460 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, TRUE) );
3461
3462 return SCIP_OKAY;
3463}
3464
3465/** checks whether an image to the given origin exists in the hash map */
3467 SCIP_HASHMAP* hashmap, /**< hash map */
3468 void* origin /**< origin to search for */
3469 )
3470{
3471 uint32_t pos;
3472
3473 assert(hashmap != NULL);
3474 assert(hashmap->slots != NULL);
3475 assert(hashmap->hashes != NULL);
3476 assert(hashmap->mask > 0);
3477
3478 return hashmapLookup(hashmap, origin, &pos);
3479}
3480
3481/** removes origin->image pair from the hash map, if it exists */
3483 SCIP_HASHMAP* hashmap, /**< hash map */
3484 void* origin /**< origin to remove from the list */
3485 )
3486{
3487 uint32_t pos;
3488
3489 assert(hashmap != NULL);
3490 assert(hashmap->slots != NULL);
3491 assert(hashmap->mask > 0);
3492
3493 assert(origin != NULL);
3494
3495 if( hashmapLookup(hashmap, origin, &pos) )
3496 {
3497 /* remove element */
3498 hashmap->hashes[pos] = 0;
3499 --hashmap->nelements;
3500
3501 /* move other elements if necessary */
3502 while( TRUE ) /*lint !e716*/
3503 {
3504 uint32_t nextpos = (pos + 1) & hashmap->mask;
3505
3506 /* nothing to do since there is no chain that needs to be moved */
3507 if( hashmap->hashes[nextpos] == 0 )
3508 return SCIP_OKAY;
3509
3510 /* check if the element is the start of a new chain and return if that is the case */
3511 if( (hashmap->hashes[nextpos]>>(hashmap->shift)) == nextpos )
3512 return SCIP_OKAY;
3513
3514 /* element should be moved to the left and next element needs to be checked */
3515 hashmap->slots[pos].origin = hashmap->slots[nextpos].origin;
3516 hashmap->slots[pos].image = hashmap->slots[nextpos].image;
3517 hashmap->hashes[pos] = hashmap->hashes[nextpos];
3518 hashmap->hashes[nextpos] = 0;
3519
3520 pos = nextpos;
3521 }
3522 }
3523
3524 return SCIP_OKAY;
3525}
3526
3527/** prints statistics about hash map usage */
3529 SCIP_HASHMAP* hashmap, /**< hash map */
3530 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
3531 )
3532{
3533 uint32_t maxprobelen = 0;
3534 uint64_t probelensum = 0;
3535 uint32_t nslots;
3536 uint32_t i;
3537
3538 assert(hashmap != NULL);
3539
3540 nslots = hashmap->mask + 1;
3541
3542 /* compute the maximum and average probe length */
3543 for( i = 0; i < nslots; ++i )
3544 {
3545 if( hashmap->hashes[i] != 0 )
3546 {
3547 uint32_t probelen = ELEM_DISTANCE(i) + 1;
3548 probelensum += probelen;
3549 maxprobelen = MAX(probelen, maxprobelen);
3550 }
3551 }
3552
3553 /* print general hash map statistics */
3554 SCIPmessagePrintInfo(messagehdlr, "%u hash entries, used %u/%u slots (%.1f%%)",
3555 (unsigned int)hashmap->nelements, (unsigned int)hashmap->nelements,
3556 (unsigned int)nslots, 100.0*(SCIP_Real)hashmap->nelements/(SCIP_Real)(nslots));
3557
3558 /* if not empty print average and maximum probe length */
3559 if( hashmap->nelements > 0 )
3560 SCIPmessagePrintInfo(messagehdlr, ", avg. probe length is %.1f, max. probe length is %u",
3561 (SCIP_Real)(probelensum)/(SCIP_Real)hashmap->nelements, (unsigned int)maxprobelen);
3562 SCIPmessagePrintInfo(messagehdlr, "\n");
3563}
3564
3565/** indicates whether a hash map has no entries */
3567 SCIP_HASHMAP* hashmap /**< hash map */
3568 )
3569{
3570 assert(hashmap != NULL);
3571
3572 return hashmap->nelements == 0;
3573}
3574
3575/** gives the number of elements in a hash map */
3577 SCIP_HASHMAP* hashmap /**< hash map */
3578 )
3579{
3580 return (int) hashmap->nelements;
3581}
3582
3583/** gives the number of entries in the internal arrays of a hash map */
3585 SCIP_HASHMAP* hashmap /**< hash map */
3586 )
3587{
3588 return (int) hashmap->mask + 1;
3589}
3590
3591/** gives the hashmap entry at the given index or NULL if entry is empty */
3593 SCIP_HASHMAP* hashmap, /**< hash map */
3594 int entryidx /**< index of hash map entry */
3595 )
3596{
3597 assert(hashmap != NULL);
3598
3599 return hashmap->hashes[entryidx] == 0 ? NULL : &hashmap->slots[entryidx];
3600}
3601
3602/** gives the origin of the hashmap entry */
3604 SCIP_HASHMAPENTRY* entry /**< hash map entry */
3605 )
3606{
3607 assert(entry != NULL);
3608
3609 return entry->origin;
3610}
3611
3612/** gives the image of the hashmap entry */
3614 SCIP_HASHMAPENTRY* entry /**< hash map entry */
3615 )
3616{
3617 assert(entry != NULL);
3618
3619 return entry->image.ptr;
3620}
3621
3622/** gives the image of the hashmap entry */
3624 SCIP_HASHMAPENTRY* entry /**< hash map entry */
3625 )
3626{
3627 assert(entry != NULL);
3628
3629 return entry->image.integer;
3630}
3631
3632/** gives the image of the hashmap entry */
3634 SCIP_HASHMAPENTRY* entry /**< hash map entry */
3635 )
3636{
3637 assert(entry != NULL);
3638
3639 return entry->image.real;
3640}
3641
3642/** sets pointer image of a hashmap entry */
3644 SCIP_HASHMAPENTRY* entry, /**< hash map entry */
3645 void* image /**< new image */
3646 )
3647{
3648 assert(entry != NULL);
3649
3650 entry->image.ptr = image;
3651}
3652
3653/** sets integer image of a hashmap entry */
3655 SCIP_HASHMAPENTRY* entry, /**< hash map entry */
3656 int image /**< new image */
3657 )
3658{
3659 assert(entry != NULL);
3660
3661 entry->image.integer = image;
3662}
3663
3664/** sets real image of a hashmap entry */
3666 SCIP_HASHMAPENTRY* entry, /**< hash map entry */
3667 SCIP_Real image /**< new image */
3668 )
3669{
3670 assert(entry != NULL);
3671
3672 entry->image.real = image;
3673}
3674
3675/** removes all entries in a hash map. */
3677 SCIP_HASHMAP* hashmap /**< hash map */
3678 )
3679{
3680 assert(hashmap != NULL);
3681
3682 BMSclearMemoryArray(hashmap->hashes, hashmap->mask + 1);
3683
3684 hashmap->nelements = 0;
3685
3686 return SCIP_OKAY;
3687}
3688
3689
3690/*
3691 * Hash Set
3692 */
3693
3694/* redefine ELEM_DISTANCE macro for hashset */
3695#undef ELEM_DISTANCE
3696/* computes the distance from it's desired position for the element stored at pos */
3697#define ELEM_DISTANCE(pos) (((pos) + nslots - hashSetDesiredPos(hashset, hashset->slots[(pos)])) & mask)
3698
3699/* calculate desired position of element in hash set */
3700static
3702 SCIP_HASHSET* hashset, /**< the hash set */
3703 void* element /**< element to calculate position for */
3704 )
3705{
3706 return (uint32_t)((UINT64_C(0x9e3779b97f4a7c15) * (uintptr_t)element)>>(hashset->shift));
3707}
3708
3709static
3711 SCIP_HASHSET* hashset, /**< hash set */
3712 void* element /**< element to insert */
3713 )
3714{
3715 uint32_t elemdistance;
3716 uint32_t pos;
3717 uint32_t nslots;
3718 uint32_t mask;
3719
3720 assert(hashset != NULL);
3721 assert(hashset->slots != NULL);
3722 assert(element != NULL);
3723
3724 pos = hashSetDesiredPos(hashset, element);
3725 nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3726 mask = nslots - 1;
3727
3728 elemdistance = 0;
3729 while( TRUE ) /*lint !e716*/
3730 {
3731 uint32_t distance;
3732
3733 /* if position is empty or key equal insert element */
3734 if( hashset->slots[pos] == NULL )
3735 {
3736 hashset->slots[pos] = element;
3737 ++hashset->nelements;
3738 return;
3739 }
3740
3741 if( hashset->slots[pos] == element )
3742 return;
3743
3744 /* otherwise check if the current element at this position is closer to its hashvalue */
3745 distance = ELEM_DISTANCE(pos);
3746 if( distance < elemdistance )
3747 {
3748 /* if this is the case we insert the new element here and find a new position for the old one */
3749 elemdistance = distance;
3750 SCIPswapPointers(&hashset->slots[pos], &element);
3751 }
3752
3753 /* continue until we have found an empty position */
3754 pos = (pos + 1) & mask;
3755 ++elemdistance;
3756 }
3757}
3758
3759/** check if the load factor of the hash set is too high and rebuild if necessary */
3760static
3762 SCIP_HASHSET* hashset, /**< hash set */
3763 BMS_BLKMEM* blkmem /**< block memory used to store hash set entries */
3764 )
3765{
3766 assert(hashset != NULL);
3767 assert(hashset->shift < 64);
3768
3769 /* use integer arithmetic to approximately check if load factor is above 90% */
3770 if( ((((uint64_t)hashset->nelements)<<10)>>(64-hashset->shift) > 921) )
3771 {
3772 void** slots;
3773 uint32_t nslots;
3774 uint32_t newnslots;
3775 uint32_t i;
3776
3777 /* calculate new size (always power of two) */
3778 nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3779 newnslots = 2*nslots;
3780 --hashset->shift;
3781
3782 /* reallocate array */
3783 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &slots, newnslots) );
3784
3785 SCIPswapPointers((void**) &slots, (void**) &hashset->slots);
3786 hashset->nelements = 0;
3787
3788 /* reinsert all elements */
3789 for( i = 0; i < nslots; ++i )
3790 {
3791 if( slots[i] != NULL )
3792 hashsetInsert(hashset, slots[i]);
3793 }
3794
3795 BMSfreeBlockMemoryArray(blkmem, &slots, nslots);
3796 }
3797
3798 return SCIP_OKAY;
3799}
3800
3801/** creates a hash set of pointers */
3803 SCIP_HASHSET** hashset, /**< pointer to store the created hash set */
3804 BMS_BLKMEM* blkmem, /**< block memory used to store hash set entries */
3805 int size /**< initial size of the hash set; it is guaranteed that the set is not
3806 * resized if at most that many elements are inserted */
3807 )
3808{
3809 uint32_t nslots;
3810
3811 assert(hashset != NULL);
3812 assert(size >= 0);
3813 assert(blkmem != NULL);
3814
3815 SCIP_ALLOC( BMSallocBlockMemory(blkmem, hashset) );
3816
3817 /* do not create too small hashtables, i.e. at least size 32, and increase
3818 * the given size by dividing it by 0.9, since then no rebuilding will
3819 * be necessary if the given number of elements are inserted. Finally round
3820 * to the next power of two.
3821 */
3822 (*hashset)->shift = 64;
3823 (*hashset)->shift -= (unsigned int)ceil(log(MAX(8.0, size / 0.9)) / log(2.0));
3824 nslots = (uint32_t)SCIPhashsetGetNSlots(*hashset);
3825 (*hashset)->nelements = 0;
3826
3827 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*hashset)->slots, nslots) );
3828
3829 return SCIP_OKAY;
3830}
3831
3832/** frees the hash set */
3834 SCIP_HASHSET** hashset, /**< pointer to the hash set */
3835 BMS_BLKMEM* blkmem /**< block memory used to store hash set entries */
3836 )
3837{
3838 BMSfreeBlockMemoryArray(blkmem, &(*hashset)->slots, SCIPhashsetGetNSlots(*hashset));
3839 BMSfreeBlockMemory(blkmem, hashset);
3840}
3841
3842/** inserts new element into the hash set */
3844 SCIP_HASHSET* hashset, /**< hash set */
3845 BMS_BLKMEM* blkmem, /**< block memory used to store hash set entries */
3846 void* element /**< element to insert */
3847 )
3848{
3849 assert(hashset != NULL);
3850 assert(hashset->slots != NULL);
3851
3852 SCIP_CALL( hashsetCheckLoad(hashset, blkmem) );
3853
3854 hashsetInsert(hashset, element);
3855
3856 return SCIP_OKAY;
3857}
3858
3859/** checks whether an element exists in the hash set */
3861 SCIP_HASHSET* hashset, /**< hash set */
3862 void* element /**< element to search for */
3863 )
3864{
3865 uint32_t pos;
3866 uint32_t nslots;
3867 uint32_t mask;
3868 uint32_t elemdistance;
3869
3870 assert(hashset != NULL);
3871 assert(hashset->slots != NULL);
3872
3873 pos = hashSetDesiredPos(hashset, element);
3874 nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3875 mask = nslots - 1;
3876 elemdistance = 0;
3877
3878 while( TRUE ) /*lint !e716*/
3879 {
3880 uint32_t distance;
3881
3882 /* found element */
3883 if( hashset->slots[pos] == element )
3884 return TRUE;
3885
3886 /* slots is empty so element cannot be contained */
3887 if( hashset->slots[pos] == NULL )
3888 return FALSE;
3889
3890 distance = ELEM_DISTANCE(pos);
3891 /* element can not be contained since otherwise we would have swapped it with this one during insert */
3892 if( elemdistance > distance )
3893 return FALSE;
3894
3895 pos = (pos + 1) & mask;
3896 ++elemdistance;
3897 }
3898}
3899
3900/** removes an element from the hash set, if it exists */
3902 SCIP_HASHSET* hashset, /**< hash set */
3903 void* element /**< origin to remove from the list */
3904 )
3905{
3906 uint32_t pos;
3907 uint32_t nslots;
3908 uint32_t mask;
3909 uint32_t elemdistance;
3910
3911 assert(hashset != NULL);
3912 assert(hashset->slots != NULL);
3913 assert(element != NULL);
3914
3915 pos = hashSetDesiredPos(hashset, element);
3916 nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3917 mask = nslots - 1;
3918 elemdistance = 0;
3919
3920 while( TRUE ) /*lint !e716*/
3921 {
3922 uint32_t distance;
3923
3924 /* found element */
3925 if( hashset->slots[pos] == element )
3926 break;
3927
3928 /* slots is empty so element cannot be contained */
3929 if( hashset->slots[pos] == NULL )
3930 return SCIP_OKAY;
3931
3932 distance = ELEM_DISTANCE(pos);
3933 /* element can not be contained since otherwise we would have swapped it with this one during insert */
3934 if( elemdistance > distance )
3935 return SCIP_OKAY;
3936
3937 pos = (pos + 1) & mask;
3938 ++elemdistance;
3939 }
3940
3941 assert(hashset->slots[pos] == element);
3942 assert(SCIPhashsetExists(hashset, element));
3943
3944 /* remove element */
3945 --hashset->nelements;
3946
3947 /* move other elements if necessary */
3948 while( TRUE ) /*lint !e716*/
3949 {
3950 uint32_t nextpos = (pos + 1) & mask;
3951
3952 /* nothing to do since there is no chain that needs to be moved */
3953 if( hashset->slots[nextpos] == NULL )
3954 {
3955 hashset->slots[pos] = NULL;
3956 assert(!SCIPhashsetExists(hashset, element));
3957 return SCIP_OKAY;
3958 }
3959
3960 /* check if the element is the start of a new chain and return if that is the case */
3961 if( hashSetDesiredPos(hashset, hashset->slots[nextpos]) == nextpos )
3962 {
3963 hashset->slots[pos] = NULL;
3964 assert(!SCIPhashsetExists(hashset, element));
3965 return SCIP_OKAY;
3966 }
3967
3968 /* element should be moved to the left and next element needs to be checked */
3969 hashset->slots[pos] = hashset->slots[nextpos];
3970
3971 pos = nextpos;
3972 }
3973}
3974
3975/** prints statistics about hash set usage */
3977 SCIP_HASHSET* hashset, /**< hash set */
3978 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
3979 )
3980{
3981 uint32_t maxprobelen = 0;
3982 uint64_t probelensum = 0;
3983 uint32_t nslots;
3984 uint32_t mask;
3985 uint32_t i;
3986
3987 assert(hashset != NULL);
3988
3989 nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3990 mask = nslots - 1;
3991
3992 /* compute the maximum and average probe length */
3993 for( i = 0; i < nslots; ++i )
3994 {
3995 if( hashset->slots[i] != NULL )
3996 {
3997 uint32_t probelen = ((hashSetDesiredPos(hashset, hashset->slots[i]) + nslots - i) & mask) + 1;
3998 probelensum += probelen;
3999 maxprobelen = MAX(probelen, maxprobelen);
4000 }
4001 }
4002
4003 /* print general hash set statistics */
4004 SCIPmessagePrintInfo(messagehdlr, "%u hash entries, used %u/%u slots (%.1f%%)",
4005 (unsigned int)hashset->nelements, (unsigned int)hashset->nelements,
4006 (unsigned int)nslots, 100.0*(SCIP_Real)hashset->nelements/(SCIP_Real)(nslots));
4007
4008 /* if not empty print average and maximum probe length */
4009 if( hashset->nelements > 0 )
4010 SCIPmessagePrintInfo(messagehdlr, ", avg. probe length is %.1f, max. probe length is %u",
4011 (SCIP_Real)(probelensum)/(SCIP_Real)hashset->nelements, (unsigned int)maxprobelen);
4012 SCIPmessagePrintInfo(messagehdlr, "\n");
4013}
4014
4015/* In debug mode, the following methods are implemented as function calls to ensure
4016 * type validity.
4017 * In optimized mode, the methods are implemented as defines to improve performance.
4018 * However, we want to have them in the library anyways, so we have to undef the defines.
4019 */
4020
4021#undef SCIPhashsetIsEmpty
4022#undef SCIPhashsetGetNElements
4023#undef SCIPhashsetGetNSlots
4024#undef SCIPhashsetGetSlots
4025
4026/** indicates whether a hash set has no entries */
4028 SCIP_HASHSET* hashset /**< hash set */
4029 )
4030{
4031 return hashset->nelements == 0;
4032}
4033
4034/** gives the number of elements in a hash set */
4036 SCIP_HASHSET* hashset /**< hash set */
4037 )
4038{
4039 return (int)hashset->nelements;
4040}
4041
4042/** gives the number of slots of a hash set */
4044 SCIP_HASHSET* hashset /**< hash set */
4045 )
4046{
4047 return (int) (1u << (64 - hashset->shift));
4048}
4049
4050/** gives the array of hash set slots; contains all elements in indetermined order and may contain NULL values */
4052 SCIP_HASHSET* hashset /**< hash set */
4053 )
4054{
4055 return hashset->slots;
4056}
4057
4058/** removes all entries in a hash set. */
4060 SCIP_HASHSET* hashset /**< hash set */
4061 )
4062{
4064
4065 hashset->nelements = 0;
4066}
4067
4068/*
4069 * Dynamic Arrays
4070 */
4071
4072/** creates a dynamic array of real values */
4074 SCIP_REALARRAY** realarray, /**< pointer to store the real array */
4075 BMS_BLKMEM* blkmem /**< block memory */
4076 )
4077{
4078 assert(realarray != NULL);
4079 assert(blkmem != NULL);
4080
4081 SCIP_ALLOC( BMSallocBlockMemory(blkmem, realarray) );
4082 (*realarray)->blkmem = blkmem;
4083 (*realarray)->vals = NULL;
4084 (*realarray)->valssize = 0;
4085 (*realarray)->firstidx = -1;
4086 (*realarray)->minusedidx = INT_MAX;
4087 (*realarray)->maxusedidx = INT_MIN;
4088
4089 return SCIP_OKAY;
4090}
4091
4092/** creates a copy of a dynamic array of real values */
4094 SCIP_REALARRAY** realarray, /**< pointer to store the copied real array */
4095 BMS_BLKMEM* blkmem, /**< block memory */
4096 SCIP_REALARRAY* sourcerealarray /**< dynamic real array to copy */
4097 )
4098{
4099 assert(realarray != NULL);
4100 assert(sourcerealarray != NULL);
4101
4102 SCIP_CALL( SCIPrealarrayCreate(realarray, blkmem) );
4103 if( sourcerealarray->valssize > 0 )
4104 {
4105 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*realarray)->vals, sourcerealarray->vals, \
4106 sourcerealarray->valssize) );
4107 }
4108 (*realarray)->valssize = sourcerealarray->valssize;
4109 (*realarray)->firstidx = sourcerealarray->firstidx;
4110 (*realarray)->minusedidx = sourcerealarray->minusedidx;
4111 (*realarray)->maxusedidx = sourcerealarray->maxusedidx;
4112
4113 return SCIP_OKAY;
4114}
4115
4116/** frees a dynamic array of real values */
4118 SCIP_REALARRAY** realarray /**< pointer to the real array */
4119 )
4120{
4121 assert(realarray != NULL);
4122 assert(*realarray != NULL);
4123
4124 BMSfreeBlockMemoryArrayNull((*realarray)->blkmem, &(*realarray)->vals, (*realarray)->valssize);
4125 BMSfreeBlockMemory((*realarray)->blkmem, realarray);
4126
4127 return SCIP_OKAY;
4128}
4129
4130/** extends dynamic array to be able to store indices from minidx to maxidx */
4132 SCIP_REALARRAY* realarray, /**< dynamic real array */
4133 int arraygrowinit, /**< initial size of array */
4134 SCIP_Real arraygrowfac, /**< growing factor of array */
4135 int minidx, /**< smallest index to allocate storage for */
4136 int maxidx /**< largest index to allocate storage for */
4137 )
4138{
4139 int nused;
4140 int nfree;
4141 int newfirstidx;
4142 int i;
4143
4144 assert(realarray != NULL);
4145 assert(realarray->minusedidx == INT_MAX || realarray->firstidx >= 0);
4146 assert(realarray->maxusedidx == INT_MIN || realarray->firstidx >= 0);
4147 assert(realarray->minusedidx == INT_MAX || realarray->minusedidx >= realarray->firstidx);
4148 assert(realarray->maxusedidx == INT_MIN || realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4149 assert(0 <= minidx);
4150 assert(minidx <= maxidx);
4151
4152 minidx = MIN(minidx, realarray->minusedidx);
4153 maxidx = MAX(maxidx, realarray->maxusedidx);
4154 assert(0 <= minidx);
4155 assert(minidx <= maxidx);
4156
4157 SCIPdebugMessage("extending realarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
4158 (void*)realarray, realarray->firstidx, realarray->valssize, realarray->minusedidx, realarray->maxusedidx, minidx, maxidx);
4159
4160 /* check, whether we have to allocate additional memory, or shift the array */
4161 nused = maxidx - minidx + 1;
4162 if( nused > realarray->valssize )
4163 {
4164 SCIP_Real* newvals;
4165 int newvalssize;
4166
4167 /* allocate new memory storage */
4168 newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
4169 SCIP_ALLOC( BMSallocBlockMemoryArray(realarray->blkmem, &newvals, newvalssize) );
4170 nfree = newvalssize - nused;
4171 newfirstidx = minidx - nfree/2;
4172 newfirstidx = MAX(newfirstidx, 0);
4173 assert(newfirstidx <= minidx);
4174 assert(maxidx < newfirstidx + newvalssize);
4175
4176 /* initialize memory array by copying old values and setting new values to zero */
4177 if( realarray->firstidx != -1 )
4178 {
4179 for( i = 0; i < realarray->minusedidx - newfirstidx; ++i )
4180 newvals[i] = 0.0;
4181
4182 /* check for possible overflow or negative value */
4183 assert(realarray->maxusedidx - realarray->minusedidx + 1 > 0);
4184
4185 BMScopyMemoryArray(&newvals[realarray->minusedidx - newfirstidx],
4186 &(realarray->vals[realarray->minusedidx - realarray->firstidx]),
4187 realarray->maxusedidx - realarray->minusedidx + 1); /*lint !e866 !e776*/
4188 for( i = realarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
4189 newvals[i] = 0.0;
4190 }
4191 else
4192 {
4193 for( i = 0; i < newvalssize; ++i )
4194 newvals[i] = 0.0;
4195 }
4196
4197 /* free old memory storage, and set the new array parameters */
4198 BMSfreeBlockMemoryArrayNull(realarray->blkmem, &realarray->vals, realarray->valssize);
4199 realarray->vals = newvals;
4200 realarray->valssize = newvalssize;
4201 realarray->firstidx = newfirstidx;
4202 }
4203 else if( realarray->firstidx == -1 )
4204 {
4205 /* a sufficiently large memory storage exists, but it was cleared */
4206 nfree = realarray->valssize - nused;
4207 assert(nfree >= 0);
4208 realarray->firstidx = minidx - nfree/2;
4209 assert(realarray->firstidx <= minidx);
4210 assert(maxidx < realarray->firstidx + realarray->valssize);
4211#ifndef NDEBUG
4212 for( i = 0; i < realarray->valssize; ++i )
4213 assert(realarray->vals[i] == 0.0);
4214#endif
4215 }
4216 else if( minidx < realarray->firstidx )
4217 {
4218 /* a sufficiently large memory storage exists, but it has to be shifted to the right */
4219 nfree = realarray->valssize - nused;
4220 assert(nfree >= 0);
4221 newfirstidx = minidx - nfree/2;
4222 newfirstidx = MAX(newfirstidx, 0);
4223 assert(newfirstidx <= minidx);
4224 assert(maxidx < newfirstidx + realarray->valssize);
4225
4226 if( realarray->minusedidx <= realarray->maxusedidx )
4227 {
4228 int shift;
4229
4230 assert(realarray->firstidx <= realarray->minusedidx);
4231 assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4232
4233 /* shift used part of array to the right */
4234 shift = realarray->firstidx - newfirstidx;
4235 assert(shift > 0);
4236 for( i = realarray->maxusedidx - realarray->firstidx; i >= realarray->minusedidx - realarray->firstidx; --i )
4237 {
4238 assert(0 <= i + shift && i + shift < realarray->valssize);
4239 realarray->vals[i + shift] = realarray->vals[i];
4240 }
4241 /* clear the formerly used head of the array */
4242 for( i = 0; i < shift; ++i )
4243 realarray->vals[realarray->minusedidx - realarray->firstidx + i] = 0.0;
4244 }
4245 realarray->firstidx = newfirstidx;
4246 }
4247 else if( maxidx >= realarray->firstidx + realarray->valssize )
4248 {
4249 /* a sufficiently large memory storage exists, but it has to be shifted to the left */
4250 nfree = realarray->valssize - nused;
4251 assert(nfree >= 0);
4252 newfirstidx = minidx - nfree/2;
4253 newfirstidx = MAX(newfirstidx, 0);
4254 assert(newfirstidx <= minidx);
4255 assert(maxidx < newfirstidx + realarray->valssize);
4256
4257 if( realarray->minusedidx <= realarray->maxusedidx )
4258 {
4259 int shift;
4260
4261 assert(realarray->firstidx <= realarray->minusedidx);
4262 assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4263
4264 /* shift used part of array to the left */
4265 shift = newfirstidx - realarray->firstidx;
4266 assert(shift > 0);
4267 for( i = realarray->minusedidx - realarray->firstidx; i <= realarray->maxusedidx - realarray->firstidx; ++i )
4268 {
4269 assert(0 <= i - shift && i - shift < realarray->valssize);
4270 realarray->vals[i - shift] = realarray->vals[i];
4271 }
4272 /* clear the formerly used tail of the array */
4273 for( i = 0; i < shift; ++i )
4274 realarray->vals[realarray->maxusedidx - realarray->firstidx - i] = 0.0;
4275 }
4276 realarray->firstidx = newfirstidx;
4277 }
4278
4279 assert(minidx >= realarray->firstidx);
4280 assert(maxidx < realarray->firstidx + realarray->valssize);
4281
4282 return SCIP_OKAY;
4283}
4284
4285/** clears a dynamic real array */
4287 SCIP_REALARRAY* realarray /**< dynamic real array */
4288 )
4289{
4290 assert(realarray != NULL);
4291
4292 SCIPdebugMessage("clearing realarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
4293 (void*)realarray, realarray->firstidx, realarray->valssize, realarray->minusedidx, realarray->maxusedidx);
4294
4295 if( realarray->minusedidx <= realarray->maxusedidx )
4296 {
4297 assert(realarray->firstidx <= realarray->minusedidx);
4298 assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4299 assert(realarray->firstidx != -1);
4300 assert(realarray->valssize > 0);
4301
4302 /* clear the used part of array */
4303 BMSclearMemoryArray(&realarray->vals[realarray->minusedidx - realarray->firstidx],
4304 realarray->maxusedidx - realarray->minusedidx + 1); /*lint !e866*/
4305
4306 /* mark the array cleared */
4307 realarray->minusedidx = INT_MAX;
4308 realarray->maxusedidx = INT_MIN;
4309 }
4310 assert(realarray->minusedidx == INT_MAX);
4311 assert(realarray->maxusedidx == INT_MIN);
4312
4313 return SCIP_OKAY;
4314}
4315
4316/** gets value of entry in dynamic array */
4318 SCIP_REALARRAY* realarray, /**< dynamic real array */
4319 int idx /**< array index to get value for */
4320 )
4321{
4322 assert(realarray != NULL);
4323 assert(idx >= 0);
4324
4325 if( idx < realarray->minusedidx || idx > realarray->maxusedidx )
4326 return 0.0;
4327 else
4328 {
4329 assert(realarray->vals != NULL);
4330 assert(idx - realarray->firstidx >= 0);
4331 assert(idx - realarray->firstidx < realarray->valssize);
4332
4333 return realarray->vals[idx - realarray->firstidx];
4334 }
4335}
4336
4337/** sets value of entry in dynamic array */
4339 SCIP_REALARRAY* realarray, /**< dynamic real array */
4340 int arraygrowinit, /**< initial size of array */
4341 SCIP_Real arraygrowfac, /**< growing factor of array */
4342 int idx, /**< array index to set value for */
4343 SCIP_Real val /**< value to set array index to */
4344 )
4345{
4346 assert(realarray != NULL);
4347 assert(idx >= 0);
4348
4349 SCIPdebugMessage("setting realarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %g\n",
4350 (void*)realarray, realarray->firstidx, realarray->valssize, realarray->minusedidx, realarray->maxusedidx, idx, val);
4351
4352 if( val != 0.0 )
4353 {
4354 /* extend array to be able to store the index */
4355 SCIP_CALL( SCIPrealarrayExtend(realarray, arraygrowinit, arraygrowfac, idx, idx) );
4356 assert(idx >= realarray->firstidx);
4357 assert(idx < realarray->firstidx + realarray->valssize);
4358
4359 /* set the array value of the index */
4360 realarray->vals[idx - realarray->firstidx] = val;
4361
4362 /* update min/maxusedidx */
4363 realarray->minusedidx = MIN(realarray->minusedidx, idx);
4364 realarray->maxusedidx = MAX(realarray->maxusedidx, idx);
4365 }
4366 else if( idx >= realarray->firstidx && idx < realarray->firstidx + realarray->valssize )
4367 {
4368 /* set the array value of the index to zero */
4369 realarray->vals[idx - realarray->firstidx] = 0.0;
4370
4371 /* check, if we can tighten the min/maxusedidx */
4372 if( idx == realarray->minusedidx )
4373 {
4374 assert(realarray->maxusedidx >= 0);
4375 assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4376 do
4377 {
4378 realarray->minusedidx++;
4379 }
4380 while( realarray->minusedidx <= realarray->maxusedidx
4381 && realarray->vals[realarray->minusedidx - realarray->firstidx] == 0.0 );
4382
4383 if( realarray->minusedidx > realarray->maxusedidx )
4384 {
4385 realarray->minusedidx = INT_MAX;
4386 realarray->maxusedidx = INT_MIN;
4387 }
4388 }
4389 else if( idx == realarray->maxusedidx )
4390 {
4391 assert(realarray->minusedidx >= 0);
4392 assert(realarray->minusedidx < realarray->maxusedidx);
4393 assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4394 do
4395 {
4396 realarray->maxusedidx--;
4397 assert(realarray->minusedidx <= realarray->maxusedidx);
4398 }
4399 while( realarray->vals[realarray->maxusedidx - realarray->firstidx] == 0.0 );
4400 }
4401 }
4402
4403 return SCIP_OKAY;
4404}
4405
4406/** increases value of entry in dynamic array */
4408 SCIP_REALARRAY* realarray, /**< dynamic real array */
4409 int arraygrowinit, /**< initial size of array */
4410 SCIP_Real arraygrowfac, /**< growing factor of array */
4411 int idx, /**< array index to increase value for */
4412 SCIP_Real incval /**< value to increase array index */
4413 )
4414{
4415 SCIP_Real oldval;
4416
4417 oldval = SCIPrealarrayGetVal(realarray, idx);
4418 if( oldval != SCIP_INVALID ) /*lint !e777*/
4419 return SCIPrealarraySetVal(realarray, arraygrowinit, arraygrowfac, idx, oldval + incval);
4420 else
4421 return SCIP_OKAY;
4422}
4423
4424/** returns the minimal index of all stored non-zero elements */
4426 SCIP_REALARRAY* realarray /**< dynamic real array */
4427 )
4428{
4429 assert(realarray != NULL);
4430
4431 return realarray->minusedidx;
4432}
4433
4434/** returns the maximal index of all stored non-zero elements */
4436 SCIP_REALARRAY* realarray /**< dynamic real array */
4437 )
4438{
4439 assert(realarray != NULL);
4440
4441 return realarray->maxusedidx;
4442}
4443
4444/** creates a dynamic array of int values */
4446 SCIP_INTARRAY** intarray, /**< pointer to store the int array */
4447 BMS_BLKMEM* blkmem /**< block memory */
4448 )
4449{
4450 assert(intarray != NULL);
4451 assert(blkmem != NULL);
4452
4453 SCIP_ALLOC( BMSallocBlockMemory(blkmem, intarray) );
4454 (*intarray)->blkmem = blkmem;
4455 (*intarray)->vals = NULL;
4456 (*intarray)->valssize = 0;
4457 (*intarray)->firstidx = -1;
4458 (*intarray)->minusedidx = INT_MAX;
4459 (*intarray)->maxusedidx = INT_MIN;
4460
4461 return SCIP_OKAY;
4462}
4463
4464/** creates a copy of a dynamic array of int values */
4466 SCIP_INTARRAY** intarray, /**< pointer to store the copied int array */
4467 BMS_BLKMEM* blkmem, /**< block memory */
4468 SCIP_INTARRAY* sourceintarray /**< dynamic int array to copy */
4469 )
4470{
4471 assert(intarray != NULL);
4472 assert(sourceintarray != NULL);
4473
4474 SCIP_CALL( SCIPintarrayCreate(intarray, blkmem) );
4475 if( sourceintarray->valssize > 0 )
4476 {
4477 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*intarray)->vals, sourceintarray->vals, sourceintarray->valssize) );
4478 }
4479 (*intarray)->valssize = sourceintarray->valssize;
4480 (*intarray)->firstidx = sourceintarray->firstidx;
4481 (*intarray)->minusedidx = sourceintarray->minusedidx;
4482 (*intarray)->maxusedidx = sourceintarray->maxusedidx;
4483
4484 return SCIP_OKAY;
4485}
4486
4487/** frees a dynamic array of int values */
4489 SCIP_INTARRAY** intarray /**< pointer to the int array */
4490 )
4491{
4492 assert(intarray != NULL);
4493 assert(*intarray != NULL);
4494
4495 BMSfreeBlockMemoryArrayNull((*intarray)->blkmem, &(*intarray)->vals, (*intarray)->valssize);
4496 BMSfreeBlockMemory((*intarray)->blkmem, intarray);
4497
4498 return SCIP_OKAY;
4499}
4500
4501/** extends dynamic array to be able to store indices from minidx to maxidx */
4503 SCIP_INTARRAY* intarray, /**< dynamic int array */
4504 int arraygrowinit, /**< initial size of array */
4505 SCIP_Real arraygrowfac, /**< growing factor of array */
4506 int minidx, /**< smallest index to allocate storage for */
4507 int maxidx /**< largest index to allocate storage for */
4508 )
4509{
4510 int nused;
4511 int nfree;
4512 int newfirstidx;
4513 int i;
4514
4515 assert(intarray != NULL);
4516 assert(intarray->minusedidx == INT_MAX || intarray->firstidx >= 0);
4517 assert(intarray->maxusedidx == INT_MIN || intarray->firstidx >= 0);
4518 assert(intarray->minusedidx == INT_MAX || intarray->minusedidx >= intarray->firstidx);
4519 assert(intarray->maxusedidx == INT_MIN || intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4520 assert(0 <= minidx);
4521 assert(minidx <= maxidx);
4522
4523 minidx = MIN(minidx, intarray->minusedidx);
4524 maxidx = MAX(maxidx, intarray->maxusedidx);
4525 assert(0 <= minidx);
4526 assert(minidx <= maxidx);
4527
4528 SCIPdebugMessage("extending intarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
4529 (void*)intarray, intarray->firstidx, intarray->valssize, intarray->minusedidx, intarray->maxusedidx, minidx, maxidx);
4530
4531 /* check, whether we have to allocate additional memory, or shift the array */
4532 nused = maxidx - minidx + 1;
4533 if( nused > intarray->valssize )
4534 {
4535 int* newvals;
4536 int newvalssize;
4537
4538 /* allocate new memory storage */
4539 newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
4540 SCIP_ALLOC( BMSallocBlockMemoryArray(intarray->blkmem, &newvals, newvalssize) );
4541 nfree = newvalssize - nused;
4542 newfirstidx = minidx - nfree/2;
4543 newfirstidx = MAX(newfirstidx, 0);
4544 assert(newfirstidx <= minidx);
4545 assert(maxidx < newfirstidx + newvalssize);
4546
4547 /* initialize memory array by copying old values and setting new values to zero */
4548 if( intarray->firstidx != -1 )
4549 {
4550 for( i = 0; i < intarray->minusedidx - newfirstidx; ++i )
4551 newvals[i] = 0;
4552
4553 /* check for possible overflow or negative value */
4554 assert(intarray->maxusedidx - intarray->minusedidx + 1 > 0);
4555
4556 BMScopyMemoryArray(&newvals[intarray->minusedidx - newfirstidx],
4557 &intarray->vals[intarray->minusedidx - intarray->firstidx],
4558 intarray->maxusedidx - intarray->minusedidx + 1); /*lint !e866 !e776*/
4559 for( i = intarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
4560 newvals[i] = 0;
4561 }
4562 else
4563 {
4564 for( i = 0; i < newvalssize; ++i )
4565 newvals[i] = 0;
4566 }
4567
4568 /* free old memory storage, and set the new array parameters */
4569 BMSfreeBlockMemoryArrayNull(intarray->blkmem, &intarray->vals, intarray->valssize);
4570 intarray->vals = newvals;
4571 intarray->valssize = newvalssize;
4572 intarray->firstidx = newfirstidx;
4573 }
4574 else if( intarray->firstidx == -1 )
4575 {
4576 /* a sufficiently large memory storage exists, but it was cleared */
4577 nfree = intarray->valssize - nused;
4578 assert(nfree >= 0);
4579 intarray->firstidx = minidx - nfree/2;
4580 assert(intarray->firstidx <= minidx);
4581 assert(maxidx < intarray->firstidx + intarray->valssize);
4582#ifndef NDEBUG
4583 for( i = 0; i < intarray->valssize; ++i )
4584 assert(intarray->vals[i] == 0);
4585#endif
4586 }
4587 else if( minidx < intarray->firstidx )
4588 {
4589 /* a sufficiently large memory storage exists, but it has to be shifted to the right */
4590 nfree = intarray->valssize - nused;
4591 assert(nfree >= 0);
4592 newfirstidx = minidx - nfree/2;
4593 newfirstidx = MAX(newfirstidx, 0);
4594 assert(newfirstidx <= minidx);
4595 assert(maxidx < newfirstidx + intarray->valssize);
4596
4597 if( intarray->minusedidx <= intarray->maxusedidx )
4598 {
4599 int shift;
4600
4601 assert(intarray->firstidx <= intarray->minusedidx);
4602 assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4603
4604 /* shift used part of array to the right */
4605 shift = intarray->firstidx - newfirstidx;
4606 assert(shift > 0);
4607 for( i = intarray->maxusedidx - intarray->firstidx; i >= intarray->minusedidx - intarray->firstidx; --i )
4608 {
4609 assert(0 <= i + shift && i + shift < intarray->valssize);
4610 intarray->vals[i + shift] = intarray->vals[i];
4611 }
4612 /* clear the formerly used head of the array */
4613 for( i = 0; i < shift; ++i )
4614 intarray->vals[intarray->minusedidx - intarray->firstidx + i] = 0;
4615 }
4616 intarray->firstidx = newfirstidx;
4617 }
4618 else if( maxidx >= intarray->firstidx + intarray->valssize )
4619 {
4620 /* a sufficiently large memory storage exists, but it has to be shifted to the left */
4621 nfree = intarray->valssize - nused;
4622 assert(nfree >= 0);
4623 newfirstidx = minidx - nfree/2;
4624 newfirstidx = MAX(newfirstidx, 0);
4625 assert(newfirstidx <= minidx);
4626 assert(maxidx < newfirstidx + intarray->valssize);
4627
4628 if( intarray->minusedidx <= intarray->maxusedidx )
4629 {
4630 int shift;
4631
4632 assert(intarray->firstidx <= intarray->minusedidx);
4633 assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4634
4635 /* shift used part of array to the left */
4636 shift = newfirstidx - intarray->firstidx;
4637 assert(shift > 0);
4638 for( i = intarray->minusedidx - intarray->firstidx; i <= intarray->maxusedidx - intarray->firstidx; ++i )
4639 {
4640 assert(0 <= i - shift && i - shift < intarray->valssize);
4641 intarray->vals[i - shift] = intarray->vals[i];
4642 }
4643 /* clear the formerly used tail of the array */
4644 for( i = 0; i < shift; ++i )
4645 intarray->vals[intarray->maxusedidx - intarray->firstidx - i] = 0;
4646 }
4647 intarray->firstidx = newfirstidx;
4648 }
4649
4650 assert(minidx >= intarray->firstidx);
4651 assert(maxidx < intarray->firstidx + intarray->valssize);
4652
4653 return SCIP_OKAY;
4654}
4655
4656/** clears a dynamic int array */
4658 SCIP_INTARRAY* intarray /**< dynamic int array */
4659 )
4660{
4661 assert(intarray != NULL);
4662
4663 SCIPdebugMessage("clearing intarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
4664 (void*)intarray, intarray->firstidx, intarray->valssize, intarray->minusedidx, intarray->maxusedidx);
4665
4666 if( intarray->minusedidx <= intarray->maxusedidx )
4667 {
4668 assert(intarray->firstidx <= intarray->minusedidx);
4669 assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4670 assert(intarray->firstidx != -1);
4671 assert(intarray->valssize > 0);
4672
4673 /* clear the used part of array */
4674 BMSclearMemoryArray(&intarray->vals[intarray->minusedidx - intarray->firstidx],
4675 intarray->maxusedidx - intarray->minusedidx + 1); /*lint !e866*/
4676
4677 /* mark the array cleared */
4678 intarray->minusedidx = INT_MAX;
4679 intarray->maxusedidx = INT_MIN;
4680 }
4681 assert(intarray->minusedidx == INT_MAX);
4682 assert(intarray->maxusedidx == INT_MIN);
4683
4684 return SCIP_OKAY;
4685}
4686
4687/** gets value of entry in dynamic array */
4689 SCIP_INTARRAY* intarray, /**< dynamic int array */
4690 int idx /**< array index to get value for */
4691 )
4692{
4693 assert(intarray != NULL);
4694 assert(idx >= 0);
4695
4696 if( idx < intarray->minusedidx || idx > intarray->maxusedidx )
4697 return 0;
4698 else
4699 {
4700 assert(intarray->vals != NULL);
4701 assert(idx - intarray->firstidx >= 0);
4702 assert(idx - intarray->firstidx < intarray->valssize);
4703
4704 return intarray->vals[idx - intarray->firstidx];
4705 }
4706}
4707
4708/** sets value of entry in dynamic array */
4710 SCIP_INTARRAY* intarray, /**< dynamic int array */
4711 int arraygrowinit, /**< initial size of array */
4712 SCIP_Real arraygrowfac, /**< growing factor of array */
4713 int idx, /**< array index to set value for */
4714 int val /**< value to set array index to */
4715 )
4716{
4717 assert(intarray != NULL);
4718 assert(idx >= 0);
4719
4720 SCIPdebugMessage("setting intarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %d\n",
4721 (void*)intarray, intarray->firstidx, intarray->valssize, intarray->minusedidx, intarray->maxusedidx, idx, val);
4722
4723 if( val != 0 )
4724 {
4725 /* extend array to be able to store the index */
4726 SCIP_CALL( SCIPintarrayExtend(intarray, arraygrowinit, arraygrowfac, idx, idx) );
4727 assert(idx >= intarray->firstidx);
4728 assert(idx < intarray->firstidx + intarray->valssize);
4729
4730 /* set the array value of the index */
4731 intarray->vals[idx - intarray->firstidx] = val;
4732
4733 /* update min/maxusedidx */
4734 intarray->minusedidx = MIN(intarray->minusedidx, idx);
4735 intarray->maxusedidx = MAX(intarray->maxusedidx, idx);
4736 }
4737 else if( idx >= intarray->firstidx && idx < intarray->firstidx + intarray->valssize )
4738 {
4739 /* set the array value of the index to zero */
4740 intarray->vals[idx - intarray->firstidx] = 0;
4741
4742 /* check, if we can tighten the min/maxusedidx */
4743 if( idx == intarray->minusedidx )
4744 {
4745 assert(intarray->maxusedidx >= 0);
4746 assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4747 do
4748 {
4749 intarray->minusedidx++;
4750 }
4751 while( intarray->minusedidx <= intarray->maxusedidx
4752 && intarray->vals[intarray->minusedidx - intarray->firstidx] == 0 );
4753 if( intarray->minusedidx > intarray->maxusedidx )
4754 {
4755 intarray->minusedidx = INT_MAX;
4756 intarray->maxusedidx = INT_MIN;
4757 }
4758 }
4759 else if( idx == intarray->maxusedidx )
4760 {
4761 assert(intarray->minusedidx >= 0);
4762 assert(intarray->minusedidx < intarray->maxusedidx);
4763 assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4764 do
4765 {
4766 intarray->maxusedidx--;
4767 assert(intarray->minusedidx <= intarray->maxusedidx);
4768 }
4769 while( intarray->vals[intarray->maxusedidx - intarray->firstidx] == 0 );
4770 }
4771 }
4772
4773 return SCIP_OKAY;
4774}
4775
4776/** increases value of entry in dynamic array */
4778 SCIP_INTARRAY* intarray, /**< dynamic int array */
4779 int arraygrowinit, /**< initial size of array */
4780 SCIP_Real arraygrowfac, /**< growing factor of array */
4781 int idx, /**< array index to increase value for */
4782 int incval /**< value to increase array index */
4783 )
4784{
4785 return SCIPintarraySetVal(intarray, arraygrowinit, arraygrowfac, idx, SCIPintarrayGetVal(intarray, idx) + incval);
4786}
4787
4788/** returns the minimal index of all stored non-zero elements */
4790 SCIP_INTARRAY* intarray /**< dynamic int array */
4791 )
4792{
4793 assert(intarray != NULL);
4794
4795 return intarray->minusedidx;
4796}
4797
4798/** returns the maximal index of all stored non-zero elements */
4800 SCIP_INTARRAY* intarray /**< dynamic int array */
4801 )
4802{
4803 assert(intarray != NULL);
4804
4805 return intarray->maxusedidx;
4806}
4807
4808
4809/** creates a dynamic array of bool values */
4811 SCIP_BOOLARRAY** boolarray, /**< pointer to store the bool array */
4812 BMS_BLKMEM* blkmem /**< block memory */
4813 )
4814{
4815 assert(boolarray != NULL);
4816 assert(blkmem != NULL);
4817
4818 SCIP_ALLOC( BMSallocBlockMemory(blkmem, boolarray) );
4819 (*boolarray)->blkmem = blkmem;
4820 (*boolarray)->vals = NULL;
4821 (*boolarray)->valssize = 0;
4822 (*boolarray)->firstidx = -1;
4823 (*boolarray)->minusedidx = INT_MAX;
4824 (*boolarray)->maxusedidx = INT_MIN;
4825
4826 return SCIP_OKAY;
4827}
4828
4829/** creates a copy of a dynamic array of bool values */
4831 SCIP_BOOLARRAY** boolarray, /**< pointer to store the copied bool array */
4832 BMS_BLKMEM* blkmem, /**< block memory */
4833 SCIP_BOOLARRAY* sourceboolarray /**< dynamic bool array to copy */
4834 )
4835{
4836 assert(boolarray != NULL);
4837 assert(sourceboolarray != NULL);
4838
4839 SCIP_CALL( SCIPboolarrayCreate(boolarray, blkmem) );
4840 if( sourceboolarray->valssize > 0 )
4841 {
4842 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*boolarray)->vals, sourceboolarray->vals,
4843 sourceboolarray->valssize) );
4844 }
4845 (*boolarray)->valssize = sourceboolarray->valssize;
4846 (*boolarray)->firstidx = sourceboolarray->firstidx;
4847 (*boolarray)->minusedidx = sourceboolarray->minusedidx;
4848 (*boolarray)->maxusedidx = sourceboolarray->maxusedidx;
4849
4850 return SCIP_OKAY;
4851}
4852
4853/** frees a dynamic array of bool values */
4855 SCIP_BOOLARRAY** boolarray /**< pointer to the bool array */
4856 )
4857{
4858 assert(boolarray != NULL);
4859 assert(*boolarray != NULL);
4860
4861 BMSfreeBlockMemoryArrayNull((*boolarray)->blkmem, &(*boolarray)->vals, (*boolarray)->valssize);
4862 BMSfreeBlockMemory((*boolarray)->blkmem, boolarray);
4863
4864 return SCIP_OKAY;
4865}
4866
4867/** extends dynamic array to be able to store indices from minidx to maxidx */
4869 SCIP_BOOLARRAY* boolarray, /**< dynamic bool array */
4870 int arraygrowinit, /**< initial size of array */
4871 SCIP_Real arraygrowfac, /**< growing factor of array */
4872 int minidx, /**< smallest index to allocate storage for */
4873 int maxidx /**< largest index to allocate storage for */
4874 )
4875{
4876 int nused;
4877 int nfree;
4878 int newfirstidx;
4879 int i;
4880
4881 assert(boolarray != NULL);
4882 assert(boolarray->minusedidx == INT_MAX || boolarray->firstidx >= 0);
4883 assert(boolarray->maxusedidx == INT_MIN || boolarray->firstidx >= 0);
4884 assert(boolarray->minusedidx == INT_MAX || boolarray->minusedidx >= boolarray->firstidx);
4885 assert(boolarray->maxusedidx == INT_MIN || boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
4886 assert(0 <= minidx);
4887 assert(minidx <= maxidx);
4888
4889 minidx = MIN(minidx, boolarray->minusedidx);
4890 maxidx = MAX(maxidx, boolarray->maxusedidx);
4891 assert(0 <= minidx);
4892 assert(minidx <= maxidx);
4893
4894 SCIPdebugMessage("extending boolarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
4895 (void*)boolarray, boolarray->firstidx, boolarray->valssize, boolarray->minusedidx, boolarray->maxusedidx, minidx, maxidx);
4896
4897 /* check, whether we have to allocate additional memory, or shift the array */
4898 nused = maxidx - minidx + 1;
4899 if( nused > boolarray->valssize )
4900 {
4901 SCIP_Bool* newvals;
4902 int newvalssize;
4903
4904 /* allocate new memory storage */
4905 newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
4906 SCIP_ALLOC( BMSallocBlockMemoryArray(boolarray->blkmem, &newvals, newvalssize) );
4907 nfree = newvalssize - nused;
4908 newfirstidx = minidx - nfree/2;
4909 newfirstidx = MAX(newfirstidx, 0);
4910 assert(newfirstidx <= minidx);
4911 assert(maxidx < newfirstidx + newvalssize);
4912
4913 /* initialize memory array by copying old values and setting new values to zero */
4914 if( boolarray->firstidx != -1 )
4915 {
4916 for( i = 0; i < boolarray->minusedidx - newfirstidx; ++i )
4917 newvals[i] = FALSE;
4918
4919 /* check for possible overflow or negative value */
4920 assert(boolarray->maxusedidx - boolarray->minusedidx + 1 > 0);
4921
4922 BMScopyMemoryArray(&newvals[boolarray->minusedidx - newfirstidx],
4923 &boolarray->vals[boolarray->minusedidx - boolarray->firstidx],
4924 boolarray->maxusedidx - boolarray->minusedidx + 1); /*lint !e866 !e776*/
4925 for( i = boolarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
4926 newvals[i] = FALSE;
4927 }
4928 else
4929 {
4930 for( i = 0; i < newvalssize; ++i )
4931 newvals[i] = FALSE;
4932 }
4933
4934 /* free old memory storage, and set the new array parameters */
4935 BMSfreeBlockMemoryArrayNull(boolarray->blkmem, &boolarray->vals, boolarray->valssize);
4936 boolarray->vals = newvals;
4937 boolarray->valssize = newvalssize;
4938 boolarray->firstidx = newfirstidx;
4939 }
4940 else if( boolarray->firstidx == -1 )
4941 {
4942 /* a sufficiently large memory storage exists, but it was cleared */
4943 nfree = boolarray->valssize - nused;
4944 assert(nfree >= 0);
4945 boolarray->firstidx = minidx - nfree/2;
4946 assert(boolarray->firstidx <= minidx);
4947 assert(maxidx < boolarray->firstidx + boolarray->valssize);
4948#ifndef NDEBUG
4949 for( i = 0; i < boolarray->valssize; ++i )
4950 assert(boolarray->vals[i] == FALSE);
4951#endif
4952 }
4953 else if( minidx < boolarray->firstidx )
4954 {
4955 /* a sufficiently large memory storage exists, but it has to be shifted to the right */
4956 nfree = boolarray->valssize - nused;
4957 assert(nfree >= 0);
4958 newfirstidx = minidx - nfree/2;
4959 newfirstidx = MAX(newfirstidx, 0);
4960 assert(newfirstidx <= minidx);
4961 assert(maxidx < newfirstidx + boolarray->valssize);
4962
4963 if( boolarray->minusedidx <= boolarray->maxusedidx )
4964 {
4965 int shift;
4966
4967 assert(boolarray->firstidx <= boolarray->minusedidx);
4968 assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
4969
4970 /* shift used part of array to the right */
4971 shift = boolarray->firstidx - newfirstidx;
4972 assert(shift > 0);
4973 for( i = boolarray->maxusedidx - boolarray->firstidx; i >= boolarray->minusedidx - boolarray->firstidx; --i )
4974 {
4975 assert(0 <= i + shift && i + shift < boolarray->valssize);
4976 boolarray->vals[i + shift] = boolarray->vals[i];
4977 }
4978 /* clear the formerly used head of the array */
4979 for( i = 0; i < shift; ++i )
4980 boolarray->vals[boolarray->minusedidx - boolarray->firstidx + i] = FALSE;
4981 }
4982 boolarray->firstidx = newfirstidx;
4983 }
4984 else if( maxidx >= boolarray->firstidx + boolarray->valssize )
4985 {
4986 /* a sufficiently large memory storage exists, but it has to be shifted to the left */
4987 nfree = boolarray->valssize - nused;
4988 assert(nfree >= 0);
4989 newfirstidx = minidx - nfree/2;
4990 newfirstidx = MAX(newfirstidx, 0);
4991 assert(newfirstidx <= minidx);
4992 assert(maxidx < newfirstidx + boolarray->valssize);
4993
4994 if( boolarray->minusedidx <= boolarray->maxusedidx )
4995 {
4996 int shift;
4997
4998 assert(boolarray->firstidx <= boolarray->minusedidx);
4999 assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
5000
5001 /* shift used part of array to the left */
5002 shift = newfirstidx - boolarray->firstidx;
5003 assert(shift > 0);
5004
5005 assert(0 <= boolarray->minusedidx - boolarray->firstidx - shift);
5006 assert(boolarray->maxusedidx - boolarray->firstidx - shift < boolarray->valssize);
5007 BMSmoveMemoryArray(&(boolarray->vals[boolarray->minusedidx - boolarray->firstidx - shift]),
5008 &(boolarray->vals[boolarray->minusedidx - boolarray->firstidx]),
5009 boolarray->maxusedidx - boolarray->minusedidx + 1); /*lint !e866*/
5010
5011 /* clear the formerly used tail of the array */
5012 for( i = 0; i < shift; ++i )
5013 boolarray->vals[boolarray->maxusedidx - boolarray->firstidx - i] = FALSE;
5014 }
5015 boolarray->firstidx = newfirstidx;
5016 }
5017
5018 assert(minidx >= boolarray->firstidx);
5019 assert(maxidx < boolarray->firstidx + boolarray->valssize);
5020
5021 return SCIP_OKAY;
5022}
5023
5024/** clears a dynamic bool array */
5026 SCIP_BOOLARRAY* boolarray /**< dynamic bool array */
5027 )
5028{
5029 assert(boolarray != NULL);
5030
5031 SCIPdebugMessage("clearing boolarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
5032 (void*)boolarray, boolarray->firstidx, boolarray->valssize, boolarray->minusedidx, boolarray->maxusedidx);
5033
5034 if( boolarray->minusedidx <= boolarray->maxusedidx )
5035 {
5036 assert(boolarray->firstidx <= boolarray->minusedidx);
5037 assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
5038 assert(boolarray->firstidx != -1);
5039 assert(boolarray->valssize > 0);
5040
5041 /* clear the used part of array */
5042 BMSclearMemoryArray(&boolarray->vals[boolarray->minusedidx - boolarray->firstidx],
5043 boolarray->maxusedidx - boolarray->minusedidx + 1); /*lint !e866*/
5044
5045 /* mark the array cleared */
5046 boolarray->minusedidx = INT_MAX;
5047 boolarray->maxusedidx = INT_MIN;
5048 }
5049 assert(boolarray->minusedidx == INT_MAX);
5050 assert(boolarray->maxusedidx == INT_MIN);
5051
5052 return SCIP_OKAY;
5053}
5054
5055/** gets value of entry in dynamic array */
5057 SCIP_BOOLARRAY* boolarray, /**< dynamic bool array */
5058 int idx /**< array index to get value for */
5059 )
5060{
5061 assert(boolarray != NULL);
5062 assert(idx >= 0);
5063
5064 if( idx < boolarray->minusedidx || idx > boolarray->maxusedidx )
5065 return FALSE;
5066 else
5067 {
5068 assert(boolarray->vals != NULL);
5069 assert(idx - boolarray->firstidx >= 0);
5070 assert(idx - boolarray->firstidx < boolarray->valssize);
5071
5072 return boolarray->vals[idx - boolarray->firstidx];
5073 }
5074}
5075
5076/** sets value of entry in dynamic array */
5078 SCIP_BOOLARRAY* boolarray, /**< dynamic bool array */
5079 int arraygrowinit, /**< initial size of array */
5080 SCIP_Real arraygrowfac, /**< growing factor of array */
5081 int idx, /**< array index to set value for */
5082 SCIP_Bool val /**< value to set array index to */
5083 )
5084{
5085 assert(boolarray != NULL);
5086 assert(idx >= 0);
5087
5088 SCIPdebugMessage("setting boolarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %u\n",
5089 (void*)boolarray, boolarray->firstidx, boolarray->valssize, boolarray->minusedidx, boolarray->maxusedidx, idx, val);
5090
5091 if( val != FALSE )
5092 {
5093 /* extend array to be able to store the index */
5094 SCIP_CALL( SCIPboolarrayExtend(boolarray, arraygrowinit, arraygrowfac, idx, idx) );
5095 assert(idx >= boolarray->firstidx);
5096 assert(idx < boolarray->firstidx + boolarray->valssize);
5097
5098 /* set the array value of the index */
5099 boolarray->vals[idx - boolarray->firstidx] = val;
5100
5101 /* update min/maxusedidx */
5102 boolarray->minusedidx = MIN(boolarray->minusedidx, idx);
5103 boolarray->maxusedidx = MAX(boolarray->maxusedidx, idx);
5104 }
5105 else if( idx >= boolarray->firstidx && idx < boolarray->firstidx + boolarray->valssize )
5106 {
5107 /* set the array value of the index to zero */
5108 boolarray->vals[idx - boolarray->firstidx] = FALSE;
5109
5110 /* check, if we can tighten the min/maxusedidx */
5111 if( idx == boolarray->minusedidx )
5112 {
5113 assert(boolarray->maxusedidx >= 0);
5114 assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
5115 do
5116 {
5117 boolarray->minusedidx++;
5118 }
5119 while( boolarray->minusedidx <= boolarray->maxusedidx
5120 && boolarray->vals[boolarray->minusedidx - boolarray->firstidx] == FALSE );
5121 if( boolarray->minusedidx > boolarray->maxusedidx )
5122 {
5123 boolarray->minusedidx = INT_MAX;
5124 boolarray->maxusedidx = INT_MIN;
5125 }
5126 }
5127 else if( idx == boolarray->maxusedidx )
5128 {
5129 assert(boolarray->minusedidx >= 0);
5130 assert(boolarray->minusedidx < boolarray->maxusedidx);
5131 assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
5132 do
5133 {
5134 boolarray->maxusedidx--;
5135 assert(boolarray->minusedidx <= boolarray->maxusedidx);
5136 }
5137 while( boolarray->vals[boolarray->maxusedidx - boolarray->firstidx] == FALSE );
5138 }
5139 }
5140
5141 return SCIP_OKAY;
5142}
5143
5144/** returns the minimal index of all stored non-zero elements */
5146 SCIP_BOOLARRAY* boolarray /**< dynamic bool array */
5147 )
5148{
5149 assert(boolarray != NULL);
5150
5151 return boolarray->minusedidx;
5152}
5153
5154/** returns the maximal index of all stored non-zero elements */
5156 SCIP_BOOLARRAY* boolarray /**< dynamic bool array */
5157 )
5158{
5159 assert(boolarray != NULL);
5160
5161 return boolarray->maxusedidx;
5162}
5163
5164
5165/** creates a dynamic array of pointer values */
5167 SCIP_PTRARRAY** ptrarray, /**< pointer to store the ptr array */
5168 BMS_BLKMEM* blkmem /**< block memory */
5169 )
5170{
5171 assert(ptrarray != NULL);
5172 assert(blkmem != NULL);
5173
5174 SCIP_ALLOC( BMSallocBlockMemory(blkmem, ptrarray) );
5175 (*ptrarray)->blkmem = blkmem;
5176 (*ptrarray)->vals = NULL;
5177 (*ptrarray)->valssize = 0;
5178 (*ptrarray)->firstidx = -1;
5179 (*ptrarray)->minusedidx = INT_MAX;
5180 (*ptrarray)->maxusedidx = INT_MIN;
5181
5182 return SCIP_OKAY;
5183}
5184
5185/** creates a copy of a dynamic array of pointer values */
5187 SCIP_PTRARRAY** ptrarray, /**< pointer to store the copied ptr array */
5188 BMS_BLKMEM* blkmem, /**< block memory */
5189 SCIP_PTRARRAY* sourceptrarray /**< dynamic ptr array to copy */
5190 )
5191{
5192 assert(ptrarray != NULL);
5193 assert(sourceptrarray != NULL);
5194
5195 SCIP_CALL( SCIPptrarrayCreate(ptrarray, blkmem) );
5196 if( sourceptrarray->valssize > 0 )
5197 {
5198 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*ptrarray)->vals, sourceptrarray->vals, sourceptrarray->valssize) );
5199 }
5200 (*ptrarray)->valssize = sourceptrarray->valssize;
5201 (*ptrarray)->firstidx = sourceptrarray->firstidx;
5202 (*ptrarray)->minusedidx = sourceptrarray->minusedidx;
5203 (*ptrarray)->maxusedidx = sourceptrarray->maxusedidx;
5204
5205 return SCIP_OKAY;
5206}
5207
5208/** frees a dynamic array of pointer values */
5210 SCIP_PTRARRAY** ptrarray /**< pointer to the ptr array */
5211 )
5212{
5213 assert(ptrarray != NULL);
5214 assert(*ptrarray != NULL);
5215
5216 BMSfreeBlockMemoryArrayNull((*ptrarray)->blkmem, &(*ptrarray)->vals, (*ptrarray)->valssize);
5217 BMSfreeBlockMemory((*ptrarray)->blkmem, ptrarray);
5218
5219 return SCIP_OKAY;
5220}
5221
5222/** extends dynamic array to be able to store indices from minidx to maxidx */
5224 SCIP_PTRARRAY* ptrarray, /**< dynamic ptr array */
5225 int arraygrowinit, /**< initial size of array */
5226 SCIP_Real arraygrowfac, /**< growing factor of array */
5227 int minidx, /**< smallest index to allocate storage for */
5228 int maxidx /**< largest index to allocate storage for */
5229 )
5230{
5231 int nused;
5232 int nfree;
5233 int newfirstidx;
5234 int i;
5235
5236 assert(ptrarray != NULL);
5237 assert(ptrarray->minusedidx == INT_MAX || ptrarray->firstidx >= 0);
5238 assert(ptrarray->maxusedidx == INT_MIN || ptrarray->firstidx >= 0);
5239 assert(ptrarray->minusedidx == INT_MAX || ptrarray->minusedidx >= ptrarray->firstidx);
5240 assert(ptrarray->maxusedidx == INT_MIN || ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5241 assert(0 <= minidx);
5242 assert(minidx <= maxidx);
5243
5244 minidx = MIN(minidx, ptrarray->minusedidx);
5245 maxidx = MAX(maxidx, ptrarray->maxusedidx);
5246 assert(0 <= minidx);
5247 assert(minidx <= maxidx);
5248
5249 SCIPdebugMessage("extending ptrarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
5250 (void*)ptrarray, ptrarray->firstidx, ptrarray->valssize, ptrarray->minusedidx, ptrarray->maxusedidx, minidx, maxidx);
5251
5252 /* check, whether we have to allocate additional memory, or shift the array */
5253 nused = maxidx - minidx + 1;
5254 if( nused > ptrarray->valssize )
5255 {
5256 void** newvals;
5257 int newvalssize;
5258
5259 /* allocate new memory storage */
5260 newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
5261 SCIP_ALLOC( BMSallocBlockMemoryArray(ptrarray->blkmem, &newvals, newvalssize) );
5262 nfree = newvalssize - nused;
5263 newfirstidx = minidx - nfree/2;
5264 newfirstidx = MAX(newfirstidx, 0);
5265 assert(newfirstidx <= minidx);
5266 assert(maxidx < newfirstidx + newvalssize);
5267
5268 /* initialize memory array by copying old values and setting new values to zero */
5269 if( ptrarray->firstidx != -1 )
5270 {
5271 for( i = 0; i < ptrarray->minusedidx - newfirstidx; ++i )
5272 newvals[i] = NULL;
5273
5274 /* check for possible overflow or negative value */
5275 assert(ptrarray->maxusedidx - ptrarray->minusedidx + 1 > 0);
5276
5277 BMScopyMemoryArray(&newvals[ptrarray->minusedidx - newfirstidx],
5278 &(ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx]),
5279 ptrarray->maxusedidx - ptrarray->minusedidx + 1); /*lint !e866 !e776*/
5280 for( i = ptrarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
5281 newvals[i] = NULL;
5282 }
5283 else
5284 {
5285 for( i = 0; i < newvalssize; ++i )
5286 newvals[i] = NULL;
5287 }
5288
5289 /* free old memory storage, and set the new array parameters */
5290 BMSfreeBlockMemoryArrayNull(ptrarray->blkmem, &ptrarray->vals, ptrarray->valssize);
5291 ptrarray->vals = newvals;
5292 ptrarray->valssize = newvalssize;
5293 ptrarray->firstidx = newfirstidx;
5294 }
5295 else if( ptrarray->firstidx == -1 )
5296 {
5297 /* a sufficiently large memory storage exists, but it was cleared */
5298 nfree = ptrarray->valssize - nused;
5299 assert(nfree >= 0);
5300 ptrarray->firstidx = minidx - nfree/2;
5301 assert(ptrarray->firstidx <= minidx);
5302 assert(maxidx < ptrarray->firstidx + ptrarray->valssize);
5303#ifndef NDEBUG
5304 for( i = 0; i < ptrarray->valssize; ++i )
5305 assert(ptrarray->vals[i] == NULL);
5306#endif
5307 }
5308 else if( minidx < ptrarray->firstidx )
5309 {
5310 /* a sufficiently large memory storage exists, but it has to be shifted to the right */
5311 nfree = ptrarray->valssize - nused;
5312 assert(nfree >= 0);
5313 newfirstidx = minidx - nfree/2;
5314 newfirstidx = MAX(newfirstidx, 0);
5315 assert(newfirstidx <= minidx);
5316 assert(maxidx < newfirstidx + ptrarray->valssize);
5317
5318 if( ptrarray->minusedidx <= ptrarray->maxusedidx )
5319 {
5320 int shift;
5321
5322 assert(ptrarray->firstidx <= ptrarray->minusedidx);
5323 assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5324
5325 /* shift used part of array to the right */
5326 shift = ptrarray->firstidx - newfirstidx;
5327 assert(shift > 0);
5328 for( i = ptrarray->maxusedidx - ptrarray->firstidx; i >= ptrarray->minusedidx - ptrarray->firstidx; --i )
5329 {
5330 assert(0 <= i + shift && i + shift < ptrarray->valssize);
5331 ptrarray->vals[i + shift] = ptrarray->vals[i];
5332 }
5333 /* clear the formerly used head of the array */
5334 for( i = 0; i < shift; ++i )
5335 ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx + i] = NULL;
5336 }
5337 ptrarray->firstidx = newfirstidx;
5338 }
5339 else if( maxidx >= ptrarray->firstidx + ptrarray->valssize )
5340 {
5341 /* a sufficiently large memory storage exists, but it has to be shifted to the left */
5342 nfree = ptrarray->valssize - nused;
5343 assert(nfree >= 0);
5344 newfirstidx = minidx - nfree/2;
5345 newfirstidx = MAX(newfirstidx, 0);
5346 assert(newfirstidx <= minidx);
5347 assert(maxidx < newfirstidx + ptrarray->valssize);
5348
5349 if( ptrarray->minusedidx <= ptrarray->maxusedidx )
5350 {
5351 int shift;
5352
5353 assert(ptrarray->firstidx <= ptrarray->minusedidx);
5354 assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5355
5356 /* shift used part of array to the left */
5357 shift = newfirstidx - ptrarray->firstidx;
5358 assert(shift > 0);
5359 for( i = ptrarray->minusedidx - ptrarray->firstidx; i <= ptrarray->maxusedidx - ptrarray->firstidx; ++i )
5360 {
5361 assert(0 <= i - shift && i - shift < ptrarray->valssize);
5362 ptrarray->vals[i - shift] = ptrarray->vals[i];
5363 }
5364 /* clear the formerly used tail of the array */
5365 for( i = 0; i < shift; ++i )
5366 ptrarray->vals[ptrarray->maxusedidx - ptrarray->firstidx - i] = NULL;
5367 }
5368 ptrarray->firstidx = newfirstidx;
5369 }
5370
5371 assert(minidx >= ptrarray->firstidx);
5372 assert(maxidx < ptrarray->firstidx + ptrarray->valssize);
5373
5374 return SCIP_OKAY;
5375}
5376
5377/** clears a dynamic pointer array */
5379 SCIP_PTRARRAY* ptrarray /**< dynamic ptr array */
5380 )
5381{
5382 assert(ptrarray != NULL);
5383
5384 SCIPdebugMessage("clearing ptrarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
5385 (void*)ptrarray, ptrarray->firstidx, ptrarray->valssize, ptrarray->minusedidx, ptrarray->maxusedidx);
5386
5387 if( ptrarray->minusedidx <= ptrarray->maxusedidx )
5388 {
5389 assert(ptrarray->firstidx <= ptrarray->minusedidx);
5390 assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5391 assert(ptrarray->firstidx != -1);
5392 assert(ptrarray->valssize > 0);
5393
5394 /* clear the used part of array */
5395 BMSclearMemoryArray(&ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx],
5396 ptrarray->maxusedidx - ptrarray->minusedidx + 1); /*lint !e866*/
5397
5398 /* mark the array cleared */
5399 ptrarray->minusedidx = INT_MAX;
5400 ptrarray->maxusedidx = INT_MIN;
5401 }
5402 assert(ptrarray->minusedidx == INT_MAX);
5403 assert(ptrarray->maxusedidx == INT_MIN);
5404
5405 return SCIP_OKAY;
5406}
5407
5408/** gets value of entry in dynamic array */
5410 SCIP_PTRARRAY* ptrarray, /**< dynamic ptr array */
5411 int idx /**< array index to get value for */
5412 )
5413{
5414 assert(ptrarray != NULL);
5415 assert(idx >= 0);
5416
5417 if( idx < ptrarray->minusedidx || idx > ptrarray->maxusedidx )
5418 return NULL;
5419 else
5420 {
5421 assert(ptrarray->vals != NULL);
5422 assert(idx - ptrarray->firstidx >= 0);
5423 assert(idx - ptrarray->firstidx < ptrarray->valssize);
5424
5425 return ptrarray->vals[idx - ptrarray->firstidx];
5426 }
5427}
5428
5429/** sets value of entry in dynamic array */
5431 SCIP_PTRARRAY* ptrarray, /**< dynamic ptr array */
5432 int arraygrowinit, /**< initial size of array */
5433 SCIP_Real arraygrowfac, /**< growing factor of array */
5434 int idx, /**< array index to set value for */
5435 void* val /**< value to set array index to */
5436 )
5437{
5438 assert(ptrarray != NULL);
5439 assert(idx >= 0);
5440
5441 SCIPdebugMessage("setting ptrarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %p\n",
5442 (void*)ptrarray, ptrarray->firstidx, ptrarray->valssize, ptrarray->minusedidx, ptrarray->maxusedidx, idx, val);
5443
5444 if( val != NULL )
5445 {
5446 /* extend array to be able to store the index */
5447 SCIP_CALL( SCIPptrarrayExtend(ptrarray, arraygrowinit, arraygrowfac, idx, idx) );
5448 assert(idx >= ptrarray->firstidx);
5449 assert(idx < ptrarray->firstidx + ptrarray->valssize);
5450
5451 /* set the array value of the index */
5452 ptrarray->vals[idx - ptrarray->firstidx] = val;
5453
5454 /* update min/maxusedidx */
5455 ptrarray->minusedidx = MIN(ptrarray->minusedidx, idx);
5456 ptrarray->maxusedidx = MAX(ptrarray->maxusedidx, idx);
5457 }
5458 else if( idx >= ptrarray->firstidx && idx < ptrarray->firstidx + ptrarray->valssize )
5459 {
5460 /* set the array value of the index to zero */
5461 ptrarray->vals[idx - ptrarray->firstidx] = NULL;
5462
5463 /* check, if we can tighten the min/maxusedidx */
5464 if( idx == ptrarray->minusedidx )
5465 {
5466 assert(ptrarray->maxusedidx >= 0);
5467 assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5468 do
5469 {
5470 ptrarray->minusedidx++;
5471 }
5472 while( ptrarray->minusedidx <= ptrarray->maxusedidx
5473 && ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx] == NULL );
5474 if( ptrarray->minusedidx > ptrarray->maxusedidx )
5475 {
5476 ptrarray->minusedidx = INT_MAX;
5477 ptrarray->maxusedidx = INT_MIN;
5478 }
5479 }
5480 else if( idx == ptrarray->maxusedidx )
5481 {
5482 assert(ptrarray->minusedidx >= 0);
5483 assert(ptrarray->minusedidx < ptrarray->maxusedidx);
5484 assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5485 do
5486 {
5487 ptrarray->maxusedidx--;
5488 assert(ptrarray->minusedidx <= ptrarray->maxusedidx);
5489 }
5490 while( ptrarray->vals[ptrarray->maxusedidx - ptrarray->firstidx] == NULL );
5491 }
5492 }
5493
5494 return SCIP_OKAY;
5495}
5496
5497/** returns the minimal index of all stored non-zero elements */
5499 SCIP_PTRARRAY* ptrarray /**< dynamic ptr array */
5500 )
5501{
5502 assert(ptrarray != NULL);
5503
5504 return ptrarray->minusedidx;
5505}
5506
5507/** returns the maximal index of all stored non-zero elements */
5509 SCIP_PTRARRAY* ptrarray /**< dynamic ptr array */
5510 )
5511{
5512 assert(ptrarray != NULL);
5513
5514 return ptrarray->maxusedidx;
5515}
5516
5517
5518/*
5519 * Sorting algorithms
5520 */
5521
5522/** default comparer for integers */
5524{
5525 int value1;
5526 int value2;
5527
5528 value1 = (int)(size_t)elem1;
5529 value2 = (int)(size_t)elem2;
5530
5531 if( value1 < value2 )
5532 return -1;
5533
5534 if( value2 < value1 )
5535 return 1;
5536
5537 return 0;
5538}
5539
5540/** implements argsort
5541 *
5542 * The data pointer is a lookup array of integers.
5543 */
5544SCIP_DECL_SORTINDCOMP(SCIPsortArgsortInt)
5545{
5546 int* args;
5547 args = (int*) dataptr;
5548
5549 if( args[ind1] < args[ind2] )
5550 return -1;
5551
5552 if( args[ind1] > args[ind2] )
5553 return 1;
5554
5555 return 0;
5556}
5557
5558
5559/** implements argsort
5560 *
5561 * The data pointer is a lookup array, which are pointer arrays.
5562 */
5563SCIP_DECL_SORTINDCOMP(SCIPsortArgsortPtr)
5564{
5565 void** args;
5566 args = (void*) dataptr;
5567
5568 if( args[ind1] < args[ind2] )
5569 return -1;
5570
5571 if( args[ind1] > args[ind2] )
5572 return 1;
5573
5574 return 0;
5575}
5576
5577
5578/* first all upwards-sorting methods */
5579
5580/** sort an indexed element set in non-decreasing order, resulting in a permutation index array */
5582 int* perm, /**< pointer to store the resulting permutation */
5583 SCIP_DECL_SORTINDCOMP((*indcomp)), /**< data element comparator */
5584 void* dataptr, /**< pointer to data field that is given to the external compare method */
5585 int len /**< number of elements to be sorted (valid index range) */
5586 )
5587{
5588 int pos;
5589
5590 assert(indcomp != NULL);
5591 assert(len == 0 || perm != NULL);
5592
5593 /* create identity permutation */
5594 for( pos = 0; pos < len; ++pos )
5595 perm[pos] = pos;
5596
5597 SCIPsortInd(perm, indcomp, dataptr, len);
5598}
5599
5600/* SCIPsortInd(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5601#define SORTTPL_NAMEEXT Ind
5602#define SORTTPL_KEYTYPE int
5603#define SORTTPL_INDCOMP
5604#include "scip/sorttpl.c" /*lint !e451*/
5605
5606
5607/* SCIPsortPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5608#define SORTTPL_NAMEEXT Ptr
5609#define SORTTPL_KEYTYPE void*
5610#define SORTTPL_PTRCOMP
5611#include "scip/sorttpl.c" /*lint !e451*/
5612
5613
5614/* SCIPsortPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5615#define SORTTPL_NAMEEXT PtrPtr
5616#define SORTTPL_KEYTYPE void*
5617#define SORTTPL_FIELD1TYPE void*
5618#define SORTTPL_PTRCOMP
5619#include "scip/sorttpl.c" /*lint !e451*/
5620
5621
5622/* SCIPsortPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5623#define SORTTPL_NAMEEXT PtrReal
5624#define SORTTPL_KEYTYPE void*
5625#define SORTTPL_FIELD1TYPE SCIP_Real
5626#define SORTTPL_PTRCOMP
5627#include "scip/sorttpl.c" /*lint !e451*/
5628
5629
5630/* SCIPsortPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5631#define SORTTPL_NAMEEXT PtrInt
5632#define SORTTPL_KEYTYPE void*
5633#define SORTTPL_FIELD1TYPE int
5634#define SORTTPL_PTRCOMP
5635#include "scip/sorttpl.c" /*lint !e451*/
5636
5637
5638/* SCIPsortPtrBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5639#define SORTTPL_NAMEEXT PtrBool
5640#define SORTTPL_KEYTYPE void*
5641#define SORTTPL_FIELD1TYPE SCIP_Bool
5642#define SORTTPL_PTRCOMP
5643#include "scip/sorttpl.c" /*lint !e451*/
5644
5645
5646/* SCIPsortPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5647#define SORTTPL_NAMEEXT PtrIntInt
5648#define SORTTPL_KEYTYPE void*
5649#define SORTTPL_FIELD1TYPE int
5650#define SORTTPL_FIELD2TYPE int
5651#define SORTTPL_PTRCOMP
5652#include "scip/sorttpl.c" /*lint !e451*/
5653
5654
5655/* SCIPsortPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5656#define SORTTPL_NAMEEXT PtrRealInt
5657#define SORTTPL_KEYTYPE void*
5658#define SORTTPL_FIELD1TYPE SCIP_Real
5659#define SORTTPL_FIELD2TYPE int
5660#define SORTTPL_PTRCOMP
5661#include "scip/sorttpl.c" /*lint !e451*/
5662
5663/* SCIPsortPtrRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5664#define SORTTPL_NAMEEXT PtrRealRealInt
5665#define SORTTPL_KEYTYPE void*
5666#define SORTTPL_FIELD1TYPE SCIP_Real
5667#define SORTTPL_FIELD2TYPE SCIP_Real
5668#define SORTTPL_FIELD3TYPE int
5669#define SORTTPL_PTRCOMP
5670#include "scip/sorttpl.c" /*lint !e451*/
5671
5672/* SCIPsortPtrRealRealBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5673#define SORTTPL_NAMEEXT PtrRealRealBoolBool
5674#define SORTTPL_KEYTYPE void*
5675#define SORTTPL_FIELD1TYPE SCIP_Real
5676#define SORTTPL_FIELD2TYPE SCIP_Real
5677#define SORTTPL_FIELD3TYPE SCIP_Bool
5678#define SORTTPL_FIELD4TYPE SCIP_Bool
5679#define SORTTPL_PTRCOMP
5680#include "scip/sorttpl.c" /*lint !e451*/
5681
5682/* SCIPsortPtrRealRealIntBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5683#define SORTTPL_NAMEEXT PtrRealRealIntBool
5684#define SORTTPL_KEYTYPE void*
5685#define SORTTPL_FIELD1TYPE SCIP_Real
5686#define SORTTPL_FIELD2TYPE SCIP_Real
5687#define SORTTPL_FIELD3TYPE int
5688#define SORTTPL_FIELD4TYPE SCIP_Bool
5689#define SORTTPL_PTRCOMP
5690#include "scip/sorttpl.c" /*lint !e451*/
5691
5692/* SCIPsortPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5693#define SORTTPL_NAMEEXT PtrRealBool
5694#define SORTTPL_KEYTYPE void*
5695#define SORTTPL_FIELD1TYPE SCIP_Real
5696#define SORTTPL_FIELD2TYPE SCIP_Bool
5697#define SORTTPL_PTRCOMP
5698#include "scip/sorttpl.c" /*lint !e451*/
5699
5700
5701/* SCIPsortPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5702#define SORTTPL_NAMEEXT PtrPtrInt
5703#define SORTTPL_KEYTYPE void*
5704#define SORTTPL_FIELD1TYPE void*
5705#define SORTTPL_FIELD2TYPE int
5706#define SORTTPL_PTRCOMP
5707#include "scip/sorttpl.c" /*lint !e451*/
5708
5709
5710/* SCIPsortPtrPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5711#define SORTTPL_NAMEEXT PtrPtrReal
5712#define SORTTPL_KEYTYPE void*
5713#define SORTTPL_FIELD1TYPE void*
5714#define SORTTPL_FIELD2TYPE SCIP_Real
5715#define SORTTPL_PTRCOMP
5716#include "scip/sorttpl.c" /*lint !e451*/
5717
5718
5719/* SCIPsortPtrRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5720#define SORTTPL_NAMEEXT PtrRealIntInt
5721#define SORTTPL_KEYTYPE void*
5722#define SORTTPL_FIELD1TYPE SCIP_Real
5723#define SORTTPL_FIELD2TYPE int
5724#define SORTTPL_FIELD3TYPE int
5725#define SORTTPL_PTRCOMP
5726#include "scip/sorttpl.c" /*lint !e451*/
5727
5728
5729/* SCIPsortPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5730#define SORTTPL_NAMEEXT PtrPtrIntInt
5731#define SORTTPL_KEYTYPE void*
5732#define SORTTPL_FIELD1TYPE void*
5733#define SORTTPL_FIELD2TYPE int
5734#define SORTTPL_FIELD3TYPE int
5735#define SORTTPL_PTRCOMP
5736#include "scip/sorttpl.c" /*lint !e451*/
5737
5738
5739/* SCIPsortPtrPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5740#define SORTTPL_NAMEEXT PtrPtrRealInt
5741#define SORTTPL_KEYTYPE void*
5742#define SORTTPL_FIELD1TYPE void*
5743#define SORTTPL_FIELD2TYPE SCIP_Real
5744#define SORTTPL_FIELD3TYPE int
5745#define SORTTPL_PTRCOMP
5746#include "scip/sorttpl.c" /*lint !e451*/
5747
5748
5749/* SCIPsortPtrPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5750#define SORTTPL_NAMEEXT PtrPtrRealBool
5751#define SORTTPL_KEYTYPE void*
5752#define SORTTPL_FIELD1TYPE void*
5753#define SORTTPL_FIELD2TYPE SCIP_Real
5754#define SORTTPL_FIELD3TYPE SCIP_Bool
5755#define SORTTPL_PTRCOMP
5756#include "scip/sorttpl.c" /*lint !e451*/
5757
5758
5759/* SCIPsortPtrPtrLongInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5760#define SORTTPL_NAMEEXT PtrPtrLongInt
5761#define SORTTPL_KEYTYPE void*
5762#define SORTTPL_FIELD1TYPE void*
5763#define SORTTPL_FIELD2TYPE SCIP_Longint
5764#define SORTTPL_FIELD3TYPE int
5765#define SORTTPL_PTRCOMP
5766#include "scip/sorttpl.c" /*lint !e451*/
5767
5768
5769/* SCIPsortPtrPtrLongIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5770#define SORTTPL_NAMEEXT PtrPtrLongIntInt
5771#define SORTTPL_KEYTYPE void*
5772#define SORTTPL_FIELD1TYPE void*
5773#define SORTTPL_FIELD2TYPE SCIP_Longint
5774#define SORTTPL_FIELD3TYPE int
5775#define SORTTPL_FIELD4TYPE int
5776#define SORTTPL_PTRCOMP
5777#include "scip/sorttpl.c" /*lint !e451*/
5778
5779
5780/* SCIPsortReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5781#define SORTTPL_NAMEEXT Real
5782#define SORTTPL_KEYTYPE SCIP_Real
5783#include "scip/sorttpl.c" /*lint !e451*/
5784
5785
5786/* SCIPsortRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5787#define SORTTPL_NAMEEXT RealBoolPtr
5788#define SORTTPL_KEYTYPE SCIP_Real
5789#define SORTTPL_FIELD1TYPE SCIP_Bool
5790#define SORTTPL_FIELD2TYPE void*
5791#include "scip/sorttpl.c" /*lint !e451*/
5792
5793
5794/* SCIPsortRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5795#define SORTTPL_NAMEEXT RealPtr
5796#define SORTTPL_KEYTYPE SCIP_Real
5797#define SORTTPL_FIELD1TYPE void*
5798#include "scip/sorttpl.c" /*lint !e451*/
5799
5800
5801/* SCIPsortRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5802#define SORTTPL_NAMEEXT RealInt
5803#define SORTTPL_KEYTYPE SCIP_Real
5804#define SORTTPL_FIELD1TYPE int
5805#include "scip/sorttpl.c" /*lint !e451*/
5806
5807
5808/* SCIPsortRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5809#define SORTTPL_NAMEEXT RealIntInt
5810#define SORTTPL_KEYTYPE SCIP_Real
5811#define SORTTPL_FIELD1TYPE int
5812#define SORTTPL_FIELD2TYPE int
5813#include "scip/sorttpl.c" /*lint !e451*/
5814
5815
5816/* SCIPsortRealIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5817#define SORTTPL_NAMEEXT RealIntLong
5818#define SORTTPL_KEYTYPE SCIP_Real
5819#define SORTTPL_FIELD1TYPE int
5820#define SORTTPL_FIELD2TYPE SCIP_Longint
5821#include "scip/sorttpl.c" /*lint !e451*/
5822
5823
5824/* SCIPsortRealIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5825#define SORTTPL_NAMEEXT RealIntPtr
5826#define SORTTPL_KEYTYPE SCIP_Real
5827#define SORTTPL_FIELD1TYPE int
5828#define SORTTPL_FIELD2TYPE void*
5829#include "scip/sorttpl.c" /*lint !e451*/
5830
5831
5832/* SCIPsortRealPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5833#define SORTTPL_NAMEEXT RealPtrPtr
5834#define SORTTPL_KEYTYPE SCIP_Real
5835#define SORTTPL_FIELD1TYPE void*
5836#define SORTTPL_FIELD2TYPE void*
5837#include "scip/sorttpl.c" /*lint !e451*/
5838
5839
5840/* SCIPsortRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5841#define SORTTPL_NAMEEXT RealRealPtr
5842#define SORTTPL_KEYTYPE SCIP_Real
5843#define SORTTPL_FIELD1TYPE SCIP_Real
5844#define SORTTPL_FIELD2TYPE void*
5845#include "scip/sorttpl.c" /*lint !e451*/
5846
5847
5848/* SCIPsortRealLongRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5849#define SORTTPL_NAMEEXT RealLongRealInt
5850#define SORTTPL_KEYTYPE SCIP_Real
5851#define SORTTPL_FIELD1TYPE SCIP_Longint
5852#define SORTTPL_FIELD2TYPE SCIP_Real
5853#define SORTTPL_FIELD3TYPE int
5854#include "scip/sorttpl.c" /*lint !e451*/
5855
5856/* SCIPsortRealRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5857#define SORTTPL_NAMEEXT RealRealIntInt
5858#define SORTTPL_KEYTYPE SCIP_Real
5859#define SORTTPL_FIELD1TYPE SCIP_Real
5860#define SORTTPL_FIELD2TYPE int
5861#define SORTTPL_FIELD3TYPE int
5862#include "scip/sorttpl.c" /*lint !e451*/
5863
5864
5865/* SCIPsortRealRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5866#define SORTTPL_NAMEEXT RealRealRealInt
5867#define SORTTPL_KEYTYPE SCIP_Real
5868#define SORTTPL_FIELD1TYPE SCIP_Real
5869#define SORTTPL_FIELD2TYPE SCIP_Real
5870#define SORTTPL_FIELD3TYPE int
5871#include "scip/sorttpl.c" /*lint !e451*/
5872
5873
5874/* SCIPsortRealRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5875#define SORTTPL_NAMEEXT RealRealRealPtr
5876#define SORTTPL_KEYTYPE SCIP_Real
5877#define SORTTPL_FIELD1TYPE SCIP_Real
5878#define SORTTPL_FIELD2TYPE SCIP_Real
5879#define SORTTPL_FIELD3TYPE void*
5880#include "scip/sorttpl.c" /*lint !e451*/
5881
5882
5883/* SCIPsortRealPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5884#define SORTTPL_NAMEEXT RealPtrPtrInt
5885#define SORTTPL_KEYTYPE SCIP_Real
5886#define SORTTPL_FIELD1TYPE void*
5887#define SORTTPL_FIELD2TYPE void*
5888#define SORTTPL_FIELD3TYPE int
5889#include "scip/sorttpl.c" /*lint !e451*/
5890
5891
5892/* SCIPsortRealPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5893#define SORTTPL_NAMEEXT RealPtrPtrIntInt
5894#define SORTTPL_KEYTYPE SCIP_Real
5895#define SORTTPL_FIELD1TYPE void*
5896#define SORTTPL_FIELD2TYPE void*
5897#define SORTTPL_FIELD3TYPE int
5898#define SORTTPL_FIELD4TYPE int
5899#include "scip/sorttpl.c" /*lint !e451*/
5900
5901
5902/* SCIPsortRealRealRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5903#define SORTTPL_NAMEEXT RealRealRealBoolPtr
5904#define SORTTPL_KEYTYPE SCIP_Real
5905#define SORTTPL_FIELD1TYPE SCIP_Real
5906#define SORTTPL_FIELD2TYPE SCIP_Real
5907#define SORTTPL_FIELD3TYPE SCIP_Bool
5908#define SORTTPL_FIELD4TYPE void*
5909#include "scip/sorttpl.c" /*lint !e451*/
5910
5911
5912/* SCIPsortRealRealRealBoolBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5913#define SORTTPL_NAMEEXT RealRealRealBoolBoolPtr
5914#define SORTTPL_KEYTYPE SCIP_Real
5915#define SORTTPL_FIELD1TYPE SCIP_Real
5916#define SORTTPL_FIELD2TYPE SCIP_Real
5917#define SORTTPL_FIELD3TYPE SCIP_Bool
5918#define SORTTPL_FIELD4TYPE SCIP_Bool
5919#define SORTTPL_FIELD5TYPE void*
5920#include "scip/sorttpl.c" /*lint !e451*/
5921
5922
5923/* SCIPsortInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5924#define SORTTPL_NAMEEXT Int
5925#define SORTTPL_KEYTYPE int
5926#include "scip/sorttpl.c" /*lint !e451*/
5927
5928
5929/* SCIPsortIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5930#define SORTTPL_NAMEEXT IntInt
5931#define SORTTPL_KEYTYPE int
5932#define SORTTPL_FIELD1TYPE int
5933#include "scip/sorttpl.c" /*lint !e451*/
5934
5935
5936/* SCIPsortIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5937#define SORTTPL_NAMEEXT IntReal
5938#define SORTTPL_KEYTYPE int
5939#define SORTTPL_FIELD1TYPE SCIP_Real
5940#include "scip/sorttpl.c" /*lint !e451*/
5941
5942
5943/* SCIPsortIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5944#define SORTTPL_NAMEEXT IntPtr
5945#define SORTTPL_KEYTYPE int
5946#define SORTTPL_FIELD1TYPE void*
5947#include "scip/sorttpl.c" /*lint !e451*/
5948
5949
5950/* SCIPsortIntIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5951#define SORTTPL_NAMEEXT IntIntInt
5952#define SORTTPL_KEYTYPE int
5953#define SORTTPL_FIELD1TYPE int
5954#define SORTTPL_FIELD2TYPE int
5955#include "scip/sorttpl.c" /*lint !e451*/
5956
5957
5958/* SCIPsortIntIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5959#define SORTTPL_NAMEEXT IntIntLong
5960#define SORTTPL_KEYTYPE int
5961#define SORTTPL_FIELD1TYPE int
5962#define SORTTPL_FIELD2TYPE SCIP_Longint
5963#include "scip/sorttpl.c" /*lint !e451*/
5964
5965/* SCIPsortIntRealLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5966#define SORTTPL_NAMEEXT IntRealLong
5967#define SORTTPL_KEYTYPE int
5968#define SORTTPL_FIELD1TYPE SCIP_Real
5969#define SORTTPL_FIELD2TYPE SCIP_Longint
5970#include "scip/sorttpl.c" /*lint !e451*/
5971
5972
5973/* SCIPsortIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5974#define SORTTPL_NAMEEXT IntIntPtr
5975#define SORTTPL_KEYTYPE int
5976#define SORTTPL_FIELD1TYPE int
5977#define SORTTPL_FIELD2TYPE void*
5978#include "scip/sorttpl.c" /*lint !e451*/
5979
5980
5981/* SCIPsortIntIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5982#define SORTTPL_NAMEEXT IntIntReal
5983#define SORTTPL_KEYTYPE int
5984#define SORTTPL_FIELD1TYPE int
5985#define SORTTPL_FIELD2TYPE SCIP_Real
5986#include "scip/sorttpl.c" /*lint !e451*/
5987
5988
5989/* SCIPsortIntPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5990#define SORTTPL_NAMEEXT IntPtrReal
5991#define SORTTPL_KEYTYPE int
5992#define SORTTPL_FIELD1TYPE void*
5993#define SORTTPL_FIELD2TYPE SCIP_Real
5994#include "scip/sorttpl.c" /*lint !e451*/
5995
5996
5997/* SCIPsortIntIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5998#define SORTTPL_NAMEEXT IntIntIntPtr
5999#define SORTTPL_KEYTYPE int
6000#define SORTTPL_FIELD1TYPE int
6001#define SORTTPL_FIELD2TYPE int
6002#define SORTTPL_FIELD3TYPE void*
6003#include "scip/sorttpl.c" /*lint !e451*/
6004
6005/* SCIPsortIntIntIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6006#define SORTTPL_NAMEEXT IntIntIntReal
6007#define SORTTPL_KEYTYPE int
6008#define SORTTPL_FIELD1TYPE int
6009#define SORTTPL_FIELD2TYPE int
6010#define SORTTPL_FIELD3TYPE SCIP_Real
6011#include "scip/sorttpl.c" /*lint !e451*/
6012
6013/* SCIPsortIntPtrIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6014#define SORTTPL_NAMEEXT IntPtrIntReal
6015#define SORTTPL_KEYTYPE int
6016#define SORTTPL_FIELD1TYPE void*
6017#define SORTTPL_FIELD2TYPE int
6018#define SORTTPL_FIELD3TYPE SCIP_Real
6019#include "scip/sorttpl.c" /*lint !e451*/
6020
6021/* SCIPsortIntIntPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6022#define SORTTPL_NAMEEXT IntIntPtrPtr
6023#define SORTTPL_KEYTYPE int
6024#define SORTTPL_FIELD1TYPE int
6025#define SORTTPL_FIELD2TYPE void*
6026#define SORTTPL_FIELD3TYPE void*
6027#include "scip/sorttpl.c" /*lint !e451*/
6028
6029/* SCIPsortIntIntPtrPtrInterval(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6030#define SORTTPL_NAMEEXT IntIntPtrPtrInterval
6031#define SORTTPL_KEYTYPE int
6032#define SORTTPL_FIELD1TYPE int
6033#define SORTTPL_FIELD2TYPE void*
6034#define SORTTPL_FIELD3TYPE void*
6035#define SORTTPL_FIELD4TYPE SCIP_INTERVAL
6036#include "scip/sorttpl.c" /*lint !e451*/
6037
6038/* SCIPsortLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6039#define SORTTPL_NAMEEXT Long
6040#define SORTTPL_KEYTYPE SCIP_Longint
6041#include "scip/sorttpl.c" /*lint !e451*/
6042
6043
6044/* SCIPsortLongPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6045#define SORTTPL_NAMEEXT LongPtr
6046#define SORTTPL_KEYTYPE SCIP_Longint
6047#define SORTTPL_FIELD1TYPE void*
6048#include "scip/sorttpl.c" /*lint !e451*/
6049
6050
6051/* SCIPsortLongPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6052#define SORTTPL_NAMEEXT LongPtrInt
6053#define SORTTPL_KEYTYPE SCIP_Longint
6054#define SORTTPL_FIELD1TYPE void*
6055#define SORTTPL_FIELD2TYPE int
6056#include "scip/sorttpl.c" /*lint !e451*/
6057
6058
6059/* SCIPsortLongPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6060#define SORTTPL_NAMEEXT LongPtrRealBool
6061#define SORTTPL_KEYTYPE SCIP_Longint
6062#define SORTTPL_FIELD1TYPE void*
6063#define SORTTPL_FIELD2TYPE SCIP_Real
6064#define SORTTPL_FIELD3TYPE SCIP_Bool
6065#include "scip/sorttpl.c" /*lint !e451*/
6066
6067
6068/* SCIPsortLongPtrRealRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6069#define SORTTPL_NAMEEXT LongPtrRealRealBool
6070#define SORTTPL_KEYTYPE SCIP_Longint
6071#define SORTTPL_FIELD1TYPE void*
6072#define SORTTPL_FIELD2TYPE SCIP_Real
6073#define SORTTPL_FIELD3TYPE SCIP_Real
6074#define SORTTPL_FIELD4TYPE SCIP_Bool
6075#include "scip/sorttpl.c" /*lint !e451*/
6076
6077
6078/* SCIPsortLongPtrRealRealIntBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6079#define SORTTPL_NAMEEXT LongPtrRealRealIntBool
6080#define SORTTPL_KEYTYPE SCIP_Longint
6081#define SORTTPL_FIELD1TYPE void*
6082#define SORTTPL_FIELD2TYPE SCIP_Real
6083#define SORTTPL_FIELD3TYPE SCIP_Real
6084#define SORTTPL_FIELD4TYPE int
6085#define SORTTPL_FIELD5TYPE SCIP_Bool
6086#include "scip/sorttpl.c" /*lint !e451*/
6087
6088
6089/* SCIPsortLongPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6090#define SORTTPL_NAMEEXT LongPtrPtrInt
6091#define SORTTPL_KEYTYPE SCIP_Longint
6092#define SORTTPL_FIELD1TYPE void*
6093#define SORTTPL_FIELD2TYPE void*
6094#define SORTTPL_FIELD3TYPE int
6095#include "scip/sorttpl.c" /*lint !e451*/
6096
6097
6098/* SCIPsortLongPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6099#define SORTTPL_NAMEEXT LongPtrPtrIntInt
6100#define SORTTPL_KEYTYPE SCIP_Longint
6101#define SORTTPL_FIELD1TYPE void*
6102#define SORTTPL_FIELD2TYPE void*
6103#define SORTTPL_FIELD3TYPE int
6104#define SORTTPL_FIELD4TYPE int
6105#include "scip/sorttpl.c" /*lint !e451*/
6106
6107
6108/* SCIPsortLongPtrPtrBoolInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6109#define SORTTPL_NAMEEXT LongPtrPtrBoolInt
6110#define SORTTPL_KEYTYPE SCIP_Longint
6111#define SORTTPL_FIELD1TYPE void*
6112#define SORTTPL_FIELD2TYPE void*
6113#define SORTTPL_FIELD3TYPE SCIP_Bool
6114#define SORTTPL_FIELD4TYPE int
6115#include "scip/sorttpl.c" /*lint !e451*/
6116
6117
6118/* SCIPsortPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6119#define SORTTPL_NAMEEXT PtrIntIntBoolBool
6120#define SORTTPL_KEYTYPE void*
6121#define SORTTPL_FIELD1TYPE int
6122#define SORTTPL_FIELD2TYPE int
6123#define SORTTPL_FIELD3TYPE SCIP_Bool
6124#define SORTTPL_FIELD4TYPE SCIP_Bool
6125#define SORTTPL_PTRCOMP
6126#include "scip/sorttpl.c" /*lint !e451*/
6127
6128
6129/* SCIPsortIntPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6130#define SORTTPL_NAMEEXT IntPtrIntIntBoolBool
6131#define SORTTPL_KEYTYPE int
6132#define SORTTPL_FIELD1TYPE void*
6133#define SORTTPL_FIELD2TYPE int
6134#define SORTTPL_FIELD3TYPE int
6135#define SORTTPL_FIELD4TYPE SCIP_Bool
6136#define SORTTPL_FIELD5TYPE SCIP_Bool
6137#include "scip/sorttpl.c" /*lint !e451*/
6138
6139
6140/* now all downwards-sorting methods */
6141
6142
6143/** sort an indexed element set in non-increasing order, resulting in a permutation index array */
6145 int* perm, /**< pointer to store the resulting permutation */
6146 SCIP_DECL_SORTINDCOMP((*indcomp)), /**< data element comparator */
6147 void* dataptr, /**< pointer to data field that is given to the external compare method */
6148 int len /**< number of elements to be sorted (valid index range) */
6149 )
6150{
6151 int pos;
6152
6153 assert(indcomp != NULL);
6154 assert(len == 0 || perm != NULL);
6155
6156 /* create identity permutation */
6157 for( pos = 0; pos < len; ++pos )
6158 perm[pos] = pos;
6159
6160 SCIPsortDownInd(perm, indcomp, dataptr, len);
6161}
6162
6163
6164/* SCIPsortDownInd(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6165#define SORTTPL_NAMEEXT DownInd
6166#define SORTTPL_KEYTYPE int
6167#define SORTTPL_INDCOMP
6168#define SORTTPL_BACKWARDS
6169#include "scip/sorttpl.c" /*lint !e451*/
6170
6171
6172/* SCIPsortDownPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6173#define SORTTPL_NAMEEXT DownPtr
6174#define SORTTPL_KEYTYPE void*
6175#define SORTTPL_PTRCOMP
6176#define SORTTPL_BACKWARDS
6177#include "scip/sorttpl.c" /*lint !e451*/
6178
6179
6180/* SCIPsortDownPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6181#define SORTTPL_NAMEEXT DownPtrPtr
6182#define SORTTPL_KEYTYPE void*
6183#define SORTTPL_FIELD1TYPE void*
6184#define SORTTPL_PTRCOMP
6185#define SORTTPL_BACKWARDS
6186#include "scip/sorttpl.c" /*lint !e451*/
6187
6188
6189/* SCIPsortDownPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6190#define SORTTPL_NAMEEXT DownPtrReal
6191#define SORTTPL_KEYTYPE void*
6192#define SORTTPL_FIELD1TYPE SCIP_Real
6193#define SORTTPL_PTRCOMP
6194#define SORTTPL_BACKWARDS
6195#include "scip/sorttpl.c" /*lint !e451*/
6196
6197
6198/* SCIPsortDownPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6199#define SORTTPL_NAMEEXT DownPtrInt
6200#define SORTTPL_KEYTYPE void*
6201#define SORTTPL_FIELD1TYPE int
6202#define SORTTPL_PTRCOMP
6203#define SORTTPL_BACKWARDS
6204#include "scip/sorttpl.c" /*lint !e451*/
6205
6206/* SCIPsortDownPtrBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6207#define SORTTPL_NAMEEXT DownPtrBool
6208#define SORTTPL_KEYTYPE void*
6209#define SORTTPL_FIELD1TYPE SCIP_Bool
6210#define SORTTPL_PTRCOMP
6211#define SORTTPL_BACKWARDS
6212#include "scip/sorttpl.c" /*lint !e451*/
6213
6214/* SCIPsortDownPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6215#define SORTTPL_NAMEEXT DownPtrIntInt
6216#define SORTTPL_KEYTYPE void*
6217#define SORTTPL_FIELD1TYPE int
6218#define SORTTPL_FIELD2TYPE int
6219#define SORTTPL_PTRCOMP
6220#define SORTTPL_BACKWARDS
6221#include "scip/sorttpl.c" /*lint !e451*/
6222
6223
6224/* SCIPsortDownPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6225#define SORTTPL_NAMEEXT DownPtrRealInt
6226#define SORTTPL_KEYTYPE void*
6227#define SORTTPL_FIELD1TYPE SCIP_Real
6228#define SORTTPL_FIELD2TYPE int
6229#define SORTTPL_PTRCOMP
6230#define SORTTPL_BACKWARDS
6231#include "scip/sorttpl.c" /*lint !e451*/
6232
6233
6234/* SCIPsortDownPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6235#define SORTTPL_NAMEEXT DownPtrRealBool
6236#define SORTTPL_KEYTYPE void*
6237#define SORTTPL_FIELD1TYPE SCIP_Real
6238#define SORTTPL_FIELD2TYPE SCIP_Bool
6239#define SORTTPL_PTRCOMP
6240#define SORTTPL_BACKWARDS
6241#include "scip/sorttpl.c" /*lint !e451*/
6242
6243
6244/* SCIPsortDownPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6245#define SORTTPL_NAMEEXT DownPtrPtrInt
6246#define SORTTPL_KEYTYPE void*
6247#define SORTTPL_FIELD1TYPE void*
6248#define SORTTPL_FIELD2TYPE int
6249#define SORTTPL_PTRCOMP
6250#define SORTTPL_BACKWARDS
6251#include "scip/sorttpl.c" /*lint !e451*/
6252
6253
6254/* SCIPsortDownPtrPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6255#define SORTTPL_NAMEEXT DownPtrPtrReal
6256#define SORTTPL_KEYTYPE void*
6257#define SORTTPL_FIELD1TYPE void*
6258#define SORTTPL_FIELD2TYPE SCIP_Real
6259#define SORTTPL_PTRCOMP
6260#define SORTTPL_BACKWARDS
6261#include "scip/sorttpl.c" /*lint !e451*/
6262
6263
6264/* SCIPsortDownPtrRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6265#define SORTTPL_NAMEEXT DownPtrRealIntInt
6266#define SORTTPL_KEYTYPE void*
6267#define SORTTPL_FIELD1TYPE SCIP_Real
6268#define SORTTPL_FIELD2TYPE int
6269#define SORTTPL_FIELD3TYPE int
6270#define SORTTPL_PTRCOMP
6271#define SORTTPL_BACKWARDS
6272#include "scip/sorttpl.c" /*lint !e451*/
6273
6274
6275/* SCIPsortDownPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6276#define SORTTPL_NAMEEXT DownPtrPtrIntInt
6277#define SORTTPL_KEYTYPE void*
6278#define SORTTPL_FIELD1TYPE void*
6279#define SORTTPL_FIELD2TYPE int
6280#define SORTTPL_FIELD3TYPE int
6281#define SORTTPL_PTRCOMP
6282#define SORTTPL_BACKWARDS
6283#include "scip/sorttpl.c" /*lint !e451*/
6284
6285
6286/* SCIPsortDownPtrPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6287#define SORTTPL_NAMEEXT DownPtrPtrRealInt
6288#define SORTTPL_KEYTYPE void*
6289#define SORTTPL_FIELD1TYPE void*
6290#define SORTTPL_FIELD2TYPE SCIP_Real
6291#define SORTTPL_FIELD3TYPE int
6292#define SORTTPL_PTRCOMP
6293#define SORTTPL_BACKWARDS
6294#include "scip/sorttpl.c" /*lint !e451*/
6295
6296
6297/* SCIPsortDownPtrPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6298#define SORTTPL_NAMEEXT DownPtrPtrRealBool
6299#define SORTTPL_KEYTYPE void*
6300#define SORTTPL_FIELD1TYPE void*
6301#define SORTTPL_FIELD2TYPE SCIP_Real
6302#define SORTTPL_FIELD3TYPE SCIP_Bool
6303#define SORTTPL_PTRCOMP
6304#define SORTTPL_BACKWARDS
6305#include "scip/sorttpl.c" /*lint !e451*/
6306
6307
6308/* SCIPsortDownPtrPtrLongInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6309#define SORTTPL_NAMEEXT DownPtrPtrLongInt
6310#define SORTTPL_KEYTYPE void*
6311#define SORTTPL_FIELD1TYPE void*
6312#define SORTTPL_FIELD2TYPE SCIP_Longint
6313#define SORTTPL_FIELD3TYPE int
6314#define SORTTPL_PTRCOMP
6315#define SORTTPL_BACKWARDS
6316#include "scip/sorttpl.c" /*lint !e451*/
6317
6318
6319/* SCIPsortDownPtrPtrLongIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6320#define SORTTPL_NAMEEXT DownPtrPtrLongIntInt
6321#define SORTTPL_KEYTYPE void*
6322#define SORTTPL_FIELD1TYPE void*
6323#define SORTTPL_FIELD2TYPE SCIP_Longint
6324#define SORTTPL_FIELD3TYPE int
6325#define SORTTPL_FIELD4TYPE int
6326#define SORTTPL_PTRCOMP
6327#define SORTTPL_BACKWARDS
6328#include "scip/sorttpl.c" /*lint !e451*/
6329
6330
6331/* SCIPsortDownReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6332#define SORTTPL_NAMEEXT DownReal
6333#define SORTTPL_KEYTYPE SCIP_Real
6334#define SORTTPL_BACKWARDS
6335#include "scip/sorttpl.c" /*lint !e451*/
6336
6337
6338/* SCIPsortDownRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6339#define SORTTPL_NAMEEXT DownRealBoolPtr
6340#define SORTTPL_KEYTYPE SCIP_Real
6341#define SORTTPL_FIELD1TYPE SCIP_Bool
6342#define SORTTPL_FIELD2TYPE void*
6343#define SORTTPL_BACKWARDS
6344#include "scip/sorttpl.c" /*lint !e451*/
6345
6346
6347/* SCIPsortDownRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6348#define SORTTPL_NAMEEXT DownRealPtr
6349#define SORTTPL_KEYTYPE SCIP_Real
6350#define SORTTPL_FIELD1TYPE void*
6351#define SORTTPL_BACKWARDS
6352#include "scip/sorttpl.c" /*lint !e451*/
6353
6354
6355/* SCIPsortDownRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6356#define SORTTPL_NAMEEXT DownRealInt
6357#define SORTTPL_KEYTYPE SCIP_Real
6358#define SORTTPL_FIELD1TYPE int
6359#define SORTTPL_BACKWARDS
6360#include "scip/sorttpl.c" /*lint !e451*/
6361
6362/* SCIPsortDownRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6363#define SORTTPL_NAMEEXT DownRealIntInt
6364#define SORTTPL_KEYTYPE SCIP_Real
6365#define SORTTPL_FIELD1TYPE int
6366#define SORTTPL_FIELD2TYPE int
6367#define SORTTPL_BACKWARDS
6368#include "scip/sorttpl.c" /*lint !e451*/
6369
6370/* SCIPsortDownRealIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6371#define SORTTPL_NAMEEXT DownRealIntLong
6372#define SORTTPL_KEYTYPE SCIP_Real
6373#define SORTTPL_FIELD1TYPE int
6374#define SORTTPL_FIELD2TYPE SCIP_Longint
6375#define SORTTPL_BACKWARDS
6376#include "scip/sorttpl.c" /*lint !e451*/
6377
6378
6379/* SCIPsortDownRealIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6380#define SORTTPL_NAMEEXT DownRealIntPtr
6381#define SORTTPL_KEYTYPE SCIP_Real
6382#define SORTTPL_FIELD1TYPE int
6383#define SORTTPL_FIELD2TYPE void*
6384#define SORTTPL_BACKWARDS
6385#include "scip/sorttpl.c" /*lint !e451*/
6386
6387
6388/* SCIPsortDownRealPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6389#define SORTTPL_NAMEEXT DownRealPtrPtr
6390#define SORTTPL_KEYTYPE SCIP_Real
6391#define SORTTPL_FIELD1TYPE void*
6392#define SORTTPL_FIELD2TYPE void*
6393#define SORTTPL_BACKWARDS
6394#include "scip/sorttpl.c" /*lint !e451*/
6395
6396/* SCIPsortDownRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6397#define SORTTPL_NAMEEXT DownRealRealInt
6398#define SORTTPL_KEYTYPE SCIP_Real
6399#define SORTTPL_FIELD1TYPE SCIP_Real
6400#define SORTTPL_FIELD2TYPE int
6401#define SORTTPL_BACKWARDS
6402#include "scip/sorttpl.c" /*lint !e451*/
6403
6404/* SCIPsortDownRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6405#define SORTTPL_NAMEEXT DownRealRealPtr
6406#define SORTTPL_KEYTYPE SCIP_Real
6407#define SORTTPL_FIELD1TYPE SCIP_Real
6408#define SORTTPL_FIELD2TYPE void*
6409#define SORTTPL_BACKWARDS
6410#include "scip/sorttpl.c" /*lint !e451*/
6411
6412/* SCIPsortDownRealRealPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6413#define SORTTPL_NAMEEXT DownRealRealPtrPtr
6414#define SORTTPL_KEYTYPE SCIP_Real
6415#define SORTTPL_FIELD1TYPE SCIP_Real
6416#define SORTTPL_FIELD2TYPE void*
6417#define SORTTPL_FIELD3TYPE void*
6418#define SORTTPL_BACKWARDS
6419#include "scip/sorttpl.c" /*lint !e451*/
6420
6421
6422/* SCIPsortDownRealLongRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6423#define SORTTPL_NAMEEXT DownRealLongRealInt
6424#define SORTTPL_KEYTYPE SCIP_Real
6425#define SORTTPL_FIELD1TYPE SCIP_Longint
6426#define SORTTPL_FIELD2TYPE SCIP_Real
6427#define SORTTPL_FIELD3TYPE int
6428#define SORTTPL_BACKWARDS
6429#include "scip/sorttpl.c" /*lint !e451*/
6430
6431
6432/* SCIPsortDownRealRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6433#define SORTTPL_NAMEEXT DownRealRealIntInt
6434#define SORTTPL_KEYTYPE SCIP_Real
6435#define SORTTPL_FIELD1TYPE SCIP_Real
6436#define SORTTPL_FIELD2TYPE int
6437#define SORTTPL_FIELD3TYPE int
6438#define SORTTPL_BACKWARDS
6439#include "scip/sorttpl.c" /*lint !e451*/
6440
6441
6442/* SCIPsortDownRealRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6443#define SORTTPL_NAMEEXT DownRealRealRealInt
6444#define SORTTPL_KEYTYPE SCIP_Real
6445#define SORTTPL_FIELD1TYPE SCIP_Real
6446#define SORTTPL_FIELD2TYPE SCIP_Real
6447#define SORTTPL_FIELD3TYPE int
6448#define SORTTPL_BACKWARDS
6449#include "scip/sorttpl.c" /*lint !e451*/
6450
6451
6452/* SCIPsortDownRealRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6453#define SORTTPL_NAMEEXT DownRealRealRealPtr
6454#define SORTTPL_KEYTYPE SCIP_Real
6455#define SORTTPL_FIELD1TYPE SCIP_Real
6456#define SORTTPL_FIELD2TYPE SCIP_Real
6457#define SORTTPL_FIELD3TYPE void*
6458#define SORTTPL_BACKWARDS
6459#include "scip/sorttpl.c" /*lint !e451*/
6460
6461
6462/* SCIPsortDownRealPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6463#define SORTTPL_NAMEEXT DownRealPtrPtrInt
6464#define SORTTPL_KEYTYPE SCIP_Real
6465#define SORTTPL_FIELD1TYPE void*
6466#define SORTTPL_FIELD2TYPE void*
6467#define SORTTPL_FIELD3TYPE int
6468#define SORTTPL_BACKWARDS
6469#include "scip/sorttpl.c" /*lint !e451*/
6470
6471/* SCIPsortDownRealPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6472#define SORTTPL_NAMEEXT DownRealPtrPtrIntInt
6473#define SORTTPL_KEYTYPE SCIP_Real
6474#define SORTTPL_FIELD1TYPE void*
6475#define SORTTPL_FIELD2TYPE void*
6476#define SORTTPL_FIELD3TYPE int
6477#define SORTTPL_FIELD4TYPE int
6478#define SORTTPL_BACKWARDS
6479#include "scip/sorttpl.c" /*lint !e451*/
6480
6481
6482/* SCIPsortDownRealRealRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6483#define SORTTPL_NAMEEXT DownRealRealRealBoolPtr
6484#define SORTTPL_KEYTYPE SCIP_Real
6485#define SORTTPL_FIELD1TYPE SCIP_Real
6486#define SORTTPL_FIELD2TYPE SCIP_Real
6487#define SORTTPL_FIELD3TYPE SCIP_Bool
6488#define SORTTPL_FIELD4TYPE void*
6489#define SORTTPL_BACKWARDS
6490#include "scip/sorttpl.c" /*lint !e451*/
6491
6492
6493/* SCIPsortDownRealRealRealBoolBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6494#define SORTTPL_NAMEEXT DownRealRealRealBoolBoolPtr
6495#define SORTTPL_KEYTYPE SCIP_Real
6496#define SORTTPL_FIELD1TYPE SCIP_Real
6497#define SORTTPL_FIELD2TYPE SCIP_Real
6498#define SORTTPL_FIELD3TYPE SCIP_Bool
6499#define SORTTPL_FIELD4TYPE SCIP_Bool
6500#define SORTTPL_FIELD5TYPE void*
6501#include "scip/sorttpl.c" /*lint !e451*/
6502
6503
6504/* SCIPsortDownInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6505#define SORTTPL_NAMEEXT DownInt
6506#define SORTTPL_KEYTYPE int
6507#define SORTTPL_BACKWARDS
6508#include "scip/sorttpl.c" /*lint !e451*/
6509
6510
6511/* SCIPsortDownIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6512#define SORTTPL_NAMEEXT DownIntInt
6513#define SORTTPL_KEYTYPE int
6514#define SORTTPL_FIELD1TYPE int
6515#define SORTTPL_BACKWARDS
6516#include "scip/sorttpl.c" /*lint !e451*/
6517
6518
6519/* SCIPsortDownIntIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6520#define SORTTPL_NAMEEXT DownIntIntReal
6521#define SORTTPL_KEYTYPE int
6522#define SORTTPL_FIELD1TYPE int
6523#define SORTTPL_FIELD2TYPE SCIP_Real
6524#define SORTTPL_BACKWARDS
6525#include "scip/sorttpl.c" /*lint !e451*/
6526
6527
6528/* SCIPsortDownIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6529#define SORTTPL_NAMEEXT DownIntReal
6530#define SORTTPL_KEYTYPE int
6531#define SORTTPL_FIELD1TYPE SCIP_Real
6532#define SORTTPL_BACKWARDS
6533#include "scip/sorttpl.c" /*lint !e451*/
6534
6535
6536/* SCIPsortDownIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6537#define SORTTPL_NAMEEXT DownIntPtr
6538#define SORTTPL_KEYTYPE int
6539#define SORTTPL_FIELD1TYPE void*
6540#define SORTTPL_BACKWARDS
6541#include "scip/sorttpl.c" /*lint !e451*/
6542
6543
6544/* SCIPsortDownIntIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6545#define SORTTPL_NAMEEXT DownIntIntInt
6546#define SORTTPL_KEYTYPE int
6547#define SORTTPL_FIELD1TYPE int
6548#define SORTTPL_FIELD2TYPE int
6549#define SORTTPL_BACKWARDS
6550#include "scip/sorttpl.c" /*lint !e451*/
6551
6552
6553/* SCIPsortDownIntIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6554#define SORTTPL_NAMEEXT DownIntIntLong
6555#define SORTTPL_KEYTYPE int
6556#define SORTTPL_FIELD1TYPE int
6557#define SORTTPL_FIELD2TYPE SCIP_Longint
6558#define SORTTPL_BACKWARDS
6559#include "scip/sorttpl.c" /*lint !e451*/
6560
6561
6562/* SCIPsortDownIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6563#define SORTTPL_NAMEEXT DownIntIntPtr
6564#define SORTTPL_KEYTYPE int
6565#define SORTTPL_FIELD1TYPE int
6566#define SORTTPL_FIELD2TYPE void*
6567#define SORTTPL_BACKWARDS
6568#include "scip/sorttpl.c" /*lint !e451*/
6569
6570
6571/* SCIPsortDownIntIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6572#define SORTTPL_NAMEEXT DownIntIntIntPtr
6573#define SORTTPL_KEYTYPE int
6574#define SORTTPL_FIELD1TYPE int
6575#define SORTTPL_FIELD2TYPE int
6576#define SORTTPL_FIELD3TYPE void*
6577#define SORTTPL_BACKWARDS
6578#include "scip/sorttpl.c" /*lint !e451*/
6579
6580
6581/* SCIPsortDownIntIntIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6582#define SORTTPL_NAMEEXT DownIntIntIntReal
6583#define SORTTPL_KEYTYPE int
6584#define SORTTPL_FIELD1TYPE int
6585#define SORTTPL_FIELD2TYPE int
6586#define SORTTPL_FIELD3TYPE SCIP_Real
6587#define SORTTPL_BACKWARDS
6588#include "scip/sorttpl.c" /*lint !e451*/
6589
6590
6591/* SCIPsortDownIntPtrIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6592#define SORTTPL_NAMEEXT DownIntPtrIntReal
6593#define SORTTPL_KEYTYPE int
6594#define SORTTPL_FIELD1TYPE void*
6595#define SORTTPL_FIELD2TYPE int
6596#define SORTTPL_FIELD3TYPE SCIP_Real
6597#define SORTTPL_BACKWARDS
6598#include "scip/sorttpl.c" /*lint !e451*/
6599
6600
6601/* SCIPsortDownLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6602#define SORTTPL_NAMEEXT DownLong
6603#define SORTTPL_KEYTYPE SCIP_Longint
6604#define SORTTPL_BACKWARDS
6605#include "scip/sorttpl.c" /*lint !e451*/
6606
6607
6608/* SCIPsortDownLongPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6609#define SORTTPL_NAMEEXT DownLongPtr
6610#define SORTTPL_KEYTYPE SCIP_Longint
6611#define SORTTPL_FIELD1TYPE void*
6612#define SORTTPL_BACKWARDS
6613#include "scip/sorttpl.c" /*lint !e451*/
6614
6615
6616/* SCIPsortDownLongPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6617#define SORTTPL_NAMEEXT DownLongPtrInt
6618#define SORTTPL_KEYTYPE SCIP_Longint
6619#define SORTTPL_FIELD1TYPE void*
6620#define SORTTPL_FIELD2TYPE int
6621#define SORTTPL_BACKWARDS
6622#include "scip/sorttpl.c" /*lint !e451*/
6623
6624
6625/* SCIPsortDownLongPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6626#define SORTTPL_NAMEEXT DownLongPtrRealBool
6627#define SORTTPL_KEYTYPE SCIP_Longint
6628#define SORTTPL_FIELD1TYPE void*
6629#define SORTTPL_FIELD2TYPE SCIP_Real
6630#define SORTTPL_FIELD3TYPE SCIP_Bool
6631#define SORTTPL_BACKWARDS
6632#include "scip/sorttpl.c" /*lint !e451*/
6633
6634
6635/* SCIPsortDownLongPtrRealRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6636#define SORTTPL_NAMEEXT DownLongPtrRealRealBool
6637#define SORTTPL_KEYTYPE SCIP_Longint
6638#define SORTTPL_FIELD1TYPE void*
6639#define SORTTPL_FIELD2TYPE SCIP_Real
6640#define SORTTPL_FIELD3TYPE SCIP_Real
6641#define SORTTPL_FIELD4TYPE SCIP_Bool
6642#define SORTTPL_BACKWARDS
6643#include "scip/sorttpl.c" /*lint !e451*/
6644
6645
6646/* SCIPsortLongPtrRealRealIntBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6647#define SORTTPL_NAMEEXT DownLongPtrRealRealIntBool
6648#define SORTTPL_KEYTYPE SCIP_Longint
6649#define SORTTPL_FIELD1TYPE void*
6650#define SORTTPL_FIELD2TYPE SCIP_Real
6651#define SORTTPL_FIELD3TYPE SCIP_Real
6652#define SORTTPL_FIELD4TYPE int
6653#define SORTTPL_FIELD5TYPE SCIP_Bool
6654#define SORTTPL_BACKWARDS
6655#include "scip/sorttpl.c" /*lint !e451*/
6656
6657
6658/* SCIPsortDownLongPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6659#define SORTTPL_NAMEEXT DownLongPtrPtrInt
6660#define SORTTPL_KEYTYPE SCIP_Longint
6661#define SORTTPL_FIELD1TYPE void*
6662#define SORTTPL_FIELD2TYPE void*
6663#define SORTTPL_FIELD3TYPE int
6664#define SORTTPL_BACKWARDS
6665#include "scip/sorttpl.c" /*lint !e451*/
6666
6667
6668/* SCIPsortDownLongPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6669#define SORTTPL_NAMEEXT DownLongPtrPtrIntInt
6670#define SORTTPL_KEYTYPE SCIP_Longint
6671#define SORTTPL_FIELD1TYPE void*
6672#define SORTTPL_FIELD2TYPE void*
6673#define SORTTPL_FIELD3TYPE int
6674#define SORTTPL_FIELD4TYPE int
6675#define SORTTPL_BACKWARDS
6676#include "scip/sorttpl.c" /*lint !e451*/
6677
6678
6679/* SCIPsortDownLongPtrPtrBoolInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6680#define SORTTPL_NAMEEXT DownLongPtrPtrBoolInt
6681#define SORTTPL_KEYTYPE SCIP_Longint
6682#define SORTTPL_FIELD1TYPE void*
6683#define SORTTPL_FIELD2TYPE void*
6684#define SORTTPL_FIELD3TYPE SCIP_Bool
6685#define SORTTPL_FIELD4TYPE int
6686#define SORTTPL_BACKWARDS
6687#include "scip/sorttpl.c" /*lint !e451*/
6688
6689
6690/* SCIPsortDownPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6691#define SORTTPL_NAMEEXT DownPtrIntIntBoolBool
6692#define SORTTPL_KEYTYPE void*
6693#define SORTTPL_FIELD1TYPE int
6694#define SORTTPL_FIELD2TYPE int
6695#define SORTTPL_FIELD3TYPE SCIP_Bool
6696#define SORTTPL_FIELD4TYPE SCIP_Bool
6697#define SORTTPL_PTRCOMP
6698#define SORTTPL_BACKWARDS
6699#include "scip/sorttpl.c" /*lint !e451*/
6700
6701
6702/* SCIPsortDownIntPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6703#define SORTTPL_NAMEEXT DownIntPtrIntIntBoolBool
6704#define SORTTPL_KEYTYPE int
6705#define SORTTPL_FIELD1TYPE void*
6706#define SORTTPL_FIELD2TYPE int
6707#define SORTTPL_FIELD3TYPE int
6708#define SORTTPL_FIELD4TYPE SCIP_Bool
6709#define SORTTPL_FIELD5TYPE SCIP_Bool
6710#define SORTTPL_BACKWARDS
6711#include "scip/sorttpl.c" /*lint !e451*/
6712
6713/*
6714 * Resulting activity
6715 */
6716
6717/** create a resource activity */
6719 SCIP_RESOURCEACTIVITY** activity, /**< pointer to store the resource activity */
6720 SCIP_VAR* var, /**< start time variable of the activity */
6721 int duration, /**< duration of the activity */
6722 int demand /**< demand of the activity */
6723 )
6724{
6725 assert(activity != NULL);
6726
6727 SCIP_ALLOC( BMSallocMemory(activity) );
6728
6729 (*activity)->var = var;
6730 (*activity)->duration = duration;
6731 (*activity)->demand = demand;
6732
6733 return SCIP_OKAY;
6734}
6735
6736/** frees a resource activity */
6738 SCIP_RESOURCEACTIVITY** activity /**< pointer to the resource activity */
6739 )
6740{
6741 assert(activity != NULL);
6742 assert(*activity != NULL);
6743
6744 BMSfreeMemory(activity);
6745}
6746
6747/* some simple variable functions implemented as defines */
6748
6749#ifndef NDEBUG
6750
6751/* In debug mode, the following methods are implemented as function calls to ensure
6752 * type validity.
6753 * In optimized mode, the methods are implemented as defines to improve performance.
6754 * However, we want to have them in the library anyways, so we have to undef the defines.
6755 */
6756
6757#undef SCIPactivityGetVar
6758#undef SCIPactivityGetDuration
6759#undef SCIPactivityGetDemand
6760#undef SCIPactivityGetEnergy
6761
6762/** returns the start time variable of the resource activity */
6764 SCIP_RESOURCEACTIVITY* activity /**< resource activity */
6765 )
6766{
6767 assert(activity != NULL);
6768
6769 return activity->var;
6770}
6771
6772/** returns the duration of the resource activity */
6774 SCIP_RESOURCEACTIVITY* activity /**< resource activity */
6775 )
6776{
6777 assert(activity != NULL);
6778
6779 return activity->duration;
6780}
6781
6782/** returns the demand of the resource activity */
6784 SCIP_RESOURCEACTIVITY* activity /**< resource activity */
6785 )
6786{
6787 assert(activity != NULL);
6788
6789 return activity->demand;
6790}
6791
6792/** returns the energy of the resource activity */
6794 SCIP_RESOURCEACTIVITY* activity /**< resource activity */
6795 )
6796{
6797 assert(activity != NULL);
6798
6799 return activity->duration * activity->demand ;
6800}
6801
6802#endif
6803
6804/*
6805 * Resource Profile
6806 */
6807
6808/** helper method to create a profile */
6809static
6811 SCIP_PROFILE** profile, /**< pointer to store the resource profile */
6812 int capacity /**< resource capacity */
6813 )
6814{
6815 SCIP_ALLOC( BMSallocMemory(profile) );
6816 BMSclearMemory(*profile);
6817
6818 (*profile)->arraysize = 10;
6819 SCIP_ALLOC( BMSallocMemoryArray(&(*profile)->timepoints, (*profile)->arraysize) );
6820 SCIP_ALLOC( BMSallocMemoryArray(&(*profile)->loads, (*profile)->arraysize) );
6821
6822 /* setup resource profile for use */
6823 (*profile)->ntimepoints = 1;
6824 (*profile)->timepoints[0] = 0;
6825 (*profile)->loads[0] = 0;
6826 (*profile)->capacity = capacity;
6827
6828 return SCIP_OKAY;
6829}
6830
6831/** creates resource profile */
6833 SCIP_PROFILE** profile, /**< pointer to store the resource profile */
6834 int capacity /**< resource capacity */
6835 )
6836{
6837 assert(profile != NULL);
6838 assert(capacity > 0);
6839
6840 SCIP_CALL_FINALLY( doProfileCreate(profile, capacity), SCIPprofileFree(profile) );
6841
6842 return SCIP_OKAY;
6843}
6844
6845/** frees given resource profile */
6847 SCIP_PROFILE** profile /**< pointer to the resource profile */
6848 )
6849{
6850 assert(profile != NULL);
6851
6852 /* free resource profile */
6853 if( *profile != NULL )
6854 {
6855 BMSfreeMemoryArrayNull(&(*profile)->loads);
6856 BMSfreeMemoryArrayNull(&(*profile)->timepoints);
6857 BMSfreeMemory(profile);
6858 }
6859}
6860
6861/** output of the given resource profile */
6863 SCIP_PROFILE* profile, /**< resource profile to output */
6864 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
6865 FILE* file /**< output file (or NULL for standard output) */
6866 )
6867{
6868 int t;
6869
6870 SCIPmessageFPrintInfo(messagehdlr, file, "Profile <%p> (capacity %d) --> ", (void*)profile, profile->capacity);
6871
6872 for( t = 0; t < profile->ntimepoints; ++t )
6873 {
6874 if( t == 0 )
6875 SCIPmessageFPrintInfo(messagehdlr, file, "%d:(%d,%d)", t, profile->timepoints[t], profile->loads[t]);
6876 else
6877 SCIPmessageFPrintInfo(messagehdlr, file, ", %d:(%d,%d)", t, profile->timepoints[t], profile->loads[t]);
6878 }
6879
6880 SCIPmessageFPrintInfo(messagehdlr, file,"\n");
6881}
6882
6883/** returns the capacity of the resource profile */
6885 SCIP_PROFILE* profile /**< resource profile to use */
6886 )
6887{
6888 assert(profile != NULL);
6889
6890 return profile->capacity;
6891}
6892
6893/** returns the number time points of the resource profile */
6895 SCIP_PROFILE* profile /**< resource profile to use */
6896 )
6897{
6898 assert(profile != NULL);
6899
6900 return profile->ntimepoints;
6901}
6902
6903/** returns the time points of the resource profile */
6905 SCIP_PROFILE* profile /**< resource profile to use */
6906 )
6907{
6908 assert(profile != NULL);
6909
6910 return profile->timepoints;
6911}
6912
6913/** returns the loads of the resource profile */
6915 SCIP_PROFILE* profile /**< resource profile to use */
6916 )
6917{
6918 assert(profile != NULL);
6919
6920 return profile->loads;
6921}
6922
6923/** returns the time point for given position of the resource profile */
6925 SCIP_PROFILE* profile, /**< resource profile to use */
6926 int pos /**< position */
6927 )
6928{
6929 assert(profile != NULL);
6930 assert(pos >= 0 && pos < profile->ntimepoints);
6931
6932 return profile->timepoints[pos];
6933}
6934
6935/** returns the loads of the resource profile at the given position */
6937 SCIP_PROFILE* profile, /**< resource profile */
6938 int pos /**< position */
6939 )
6940{
6941 assert(profile != NULL);
6942 assert(pos >= 0 && pos < profile->ntimepoints);
6943
6944 return profile->loads[pos];
6945}
6946
6947/** returns if the given time point exists in the resource profile and stores the position of the given time point if it
6948 * exists; otherwise the position of the next smaller existing time point is stored
6949 */
6951 SCIP_PROFILE* profile, /**< resource profile to search */
6952 int timepoint, /**< time point to search for */
6953 int* pos /**< pointer to store the position */
6954 )
6955{
6956 assert(profile != NULL);
6957 assert(timepoint >= 0);
6958 assert(profile->ntimepoints > 0);
6959 assert(profile->timepoints[0] == 0);
6960
6961 /* find the position of time point in the time points array via binary search */
6962 if( SCIPsortedvecFindInt(profile->timepoints, timepoint, profile->ntimepoints, pos) )
6963 return TRUE;
6964
6965 assert(*pos > 0);
6966 (*pos)--;
6967
6968 return FALSE;
6969}
6970
6971/* ensures that resource profile arrays is big enough */
6972static
6974 SCIP_PROFILE* profile, /**< resource profile to insert the time point */
6975 int neededsize /**< needed size */
6976 )
6977{
6978 assert(profile->arraysize > 0);
6979
6980 /* check whether the arrays are big enough */
6981 if( neededsize <= profile->arraysize )
6982 return SCIP_OKAY;
6983
6984 profile->arraysize *= 2;
6985
6986 SCIP_ALLOC( BMSreallocMemoryArray(&profile->timepoints, profile->arraysize) );
6987 SCIP_ALLOC( BMSreallocMemoryArray(&profile->loads, profile->arraysize) );
6988
6989 return SCIP_OKAY;
6990}
6991
6992/** inserts the given time point into the resource profile if it this time point does not exists yet; returns its
6993 * position in the time point array
6994 */
6995static
6997 SCIP_PROFILE* profile, /**< resource profile to insert the time point */
6998 int timepoint, /**< time point to insert */
6999 int* pos /**< pointer to store the insert position */
7000 )
7001{
7002 assert(profile != NULL);
7003 assert(timepoint >= 0);
7004 assert(profile->arraysize >= profile->ntimepoints);
7005
7006 /* get the position of the given time point in the resource profile array if it exists; otherwise the position of the
7007 * next smaller existing time point
7008 */
7009 if( !SCIPprofileFindLeft(profile, timepoint, pos) )
7010 {
7011 assert(*pos >= 0 && *pos < profile->ntimepoints);
7012 assert(timepoint >= profile->timepoints[*pos]);
7013
7014 /* ensure that the arrays are big enough */
7015 SCIP_CALL( ensureProfileSize(profile, profile->ntimepoints + 1) );
7016 assert(profile->arraysize > profile->ntimepoints);
7017
7018 /* insert new time point into the (sorted) resource profile */
7019 SCIPsortedvecInsertIntInt(profile->timepoints, profile->loads, timepoint, profile->loads[*pos],
7020 &profile->ntimepoints, pos);
7021 }
7022
7023#ifndef NDEBUG
7024 /* check if the time points are sorted */
7025 {
7026 int i;
7027 for( i = 1; i < profile->ntimepoints; ++i )
7028 assert(profile->timepoints[i-1] < profile->timepoints[i]);
7029 }
7030#endif
7031
7032 return SCIP_OKAY;
7033}
7034
7035/** updates the resource profile due to inserting of a core */
7036static
7038 SCIP_PROFILE* profile, /**< resource profile to update */
7039 int left, /**< left side of core interval */
7040 int right, /**< right side of core interval */
7041 int demand, /**< demand of the core */
7042 int* pos, /**< pointer to store the first position were it gets infeasible */
7043 SCIP_Bool* infeasible /**< pointer to store if the update is infeasible */
7044 )
7045{
7046 int startpos;
7047 int endpos;
7048 int i;
7049
7050 assert(profile != NULL);
7051 assert(profile->arraysize >= profile->ntimepoints);
7052 assert(left >= 0);
7053 assert(left < right);
7054 assert(infeasible != NULL);
7055
7056 (*infeasible) = FALSE;
7057 (*pos) = -1;
7058
7059 /* get position of the starttime in profile */
7060 SCIP_CALL( profileInsertTimepoint(profile, left, &startpos) );
7061 assert(profile->timepoints[startpos] == left);
7062
7063 /* get position of the endtime in profile */
7064 SCIP_CALL( profileInsertTimepoint(profile, right, &endpos) );
7065 assert(profile->timepoints[endpos] == right);
7066
7067 assert(startpos < endpos);
7068 assert(profile->arraysize >= profile->ntimepoints);
7069
7070 /* remove/add the given demand from the core */
7071 for( i = startpos; i < endpos; ++i )
7072 {
7073 profile->loads[i] += demand;
7074
7075 /* check if the core fits */
7076 if( profile->loads[i] > profile->capacity )
7077 {
7078 SCIPdebugMessage("core insertion detected infeasibility (pos %d)\n", i);
7079
7080 (*infeasible) = TRUE;
7081 (*pos) = i;
7082
7083 /* remove the partly inserted core since it does fit completely */
7084 for( ; i >= startpos; --i ) /*lint !e445*/
7085 profile->loads[i] -= demand;
7086
7087 break;
7088 }
7089 }
7090
7091 return SCIP_OKAY;
7092}
7093
7094/** insert a core into resource profile; if the core is non-empty the resource profile will be updated otherwise nothing
7095 * happens
7096 */
7098 SCIP_PROFILE* profile, /**< resource profile */
7099 int left, /**< left side of the core */
7100 int right, /**< right side of the core */
7101 int demand, /**< demand of the core */
7102 int* pos, /**< pointer to store the first position were it gets infeasible */
7103 SCIP_Bool* infeasible /**< pointer to store if the core does not fit due to capacity */
7104 )
7105{
7106 assert(profile != NULL);
7107 assert(left < right);
7108 assert(demand >= 0);
7109 assert(infeasible != NULL);
7110
7111 (*infeasible) = FALSE;
7112 (*pos) = -1;
7113
7114 /* insert core into the resource profile */
7115 SCIPdebugMessage("insert core [%d,%d] with demand %d\n", left, right, demand);
7116
7117 if( demand > 0 )
7118 {
7119 /* try to insert core into the resource profile */
7120 SCIP_CALL( profileUpdate(profile, left, right, demand, pos, infeasible) );
7121 }
7122
7123 return SCIP_OKAY;
7124}
7125
7126/** subtracts the demand from the resource profile during core time */
7128 SCIP_PROFILE* profile, /**< resource profile to use */
7129 int left, /**< left side of the core */
7130 int right, /**< right side of the core */
7131 int demand /**< demand of the core */
7132 )
7133{
7134 SCIP_Bool infeasible;
7135 int pos;
7136
7137 assert(left < right);
7138#ifndef NDEBUG
7139 {
7140 /* check if the left and right time points of the core correspond to a time point in the resource profile; this
7141 * should be the case since we added the core before to the resource profile
7142 */
7143 assert(SCIPprofileFindLeft(profile, left, &pos));
7144 assert(SCIPprofileFindLeft(profile, right, &pos));
7145 }
7146#endif
7147
7148 /* remove the core from the resource profile */
7149 SCIPdebugMessage("delete core [%d,%d] with demand %d\n", left, right, demand);
7150
7151 SCIP_CALL( profileUpdate(profile, left, right, -demand, &pos, &infeasible) );
7152 assert(!infeasible);
7153
7154 return SCIP_OKAY; /*lint !e438*/
7155}
7156
7157/** returns TRUE if the core (given by its demand and during) can be inserted at the given time point; otherwise FALSE */
7158static
7160 SCIP_PROFILE* profile, /**< resource profile to use */
7161 int pos, /**< pointer to store the position in the profile to start the serch */
7162 int lst, /**< latest start time */
7163 int duration, /**< duration of the core */
7164 int demand, /**< demand of the core */
7165 SCIP_Bool* infeasible /**< pointer store if the corer cannot be inserted */
7166 )
7167{
7168 int remainingduration;
7169 int startpos;
7170
7171 assert(profile != NULL);
7172 assert(pos >= 0);
7173 assert(pos < profile->ntimepoints);
7174 assert(duration > 0);
7175 assert(demand > 0);
7176 assert(profile->loads[profile->ntimepoints-1] == 0);
7177
7178 remainingduration = duration;
7179 startpos = pos;
7180 (*infeasible) = FALSE;
7181
7182 if( profile->timepoints[startpos] > lst )
7183 {
7184 (*infeasible) = TRUE;
7185 return pos;
7186 }
7187
7188 while( pos < profile->ntimepoints - 1 )
7189 {
7190 if( profile->loads[pos] + demand > profile->capacity )
7191 {
7192 SCIPdebugMessage("profile <%p>: core does not fit at time point %d (pos %d)\n", (void*)profile, profile->timepoints[pos], pos);
7193 startpos = pos + 1;
7194 remainingduration = duration;
7195
7196 if( profile->timepoints[startpos] > lst )
7197 {
7198 (*infeasible) = TRUE;
7199 return pos;
7200 }
7201 }
7202 else
7203 remainingduration -= profile->timepoints[pos+1] - profile->timepoints[pos];
7204
7205 if( remainingduration <= 0 )
7206 break;
7207
7208 pos++;
7209 }
7210
7211 return startpos;
7212}
7213
7214/** return the earliest possible starting point within the time interval [lb,ub] for a given core (given by its demand
7215 * and duration)
7216 */
7218 SCIP_PROFILE* profile, /**< resource profile to use */
7219 int est, /**< earliest starting time of the given core */
7220 int lst, /**< latest starting time of the given core */
7221 int duration, /**< duration of the core */
7222 int demand, /**< demand of the core */
7223 SCIP_Bool* infeasible /**< pointer store if the corer cannot be inserted */
7224 )
7225{
7226 SCIP_Bool found;
7227 int pos;
7228
7229 assert(profile != NULL);
7230 assert(est >= 0);
7231 assert(est <= lst);
7232 assert(duration >= 0);
7233 assert(demand >= 0);
7234 assert(infeasible != NULL);
7235 assert(profile->ntimepoints > 0);
7236 assert(profile->loads[profile->ntimepoints-1] == 0);
7237
7238 SCIPdebugMessage("profile <%p>: find earliest start time (demad %d, duration %d) [%d,%d]\n", (void*)profile, demand, duration, est, lst);
7239
7240 if( duration == 0 || demand == 0 )
7241 {
7242 *infeasible = FALSE;
7243 return est;
7244 }
7245
7246 found = SCIPprofileFindLeft(profile, est, &pos);
7247 SCIPdebugMessage("profile <%p>: earliest start time does %s exist as time point (pos %d)\n", (void*)profile, found ? "" : "not", pos);
7248
7249 /* if the position is the last time point in the profile, the core can be inserted at its earliest start time */
7250 if( pos == profile->ntimepoints - 1 )
7251 {
7252 (*infeasible) = FALSE;
7253 return est;
7254 }
7255
7256 if( found )
7257 {
7258 /* if the start time matches a time point in the profile we can just search */
7259 assert(profile->timepoints[pos] == est);
7260 pos = profileFindFeasibleStart(profile, pos, lst, duration, demand, infeasible);
7261
7262 assert(pos < profile->ntimepoints);
7263 est = profile->timepoints[pos];
7264 }
7265 else if( profile->loads[pos] + demand > profile->capacity )
7266 {
7267 /* if the the time point left to the start time has not enough free capacity we can just search the profile
7268 * starting from the next time point
7269 */
7270 assert(profile->timepoints[pos] <= est);
7271 pos = profileFindFeasibleStart(profile, pos+1, lst, duration, demand, infeasible);
7272
7273 assert(pos < profile->ntimepoints);
7274 est = profile->timepoints[pos];
7275 }
7276 else
7277 {
7278 int remainingduration;
7279
7280 /* check if the core can be placed at its earliest start time */
7281
7282 assert(pos < profile->ntimepoints - 1);
7283
7284 remainingduration = duration - (profile->timepoints[pos+1] - est);
7285 SCIPdebugMessage("remaining duration %d\n", remainingduration);
7286
7287 if( remainingduration <= 0 )
7288 (*infeasible) = FALSE;
7289 else
7290 {
7291 pos = profileFindFeasibleStart(profile, pos+1, profile->timepoints[pos+1], remainingduration, demand, infeasible);
7292 SCIPdebugMessage("remaining duration can%s be processed\n", *infeasible ? "not" : "");
7293
7294 if( *infeasible )
7295 {
7296 pos = profileFindFeasibleStart(profile, pos+1, lst, duration, demand, infeasible);
7297
7298 assert(pos < profile->ntimepoints);
7299 est = profile->timepoints[pos];
7300 }
7301 }
7302 }
7303
7304 return est;
7305}
7306
7307/** returns TRUE if the core (given by its demand and during) can be inserted at the given time point; otherwise FALSE */
7308static
7310 SCIP_PROFILE* profile, /**< resource profile to use */
7311 int pos, /**< pointer to store the position in the profile to start the search */
7312 int ect, /**< earliest completion time */
7313 int duration, /**< duration of the core */
7314 int demand, /**< demand of the core */
7315 SCIP_Bool* infeasible /**< pointer store if the corer cannot be inserted */
7316 )
7317{
7318 int remainingduration;
7319 int endpos;
7320
7321 assert(profile != NULL);
7322 assert(pos >= 0);
7323 assert(pos < profile->ntimepoints);
7324 assert(duration > 0);
7325 assert(demand > 0);
7326 assert(profile->ntimepoints > 0);
7327 assert(profile->loads[profile->ntimepoints-1] == 0);
7328
7329 remainingduration = duration;
7330 endpos = pos;
7331 (*infeasible) = TRUE;
7332
7333 if( profile->timepoints[endpos] < ect - duration )
7334 return pos;
7335
7336 while( pos > 0 )
7337 {
7338 if( profile->loads[pos-1] + demand > profile->capacity )
7339 {
7340 SCIPdebugMessage("profile <%p>: core does not fit at time point %d (pos %d)\n", (void*)profile, profile->timepoints[pos-1], pos-1);
7341
7342 endpos = pos - 1;
7343 remainingduration = duration;
7344
7345 if( profile->timepoints[endpos] < ect - duration )
7346 return pos;
7347 }
7348 else
7349 remainingduration -= profile->timepoints[pos] - profile->timepoints[pos-1];
7350
7351 if( remainingduration <= 0 )
7352 {
7353 *infeasible = FALSE;
7354 break;
7355 }
7356
7357 pos--;
7358 }
7359
7360 return endpos;
7361}
7362
7363/** return the latest possible starting point within the time interval [lb,ub] for a given core (given by its demand and
7364 * duration)
7365 */
7367 SCIP_PROFILE* profile, /**< resource profile to use */
7368 int est, /**< earliest possible start point */
7369 int lst, /**< latest possible start point */
7370 int duration, /**< duration of the core */
7371 int demand, /**< demand of the core */
7372 SCIP_Bool* infeasible /**< pointer store if the core cannot be inserted */
7373 )
7374{
7375 SCIP_Bool found;
7376 int ect;
7377 int lct;
7378 int pos;
7379
7380 assert(profile != NULL);
7381 assert(est >= 0);
7382 assert(est <= lst);
7383 assert(duration >= 0);
7384 assert(demand >= 0);
7385 assert(infeasible != NULL);
7386 assert(profile->ntimepoints > 0);
7387 assert(profile->loads[profile->ntimepoints-1] == 0);
7388
7389 if( duration == 0 || demand == 0 )
7390 {
7391 *infeasible = FALSE;
7392 return lst;
7393 }
7394
7395 ect = est + duration;
7396 lct = lst + duration;
7397
7398 found = SCIPprofileFindLeft(profile, lct, &pos);
7399 SCIPdebugMessage("profile <%p>: latest completion time %d does %s exist as time point (pos %d)\n", (void*)profile, lct, found ? "" : "not", pos);
7400
7401 if( found )
7402 {
7403 /* if the start time matches a time point in the profile we can just search */
7404 assert(profile->timepoints[pos] == lct);
7405 pos = profileFindDownFeasibleStart(profile, pos, ect, duration, demand, infeasible);
7406
7407 assert(pos < profile->ntimepoints && pos >= 0);
7408 lct = profile->timepoints[pos];
7409 }
7410 else if( profile->loads[pos] + demand > profile->capacity )
7411 {
7412 /* if the time point left to the start time has not enough free capacity we can just search the profile starting
7413 * from the next time point
7414 */
7415 assert(profile->timepoints[pos] < lct);
7416 pos = profileFindDownFeasibleStart(profile, pos, ect, duration, demand, infeasible);
7417
7418 assert(pos < profile->ntimepoints && pos >= 0);
7419 lct = profile->timepoints[pos];
7420 }
7421 else
7422 {
7423 int remainingduration;
7424
7425 /* check if the core can be placed at its latest start time */
7426 assert(profile->timepoints[pos] < lct);
7427
7428 remainingduration = duration - (lct - profile->timepoints[pos]);
7429
7430 if( remainingduration <= 0 )
7431 (*infeasible) = FALSE;
7432 else
7433 {
7434 pos = profileFindDownFeasibleStart(profile, pos, profile->timepoints[pos], remainingduration, demand, infeasible);
7435
7436 if( *infeasible )
7437 {
7438 pos = profileFindDownFeasibleStart(profile, pos, ect, duration, demand, infeasible);
7439
7440 assert(pos < profile->ntimepoints && pos >= 0);
7441 lct = profile->timepoints[pos];
7442 }
7443 }
7444 }
7445
7446 return lct - duration;
7447}
7448
7449/*
7450 * Directed graph
7451 */
7452
7453/** creates directed graph structure */
7455 SCIP_DIGRAPH** digraph, /**< pointer to store the created directed graph */
7456 BMS_BLKMEM* blkmem, /**< block memory to store the data */
7457 int nnodes /**< number of nodes */
7458 )
7459{
7460 assert(digraph != NULL);
7461 assert(blkmem != NULL);
7462 assert(nnodes > 0);
7463
7464 /* allocate memory for the graph and the arrays storing arcs and data */
7465 SCIP_ALLOC( BMSallocBlockMemory(blkmem, digraph) );
7466 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->successors, nnodes) );
7467 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->arcdata, nnodes) );
7468 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->successorssize, nnodes) );
7469 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->nsuccessors, nnodes) );
7470 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->nodedata, nnodes) );
7471
7472 /* store number of nodes */
7473 (*digraph)->nnodes = nnodes;
7474
7475 /* at the beginning, no components are stored */
7476 (*digraph)->blkmem = blkmem;
7477 (*digraph)->ncomponents = 0;
7478 (*digraph)->componentstartsize = 0;
7479 (*digraph)->components = NULL;
7480 (*digraph)->componentstarts = NULL;
7481
7482 /* all nodes are initially considered as non-articulation points */
7483 (*digraph)->narticulations = -1;
7484 (*digraph)->articulations = NULL;
7485 (*digraph)->articulationscheck = FALSE;
7486
7487 return SCIP_OKAY;
7488}
7489
7490/** resize directed graph structure */
7492 SCIP_DIGRAPH* digraph, /**< directed graph */
7493 int nnodes /**< new number of nodes */
7494 )
7495{
7496 int n;
7497 assert(digraph != NULL);
7498 assert(digraph->blkmem != NULL);
7499
7500 /* check if the digraph has already a proper size */
7501 if( nnodes <= digraph->nnodes )
7502 return SCIP_OKAY;
7503
7504 /* reallocate memory for increasing the arrays storing arcs and data */
7505 SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->successors, digraph->nnodes, nnodes) );
7506 SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->arcdata, digraph->nnodes, nnodes) );
7507 SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->successorssize, digraph->nnodes, nnodes) );
7508 SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->nsuccessors, digraph->nnodes, nnodes) );
7509 SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->nodedata, digraph->nnodes, nnodes) );
7510
7511 /* initialize the new node data structures */
7512 for( n = digraph->nnodes; n < nnodes; ++n )
7513 {
7514 digraph->nodedata[n] = NULL;
7515 digraph->arcdata[n] = NULL;
7516 digraph->successors[n] = NULL;
7517 digraph->successorssize[n] = 0;
7518 digraph->nsuccessors[n] = 0;
7519 }
7520
7521 /* store the new number of nodes */
7522 digraph->nnodes = nnodes;
7523
7524 return SCIP_OKAY;
7525}
7526
7527/** copies directed graph structure
7528 *
7529 * @note The data in nodedata is copied verbatim. This possibly has to be adapted by the user.
7530 */
7532 SCIP_DIGRAPH** targetdigraph, /**< pointer to store the copied directed graph */
7533 SCIP_DIGRAPH* sourcedigraph, /**< source directed graph */
7534 BMS_BLKMEM* targetblkmem /**< block memory to store the target block memory, or NULL to use the same
7535 * the same block memory as used for the \p sourcedigraph */
7536 )
7537{
7538 int ncomponents;
7539 int nnodes;
7540 int i;
7541 SCIP_Bool articulationscheck;
7542
7543 assert(sourcedigraph != NULL);
7544 assert(targetdigraph != NULL);
7545
7546 /* use the source digraph block memory if not specified otherwise */
7547 if( targetblkmem == NULL )
7548 targetblkmem = sourcedigraph->blkmem;
7549
7550 assert(targetblkmem != NULL);
7551
7552 SCIP_ALLOC( BMSallocBlockMemory(targetblkmem, targetdigraph) );
7553
7554 nnodes = sourcedigraph->nnodes;
7555 ncomponents = sourcedigraph->ncomponents;
7556 articulationscheck = sourcedigraph->articulationscheck;
7557 (*targetdigraph)->nnodes = nnodes;
7558 (*targetdigraph)->ncomponents = ncomponents;
7559 (*targetdigraph)->blkmem = targetblkmem;
7560
7561 /* copy arcs and data */
7562 SCIP_ALLOC( BMSallocClearBlockMemoryArray(targetblkmem, &(*targetdigraph)->successors, nnodes) );
7563 SCIP_ALLOC( BMSallocClearBlockMemoryArray(targetblkmem, &(*targetdigraph)->arcdata, nnodes) );
7564 SCIP_ALLOC( BMSallocClearBlockMemoryArray(targetblkmem, &(*targetdigraph)->nodedata, nnodes) );
7565
7566 /* copy lists of successors and arc data */
7567 for( i = 0; i < nnodes; ++i )
7568 {
7569 if( sourcedigraph->nsuccessors[i] > 0 )
7570 {
7571 assert(sourcedigraph->successors[i] != NULL);
7572 assert(sourcedigraph->arcdata[i] != NULL);
7573
7574 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &((*targetdigraph)->successors[i]),
7575 sourcedigraph->successors[i], sourcedigraph->nsuccessors[i]) ); /*lint !e866*/
7576 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &((*targetdigraph)->arcdata[i]),
7577 sourcedigraph->arcdata[i], sourcedigraph->nsuccessors[i]) ); /*lint !e866*/
7578 }
7579 /* copy node data - careful if these are pointers to some information -> need to be copied by hand */
7580 (*targetdigraph)->nodedata[i] = sourcedigraph->nodedata[i];
7581 }
7582
7583 /* use nsuccessors as size to save memory */
7584 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->successorssize, sourcedigraph->nsuccessors, nnodes) );
7585 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->nsuccessors, sourcedigraph->nsuccessors, nnodes) );
7586
7587 /* copy component data */
7588 if( ncomponents > 0 )
7589 {
7590 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->components, sourcedigraph->components,
7591 sourcedigraph->componentstarts[ncomponents]) );
7592 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->componentstarts,
7593 sourcedigraph->componentstarts,ncomponents + 1) ); /*lint !e776*/
7594 (*targetdigraph)->componentstartsize = ncomponents + 1;
7595 }
7596 else
7597 {
7598 (*targetdigraph)->components = NULL;
7599 (*targetdigraph)->componentstarts = NULL;
7600 (*targetdigraph)->componentstartsize = 0;
7601 }
7602
7603 /* copy the articulation point information if it has been computed and is up-to-date */
7604 if( articulationscheck )
7605 {
7606 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->articulations, sourcedigraph->articulations, sourcedigraph->narticulations) );
7607 (*targetdigraph)->narticulations = sourcedigraph->narticulations;
7608 (*targetdigraph)->articulationscheck = TRUE;
7609 }
7610 else
7611 {
7612 (*targetdigraph)->narticulations = -1;
7613 (*targetdigraph)->articulations = NULL;
7614 (*targetdigraph)->articulationscheck = FALSE;
7615 }
7616
7617 return SCIP_OKAY;
7618}
7619
7620/** sets the sizes of the successor lists for the nodes in a directed graph and allocates memory for the lists */
7622 SCIP_DIGRAPH* digraph, /**< directed graph */
7623 int* sizes /**< sizes of the successor lists */
7624 )
7625{
7626 int i;
7627 BMS_BLKMEM* blkmem;
7628
7629 assert(digraph != NULL);
7630 assert(digraph->nnodes > 0);
7631 blkmem = digraph->blkmem;
7632
7633 for( i = 0; i < digraph->nnodes; ++i )
7634 {
7635 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->successors[i], sizes[i]) ); /*lint !e866*/
7636 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->arcdata[i], sizes[i]) ); /*lint !e866*/
7637 digraph->successorssize[i] = sizes[i];
7638 digraph->nsuccessors[i] = 0;
7639 }
7640
7641 return SCIP_OKAY;
7642}
7643
7644/** frees given directed graph structure */
7646 SCIP_DIGRAPH** digraph /**< pointer to the directed graph */
7647 )
7648{
7649 int i;
7650 BMS_BLKMEM* blkmem;
7651 SCIP_DIGRAPH* digraphptr;
7652
7653 assert(digraph != NULL);
7654 assert(*digraph != NULL);
7655 assert((*digraph)->blkmem != NULL);
7656
7657 blkmem = (*digraph)->blkmem;
7658 digraphptr = *digraph;
7659
7660 /* free arrays storing the successor nodes and arc data */
7661 for( i = digraphptr->nnodes - 1; i >= 0; --i )
7662 {
7663 BMSfreeBlockMemoryArrayNull(blkmem, &digraphptr->successors[i], digraphptr->successorssize[i]);
7664 BMSfreeBlockMemoryArrayNull(blkmem, &digraphptr->arcdata[i], digraphptr->successorssize[i]);
7665 }
7666
7667 /* free components structure */
7668 SCIPdigraphFreeComponents(digraphptr);
7669 assert(digraphptr->ncomponents == 0);
7670 assert(digraphptr->componentstartsize == 0);
7671 assert(digraphptr->components == NULL);
7672 assert(digraphptr->componentstarts == NULL);
7673
7674 /* free the articulation points structure if it has been computed*/
7675 if( digraphptr->articulationscheck )
7676 BMSfreeBlockMemoryArray(blkmem, &digraphptr->articulations, digraphptr->narticulations);
7677
7678 /* free directed graph data structure */
7679 BMSfreeBlockMemoryArray(blkmem, &digraphptr->nodedata, digraphptr->nnodes);
7680 BMSfreeBlockMemoryArray(blkmem, &digraphptr->successorssize, digraphptr->nnodes);
7681 BMSfreeBlockMemoryArray(blkmem, &digraphptr->nsuccessors, digraphptr->nnodes);
7682 BMSfreeBlockMemoryArray(blkmem, &digraphptr->successors, digraphptr->nnodes);
7683 BMSfreeBlockMemoryArray(blkmem, &digraphptr->arcdata, digraphptr->nnodes);
7684
7685 BMSfreeBlockMemory(blkmem, digraph);
7686}
7687
7688#define STARTSUCCESSORSSIZE 5
7689
7690/** ensures that successors array of one node in a directed graph is big enough */
7691static
7693 SCIP_DIGRAPH* digraph, /**< directed graph */
7694 int idx, /**< index for which the size is ensured */
7695 int newsize /**< needed size */
7696 )
7697{
7698 BMS_BLKMEM* blkmem;
7699
7700 assert(digraph != NULL);
7701 assert(digraph->blkmem != NULL);
7702 assert(idx >= 0);
7703 assert(idx < digraph->nnodes);
7704 assert(newsize > 0);
7705 assert(digraph->successorssize[idx] == 0 || digraph->successors[idx] != NULL);
7706 assert(digraph->successorssize[idx] == 0 || digraph->arcdata[idx] != NULL);
7707
7708 blkmem = digraph->blkmem;
7709
7710 /* check whether array is big enough, and realloc, if needed */
7711 if( newsize > digraph->successorssize[idx] )
7712 {
7713 if( digraph->successors[idx] == NULL )
7714 {
7715 assert(digraph->arcdata[idx] == NULL);
7716 digraph->successorssize[idx] = STARTSUCCESSORSSIZE;
7717 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->successors[idx], digraph->successorssize[idx]) ); /*lint !e866*/
7718 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->arcdata[idx], digraph->successorssize[idx]) ); /*lint !e866*/
7719 }
7720 else
7721 {
7722 newsize = MAX(newsize, 2 * digraph->successorssize[idx]);
7723 assert(digraph->arcdata[idx] != NULL);
7724 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &digraph->successors[idx], digraph->successorssize[idx], newsize) ); /*lint !e866*/
7725 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &digraph->arcdata[idx], digraph->successorssize[idx], newsize) ); /*lint !e866*/
7726 digraph->successorssize[idx] = newsize;
7727 }
7728 }
7729
7730 assert(newsize <= digraph->successorssize[idx]);
7731
7732 return SCIP_OKAY;
7733}
7734
7735/** add (directed) arc and a related data to the directed graph structure
7736 *
7737 * @note if the arc is already contained, it is added a second time
7738 */
7740 SCIP_DIGRAPH* digraph, /**< directed graph */
7741 int startnode, /**< start node of the arc */
7742 int endnode, /**< start node of the arc */
7743 void* data /**< data that should be stored for the arc; or NULL */
7744 )
7745{
7746 assert(digraph != NULL);
7747 assert(startnode >= 0);
7748 assert(endnode >= 0);
7749 assert(startnode < digraph->nnodes);
7750 assert(endnode < digraph->nnodes);
7751
7752 SCIP_CALL( ensureSuccessorsSize(digraph, startnode, digraph->nsuccessors[startnode] + 1) );
7753
7754 /* add arc */
7755 digraph->successors[startnode][digraph->nsuccessors[startnode]] = endnode;
7756 digraph->arcdata[startnode][digraph->nsuccessors[startnode]] = data;
7757 digraph->nsuccessors[startnode]++;
7758
7759 /* the articulation points are not up-to-date */
7760 digraph->articulationscheck = FALSE;
7761
7762 return SCIP_OKAY;
7763}
7764
7765/** add (directed) arc to the directed graph structure, if it is not contained, yet
7766 *
7767 * @note if there already exists an arc from startnode to endnode, the new arc is not added,
7768 * even if its data is different
7769 */
7771 SCIP_DIGRAPH* digraph, /**< directed graph */
7772 int startnode, /**< start node of the arc */
7773 int endnode, /**< start node of the arc */
7774 void* data /**< data that should be stored for the arc; or NULL */
7775 )
7776{
7777 int nsuccessors;
7778 int i;
7779
7780 assert(digraph != NULL);
7781 assert(startnode >= 0);
7782 assert(endnode >= 0);
7783 assert(startnode < digraph->nnodes);
7784 assert(endnode < digraph->nnodes);
7785
7786 nsuccessors = digraph->nsuccessors[startnode];
7787
7788 /* search for the arc in existing arcs */
7789 for( i = 0; i < nsuccessors; ++i )
7790 if( digraph->successors[startnode][i] == endnode )
7791 return SCIP_OKAY;
7792
7793 SCIP_CALL( ensureSuccessorsSize(digraph, startnode, nsuccessors + 1) );
7794
7795 /* add arc */
7796 digraph->successors[startnode][nsuccessors] = endnode;
7797 digraph->arcdata[startnode][nsuccessors] = data;
7798 ++(digraph->nsuccessors[startnode]);
7799
7800 /* the articulation points are not up-to-date */
7801 digraph->articulationscheck = FALSE;
7802
7803 return SCIP_OKAY;
7804}
7805
7806/** sets the number of successors to a given value */
7808 SCIP_DIGRAPH* digraph, /**< directed graph */
7809 int node, /**< node for which the number of successors has to be changed */
7810 int nsuccessors /**< new number of successors */
7811 )
7812{
7813 assert(digraph != NULL);
7814 assert(node >= 0);
7815 assert(node < digraph->nnodes);
7816
7817 digraph->nsuccessors[node] = nsuccessors;
7818
7819 return SCIP_OKAY;
7820}
7821
7822/** returns the number of nodes of the given digraph */
7824 SCIP_DIGRAPH* digraph /**< directed graph */
7825 )
7826{
7827 assert(digraph != NULL);
7828
7829 return digraph->nnodes;
7830}
7831
7832/** returns the node data, or NULL if no data exist */
7834 SCIP_DIGRAPH* digraph, /**< directed graph */
7835 int node /**< node for which the node data is returned */
7836 )
7837{
7838 assert(digraph != NULL);
7839 assert(node >= 0);
7840 assert(node < digraph->nnodes);
7841
7842 return digraph->nodedata[node];
7843}
7844
7845/** sets the node data
7846 *
7847 * @note The old user pointer is not freed. This has to be done by the user
7848 */
7850 SCIP_DIGRAPH* digraph, /**< directed graph */
7851 void* dataptr, /**< user node data pointer, or NULL */
7852 int node /**< node for which the node data is returned */
7853 )
7854{
7855 assert(digraph != NULL);
7856 assert(node >= 0);
7857 assert(node < digraph->nnodes);
7858
7859 digraph->nodedata[node] = dataptr;
7860}
7861
7862/** returns the total number of arcs in the given digraph */
7864 SCIP_DIGRAPH* digraph /**< directed graph */
7865 )
7866{
7867 int i;
7868 int narcs;
7869
7870 assert(digraph != NULL);
7871
7872 /* count number of arcs */
7873 narcs = 0;
7874 for( i = 0; i < digraph->nnodes; ++i )
7875 narcs += digraph->nsuccessors[i];
7876
7877 return narcs;
7878}
7879
7880/** returns the number of successor nodes of the given node */
7882 SCIP_DIGRAPH* digraph, /**< directed graph */
7883 int node /**< node for which the number of outgoing arcs is returned */
7884 )
7885{
7886 assert(digraph != NULL);
7887 assert(node >= 0);
7888 assert(node < digraph->nnodes);
7889 assert(digraph->nsuccessors[node] >= 0);
7890 assert(digraph->nsuccessors[node] <= digraph->successorssize[node]);
7891
7892 return digraph->nsuccessors[node];
7893}
7894
7895/** returns the array of indices of the successor nodes; this array must not be changed from outside */
7897 SCIP_DIGRAPH* digraph, /**< directed graph */
7898 int node /**< node for which the array of outgoing arcs is returned */
7899 )
7900{
7901 assert(digraph != NULL);
7902 assert(node >= 0);
7903 assert(node < digraph->nnodes);
7904 assert(digraph->nsuccessors[node] >= 0);
7905 assert(digraph->nsuccessors[node] <= digraph->successorssize[node]);
7906 assert((digraph->nsuccessors[node] == 0) || (digraph->successors[node] != NULL));
7907
7908 return digraph->successors[node];
7909}
7910
7911/** returns the array of data corresponding to the arcs originating at the given node, or NULL if no data exist; this
7912 * array must not be changed from outside
7913 */
7915 SCIP_DIGRAPH* digraph, /**< directed graph */
7916 int node /**< node for which the data corresponding to the outgoing arcs is returned */
7917 )
7918{
7919 assert(digraph != NULL);
7920 assert(node >= 0);
7921 assert(node < digraph->nnodes);
7922 assert(digraph->nsuccessors[node] >= 0);
7923 assert(digraph->nsuccessors[node] <= digraph->successorssize[node]);
7924 assert(digraph->arcdata != NULL);
7925
7926 return digraph->arcdata[node];
7927}
7928
7929/** performs depth-first-search in the given directed graph from the given start node */
7930static
7932 SCIP_DIGRAPH* digraph, /**< directed graph */
7933 int startnode, /**< node to start the depth-first-search */
7934 SCIP_Bool* visited, /**< array to store for each node, whether it was already visited */
7935 int* dfsstack, /**< array of size number of nodes to store the stack;
7936 * only needed for performance reasons */
7937 int* stackadjvisited, /**< array of size number of nodes to store the number of adjacent nodes already visited
7938 * for each node on the stack; only needed for performance reasons */
7939 int* dfsnodes, /**< array of nodes that can be reached starting at startnode, in reverse dfs order */
7940 int* ndfsnodes /**< pointer to store number of nodes that can be reached starting at startnode */
7941 )
7942{
7943 int stackidx;
7944
7945 assert(digraph != NULL);
7946 assert(startnode >= 0);
7947 assert(startnode < digraph->nnodes);
7948 assert(visited != NULL);
7949 assert(visited[startnode] == FALSE);
7950 assert(dfsstack != NULL);
7951 assert(dfsnodes != NULL);
7952 assert(ndfsnodes != NULL);
7953
7954 /* put start node on the stack */
7955 dfsstack[0] = startnode;
7956 stackadjvisited[0] = 0;
7957 stackidx = 0;
7958
7959 while( stackidx >= 0 )
7960 {
7961 int currnode;
7962 int sadv;
7963
7964 /* get next node from stack */
7965 currnode = dfsstack[stackidx];
7966
7967 sadv = stackadjvisited[stackidx];
7968 assert( 0 <= sadv && sadv <= digraph->nsuccessors[currnode] );
7969
7970 /* mark current node as visited */
7971 assert( visited[currnode] == (sadv > 0) );
7972 visited[currnode] = TRUE;
7973
7974 /* iterate through the successor list until we reach unhandled node */
7975 while( sadv < digraph->nsuccessors[currnode] && visited[digraph->successors[currnode][sadv]] )
7976 ++sadv;
7977
7978 /* the current node was completely handled, remove it from stack */
7979 if( sadv == digraph->nsuccessors[currnode] )
7980 {
7981 --stackidx;
7982
7983 /* store node in the sorted nodes array */
7984 dfsnodes[(*ndfsnodes)++] = currnode;
7985 }
7986 /* handle next unhandled successor node */
7987 else
7988 {
7989 assert( ! visited[digraph->successors[currnode][sadv]] );
7990
7991 /* store current stackadjvisted index */
7992 stackadjvisited[stackidx] = sadv + 1;
7993
7994 /* put the successor node onto the stack */
7995 ++stackidx;
7996 dfsstack[stackidx] = digraph->successors[currnode][sadv];
7997 stackadjvisited[stackidx] = 0;
7998 assert( stackidx < digraph->nnodes );
7999 }
8000 }
8001}
8002
8003/** checks for articulation points in a given directed graph through a recursive depth-first-search.
8004 * starts from a given start node and keeps track of the nodes' discovery time in search for back edges.
8005 *
8006 * @note an articulation point is a node whose removal disconnects a connected graph or increases
8007 * the number of connected components in a disconnected graph
8008 */
8009static
8011 SCIP_DIGRAPH* digraph, /**< directed graph */
8012 int startnode, /**< node to start the depth-first-search */
8013 SCIP_Bool* visited, /**< array to store for each node, whether it was already visited */
8014 int* tdisc, /**< array of size number of nodes to store each node's discovery time */
8015 int* mindisc, /**< array of size number of nodes to store the discovery time of the earliest discovered vertex
8016 * to which startnode (or any node in the subtree rooted at it) is having a back edge */
8017 int* parent, /**< array to store the parent of each node in the DFS tree */
8018 SCIP_Bool* articulationflag, /**< array to mark whether a node is identified as an articulation point */
8019 int time /**< current discovery time in the DFS */
8020 )
8021{
8022 int n;
8023 int nchildren = 0;
8024 int nsucc;
8025 int* succnodes;
8026
8027 assert(digraph != NULL);
8028 assert(startnode >= 0);
8029 assert(startnode < digraph->nnodes);
8030 assert(visited != NULL);
8031 assert(visited[startnode] == FALSE);
8032 assert(tdisc != NULL);
8033 assert(mindisc != NULL);
8034 assert(parent != NULL);
8035 assert(articulationflag != NULL);
8036 assert(time >= 0);
8037
8038 nsucc = (int) SCIPdigraphGetNSuccessors(digraph, startnode);
8039 succnodes = (int*) SCIPdigraphGetSuccessors(digraph, startnode);
8040 visited[startnode] = TRUE;
8041 tdisc[startnode] = time + 1;
8042 mindisc[startnode] = time + 1;
8043
8044 /* process all the adjacent nodes to startnode */
8045 for( n = 0; n < nsucc; ++n)
8046 {
8047 if( !visited[succnodes[n]] )
8048 {
8049 parent[succnodes[n]] = startnode;
8050 ++nchildren;
8051 findArticulationPointsUtil(digraph, succnodes[n], visited, tdisc, mindisc, parent, articulationflag, time + 1);
8052 /* updated the mindisc of startnode when the DFS concludes for node n*/
8053 mindisc[startnode] = MIN(mindisc[startnode], mindisc[succnodes[n]]);
8054
8055 /* the root is an articulation point if it has more than 2 children*/
8056 if( parent[startnode] == -1 && nchildren > 1 )
8057 articulationflag[startnode] = TRUE;
8058 /* a vertex startnode is an articulation point if it is not the root and
8059 * there is no back edge from the subtree rooted at child n to any of the ancestors of startnode */
8060 if( parent[startnode] > -1 && mindisc[succnodes[n]] >= tdisc[startnode] )
8061 articulationflag[startnode] = TRUE;
8062 }
8063 else
8064 {
8065 if( parent[startnode] != succnodes[n] )
8066 mindisc[startnode] = MIN(mindisc[startnode], tdisc[succnodes[n]]);
8067 }
8068 }
8069
8070 if( articulationflag[startnode] )
8071 ++digraph->narticulations;
8072}
8073
8074/** identifies the articulation points in a given directed graph
8075 * uses the helper recursive function findArticulationPointsUtil
8076 */
8078 SCIP_DIGRAPH* digraph, /**< directed graph */
8079 int** articulations, /**< array to store the sorted node indices of the computed articulation points, or NULL */
8080 int* narticulations /**< number of the computed articulation points, or NULL */
8081 )
8082{
8083 SCIP_RETCODE retcode = SCIP_OKAY;
8084 BMS_BLKMEM* blkmem;
8085 SCIP_Bool* visited = NULL;
8086 SCIP_Bool* articulationflag = NULL;
8087 int* tdisc = NULL;
8088 int* mindisc = NULL;
8089 int* parent = NULL;
8090 int n;
8091 int articulationidx = 0;
8092 int time = 0;
8093
8094 assert(digraph != NULL);
8095 assert(digraph->nnodes > 0);
8096
8097 /* Only perform the computation if the articulation points are NOT up-to-date */
8098 if( !digraph->articulationscheck )
8099 {
8100 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&visited, digraph->nnodes), TERMINATE );
8101 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&tdisc, digraph->nnodes), TERMINATE );
8102 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&mindisc, digraph->nnodes), TERMINATE );
8103 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&parent, digraph->nnodes), TERMINATE );
8104 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&articulationflag, digraph->nnodes), TERMINATE );
8105
8106 assert(digraph->blkmem != NULL);
8107 blkmem = digraph->blkmem;
8108
8109 if( digraph->narticulations >= 0 ) /* case: articulations have already been computed but not up-to-date */
8110 BMSfreeBlockMemoryArray(blkmem, &digraph->articulations, digraph->narticulations);
8111
8112 /* Initialize the no. of articulation points ahead of the recursive computation */
8113 digraph->narticulations = 0;
8114
8115 for( n = 0; n < digraph->nnodes; ++n )
8116 {
8117 visited[n] = FALSE;
8118 parent[n] = -1;
8119 articulationflag[n] = FALSE;
8120 }
8121
8122 /* the function is called on every unvisited node in the graph to cover the disconnected graph case */
8123 for( n = 0; n < digraph->nnodes; ++n )
8124 {
8125 if( !visited[n] )
8126 findArticulationPointsUtil(digraph, n, visited, tdisc, mindisc, parent, articulationflag, time);
8127 }
8128
8129 /* allocation of the block memory for the node indices of the articulation points*/
8130 SCIP_ALLOC_TERMINATE( retcode, BMSallocBlockMemoryArray(blkmem, &digraph->articulations, digraph->narticulations), TERMINATE );
8131
8132 for( n = 0; n < digraph->nnodes; ++n )
8133 {
8134 if( articulationflag[n] )
8135 {
8136 digraph->articulations[articulationidx] = n;
8137 ++articulationidx;
8138 }
8139 }
8140 }
8141
8142 if( articulations != NULL )
8143 (*articulations) = digraph->articulations;
8144 if( narticulations != NULL )
8145 (*narticulations) = digraph->narticulations;
8146
8147 /* the articulation points are now up-to-date */
8148 digraph->articulationscheck = TRUE;
8149
8150TERMINATE:
8151 BMSfreeMemoryArrayNull(&articulationflag);
8152 BMSfreeMemoryArrayNull(&parent);
8153 BMSfreeMemoryArrayNull(&mindisc);
8154 BMSfreeMemoryArrayNull(&tdisc);
8155 BMSfreeMemoryArrayNull(&visited);
8156
8157 return retcode;
8158}
8159
8160/** Compute undirected connected components on the given graph.
8161 *
8162 * @note For each arc, its reverse is added, so the graph does not need to be the directed representation of an
8163 * undirected graph.
8164 */
8166 SCIP_DIGRAPH* digraph, /**< directed graph */
8167 int minsize, /**< all components with less nodes are ignored */
8168 int* components, /**< array with as many slots as there are nodes in the directed graph
8169 * to store for each node the component to which it belongs
8170 * (components are numbered 0 to ncomponents - 1); or NULL, if components
8171 * are accessed one-by-one using SCIPdigraphGetComponent() */
8172 int* ncomponents /**< pointer to store the number of components; or NULL, if the
8173 * number of components is accessed by SCIPdigraphGetNComponents() */
8174 )
8175{
8176 BMS_BLKMEM* blkmem;
8177 SCIP_Bool* visited;
8178 int* ndirectedsuccessors;
8179 int* stackadjvisited;
8180 int* dfsstack;
8181 int ndfsnodes;
8182 int compstart;
8183 int v;
8184 int i;
8185 int j;
8186
8187 SCIP_RETCODE retcode = SCIP_OKAY;
8188
8189 assert(digraph != NULL);
8190 assert(digraph->nnodes > 0);
8191 assert(digraph->blkmem != NULL);
8192
8193 blkmem = digraph->blkmem;
8194
8195 /* first free the old components */
8196 if( digraph->ncomponents > 0 )
8197 {
8199 }
8200
8201 digraph->ncomponents = 0;
8202 digraph->componentstartsize = 10;
8203
8204 /* storage to hold components is stored in block memory */
8205 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->components, digraph->nnodes) );
8207
8208 /* allocate temporary arrays */
8209 SCIP_ALLOC_TERMINATE( retcode, BMSallocClearMemoryArray(&visited, digraph->nnodes), TERMINATE );
8210 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsstack, digraph->nnodes), TERMINATE );
8211 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&stackadjvisited, digraph->nnodes), TERMINATE );
8212 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&ndirectedsuccessors, digraph->nnodes), TERMINATE );
8213
8214 digraph->componentstarts[0] = 0;
8215
8216 /* store the number of directed arcs per node */
8217 BMScopyMemoryArray(ndirectedsuccessors, digraph->nsuccessors, digraph->nnodes);
8218
8219 /* add reverse arcs to the graph */
8220 for( i = digraph->nnodes - 1; i >= 0; --i )
8221 {
8222 for( j = 0; j < ndirectedsuccessors[i]; ++j )
8223 {
8224 SCIP_CALL_TERMINATE( retcode, SCIPdigraphAddArc(digraph, digraph->successors[i][j], i, NULL), TERMINATE );
8225 }
8226 }
8227
8228 for( v = 0; v < digraph->nnodes; ++v )
8229 {
8230 if( visited[v] )
8231 continue;
8232
8233 compstart = digraph->componentstarts[digraph->ncomponents];
8234 ndfsnodes = 0;
8235 depthFirstSearch(digraph, v, visited, dfsstack, stackadjvisited,
8236 &digraph->components[compstart], &ndfsnodes);
8237
8238 /* forget about this component if it is too small */
8239 if( ndfsnodes >= minsize )
8240 {
8241 digraph->ncomponents++;
8242
8243 /* enlarge componentstartsize array, if needed */
8244 if( digraph->ncomponents >= digraph->componentstartsize )
8245 {
8246 int newsize;
8247
8248 newsize = 2 * digraph->componentstartsize;
8249 assert(digraph->ncomponents < newsize);
8250
8251 SCIP_ALLOC_TERMINATE( retcode, BMSreallocBlockMemoryArray(blkmem, &digraph->componentstarts, digraph->componentstartsize, newsize), TERMINATE );
8252 digraph->componentstartsize = newsize;
8253 }
8254 digraph->componentstarts[digraph->ncomponents] = compstart + ndfsnodes;
8255
8256 /* store component number for contained nodes if array was given */
8257 if( components != NULL )
8258 {
8259 for( i = digraph->componentstarts[digraph->ncomponents] - 1; i >= compstart; --i )
8260 {
8261 components[digraph->components[i]] = digraph->ncomponents - 1;
8262 }
8263 }
8264 }
8265 }
8266
8267 /* restore the number of directed arcs per node */
8268 BMScopyMemoryArray(digraph->nsuccessors, ndirectedsuccessors, digraph->nnodes);
8269 BMSclearMemoryArray(visited, digraph->nnodes);
8270
8271 /* return number of components, if the pointer was given */
8272 if( ncomponents != NULL )
8273 (*ncomponents) = digraph->ncomponents;
8274
8275TERMINATE:
8276 if( retcode != SCIP_OKAY )
8277 {
8279 }
8280 /* coverity[uninit_use_in_call] */
8281 BMSfreeMemoryArrayNull(&ndirectedsuccessors);
8282 BMSfreeMemoryArrayNull(&stackadjvisited);
8283 BMSfreeMemoryArrayNull(&dfsstack);
8284 BMSfreeMemoryArrayNull(&visited);
8285
8286 return retcode;
8287}
8288
8289/** Performs an (almost) topological sort on the undirected components of the given directed graph. The undirected
8290 * components should be computed before using SCIPdigraphComputeUndirectedComponents().
8291 *
8292 * @note In general a topological sort is not unique. Note, that there might be directed cycles, that are randomly
8293 * broken, which is the reason for having only almost topologically sorted arrays.
8294 */
8296 SCIP_DIGRAPH* digraph /**< directed graph */
8297 )
8298{
8299 SCIP_Bool* visited = NULL;
8300 int* comps;
8301 int* compstarts;
8302 int* stackadjvisited = NULL;
8303 int* dfsstack = NULL;
8304 int* dfsnodes = NULL;
8305 int ndfsnodes;
8306 int ncomps;
8307 int i;
8308 int j;
8309 int k;
8310 int endidx;
8311 SCIP_RETCODE retcode = SCIP_OKAY;
8312
8313 assert(digraph != NULL);
8314
8315 ncomps = digraph->ncomponents;
8316 comps = digraph->components;
8317 compstarts = digraph->componentstarts;
8318
8319 SCIP_ALLOC_TERMINATE( retcode, BMSallocClearMemoryArray(&visited, digraph->nnodes), TERMINATE );
8320 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsnodes, digraph->nnodes), TERMINATE );
8321 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsstack, digraph->nnodes), TERMINATE );
8322 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&stackadjvisited, digraph->nnodes), TERMINATE );
8323
8324 /* sort the components (almost) topologically */
8325 for( i = 0; i < ncomps; ++i )
8326 {
8327 endidx = compstarts[i+1] - 1;
8328 ndfsnodes = 0;
8329 for( j = compstarts[i]; j < compstarts[i+1]; ++j )
8330 {
8331 if( visited[comps[j]] )
8332 continue;
8333
8334 /* perform depth first search, nodes visited in this call are appended to the list dfsnodes in reverse
8335 * dfs order, after the nodes already contained;
8336 * so at every point in time, the nodes in dfsnode are in reverse (almost) topological order
8337 */
8338 depthFirstSearch(digraph, comps[j], visited, dfsstack, stackadjvisited, dfsnodes, &ndfsnodes);
8339 }
8340 assert(endidx - ndfsnodes == compstarts[i] - 1);
8341
8342 /* copy reverse (almost) topologically sorted array of nodes reached by the dfs searches;
8343 * reverse their order to get an (almost) topologically sort
8344 */
8345 for( k = 0; k < ndfsnodes; ++k )
8346 {
8347 digraph->components[endidx - k] = dfsnodes[k];
8348 }
8349 }
8350
8351TERMINATE:
8352 BMSfreeMemoryArrayNull(&stackadjvisited);
8353 BMSfreeMemoryArrayNull(&dfsstack);
8354 BMSfreeMemoryArrayNull(&dfsnodes);
8355 BMSfreeMemoryArrayNull(&visited);
8356
8357 return retcode;
8358}
8359
8360/** returns the number of previously computed undirected components for the given directed graph */
8362 SCIP_DIGRAPH* digraph /**< directed graph */
8363 )
8364{
8365 assert(digraph != NULL);
8366 assert(digraph->componentstartsize > 0); /* components should have been computed */
8367
8368 return digraph->ncomponents;
8369}
8370
8371/** Returns the previously computed undirected component of the given number for the given directed graph.
8372 * If the components were sorted using SCIPdigraphTopoSortComponents(), the component is (almost) topologically sorted.
8373 */
8375 SCIP_DIGRAPH* digraph, /**< directed graph */
8376 int compidx, /**< number of the component to return */
8377 int** nodes, /**< pointer to store the nodes in the component; or NULL, if not needed */
8378 int* nnodes /**< pointer to store the number of nodes in the component;
8379 * or NULL, if not needed */
8380 )
8381{
8382 assert(digraph != NULL);
8383 assert(compidx >= 0);
8384 assert(compidx < digraph->ncomponents);
8385 assert(nodes != NULL || nnodes != NULL);
8386
8387 if( nodes != NULL )
8388 (*nodes) = &(digraph->components[digraph->componentstarts[compidx]]);
8389 if( nnodes != NULL )
8390 (*nnodes) = digraph->componentstarts[compidx + 1] - digraph->componentstarts[compidx];
8391}
8392
8393/* Performs Tarjan's algorithm for a given directed graph to obtain the strongly connected components
8394 * which are reachable from a given node.
8395 */
8396static
8398 SCIP_DIGRAPH* digraph, /**< directed graph */
8399 int v, /**< node to start the algorithm */
8400 int* lowlink, /**< array to store lowlink values */
8401 int* dfsidx, /**< array to store dfs indices */
8402 int* stack, /**< array to store a stack */
8403 int* stacksize, /**< pointer to store the size of the stack */
8404 SCIP_Bool* unprocessed, /**< array to store which node is unprocessed yet */
8405 SCIP_Bool* nodeinstack, /**< array to store which nodes are in the stack */
8406 int* maxdfs, /**< pointer to store index for DFS */
8407 int* strongcomponents, /**< array to store for each node the strongly connected
8408 * component to which it belongs (components are
8409 * numbered 0 to nstrongcomponents - 1); */
8410 int* nstrongcomponents, /**< pointer to store the number of computed components so far */
8411 int* strongcompstartidx, /**< array to store the start index of the computed components */
8412 int* nstorednodes /**< pointer to store the number of already stored nodes */
8413 )
8414{
8415 int i;
8416
8417 assert(digraph != NULL);
8418 assert(v >= 0);
8419 assert(v < digraph->nnodes);
8420 assert(lowlink != NULL);
8421 assert(dfsidx != NULL);
8422 assert(stack != NULL);
8423 assert(stacksize != NULL);
8424 assert(*stacksize >= 0);
8425 assert(*stacksize < digraph->nnodes);
8426 assert(unprocessed != NULL);
8427 assert(nodeinstack != NULL);
8428 assert(maxdfs != NULL);
8429 assert(strongcomponents != NULL);
8430 assert(nstrongcomponents != NULL);
8431 assert(strongcompstartidx != NULL);
8432 assert(nstorednodes != NULL);
8433 assert(*nstorednodes >= 0 && *nstorednodes < digraph->nnodes);
8434
8435 dfsidx[v] = *maxdfs;
8436 lowlink[v] = *maxdfs;
8437 *maxdfs += 1;
8438
8439 /* add v to the stack */
8440 stack[*stacksize] = v;
8441 *stacksize += 1;
8442 nodeinstack[v] = TRUE;
8443
8444 /* mark v as processed */
8445 unprocessed[v] = FALSE;
8446
8447 for( i = 0; i < digraph->nsuccessors[v]; ++i )
8448 {
8449 int w;
8450
8451 /* edge (v,w) */
8452 w = digraph->successors[v][i];
8453
8454 if( unprocessed[w] )
8455 {
8456 tarjan(digraph, w, lowlink, dfsidx, stack, stacksize, unprocessed, nodeinstack, maxdfs, strongcomponents,
8457 nstrongcomponents, strongcompstartidx, nstorednodes);
8458
8459 assert(lowlink[v] >= 0 && lowlink[v] < digraph->nnodes);
8460 assert(lowlink[w] >= 0 && lowlink[w] < digraph->nnodes);
8461
8462 /* update lowlink */
8463 lowlink[v] = MIN(lowlink[v], lowlink[w]);
8464 }
8465 else if( nodeinstack[w] )
8466 {
8467 assert(lowlink[v] >= 0 && lowlink[v] < digraph->nnodes);
8468 assert(dfsidx[w] >= 0 && dfsidx[w] < digraph->nnodes);
8469
8470 /* update lowlink */
8471 lowlink[v] = MIN(lowlink[v], dfsidx[w]);
8472 }
8473 }
8474
8475 /* found a root of a strong component */
8476 if( lowlink[v] == dfsidx[v] )
8477 {
8478 int w;
8479
8480 strongcompstartidx[*nstrongcomponents] = *nstorednodes;
8481 *nstrongcomponents += 1;
8482
8483 do
8484 {
8485 assert(*stacksize > 0);
8486
8487 /* stack.pop() */
8488 w = stack[*stacksize - 1];
8489 *stacksize -= 1;
8490 nodeinstack[w] = FALSE;
8491
8492 /* store the node in the corresponding component */
8493 strongcomponents[*nstorednodes] = w;
8494 *nstorednodes += 1;
8495 }
8496 while( v != w );
8497 }
8498}
8499
8500/** Computes all strongly connected components of an undirected connected component with Tarjan's Algorithm.
8501 * The resulting strongly connected components are sorted topologically (starting from the end of the
8502 * strongcomponents array).
8503 *
8504 * @note In general a topological sort of the strongly connected components is not unique.
8505 */
8507 SCIP_DIGRAPH* digraph, /**< directed graph */
8508 int compidx, /**< number of the undirected connected component */
8509 int* strongcomponents, /**< array to store the strongly connected components
8510 * (length >= size of the component) */
8511 int* strongcompstartidx, /**< array to store the start indices of the strongly connected
8512 * components (length >= size of the component) */
8513 int* nstrongcomponents /**< pointer to store the number of strongly connected
8514 * components */
8515 )
8516{
8517 int* lowlink = NULL;
8518 int* dfsidx = NULL;
8519 int* stack = NULL;
8520 int stacksize;
8521 SCIP_Bool* unprocessed = NULL;
8522 SCIP_Bool* nodeinstack = NULL;
8523 int maxdfs;
8524 int nstorednodes;
8525 int i;
8526 SCIP_RETCODE retcode;
8527
8528 assert(digraph != NULL);
8529 assert(compidx >= 0);
8530 assert(compidx < digraph->ncomponents);
8531 assert(strongcomponents != NULL);
8532 assert(strongcompstartidx != NULL);
8533 assert(nstrongcomponents != NULL);
8534
8535 retcode = SCIP_OKAY;
8536
8537 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&lowlink, digraph->nnodes), TERMINATE );
8538 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsidx, digraph->nnodes), TERMINATE );
8539 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&stack, digraph->nnodes), TERMINATE );
8540 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&unprocessed, digraph->nnodes), TERMINATE );
8541 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&nodeinstack, digraph->nnodes), TERMINATE );
8542
8543 for( i = 0; i < digraph->nnodes; ++i )
8544 {
8545 lowlink[i] = -1;
8546 dfsidx[i] = -1;
8547 stack[i] = -1;
8548 unprocessed[i] = TRUE;
8549 nodeinstack[i] = FALSE;
8550 }
8551
8552 nstorednodes = 0;
8553 stacksize = 0;
8554 maxdfs = 0;
8555 *nstrongcomponents = 0;
8556
8557 /* iterate over all nodes in the undirected connected component */
8558 for( i = digraph->componentstarts[compidx]; i < digraph->componentstarts[compidx + 1]; ++i )
8559 {
8560 int v;
8561
8562 v = digraph->components[i];
8563 assert(v >= 0 && v < digraph->nnodes);
8564
8565 /* call Tarjan's algorithm for unprocessed nodes */
8566 if( unprocessed[v] )
8567 {
8568 SCIPdebugMessage("apply Tarjan's algorithm for node %d\n", v);
8569 tarjan(digraph, v, lowlink, dfsidx, stack, &stacksize, unprocessed, nodeinstack, &maxdfs,
8570 strongcomponents, nstrongcomponents, strongcompstartidx, &nstorednodes);
8571 }
8572 }
8573
8574 /* we should have stored as many nodes as in the undirected connected component */
8575 assert(nstorednodes == digraph->componentstarts[compidx + 1] - digraph->componentstarts[compidx]);
8576
8577 /* to simplify the iteration over all strongly connected components */
8578 assert(*nstrongcomponents < digraph->nnodes + 1);
8579 strongcompstartidx[*nstrongcomponents] = nstorednodes;
8580
8581 assert(retcode == SCIP_OKAY);
8582
8583TERMINATE:
8584 BMSfreeMemoryArrayNull(&lowlink);
8585 BMSfreeMemoryArrayNull(&dfsidx);
8586 BMSfreeMemoryArrayNull(&stack);
8587 BMSfreeMemoryArrayNull(&unprocessed);
8588 BMSfreeMemoryArrayNull(&nodeinstack);
8589
8590 return retcode;
8591}
8592
8593/** frees the component information for the given directed graph */
8595 SCIP_DIGRAPH* digraph /**< directed graph */
8596 )
8597{
8598 BMS_BLKMEM* blkmem;
8599
8600 assert(digraph != NULL);
8601 assert(digraph->blkmem != NULL);
8602
8603 blkmem = digraph->blkmem;
8604
8605 /* free components structure */
8606 if( digraph->componentstartsize > 0 )
8607 {
8608 BMSfreeBlockMemoryArray(blkmem, &digraph->componentstarts, digraph->componentstartsize);
8609 BMSfreeBlockMemoryArray(blkmem, &digraph->components, digraph->nnodes);
8610 digraph->components = NULL;
8611 digraph->componentstarts = NULL;
8612 digraph->ncomponents = 0;
8613 digraph->componentstartsize = 0;
8614 }
8615#ifndef NDEBUG
8616 else
8617 {
8618 assert(digraph->components == NULL);
8619 assert(digraph->componentstarts == NULL);
8620 assert(digraph->ncomponents == 0);
8621 }
8622#endif
8623}
8624
8625/** output of the given directed graph via the given message handler */
8627 SCIP_DIGRAPH* digraph, /**< directed graph */
8628 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
8629 FILE* file /**< output file (or NULL for standard output) */
8630 )
8631{
8632 int n;
8633
8634 for( n = 0; n < digraph->nnodes; ++n )
8635 {
8636 int* successors;
8637 int nsuccessors;
8638 int m;
8639
8640 nsuccessors = digraph->nsuccessors[n];
8641 successors = digraph->successors[n];
8642
8643 SCIPmessageFPrintInfo(messagehdlr, file, "node %d --> ", n);
8644
8645 for( m = 0; m < nsuccessors ; ++m )
8646 {
8647 if( m == 0 )
8648 {
8649 SCIPmessageFPrintInfo(messagehdlr, file, "%d", successors[m]);
8650 }
8651 else
8652 {
8653 SCIPmessageFPrintInfo(messagehdlr, file, ", %d", successors[m]);
8654 }
8655 }
8656 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
8657 }
8658}
8659
8660/** prints the given directed graph structure in GML format into the given file */
8662 SCIP_DIGRAPH* digraph, /**< directed graph */
8663 FILE* file /**< file to write to */
8664 )
8665{
8666 int n;
8667
8668 /* write GML format opening */
8670
8671 /* write all nodes of the graph */
8672 for( n = 0; n < digraph->nnodes; ++n )
8673 {
8674 char label[SCIP_MAXSTRLEN];
8675
8676 (void)SCIPsnprintf(label, SCIP_MAXSTRLEN, "%d", n);
8677 SCIPgmlWriteNode(file, (unsigned int)n, label, "circle", NULL, NULL);
8678 }
8679
8680 /* write all edges */
8681 for( n = 0; n < digraph->nnodes; ++n )
8682 {
8683 int* successors;
8684 int nsuccessors;
8685 int m;
8686
8687 nsuccessors = digraph->nsuccessors[n];
8688 successors = digraph->successors[n];
8689
8690 for( m = 0; m < nsuccessors; ++m )
8691 {
8692 SCIPgmlWriteArc(file, (unsigned int)n, (unsigned int)successors[m], NULL, NULL);
8693 }
8694 }
8695 /* write GML format closing */
8696 SCIPgmlWriteClosing(file);
8697}
8698
8699/** output of the given directed graph via the given message handler */
8701 SCIP_DIGRAPH* digraph, /**< directed graph */
8702 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
8703 FILE* file /**< output file (or NULL for standard output) */
8704 )
8705{
8706 int c;
8707 int i;
8708
8709 for( c = 0; c < digraph->ncomponents; ++c )
8710 {
8711 int start = digraph->componentstarts[c];
8712 int end = digraph->componentstarts[c+1];
8713
8714 SCIPmessageFPrintInfo(messagehdlr, file, "Components %d --> ", c);
8715
8716 for( i = start; i < end; ++i )
8717 {
8718 if( i == start )
8719 {
8720 SCIPmessageFPrintInfo(messagehdlr, file, "%d", digraph->components[i]);
8721 }
8722 else
8723 {
8724 SCIPmessageFPrintInfo(messagehdlr, file, ", %d", digraph->components[i]);
8725 }
8726 }
8727 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
8728 }
8729}
8730
8731/*
8732 * Binary tree
8733 */
8734
8735/** creates a node for a binary tree */
8736static
8738 SCIP_BT* tree, /**< binary tree */
8739 SCIP_BTNODE** node /**< pointer to store the created node */
8740 )
8741{
8742 SCIP_ALLOC( BMSallocBlockMemory(tree->blkmem, node) );
8743
8744 (*node)->parent = NULL;
8745 (*node)->left = NULL;
8746 (*node)->right = NULL;
8747 (*node)->dataptr = NULL;
8748
8749 return SCIP_OKAY;
8750}
8751
8752/** creates a tree node with (optinal) user data */
8754 SCIP_BT* tree, /**< binary tree */
8755 SCIP_BTNODE** node, /**< pointer to store the created node */
8756 void* dataptr /**< user node data pointer, or NULL */
8757 )
8758{
8759 assert(tree != NULL);
8760 assert(node != NULL);
8761
8762 SCIP_CALL( btnodeCreateEmpty(tree, node) );
8763
8764 assert((*node)->parent == NULL);
8765 assert((*node)->left == NULL);
8766 assert((*node)->right == NULL);
8767
8768 /* initialize user data */
8769 (*node)->dataptr = dataptr;
8770
8771 return SCIP_OKAY;
8772}
8773
8774/** frees a tree leaf */
8775static
8777 SCIP_BT* tree, /**< binary tree */
8778 SCIP_BTNODE** node /**< pointer to node which has to be freed */
8779 )
8780{
8781 assert(tree != NULL);
8782 assert(node != NULL);
8783 assert(*node != NULL);
8784
8785 assert((*node)->left == NULL);
8786 assert((*node)->right == NULL);
8787
8788#ifdef SCIP_DISABLED_CODE
8789 /* remove reference from parent node */
8790 if( (*node)->parent != NULL )
8791 {
8792 assert(*node != NULL);
8793
8794 assert((*node)->parent->left == *node || ((*node)->parent->right == *node));
8795
8796 if( (*node)->parent->left == *node )
8797 {
8798 (*node)->parent->left = NULL;
8799 }
8800 else
8801 {
8802 assert((*node)->parent->right == *node);
8803 (*node)->parent->right = NULL;
8804 }
8805 }
8806#endif
8807
8808 assert(*node != NULL);
8809 BMSfreeBlockMemory(tree->blkmem, node);
8810 assert(*node == NULL);
8811}
8812
8813/** frees the node including the rooted subtree
8814 *
8815 * @note The user pointer (object) is not freed. If needed, it has to be done by the user.
8816 */
8818 SCIP_BT* tree, /**< binary tree */
8819 SCIP_BTNODE** node /**< node to be freed */
8820 )
8821{
8822 assert(tree != NULL);
8823 assert(node != NULL);
8824 assert(*node != NULL);
8825
8826 if( (*node)->left != NULL )
8827 {
8828 SCIPbtnodeFree(tree, &(*node)->left);
8829 assert((*node)->left == NULL);
8830 }
8831
8832 if( (*node)->right != NULL )
8833 {
8834 SCIPbtnodeFree(tree, &(*node)->right);
8835 assert((*node)->right == NULL);
8836 }
8837
8838 btnodeFreeLeaf(tree, node);
8839 assert(*node == NULL);
8840}
8841
8842/* some simple variable functions implemented as defines */
8843
8844/* In debug mode, the following methods are implemented as function calls to ensure
8845 * type validity.
8846 * In optimized mode, the methods are implemented as defines to improve performance.
8847 * However, we want to have them in the library anyways, so we have to undef the defines.
8848 */
8849
8850#undef SCIPbtnodeGetData
8851#undef SCIPbtnodeGetKey
8852#undef SCIPbtnodeGetParent
8853#undef SCIPbtnodeGetLeftchild
8854#undef SCIPbtnodeGetRightchild
8855#undef SCIPbtnodeGetSibling
8856#undef SCIPbtnodeIsRoot
8857#undef SCIPbtnodeIsLeaf
8858#undef SCIPbtnodeIsLeftchild
8859#undef SCIPbtnodeIsRightchild
8860
8861/** returns the user data pointer stored in that node */
8863 SCIP_BTNODE* node /**< node */
8864 )
8865{
8866 assert(node != NULL);
8867
8868 return node->dataptr;
8869}
8870
8871/** returns the parent which can be NULL if the given node is the root */
8873 SCIP_BTNODE* node /**< node */
8874 )
8875{
8876 assert(node != NULL);
8877
8878 return node->parent;
8879}
8880
8881/** returns left child which can be NULL if the given node is a leaf */
8883 SCIP_BTNODE* node /**< node */
8884 )
8885{
8886 assert(node != NULL);
8887
8888 return node->left;
8889}
8890
8891/** returns right child which can be NULL if the given node is a leaf */
8893 SCIP_BTNODE* node /**< node */
8894 )
8895{
8896 assert(node != NULL);
8897
8898 return node->right;
8899}
8900
8901/** returns the sibling of the node or NULL if does not exist */
8903 SCIP_BTNODE* node /**< node */
8904 )
8905{
8906 SCIP_BTNODE* parent;
8907
8908 parent = SCIPbtnodeGetParent(node);
8909
8910 if( parent == NULL )
8911 return NULL;
8912
8913 if( SCIPbtnodeGetLeftchild(parent) == node )
8914 return SCIPbtnodeGetRightchild(parent);
8915
8916 assert(SCIPbtnodeGetRightchild(parent) == node);
8917
8918 return SCIPbtnodeGetLeftchild(parent);
8919}
8920
8921/** returns whether the node is a root node */
8923 SCIP_BTNODE* node /**< node */
8924 )
8925{
8926 assert(node != NULL);
8927
8928 return (node->parent == NULL);
8929}
8930
8931/** returns whether the node is a leaf */
8933 SCIP_BTNODE* node /**< node */
8934 )
8935{
8936 assert(node != NULL);
8937
8938 return (node->left == NULL && node->right == NULL);
8939}
8940
8941/** returns TRUE if the given node is left child */
8943 SCIP_BTNODE* node /**< node */
8944 )
8945{
8946 SCIP_BTNODE* parent;
8947
8948 if( SCIPbtnodeIsRoot(node) )
8949 return FALSE;
8950
8951 parent = SCIPbtnodeGetParent(node);
8952
8953 if( SCIPbtnodeGetLeftchild(parent) == node )
8954 return TRUE;
8955
8956 return FALSE;
8957}
8958
8959/** returns TRUE if the given node is right child */
8961 SCIP_BTNODE* node /**< node */
8962 )
8963{
8964 SCIP_BTNODE* parent;
8965
8966 if( SCIPbtnodeIsRoot(node) )
8967 return FALSE;
8968
8969 parent = SCIPbtnodeGetParent(node);
8970
8971 if( SCIPbtnodeGetRightchild(parent) == node )
8972 return TRUE;
8973
8974 return FALSE;
8975}
8976
8977/** sets the give node data
8978 *
8979 * @note The old user pointer is not freed.
8980 */
8982 SCIP_BTNODE* node, /**< node */
8983 void* dataptr /**< node user data pointer */
8984 )
8985{
8986 assert(node != NULL);
8987
8988 node->dataptr = dataptr;
8989}
8990
8991/** sets parent node
8992 *
8993 * @note The old parent including the rooted subtree is not delete.
8994 */
8996 SCIP_BTNODE* node, /**< node */
8997 SCIP_BTNODE* parent /**< new parent node, or NULL */
8998 )
8999{
9000 assert(node != NULL);
9001
9002 node->parent = parent;
9003}
9004
9005/** sets left child
9006 *
9007 * @note The old left child including the rooted subtree is not delete.
9008 */
9010 SCIP_BTNODE* node, /**< node */
9011 SCIP_BTNODE* left /**< new left child, or NULL */
9012 )
9013{
9014 assert(node != NULL);
9015
9016 node->left = left;
9017}
9018
9019/** sets right child
9020 *
9021 * @note The old right child including the rooted subtree is not delete.
9022 */
9024 SCIP_BTNODE* node, /**< node */
9025 SCIP_BTNODE* right /**< new right child, or NULL */
9026 )
9027{
9028 assert(node != NULL);
9029
9030 node->right = right;
9031}
9032
9033/** creates an binary tree */
9035 SCIP_BT** tree, /**< pointer to store the created binary tree */
9036 BMS_BLKMEM* blkmem /**< block memory used to createnode */
9037 )
9038{
9039 assert(tree != NULL);
9040 assert(blkmem != NULL);
9041
9042 SCIP_ALLOC( BMSallocBlockMemory(blkmem, tree) );
9043 (*tree)->blkmem = blkmem;
9044 (*tree)->root = NULL;
9045
9046 return SCIP_OKAY;
9047}
9048
9049/** frees binary tree
9050 *
9051 * @note The user pointers (object) of the nodes are not freed. If needed, it has to be done by the user.
9052 */
9054 SCIP_BT** tree /**< pointer to binary tree */
9055 )
9056{
9057 assert(tree != NULL);
9058
9059 if( (*tree)->root != NULL )
9060 {
9061 SCIPbtnodeFree(*tree, &((*tree)->root));
9062 }
9063
9064 BMSfreeBlockMemory((*tree)->blkmem, tree);
9065}
9066
9067/** prints the rooted subtree of the given binary tree node in GML format into the given file */
9068static
9070 SCIP_BTNODE* node, /**< binary tree node */
9071 FILE* file, /**< file to write to */
9072 int* nnodes /**< pointer to count the number of nodes */
9073 )
9074{
9075 SCIP_BTNODE* left;
9076 SCIP_BTNODE* right;
9077 char label[SCIP_MAXSTRLEN];
9078
9079 assert(node != NULL);
9080
9081 (*nnodes)++;
9082 (void)SCIPsnprintf(label, SCIP_MAXSTRLEN, "%d", *nnodes);
9083
9084 SCIPgmlWriteNode(file, (unsigned int)(size_t)node, label, "circle", NULL, NULL);
9085
9086 left = SCIPbtnodeGetLeftchild(node);
9087 right = SCIPbtnodeGetRightchild(node);
9088
9089 if( left != NULL )
9090 {
9091 btPrintSubtree(left, file, nnodes);
9092
9093 SCIPgmlWriteArc(file, (unsigned int)(size_t)node, (unsigned int)(size_t)left, NULL, NULL);
9094 }
9095
9096 if( right != NULL )
9097 {
9098 btPrintSubtree(right, file, nnodes);
9099
9100 SCIPgmlWriteArc(file, (unsigned int)(size_t)node, (unsigned int)(size_t)right, NULL, NULL);
9101 }
9102}
9103
9104/** prints the binary tree in GML format into the given file */
9106 SCIP_BT* tree, /**< binary tree */
9107 FILE* file /**< file to write to */
9108 )
9109{
9110 /* write GML opening */
9112
9113 if( !SCIPbtIsEmpty(tree) )
9114 {
9115 SCIP_BTNODE* root;
9116 int nnodes;
9117
9118 root = SCIPbtGetRoot(tree);
9119 assert(root != NULL);
9120
9121 nnodes = 0;
9122
9123 btPrintSubtree(root, file, &nnodes);
9124 }
9125
9126 /* write GML closing */
9127 SCIPgmlWriteClosing(file);
9128}
9129
9130/* some simple variable functions implemented as defines */
9131#undef SCIPbtIsEmpty
9132#undef SCIPbtGetRoot
9133
9134/** returns whether the binary tree is empty (has no nodes) */
9136 SCIP_BT* tree /**< binary tree */
9137 )
9138{
9139 assert(tree != NULL);
9140
9141 return (tree->root == NULL);
9142}
9143
9144/** returns the the root node of the binary or NULL if the binary tree is empty */
9146 SCIP_BT* tree /**< tree to be evaluated */
9147 )
9148{
9149 assert(tree != NULL);
9150
9151 return tree->root;
9152}
9153
9154/** sets root node
9155 *
9156 * @note The old root including the rooted subtree is not delete.
9157 */
9159 SCIP_BT* tree, /**< tree to be evaluated */
9160 SCIP_BTNODE* root /**< new root, or NULL */
9161 )
9162{
9163 assert(tree != NULL);
9164
9165 tree->root = root;
9166}
9167
9168
9169/*
9170 * Numerical methods
9171 */
9172
9173/** returns the machine epsilon: the smallest number eps > 0, for which 1.0 + eps > 1.0 */
9175 void
9176 )
9177{
9178 SCIP_Real eps;
9179 SCIP_Real lasteps;
9180 SCIP_Real one;
9181 SCIP_Real onepluseps;
9182
9183 one = 1.0;
9184 eps = 1.0;
9185 do
9186 {
9187 lasteps = eps;
9188 eps /= 2.0;
9189 onepluseps = one + eps;
9190 }
9191 while( onepluseps > one );
9192
9193 return lasteps;
9194}
9195
9196/** calculates the greatest common divisor of the two given values */
9198 SCIP_Longint val1, /**< first value of greatest common devisor calculation */
9199 SCIP_Longint val2 /**< second value of greatest common devisor calculation */
9200 )
9201{
9202 int t;
9203
9204 assert(val1 > 0);
9205 assert(val2 > 0);
9206
9207 t = 0;
9208 /* if val1 is even, divide it by 2 */
9209 while( !(val1 & 1) )
9210 {
9211 val1 >>= 1; /*lint !e704*/
9212
9213 /* if val2 is even too, divide it by 2 and increase t(=number of e) */
9214 if( !(val2 & 1) )
9215 {
9216 val2 >>= 1; /*lint !e704*/
9217 ++t;
9218 }
9219 /* only val1 can be odd */
9220 else
9221 {
9222 /* while val1 is even, divide it by 2 */
9223 while( !(val1 & 1) )
9224 val1 >>= 1; /*lint !e704*/
9225
9226 break;
9227 }
9228 }
9229
9230 /* while val2 is even, divide it by 2 */
9231 while( !(val2 & 1) )
9232 val2 >>= 1; /*lint !e704*/
9233
9234 /* the following if/else condition is only to make sure that we do not overflow when adding up both values before
9235 * dividing them by 4 in the following while loop
9236 */
9237 if( t == 0 )
9238 {
9239 if( val1 > val2 )
9240 {
9241 val1 -= val2;
9242
9243 /* divide val1 by 2 as long as possible */
9244 while( !(val1 & 1) )
9245 val1 >>= 1; /*lint !e704*/
9246 }
9247 else if( val1 < val2 )
9248 {
9249 val2 -= val1;
9250
9251 /* divide val2 by 2 as long as possible */
9252 while( !(val2 & 1) )
9253 val2 >>= 1; /*lint !e704*/
9254 }
9255 }
9256
9257 /* val1 and val2 are odd */
9258 while( val1 != val2 )
9259 {
9260 if( val1 > val2 )
9261 {
9262 /* we can stop if one value reached one */
9263 if( val2 == 1 )
9264 return (val2 << t); /*lint !e647 !e703*/
9265
9266 /* if ((val1 xor val2) and 2) = 2, then gcd(val1, val2) = gcd((val1 + val2)/4, val2),
9267 * and otherwise gcd(val1, val2) = gcd((val1 − val2)/4, val2)
9268 */
9269 if( ((val1 ^ val2) & 2) == 2 )
9270 val1 += val2;
9271 else
9272 val1 -= val2;
9273
9274 assert((val1 & 3) == 0);
9275 val1 >>= 2; /*lint !e704*/
9276
9277 /* if val1 is still even, divide it by 2 */
9278 while( !(val1 & 1) )
9279 val1 >>= 1; /*lint !e704*/
9280 }
9281 else
9282 {
9283 /* we can stop if one value reached one */
9284 if( val1 == 1 )
9285 return (val1 << t); /*lint !e647 !e703*/
9286
9287 /* if ((val2 xor val1) and 2) = 2, then gcd(val2, val1) = gcd((val2 + val1)/4, val1),
9288 * and otherwise gcd(val2, val1) = gcd((val2 − val1)/4, val1)
9289 */
9290 if( ((val2 ^ val1) & 2) == 2 )
9291 val2 += val1;
9292 else
9293 val2 -= val1;
9294
9295 assert((val2 & 3) == 0);
9296 val2 >>= 2; /*lint !e704*/
9297
9298 /* if val2 is still even, divide it by 2 */
9299 while( !(val2 & 1) )
9300 val2 >>= 1; /*lint !e704*/
9301 }
9302 }
9303
9304 return (val1 << t); /*lint !e703*/
9305}
9306
9307
9308/* for the MS compiler, the function nextafter is named _nextafter */
9309#if defined(_MSC_VER) && !defined(NO_NEXTAFTER)
9310#define nextafter(x,y) _nextafter(x,y)
9311#endif
9312
9313/* on systems where the function nextafter is not defined, we provide an implementation from Sun */
9314#ifdef NO_NEXTAFTER
9315/* The following implementation of the routine nextafter() comes with the following license:
9316 *
9317 * ====================================================
9318 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
9319 *
9320 * Developed at SunSoft, a Sun Microsystems, Inc. business.
9321 * Permission to use, copy, modify, and distribute this
9322 * software is freely granted, provided that this notice
9323 * is preserved.
9324 * ====================================================
9325 */
9326
9327#define __HI(x) *(1+(int*)&x)
9328#define __LO(x) *(int*)&x
9329#define __HIp(x) *(1+(int*)x)
9330#define __LOp(x) *(int*)x
9331
9332static
9333double nextafter(double x, double y)
9334{
9335 int hx;
9336 int hy;
9337 int ix;
9338 int iy;
9339 unsigned lx;
9340 unsigned ly;
9341
9342 /* cppcheck-suppress invalidPointerCast */
9343 hx = __HI(x); /* high word of x */
9344 /* cppcheck-suppress invalidPointerCast */
9345 lx = __LO(x); /* low word of x */
9346 /* cppcheck-suppress invalidPointerCast */
9347 hy = __HI(y); /* high word of y */
9348 /* cppcheck-suppress invalidPointerCast */
9349 ly = __LO(y); /* low word of y */
9350 ix = hx&0x7fffffff; /* |x| */
9351 iy = hy&0x7fffffff; /* |y| */
9352
9353 if( ((ix>=0x7ff00000) && ((ix-0x7ff00000)|lx) != 0 ) || /* x is nan */
9354 ( (iy>=0x7ff00000) && ((iy-0x7ff00000)|ly) != 0 )) /* y is nan */
9355 return x + y;
9356
9357 /* x == y, return x */
9358 if( x == y )
9359 return x;
9360
9361 /* x == 0 */
9362 if( (ix|lx) == 0 )
9363 {
9364 /* return +-minsubnormal */
9365 /* cppcheck-suppress invalidPointerCast */
9366 __HI(x) = hy&0x80000000;
9367 /* cppcheck-suppress invalidPointerCast */
9368 __LO(x) = 1;
9369 y = x * x;
9370 if ( y == x )
9371 return y;
9372 else
9373 return x; /* raise underflow flag */
9374 }
9375 /* x > 0 */
9376 if( hx >= 0 )
9377 {
9378 /* x > y, x -= ulp */
9379 if( hx > hy || ((hx == hy) && (lx > ly)) )
9380 {
9381 if ( lx == 0 )
9382 hx -= 1;
9383 lx -= 1;
9384 }
9385 else
9386 {
9387 /* x < y, x += ulp */
9388 lx += 1;
9389 if ( lx == 0 )
9390 hx += 1;
9391 }
9392 }
9393 else
9394 {
9395 /* x < 0 */
9396 if( hy >= 0 || hx > hy || ((hx == hy) && (lx > ly)) )
9397 {
9398 /* x < y, x -= ulp */
9399 if ( lx == 0 )
9400 hx -= 1;
9401 lx -= 1;
9402 }
9403 else
9404 {
9405 /* x > y, x += ulp */
9406 lx += 1;
9407 if( lx == 0 )
9408 hx += 1;
9409 }
9410 }
9411 hy = hx&0x7ff00000;
9412 /* overflow */
9413 if( hy >= 0x7ff00000 )
9414 return x + x;
9415 if( hy < 0x00100000 )
9416 {
9417 /* underflow */
9418 y = x*x;
9419 if( y != x )
9420 {
9421 /* raise underflow flag */
9422 /* cppcheck-suppress invalidPointerCast */
9423 __HI(y) = hx;
9424 /* cppcheck-suppress invalidPointerCast */
9425 __LO(y) = lx;
9426 return y;
9427 }
9428 }
9429
9430 /* cppcheck-suppress invalidPointerCast */
9431 __HI(x) = hx;
9432 /* cppcheck-suppress invalidPointerCast */
9433 __LO(x) = lx;
9434 return x;
9435}
9436#endif
9437
9438
9439/** returns the next representable value of from in the direction of to */
9441 SCIP_Real from, /**< value from which the next representable value should be returned */
9442 SCIP_Real to /**< direction in which the next representable value should be returned */
9443 )
9444{
9445 return nextafter(from, to);
9446}
9447
9448/** calculates the smallest common multiple of the two given values */
9450 SCIP_Longint val1, /**< first value of smallest common multiple calculation */
9451 SCIP_Longint val2 /**< second value of smallest common multiple calculation */
9452 )
9453{
9454 SCIP_Longint gcd;
9455
9456 assert(val1 > 0);
9457 assert(val2 > 0);
9458
9459 gcd = SCIPcalcGreComDiv(val1, val2);
9460
9461 return val1/gcd * val2;
9462}
9463
9464static const SCIP_Real simplednoms[] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0,
9465 17.0, 18.0, 19.0, 25.0, -1.0};
9466
9467/** converts a real number into a (approximate) rational representation, and returns TRUE iff the conversion was
9468 * successful
9469 */
9471 SCIP_Real val, /**< real value r to convert into rational number */
9472 SCIP_Real mindelta, /**< minimal allowed difference r - q of real r and rational q = n/d */
9473 SCIP_Real maxdelta, /**< maximal allowed difference r - q of real r and rational q = n/d */
9474 SCIP_Longint maxdnom, /**< maximal denominator allowed */
9475 SCIP_Longint* numerator, /**< pointer to store the numerator n of the rational number */
9476 SCIP_Longint* denominator /**< pointer to store the denominator d of the rational number */
9477 )
9478{
9479 SCIP_Real a;
9480 SCIP_Real b;
9481 SCIP_Real g0;
9482 SCIP_Real g1;
9483 SCIP_Real gx;
9484 SCIP_Real h0;
9485 SCIP_Real h1;
9486 SCIP_Real hx;
9487 SCIP_Real delta0;
9488 SCIP_Real delta1;
9489 SCIP_Real epsilon;
9490 int i;
9491
9492 assert(mindelta <= 0.0);
9493 assert(maxdelta >= 0.0);
9494 assert(numerator != NULL);
9495 assert(denominator != NULL);
9496
9497 if( REALABS(val) >= ((SCIP_Real)SCIP_LONGINT_MAX) / maxdnom )
9498 return FALSE;
9499
9500 /* try the simple denominators first: each value of the simpledenoms table multiplied by powers of 10
9501 * is tried as denominator
9502 */
9503 for( i = 0; simplednoms[i] > 0.0; ++i )
9504 {
9505 SCIP_Real nom;
9506 SCIP_Real dnom;
9507 SCIP_Real ratval0;
9508 SCIP_Real ratval1;
9509
9510 /* try powers of 10 (including 10^0) */
9511 dnom = simplednoms[i];
9512 while( dnom <= maxdnom )
9513 {
9514 nom = floor(val * dnom);
9515 ratval0 = nom/dnom;
9516 ratval1 = (nom+1.0)/dnom;
9517 if( mindelta <= val - ratval0 && val - ratval1 <= maxdelta )
9518 {
9519 if( val - ratval0 <= maxdelta )
9520 {
9521 *numerator = (SCIP_Longint)nom;
9522 *denominator = (SCIP_Longint)dnom;
9523 return TRUE;
9524 }
9525 if( mindelta <= val - ratval1 )
9526 {
9527 *numerator = (SCIP_Longint)(nom+1.0);
9528 *denominator = (SCIP_Longint)dnom;
9529 return TRUE;
9530 }
9531 }
9532 dnom *= 10.0;
9533 }
9534 }
9535
9536 /* the simple denominators didn't work: calculate rational representation with arbitrary denominator */
9537 epsilon = MIN(-mindelta, maxdelta)/2.0;
9538
9539 b = val;
9540 a = EPSFLOOR(b, epsilon);
9541 g0 = a;
9542 h0 = 1.0;
9543 g1 = 1.0;
9544 h1 = 0.0;
9545 delta0 = val - g0/h0;
9546 delta1 = (delta0 < 0.0 ? val - (g0-1.0)/h0 : val - (g0+1.0)/h0);
9547
9548 while( (delta0 < mindelta || delta0 > maxdelta) && (delta1 < mindelta || delta1 > maxdelta) )
9549 {
9550 assert(EPSGT(b, a, epsilon));
9551 assert(h0 >= 0.0);
9552 assert(h1 >= 0.0);
9553
9554 b = 1.0 / (b - a);
9555 a = EPSFLOOR(b, epsilon);
9556
9557 assert(a >= 0.0);
9558 gx = g0;
9559 hx = h0;
9560
9561 g0 = a * g0 + g1;
9562 h0 = a * h0 + h1;
9563
9564 g1 = gx;
9565 h1 = hx;
9566
9567 if( h0 > maxdnom )
9568 return FALSE;
9569
9570 delta0 = val - g0/h0;
9571 delta1 = (delta0 < 0.0 ? val - (g0-1.0)/h0 : val - (g0+1.0)/h0);
9572 }
9573
9574 if( REALABS(g0) > (SCIP_Real)(SCIP_LONGINT_MAX >> 4) || h0 > (SCIP_Real)(SCIP_LONGINT_MAX >> 4) )
9575 return FALSE;
9576
9577 assert(h0 > 0.5);
9578
9579 if( delta0 < mindelta )
9580 {
9581 assert(mindelta <= delta1 && delta1 <= maxdelta);
9582 *numerator = (SCIP_Longint)(g0 - 1.0);
9584 }
9585 else if( delta0 > maxdelta )
9586 {
9587 assert(mindelta <= delta1 && delta1 <= maxdelta);
9588 *numerator = (SCIP_Longint)(g0 + 1.0);
9590 }
9591 else
9592 {
9593 *numerator = (SCIP_Longint)g0;
9595 }
9596 assert(*denominator >= 1);
9597 assert(val - (SCIP_Real)(*numerator)/(SCIP_Real)(*denominator) >= mindelta);
9598 assert(val - (SCIP_Real)(*numerator)/(SCIP_Real)(*denominator) <= maxdelta);
9599
9600 return TRUE;
9601}
9602
9603/** checks, if value is integral without any tolerances */
9605 SCIP_Real val /**< value to process */
9606 )
9607{
9608 return floor(val) == val; /*lint !e777*/
9609}
9610
9611/** checks, whether the given scalar scales the given value to an integral number with error in the given bounds */
9612static
9614 SCIP_Real val, /**< value that should be scaled to an integral value */
9615 SCIP_Real scalar, /**< scalar that should be tried */
9616 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
9617 SCIP_Real maxdelta /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
9618 )
9619{
9620 SCIP_Real sval;
9621 SCIP_Real downval;
9622 SCIP_Real upval;
9623
9624 assert(mindelta <= 0.0);
9625 assert(maxdelta >= 0.0);
9626
9627 sval = val * scalar;
9628 downval = floor(sval);
9629 upval = ceil(sval);
9630
9631 return (SCIPrelDiff(sval, downval) <= maxdelta || SCIPrelDiff(sval, upval) >= mindelta);
9632}
9633
9634/** additional scalars that are tried in integrality scaling */
9635static const SCIP_Real scalars[] = {3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0};
9636static const int nscalars = 9;
9637
9638/** tries to find a value, such that all given values, if scaled with this value become integral in relative allowed
9639 * difference in between mindelta and maxdelta
9640 */
9642 SCIP_Real* vals, /**< values to scale */
9643 int nvals, /**< number of values to scale */
9644 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
9645 SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
9646 SCIP_Longint maxdnom, /**< maximal denominator allowed in rational numbers */
9647 SCIP_Real maxscale, /**< maximal allowed scalar */
9648 SCIP_Real* intscalar, /**< pointer to store scalar that would make the coefficients integral, or NULL */
9649 SCIP_Bool* success /**< stores whether returned value is valid */
9650 )
9651{
9652 SCIP_Real bestscalar;
9653 SCIP_Longint gcd;
9654 SCIP_Longint scm;
9657 SCIP_Real val;
9658 SCIP_Real minval;
9659 SCIP_Real absval;
9660 SCIP_Real scaleval;
9661 SCIP_Bool scalable;
9662 SCIP_Bool rational;
9663 int c;
9664 int s;
9665 int i;
9666
9667 assert(vals != NULL);
9668 assert(nvals >= 0);
9669 assert(maxdnom >= 1);
9670 assert(mindelta < 0.0);
9671 assert(maxdelta > 0.0);
9672 assert(success != NULL);
9673
9674 SCIPdebugMessage("trying to find rational representation for given values\n");
9675
9676 if( intscalar != NULL )
9677 *intscalar = SCIP_INVALID;
9678 *success = FALSE;
9679
9680 /* get minimal absolute non-zero value */
9681 minval = SCIP_REAL_MAX;
9682 for( c = 0; c < nvals; ++c )
9683 {
9684 val = vals[c];
9685 if( val < mindelta || val > maxdelta )
9686 {
9687 absval = REALABS(val);
9688 minval = MIN(minval, absval);
9689 }
9690 }
9691
9692 if( minval == SCIP_REAL_MAX ) /*lint !e777*/
9693 {
9694 /* all coefficients are zero (inside tolerances) */
9695 if( intscalar != NULL )
9696 *intscalar = 1.0;
9697 *success = TRUE;
9698 SCIPdebugMessage(" -> all values are zero (inside tolerances)\n");
9699
9700 return SCIP_OKAY;
9701 }
9702 assert(minval > MIN(-mindelta, maxdelta));
9703
9704 bestscalar = SCIP_INVALID;
9705
9706 for( i = 0; i < 2; ++i )
9707 {
9708 scalable = TRUE;
9709
9710 /* try, if values can be made integral multiplying them with the reciprocal of the smallest value and a power of 2 */
9711 if( i == 0 )
9712 scaleval = 1.0/minval;
9713 /* try, if values can be made integral by multiplying them by a power of 2 */
9714 else
9715 scaleval = 1.0;
9716
9717 for( c = 0; c < nvals && scalable; ++c )
9718 {
9719 /* check, if the value can be scaled with a simple scalar */
9720 val = vals[c];
9721 if( val == 0.0 ) /* zeros are allowed in the vals array */
9722 continue;
9723
9724 absval = REALABS(val);
9725 while( scaleval <= maxscale
9726 && (absval * scaleval < 0.5 || !isIntegralScalar(val, scaleval, mindelta, maxdelta)) )
9727 {
9728 for( s = 0; s < nscalars; ++s )
9729 {
9730 if( isIntegralScalar(val, scaleval * scalars[s], mindelta, maxdelta) )
9731 {
9732 scaleval *= scalars[s];
9733 break;
9734 }
9735 }
9736 if( s >= nscalars )
9737 scaleval *= 2.0;
9738 }
9739 scalable = (scaleval <= maxscale);
9740 SCIPdebugMessage(" -> val=%g, scaleval=%g, val*scaleval=%g, scalable=%u\n",
9741 val, scaleval, val*scaleval, scalable);
9742 }
9743 if( scalable )
9744 {
9745 /* make values integral by dividing them by the smallest value (and multiplying them with a power of 2) */
9746 assert(scaleval <= maxscale);
9747
9748 /* check if we found a better scaling value */
9749 if( scaleval < bestscalar )
9750 bestscalar = scaleval;
9751
9752 SCIPdebugMessage(" -> integrality could be achieved by scaling with %g\n", scaleval);
9753
9754 /* if the scalar is still the reciprocal of the minimal value, all coeffcients are the same and we do not get a better scalar */
9755 if( i == 0 && EPSEQ(scaleval, 1.0/minval, SCIP_DEFAULT_EPSILON) )
9756 {
9757 if( intscalar != NULL )
9758 *intscalar = bestscalar;
9759 *success = TRUE;
9760
9761 return SCIP_OKAY;
9762 }
9763 }
9764 }
9765
9766 /* convert each value into a rational number, calculate the greatest common divisor of the numerators
9767 * and the smallest common multiple of the denominators
9768 */
9769 gcd = 1;
9770 scm = 1;
9771 rational = TRUE;
9772
9773 /* first value (to initialize gcd) */
9774 for( c = 0; c < nvals && rational; ++c )
9775 {
9776 val = vals[c];
9777 if( val == 0.0 ) /* zeros are allowed in the vals array */
9778 continue;
9779
9780 rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &numerator, &denominator);
9781 if( rational && numerator != 0 )
9782 {
9783 assert(denominator > 0);
9784 gcd = ABS(numerator);
9785 scm = denominator;
9786 rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
9787 SCIPdebugMessage(" -> c=%d first rational: val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
9788 c, val, numerator, denominator, gcd, scm, rational);
9789 break;
9790 }
9791 }
9792
9793 /* remaining values */
9794 for( ++c; c < nvals && rational; ++c )
9795 {
9796 val = vals[c];
9797 if( val == 0.0 ) /* zeros are allowed in the vals array */
9798 continue;
9799
9800 rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &numerator, &denominator);
9801 if( rational && numerator != 0 )
9802 {
9803 assert(denominator > 0);
9804 gcd = SCIPcalcGreComDiv(gcd, ABS(numerator));
9806 rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
9807 SCIPdebugMessage(" -> c=%d next rational : val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
9808 c, val, numerator, denominator, gcd, scm, rational);
9809 }
9810 else
9811 {
9812 SCIPdebugMessage(" -> failed to convert %g into a rational representation\n", val);
9813 }
9814 }
9815
9816 if( rational )
9817 {
9818 /* make values integral by multiplying them with the smallest common multiple of the denominators */
9819 assert((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
9820
9821 /* check if we found a better scaling value */
9822 if( (SCIP_Real)scm/(SCIP_Real)gcd < bestscalar )
9823 bestscalar = (SCIP_Real)scm/(SCIP_Real)gcd;
9824
9825 SCIPdebugMessage(" -> integrality could be achieved by scaling with %g (rational:%" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ")\n",
9826 (SCIP_Real)scm/(SCIP_Real)gcd, scm, gcd);
9827 }
9828
9829 if( bestscalar < SCIP_INVALID )
9830 {
9831 if( intscalar != NULL )
9832 *intscalar = bestscalar;
9833 *success = TRUE;
9834
9835 SCIPdebugMessage(" -> smallest value to achieve integrality is %g \n", bestscalar);
9836 }
9837
9838 return SCIP_OKAY;
9839}
9840
9841/** tries to find a value, such that all given values, if scaled with this value become integral */
9843 BMS_BUFMEM* buffer,
9844 SCIP_RATIONAL** vals, /**< values to scale */
9845 int nvals, /**< number of values to scale */
9846 SCIP_Real maxscale, /**< maximal allowed scalar */
9847 SCIP_RATIONAL* intscalar, /**< pointer to store scalar that would make the coefficients integral */
9848 SCIP_Bool* success /**< stores whether returned value is valid */
9849 )
9850{
9851 SCIP_Longint gcd;
9852 SCIP_Longint scm;
9855 SCIP_Longint updatemultiplier;
9856 SCIP_RATIONAL* ratupdate;
9857 SCIP_RATIONAL* ratscm;
9858 SCIP_Bool scalable;
9859 int c;
9860
9861 assert(vals != NULL);
9862 assert(nvals >= 0);
9863 assert(success != NULL);
9864
9865 SCIPdebugMessage("trying to find rational representation for given rational values\n");
9866
9867 *success = FALSE;
9868
9869 /** @todo test whether it is faster to compute scm and gcd via mpz_scm() and mpz_gcd() in
9870 * SCIPcalcIntegralScalarExact(); even if we stay with the SCIP_Longint conversion, we could use the other way
9871 * to check the correctness of our result
9872 */
9873 /* calculate the greatest common divisor of the numerators and the smallest common multiple of the denominators */
9874 gcd = 1;
9875 scm = 1;
9876 scalable = TRUE;
9877
9878 SCIP_CALL( SCIPrationalCreateBuffer(buffer, &ratupdate) );
9879 SCIP_CALL( SCIPrationalCreateBuffer(buffer, &ratscm) );
9880
9881 /* first value (to initialize gcd) */
9882 for( c = 0; c < nvals && scalable; ++c )
9883 {
9884 if( SCIPrationalIsZero(vals[c]) ) /* zeros are allowed in the vals array */
9885 continue;
9886
9887 /* get numerator and check whether it fits into SCIP_Longint */
9890 {
9891 scalable = FALSE;
9892 break;
9893 }
9894
9895 /* get numerator and check whether it fits into SCIP_Longint */
9898 {
9899 scalable = FALSE;
9900 break;
9901 }
9902
9903 assert(denominator > 0);
9904 gcd = ABS(numerator);
9905 scm = denominator;
9906
9907 scalable = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale); /*lint !e838*/
9908
9909 break;
9910 }
9911
9912 /* remaining values */
9913 for( ++c; c < nvals && scalable; ++c )
9914 {
9915 if( SCIPrationalIsZero(vals[c]) ) /* zeros are allowed in the vals array */
9916 continue;
9917
9918 /* get numerator and check whether it fits into SCIP_Longint */
9921 {
9922 scalable = FALSE;
9923 break;
9924 }
9925
9926 /* get denom and check whether it fits into SCIP_Longint */
9929 {
9930 scalable = FALSE;
9931 break;
9932 }
9933
9934 assert(denominator > 0);
9935
9936 gcd = SCIPcalcGreComDiv(gcd, ABS(numerator));
9937
9938 /* update scm via newscm = scm * denominator / gcd(scm, denominator) and check whether it fits into SCIP_Longint */
9939 updatemultiplier = denominator / SCIPcalcGreComDiv(scm, denominator);
9940 SCIPrationalSetFraction(ratupdate, updatemultiplier, 1LL);
9941 SCIPrationalSetFraction(ratscm, scm, 1LL);
9942 SCIPrationalMult(ratscm, ratscm, ratupdate);
9944
9945 scm = SCIPrationalNumerator(ratscm);
9946
9947 if( scm == SCIP_LONGINT_MAX )
9948 {
9949 scalable = FALSE;
9950 break;
9951 }
9952
9953 scalable = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale); /*lint !e838*/
9954 }
9955
9956 if( scalable )
9957 {
9958 /* make values integral by multiplying them with the smallest common multiple of the denominators */
9959 assert((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
9960
9961 SCIPrationalSetFraction(intscalar, scm, gcd);
9962 SCIPrationalCanonicalize(intscalar);
9963
9964 *success = TRUE;
9965
9966 }
9967
9968 SCIPrationalFreeBuffer(buffer, &ratscm);
9969 SCIPrationalFreeBuffer(buffer, &ratupdate);
9970
9971 return SCIP_OKAY;
9972}
9973
9974/* Inform compiler that this code accesses the floating-point environment, so that
9975 * certain optimizations should be omitted (http://www.cplusplus.com/reference/cfenv/FENV_ACCESS/).
9976 * Not supported by Clang (gives warning) and GCC (silently), at the moment.
9977 */
9978#if defined(__INTEL_COMPILER) || defined(_MSC_VER)
9979#pragma fenv_access (on)
9980#elif defined(__GNUC__) && !defined(__clang__)
9981#pragma STDC FENV_ACCESS ON
9982#endif
9983#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
9984#if defined(__clang__)
9985__attribute__((optnone))
9986#else
9987__attribute__((optimize(0)))
9988#endif
9989#endif
9990/** given a (usually very small) interval, tries to find a rational number with simple denominator (i.e. a small
9991 * number, probably multiplied with powers of 10) out of this interval; returns TRUE iff a valid rational
9992 * number inside the interval was found
9993 */
9995 SCIP_Real lb, /**< lower bound of the interval */
9996 SCIP_Real ub, /**< upper bound of the interval */
9997 SCIP_Longint maxdnom, /**< maximal denominator allowed for resulting rational number */
9998 SCIP_Longint* numerator, /**< pointer to store the numerator n of the rational number */
9999 SCIP_Longint* denominator /**< pointer to store the denominator d of the rational number */
10000 )
10001{
10002 SCIP_Real center;
10003 SCIP_Real delta;
10004
10005 assert(lb <= ub);
10006
10007 center = 0.5*(lb+ub);
10008
10009 /* in order to compute a rational number that is exactly within the bounds (as the user expects),
10010 * we computed the allowed delta with downward rounding, if available
10011 */
10013 {
10014 SCIP_ROUNDMODE roundmode;
10015
10016 roundmode = SCIPintervalGetRoundingMode();
10018
10019 delta = 0.5*(ub-lb);
10020
10021 SCIPintervalSetRoundingMode(roundmode);
10022 }
10023 else
10024 {
10025 delta = 0.5*(ub-lb);
10026 }
10027
10028 return SCIPrealToRational(center, -delta, +delta, maxdnom, numerator, denominator);
10029}
10030
10031#if defined(__INTEL_COMPILER) || defined(_MSC_VER)
10032#pragma fenv_access (off)
10033#elif defined(__GNUC__) && !defined(__clang__)
10034#pragma STDC FENV_ACCESS OFF
10035#endif
10036
10037/** given a (usually very small) interval, selects a value inside this interval; it is tried to select a rational number
10038 * with simple denominator (i.e. a small number, probably multiplied with powers of 10);
10039 * if no valid rational number inside the interval was found, selects the central value of the interval
10040 */
10042 SCIP_Real lb, /**< lower bound of the interval */
10043 SCIP_Real ub, /**< upper bound of the interval */
10044 SCIP_Longint maxdnom /**< maximal denominator allowed for resulting rational number */
10045 )
10046{
10047 SCIP_Real val;
10048
10049 val = 0.5*(lb+ub);
10050 if( lb < ub )
10051 {
10054 SCIP_Bool success;
10055
10056 /* try to find a "simple" rational number inside the interval */
10057 SCIPdebugMessage("simple rational in [%.9f,%.9f]:", lb, ub);
10058 success = SCIPfindSimpleRational(lb, ub, maxdnom, &numerator, &denominator);
10059 if( success )
10060 {
10063
10064 if( val - lb < 0.0 || val - ub > 0.0 )
10065 {
10066 SCIPdebugPrintf(" value is out of interval bounds by %g -> failed\n", MAX(lb-val, val-ub));
10067 val = 0.5*(lb+ub);
10068 }
10069 }
10070 else
10071 {
10072 SCIPdebugPrintf(" failed\n");
10073 }
10074 }
10075
10076 return val;
10077}
10078
10079/** Performs the Newton Procedure from a given starting point to compute a root of the given function with
10080 * specified precision and maximum number of iterations. If the procedure fails, SCIP_INVALID is returned.
10081 */
10083 SCIP_DECL_NEWTONEVAL((*function)), /**< pointer to function for which roots are computed */
10084 SCIP_DECL_NEWTONEVAL((*derivative)), /**< pointer to derivative of above function */
10085 SCIP_Real* params, /**< parameters needed for function (can be NULL) */
10086 int nparams, /**< number of parameters (can be 0) */
10087 SCIP_Real x, /**< starting point */
10088 SCIP_Real eps, /**< tolerance */
10089 int k /**< iteration limit */
10090 )
10091{
10092 SCIP_Real result = x;
10093 int iteration = 0;
10094
10095 assert(function != NULL);
10096 assert(derivative != NULL);
10097 assert(params != NULL || nparams == 0);
10098 assert(eps > 0.0);
10099 assert(k >= 0);
10100 assert(x != SCIP_INVALID); /*lint !e777*/
10101
10102 while( iteration < k )
10103 {
10104 SCIP_Real deriv = derivative(result, params, nparams);
10105
10106 /* if we arrive at a stationary point, the procedure is aborted */
10107 if( REALABS(deriv) <= eps || deriv == SCIP_INVALID ) /*lint !e777*/
10108 return SCIP_INVALID;
10109
10110 result = result - function(result, params, nparams) / deriv;
10111
10112 /* if new point is within eps-range of 0, we are done */
10113 if( REALABS(function(result, params, nparams)) <= eps )
10114 break;
10115
10116 ++iteration;
10117 }
10118
10119 if( k == iteration )
10120 return SCIP_INVALID;
10121 else
10122 return result;
10123}
10124
10125
10126/*
10127 * Random Numbers
10128 */
10129
10130
10131/* initial seeds for KISS random number generator */
10132#define DEFAULT_SEED UINT32_C(123456789)
10133#define DEFAULT_XOR UINT32_C(362436000)
10134#define DEFAULT_MWC UINT32_C(521288629)
10135#define DEFAULT_CST UINT32_C(7654321)
10136
10137
10138/** initializes a random number generator with a given start seed */
10140 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10141 unsigned int initseed /**< initial random seed */
10142 )
10143{
10144 assert(randnumgen != NULL);
10145
10146 /* use MAX() to avoid zero after over flowing */
10147 randnumgen->seed = MAX(SCIPhashTwo(DEFAULT_SEED, initseed), 1u);
10148 randnumgen->xor_seed = MAX(SCIPhashTwo(DEFAULT_XOR, initseed), 1u);
10149 randnumgen->mwc_seed = MAX(SCIPhashTwo(DEFAULT_MWC, initseed), 1u);
10150 randnumgen->cst_seed = SCIPhashTwo(DEFAULT_CST, initseed);
10151
10152 assert(randnumgen->seed > 0);
10153 assert(randnumgen->xor_seed > 0);
10154 assert(randnumgen->mwc_seed > 0);
10155}
10156
10157/** returns a random number between 0 and UINT32_MAX
10158 *
10159 * implementation of KISS random number generator developed by George Marsaglia.
10160 * KISS is combination of three different random number generators:
10161 * - Linear congruential generator
10162 * - Xorshift
10163 * - Lag-1 Multiply-with-carry
10164 *
10165 * KISS has a period of 2^123 and passes all statistical test part of BigCrush-Test of TestU01 [1].
10166 *
10167 * [1] http://dl.acm.org/citation.cfm?doid=1268776.1268777
10168 */
10169static
10171 SCIP_RANDNUMGEN* randnumgen /**< random number generator */
10172 )
10173{
10174 uint64_t t;
10175
10176 /* linear congruential */
10177 randnumgen->seed = (uint32_t) (randnumgen->seed * UINT64_C(1103515245) + UINT64_C(12345));
10178
10179 /* Xorshift */
10180 randnumgen->xor_seed ^= (randnumgen->xor_seed << 13);
10181 randnumgen->xor_seed ^= (randnumgen->xor_seed >> 17);
10182 randnumgen->xor_seed ^= (randnumgen->xor_seed << 5);
10183
10184 /* Multiply-with-carry */
10185 t = UINT64_C(698769069) * randnumgen->mwc_seed + randnumgen->cst_seed;
10186 randnumgen->cst_seed = (uint32_t) (t >> 32);
10187 randnumgen->mwc_seed = (uint32_t) t;
10188
10189 return randnumgen->seed + randnumgen->xor_seed + randnumgen->mwc_seed;
10190}
10191
10192/** creates and initializes a random number generator */
10194 SCIP_RANDNUMGEN** randnumgen, /**< random number generator */
10195 BMS_BLKMEM* blkmem, /**< block memory */
10196 unsigned int initialseed /**< initial random seed */
10197 )
10198{
10199 assert(randnumgen != NULL);
10200
10201 SCIP_ALLOC( BMSallocBlockMemory(blkmem, randnumgen) );
10202
10203 SCIPrandomSetSeed((*randnumgen), initialseed);
10204
10205 return SCIP_OKAY;
10206}
10207
10208/** frees a random number generator */
10210 SCIP_RANDNUMGEN** randnumgen, /**< random number generator */
10211 BMS_BLKMEM* blkmem /**< block memory */
10212 )
10213{
10214 assert(randnumgen != NULL);
10215 assert((*randnumgen) != NULL);
10216
10217 BMSfreeBlockMemory(blkmem, randnumgen);
10218
10219 return;
10220}
10221
10222/** returns a random integer between minrandval and maxrandval */
10224 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10225 int minrandval, /**< minimal value to return */
10226 int maxrandval /**< maximal value to return */
10227 )
10228{
10229 SCIP_Real randnumber;
10230 SCIP_Longint zeromax;
10231
10232 randnumber = (SCIP_Real)randomGetRand(randnumgen)/(UINT32_MAX+1.0);
10233 assert(randnumber >= 0.0);
10234 assert(randnumber < 1.0);
10235
10236 /* we need to shift the range to the non-negative integers to handle negative integer values correctly.
10237 * we use a long integer to avoid overflows.
10238 */
10239 zeromax = (SCIP_Longint)maxrandval - (SCIP_Longint)minrandval + 1;
10240
10241 return (int) ((SCIP_Longint)(zeromax * randnumber) + (SCIP_Longint)minrandval);
10242}
10243
10244/** returns a random real between minrandval and maxrandval */
10246 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10247 SCIP_Real minrandval, /**< minimal value to return */
10248 SCIP_Real maxrandval /**< maximal value to return */
10249 )
10250{
10251 SCIP_Real randnumber;
10252
10253 randnumber = (SCIP_Real)randomGetRand(randnumgen)/(SCIP_Real)UINT32_MAX;
10254 assert(randnumber >= 0.0);
10255 assert(randnumber <= 1.0);
10256
10257 /* we multiply minrandval and maxrandval separately by randnumber in order to avoid overflow if they are more than
10258 * SCIP_REAL_MAX apart
10259 */
10260 return minrandval*(1.0 - randnumber) + maxrandval*randnumber;
10261}
10262
10263/** randomly shuffles parts of an integer array using the Fisher-Yates algorithm */
10265 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10266 int* array, /**< array to be shuffled */
10267 int begin, /**< first included index that should be subject to shuffling
10268 * (0 for first array entry)
10269 */
10270 int end /**< first excluded index that should not be subject to shuffling
10271 * (array size for last array entry)
10272 */
10273 )
10274{
10275 int tmp;
10276 int i;
10277
10278 /* loop backwards through all elements and always swap the current last element to a random position */
10279 while( end > begin+1 )
10280 {
10281 --end;
10282
10283 /* get a random position into which the last entry should be shuffled */
10284 i = SCIPrandomGetInt(randnumgen, begin, end);
10285
10286 /* swap the last element and the random element */
10287 tmp = array[i];
10288 array[i] = array[end];
10289 array[end] = tmp;
10290 }
10291}
10292
10293/** randomly shuffles parts of an array using the Fisher-Yates algorithm */
10295 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10296 void** array, /**< array to be shuffled */
10297 int begin, /**< first included index that should be subject to shuffling
10298 * (0 for first array entry)
10299 */
10300 int end /**< first excluded index that should not be subject to shuffling
10301 * (array size for last array entry)
10302 */
10303 )
10304{
10305 void* tmp;
10306 int i;
10307
10308 /* loop backwards through all elements and always swap the current last element to a random position */
10309 while( end > begin+1 )
10310 {
10311 end--;
10312
10313 /* get a random position into which the last entry should be shuffled */
10314 i = SCIPrandomGetInt(randnumgen, begin, end);
10315
10316 /* swap the last element and the random element */
10317 tmp = array[i];
10318 array[i] = array[end];
10319 array[end] = tmp;
10320 }
10321}
10322
10323/** draws a random subset of disjoint elements from a given set of disjoint elements;
10324 * this implementation is suited for the case that nsubelems is considerably smaller then nelems
10325 */
10327 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10328 void** set, /**< original set, from which elements should be drawn */
10329 int nelems, /**< number of elements in original set */
10330 void** subset, /**< subset in which drawn elements should be stored */
10331 int nsubelems /**< number of elements that should be drawn and stored */
10332 )
10333{
10334 int i;
10335 int j;
10336
10337 /* if both sets are of equal size, we just copy the array */
10338 if( nelems == nsubelems)
10339 {
10340 BMScopyMemoryArray(subset,set,nelems);
10341 return SCIP_OKAY;
10342 }
10343
10344 /* abort, if size of subset is too big */
10345 if( nsubelems > nelems )
10346 {
10347 SCIPerrorMessage("Cannot create %d-elementary subset of %d-elementary set.\n", nsubelems, nelems);
10348 return SCIP_INVALIDDATA;
10349 }
10350#ifndef NDEBUG
10351 for( i = 0; i < nsubelems; i++ )
10352 for( j = 0; j < i; j++ )
10353 assert(set[i] != set[j]);
10354#endif
10355
10356 /* draw each element individually */
10357 i = 0;
10358 while( i < nsubelems )
10359 {
10360 int r;
10361
10362 r = SCIPrandomGetInt(randnumgen, 0, nelems-1);
10363 subset[i] = set[r];
10364
10365 /* if we get an element that we already had, we will draw again */
10366 for( j = 0; j < i; j++ )
10367 {
10368 if( subset[i] == subset[j] )
10369 {
10370 --i;
10371 break;
10372 }
10373 }
10374 ++i;
10375 }
10376 return SCIP_OKAY;
10377}
10378
10379/*
10380 * Additional math functions
10381 */
10382
10383/** calculates a binomial coefficient n over m, choose m elements out of n, maximal value will be 33 over 16 (because
10384 * the n=33 is the last line in the Pascal's triangle where each entry fits in a 4 byte value), an error occurs due to
10385 * big numbers or an negative value m (and m < n) and -1 will be returned
10386 */
10388 int n, /**< number of different elements */
10389 int m /**< number to choose out of the above */
10390 )
10391{
10392 if( m == 0 || m >= n )
10393 return 1;
10394
10395 if( m < 0 )
10396 return -1;
10397
10398 /* symmetry of the binomial coefficient, choose smaller m */
10399 if( m > n/2 )
10400 m = n - m;
10401
10402 /* trivial case m == 1 */
10403 if( m == 1 )
10404 return n;
10405
10406 /* simple case m == 2 */
10407 if( m == 2 )
10408 {
10409 if( ((SCIP_Real)SCIP_LONGINT_MAX) / n >= (n-1) * 2 ) /*lint !e790*/
10410 return ((SCIP_Longint)n*(n-1)/2); /*lint !e647*/
10411 else
10412 return -1;
10413 }
10414
10415 /* abort on to big numbers */
10416 if( m > 16 || n > 33 )
10417 return -1;
10418
10419 /* simple case m == 3 */
10420 if( m == 3 )
10421 return (n*(n-1)*(n-2)/6); /*lint !e647*/
10422 else
10423 {
10424 /* first half of Pascal's triangle numbers(without the symmetric part) backwards from (33,16) over (32,16),
10425 * (33,15), (32,15),(31,15, (30,15), (33,14) to (8,4) (rest is calculated directly)
10426 *
10427 * due to this order we can extract the right binomial coefficient by (16-m)^2+(16-m)+(33-n)
10428 */
10429 static const SCIP_Longint binoms[182] = {
10430 1166803110, 601080390, 1037158320, 565722720, 300540195, 155117520, 818809200, 471435600, 265182525, 145422675,
10431 77558760, 40116600, 573166440, 347373600, 206253075, 119759850, 67863915, 37442160, 20058300, 10400600,
10432 354817320, 225792840, 141120525, 86493225, 51895935, 30421755, 17383860, 9657700, 5200300, 2704156, 193536720,
10433 129024480, 84672315, 54627300, 34597290, 21474180, 13037895, 7726160, 4457400, 2496144, 1352078, 705432,
10434 92561040, 64512240, 44352165, 30045015, 20030010, 13123110, 8436285, 5311735, 3268760, 1961256, 1144066,
10435 646646, 352716, 184756, 38567100, 28048800, 20160075, 14307150, 10015005, 6906900, 4686825, 3124550, 2042975,
10436 1307504, 817190, 497420, 293930, 167960, 92378, 48620, 13884156, 10518300, 7888725, 5852925, 4292145, 3108105,
10437 2220075, 1562275, 1081575, 735471, 490314, 319770, 203490, 125970, 75582, 43758, 24310, 12870, 4272048, 3365856,
10438 2629575, 2035800, 1560780, 1184040, 888030, 657800, 480700, 346104, 245157, 170544, 116280, 77520, 50388, 31824,
10439 19448, 11440, 6435, 3432, 1107568, 906192, 736281, 593775, 475020, 376740, 296010, 230230, 177100, 134596,
10440 100947, 74613, 54264, 38760, 27132, 18564, 12376, 8008, 5005, 3003, 1716, 924, 237336, 201376, 169911, 142506,
10441 118755, 98280, 80730, 65780, 53130, 42504, 33649, 26334, 20349, 15504, 11628, 8568, 6188, 4368, 3003, 2002,
10442 1287, 792, 462, 252, 40920, 35960, 31465, 27405, 23751, 20475, 17550, 14950, 12650, 10626, 8855, 7315, 5985,
10443 4845, 3876, 3060, 2380, 1820, 1365, 1001, 715, 495, 330, 210, 126, 70};
10444
10445 /* m can at most be 16 */
10446 const int t = 16-m;
10447 assert(t >= 0);
10448 assert(n <= 33);
10449
10450 /* binoms array hast exactly 182 elements */
10451 assert(t*(t+1)+(33-n) < 182);
10452
10453 return binoms[t*(t+1)+(33-n)]; /*lint !e662 !e661*/
10454 }
10455}
10456
10457#ifndef NDEBUG
10458/** calculates hash for floating-point number by using Fibonacci hashing */
10459#if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ * 10 >= 490 && !defined(__INTEL_COMPILER)
10460__attribute__((no_sanitize_undefined))
10461#endif
10462unsigned int SCIPcalcFibHash(
10463 SCIP_Real v /**< number to hash */
10464 )
10465{
10466 if( v >= 0 )
10467 return ((unsigned long long)(v * 2654435769)) % UINT_MAX;
10468 return ((unsigned long long)(-v * 683565275)) % UINT_MAX;
10469}
10470#endif
10471
10472/** negates a number */
10474 SCIP_Real x /**< value to negate */
10475 )
10476{
10477 return -x;
10478}
10479
10480/*
10481 * Permutations / Shuffling
10482 */
10483
10484/** swaps two ints */
10486 int* value1, /**< pointer to first integer */
10487 int* value2 /**< pointer to second integer */
10488 )
10489{
10490 int tmp;
10491
10492 tmp = *value1;
10493 *value1 = *value2;
10494 *value2 = tmp;
10495}
10496
10497/** swaps two real values */
10499 SCIP_Real* value1, /**< pointer to first real value */
10500 SCIP_Real* value2 /**< pointer to second real value */
10501 )
10502{
10503 SCIP_Real tmp;
10504
10505 tmp = *value1;
10506 *value1 = *value2;
10507 *value2 = tmp;
10508}
10509
10510/** swaps the addresses of two pointers */
10512 void** pointer1, /**< first pointer */
10513 void** pointer2 /**< second pointer */
10514 )
10515{
10516 void* tmp;
10517
10518 tmp = *pointer1;
10519 *pointer1 = *pointer2;
10520 *pointer2 = tmp;
10521}
10522
10523
10524/*
10525 * Arrays
10526 */
10527
10528
10529/** computes set intersection (duplicates removed) of two integer arrays that are ordered ascendingly */
10531 int* array1, /**< first array (in ascending order) */
10532 int narray1, /**< number of entries of first array */
10533 int* array2, /**< second array (in ascending order) */
10534 int narray2, /**< number of entries of second array */
10535 int* intersectarray, /**< intersection of array1 and array2
10536 * (note: it is possible to use array1 for this input argument) */
10537 int* nintersectarray /**< pointer to store number of entries of intersection array
10538 * (note: it is possible to use narray1 for this input argument) */
10539 )
10540{
10541 int cnt = 0;
10542 int k = 0;
10543 int v1;
10544 int v2;
10545
10546 assert( array1 != NULL );
10547 assert( array2 != NULL );
10548 assert( intersectarray != NULL );
10549 assert( nintersectarray != NULL );
10550
10551 /* determine intersection of array1 and array2 */
10552 for (v1 = 0; v1 < narray1; ++v1)
10553 {
10554 assert( v1 == 0 || array1[v1] >= array1[v1-1] );
10555
10556 /* skip duplicate entries */
10557 if ( v1+1 < narray1 && array1[v1] == array1[v1+1])
10558 continue;
10559
10560 for (v2 = k; v2 < narray2; ++v2)
10561 {
10562 assert( v2 == 0 || array2[v2] >= array2[v2-1] );
10563
10564 if ( array2[v2] > array1[v1] )
10565 {
10566 k = v2;
10567 break;
10568 }
10569 else if ( array2[v2] == array1[v1] )
10570 {
10571 intersectarray[cnt++] = array2[v2];
10572 k = v2 + 1;
10573 break;
10574 }
10575 }
10576 }
10577
10578 /* store size of intersection array */
10579 *nintersectarray = cnt;
10580}
10581
10582/** computes set intersection (duplicates removed) of two void-pointer arrays that are ordered ascendingly */
10584 void** array1, /**< pointer to first data array */
10585 int narray1, /**< number of entries of first array */
10586 void** array2, /**< pointer to second data array */
10587 int narray2, /**< number of entries of second array */
10588 SCIP_DECL_SORTPTRCOMP((*ptrcomp)), /**< data element comparator */
10589 void** intersectarray, /**< intersection of array1 and array2
10590 * (note: it is possible to use array1 for this input argument) */
10591 int* nintersectarray /**< pointer to store number of entries of intersection array
10592 * (note: it is possible to use narray1 for this input argument) */
10593 )
10594{
10595 int cnt = 0;
10596 int k = 0;
10597 int v1;
10598 int v2;
10599
10600 assert( array1 != NULL );
10601 assert( array2 != NULL );
10602 assert( ptrcomp != NULL );
10603 assert( intersectarray != NULL );
10604 assert( nintersectarray != NULL );
10605
10606 /* determine intersection of array1 and array2 */
10607 for( v1 = 0; v1 < narray1; ++v1 )
10608 {
10609 assert( v1 == 0 || (*ptrcomp)(array1[v1], array1[v1-1]) >= 0 );
10610
10611 /* skip duplicate entries */
10612 if( v1+1 < narray1 && array1[v1] == array1[v1+1] )
10613 continue;
10614
10615 for( v2 = k; v2 < narray2; ++v2 )
10616 {
10617 assert( v2 == 0 || (*ptrcomp)(array2[v2], array2[v2-1]) > 0 || array2[v2] == array2[v2-1] );
10618
10619 if( (*ptrcomp)(array2[v2], array1[v1]) > 0 )
10620 {
10621 k = v2;
10622 break;
10623 }
10624
10625 if( array2[v2] == array1[v1] )
10626 {
10627 intersectarray[cnt++] = array2[v2];
10628 k = v2 + 1;
10629 break;
10630 }
10631 }
10632 }
10633
10634 /* store size of intersection array */
10635 *nintersectarray = cnt;
10636}
10637
10638/** computes set difference (duplicates removed) of two integer arrays that are ordered ascendingly */
10640 int* array1, /**< first array (in ascending order) */
10641 int narray1, /**< number of entries of first array */
10642 int* array2, /**< second array (in ascending order) */
10643 int narray2, /**< number of entries of second array */
10644 int* setminusarray, /**< array to store entries of array1 that are not an entry of array2
10645 * (note: it is possible to use array1 for this input argument) */
10646 int* nsetminusarray /**< pointer to store number of entries of setminus array
10647 * (note: it is possible to use narray1 for this input argument) */
10648 )
10649{
10650 int cnt = 0;
10651 int v1 = 0;
10652 int v2 = 0;
10653
10654 assert( array1 != NULL );
10655 assert( array2 != NULL );
10656 assert( setminusarray != NULL );
10657 assert( nsetminusarray != NULL );
10658
10659 while ( v1 < narray1 )
10660 {
10661 int entry1;
10662
10663 assert( v1 == 0 || array1[v1] >= array1[v1-1] );
10664
10665 /* skip duplicate entries */
10666 while ( v1 + 1 < narray1 && array1[v1] == array1[v1 + 1] )
10667 ++v1;
10668
10669 entry1 = array1[v1];
10670
10671 while ( v2 < narray2 && array2[v2] < entry1 )
10672 ++v2;
10673
10674 if ( v2 >= narray2 || entry1 < array2[v2] )
10675 setminusarray[cnt++] = entry1;
10676 ++v1;
10677 }
10678
10679 /* store size of setminus array */
10680 *nsetminusarray = cnt;
10681}
10682
10683
10684/*
10685 * Strings
10686 */
10687
10688
10689/** copies characters from 'src' to 'dest', copying is stopped when either the 'stop' character is reached or after
10690 * 'cnt' characters have been copied, whichever comes first.
10691 *
10692 * @note undefined behavior on overlapping arrays
10693 */
10695 char* dest, /**< destination pointer to copy to */
10696 const char* src, /**< source pointer to copy from */
10697 char stop, /**< character when found stop copying */
10698 unsigned int cnt /**< maximal number of characters to copy */
10699 )
10700{
10701 if( dest == NULL || src == NULL || cnt == 0 )
10702 return -1;
10703 else
10704 {
10705 char* destination = dest;
10706
10707 while( cnt-- && (*destination++ = *src++) != stop ); /*lint !e722*/
10708
10709 return (int)(destination - dest);
10710 }
10711}
10712
10713/** prints an error message containing of the given string followed by a string describing the current system error
10714 *
10715 * Prefers to use the strerror_r method, which is threadsafe. On systems where this method does not exist,
10716 * NO_STRERROR_R should be defined (see INSTALL). In this case, strerror is used which is not guaranteed to be
10717 * threadsafe (on SUN-systems, it actually is).
10718 */
10720 const char* message /**< first part of the error message, e.g. the filename */
10721 )
10722{
10723#ifdef NO_STRERROR_R
10724 SCIPmessagePrintError("%s: %s\n", message, strerror(errno));
10725#else
10726 char buf[SCIP_MAXSTRLEN];
10727
10728#ifdef _WIN32
10729 /* strerror_s returns 0 on success; the string is \0 terminated. */
10730 if ( strerror_s(buf, SCIP_MAXSTRLEN, errno) != 0 )
10731 SCIPmessagePrintError("Unknown error number %d or error message too long.\n", errno);
10732 SCIPmessagePrintError("%s: %s\n", message, buf);
10733#elif (_POSIX_C_SOURCE >= 200112L || __DARWIN_C_LEVEL > 200112L || _XOPEN_SOURCE >= 600) && ! defined(_GNU_SOURCE)
10734 /* We are in the POSIX/XSI case, where strerror_r returns 0 on success; \0 termination is unclear. */
10735 if ( strerror_r(errno, buf, SCIP_MAXSTRLEN) != 0 )
10736 SCIPmessagePrintError("Unknown error number %d.\n", errno);
10737 buf[SCIP_MAXSTRLEN - 1] = '\0';
10738 SCIPmessagePrintError("%s: %s\n", message, buf);
10739#else
10740 /* We are in the GNU case, where strerror_r returns a pointer to the error string. This string is possibly stored
10741 * in buf and is always \0 terminated.
10742 * However, if compiling on one system and executing on another system, we might actually call a different
10743 * variant of the strerror_r function than we had at compile time.
10744 */
10745 char* errordescr;
10746 *buf = '\0';
10747 errordescr = strerror_r(errno, buf, SCIP_MAXSTRLEN);
10748 if( *buf != '\0' )
10749 {
10750 /* strerror_r wrote into buf */
10751 SCIPmessagePrintError("%s: %s\n", message, buf);
10752 }
10753 else if( errordescr != NULL )
10754 {
10755 /* strerror_r returned something non-NULL */
10756 SCIPmessagePrintError("%s: %s\n", message, errordescr);
10757 }
10758 else
10759 {
10760 /* strerror_r did return NULL and did not write into buf */
10761 SCIPmessagePrintError("Could not obtain description for error %d.\n", errno);
10762 }
10763#endif
10764#endif
10765}
10766
10767/** extracts tokens from strings - wrapper method for strtok_r() */
10769 char* s, /**< string to parse */
10770 const char* delim, /**< delimiters for parsing */
10771 char** ptrptr /**< pointer to working char pointer - must stay the same while parsing */
10772 )
10773{
10774#ifdef SCIP_NO_STRTOK_R
10775 return strtok(s, delim);
10776#else
10777 return strtok_r(s, delim, ptrptr);
10778#endif
10779}
10780
10781/** translates the given string into a string where unescaped symbols ", ', and spaces are escaped with a \ prefix */
10783 char* t, /**< target buffer to store escaped string */
10784 int bufsize, /**< size of buffer t */
10785 const char* s /**< string to transform into escaped string */
10786 )
10787{
10788 int len;
10789 int i;
10790 int p;
10791
10792 assert(t != NULL);
10793 assert(bufsize > 0);
10794
10795 len = (int)strlen(s);
10796 for( p = 0, i = 0; i <= len && p < bufsize; ++i, ++p )
10797 {
10798 if( s[i] == '\\' )
10799 {
10800 t[p] = s[i];
10801 ++p; /*lint !e850*/
10802 ++i; /*lint !e850*/
10803 }
10804 else if( s[i] == ' ' || s[i] == '\"' || s[i] == '\'' )
10805 {
10806 t[p] = '\\';
10807 ++p; /*lint !e850*/
10808 }
10809 if( i <= len && p < bufsize )
10810 t[p] = s[i];
10811 }
10812 t[bufsize-1] = '\0';
10813}
10814
10815/** increases string pointer as long as it refers to a space character or an explicit space control sequence */
10817 char** s /**< pointer to string pointer */
10818 )
10819{
10820 while( isspace((unsigned char)**s) || ( **s == '\\' && *(*s+1) != '\0' && strchr(SCIP_SPACECONTROL, *(*s+1)) ) )
10821 *s += **s == '\\' ? 2 : 1;
10822
10823 return SCIP_OKAY;
10824}
10825
10826/* safe version of snprintf */
10828 char* t, /**< target string */
10829 int len, /**< length of the string to copy */
10830 const char* s, /**< source string */
10831 ... /**< further parameters */
10832 )
10833{
10834 va_list ap;
10835 int n;
10836
10837 assert(t != NULL);
10838 assert(len > 0);
10839
10840 va_start(ap, s); /*lint !e826*/
10841
10842#if defined(_MSC_VER) && _MSC_VER < 1900
10843 n = _vsnprintf(t, (size_t) len, s, ap);
10844#else
10845 n = vsnprintf(t, (size_t) len, s, ap); /*lint !e571*/
10846#endif
10847 va_end(ap);
10848
10849 if( n < 0 || n >= len )
10850 {
10851#ifndef NDEBUG
10852 if( n < 0 )
10853 {
10854 SCIPerrorMessage("vsnprintf returned %d\n",n);
10855 }
10856#endif
10857 t[len-1] = '\0';
10858 }
10859 return n;
10860}
10861
10862/** portable version of strcasecmp for case-insensitive comparison of two strings */
10864 const char* s1, /**< first string */
10865 const char* s2 /**< second string */
10866 )
10867{
10868#ifdef _MSC_VER
10869 return _stricmp(s1, s2);
10870#else
10871 return strcasecmp(s1, s2);
10872#endif
10873}
10874
10875/** portable version of strncasecmp for case-insensitive comparison of two strings up to a given number of characters */
10877 const char* s1, /**< first string */
10878 const char* s2, /**< second string */
10879 int length /**< maximal length to compare */
10880 )
10881{
10882 assert(length >= 0);
10883#ifdef _MSC_VER
10884 return _strnicmp(s1, s2, (size_t)length);
10885#else
10886 return strncasecmp(s1, s2, (size_t)length); /*lint !e571*/
10887#endif
10888}
10889
10890/** safe version of strncpy
10891 *
10892 * Copies string in s to t using at most @a size-1 nonzero characters (strncpy copies size characters). It always adds
10893 * a terminating zero char. Does not pad the remaining string with zero characters (unlike strncpy). Returns the number
10894 * of copied nonzero characters, if the length of s is at most size - 1, and returns size otherwise. Thus, the original
10895 * string was truncated if the return value is size.
10896 */
10898 char* t, /**< target string */
10899 const char* s, /**< source string */
10900 int size /**< maximal size of t */
10901 )
10902{
10903 int n;
10904
10905 if( size <= 0 )
10906 return 0;
10907
10908 /* decrease size by 1 to create space for terminating zero char */
10909 --size;
10910 for( n = 0; n < size && *s != '\0'; n++ )
10911 *(t++) = *(s++);
10912 *t = '\0';
10913
10914 if( *s != '\0' )
10915 ++n;
10916
10917 return n;
10918}
10919
10920/** extract the next token as a integer value if it is one; in case no value is parsed the endptr is set to @p str
10921 *
10922 * @return Returns TRUE if a value could be extracted, otherwise FALSE
10923 */
10925 const char* str, /**< string to search */
10926 int* value, /**< pointer to store the parsed value */
10927 char** endptr /**< pointer to store the final string position if successfully parsed, otherwise @p str */
10928 )
10929{
10930 assert(str != NULL);
10931 assert(value != NULL);
10932 assert(endptr != NULL);
10933
10934 /* init errno to detect possible errors */
10935 errno = 0;
10936
10937 *value = (int) strtol(str, endptr, 10);
10938
10939 if( *endptr != str && *endptr != NULL )
10940 {
10941 SCIPdebugMessage("parsed integer value <%d>\n", *value);
10942 return TRUE;
10943 }
10944 *endptr = (char*)str;
10945
10946 SCIPdebugMessage("failed parsing integer value <%s>\n", str);
10947
10948 return FALSE;
10949}
10950
10951/** extract the next token as a double value if it is one; in case no value is parsed the endptr is set to @p str
10952 *
10953 * @return Returns TRUE if a value could be extracted, otherwise FALSE
10954 */
10956 const char* str, /**< string to search */
10957 SCIP_Real* value, /**< pointer to store the parsed value */
10958 char** endptr /**< pointer to store the final string position if successfully parsed, otherwise @p str */
10959 )
10960{
10961 assert(str != NULL);
10962 assert(value != NULL);
10963 assert(endptr != NULL);
10964
10965 /* init errno to detect possible errors */
10966 errno = 0;
10967
10968 *value = strtod(str, endptr);
10969
10970 if( *endptr != str && *endptr != NULL )
10971 {
10972 SCIPdebugMessage("parsed real value <%g>\n", *value);
10973 return TRUE;
10974 }
10975 *endptr = (char*)str;
10976
10977 SCIPdebugMessage("failed parsing real value <%s>\n", str);
10978
10979 return FALSE;
10980}
10981
10982/** copies the first size characters between a start and end character of str into token, if no error occurred endptr
10983 * will point to the position after the read part, otherwise it will point to @p str
10984 */
10986 const char* str, /**< string to search */
10987 char startchar, /**< character which defines the beginning */
10988 char endchar, /**< character which defines the ending */
10989 char* token, /**< string to store the copy */
10990 int size, /**< size of the token char array */
10991 char** endptr /**< pointer to store the final string position if successfully parsed, otherwise @p str */
10992 )
10993{
10994 const char* copystr;
10995 int nchars;
10996
10997 assert(str != NULL);
10998 assert(token != NULL);
10999 assert(size > 0);
11000 assert(endptr != NULL);
11001
11002 nchars = 0;
11003
11004 copystr = str;
11005
11006 /* find starting character */
11007 while( *str != '\0' && *str != startchar )
11008 ++str;
11009
11010 /* did not find start character */
11011 if( *str == '\0' )
11012 {
11013 *endptr = (char*)copystr;
11014 return;
11015 }
11016
11017 /* skip start character */
11018 ++str;
11019
11020 /* copy string */
11021 while( *str != '\0' && *str != endchar && nchars < size-1 )
11022 {
11023 assert(nchars < SCIP_MAXSTRLEN);
11024 token[nchars] = *str;
11025 nchars++;
11026 ++str;
11027 }
11028
11029 /* add end to token */
11030 token[nchars] = '\0';
11031
11032 /* if section was longer than size, we want to reach the end of the parsing section anyway */
11033 if( nchars == (size-1) )
11034 while( *str != '\0' && *str != endchar )
11035 ++str;
11036
11037 /* did not find end character */
11038 if( *str == '\0' )
11039 {
11040 *endptr = (char*)copystr;
11041 return;
11042 }
11043
11044 /* skip end character */
11045 ++str;
11046
11047 SCIPdebugMessage("parsed section <%s>\n", token);
11048
11049 *endptr = (char*) str;
11050}
11051
11052/*
11053 * File methods
11054 */
11055
11056/** returns whether the given file exists */
11058 const char* filename /**< file name */
11059 )
11060{
11061 FILE* f;
11062
11063 f = fopen(filename, "r");
11064 if( f == NULL )
11065 return FALSE;
11066
11067 fclose(f);
11068
11069 return TRUE;
11070}
11071
11072/** splits filename into path, name, and extension */
11074 char* filename, /**< filename to split; is destroyed (but not freed) during process */
11075 char** path, /**< pointer to store path, or NULL if not needed */
11076 char** name, /**< pointer to store name, or NULL if not needed */
11077 char** extension, /**< pointer to store extension, or NULL if not needed */
11078 char** compression /**< pointer to store compression extension, or NULL if not needed */
11079 )
11080{
11081 char* lastslash;
11082 char* lastbackslash;
11083 char* lastdot;
11084
11085 assert(filename != NULL);
11086
11087 if( path != NULL )
11088 *path = NULL;
11089 if( name != NULL )
11090 *name = NULL;
11091 if( extension != NULL )
11092 *extension = NULL;
11093 if( compression != NULL )
11094 *compression = NULL;
11095
11096 /* treat both slashes '/' and '\' as directory delimiters */
11097 lastslash = strrchr(filename, '/');
11098 lastbackslash = strrchr(filename, '\\');
11099 lastslash = MAX(lastslash, lastbackslash); /*lint !e613*/
11100 lastdot = strrchr(filename, '.');
11101 if( lastslash != NULL && lastdot != NULL && lastdot < lastslash ) /* is the last dot belonging to the path? */
11102 lastdot = NULL;
11103
11104 /* detect known compression extensions */
11105#ifdef SCIP_WITH_ZLIB
11106 if( lastdot != NULL )
11107 {
11108 char* compext;
11109
11110 compext = lastdot+1;
11111 if( strcmp(compext, "gz") == 0
11112 || strcmp(compext, "z") == 0
11113 || strcmp(compext, "Z") == 0 )
11114 {
11115 if( compression != NULL )
11116 *compression = compext;
11117 *lastdot = '\0';
11118 }
11119
11120 /* find again the last dot in the filename without compression extension */
11121 lastdot = strrchr(filename, '.');
11122 if( lastslash != NULL && lastdot != NULL && lastdot < lastslash ) /* is the last dot belonging to the path? */
11123 lastdot = NULL;
11124 }
11125#endif
11126
11127 if( lastslash == NULL )
11128 {
11129 if( name != NULL )
11130 *name = filename;
11131 }
11132 else
11133 {
11134 if( path != NULL )
11135 *path = filename;
11136 if( name != NULL )
11137 *name = lastslash+1;
11138 *lastslash = '\0';
11139 }
11140
11141 if( lastdot != NULL )
11142 {
11143 if( extension != NULL )
11144 *extension = lastdot+1;
11145 *lastdot = '\0';
11146 }
11147}
11148
11149/*
11150 * simple functions implemented as defines
11151 */
11152
11153/* In debug mode, the following methods are implemented as function calls to ensure
11154 * type validity.
11155 * In optimized mode, the methods are implemented as defines to improve performance.
11156 * However, we want to have them in the library anyways, so we have to undef the defines.
11157 */
11158
11159#undef SCIPrelDiff
11160
11161/** returns the relative difference: (val1-val2)/max(|val1|,|val2|,1.0) */
11163 SCIP_Real val1, /**< first value to be compared */
11164 SCIP_Real val2 /**< second value to be compared */
11165 )
11166{
11167 SCIP_Real absval1;
11168 SCIP_Real absval2;
11169 SCIP_Real quot;
11170
11171 absval1 = REALABS(val1);
11172 absval2 = REALABS(val2);
11173 quot = MAX3(1.0, absval1, absval2);
11174
11175 return (val1-val2)/quot;
11176}
11177
11178
11179/** computes the gap from the primal and the dual bound */
11181 SCIP_Real eps, /**< the value treated as zero */
11182 SCIP_Real inf, /**< the value treated as infinity */
11183 SCIP_Real primalbound, /**< the primal bound */
11184 SCIP_Real dualbound /**< the dual bound */
11185 )
11186{
11187 if( EPSEQ(primalbound, dualbound, eps) )
11188 return 0.0;
11189 else
11190 {
11191 SCIP_Real absdual = REALABS(dualbound);
11192 SCIP_Real absprimal = REALABS(primalbound);
11193
11194 if( EPSZ(dualbound, eps) || EPSZ(primalbound, eps) || absprimal >= inf || absdual >= inf ||
11195 primalbound * dualbound < 0.0 )
11196 return inf;
11197 else
11198 return REALABS((primalbound - dualbound)/MIN(absdual, absprimal));
11199 }
11200}
11201
11202/*
11203 * disjoint set (union-find) data structure
11204 */
11205
11206/** creates a disjoint set (union find) structure \p djset for \p ncomponents many components (of size one) */
11208 SCIP_DISJOINTSET** djset, /**< disjoint set (union find) data structure */
11209 BMS_BLKMEM* blkmem, /**< block memory */
11210 int ncomponents /**< number of components */
11211 )
11212{
11213 assert(djset != NULL);
11214 assert(blkmem != NULL);
11215
11216 /* allocate the necessary memory */
11217 assert(ncomponents > 0);
11218 SCIP_ALLOC( BMSallocBlockMemory(blkmem, djset) );
11219 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &((*djset)->parents), ncomponents) );
11220 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &((*djset)->sizes), ncomponents) );
11221 (*djset)->size = ncomponents;
11222
11223 /* clear the data structure */
11224 SCIPdisjointsetClear(*djset);
11225
11226 return SCIP_OKAY;
11227}
11228
11229/** clears the disjoint set (union find) structure \p djset */
11231 SCIP_DISJOINTSET* djset /**< disjoint set (union find) data structure */
11232 )
11233{
11234 int i;
11235
11236 djset->componentcount = djset->size;
11237
11238 /* reset all components to be unconnected */
11239 for( i = 0; i < djset->componentcount; i++ )
11240 {
11241 djset->parents[i] = i;
11242 djset->sizes[i] = 1;
11243 }
11244}
11245
11246/** finds and returns the component identifier of this \p element */
11248 SCIP_DISJOINTSET* djset, /**< disjoint set (union find) data structure */
11249 int element /**< element to be found */
11250 )
11251{
11252 int newelement;
11253 int root = element;
11254 int* parents = djset->parents;
11255
11256 /* find root of this element */
11257 while( root != parents[root] )
11258 {
11259 root = parents[root];
11260 }
11261
11262 /* compress the path to make future queries faster */
11263 while( element != root )
11264 {
11265 newelement = parents[element];
11266 parents[element] = root;
11267 element = newelement;
11268 }
11269
11270 return root;
11271}
11272
11273/** merges the components containing the elements \p p and \p q */
11275 SCIP_DISJOINTSET* djset, /**< disjoint set (union find) data structure */
11276 int p, /**< first element */
11277 int q, /**< second element */
11278 SCIP_Bool forcerepofp /**< force representative of p to be new representative */
11279 )
11280{
11281 int idp;
11282 int idq;
11283 int* sizes;
11284 int* parents;
11285
11286 assert(djset != NULL);
11287 assert(0 <= p);
11288 assert(0 <= q);
11289 assert(djset->size > p);
11290 assert(djset->size > q);
11291
11292 idp = SCIPdisjointsetFind(djset, p);
11293 idq = SCIPdisjointsetFind(djset, q);
11294
11295 /* if p and q lie in the same component, there is nothing to be done */
11296 if( idp == idq )
11297 return;
11298
11299 sizes = djset->sizes;
11300 parents = djset->parents;
11301
11302 if( forcerepofp )
11303 {
11304 parents[idq] = idp;
11305 sizes[idp] += sizes[idq];
11306 }
11307 else
11308 {
11309 if( sizes[idp] < sizes[idq] )
11310 {
11311 parents[idp] = idq;
11312 sizes[idq] += sizes[idp];
11313 }
11314 else
11315 {
11316 parents[idq] = idp;
11317 sizes[idp] += sizes[idq];
11318 }
11319 }
11320 /* one less component */
11321 djset->componentcount--;
11322}
11323
11324/** frees the disjoint set (union find) data structure */
11326 SCIP_DISJOINTSET** djset, /**< pointer to disjoint set (union find) data structure */
11327 BMS_BLKMEM* blkmem /**< block memory */
11328 )
11329{
11330 SCIP_DISJOINTSET* dsptr;
11331
11332 assert(djset != NULL);
11333 assert(*djset != NULL);
11334
11335 dsptr = *djset;
11336
11337 BMSfreeBlockMemoryArray(blkmem, &dsptr->sizes, dsptr->size);
11338 BMSfreeBlockMemoryArray(blkmem, &dsptr->parents, dsptr->size);
11339
11340 BMSfreeBlockMemory(blkmem, djset);
11341}
11342
11343/** returns the number of independent components in this disjoint set (union find) data structure */
11345 SCIP_DISJOINTSET* djset /**< disjoint set (union find) data structure */
11346 )
11347{
11348 assert(djset != NULL);
11349
11350 return djset->componentcount;
11351}
11352
11353/** returns the size (number of nodes) of this disjoint set (union find) data structure */
11355 SCIP_DISJOINTSET* djset /**< disjoint set (union find) data structure */
11356 )
11357{
11358 assert(djset != NULL);
11359
11360 return djset->size;
11361}
11362
11363/** checks whether a given string t appears at the beginning of the string s (up to spaces at beginning) */
11365 const char* s, /**< string to search in */
11366 const char* t, /**< string to search for */
11367 size_t tlen /**< length of t */
11368 )
11369{
11370 int idxctr = 0;
11371
11372 assert(s != NULL);
11373 assert(t != NULL);
11374
11375 /* skip whitespace at beginning */
11376 while( idxctr < SCIP_MAXSTRLEN && isspace((unsigned char)s[idxctr]) )
11377 ++idxctr;
11378 if( strncmp(&s[idxctr], t, tlen) == 0 )
11379 return TRUE;
11380 return FALSE;
11381}
SCIP_VAR * h
Definition: circlepacking.c:68
SCIP_VAR * w
Definition: circlepacking.c:67
SCIP_VAR * a
Definition: circlepacking.c:66
SCIP_VAR ** b
Definition: circlepacking.c:65
SCIP_VAR ** y
Definition: circlepacking.c:64
SCIP_Real * r
Definition: circlepacking.c:59
SCIP_VAR ** x
Definition: circlepacking.c:63
common defines and data types used in all packages of SCIP
#define NULL
Definition: def.h:248
#define SCIP_MAXSTRLEN
Definition: def.h:269
#define SCIP_Longint
Definition: def.h:141
#define SCIP_UNUSED(x)
Definition: def.h:409
#define LOG2(x)
Definition: def.h:211
#define SCIP_SPACECONTROL
Definition: def.h:270
#define SCIP_REAL_MAX
Definition: def.h:158
#define SCIP_INVALID
Definition: def.h:178
#define SCIP_Bool
Definition: def.h:91
#define SCIP_DEFAULT_EPSILON
Definition: def.h:164
#define MIN(x, y)
Definition: def.h:224
#define SCIP_ALLOC(x)
Definition: def.h:366
#define MAX3(x, y, z)
Definition: def.h:228
#define SCIP_ALLOC_TERMINATE(retcode, x, TERM)
Definition: def.h:386
#define SCIP_Real
Definition: def.h:156
#define ABS(x)
Definition: def.h:216
#define EPSEQ(x, y, eps)
Definition: def.h:183
#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 EPSFLOOR(x, eps)
Definition: def.h:191
#define REALABS(x)
Definition: def.h:182
#define EPSGT(x, y, eps)
Definition: def.h:186
#define SCIP_LONGINT_MAX
Definition: def.h:142
#define EPSZ(x, eps)
Definition: def.h:188
#define SCIP_CALL(x)
Definition: def.h:355
#define SCIP_CALL_FINALLY(x, y)
Definition: def.h:397
#define nnodes
Definition: gastrans.c:74
#define narcs
Definition: gastrans.c:77
void SCIPcomputeArraysIntersectionPtr(void **array1, int narray1, void **array2, int narray2, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void **intersectarray, int *nintersectarray)
Definition: misc.c:10583
void SCIPcomputeArraysSetminusInt(int *array1, int narray1, int *array2, int narray2, int *setminusarray, int *nsetminusarray)
Definition: misc.c:10639
void SCIPcomputeArraysIntersectionInt(int *array1, int narray1, int *array2, int narray2, int *intersectarray, int *nintersectarray)
Definition: misc.c:10530
void SCIPbtnodeSetRightchild(SCIP_BTNODE *node, SCIP_BTNODE *right)
Definition: misc.c:9023
SCIP_BTNODE * SCIPbtnodeGetRightchild(SCIP_BTNODE *node)
Definition: misc.c:8892
SCIP_Bool SCIPbtIsEmpty(SCIP_BT *tree)
Definition: misc.c:9135
SCIP_RETCODE SCIPbtCreate(SCIP_BT **tree, BMS_BLKMEM *blkmem)
Definition: misc.c:9034
void SCIPbtnodeFree(SCIP_BT *tree, SCIP_BTNODE **node)
Definition: misc.c:8817
SCIP_Bool SCIPbtnodeIsLeaf(SCIP_BTNODE *node)
Definition: misc.c:8932
void SCIPbtnodeSetData(SCIP_BTNODE *node, void *dataptr)
Definition: misc.c:8981
void * SCIPbtnodeGetData(SCIP_BTNODE *node)
Definition: misc.c:8862
SCIP_RETCODE SCIPbtnodeCreate(SCIP_BT *tree, SCIP_BTNODE **node, void *dataptr)
Definition: misc.c:8753
SCIP_Bool SCIPbtnodeIsRightchild(SCIP_BTNODE *node)
Definition: misc.c:8960
void SCIPbtnodeSetParent(SCIP_BTNODE *node, SCIP_BTNODE *parent)
Definition: misc.c:8995
SCIP_BTNODE * SCIPbtnodeGetSibling(SCIP_BTNODE *node)
Definition: misc.c:8902
SCIP_Bool SCIPbtnodeIsLeftchild(SCIP_BTNODE *node)
Definition: misc.c:8942
void SCIPbtnodeSetLeftchild(SCIP_BTNODE *node, SCIP_BTNODE *left)
Definition: misc.c:9009
SCIP_BTNODE * SCIPbtnodeGetParent(SCIP_BTNODE *node)
Definition: misc.c:8872
void SCIPbtFree(SCIP_BT **tree)
Definition: misc.c:9053
SCIP_BTNODE * SCIPbtnodeGetLeftchild(SCIP_BTNODE *node)
Definition: misc.c:8882
void SCIPbtSetRoot(SCIP_BT *tree, SCIP_BTNODE *root)
Definition: misc.c:9158
SCIP_Bool SCIPbtnodeIsRoot(SCIP_BTNODE *node)
Definition: misc.c:8922
SCIP_BTNODE * SCIPbtGetRoot(SCIP_BT *tree)
Definition: misc.c:9145
void SCIPbtPrintGml(SCIP_BT *tree, FILE *file)
Definition: misc.c:9105
void SCIPdigraphPrintComponents(SCIP_DIGRAPH *digraph, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: misc.c:8700
void ** SCIPdigraphGetSuccessorsData(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7914
void SCIPdigraphFreeComponents(SCIP_DIGRAPH *digraph)
Definition: misc.c:8594
int SCIPdigraphGetNSuccessors(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7881
SCIP_RETCODE SCIPdigraphComputeUndirectedComponents(SCIP_DIGRAPH *digraph, int minsize, int *components, int *ncomponents)
Definition: misc.c:8165
int SCIPdigraphGetNNodes(SCIP_DIGRAPH *digraph)
Definition: misc.c:7823
void SCIPdigraphPrintGml(SCIP_DIGRAPH *digraph, FILE *file)
Definition: misc.c:8661
void SCIPdigraphGetComponent(SCIP_DIGRAPH *digraph, int compidx, int **nodes, int *nnodes)
Definition: misc.c:8374
SCIP_RETCODE SCIPdigraphAddArc(SCIP_DIGRAPH *digraph, int startnode, int endnode, void *data)
Definition: misc.c:7739
SCIP_RETCODE SCIPdigraphTopoSortComponents(SCIP_DIGRAPH *digraph)
Definition: misc.c:8295
SCIP_RETCODE SCIPdigraphSetSizes(SCIP_DIGRAPH *digraph, int *sizes)
Definition: misc.c:7621
SCIP_RETCODE SCIPdigraphComputeDirectedComponents(SCIP_DIGRAPH *digraph, int compidx, int *strongcomponents, int *strongcompstartidx, int *nstrongcomponents)
Definition: misc.c:8506
SCIP_RETCODE SCIPdigraphAddArcSafe(SCIP_DIGRAPH *digraph, int startnode, int endnode, void *data)
Definition: misc.c:7770
void SCIPdigraphFree(SCIP_DIGRAPH **digraph)
Definition: misc.c:7645
int SCIPdigraphGetNArcs(SCIP_DIGRAPH *digraph)
Definition: misc.c:7863
void SCIPdigraphPrint(SCIP_DIGRAPH *digraph, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: misc.c:8626
void * SCIPdigraphGetNodeData(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7833
void SCIPdigraphSetNodeData(SCIP_DIGRAPH *digraph, void *dataptr, int node)
Definition: misc.c:7849
SCIP_RETCODE SCIPdigraphSetNSuccessors(SCIP_DIGRAPH *digraph, int node, int nsuccessors)
Definition: misc.c:7807
int * SCIPdigraphGetSuccessors(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7896
int SCIPdigraphGetNComponents(SCIP_DIGRAPH *digraph)
Definition: misc.c:8361
SCIP_RETCODE SCIPdigraphResize(SCIP_DIGRAPH *digraph, int nnodes)
Definition: misc.c:7491
SCIP_RETCODE SCIPdigraphGetArticulationPoints(SCIP_DIGRAPH *digraph, int **articulations, int *narticulations)
Definition: misc.c:8077
int SCIPdisjointsetGetSize(SCIP_DISJOINTSET *djset)
Definition: misc.c:11354
void SCIPdisjointsetClear(SCIP_DISJOINTSET *djset)
Definition: misc.c:11230
int SCIPdisjointsetGetComponentCount(SCIP_DISJOINTSET *djset)
Definition: misc.c:11344
int SCIPdisjointsetFind(SCIP_DISJOINTSET *djset, int element)
Definition: misc.c:11247
void SCIPdisjointsetUnion(SCIP_DISJOINTSET *djset, int p, int q, SCIP_Bool forcerepofp)
Definition: misc.c:11274
SCIP_Bool SCIPfileExists(const char *filename)
Definition: misc.c:11057
void SCIPsplitFilename(char *filename, char **path, char **name, char **extension, char **compression)
Definition: misc.c:11073
void SCIPdotWriteOpening(FILE *file)
Definition: misc.c:715
void SCIPdotWriteClosing(FILE *file)
Definition: misc.c:753
void SCIPdotWriteArc(FILE *file, int source, int target, const char *color)
Definition: misc.c:740
void SCIPgmlWriteNodeWeight(FILE *file, unsigned int id, const char *label, const char *nodetype, const char *fillcolor, const char *bordercolor, SCIP_Real weight)
Definition: misc.c:549
void SCIPgmlWriteNode(FILE *file, unsigned int id, const char *label, const char *nodetype, const char *fillcolor, const char *bordercolor)
Definition: misc.c:501
void SCIPgmlWriteClosing(FILE *file)
Definition: misc.c:703
void SCIPdotWriteNode(FILE *file, int node, const char *label, const char *nodetype, const char *fillcolor, const char *bordercolor)
Definition: misc.c:725
void SCIPgmlWriteOpening(FILE *file, SCIP_Bool directed)
Definition: misc.c:687
void SCIPgmlWriteEdge(FILE *file, unsigned int source, unsigned int target, const char *label, const char *color)
Definition: misc.c:599
void SCIPgmlWriteArc(FILE *file, unsigned int source, unsigned int target, const char *label, const char *color)
Definition: misc.c:643
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3095
void * SCIPhashmapEntryGetImage(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3613
SCIP_Real SCIPhashmapGetImageReal(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3344
SCIP_RETCODE SCIPhashmapInsertReal(SCIP_HASHMAP *hashmap, void *origin, SCIP_Real image)
Definition: misc.c:3251
void SCIPhashmapPrintStatistics(SCIP_HASHMAP *hashmap, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:3528
int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3304
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3284
SCIP_RETCODE SCIPhashmapSetImageReal(SCIP_HASHMAP *hashmap, void *origin, SCIP_Real image)
Definition: misc.c:3434
void SCIPhashmapEntrySetImageInt(SCIP_HASHMAPENTRY *entry, int image)
Definition: misc.c:3654
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:3143
SCIP_RETCODE SCIPhashmapSetImage(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:3366
int SCIPhashmapGetNElements(SCIP_HASHMAP *hashmap)
Definition: misc.c:3576
int SCIPhashmapEntryGetImageInt(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3623
void SCIPhashmapEntrySetImageReal(SCIP_HASHMAPENTRY *entry, SCIP_Real image)
Definition: misc.c:3665
int SCIPhashmapGetNEntries(SCIP_HASHMAP *hashmap)
Definition: misc.c:3584
SCIP_HASHMAPENTRY * SCIPhashmapGetEntry(SCIP_HASHMAP *hashmap, int entryidx)
Definition: misc.c:3592
void SCIPhashmapEntrySetImage(SCIP_HASHMAPENTRY *entry, void *image)
Definition: misc.c:3643
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3061
void * SCIPhashmapEntryGetOrigin(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3603
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3466
SCIP_RETCODE SCIPhashmapInsertInt(SCIP_HASHMAP *hashmap, void *origin, int image)
Definition: misc.c:3179
SCIP_Bool SCIPhashmapIsEmpty(SCIP_HASHMAP *hashmap)
Definition: misc.c:3566
SCIP_RETCODE SCIPhashmapInsertLong(SCIP_HASHMAP *hashmap, void *origin, SCIP_Longint image)
Definition: misc.c:3215
SCIP_RETCODE SCIPhashmapRemoveAll(SCIP_HASHMAP *hashmap)
Definition: misc.c:3676
SCIP_Real SCIPhashmapEntryGetImageReal(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3633
SCIP_RETCODE SCIPhashmapRemove(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3482
SCIP_Longint SCIPhashmapGetImageLong(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3324
SCIP_RETCODE SCIPhashmapSetImageInt(SCIP_HASHMAP *hashmap, void *origin, int image)
Definition: misc.c:3400
void SCIPhashsetFree(SCIP_HASHSET **hashset, BMS_BLKMEM *blkmem)
Definition: misc.c:3833
void SCIPhashsetPrintStatistics(SCIP_HASHSET *hashset, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:3976
SCIP_Bool SCIPhashsetExists(SCIP_HASHSET *hashset, void *element)
Definition: misc.c:3860
void ** SCIPhashsetGetSlots(SCIP_HASHSET *hashset)
Definition: misc.c:4051
int SCIPhashsetGetNElements(SCIP_HASHSET *hashset)
Definition: misc.c:4035
int SCIPhashsetGetNSlots(SCIP_HASHSET *hashset)
Definition: misc.c:4043
void SCIPhashsetRemoveAll(SCIP_HASHSET *hashset)
Definition: misc.c:4059
SCIP_Bool SCIPhashsetIsEmpty(SCIP_HASHSET *hashset)
Definition: misc.c:4027
SCIP_RETCODE SCIPhashsetInsert(SCIP_HASHSET *hashset, BMS_BLKMEM *blkmem, void *element)
Definition: misc.c:3843
SCIP_RETCODE SCIPhashsetCreate(SCIP_HASHSET **hashset, BMS_BLKMEM *blkmem, int size)
Definition: misc.c:3802
SCIP_RETCODE SCIPhashsetRemove(SCIP_HASHSET *hashset, void *element)
Definition: misc.c:3901
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2348
SCIP_Bool SCIPhashtableExists(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2647
#define SCIPhashTwo(a, b)
Definition: pub_misc.h:568
int SCIPhashtableGetNEntries(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2765
SCIP_RETCODE SCIPhashtableSafeInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2567
void * SCIPhashtableGetEntry(SCIP_HASHTABLE *hashtable, int entryidx)
Definition: misc.c:2773
SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition: misc.c:2298
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition: misc.c:2596
void SCIPhashtableRemoveAll(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2743
SCIP_Real SCIPhashtableGetLoad(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2782
void SCIPhashtablePrintStatistics(SCIP_HASHTABLE *hashtable, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:2792
SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2665
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2535
SCIP_Longint SCIPhashtableGetNElements(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2755
SCIP_Longint SCIPmultihashGetNElements(SCIP_MULTIHASH *multihash)
Definition: misc.c:2233
void SCIPmultihashFree(SCIP_MULTIHASH **multihash)
Definition: misc.c:1995
SCIP_RETCODE SCIPmultihashInsert(SCIP_MULTIHASH *multihash, void *element)
Definition: misc.c:2026
SCIP_RETCODE SCIPmultihashRemove(SCIP_MULTIHASH *multihash, void *element)
Definition: misc.c:2178
void SCIPmultihashRemoveAll(SCIP_MULTIHASH *multihash)
Definition: misc.c:2212
SCIP_RETCODE SCIPmultihashSafeInsert(SCIP_MULTIHASH *multihash, void *element)
Definition: misc.c:2067
SCIP_DECL_HASHKEYEQ(SCIPhashKeyEqString)
Definition: misc.c:2830
int SCIPcalcMultihashSize(int minsize)
Definition: misc.c:1639
SCIP_Real SCIPmultihashGetLoad(SCIP_MULTIHASH *multihash)
Definition: misc.c:2243
SCIP_RETCODE SCIPmultihashCreate(SCIP_MULTIHASH **multihash, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition: misc.c:1962
SCIP_DECL_HASHKEYVAL(SCIPhashKeyValString)
Definition: misc.c:2839
void * SCIPmultihashRetrieve(SCIP_MULTIHASH *multihash, void *key)
Definition: misc.c:2086
void * SCIPmultihashRetrieveNext(SCIP_MULTIHASH *multihash, SCIP_MULTIHASHLIST **multihashlist, void *key)
Definition: misc.c:2115
SCIP_Bool SCIPmultihashExists(SCIP_MULTIHASH *multihash, void *element)
Definition: misc.c:2151
void SCIPmultihashPrintStatistics(SCIP_MULTIHASH *multihash, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:2253
SCIP_DECL_HASHGETKEY(SCIPhashGetKeyStandard)
Definition: misc.c:2858
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9197
SCIP_Longint SCIPcalcBinomCoef(int n, int m)
Definition: misc.c:10387
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9449
SCIP_Real SCIPselectSimpleValue(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom)
Definition: misc.c:10041
SCIP_Real SCIPcomputeGap(SCIP_Real eps, SCIP_Real inf, SCIP_Real primalbound, SCIP_Real dualbound)
Definition: misc.c:11180
SCIP_Bool SCIPfindSimpleRational(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom, SCIP_Longint *numerator, SCIP_Longint *denominator)
Definition: misc.c:9994
SCIP_Real SCIPcalcRootNewton(SCIP_DECL_NEWTONEVAL((*function)), SCIP_DECL_NEWTONEVAL((*derivative)), SCIP_Real *params, int nparams, SCIP_Real x, SCIP_Real eps, int k)
Definition: misc.c:10082
SCIP_Real SCIPnextafter(SCIP_Real from, SCIP_Real to)
Definition: misc.c:9440
SCIP_RETCODE SCIPcalcIntegralScalarExact(BMS_BUFMEM *buffer, SCIP_RATIONAL **vals, int nvals, SCIP_Real maxscale, SCIP_RATIONAL *intscalar, SCIP_Bool *success)
Definition: misc.c:9842
SCIP_Bool SCIPrealIsExactlyIntegral(SCIP_Real val)
Definition: misc.c:9604
SCIP_Real SCIPcalcMachineEpsilon(void)
Definition: misc.c:9174
unsigned int SCIPcalcFibHash(SCIP_Real v)
Definition: misc.c:10462
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *numerator, SCIP_Longint *denominator)
Definition: misc.c:9470
SCIP_RETCODE SCIPcalcIntegralScalar(SCIP_Real *vals, int nvals, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Real maxscale, SCIP_Real *intscalar, SCIP_Bool *success)
Definition: misc.c:9641
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:11162
void SCIPswapInts(int *value1, int *value2)
Definition: misc.c:10485
void SCIPrandomPermuteIntArray(SCIP_RANDNUMGEN *randnumgen, int *array, int begin, int end)
Definition: misc.c:10264
void SCIPswapPointers(void **pointer1, void **pointer2)
Definition: misc.c:10511
void SCIPswapReals(SCIP_Real *value1, SCIP_Real *value2)
Definition: misc.c:10498
void SCIPrandomPermuteArray(SCIP_RANDNUMGEN *randnumgen, void **array, int begin, int end)
Definition: misc.c:10294
void ** SCIPpqueueElems(SCIP_PQUEUE *pqueue)
Definition: misc.c:1540
void SCIPpqueueDelPos(SCIP_PQUEUE *pqueue, int pos)
Definition: misc.c:1435
void SCIPpqueueClear(SCIP_PQUEUE *pqueue)
Definition: misc.c:1335
int SCIPpqueueFind(SCIP_PQUEUE *pqueue, void *elem)
Definition: misc.c:1551
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 * SCIPpqueueRemove(SCIP_PQUEUE *pqueue)
Definition: misc.c:1495
void * SCIPpqueueFirst(SCIP_PQUEUE *pqueue)
Definition: misc.c:1515
void SCIPintervalSetRoundingModeDownwards(void)
SCIP_ROUNDMODE SCIPintervalGetRoundingMode(void)
void SCIPintervalSetRoundingMode(SCIP_ROUNDMODE roundmode)
int SCIP_ROUNDMODE
Definition: intervalarith.h:65
SCIP_Bool SCIPintervalHasRoundingControl(void)
void SCIPrationalMult(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:1066
void SCIPrationalFreeBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
Definition: rational.cpp:473
SCIP_Longint SCIPrationalDenominator(SCIP_RATIONAL *rational)
Definition: rational.cpp:2027
SCIP_RETCODE SCIPrationalCreateBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
Definition: rational.cpp:123
SCIP_Bool SCIPrationalIsZero(SCIP_RATIONAL *rational)
Definition: rational.cpp:1624
void SCIPrationalCanonicalize(SCIP_RATIONAL *rational)
Definition: rational.cpp:538
void SCIPrationalSetFraction(SCIP_RATIONAL *res, SCIP_Longint nom, SCIP_Longint denom)
Definition: rational.cpp:582
SCIP_Longint SCIPrationalNumerator(SCIP_RATIONAL *rational)
Definition: rational.cpp:2018
int SCIPqueueNElems(SCIP_QUEUE *queue)
Definition: misc.c:1249
unsigned int SCIPqueueRemoveUInt(SCIP_QUEUE *queue)
Definition: misc.c:1166
void SCIPqueueFree(SCIP_QUEUE **queue)
Definition: misc.c:1019
SCIP_RETCODE SCIPqueueInsertUInt(SCIP_QUEUE *queue, unsigned int elem)
Definition: misc.c:1107
SCIP_RETCODE SCIPqueueCreate(SCIP_QUEUE **queue, int initsize, SCIP_Real sizefac)
Definition: misc.c:995
void SCIPqueueClear(SCIP_QUEUE *queue)
Definition: misc.c:1030
SCIP_RETCODE SCIPqueueInsert(SCIP_QUEUE *queue, void *elem)
Definition: misc.c:1081
SCIP_Bool SCIPqueueIsEmpty(SCIP_QUEUE *queue)
Definition: misc.c:1236
void * SCIPqueueRemove(SCIP_QUEUE *queue)
Definition: misc.c:1132
void * SCIPqueueFirst(SCIP_QUEUE *queue)
Definition: misc.c:1200
unsigned int SCIPqueueFirstUInt(SCIP_QUEUE *queue)
Definition: misc.c:1218
SCIP_Real SCIPrandomGetReal(SCIP_RANDNUMGEN *randnumgen, SCIP_Real minrandval, SCIP_Real maxrandval)
Definition: misc.c:10245
SCIP_RETCODE SCIPrandomGetSubset(SCIP_RANDNUMGEN *randnumgen, void **set, int nelems, void **subset, int nsubelems)
Definition: misc.c:10326
int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
Definition: misc.c:10223
void SCIPregressionRemoveObservation(SCIP_REGRESSION *regression, SCIP_Real x, SCIP_Real y)
Definition: misc.c:353
void SCIPregressionAddObservation(SCIP_REGRESSION *regression, SCIP_Real x, SCIP_Real y)
Definition: misc.c:385
SCIP_Real SCIPregressionGetIntercept(SCIP_REGRESSION *regression)
Definition: misc.c:278
int SCIPregressionGetNObservations(SCIP_REGRESSION *regression)
Definition: misc.c:258
void SCIPregressionFree(SCIP_REGRESSION **regression)
Definition: misc.c:436
SCIP_RETCODE SCIPregressionCreate(SCIP_REGRESSION **regression)
Definition: misc.c:420
void SCIPregressionReset(SCIP_REGRESSION *regression)
Definition: misc.c:404
SCIP_Real SCIPregressionGetSlope(SCIP_REGRESSION *regression)
Definition: misc.c:268
SCIP_RETCODE SCIPactivityCreate(SCIP_RESOURCEACTIVITY **activity, SCIP_VAR *var, int duration, int demand)
Definition: misc.c:6718
int SCIPactivityGetDuration(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6773
int SCIPactivityGetEnergy(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6793
SCIP_VAR * SCIPactivityGetVar(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6763
int SCIPactivityGetDemand(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6783
void SCIPactivityFree(SCIP_RESOURCEACTIVITY **activity)
Definition: misc.c:6737
SCIP_RETCODE SCIPprofileInsertCore(SCIP_PROFILE *profile, int left, int right, int demand, int *pos, SCIP_Bool *infeasible)
Definition: misc.c:7097
int * SCIPprofileGetTimepoints(SCIP_PROFILE *profile)
Definition: misc.c:6904
int SCIPprofileGetLatestFeasibleStart(SCIP_PROFILE *profile, int est, int lst, int duration, int demand, SCIP_Bool *infeasible)
Definition: misc.c:7366
SCIP_Bool SCIPprofileFindLeft(SCIP_PROFILE *profile, int timepoint, int *pos)
Definition: misc.c:6950
int SCIPprofileGetEarliestFeasibleStart(SCIP_PROFILE *profile, int est, int lst, int duration, int demand, SCIP_Bool *infeasible)
Definition: misc.c:7217
int SCIPprofileGetNTimepoints(SCIP_PROFILE *profile)
Definition: misc.c:6894
void SCIPprofileFree(SCIP_PROFILE **profile)
Definition: misc.c:6846
int SCIPprofileGetLoad(SCIP_PROFILE *profile, int pos)
Definition: misc.c:6936
int * SCIPprofileGetLoads(SCIP_PROFILE *profile)
Definition: misc.c:6914
SCIP_RETCODE SCIPprofileCreate(SCIP_PROFILE **profile, int capacity)
Definition: misc.c:6832
int SCIPprofileGetTime(SCIP_PROFILE *profile, int pos)
Definition: misc.c:6924
int SCIPprofileGetCapacity(SCIP_PROFILE *profile)
Definition: misc.c:6884
SCIP_RETCODE SCIPprofileDeleteCore(SCIP_PROFILE *profile, int left, int right, int demand)
Definition: misc.c:7127
void SCIPprofilePrint(SCIP_PROFILE *profile, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: misc.c:6862
SCIP_Real SCIPnormalCDF(SCIP_Real mean, SCIP_Real variance, SCIP_Real value)
Definition: misc.c:200
SCIP_Real SCIPcomputeTwoSampleTTestValue(SCIP_Real meanx, SCIP_Real meany, SCIP_Real variancex, SCIP_Real variancey, SCIP_Real countx, SCIP_Real county)
Definition: misc.c:127
SCIP_Real SCIPnormalGetCriticalValue(SCIP_CONFIDENCELEVEL clevel)
Definition: misc.c:187
SCIP_Real SCIPstudentTGetCriticalValue(SCIP_CONFIDENCELEVEL clevel, int df)
Definition: misc.c:110
SCIP_Real SCIPerf(SCIP_Real x)
Definition: misc.c:160
void SCIPsortInd(int *indarray, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
void SCIPsortDown(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
Definition: misc.c:6144
SCIP_Bool SCIPsortedvecFindInt(int *intarray, int val, int len, int *pos)
void SCIPsort(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
Definition: misc.c:5581
SCIP_DECL_SORTPTRCOMP(SCIPsortCompInt)
Definition: misc.c:5523
void SCIPsortedvecInsertIntInt(int *intarray1, int *intarray2, int keyval, int field1val, int *len, int *pos)
void SCIPsortDownInd(int *indarray, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
SCIP_DECL_SORTINDCOMP(SCIPsortArgsortInt)
Definition: misc.c:5544
int SCIPsparseSolGetNVars(SCIP_SPARSESOL *sparsesol)
Definition: misc.c:841
SCIP_Longint * SCIPsparseSolGetLbs(SCIP_SPARSESOL *sparsesol)
Definition: misc.c:851
void SCIPsparseSolGetFirstSol(SCIP_SPARSESOL *sparsesol, SCIP_Longint *sol, int nvars)
Definition: misc.c:871
SCIP_RETCODE SCIPsparseSolCreate(SCIP_SPARSESOL **sparsesol, SCIP_VAR **vars, int nvars, SCIP_Bool cleared)
Definition: misc.c:767
SCIP_Longint * SCIPsparseSolGetUbs(SCIP_SPARSESOL *sparsesol)
Definition: misc.c:861
void SCIPsparseSolFree(SCIP_SPARSESOL **sparsesol)
Definition: misc.c:817
SCIP_Bool SCIPsparseSolGetNextSol(SCIP_SPARSESOL *sparsesol, SCIP_Longint *sol, int nvars)
Definition: misc.c:894
SCIP_VAR ** SCIPsparseSolGetVars(SCIP_SPARSESOL *sparsesol)
Definition: misc.c:831
SCIP_Bool SCIPstrToIntValue(const char *str, int *value, char **endptr)
Definition: misc.c:10924
int SCIPstrcasecmp(const char *s1, const char *s2)
Definition: misc.c:10863
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
void SCIPescapeString(char *t, int bufsize, const char *s)
Definition: misc.c:10782
void SCIPstrCopySection(const char *str, char startchar, char endchar, char *token, int size, char **endptr)
Definition: misc.c:10985
void SCIPprintSysError(const char *message)
Definition: misc.c:10719
SCIP_Bool SCIPstrAtStart(const char *s, const char *t, size_t tlen)
Definition: misc.c:11364
SCIP_RETCODE SCIPskipSpace(char **s)
Definition: misc.c:10816
int SCIPstrncpy(char *t, const char *s, int size)
Definition: misc.c:10897
int SCIPstrncasecmp(const char *s1, const char *s2, int length)
Definition: misc.c:10876
char * SCIPstrtok(char *s, const char *delim, char **ptrptr)
Definition: misc.c:10768
int SCIPmemccpy(char *dest, const char *src, char stop, unsigned int cnt)
Definition: misc.c:10694
static SCIP_RETCODE optimize(SCIP *scip, SCIP_SOL *worksol, SCIP_VAR **vars, int *blockstart, int *blockend, int nblocks, OPTTYPE opttype, SCIP_Real *activities, int nrows, SCIP_Bool *improvement, SCIP_Bool *varboundserr, SCIP_HEURDATA *heurdata)
Definition: heur_twoopt.c:967
interval arithmetics for provable bounds
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:462
#define BMSfreeMemory(ptr)
Definition: memory.h:145
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:465
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:451
#define BMSreallocMemoryArray(ptr, num)
Definition: memory.h:127
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:468
#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 BMSallocBlockMemoryArray(mem, ptr, num)
Definition: memory.h:454
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:134
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:467
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:458
#define BMSmoveMemoryArray(ptr, source, num)
Definition: memory.h:138
#define BMSallocClearBlockMemoryArray(mem, ptr, num)
Definition: memory.h:455
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
#define BMSallocClearMemoryArray(ptr, num)
Definition: memory.h:125
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:437
#define BMSfreeMemoryArrayNull(ptr)
Definition: memory.h:148
#define BMSallocMemory(ptr)
Definition: memory.h:118
void SCIPmessagePrintError(const char *formatstr,...)
Definition: message.c:791
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:618
void SCIPmessagePrintInfo(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:594
SCIP_RETCODE SCIPrealarrayExtend(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
Definition: misc.c:4131
#define GMLNODEHEIGTH
Definition: misc.c:492
#define ELEM_DISTANCE(pos)
Definition: misc.c:3697
SCIP_Bool SCIPboolarrayGetVal(SCIP_BOOLARRAY *boolarray, int idx)
Definition: misc.c:5056
static void incrementalStatsUpdate(SCIP_Real value, SCIP_Real *meanptr, SCIP_Real *sumvarptr, int nobservations, SCIP_Bool add)
Definition: misc.c:327
static SCIP_RETCODE doProfileCreate(SCIP_PROFILE **profile, int capacity)
Definition: misc.c:6810
static int primetable[]
Definition: misc.c:1575
SCIP_RETCODE SCIPboolarrayFree(SCIP_BOOLARRAY **boolarray)
Definition: misc.c:4854
SCIP_RETCODE SCIPboolarrayCopy(SCIP_BOOLARRAY **boolarray, BMS_BLKMEM *blkmem, SCIP_BOOLARRAY *sourceboolarray)
Definition: misc.c:4830
static void pqueueElemChgPos(SCIP_PQUEUE *pqueue, void *elem, int oldpos, int newpos)
Definition: misc.c:1346
#define GMLNODEBORDERCOLOR
Definition: misc.c:497
static void multihashlistFree(SCIP_MULTIHASHLIST **multihashlist, BMS_BLKMEM *blkmem)
Definition: misc.c:1675
static SCIP_RETCODE multihashlistAppend(SCIP_MULTIHASHLIST **multihashlist, BMS_BLKMEM *blkmem, void *element)
Definition: misc.c:1653
static SCIP_RETCODE hashtableCheckLoad(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2482
int SCIPptrarrayGetMaxIdx(SCIP_PTRARRAY *ptrarray)
Definition: misc.c:5508
#define DEFAULT_SEED
Definition: misc.c:10132
SCIP_RETCODE SCIPrealarraySetVal(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, SCIP_Real val)
Definition: misc.c:4338
SCIP_RETCODE SCIPintarraySetVal(SCIP_INTARRAY *intarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, int val)
Definition: misc.c:4709
static SCIP_Bool multihashlistRemove(SCIP_MULTIHASHLIST **multihashlist, BMS_BLKMEM *blkmem, void *element)
Definition: misc.c:1813
static const int primetablesize
Definition: misc.c:1627
#define SCIP_MULTIHASH_MAXSIZE
Definition: misc.c:1840
SCIP_RETCODE SCIPintarrayFree(SCIP_INTARRAY **intarray)
Definition: misc.c:4488
#define DEFAULT_MWC
Definition: misc.c:10134
#define PQ_RIGHTCHILD(p)
Definition: misc.c:1275
static SCIP_RETCODE queueResize(SCIP_QUEUE *queue, int minsize)
Definition: misc.c:976
static SCIP_RETCODE queueCheckSize(SCIP_QUEUE *queue)
Definition: misc.c:1042
static int profileFindFeasibleStart(SCIP_PROFILE *profile, int pos, int lst, int duration, int demand, SCIP_Bool *infeasible)
Definition: misc.c:7159
static void tarjan(SCIP_DIGRAPH *digraph, int v, int *lowlink, int *dfsidx, int *stack, int *stacksize, SCIP_Bool *unprocessed, SCIP_Bool *nodeinstack, int *maxdfs, int *strongcomponents, int *nstrongcomponents, int *strongcompstartidx, int *nstorednodes)
Definition: misc.c:8397
#define DEFAULT_XOR
Definition: misc.c:10133
void SCIPdisjointsetFree(SCIP_DISJOINTSET **djset, BMS_BLKMEM *blkmem)
Definition: misc.c:11325
static void btnodeFreeLeaf(SCIP_BT *tree, SCIP_BTNODE **node)
Definition: misc.c:8776
static void depthFirstSearch(SCIP_DIGRAPH *digraph, int startnode, SCIP_Bool *visited, int *dfsstack, int *stackadjvisited, int *dfsnodes, int *ndfsnodes)
Definition: misc.c:7931
int SCIPptrarrayGetMinIdx(SCIP_PTRARRAY *ptrarray)
Definition: misc.c:5498
static SCIP_RETCODE profileUpdate(SCIP_PROFILE *profile, int left, int right, int demand, int *pos, SCIP_Bool *infeasible)
Definition: misc.c:7037
static SCIP_RETCODE ensureSuccessorsSize(SCIP_DIGRAPH *digraph, int idx, int newsize)
Definition: misc.c:7692
static SCIP_RETCODE profileInsertTimepoint(SCIP_PROFILE *profile, int timepoint, int *pos)
Definition: misc.c:6996
SCIP_RETCODE SCIPptrarrayExtend(SCIP_PTRARRAY *ptrarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
Definition: misc.c:5223
SCIP_RETCODE SCIPboolarrayExtend(SCIP_BOOLARRAY *boolarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
Definition: misc.c:4868
SCIP_RETCODE SCIPptrarrayCopy(SCIP_PTRARRAY **ptrarray, BMS_BLKMEM *blkmem, SCIP_PTRARRAY *sourceptrarray)
Definition: misc.c:5186
static void * multihashlistRetrieve(SCIP_MULTIHASHLIST *multihashlist, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr, uint64_t keyval, void *key)
Definition: misc.c:1730
static SCIP_RETCODE hashtableInsert(SCIP_HASHTABLE *hashtable, void *element, void *key, uint32_t hashval, SCIP_Bool override)
Definition: misc.c:2398
static void btPrintSubtree(SCIP_BTNODE *node, FILE *file, int *nnodes)
Definition: misc.c:9069
int SCIPboolarrayGetMaxIdx(SCIP_BOOLARRAY *boolarray)
Definition: misc.c:5155
static const SCIP_Real studentt_quartilesabove[]
Definition: misc.c:102
void SCIPrandomFree(SCIP_RANDNUMGEN **randnumgen, BMS_BLKMEM *blkmem)
Definition: misc.c:10209
SCIP_RETCODE SCIPdisjointsetCreate(SCIP_DISJOINTSET **djset, BMS_BLKMEM *blkmem, int ncomponents)
Definition: misc.c:11207
SCIP_RETCODE SCIPrandomCreate(SCIP_RANDNUMGEN **randnumgen, BMS_BLKMEM *blkmem, unsigned int initialseed)
Definition: misc.c:10193
SCIP_RETCODE SCIPintarrayCopy(SCIP_INTARRAY **intarray, BMS_BLKMEM *blkmem, SCIP_INTARRAY *sourceintarray)
Definition: misc.c:4465
SCIP_RETCODE SCIPptrarrayClear(SCIP_PTRARRAY *ptrarray)
Definition: misc.c:5378
static SCIP_RETCODE hashmapInsert(SCIP_HASHMAP *hashmap, void *origin, SCIP_HASHMAPIMAGE image, uint32_t hashval, SCIP_Bool override)
Definition: misc.c:2890
int SCIPrealarrayGetMaxIdx(SCIP_REALARRAY *realarray)
Definition: misc.c:4435
SCIP_RETCODE SCIPdigraphCreate(SCIP_DIGRAPH **digraph, BMS_BLKMEM *blkmem, int nnodes)
Definition: misc.c:7454
static uint32_t hashSetDesiredPos(SCIP_HASHSET *hashset, void *element)
Definition: misc.c:3701
int SCIPintarrayGetMaxIdx(SCIP_INTARRAY *intarray)
Definition: misc.c:4799
SCIP_RETCODE SCIPintarrayCreate(SCIP_INTARRAY **intarray, BMS_BLKMEM *blkmem)
Definition: misc.c:4445
static SCIP_RETCODE hashsetCheckLoad(SCIP_HASHSET *hashset, BMS_BLKMEM *blkmem)
Definition: misc.c:3761
static void regressionRecompute(SCIP_REGRESSION *regression)
Definition: misc.c:289
#define STARTSUCCESSORSSIZE
Definition: misc.c:7688
SCIP_Real SCIPrealarrayGetVal(SCIP_REALARRAY *realarray, int idx)
Definition: misc.c:4317
SCIP_RETCODE SCIPptrarrayFree(SCIP_PTRARRAY **ptrarray)
Definition: misc.c:5209
SCIP_RETCODE SCIPintarrayClear(SCIP_INTARRAY *intarray)
Definition: misc.c:4657
#define GMLNODEWIDTH
Definition: misc.c:491
#define SCIP_MULTIHASH_RESIZE_PERCENTAGE
Definition: misc.c:1841
SCIP_RETCODE SCIPrealarrayIncVal(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, SCIP_Real incval)
Definition: misc.c:4407
int SCIPrealarrayGetMinIdx(SCIP_REALARRAY *realarray)
Definition: misc.c:4425
SCIP_RETCODE SCIPrealarrayCreate(SCIP_REALARRAY **realarray, BMS_BLKMEM *blkmem)
Definition: misc.c:4073
#define GMLFONTSIZE
Definition: misc.c:493
static const int nscalars
Definition: misc.c:9636
SCIP_RETCODE SCIPrealarrayClear(SCIP_REALARRAY *realarray)
Definition: misc.c:4286
int SCIPboolarrayGetMinIdx(SCIP_BOOLARRAY *boolarray)
Definition: misc.c:5145
static int calcGrowSize(int initsize, SCIP_Real growfac, int num)
Definition: misc.c:445
#define GMLNODETYPE
Definition: misc.c:494
static const SCIP_Real studentt_quartiles[]
Definition: misc.c:81
static const int studentt_maxdf
Definition: misc.c:107
#define PQ_PARENT(q)
Definition: misc.c:1273
static uint32_t randomGetRand(SCIP_RANDNUMGEN *randnumgen)
Definition: misc.c:10170
static uint32_t hashvalue(uint64_t input)
Definition: misc.c:1631
static void findArticulationPointsUtil(SCIP_DIGRAPH *digraph, int startnode, SCIP_Bool *visited, int *tdisc, int *mindisc, int *parent, SCIP_Bool *articulationflag, int time)
Definition: misc.c:8010
static void queueCheckMarker(SCIP_QUEUE *queue)
Definition: misc.c:1067
static int profileFindDownFeasibleStart(SCIP_PROFILE *profile, int pos, int ect, int duration, int demand, SCIP_Bool *infeasible)
Definition: misc.c:7309
int SCIPintarrayGetMinIdx(SCIP_INTARRAY *intarray)
Definition: misc.c:4789
static SCIP_RETCODE pqueueResize(SCIP_PQUEUE *pqueue, int minsize)
Definition: misc.c:1280
SCIP_RETCODE SCIPrealarrayCopy(SCIP_REALARRAY **realarray, BMS_BLKMEM *blkmem, SCIP_REALARRAY *sourcerealarray)
Definition: misc.c:4093
static SCIP_RETCODE hashmapCheckLoad(SCIP_HASHMAP *hashmap)
Definition: misc.c:3010
void * SCIPptrarrayGetVal(SCIP_PTRARRAY *ptrarray, int idx)
Definition: misc.c:5409
void SCIPrandomSetSeed(SCIP_RANDNUMGEN *randnumgen, unsigned int initseed)
Definition: misc.c:10139
#define PQ_LEFTCHILD(p)
Definition: misc.c:1274
SCIP_RETCODE SCIPintarrayExtend(SCIP_INTARRAY *intarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
Definition: misc.c:4502
#define SCIP_MULTIHASH_GROW_FACTOR
Definition: misc.c:1842
static SCIP_RETCODE multihashResize(SCIP_MULTIHASH *multihash)
Definition: misc.c:1846
SCIP_RETCODE SCIPboolarrayCreate(SCIP_BOOLARRAY **boolarray, BMS_BLKMEM *blkmem)
Definition: misc.c:4810
static SCIP_RETCODE ensureProfileSize(SCIP_PROFILE *profile, int neededsize)
Definition: misc.c:6973
static SCIP_Bool isIntegralScalar(SCIP_Real val, SCIP_Real scalar, SCIP_Real mindelta, SCIP_Real maxdelta)
Definition: misc.c:9613
#define GMLEDGECOLOR
Definition: misc.c:496
SCIP_Real SCIPnegateReal(SCIP_Real x)
Definition: misc.c:10473
static SCIP_RETCODE btnodeCreateEmpty(SCIP_BT *tree, SCIP_BTNODE **node)
Definition: misc.c:8737
#define DEFAULT_CST
Definition: misc.c:10135
SCIP_RETCODE SCIPboolarrayClear(SCIP_BOOLARRAY *boolarray)
Definition: misc.c:5025
static void * multihashlistRetrieveNext(SCIP_MULTIHASHLIST **multihashlist, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr, uint64_t keyval, void *key)
Definition: misc.c:1780
SCIP_RETCODE SCIPintarrayIncVal(SCIP_INTARRAY *intarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, int incval)
Definition: misc.c:4777
int SCIPintarrayGetVal(SCIP_INTARRAY *intarray, int idx)
Definition: misc.c:4688
static SCIP_Bool hashmapLookup(SCIP_HASHMAP *hashmap, void *origin, uint32_t *pos)
Definition: misc.c:2965
static const SCIP_Real scalars[]
Definition: misc.c:9635
SCIP_RETCODE SCIPdigraphCopy(SCIP_DIGRAPH **targetdigraph, SCIP_DIGRAPH *sourcedigraph, BMS_BLKMEM *targetblkmem)
Definition: misc.c:7531
#define GMLNODEFILLCOLOR
Definition: misc.c:495
SCIP_RETCODE SCIPptrarrayCreate(SCIP_PTRARRAY **ptrarray, BMS_BLKMEM *blkmem)
Definition: misc.c:5166
SCIP_RETCODE SCIPptrarraySetVal(SCIP_PTRARRAY *ptrarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, void *val)
Definition: misc.c:5430
static const SCIP_Real simplednoms[]
Definition: misc.c:9464
static SCIP_MULTIHASHLIST * multihashlistFind(SCIP_MULTIHASHLIST *multihashlist, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr, uint64_t keyval, void *key)
Definition: misc.c:1699
SCIP_RETCODE SCIPrealarrayFree(SCIP_REALARRAY **realarray)
Definition: misc.c:4117
static void hashsetInsert(SCIP_HASHSET *hashset, void *element)
Definition: misc.c:3710
SCIP_RETCODE SCIPboolarraySetVal(SCIP_BOOLARRAY *boolarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, SCIP_Bool val)
Definition: misc.c:5077
internal miscellaneous methods
#define M_SQRT2
Definition: misc_rowprep.c:59
SCIP_Longint denominator(Rational &r)
SCIP_Longint numerator(Rational &r)
Definition: pqueue.h:38
real eps
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPdebugMessage
Definition: pub_message.h:96
#define SCIPdebugPrintf
Definition: pub_message.h:99
public data structures and miscellaneous methods
wrapper for rational number arithmetic
template functions for sorting
BMS_BLKMEM * blkmem
Definition: struct_misc.h:182
SCIP_Bool * vals
Definition: struct_misc.h:183
SCIP_BTNODE * parent
Definition: struct_misc.h:241
void * dataptr
Definition: struct_misc.h:244
SCIP_BTNODE * left
Definition: struct_misc.h:242
SCIP_BTNODE * right
Definition: struct_misc.h:243
SCIP_BTNODE * root
Definition: struct_misc.h:250
BMS_BLKMEM * blkmem
Definition: struct_misc.h:251
SCIP_Bool articulationscheck
Definition: struct_misc.h:235
int ** successors
Definition: struct_misc.h:223
void ** nodedata
Definition: struct_misc.h:225
int * successorssize
Definition: struct_misc.h:226
void *** arcdata
Definition: struct_misc.h:224
int componentstartsize
Definition: struct_misc.h:232
int * articulations
Definition: struct_misc.h:230
int * componentstarts
Definition: struct_misc.h:229
int narticulations
Definition: struct_misc.h:234
BMS_BLKMEM * blkmem
Definition: struct_misc.h:222
int * components
Definition: struct_misc.h:228
int * nsuccessors
Definition: struct_misc.h:227
SCIP_HASHMAPIMAGE image
Definition: struct_misc.h:134
uint32_t nelements
Definition: struct_misc.h:145
BMS_BLKMEM * blkmem
Definition: struct_misc.h:140
SCIP_HASHMAPTYPE hashmaptype
Definition: struct_misc.h:146
uint32_t mask
Definition: struct_misc.h:144
uint32_t shift
Definition: struct_misc.h:143
SCIP_HASHMAPENTRY * slots
Definition: struct_misc.h:141
uint32_t * hashes
Definition: struct_misc.h:142
uint32_t nelements
Definition: struct_misc.h:154
void ** slots
Definition: struct_misc.h:152
uint32_t shift
Definition: struct_misc.h:153
void * userptr
Definition: struct_misc.h:95
uint32_t nelements
Definition: struct_misc.h:100
uint32_t shift
Definition: struct_misc.h:98
uint32_t mask
Definition: struct_misc.h:99
BMS_BLKMEM * blkmem
Definition: struct_misc.h:94
void ** slots
Definition: struct_misc.h:96
uint32_t * hashes
Definition: struct_misc.h:97
BMS_BLKMEM * blkmem
Definition: struct_misc.h:171
SCIP_MULTIHASHLIST * next
Definition: struct_misc.h:107
SCIP_MULTIHASHLIST ** lists
Definition: struct_misc.h:117
BMS_BLKMEM * blkmem
Definition: struct_misc.h:116
SCIP_Longint nelements
Definition: struct_misc.h:120
void ** slots
Definition: struct_misc.h:83
SCIP_Real sizefac
Definition: struct_misc.h:80
int * timepoints
Definition: struct_misc.h:212
void ** vals
Definition: struct_misc.h:194
BMS_BLKMEM * blkmem
Definition: struct_misc.h:193
SCIP_Real sizefac
Definition: struct_misc.h:62
int firstused
Definition: struct_misc.h:65
SCIP_QUEUEELEMENT * slots
Definition: struct_misc.h:63
int firstfree
Definition: struct_misc.h:64
uint32_t xor_seed
Definition: struct_misc.h:272
uint32_t cst_seed
Definition: struct_misc.h:274
uint32_t mwc_seed
Definition: struct_misc.h:273
SCIP_Real * vals
Definition: struct_misc.h:161
BMS_BLKMEM * blkmem
Definition: struct_misc.h:160
SCIP_Real slope
Definition: struct_misc.h:258
SCIP_Real meany
Definition: struct_misc.h:260
SCIP_Real meanx
Definition: struct_misc.h:259
SCIP_Real variancesumx
Definition: struct_misc.h:262
SCIP_Real corrcoef
Definition: struct_misc.h:264
SCIP_Real sumxy
Definition: struct_misc.h:261
SCIP_Real intercept
Definition: struct_misc.h:257
SCIP_Real variancesumy
Definition: struct_misc.h:263
SCIP_Longint * lbvalues
Definition: struct_misc.h:49
SCIP_VAR ** vars
Definition: struct_misc.h:48
SCIP_Longint * ubvalues
Definition: struct_misc.h:50
miscellaneous datastructures
Definition: heur_padm.c:135
@ SCIP_HASHMAPTYPE_REAL
Definition: type_misc.h:60
@ SCIP_HASHMAPTYPE_POINTER
Definition: type_misc.h:59
@ SCIP_HASHMAPTYPE_UNKNOWN
Definition: type_misc.h:58
@ SCIP_HASHMAPTYPE_INT
Definition: type_misc.h:61
@ SCIP_HASHMAPTYPE_LONG
Definition: type_misc.h:62
#define SCIP_DECL_PQUEUEELEMCHGPOS(x)
Definition: type_misc.h:209
#define SCIP_DECL_NEWTONEVAL(x)
Definition: type_misc.h:206
enum SCIP_Confidencelevel SCIP_CONFIDENCELEVEL
Definition: type_misc.h:53
@ SCIP_INVALIDDATA
Definition: type_retcode.h:52
@ SCIP_KEYALREADYEXISTING
Definition: type_retcode.h:58
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
SCIP_Longint longint
Definition: struct_misc.h:127
unsigned int uinteger
Definition: struct_misc.h:56