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