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