Scippy

SCIP

Solving Constraint Integer Programs

misc.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2024 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file misc.c
26 * @ingroup OTHER_CFILES
27 * @brief miscellaneous methods
28 * @author Tobias Achterberg
29 * @author Gerald Gamrath
30 * @author Stefan Heinz
31 * @author Michael Winkler
32 * @author Kati Wolter
33 * @author Gregor Hendel
34 */
35
36/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
37
38#define _USE_MATH_DEFINES /* to get M_SQRT2 on Windows */ /*lint !750 */
39
40#include <assert.h>
41#include <string.h>
42#include <stdarg.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <errno.h>
46#include <ctype.h>
47#include <math.h>
48
49#include "scip/def.h"
50#include "scip/pub_message.h"
51#include "scip/misc.h"
52#include "scip/intervalarith.h"
53#include "scip/pub_misc.h"
54
55#ifndef NDEBUG
56#include "scip/struct_misc.h"
57#endif
58
59/*
60 * methods for statistical tests
61 */
62
63/**< contains all critical values for a one-sided two sample t-test up to 15 degrees of freedom
64 * a critical value represents a threshold for rejecting the null-hypothesis in hypothesis testing at
65 * a certain confidence level;
66 *
67 * access through method SCIPstudentTGetCriticalValue()
68 *
69 * source: German Wikipedia
70 *
71 * for confidence levels
72 * c =
73 * 0.75 0.875 0.90 0.95 0.975 (one-sided)
74 * 0.50 0.750 0.80 0.90 0.950 (two-sided)
75 *
76 */
77static const SCIP_Real studentt_quartiles[] = { /* df:*/
78 1.000, 2.414, 3.078, 6.314, 12.706, /* 1 */
79 0.816, 1.604, 1.886, 2.920, 4.303, /* 2 */
80 0.765, 1.423, 1.638, 2.353, 3.182, /* 3 */
81 0.741, 1.344, 1.533, 2.132, 2.776, /* 4 */
82 0.727, 1.301, 1.476, 2.015, 2.571, /* 5 */
83 0.718, 1.273, 1.440, 1.943, 2.447, /* 6 */
84 0.711, 1.254, 1.415, 1.895, 2.365, /* 7 */
85 0.706, 1.240, 1.397, 1.860, 2.306, /* 8 */
86 0.703, 1.230, 1.383, 1.833, 2.262, /* 9 */
87 0.700, 1.221, 1.372, 1.812, 2.228, /* 10 */
88 0.697, 1.214, 1.363, 1.796, 2.201, /* 11 */
89 0.695, 1.209, 1.356, 1.782, 2.179, /* 12 */
90 0.694, 1.204, 1.350, 1.771, 2.160, /* 13 */
91 0.692, 1.200, 1.345, 1.761, 2.145, /* 14 */
92 0.691, 1.197, 1.341, 1.753, 2.131 /* 15 */
93};
94
95/**< critical values for higher degrees of freedom of Student-T distribution for the same error probabilities; infact,
96 * these are critical values of the standard normal distribution with mean 0 and variance 1
97 */
99 0.674, 1.150, 1.282, 1.645, 1.960
100};
101
102/** the maximum degrees of freedom represented before switching to normal approximation */
103static const int studentt_maxdf = sizeof(studentt_quartiles)/(5 * sizeof(SCIP_Real));
104
105/** get critical value of a Student-T distribution for a given number of degrees of freedom at a confidence level */
107 SCIP_CONFIDENCELEVEL clevel, /**< (one-sided) confidence level */
108 int df /**< degrees of freedom */
109 )
110{
111 if( df > studentt_maxdf )
112 return studentt_quartilesabove[(int)clevel];
113 else
114 return studentt_quartiles[(int)clevel + 5 * (df - 1)];
115}
116
117/** compute a t-value for the hypothesis that x and y are from the same population; Assuming that
118 * x and y represent normally distributed random samples with equal variance, the returned value
119 * comes from a Student-T distribution with countx + county - 2 degrees of freedom; this
120 * value can be compared with a critical value (see also SCIPstudentTGetCriticalValue()) at
121 * a predefined confidence level for checking if x and y significantly differ in location
122 */
124 SCIP_Real meanx, /**< the mean of the first distribution */
125 SCIP_Real meany, /**< the mean of the second distribution */
126 SCIP_Real variancex, /**< the variance of the x-distribution */
127 SCIP_Real variancey, /**< the variance of the y-distribution */
128 SCIP_Real countx, /**< number of samples of x */
129 SCIP_Real county /**< number of samples of y */
130 )
131{
132 SCIP_Real pooledvariance;
133 SCIP_Real tresult;
134
135 /* too few samples */
136 if( countx < 1.9 || county < 1.9 )
137 return SCIP_INVALID;
138
139 /* pooled variance is the weighted average of the two variances */
140 pooledvariance = (countx - 1) * variancex + (county - 1) * variancey;
141 pooledvariance /= (countx + county - 2);
142
143 /* a variance close to zero means the distributions are basically constant */
144 pooledvariance = MAX(pooledvariance, 1e-9);
145
146 /* tresult can be understood as realization of a Student-T distributed variable with
147 * countx + county - 2 degrees of freedom
148 */
149 tresult = (meanx - meany) / sqrt(pooledvariance);
150 tresult *= sqrt(countx * county / (countx + county));
151
152 return tresult;
153}
154
155/** returns the value of the Gauss error function evaluated at a given point */
157 SCIP_Real x /**< value to evaluate */
158 )
159{
160#if defined(_WIN32) || defined(_WIN64)
161 SCIP_Real a1, a2, a3, a4, a5, p, t, y;
162 int sign;
163
164 a1 = 0.254829592;
165 a2 = -0.284496736;
166 a3 = 1.421413741;
167 a4 = -1.453152027;
168 a5 = 1.061405429;
169 p = 0.3275911;
170
171 sign = (x >= 0) ? 1 : -1;
172 x = REALABS(x);
173
174 t = 1.0/(1.0 + p*x);
175 y = 1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*exp(-x*x);
176 return sign * y;
177#else
178 return erf(x);
179#endif
180}
181
182/** get critical value of a standard normal distribution at a given confidence level */
184 SCIP_CONFIDENCELEVEL clevel /**< (one-sided) confidence level */
185 )
186{
187 return studentt_quartilesabove[(int)clevel];
188}
189
190/** calculates the cumulative distribution P(-infinity <= x <= value) that a normally distributed
191 * random variable x takes a value between -infinity and parameter \p value.
192 *
193 * The distribution is given by the respective mean and deviation. This implementation
194 * uses the error function SCIPerf().
195 */
197 SCIP_Real mean, /**< the mean value of the distribution */
198 SCIP_Real variance, /**< the square of the deviation of the distribution */
199 SCIP_Real value /**< the upper limit of the calculated distribution integral */
200 )
201{
202 SCIP_Real normvalue;
204
205 /* we need to calculate the standard deviation from the variance */
206 assert(variance >= -1e-9);
207 if( variance < 1e-9 )
208 std = 0.0;
209 else
210 std = sqrt(variance);
211
212 /* special treatment for zero variance */
213 if( std < 1e-9 )
214 {
215 if( value < mean + 1e-9 )
216 return 1.0;
217 else
218 return 0.0;
219 }
220 assert( std != 0.0 ); /* for lint */
221
222 /* scale and translate to standard normal distribution. Factor sqrt(2) is needed for SCIPerf() function */
223 normvalue = (value - mean)/(std * M_SQRT2);
224
225 SCIPdebugMessage(" Normalized value %g = ( %g - %g ) / (%g * 1.4142136)\n", normvalue, value, mean, std);
226
227 /* calculate the cumulative distribution function for normvalue. For negative normvalues, we negate the normvalue and
228 * use the oddness of the SCIPerf()-function; special treatment for values close to zero.
229 */
230 if( normvalue < 1e-9 && normvalue > -1e-9 )
231 return .5;
232 else if( normvalue > 0 )
233 {
234 SCIP_Real erfresult;
235
236 erfresult = SCIPerf(normvalue);
237 return erfresult / 2.0 + 0.5;
238 }
239 else
240 {
241 SCIP_Real erfresult;
242
243 erfresult = SCIPerf(-normvalue);
244
245 return 0.5 - erfresult / 2.0;
246 }
247}
248
249/*
250 * SCIP regression methods
251 */
252
253/** returns the number of observations of this regression */
255 SCIP_REGRESSION* regression /**< regression data structure */
256 )
257{
258 assert(regression != NULL);
259
260 return regression->nobservations;
261}
262
263/** return the current slope of the regression */
265 SCIP_REGRESSION* regression /**< regression data structure */
266 )
267{
268 assert(regression != NULL);
269
270 return regression->slope;
271}
272
273/** get the current y-intercept of the regression */
275 SCIP_REGRESSION* regression /**< regression data structure */
276 )
277{
278 assert(regression != NULL);
279
280 return regression->intercept;
281}
282
283/** recomputes regression coefficients from available observation data */
284static
286 SCIP_REGRESSION* regression /**< regression data structure */
287 )
288{
289 /* regression coefficients require two or more observations and variance in x */
290 if( regression->nobservations <= 1 || EPSZ(regression->variancesumx, 1e-9) )
291 {
292 regression->slope = SCIP_INVALID;
293 regression->intercept = SCIP_INVALID;
294 regression->corrcoef = SCIP_INVALID;
295 }
296 else if( EPSZ(regression->variancesumy, 1e-9) )
297 {
298 /* 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 */
299 regression->slope = 0.0;
300 regression->corrcoef = 0.0;
301 regression->intercept = regression->meany;
302 }
303 else
304 {
305 /* we ruled this case out already, but to please some compilers... */
306 assert(regression->variancesumx > 0.0);
307 assert(regression->variancesumy > 0.0);
308
309 /* compute slope */
310 regression->slope = (regression->sumxy - regression->nobservations * regression->meanx * regression->meany) / regression->variancesumx;
311
312 /* compute y-intercept */
313 regression->intercept = regression->meany - regression->slope * regression->meanx;
314
315 /* compute empirical correlation coefficient */
316 regression->corrcoef = (regression->sumxy - regression->nobservations * regression->meanx * regression->meany) /
317 sqrt(regression->variancesumx * regression->variancesumy);
318 }
319}
320
321/* incremental update of statistics describing mean and variance */
322static
324 SCIP_Real value, /**< current value to be added to incremental statistics */
325 SCIP_Real* meanptr, /**< pointer to value of current mean */
326 SCIP_Real* sumvarptr, /**< pointer to the value of the current variance sum term */
327 int nobservations, /**< total number of observations */
328 SCIP_Bool add /**< TRUE if the value should be added, FALSE for removing it */
329 )
330{
331 SCIP_Real oldmean;
332 SCIP_Real addfactor;
333 assert(meanptr != NULL);
334 assert(sumvarptr != NULL);
335 assert(nobservations > 0 || add);
336
337 addfactor = add ? 1.0 : -1.0;
338
339 oldmean = *meanptr;
340 *meanptr = oldmean + addfactor * (value - oldmean)/(SCIP_Real)nobservations;
341 *sumvarptr += addfactor * (value - oldmean) * (value - (*meanptr));
342
343 /* it may happen that *sumvarptr is slightly negative, especially after a series of add/removal operations */
344 assert(*sumvarptr >= -1e-4);
345 *sumvarptr = MAX(0.0, *sumvarptr);
346}
347
348/** removes an observation (x,y) from the regression */
350 SCIP_REGRESSION* regression, /**< regression data structure */
351 SCIP_Real x, /**< X of observation */
352 SCIP_Real y /**< Y of the observation */
353 )
354{
355 assert(regression != NULL);
356 assert(regression->nobservations > 0);
357
358 /* simply call the reset function in the case of a single remaining observation to avoid numerical troubles */
359 if( regression->nobservations == 1 )
360 {
361 SCIPregressionReset(regression);
362 }
363 else
364 {
365 SCIP_Bool add = FALSE;
366 --regression->nobservations;
367
368 /* decrement individual means and variances */
369 incrementalStatsUpdate(x, &regression->meanx, &regression->variancesumx, regression->nobservations, add);
370 incrementalStatsUpdate(y, &regression->meany, &regression->variancesumy, regression->nobservations, add);
371
372 /* decrement product sum */
373 regression->sumxy -= (x * y);
374 }
375
376 /* recompute regression parameters */
377 regressionRecompute(regression);
378}
379
380/** update regression by a new observation (x,y) */
382 SCIP_REGRESSION* regression, /**< regression data structure */
383 SCIP_Real x, /**< X of observation */
384 SCIP_Real y /**< Y of the observation */
385 )
386{
387 SCIP_Bool add = TRUE;
388 assert(regression != NULL);
389
390 ++(regression->nobservations);
391 incrementalStatsUpdate(x, &regression->meanx, &regression->variancesumx, regression->nobservations, add);
392 incrementalStatsUpdate(y, &regression->meany, &regression->variancesumy, regression->nobservations, add);
393
394 regression->sumxy += x * y;
395
396 regressionRecompute(regression);
397}
398
399/** reset regression data structure */
401 SCIP_REGRESSION* regression /**< regression data structure */
402 )
403{
404 regression->intercept = SCIP_INVALID;
405 regression->slope = SCIP_INVALID;
406 regression->corrcoef = SCIP_INVALID;
407 regression->meanx = 0;
408 regression->variancesumx = 0;
409 regression->sumxy = 0;
410 regression->meany = 0;
411 regression->variancesumy = 0;
412 regression->nobservations = 0;
413}
414
415/** creates and resets a regression */
417 SCIP_REGRESSION** regression /**< regression data structure */
418 )
419{
420 assert(regression != NULL);
421
422 /* allocate necessary memory */
423 SCIP_ALLOC (BMSallocMemory(regression) );
424
425 /* reset the regression */
426 SCIPregressionReset(*regression);
427
428 return SCIP_OKAY;
429}
430
431/** creates and resets a regression */
433 SCIP_REGRESSION** regression /**< regression data structure */
434 )
435{
436 BMSfreeMemory(regression);
437}
438
439/** calculate memory size for dynamically allocated arrays (copied from scip/set.c) */
440static
442 int initsize, /**< initial size of array */
443 SCIP_Real growfac, /**< growing factor of array */
444 int num /**< minimum number of entries to store */
445 )
446{
447 int size;
448
449 assert(initsize >= 0);
450 assert(growfac >= 1.0);
451 assert(num >= 0);
452
453 if( growfac == 1.0 )
454 size = MAX(initsize, num);
455 else
456 {
457 int oldsize;
458
459 /* calculate the size with this loop, such that the resulting numbers are always the same (-> block memory) */
460 initsize = MAX(initsize, 4);
461 size = initsize;
462 oldsize = size - 1;
463
464 /* second condition checks against overflow */
465 while( size < num && size > oldsize )
466 {
467 oldsize = size;
468 size = (int)(growfac * size + initsize);
469 }
470
471 /* if an overflow happened, set the correct value */
472 if( size <= oldsize )
473 size = num;
474 }
475
476 assert(size >= initsize);
477 assert(size >= num);
478
479 return size;
480}
481
482/*
483 * GML graphical printing methods
484 * For a detailed format decription see http://docs.yworks.com/yfiles/doc/developers-guide/gml.html
485 */
486
487#define GMLNODEWIDTH 120.0
488#define GMLNODEHEIGTH 30.0
489#define GMLFONTSIZE 13
490#define GMLNODETYPE "rectangle"
491#define GMLNODEFILLCOLOR "#ff0000"
492#define GMLEDGECOLOR "black"
493#define GMLNODEBORDERCOLOR "#000000"
494
495
496/** writes a node section to the given graph file */
498 FILE* file, /**< file to write to */
499 unsigned int id, /**< id of the node */
500 const char* label, /**< label of the node */
501 const char* nodetype, /**< type of the node, or NULL */
502 const char* fillcolor, /**< color of the node's interior, or NULL */
503 const char* bordercolor /**< color of the node's border, or NULL */
504 )
505{
506 assert(file != NULL);
507 assert(label != NULL);
508
509 fprintf(file, " node\n");
510 fprintf(file, " [\n");
511 fprintf(file, " id %u\n", id);
512 fprintf(file, " label \"%s\"\n", label);
513 fprintf(file, " graphics\n");
514 fprintf(file, " [\n");
515 fprintf(file, " w %g\n", GMLNODEWIDTH);
516 fprintf(file, " h %g\n", GMLNODEHEIGTH);
517
518 if( nodetype != NULL )
519 fprintf(file, " type \"%s\"\n", nodetype);
520 else
521 fprintf(file, " type \"%s\"\n", GMLNODETYPE);
522
523 if( fillcolor != NULL )
524 fprintf(file, " fill \"%s\"\n", fillcolor);
525 else
526 fprintf(file, " fill \"%s\"\n", GMLNODEFILLCOLOR);
527
528 if( bordercolor != NULL )
529 fprintf(file, " outline \"%s\"\n", bordercolor);
530 else
531 fprintf(file, " outline \"%s\"\n", GMLNODEBORDERCOLOR);
532
533 fprintf(file, " ]\n");
534 fprintf(file, " LabelGraphics\n");
535 fprintf(file, " [\n");
536 fprintf(file, " text \"%s\"\n", label);
537 fprintf(file, " fontSize %d\n", GMLFONTSIZE);
538 fprintf(file, " fontName \"Dialog\"\n");
539 fprintf(file, " anchor \"c\"\n");
540 fprintf(file, " ]\n");
541 fprintf(file, " ]\n");
542}
543
544/** writes a node section including weight to the given graph file */
546 FILE* file, /**< file to write to */
547 unsigned int id, /**< id of the node */
548 const char* label, /**< label of the node */
549 const char* nodetype, /**< type of the node, or NULL */
550 const char* fillcolor, /**< color of the node's interior, or NULL */
551 const char* bordercolor, /**< color of the node's border, or NULL */
552 SCIP_Real weight /**< weight of node */
553 )
554{
555 assert(file != NULL);
556 assert(label != NULL);
557
558 fprintf(file, " node\n");
559 fprintf(file, " [\n");
560 fprintf(file, " id %u\n", id);
561 fprintf(file, " label \"%s\"\n", label);
562 fprintf(file, " weight %g\n", weight);
563 fprintf(file, " graphics\n");
564 fprintf(file, " [\n");
565 fprintf(file, " w %g\n", GMLNODEWIDTH);
566 fprintf(file, " h %g\n", GMLNODEHEIGTH);
567
568 if( nodetype != NULL )
569 fprintf(file, " type \"%s\"\n", nodetype);
570 else
571 fprintf(file, " type \"%s\"\n", GMLNODETYPE);
572
573 if( fillcolor != NULL )
574 fprintf(file, " fill \"%s\"\n", fillcolor);
575 else
576 fprintf(file, " fill \"%s\"\n", GMLNODEFILLCOLOR);
577
578 if( bordercolor != NULL )
579 fprintf(file, " outline \"%s\"\n", bordercolor);
580 else
581 fprintf(file, " outline \"%s\"\n", GMLNODEBORDERCOLOR);
582
583 fprintf(file, " ]\n");
584 fprintf(file, " LabelGraphics\n");
585 fprintf(file, " [\n");
586 fprintf(file, " text \"%s\"\n", label);
587 fprintf(file, " fontSize %d\n", GMLFONTSIZE);
588 fprintf(file, " fontName \"Dialog\"\n");
589 fprintf(file, " anchor \"c\"\n");
590 fprintf(file, " ]\n");
591 fprintf(file, " ]\n");
592}
593
594/** writes an edge section to the given graph file */
596 FILE* file, /**< file to write to */
597 unsigned int source, /**< source node id of the node */
598 unsigned int target, /**< target node id of the edge */
599 const char* label, /**< label of the edge, or NULL */
600 const char* color /**< color of the edge, or NULL */
601 )
602{
603 assert(file != NULL);
604
605 fprintf(file, " edge\n");
606 fprintf(file, " [\n");
607 fprintf(file, " source %u\n", source);
608 fprintf(file, " target %u\n", target);
609
610 if( label != NULL)
611 fprintf(file, " label \"%s\"\n", label);
612
613 fprintf(file, " graphics\n");
614 fprintf(file, " [\n");
615
616 if( color != NULL )
617 fprintf(file, " fill \"%s\"\n", color);
618 else
619 fprintf(file, " fill \"%s\"\n", GMLEDGECOLOR);
620
621 /* fprintf(file, " arrow \"both\"\n"); */
622 fprintf(file, " ]\n");
623
624 if( label != NULL)
625 {
626 fprintf(file, " LabelGraphics\n");
627 fprintf(file, " [\n");
628 fprintf(file, " text \"%s\"\n", label);
629 fprintf(file, " fontSize %d\n", GMLFONTSIZE);
630 fprintf(file, " fontName \"Dialog\"\n");
631 fprintf(file, " anchor \"c\"\n");
632 fprintf(file, " ]\n");
633 }
634
635 fprintf(file, " ]\n");
636}
637
638/** writes an arc section to the given graph file */
640 FILE* file, /**< file to write to */
641 unsigned int source, /**< source node id of the node */
642 unsigned int target, /**< target node id of the edge */
643 const char* label, /**< label of the edge, or NULL */
644 const char* color /**< color of the edge, or NULL */
645 )
646{
647 assert(file != NULL);
648
649 fprintf(file, " edge\n");
650 fprintf(file, " [\n");
651 fprintf(file, " source %u\n", source);
652 fprintf(file, " target %u\n", target);
653
654 if( label != NULL)
655 fprintf(file, " label \"%s\"\n", label);
656
657 fprintf(file, " graphics\n");
658 fprintf(file, " [\n");
659
660 if( color != NULL )
661 fprintf(file, " fill \"%s\"\n", color);
662 else
663 fprintf(file, " fill \"%s\"\n", GMLEDGECOLOR);
664
665 fprintf(file, " targetArrow \"standard\"\n");
666 fprintf(file, " ]\n");
667
668 if( label != NULL)
669 {
670 fprintf(file, " LabelGraphics\n");
671 fprintf(file, " [\n");
672 fprintf(file, " text \"%s\"\n", label);
673 fprintf(file, " fontSize %d\n", GMLFONTSIZE);
674 fprintf(file, " fontName \"Dialog\"\n");
675 fprintf(file, " anchor \"c\"\n");
676 fprintf(file, " ]\n");
677 }
678
679 fprintf(file, " ]\n");
680}
681
682/** writes the starting line to a GML graph file, does not open a file */
684 FILE* file, /**< file to write to */
685 SCIP_Bool directed /**< is the graph directed */
686 )
687{
688 assert(file != NULL);
689
690 fprintf(file, "graph\n");
691 fprintf(file, "[\n");
692 fprintf(file, " hierarchic 1\n");
693
694 if( directed )
695 fprintf(file, " directed 1\n");
696}
697
698/** writes the ending lines to a GML graph file, does not close a file */
700 FILE* file /**< file to close */
701 )
702{
703 assert(file != NULL);
704
705 fprintf(file, "]\n");
706}
707
708/**
709 * writes the opening line to a dot graph file, does not open a file
710 */
712 FILE* file /**< file to write to */
713 )
714{
715 assert(file != NULL);
716
717 fprintf(file, "digraph G {\n");
718}
719
720/** adds a node to the dot graph */
722 FILE* file, /**< file to write to */
723 int node, /**< node id */
724 const char* label, /**< node label */
725 const char* nodetype, /**< type of the node, or NULL */
726 const char* fillcolor, /**< color of the node's interior, or NULL */
727 const char* bordercolor /**< color of the node's border, or NULL */
728 )
729{
730 assert(file != NULL);
731
732 fprintf(file, "\t%d [shape=\"%s\", label=\"%s\", style=\"filled\", fillcolor=\"%s\", color=\"%s\"];\n", node, nodetype, label, fillcolor, bordercolor);
733}
734
735/** adds an arc (edge) between two nodes in the dot graph */
737 FILE* file, /**< file to write to */
738 int source, /**< source node id of the node */
739 int target, /**< target node id of the edge */
740 const char* color /**< color of the edge, or NULL */
741 )
742{
743 assert(file != NULL);
744
745 fprintf(file, "\t%d -> %d [color=\"%s\"];\n", source, target, color);
746}
747
748/** writes the closing line to a dot graph file, does not close a file */
750 FILE* file /**< file to write to */
751 )
752{
753 assert(file != NULL);
754
755 fprintf(file, "}\n");
756}
757
758/*
759 * Sparse solution
760 */
761
762/** creates a sparse solution */
764 SCIP_SPARSESOL** sparsesol, /**< pointer to store the created sparse solution */
765 SCIP_VAR** vars, /**< variables in the sparse solution, must not contain continuous
766 * variables
767 */
768 int nvars, /**< number of variables to store, size of the lower and upper bound
769 * arrays
770 */
771 SCIP_Bool cleared /**< should the lower and upper bound arrays be cleared (entries set to
772 * 0)
773 */
774 )
775{
776 assert(sparsesol != NULL);
777 assert(vars != NULL);
778 assert(nvars >= 0);
779
780 SCIP_ALLOC( BMSallocMemory(sparsesol) );
781
782#ifndef NDEBUG
783 {
784 int v;
785
786 for( v = nvars - 1; v >= 0; --v )
787 {
788 assert(vars[v] != NULL);
789 /* assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS); */
790 }
791 }
792#endif
793
794 /* copy variables */
795 SCIP_ALLOC( BMSduplicateMemoryArray(&((*sparsesol)->vars), vars, nvars) );
796
797 /* create bound arrays */
798 if( cleared )
799 {
800 SCIP_ALLOC( BMSallocClearMemoryArray(&((*sparsesol)->lbvalues), nvars) );
801 SCIP_ALLOC( BMSallocClearMemoryArray(&((*sparsesol)->ubvalues), nvars) );
802 }
803 else
804 {
805 SCIP_ALLOC( BMSallocMemoryArray(&((*sparsesol)->lbvalues), nvars) );
806 SCIP_ALLOC( BMSallocMemoryArray(&((*sparsesol)->ubvalues), nvars) );
807 }
808
809 (*sparsesol)->nvars = nvars;
810
811 return SCIP_OKAY;
812}
813
814/** frees sparse solution */
816 SCIP_SPARSESOL** sparsesol /**< pointer to a sparse solution */
817 )
818{
819 assert(sparsesol != NULL);
820 assert(*sparsesol != NULL);
821
822 BMSfreeMemoryArray(&((*sparsesol)->vars));
823 BMSfreeMemoryArray(&((*sparsesol)->ubvalues));
824 BMSfreeMemoryArray(&((*sparsesol)->lbvalues));
825 BMSfreeMemory(sparsesol);
826}
827
828/** returns the variables stored in the given sparse solution */
830 SCIP_SPARSESOL* sparsesol /**< a sparse solution */
831 )
832{
833 assert(sparsesol != NULL);
834
835 return sparsesol->vars;
836}
837
838/** returns the number of variables stored in the given sparse solution */
840 SCIP_SPARSESOL* sparsesol /**< a sparse solution */
841 )
842{
843 assert(sparsesol != NULL);
844
845 return sparsesol->nvars;
846}
847
848/** returns the lower bound array for all variables for a given sparse solution */
850 SCIP_SPARSESOL* sparsesol /**< a sparse solution */
851 )
852{
853 assert(sparsesol != NULL);
854
855 return sparsesol->lbvalues;
856}
857
858/** returns the upper bound array for all variables for a given sparse solution */
860 SCIP_SPARSESOL* sparsesol /**< a sparse solution */
861 )
862{
863 assert(sparsesol != NULL);
864
865 return sparsesol->ubvalues;
866}
867
868/** constructs the first solution of sparse solution (all variables are set to their lower bound value */
870 SCIP_SPARSESOL* sparsesol, /**< sparse solutions */
871 SCIP_Longint* sol, /**< array to store the first solution */
872 int nvars /**< number of variables */
873 )
874{
875 SCIP_Longint* lbvalues;
876 int v;
877
878 assert(sparsesol != NULL);
879 assert(sol != NULL);
880 assert(nvars == SCIPsparseSolGetNVars(sparsesol));
881
882 lbvalues = SCIPsparseSolGetLbs(sparsesol);
883 assert(lbvalues != NULL);
884
885 /* copy the lower bounds */
886 for( v = 0; v < nvars; ++v )
887 sol[v] = lbvalues[v];
888}
889
890
891/** constructs the next solution of the sparse solution and return whether there was one more or not */
893 SCIP_SPARSESOL* sparsesol, /**< sparse solutions */
894 SCIP_Longint* sol, /**< current solution array which get changed to the next solution */
895 int nvars /**< number of variables */
896 )
897{
898 SCIP_Longint* lbvalues;
899 SCIP_Longint* ubvalues;
900 SCIP_Longint lbvalue;
901 SCIP_Longint ubvalue;
902 SCIP_Bool singular;
903 SCIP_Bool carryflag;
904 int v;
905
906 assert(sparsesol != NULL);
907 assert(sol != NULL);
908
909 if( nvars == 0 )
910 return FALSE;
911
912 assert(nvars > 0);
913 assert(nvars == SCIPsparseSolGetNVars(sparsesol));
914
915 lbvalues = SCIPsparseSolGetLbs(sparsesol);
916 ubvalues = SCIPsparseSolGetUbs(sparsesol);
917 assert(lbvalues != NULL);
918 assert(ubvalues != NULL);
919
920 singular = TRUE;
921 carryflag = FALSE;
922
923 for( v = 0; v < nvars; ++v )
924 {
925 lbvalue = lbvalues[v];
926 ubvalue = ubvalues[v];
927
928 if( lbvalue < ubvalue )
929 {
930 singular = FALSE;
931
932 if( carryflag == FALSE )
933 {
934 if( sol[v] < ubvalue )
935 {
936 sol[v]++;
937 break;
938 }
939 else
940 {
941 /* in the last solution the variables v was set to its upper bound value */
942 assert(sol[v] == ubvalue);
943 sol[v] = lbvalue;
944 carryflag = TRUE;
945 }
946 }
947 else
948 {
949 if( sol[v] < ubvalue )
950 {
951 sol[v]++;
952 carryflag = FALSE;
953 break;
954 }
955 else
956 {
957 assert(sol[v] == ubvalue);
958 sol[v] = lbvalue;
959 }
960 }
961 }
962 }
963
964 return (!carryflag && !singular);
965}
966
967
968/*
969 * Queue
970 */
971
972/** resizes element memory to hold at least the given number of elements */
973static
975 SCIP_QUEUE* queue, /**< pointer to a queue */
976 int minsize /**< minimal number of storable elements */
977 )
978{
979 assert(queue != NULL);
980 assert(minsize > 0);
981
982 if( minsize <= queue->size )
983 return SCIP_OKAY;
984
985 queue->size = MAX(minsize, (int)(queue->size * queue->sizefac));
986 SCIP_ALLOC( BMSreallocMemoryArray(&queue->slots, queue->size) );
987
988 return SCIP_OKAY;
989}
990
991
992/** creates a (circular) queue, best used if the size will be fixed or will not be increased that much */
994 SCIP_QUEUE** queue, /**< pointer to the new queue */
995 int initsize, /**< initial number of available element slots */
996 SCIP_Real sizefac /**< memory growing factor applied, if more element slots are needed */
997 )
998{
999 assert(queue != NULL);
1000
1001 initsize = MAX(1, initsize);
1002 sizefac = MAX(1.0, sizefac);
1003
1004 SCIP_ALLOC( BMSallocMemory(queue) );
1005 (*queue)->firstfree = 0;
1006 (*queue)->firstused = -1;
1007 (*queue)->size = 0;
1008 (*queue)->sizefac = sizefac;
1009 (*queue)->slots = NULL;
1010
1011 SCIP_CALL( queueResize(*queue, initsize) );
1012
1013 return SCIP_OKAY;
1014}
1015
1016/** frees queue, but not the data elements themselves */
1018 SCIP_QUEUE** queue /**< pointer to a queue */
1019 )
1020{
1021 assert(queue != NULL);
1022
1023 BMSfreeMemoryArray(&(*queue)->slots);
1024 BMSfreeMemory(queue);
1025}
1026
1027/** clears the queue, but doesn't free the data elements themselves */
1029 SCIP_QUEUE* queue /**< queue */
1030 )
1031{
1032 assert(queue != NULL);
1033
1034 queue->firstfree = 0;
1035 queue->firstused = -1;
1036}
1037
1038/** reallocates slots if queue is necessary */
1039static
1041 SCIP_QUEUE* queue /**< queue */
1042 )
1043{
1044 if( queue->firstfree == queue->firstused )
1045 {
1046 int sizediff;
1047 int oldsize = queue->size;
1048
1049 SCIP_CALL( queueResize(queue, queue->size+1) );
1050 assert(oldsize < queue->size);
1051
1052 sizediff = queue->size - oldsize;
1053
1054 /* move the used memory at the slots to the end */
1055 BMSmoveMemoryArray(&(queue->slots[queue->firstused + sizediff]), &(queue->slots[queue->firstused]), oldsize - queue->firstused); /*lint !e866*/
1056 queue->firstused += sizediff;
1057 }
1058 assert(queue->firstfree != queue->firstused);
1059
1060 return SCIP_OKAY;
1061}
1062
1063/** checks and adjusts marker of first free and first used slot */
1064static
1066 SCIP_QUEUE* queue /**< queue */
1067 )
1068{
1069 /* if we saved the value at the last position we need to reset the firstfree position */
1070 if( queue->firstfree == queue->size )
1071 queue->firstfree = 0;
1072
1073 /* if a first element was added, we need to update the firstused counter */
1074 if( queue->firstused == -1 )
1075 queue->firstused = 0;
1076}
1077
1078/** inserts pointer element at the end of the queue */
1080 SCIP_QUEUE* queue, /**< queue */
1081 void* elem /**< element to be inserted */
1082 )
1083{
1084 assert(queue != NULL);
1085 assert(queue->slots != NULL);
1086 assert(queue->firstused >= -1 && queue->firstused < queue->size);
1087 assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1088 assert(queue->firstused > -1 || queue->firstfree == 0);
1089 assert(elem != NULL);
1090
1091 /* check allocated memory */
1092 SCIP_CALL( queueCheckSize(queue) );
1093
1094 /* insert element at the first free slot */
1095 queue->slots[queue->firstfree].ptr = elem;
1096 ++(queue->firstfree);
1097
1098 /* check and adjust marker */
1099 queueCheckMarker(queue);
1100
1101 return SCIP_OKAY;
1102}
1103
1104/** inserts unsigned integer element at the end of the queue */
1106 SCIP_QUEUE* queue, /**< queue */
1107 unsigned int elem /**< element to be inserted */
1108 )
1109{
1110 assert(queue != NULL);
1111 assert(queue->slots != NULL);
1112 assert(queue->firstused >= -1 && queue->firstused < queue->size);
1113 assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1114 assert(queue->firstused > -1 || queue->firstfree == 0);
1115
1116 /* check allocated memory */
1117 SCIP_CALL( queueCheckSize(queue) );
1118
1119 /* insert element at the first free slot */
1120 queue->slots[queue->firstfree].uinteger = elem;
1121 ++(queue->firstfree);
1122
1123 /* check and adjust marker */
1124 queueCheckMarker(queue);
1125
1126 return SCIP_OKAY;
1127}
1128
1129/** removes and returns the first pointer element of the queue, or NULL if no element exists */
1131 SCIP_QUEUE* queue /**< queue */
1132 )
1133{
1134 int pos;
1135
1136 assert(queue != NULL);
1137 assert(queue->firstused >= -1 && queue->firstused < queue->size);
1138 assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1139 assert(queue->firstused > -1 || queue->firstfree == 0);
1140
1141 if( queue->firstused == -1 )
1142 return NULL;
1143
1144 assert(queue->slots != NULL);
1145
1146 pos = queue->firstused;
1147 ++(queue->firstused);
1148
1149 /* if we removed the value at the last position we need to reset the firstused position */
1150 if( queue->firstused == queue->size )
1151 queue->firstused = 0;
1152
1153 /* if we reached the first free position we can reset both, firstused and firstused, positions */
1154 if( queue->firstused == queue->firstfree )
1155 {
1156 queue->firstused = -1;
1157 queue->firstfree = 0; /* this is not necessary but looks better if we have an empty list to reset this value */
1158 }
1159
1160 return (queue->slots[pos].ptr);
1161}
1162
1163/** removes and returns the first unsigned integer element of the queue, or UINT_MAX if no element exists */
1165 SCIP_QUEUE* queue /**< queue */
1166 )
1167{
1168 int pos;
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 pos = queue->firstused;
1181 ++(queue->firstused);
1182
1183 /* if we removed the value at the last position we need to reset the firstused position */
1184 if( queue->firstused == queue->size )
1185 queue->firstused = 0;
1186
1187 /* if we reached the first free position we can reset both, firstused and firstused, positions */
1188 if( queue->firstused == queue->firstfree )
1189 {
1190 queue->firstused = -1;
1191 queue->firstfree = 0; /* this is not necessary but looks better if we have an empty list to reset this value */
1192 }
1193
1194 return (queue->slots[pos].uinteger);
1195}
1196
1197/** returns the first element of the queue without removing it, or NULL if no element exists */
1199 SCIP_QUEUE* queue /**< queue */
1200 )
1201{
1202 assert(queue != NULL);
1203 assert(queue->firstused >= -1 && queue->firstused < queue->size);
1204 assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1205 assert(queue->firstused > -1 || queue->firstfree == 0);
1206
1207 if( queue->firstused == -1 )
1208 return NULL;
1209
1210 assert(queue->slots != NULL);
1211
1212 return queue->slots[queue->firstused].ptr;
1213}
1214
1215/** returns the first unsigned integer element of the queue without removing it, or UINT_MAX if no element exists */
1217 SCIP_QUEUE* queue /**< queue */
1218 )
1219{
1220 assert(queue != NULL);
1221 assert(queue->firstused >= -1 && queue->firstused < queue->size);
1222 assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1223 assert(queue->firstused > -1 || queue->firstfree == 0);
1224
1225 if( queue->firstused == -1 )
1226 return UINT_MAX;
1227
1228 assert(queue->slots != NULL);
1229
1230 return queue->slots[queue->firstused].uinteger;
1231}
1232
1233/** returns whether the queue is empty */
1235 SCIP_QUEUE* queue /**< queue */
1236 )
1237{
1238 assert(queue != NULL);
1239 assert(queue->firstused >= -1 && queue->firstused < queue->size);
1240 assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1241 assert(queue->firstused > -1 || queue->firstfree == 0);
1242
1243 return (queue->firstused == -1);
1244}
1245
1246/** returns the number of elements in the queue */
1248 SCIP_QUEUE* queue /**< queue */
1249 )
1250{
1251 assert(queue != NULL);
1252 assert(queue->firstused >= -1 && queue->firstused < queue->size);
1253 assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1254 assert(queue->firstused > -1 || queue->firstfree == 0);
1255
1256 if( queue->firstused == -1 )
1257 return 0;
1258 else if( queue->firstused < queue->firstfree )
1259 return queue->firstfree - queue->firstused;
1260 else if( queue->firstused == queue->firstfree )
1261 return queue->size;
1262 else
1263 return queue->firstfree + (queue->size - queue->firstused);
1264}
1265
1266
1267/*
1268 * Priority Queue
1269 */
1270
1271#define PQ_PARENT(q) (((q)+1)/2-1)
1272#define PQ_LEFTCHILD(p) (2*(p)+1)
1273#define PQ_RIGHTCHILD(p) (2*(p)+2)
1274
1275
1276/** resizes element memory to hold at least the given number of elements */
1277static
1279 SCIP_PQUEUE* pqueue, /**< pointer to a priority queue */
1280 int minsize /**< minimal number of storable elements */
1281 )
1282{
1283 assert(pqueue != NULL);
1284
1285 if( minsize <= pqueue->size )
1286 return SCIP_OKAY;
1287
1288 pqueue->size = MAX(minsize, (int)(pqueue->size * pqueue->sizefac));
1289 SCIP_ALLOC( BMSreallocMemoryArray(&pqueue->slots, pqueue->size) );
1290
1291 return SCIP_OKAY;
1292}
1293
1294/** creates priority queue */
1296 SCIP_PQUEUE** pqueue, /**< pointer to a priority queue */
1297 int initsize, /**< initial number of available element slots */
1298 SCIP_Real sizefac, /**< memory growing factor applied, if more element slots are needed */
1299 SCIP_DECL_SORTPTRCOMP((*ptrcomp)), /**< data element comparator */
1300 SCIP_DECL_PQUEUEELEMCHGPOS((*elemchgpos)) /**< callback to act on position change of elem in priority queue, or NULL */
1301 )
1302{
1303 assert(pqueue != NULL);
1304 assert(ptrcomp != NULL);
1305
1306 initsize = MAX(1, initsize);
1307 sizefac = MAX(1.0, sizefac);
1308
1309 SCIP_ALLOC( BMSallocMemory(pqueue) );
1310 (*pqueue)->len = 0;
1311 (*pqueue)->size = 0;
1312 (*pqueue)->sizefac = sizefac;
1313 (*pqueue)->slots = NULL;
1314 (*pqueue)->ptrcomp = ptrcomp;
1315 (*pqueue)->elemchgpos = elemchgpos;
1316 SCIP_CALL( pqueueResize(*pqueue, initsize) );
1317
1318 return SCIP_OKAY;
1319}
1320
1321/** frees priority queue, but not the data elements themselves */
1323 SCIP_PQUEUE** pqueue /**< pointer to a priority queue */
1324 )
1325{
1326 assert(pqueue != NULL);
1327
1328 BMSfreeMemoryArray(&(*pqueue)->slots);
1329 BMSfreeMemory(pqueue);
1330}
1331
1332/** clears the priority queue, but doesn't free the data elements themselves */
1334 SCIP_PQUEUE* pqueue /**< priority queue */
1335 )
1336{
1337 assert(pqueue != NULL);
1338
1339 pqueue->len = 0;
1340}
1341
1342/** assign element to new slot in priority queue */
1343static
1345 SCIP_PQUEUE* pqueue, /**< priority queue */
1346 void* elem, /**< element whose position changes */
1347 int oldpos, /**< old position or -1 if elem is newly inserted */
1348 int newpos /**< new position */
1349 )
1350{
1351 pqueue->slots[newpos] = elem;
1352
1353 /* act on position change */
1354 if( pqueue->elemchgpos != NULL )
1355 {
1356 pqueue->elemchgpos(elem, oldpos, newpos);
1357 }
1358}
1359
1360#ifdef SCIP_MORE_DEBUG
1361/** ensure that the priority queue still has the heap property */
1362static
1363SCIP_Bool pqueueHasHeapProperty(
1364 SCIP_PQUEUE* pqueue /**< priority queue */
1365 )
1366{
1367 int i;
1368
1369 if( SCIPpqueueNElems(pqueue) == 0 )
1370 return TRUE;
1371
1372 /* check local heap property between parents and children */
1373 for( i = 0; i < SCIPpqueueNElems(pqueue); ++i )
1374 {
1375 if( i > 0 && pqueue->ptrcomp(pqueue->slots[i], pqueue->slots[PQ_PARENT(i)]) < 0 )
1376 return FALSE;
1377 if( i < PQ_PARENT(SCIPpqueueNElems(pqueue)) )
1378 {
1379 int leftchild = PQ_LEFTCHILD(i);
1380 int rightchild = PQ_RIGHTCHILD(i);
1381 assert(leftchild < SCIPpqueueNElems(pqueue));
1382 assert(rightchild <= SCIPpqueueNElems(pqueue));
1383 if( pqueue->ptrcomp(pqueue->slots[i], pqueue->slots[leftchild]) > 0 )
1384 return FALSE;
1385 if( rightchild < SCIPpqueueNElems(pqueue) && pqueue->ptrcomp(pqueue->slots[i], pqueue->slots[rightchild]) > 0)
1386 return FALSE;
1387 }
1388 }
1389 return TRUE;
1390}
1391#endif
1392
1393/** inserts element into priority queue */
1395 SCIP_PQUEUE* pqueue, /**< priority queue */
1396 void* elem /**< element to be inserted */
1397 )
1398{
1399 int pos;
1400 int parentpos;
1401
1402 assert(pqueue != NULL);
1403 assert(pqueue->len >= 0);
1404 assert(elem != NULL);
1405
1406 SCIP_CALL( pqueueResize(pqueue, pqueue->len+1) );
1407
1408 /* insert element as leaf in the tree, move it towards the root as long it is better than its parent */
1409 pos = pqueue->len;
1410 pqueue->len++;
1411 parentpos = PQ_PARENT(pos);
1412 while( pos > 0 && (*pqueue->ptrcomp)(elem, pqueue->slots[parentpos]) < 0 )
1413 {
1414 assert((*pqueue->ptrcomp)(pqueue->slots[parentpos], elem) >= 0);
1415 pqueueElemChgPos(pqueue, pqueue->slots[parentpos], parentpos, pos);
1416
1417 pos = parentpos;
1418 parentpos = PQ_PARENT(pos);
1419 }
1420
1421 /* insert element at the found position */
1422 pqueueElemChgPos(pqueue, elem, -1, pos);
1423
1424#ifdef SCIP_MORE_DEBUG
1425 assert(pqueueHasHeapProperty(pqueue));
1426#endif
1427
1428 return SCIP_OKAY;
1429}
1430
1431
1432/** delete element at specified position, maintaining the heap property */
1434 SCIP_PQUEUE* pqueue, /**< priority queue */
1435 int pos /**< position of element that should be deleted */
1436 )
1437{
1438 void* last;
1439
1440 assert(pqueue != NULL);
1441 assert(pos >= 0);
1442 assert(pos < SCIPpqueueNElems(pqueue));
1443
1444 /* remove element at specified position of the tree, move the better child to its parents position until the last element
1445 * of the queue could be placed in the empty slot
1446 */
1447 pqueue->len--;
1448
1449 /* everything in place */
1450 if( pos == pqueue->len )
1451 return;
1452
1453 last = pqueue->slots[pqueue->len];
1454
1455 /* last element is brought to pos. it may now violate the heap property compared to its parent, or to its children.
1456 * In the first case, move it up, otherwise, move it down.
1457 */
1458 while( pos > 0 && (*pqueue->ptrcomp)(last, pqueue->slots[PQ_PARENT(pos)]) < 0 )
1459 {
1460 pqueueElemChgPos(pqueue, pqueue->slots[PQ_PARENT(pos)], PQ_PARENT(pos), pos);
1461 pos = PQ_PARENT(pos);
1462 }
1463
1464 while( pos <= PQ_PARENT(pqueue->len-1) )
1465 {
1466 int childpos = PQ_LEFTCHILD(pos);
1467 int brotherpos = PQ_RIGHTCHILD(pos);
1468
1469 /* determine better of the two children */
1470 if( brotherpos < pqueue->len && (*pqueue->ptrcomp)(pqueue->slots[brotherpos], pqueue->slots[childpos]) < 0 )
1471 childpos = brotherpos;
1472
1473 if( (*pqueue->ptrcomp)(last, pqueue->slots[childpos]) <= 0 )
1474 break;
1475
1476 /* move better element from childpos to pos */
1477 pqueueElemChgPos(pqueue, pqueue->slots[childpos], childpos, pos);
1478
1479 pos = childpos;
1480 }
1481
1482 /* pos must point into a valid position */
1483 assert(pos <= pqueue->len - 1);
1484
1485 pqueueElemChgPos(pqueue, last, pqueue->len, pos);
1486
1487#ifdef SCIP_MORE_DEBUG
1488 assert(pqueueHasHeapProperty(pqueue));
1489#endif
1490}
1491
1492/** removes and returns best element from the priority queue */
1494 SCIP_PQUEUE* pqueue /**< priority queue */
1495 )
1496{
1497 void* root;
1498
1499 assert(pqueue != NULL);
1500 assert(pqueue->len >= 0);
1501
1502 if( pqueue->len == 0 )
1503 return NULL;
1504
1505 root = pqueue->slots[0];
1506
1507 SCIPpqueueDelPos(pqueue, 0);
1508
1509 return root;
1510}
1511
1512/** returns the best element of the queue without removing it */
1514 SCIP_PQUEUE* pqueue /**< priority queue */
1515 )
1516{
1517 assert(pqueue != NULL);
1518 assert(pqueue->len >= 0);
1519
1520 if( pqueue->len == 0 )
1521 return NULL;
1522
1523 return pqueue->slots[0];
1524}
1525
1526/** returns the number of elements in the queue */
1528 SCIP_PQUEUE* pqueue /**< priority queue */
1529 )
1530{
1531 assert(pqueue != NULL);
1532 assert(pqueue->len >= 0);
1533
1534 return pqueue->len;
1535}
1536
1537/** returns the elements of the queue; changing the returned array may destroy the queue's ordering! */
1539 SCIP_PQUEUE* pqueue /**< priority queue */
1540 )
1541{
1542 assert(pqueue != NULL);
1543 assert(pqueue->len >= 0);
1544
1545 return pqueue->slots;
1546}
1547
1548/** return the position of @p elem in the priority queue, or -1 if element is not found */
1550 SCIP_PQUEUE* pqueue, /**< priority queue */
1551 void* elem /**< element to be inserted */
1552 )
1553{
1554 int pos = -1;
1555
1556 while( ++pos < SCIPpqueueNElems(pqueue) )
1557 {
1558 if( pqueue->slots[pos] == elem )
1559 return pos;
1560 }
1561
1562 return -1;
1563}
1564
1565
1566
1567
1568/*
1569 * Hash Table
1570 */
1571
1572/** table of some prime numbers */
1573static int primetable[] = {
1574 2,
1575 7,
1576 19,
1577 31,
1578 59,
1579 227,
1580 617,
1581 1523,
1582 3547,
1583 8011,
1584 17707,
1585 38723,
1586 83833,
1587 180317,
1588 385897,
1589 821411,
1590 1742369,
1591 3680893,
1592 5693959,
1593 7753849,
1594 9849703,
1595 11973277,
1596 14121853,
1597 17643961,
1598 24273817,
1599 32452843,
1600 49979687,
1601 67867967,
1602 86028121,
1603 104395301,
1604 122949823,
1605 141650939,
1606 160481183,
1607 179424673,
1608 198491317,
1609 217645177,
1610 256203161,
1611 314606869,
1612 373587883,
1613 433024223,
1614 492876847,
1615 553105243,
1616 613651349,
1617 694847533,
1618 756065159,
1619 817504243,
1620 879190747,
1621 941083981,
1622 982451653,
1623 INT_MAX
1624};
1625static const int primetablesize = sizeof(primetable)/sizeof(int);
1626
1627/** simple and fast 2-universal hash function using multiply and shift */
1628static
1629uint32_t hashvalue(
1630 uint64_t input /**< key value */
1631 )
1632{
1633 return ( (uint32_t) ((UINT64_C(0x9e3779b97f4a7c15) * input)>>32) ) | 1u;
1634}
1635
1636/** returns a reasonable hash table size (a prime number) that is at least as large as the specified value */
1638 int minsize /**< minimal size of the hash table */
1639 )
1640{
1641 int pos;
1642
1643 (void) SCIPsortedvecFindInt(primetable, minsize, primetablesize, &pos);
1644 assert(0 <= pos && pos < primetablesize);
1645
1646 return primetable[pos];
1647}
1648
1649/** appends element to the multihash list */
1650static
1652 SCIP_MULTIHASHLIST** multihashlist, /**< pointer to hash list */
1653 BMS_BLKMEM* blkmem, /**< block memory */
1654 void* element /**< element to append to the list */
1655 )
1656{
1657 SCIP_MULTIHASHLIST* newlist;
1658
1659 assert(multihashlist != NULL);
1660 assert(blkmem != NULL);
1661 assert(element != NULL);
1662
1663 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &newlist) );
1664 newlist->element = element;
1665 newlist->next = *multihashlist;
1666 *multihashlist = newlist;
1667
1668 return SCIP_OKAY;
1669}
1670
1671/** frees a multihash list entry and all its successors */
1672static
1674 SCIP_MULTIHASHLIST** multihashlist, /**< pointer to multihash list to free */
1675 BMS_BLKMEM* blkmem /**< block memory */
1676 )
1677{
1678 SCIP_MULTIHASHLIST* list;
1679 SCIP_MULTIHASHLIST* nextlist;
1680
1681 assert(multihashlist != NULL);
1682 assert(blkmem != NULL);
1683
1684 list = *multihashlist;
1685 while( list != NULL )
1686 {
1687 nextlist = list->next;
1688 BMSfreeBlockMemory(blkmem, &list);
1689 list = nextlist;
1690 }
1691
1692 *multihashlist = NULL;
1693}
1694
1695/** finds multihash list entry pointing to element with given key in the multihash list, returns NULL if not found */
1696static
1698 SCIP_MULTIHASHLIST* multihashlist, /**< multihash list */
1699 SCIP_DECL_HASHGETKEY((*hashgetkey)), /**< gets the key of the given element */
1700 SCIP_DECL_HASHKEYEQ ((*hashkeyeq)), /**< returns TRUE iff both keys are equal */
1701 SCIP_DECL_HASHKEYVAL((*hashkeyval)), /**< returns the hash value of the key */
1702 void* userptr, /**< user pointer */
1703 uint64_t keyval, /**< hash value of key */
1704 void* key /**< key to retrieve */
1705 )
1706{
1707 uint64_t currentkeyval;
1708 void* currentkey;
1709
1710 assert(hashkeyeq != NULL);
1711 assert(key != NULL);
1712
1713 while( multihashlist != NULL )
1714 {
1715 currentkey = hashgetkey(userptr, multihashlist->element);
1716 currentkeyval = hashkeyval(userptr, currentkey);
1717 if( currentkeyval == keyval && hashkeyeq(userptr, currentkey, key) )
1718 return multihashlist;
1719
1720 multihashlist = multihashlist->next;
1721 }
1722
1723 return NULL;
1724}
1725
1726/** retrieves element with given key from the multihash list, or NULL */
1727static
1729 SCIP_MULTIHASHLIST* multihashlist, /**< hash list */
1730 SCIP_DECL_HASHGETKEY((*hashgetkey)), /**< gets the key of the given element */
1731 SCIP_DECL_HASHKEYEQ ((*hashkeyeq)), /**< returns TRUE iff both keys are equal */
1732 SCIP_DECL_HASHKEYVAL((*hashkeyval)), /**< returns the hash value of the key */
1733 void* userptr, /**< user pointer */
1734 uint64_t keyval, /**< hash value of key */
1735 void* key /**< key to retrieve */
1736 )
1737{
1739
1740 /* find hash list entry */
1741 h = multihashlistFind(multihashlist, hashgetkey, hashkeyeq, hashkeyval, userptr, keyval, key);
1742
1743 /* return element */
1744 if( h != NULL )
1745 {
1746#ifndef NDEBUG
1748
1749 h2 = multihashlistFind(h->next, hashgetkey, hashkeyeq, hashkeyval, userptr, keyval, key);
1750
1751 if( h2 != NULL )
1752 {
1753 void* key1;
1754 void* key2;
1755
1756 key1 = hashgetkey(userptr, h->element);
1757 key2 = hashgetkey(userptr, h2->element);
1758 assert(hashkeyval(userptr, key1) == hashkeyval(userptr, key2));
1759
1760 if( hashkeyeq(userptr, key1, key2) )
1761 {
1762 SCIPerrorMessage("WARNING: hashkey with same value exists multiple times (e.g. duplicate constraint/variable names), so the return value is maybe not correct\n");
1763 }
1764 }
1765#endif
1766
1767 return h->element;
1768 }
1769 else
1770 return NULL;
1771}
1772
1773
1774/** retrieves element with given key from the multihash list, or NULL
1775 * returns pointer to multihash table list entry
1776 */
1777static
1779 SCIP_MULTIHASHLIST** multihashlist, /**< on input: hash list to search; on exit: hash list entry corresponding
1780 * to element after retrieved one, or NULL */
1781 SCIP_DECL_HASHGETKEY((*hashgetkey)), /**< gets the key of the given element */
1782 SCIP_DECL_HASHKEYEQ ((*hashkeyeq)), /**< returns TRUE iff both keys are equal */
1783 SCIP_DECL_HASHKEYVAL((*hashkeyval)), /**< returns the hash value of the key */
1784 void* userptr, /**< user pointer */
1785 uint64_t keyval, /**< hash value of key */
1786 void* key /**< key to retrieve */
1787 )
1788{
1790
1791 assert(multihashlist != NULL);
1792
1793 /* find hash list entry */
1794 h = multihashlistFind(*multihashlist, hashgetkey, hashkeyeq, hashkeyval, userptr, keyval, key);
1795
1796 /* return element */
1797 if( h != NULL )
1798 {
1799 *multihashlist = h->next;
1800
1801 return h->element;
1802 }
1803
1804 *multihashlist = NULL;
1805
1806 return NULL;
1807}
1808
1809/** removes element from the multihash list */
1810static
1812 SCIP_MULTIHASHLIST** multihashlist, /**< pointer to hash list */
1813 BMS_BLKMEM* blkmem, /**< block memory */
1814 void* element /**< element to remove from the list */
1815 )
1816{
1817 SCIP_MULTIHASHLIST* nextlist;
1818
1819 assert(multihashlist != NULL);
1820 assert(blkmem != NULL);
1821 assert(element != NULL);
1822
1823 while( *multihashlist != NULL && (*multihashlist)->element != element )
1824 multihashlist = &(*multihashlist)->next;
1825
1826 if( *multihashlist != NULL )
1827 {
1828 nextlist = (*multihashlist)->next;
1829 BMSfreeBlockMemory(blkmem, multihashlist);
1830 *multihashlist = nextlist;
1831
1832 return TRUE;
1833 }
1834
1835 return FALSE;
1836}
1837
1838#define SCIP_MULTIHASH_MAXSIZE 33554431 /* 2^25 - 1*/
1839#define SCIP_MULTIHASH_RESIZE_PERCENTAGE 65
1840#define SCIP_MULTIHASH_GROW_FACTOR 1.31
1841
1842/** resizing(increasing) the given multihash */
1843static
1845 SCIP_MULTIHASH* multihash /**< hash table */
1846 )
1847{
1848 SCIP_MULTIHASHLIST** newlists;
1849 SCIP_MULTIHASHLIST* multihashlist;
1850 SCIP_Longint nelements;
1851 int nnewlists;
1852 int l;
1853
1854 assert(multihash != NULL);
1855 assert(multihash->lists != NULL);
1856 assert(multihash->nlists > 0);
1857 assert(multihash->hashgetkey != NULL);
1858 assert(multihash->hashkeyeq != NULL);
1859 assert(multihash->hashkeyval != NULL);
1860
1861 /* get new memeory for hash table lists */
1862 nnewlists = (int) MIN((unsigned int)(multihash->nlists * SCIP_MULTIHASH_GROW_FACTOR), SCIP_MULTIHASH_MAXSIZE);
1863 nnewlists = MAX(nnewlists, multihash->nlists);
1864
1865 SCIPdebugMessage("load = %g, nelements = %" SCIP_LONGINT_FORMAT ", nlists = %d, nnewlist = %d\n", SCIPmultihashGetLoad(multihash), multihash->nelements, multihash->nlists, nnewlists);
1866
1867 if( nnewlists > multihash->nlists )
1868 {
1869 SCIP_Bool onlyone;
1870 void* key;
1871 uint64_t keyval;
1872 unsigned int hashval;
1873
1874 SCIP_ALLOC( BMSallocClearBlockMemoryArray(multihash->blkmem, &newlists, nnewlists) );
1875
1876 /* move all lists */
1877 for( l = multihash->nlists - 1; l >= 0; --l )
1878 {
1879 multihashlist = multihash->lists[l];
1880 onlyone = TRUE;
1881
1882 /* move all elements frmm the old lists into the new lists */
1883 while( multihashlist != NULL )
1884 {
1885 /* get the hash key and its hash value */
1886 key = multihash->hashgetkey(multihash->userptr, multihashlist->element);
1887 keyval = multihash->hashkeyval(multihash->userptr, key);
1888 hashval = (unsigned int) (keyval % (unsigned) nnewlists); /*lint !e573*/
1889
1890 /* if the old hash table list consists of only one entry, we still can use this old memory block instead
1891 * of creating a new one
1892 */
1893 if( multihashlist->next == NULL && onlyone )
1894 {
1895 /* the new list is also empty, we can directly copy the entry */
1896 if( newlists[hashval] == NULL )
1897 newlists[hashval] = multihashlist;
1898 /* the new list is not empty, so we need to find the first empty spot */
1899 else
1900 {
1901 SCIP_MULTIHASHLIST* lastnext = newlists[hashval];
1902 SCIP_MULTIHASHLIST* next = lastnext->next;
1903
1904 while( next != NULL )
1905 {
1906 lastnext = next;
1907 next = next->next;
1908 }
1909
1910 lastnext->next = multihashlist;
1911 }
1912
1913 multihash->lists[l] = NULL;
1914 }
1915 else
1916 {
1917 /* append old element to the list at the hash position */
1918 SCIP_CALL( multihashlistAppend(&(newlists[hashval]), multihash->blkmem, multihashlist->element) );
1919 }
1920
1921 onlyone = FALSE;
1922 multihashlist = multihashlist->next;
1923 }
1924 }
1925
1926 /* remember number of elements */
1927 nelements = multihash->nelements;
1928 /* clear old lists */
1929 SCIPmultihashRemoveAll(multihash);
1930 /* free old lists */
1931 BMSfreeBlockMemoryArray(multihash->blkmem, &(multihash->lists), multihash->nlists);
1932
1933 /* set new data */
1934 multihash->lists = newlists;
1935 multihash->nlists = nnewlists;
1936 multihash->nelements = nelements;
1937
1938#ifdef SCIP_MORE_DEBUG
1939 {
1940 SCIP_Longint sumslotsize = 0;
1941
1942 for( l = 0; l < multihash->nlists; ++l )
1943 {
1944 multihashlist = multihash->lists[l];
1945 while( multihashlist != NULL )
1946 {
1947 sumslotsize++;
1948 multihashlist = multihashlist->next;
1949 }
1950 }
1951 assert(sumslotsize == multihash->nelements);
1952 }
1953#endif
1954 }
1955
1956 return SCIP_OKAY;
1957}
1958
1959/** creates a multihash table */
1961 SCIP_MULTIHASH** multihash, /**< pointer to store the created multihash table */
1962 BMS_BLKMEM* blkmem, /**< block memory used to store multihash table entries */
1963 int tablesize, /**< size of the hash table */
1964 SCIP_DECL_HASHGETKEY((*hashgetkey)), /**< gets the key of the given element */
1965 SCIP_DECL_HASHKEYEQ ((*hashkeyeq)), /**< returns TRUE iff both keys are equal */
1966 SCIP_DECL_HASHKEYVAL((*hashkeyval)), /**< returns the hash value of the key */
1967 void* userptr /**< user pointer */
1968 )
1969{
1970 /* only assert non negative to catch overflow errors
1971 * but not zeros due to integer divison
1972 */
1973 assert(tablesize >= 0);
1974 assert(multihash != NULL);
1975 assert(hashgetkey != NULL);
1976 assert(hashkeyeq != NULL);
1977 assert(hashkeyval != NULL);
1978
1979 SCIP_ALLOC( BMSallocBlockMemory(blkmem, multihash) );
1980 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*multihash)->lists, tablesize) );
1981 (*multihash)->blkmem = blkmem;
1982 (*multihash)->nlists = tablesize;
1983 (*multihash)->hashgetkey = hashgetkey;
1984 (*multihash)->hashkeyeq = hashkeyeq;
1985 (*multihash)->hashkeyval = hashkeyval;
1986 (*multihash)->userptr = userptr;
1987 (*multihash)->nelements = 0;
1988
1989 return SCIP_OKAY;
1990}
1991
1992/** frees the multihash table */
1994 SCIP_MULTIHASH** multihash /**< pointer to the multihash table */
1995 )
1996{
1997 int i;
1998 SCIP_MULTIHASH* table;
1999 BMS_BLKMEM* blkmem;
2000 SCIP_MULTIHASHLIST** lists;
2001
2002 assert(multihash != NULL);
2003 assert(*multihash != NULL);
2004
2005 table = (*multihash);
2006 blkmem = table->blkmem;
2007 lists = table->lists;
2008
2009 /* free hash lists */
2010 for( i = table->nlists - 1; i >= 0; --i )
2011 multihashlistFree(&lists[i], blkmem);
2012
2013 /* free main hash table data structure */
2014 BMSfreeBlockMemoryArray(blkmem, &table->lists, table->nlists);
2015 BMSfreeBlockMemory(blkmem, multihash);
2016}
2017
2018
2019/** inserts element in multihash table (multiple inserts of same element possible)
2020 *
2021 * @note A pointer to a multihashlist returned by SCIPmultihashRetrieveNext() might get invalid when adding an element
2022 * to the hash table, due to dynamic resizing.
2023 */
2025 SCIP_MULTIHASH* multihash, /**< multihash table */
2026 void* element /**< element to insert into the table */
2027 )
2028{
2029 void* key;
2030 uint64_t keyval;
2031 unsigned int hashval;
2032
2033 assert(multihash != NULL);
2034 assert(multihash->lists != NULL);
2035 assert(multihash->nlists > 0);
2036 assert(multihash->hashgetkey != NULL);
2037 assert(multihash->hashkeyeq != NULL);
2038 assert(multihash->hashkeyval != NULL);
2039 assert(element != NULL);
2040
2041 /* dynamically resizing the hashtables */
2043 {
2044 SCIP_CALL( multihashResize(multihash) );
2045 }
2046
2047 /* get the hash key and its hash value */
2048 key = multihash->hashgetkey(multihash->userptr, element);
2049 keyval = multihash->hashkeyval(multihash->userptr, key);
2050 hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
2051
2052 /* append element to the list at the hash position */
2053 SCIP_CALL( multihashlistAppend(&multihash->lists[hashval], multihash->blkmem, element) );
2054
2055 ++(multihash->nelements);
2056
2057 return SCIP_OKAY;
2058}
2059
2060/** inserts element in multihash table (multiple insertion of same element is checked and results in an error)
2061 *
2062 * @note A pointer to a multihashlist returned by SCIPmultihashRetrieveNext() might get invalid when adding a new
2063 * element to the multihash table, due to dynamic resizing.
2064 */
2066 SCIP_MULTIHASH* multihash, /**< multihash table */
2067 void* element /**< element to insert into the table */
2068 )
2069{
2070 assert(multihash != NULL);
2071 assert(multihash->hashgetkey != NULL);
2072
2073 /* check, if key is already existing */
2074 if( SCIPmultihashRetrieve(multihash, multihash->hashgetkey(multihash->userptr, element)) != NULL )
2076
2077 /* insert element in hash table */
2078 SCIP_CALL( SCIPmultihashInsert(multihash, element) );
2079
2080 return SCIP_OKAY;
2081}
2082
2083/** retrieve element with key from multihash table, returns NULL if not existing */
2085 SCIP_MULTIHASH* multihash, /**< multihash table */
2086 void* key /**< key to retrieve */
2087 )
2088{
2089 uint64_t keyval;
2090 unsigned int hashval;
2091
2092 assert(multihash != NULL);
2093 assert(multihash->lists != NULL);
2094 assert(multihash->nlists > 0);
2095 assert(multihash->hashgetkey != NULL);
2096 assert(multihash->hashkeyeq != NULL);
2097 assert(multihash->hashkeyval != NULL);
2098 assert(key != NULL);
2099
2100 /* get the hash value of the key */
2101 keyval = multihash->hashkeyval(multihash->userptr, key);
2102 hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
2103
2104 return multihashlistRetrieve(multihash->lists[hashval], multihash->hashgetkey, multihash->hashkeyeq,
2105 multihash->hashkeyval, multihash->userptr, keyval, key);
2106}
2107
2108/** retrieve element with key from multihash table, returns NULL if not existing
2109 * can be used to retrieve all entries with the same key (one-by-one)
2110 *
2111 * @note The returned multimultihashlist pointer might get invalid when adding a new element to the multihash table.
2112 */
2114 SCIP_MULTIHASH* multihash, /**< multihash table */
2115 SCIP_MULTIHASHLIST** multihashlist, /**< input: entry in hash table list from which to start searching, or NULL
2116 * output: entry in hash table list corresponding to element after
2117 * retrieved one, or NULL */
2118 void* key /**< key to retrieve */
2119 )
2120{
2121 uint64_t keyval;
2122
2123 assert(multihash != NULL);
2124 assert(multihash->lists != NULL);
2125 assert(multihash->nlists > 0);
2126 assert(multihash->hashgetkey != NULL);
2127 assert(multihash->hashkeyeq != NULL);
2128 assert(multihash->hashkeyval != NULL);
2129 assert(multihashlist != NULL);
2130 assert(key != NULL);
2131
2132 keyval = multihash->hashkeyval(multihash->userptr, key);
2133
2134 if( *multihashlist == NULL )
2135 {
2136 unsigned int hashval;
2137
2138 /* get the hash value of the key */
2139 hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
2140
2141 *multihashlist = multihash->lists[hashval];
2142 }
2143
2144 return multihashlistRetrieveNext(multihashlist, multihash->hashgetkey, multihash->hashkeyeq,
2145 multihash->hashkeyval, multihash->userptr, keyval, key);
2146}
2147
2148/** returns whether the given element exists in the multihash table */
2150 SCIP_MULTIHASH* multihash, /**< multihash table */
2151 void* element /**< element to search in the table */
2152 )
2153{
2154 void* key;
2155 uint64_t keyval;
2156 unsigned int hashval;
2157
2158 assert(multihash != NULL);
2159 assert(multihash->lists != NULL);
2160 assert(multihash->nlists > 0);
2161 assert(multihash->hashgetkey != NULL);
2162 assert(multihash->hashkeyeq != NULL);
2163 assert(multihash->hashkeyval != NULL);
2164 assert(element != NULL);
2165
2166 /* get the hash key and its hash value */
2167 key = multihash->hashgetkey(multihash->userptr, element);
2168 keyval = multihash->hashkeyval(multihash->userptr, key);
2169 hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
2170
2171 return (multihashlistFind(multihash->lists[hashval], multihash->hashgetkey, multihash->hashkeyeq,
2172 multihash->hashkeyval, multihash->userptr, keyval, key) != NULL);
2173}
2174
2175/** removes element from the multihash table, if it exists */
2177 SCIP_MULTIHASH* multihash, /**< multihash table */
2178 void* element /**< element to remove from the table */
2179 )
2180{
2181 void* key;
2182 uint64_t keyval;
2183 unsigned int hashval;
2184
2185 assert(multihash != NULL);
2186 assert(multihash->lists != NULL);
2187 assert(multihash->nlists > 0);
2188 assert(multihash->hashgetkey != NULL);
2189 assert(multihash->hashkeyeq != NULL);
2190 assert(multihash->hashkeyval != NULL);
2191 assert(element != NULL);
2192
2193 /* get the hash key and its hash value */
2194 key = multihash->hashgetkey(multihash->userptr, element);
2195 keyval = multihash->hashkeyval(multihash->userptr, key);
2196 hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
2197
2198 /* remove element from the list at the hash position */
2199 if( multihashlistRemove(&multihash->lists[hashval], multihash->blkmem, element) )
2200 --(multihash->nelements);
2201
2202 return SCIP_OKAY;
2203}
2204
2205/** removes all elements of the multihash table
2206 *
2207 * @note From a performance point of view you should not fill and clear a hash table too often since the clearing can
2208 * be expensive. Clearing is done by looping over all buckets and removing the hash table lists one-by-one.
2209 */
2211 SCIP_MULTIHASH* multihash /**< multihash table */
2212 )
2213{
2214 BMS_BLKMEM* blkmem;
2215 SCIP_MULTIHASHLIST** lists;
2216 int i;
2217
2218 assert(multihash != NULL);
2219
2220 blkmem = multihash->blkmem;
2221 lists = multihash->lists;
2222
2223 /* free hash lists */
2224 for( i = multihash->nlists - 1; i >= 0; --i )
2225 multihashlistFree(&lists[i], blkmem);
2226
2227 multihash->nelements = 0;
2228}
2229
2230/** returns number of multihash table elements */
2232 SCIP_MULTIHASH* multihash /**< multihash table */
2233 )
2234{
2235 assert(multihash != NULL);
2236
2237 return multihash->nelements;
2238}
2239
2240/** returns the load of the given multihash table in percentage */
2242 SCIP_MULTIHASH* multihash /**< multihash table */
2243 )
2244{
2245 assert(multihash != NULL);
2246
2247 return ((SCIP_Real)(multihash->nelements) / (multihash->nlists) * 100.0);
2248}
2249
2250/** prints statistics about multihash table usage */
2252 SCIP_MULTIHASH* multihash, /**< multihash table */
2253 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
2254 )
2255{
2256 SCIP_MULTIHASHLIST* multihashlist;
2257 int usedslots;
2258 int maxslotsize;
2259 int sumslotsize;
2260 int slotsize;
2261 int i;
2262
2263 assert(multihash != NULL);
2264
2265 usedslots = 0;
2266 maxslotsize = 0;
2267 sumslotsize = 0;
2268 for( i = 0; i < multihash->nlists; ++i )
2269 {
2270 multihashlist = multihash->lists[i];
2271 if( multihashlist != NULL )
2272 {
2273 usedslots++;
2274 slotsize = 0;
2275 while( multihashlist != NULL )
2276 {
2277 slotsize++;
2278 multihashlist = multihashlist->next;
2279 }
2280 maxslotsize = MAX(maxslotsize, slotsize);
2281 sumslotsize += slotsize;
2282 }
2283 }
2284 assert(sumslotsize == multihash->nelements);
2285 SCIP_UNUSED(sumslotsize);
2286
2287 SCIPmessagePrintInfo(messagehdlr, "%" SCIP_LONGINT_FORMAT " multihash entries, used %d/%d slots (%.1f%%)",
2288 multihash->nelements, usedslots, multihash->nlists, 100.0*(SCIP_Real)usedslots/(SCIP_Real)(multihash->nlists));
2289 if( usedslots > 0 )
2290 SCIPmessagePrintInfo(messagehdlr, ", avg. %.1f entries/used slot, max. %d entries in slot",
2291 (SCIP_Real)(multihash->nelements)/(SCIP_Real)usedslots, maxslotsize);
2292 SCIPmessagePrintInfo(messagehdlr, "\n");
2293}
2294
2295/** creates a hash table */
2297 SCIP_HASHTABLE** hashtable, /**< pointer to store the created hash table */
2298 BMS_BLKMEM* blkmem, /**< block memory used to store hash table entries */
2299 int tablesize, /**< size of the hash table */
2300 SCIP_DECL_HASHGETKEY((*hashgetkey)), /**< gets the key of the given element */
2301 SCIP_DECL_HASHKEYEQ ((*hashkeyeq)), /**< returns TRUE iff both keys are equal */
2302 SCIP_DECL_HASHKEYVAL((*hashkeyval)), /**< returns the hash value of the key */
2303 void* userptr /**< user pointer */
2304 )
2305{
2306 unsigned int nslots;
2307
2308 /* only assert non negative to catch overflow errors
2309 * but not zeros due to integer divison
2310 */
2311 assert(tablesize >= 0);
2312 assert(hashtable != NULL);
2313 assert(hashgetkey != NULL);
2314 assert(hashkeyeq != NULL);
2315 assert(hashkeyval != NULL);
2316 assert(blkmem != NULL);
2317
2318 SCIP_ALLOC( BMSallocBlockMemory(blkmem, hashtable) );
2319
2320 /* dont create too small hashtables, i.e. at least size 32, and increase
2321 * the given size by divinding it by 0.9, since then no rebuilding will
2322 * be necessary if the given number of elements are inserted. Finally round
2323 * to the next power of two.
2324 */
2325 (*hashtable)->shift = 32;
2326 (*hashtable)->shift -= (unsigned int)ceil(LOG2(MAX(32.0, tablesize / 0.9)));
2327
2328 /* compute size from shift */
2329 nslots = 1u << (32 - (*hashtable)->shift);
2330
2331 /* compute mask to do a fast modulo by nslots using bitwise and */
2332 (*hashtable)->mask = nslots - 1;
2333 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*hashtable)->slots, nslots) );
2334 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*hashtable)->hashes, nslots) );
2335 (*hashtable)->blkmem = blkmem;
2336 (*hashtable)->hashgetkey = hashgetkey;
2337 (*hashtable)->hashkeyeq = hashkeyeq;
2338 (*hashtable)->hashkeyval = hashkeyval;
2339 (*hashtable)->userptr = userptr;
2340 (*hashtable)->nelements = 0;
2341
2342 return SCIP_OKAY;
2343}
2344
2345/** frees the hash table */
2347 SCIP_HASHTABLE** hashtable /**< pointer to the hash table */
2348 )
2349{
2350 uint32_t nslots;
2351 SCIP_HASHTABLE* table;
2352
2353 assert(hashtable != NULL);
2354 assert(*hashtable != NULL);
2355 table = *hashtable;
2356 nslots = (*hashtable)->mask + 1;
2357#ifdef SCIP_DEBUG
2358 {
2359 uint32_t maxprobelen = 0;
2360 uint64_t probelensum = 0;
2361 uint32_t i;
2362
2363 assert(table != NULL);
2364
2365 for( i = 0; i < nslots; ++i )
2366 {
2367 if( table->hashes[i] != 0 )
2368 {
2369 uint32_t probelen = ((i + table->mask + 1 - (table->hashes[i]>>(table->shift))) & table->mask) + 1;
2370 probelensum += probelen;
2371 maxprobelen = MAX(probelen, maxprobelen);
2372 }
2373 }
2374
2375 SCIPdebugMessage("%u hash table entries, used %u/%u slots (%.1f%%)",
2376 (unsigned int)table->nelements, (unsigned int)table->nelements, (unsigned int)nslots,
2377 100.0*(SCIP_Real)table->nelements/(SCIP_Real)(nslots));
2378 if( table->nelements > 0 )
2379 SCIPdebugMessage(", avg. probe length is %.1f, max. probe length is %u",
2380 (SCIP_Real)(probelensum)/(SCIP_Real)table->nelements, (unsigned int)maxprobelen);
2381 SCIPdebugMessage("\n");
2382 }
2383#endif
2384
2385 /* free main hash table data structure */
2386 BMSfreeBlockMemoryArray((*hashtable)->blkmem, &table->hashes, nslots);
2387 BMSfreeBlockMemoryArray((*hashtable)->blkmem, &table->slots, nslots);
2388 BMSfreeBlockMemory((*hashtable)->blkmem, hashtable);
2389}
2390
2391/** removes all elements of the hash table
2392 *
2393 * @note From a performance point of view you should not fill and clear a hash table too often since the clearing can
2394 * be expensive. Clearing is done by looping over all buckets and removing the hash table lists one-by-one.
2395 *
2396 * @deprecated Please use SCIPhashtableRemoveAll()
2397 */
2399 SCIP_HASHTABLE* hashtable /**< hash table */
2400 )
2401{
2402 SCIPhashtableRemoveAll(hashtable);
2403}
2404
2405/* computes the distance from it's desired position for the element stored at pos */
2406#define ELEM_DISTANCE(pos) (((pos) + hashtable->mask + 1 - (hashtable->hashes[(pos)]>>(hashtable->shift))) & hashtable->mask)
2407
2408/** inserts element in hash table (multiple inserts of same element overrides previous one) */
2409static
2411 SCIP_HASHTABLE* hashtable, /**< hash table */
2412 void* element, /**< element to insert into the table */
2413 void* key, /**< key of element */
2414 uint32_t hashval, /**< hash value of element */
2415 SCIP_Bool override /**< should element be overridden or an error be returned if already existing */
2416 )
2417{
2418 uint32_t elemdistance;
2419 uint32_t pos;
2420#ifndef NDEBUG
2421 SCIP_Bool swapped = FALSE;
2422#endif
2423
2424 assert(hashtable != NULL);
2425 assert(hashtable->slots != NULL);
2426 assert(hashtable->hashes != NULL);
2427 assert(hashtable->mask > 0);
2428 assert(hashtable->hashgetkey != NULL);
2429 assert(hashtable->hashkeyeq != NULL);
2430 assert(hashtable->hashkeyval != NULL);
2431 assert(element != NULL);
2432
2433 pos = hashval>>(hashtable->shift);
2434 elemdistance = 0;
2435 while( TRUE ) /*lint !e716*/
2436 {
2437 uint32_t distance;
2438
2439 /* if position is empty or key equal insert element */
2440 if( hashtable->hashes[pos] == 0 )
2441 {
2442 hashtable->slots[pos] = element;
2443 hashtable->hashes[pos] = hashval;
2444 ++hashtable->nelements;
2445 return SCIP_OKAY;
2446 }
2447
2448 if( hashtable->hashes[pos] == hashval && hashtable->hashkeyeq(hashtable->userptr,
2449 hashtable->hashgetkey(hashtable->userptr, hashtable->slots[pos]), key) )
2450 {
2451 if( override )
2452 {
2453#ifndef NDEBUG
2454 assert(! swapped);
2455#endif
2456 hashtable->slots[pos] = element;
2457 hashtable->hashes[pos] = hashval;
2458 return SCIP_OKAY;
2459 }
2460 else
2461 {
2463 }
2464 }
2465
2466 /* otherwise check if the current element at this position is closer to its hashvalue */
2467 distance = ELEM_DISTANCE(pos);
2468 if( distance < elemdistance )
2469 {
2470 uint32_t tmp;
2471
2472 /* if this is the case we insert the new element here and find a new position for the old one */
2473 elemdistance = distance;
2474 SCIPswapPointers(&hashtable->slots[pos], &element);
2475 tmp = hashval;
2476 hashval = hashtable->hashes[pos];
2477 hashtable->hashes[pos] = tmp;
2478 key = hashtable->hashgetkey(hashtable->userptr, element);
2479
2480 /* after doing a swap the case that other elements are replaced must not happen anymore */
2481#ifndef NDEBUG
2482 swapped = TRUE;
2483#endif
2484 }
2485
2486 /* continue until we have found an empty position */
2487 pos = (pos + 1) & hashtable->mask;
2488 ++elemdistance;
2489 }
2490}
2491
2492/** check if the load factor of the hashtable is too high and rebuild if necessary */
2493static
2495 SCIP_HASHTABLE* hashtable /**< hash table */
2496 )
2497{
2498 assert(hashtable != NULL);
2499 assert(hashtable->shift < 32);
2500
2501 /* use integer arithmetic to approximately check if load factor is above 90% */
2502 if( ((((uint64_t)hashtable->nelements)<<10)>>(32-hashtable->shift) > 921) )
2503 {
2504 void** slots;
2505 uint32_t* hashes;
2506 uint32_t nslots;
2507 uint32_t newnslots;
2508 uint32_t i;
2509
2510 /* calculate new size (always power of two) */
2511 nslots = hashtable->mask + 1;
2512 newnslots = 2*nslots;
2513 hashtable->mask = newnslots-1;
2514 --hashtable->shift;
2515
2516 /* reallocate array */
2517 SCIP_ALLOC( BMSallocBlockMemoryArray(hashtable->blkmem, &slots, newnslots) );
2518 SCIP_ALLOC( BMSallocClearBlockMemoryArray(hashtable->blkmem, &hashes, newnslots) );
2519
2520 SCIPswapPointers((void**) &slots, (void**) &hashtable->slots);
2521 SCIPswapPointers((void**) &hashes, (void**) &hashtable->hashes);
2522 hashtable->nelements = 0;
2523
2524 /* reinsert all elements */
2525 for( i = 0; i < nslots; ++i )
2526 {
2527 /* using SCIP_CALL_ABORT since there are no allocations or duplicates
2528 * and thus no bad return codes when inserting the elements
2529 */
2530 if( hashes[i] != 0 )
2531 {
2532 SCIP_CALL_ABORT( hashtableInsert(hashtable, slots[i], hashtable->hashgetkey(hashtable->userptr, slots[i]), hashes[i], FALSE) );
2533 }
2534 }
2535 BMSfreeBlockMemoryArray(hashtable->blkmem, &hashes, nslots);
2536 BMSfreeBlockMemoryArray(hashtable->blkmem, &slots, nslots);
2537 }
2538
2539 return SCIP_OKAY;
2540}
2541
2542
2543/** inserts element in hash table
2544 *
2545 * @note multiple inserts of same element overrides previous one
2546 */
2548 SCIP_HASHTABLE* hashtable, /**< hash table */
2549 void* element /**< element to insert into the table */
2550 )
2551{
2552 void* key;
2553 uint64_t keyval;
2554 uint32_t hashval;
2555
2556 assert(hashtable != NULL);
2557 assert(hashtable->slots != NULL);
2558 assert(hashtable->hashes != NULL);
2559 assert(hashtable->mask > 0);
2560 assert(hashtable->hashgetkey != NULL);
2561 assert(hashtable->hashkeyeq != NULL);
2562 assert(hashtable->hashkeyval != NULL);
2563 assert(element != NULL);
2564
2565 SCIP_CALL( hashtableCheckLoad(hashtable) );
2566
2567 /* get the hash key and its hash value */
2568 key = hashtable->hashgetkey(hashtable->userptr, element);
2569 keyval = hashtable->hashkeyval(hashtable->userptr, key);
2570 hashval = hashvalue(keyval);
2571
2572 return hashtableInsert(hashtable, element, key, hashval, TRUE);
2573}
2574
2575/** inserts element in hash table
2576 *
2577 * @note multiple insertion of same element is checked and results in an error
2578 */
2580 SCIP_HASHTABLE* hashtable, /**< hash table */
2581 void* element /**< element to insert into the table */
2582 )
2583{
2584 void* key;
2585 uint64_t keyval;
2586 uint32_t hashval;
2587
2588 assert(hashtable != NULL);
2589 assert(hashtable->slots != NULL);
2590 assert(hashtable->hashes != NULL);
2591 assert(hashtable->mask > 0);
2592 assert(hashtable->hashgetkey != NULL);
2593 assert(hashtable->hashkeyeq != NULL);
2594 assert(hashtable->hashkeyval != NULL);
2595 assert(element != NULL);
2596
2597 SCIP_CALL( hashtableCheckLoad(hashtable) );
2598
2599 /* get the hash key and its hash value */
2600 key = hashtable->hashgetkey(hashtable->userptr, element);
2601 keyval = hashtable->hashkeyval(hashtable->userptr, key);
2602 hashval = hashvalue(keyval);
2603
2604 return hashtableInsert(hashtable, element, key, hashval, FALSE);
2605}
2606
2607/** retrieve element with key from hash table, returns NULL if not existing */
2609 SCIP_HASHTABLE* hashtable, /**< hash table */
2610 void* key /**< key to retrieve */
2611 )
2612{
2613 uint64_t keyval;
2614 uint32_t hashval;
2615 uint32_t pos;
2616 uint32_t elemdistance;
2617
2618 assert(hashtable != NULL);
2619 assert(hashtable->slots != NULL);
2620 assert(hashtable->hashes != NULL);
2621 assert(hashtable->mask > 0);
2622 assert(hashtable->hashgetkey != NULL);
2623 assert(hashtable->hashkeyeq != NULL);
2624 assert(hashtable->hashkeyval != NULL);
2625 assert(key != NULL);
2626
2627 /* get the hash value of the key */
2628 keyval = hashtable->hashkeyval(hashtable->userptr, key);
2629 hashval = hashvalue(keyval);
2630
2631 pos = hashval>>(hashtable->shift);
2632 elemdistance = 0;
2633
2634 while( TRUE ) /*lint !e716*/
2635 {
2636 uint32_t distance;
2637
2638 /* slots is empty so element cannot be contained */
2639 if( hashtable->hashes[pos] == 0 )
2640 return NULL;
2641
2642 distance = ELEM_DISTANCE(pos);
2643
2644 /* element cannot be contained since otherwise we would have swapped it with this one during insert */
2645 if( elemdistance > distance )
2646 return NULL;
2647
2648 /* found element */
2649 if( hashtable->hashes[pos] == hashval && hashtable->hashkeyeq(hashtable->userptr,
2650 hashtable->hashgetkey(hashtable->userptr, hashtable->slots[pos]), key) )
2651 return hashtable->slots[pos];
2652
2653 pos = (pos + 1) & hashtable->mask;
2654 ++elemdistance;
2655 }
2656}
2657
2658/** returns whether the given element exists in the table */
2660 SCIP_HASHTABLE* hashtable, /**< hash table */
2661 void* element /**< element to search in the table */
2662 )
2663{
2664 assert(hashtable != NULL);
2665 assert(hashtable->slots != NULL);
2666 assert(hashtable->hashes != NULL);
2667 assert(hashtable->mask > 0);
2668 assert(hashtable->hashgetkey != NULL);
2669 assert(hashtable->hashkeyeq != NULL);
2670 assert(hashtable->hashkeyval != NULL);
2671 assert(element != NULL);
2672
2673 return (SCIPhashtableRetrieve(hashtable, hashtable->hashgetkey(hashtable->userptr, element)) != NULL);
2674}
2675
2676/** removes element from the hash table, if it exists */
2678 SCIP_HASHTABLE* hashtable, /**< hash table */
2679 void* element /**< element to remove from the table */
2680 )
2681{
2682 void* key;
2683 uint64_t keyval;
2684 uint32_t hashval;
2685 uint32_t elemdistance;
2686 uint32_t distance;
2687 uint32_t pos;
2688
2689 assert(hashtable != NULL);
2690 assert(hashtable->slots != NULL);
2691 assert(hashtable->hashes != NULL);
2692 assert(hashtable->mask > 0);
2693 assert(hashtable->hashgetkey != NULL);
2694 assert(hashtable->hashkeyeq != NULL);
2695 assert(hashtable->hashkeyval != NULL);
2696 assert(element != NULL);
2697
2698 /* get the hash key and its hash value */
2699 key = hashtable->hashgetkey(hashtable->userptr, element);
2700 keyval = hashtable->hashkeyval(hashtable->userptr, key);
2701 hashval = hashvalue(keyval);
2702
2703 elemdistance = 0;
2704 pos = hashval>>(hashtable->shift);
2705 while( TRUE ) /*lint !e716*/
2706 {
2707 /* slots empty so element not contained */
2708 if( hashtable->hashes[pos] == 0 )
2709 return SCIP_OKAY;
2710
2711 distance = ELEM_DISTANCE(pos);
2712
2713 /* element can not be contained since otherwise we would have swapped it with this one */
2714 if( elemdistance > distance )
2715 return SCIP_OKAY;
2716
2717 if( hashtable->hashes[pos] == hashval && hashtable->hashkeyeq(hashtable->userptr,
2718 hashtable->hashgetkey(hashtable->userptr, hashtable->slots[pos]), key) )
2719 {
2720 /* element exists at pos so break out of loop */
2721 break;
2722 }
2723
2724 pos = (pos + 1) & hashtable->mask;
2725 ++elemdistance;
2726 }
2727
2728 /* remove element */
2729 hashtable->hashes[pos] = 0;
2730 --hashtable->nelements;
2731 while( TRUE ) /*lint !e716*/
2732 {
2733 uint32_t nextpos = (pos + 1) & hashtable->mask;
2734
2735 /* nothing to do since there is no chain that needs to be moved */
2736 if( hashtable->hashes[nextpos] == 0 )
2737 break;
2738
2739 /* check if the element is the start of a new chain and return if that is the case */
2740 if( (hashtable->hashes[nextpos]>>(hashtable->shift)) == nextpos )
2741 break;
2742
2743 /* element should be moved to the left and next element needs to be checked */
2744 hashtable->slots[pos] = hashtable->slots[nextpos];
2745 hashtable->hashes[pos] = hashtable->hashes[nextpos];
2746 hashtable->hashes[nextpos] = 0;
2747
2748 pos = nextpos;
2749 }
2750
2751 return SCIP_OKAY;
2752}
2753
2754/** removes all elements of the hash table */
2756 SCIP_HASHTABLE* hashtable /**< hash table */
2757 )
2758{
2759 assert(hashtable != NULL);
2760
2761 BMSclearMemoryArray(hashtable->hashes, hashtable->mask + 1);
2762
2763 hashtable->nelements = 0;
2764}
2765
2766/** returns number of hash table elements */
2768 SCIP_HASHTABLE* hashtable /**< hash table */
2769 )
2770{
2771 assert(hashtable != NULL);
2772
2773 return hashtable->nelements;
2774}
2775
2776/** gives the number of entries in the internal arrays of a hash table */
2778 SCIP_HASHTABLE* hashtable /**< hash table */
2779 )
2780{
2781 return (int) hashtable->mask + 1;
2782}
2783
2784/** gives the element at the given index or NULL if entry at that index has no element */
2786 SCIP_HASHTABLE* hashtable, /**< hash table */
2787 int entryidx /**< index of hash table entry */
2788 )
2789{
2790 return hashtable->hashes[entryidx] == 0 ? NULL : hashtable->slots[entryidx];
2791}
2792
2793/** returns the load of the given hash table in percentage */
2795 SCIP_HASHTABLE* hashtable /**< hash table */
2796 )
2797{
2798 assert(hashtable != NULL);
2799
2800 return ((SCIP_Real)(hashtable->nelements) / (hashtable->mask + 1) * 100.0);
2801}
2802
2803/** prints statistics about hash table usage */
2805 SCIP_HASHTABLE* hashtable, /**< hash table */
2806 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
2807 )
2808{
2809 uint32_t maxprobelen = 0;
2810 uint64_t probelensum = 0;
2811 uint32_t nslots;
2812 uint32_t i;
2813
2814 assert(hashtable != NULL);
2815
2816 nslots = hashtable->mask + 1;
2817
2818 /* compute the maximum and average probe length */
2819 for( i = 0; i < nslots; ++i )
2820 {
2821 if( hashtable->hashes[i] != 0 )
2822 {
2823 uint32_t probelen = ELEM_DISTANCE(i) + 1;
2824 probelensum += probelen;
2825 maxprobelen = MAX(probelen, maxprobelen);
2826 }
2827 }
2828
2829 /* print general hash table statistics */
2830 SCIPmessagePrintInfo(messagehdlr, "%u hash entries, used %u/%u slots (%.1f%%)",
2831 (unsigned int)hashtable->nelements, (unsigned int)hashtable->nelements,
2832 (unsigned int)nslots, 100.0*(SCIP_Real)hashtable->nelements/(SCIP_Real)(nslots));
2833
2834 /* if not empty print average and maximum probe length */
2835 if( hashtable->nelements > 0 )
2836 SCIPmessagePrintInfo(messagehdlr, ", avg. probe length is %.1f, max. probe length is %u",
2837 (SCIP_Real)(probelensum)/(SCIP_Real)hashtable->nelements, (unsigned int)maxprobelen);
2838 SCIPmessagePrintInfo(messagehdlr, "\n");
2839}
2840
2841/** returns TRUE iff both keys (i.e. strings) are equal */
2842SCIP_DECL_HASHKEYEQ(SCIPhashKeyEqString)
2843{ /*lint --e{715}*/
2844 const char* string1 = (const char*)key1;
2845 const char* string2 = (const char*)key2;
2846
2847 return (strcmp(string1, string2) == 0);
2848}
2849
2850/** returns the hash value of the key (i.e. string) */
2851SCIP_DECL_HASHKEYVAL(SCIPhashKeyValString)
2852{ /*lint --e{715}*/
2853 const char* str;
2854 uint64_t hash;
2855
2856 str = (const char*)key;
2857 hash = 37;
2858 while( *str != '\0' )
2859 {
2860 hash *= 11;
2861 hash += (unsigned int)(*str); /*lint !e571*/
2862 str++;
2863 }
2864
2865 return hash;
2866}
2867
2868
2869/** gets the element as the key */
2870SCIP_DECL_HASHGETKEY(SCIPhashGetKeyStandard)
2871{ /*lint --e{715}*/
2872 /* the key is the element itself */
2873 return elem;
2874}
2875
2876/** returns TRUE iff both keys(pointer) are equal */
2877SCIP_DECL_HASHKEYEQ(SCIPhashKeyEqPtr)
2878{ /*lint --e{715}*/
2879 return (key1 == key2);
2880}
2881
2882/** returns the hash value of the key */
2883SCIP_DECL_HASHKEYVAL(SCIPhashKeyValPtr)
2884{ /*lint --e{715}*/
2885 /* the key is used as the keyvalue too */
2886 return (uint64_t) (uintptr_t) key;
2887}
2888
2889
2890
2891/*
2892 * Hash Map
2893 */
2894
2895/* redefine ELEM_DISTANCE macro for hashmap */
2896#undef ELEM_DISTANCE
2897/* computes the distance from it's desired position for the element stored at pos */
2898#define ELEM_DISTANCE(pos) (((pos) + hashmap->mask + 1 - (hashmap->hashes[(pos)]>>(hashmap->shift))) & hashmap->mask)
2899
2900/** inserts element in hash table */
2901static
2903 SCIP_HASHMAP* hashmap, /**< hash map */
2904 void* origin, /**< element to insert into the table */
2905 SCIP_HASHMAPIMAGE image, /**< key of element */
2906 uint32_t hashval, /**< hash value of element */
2907 SCIP_Bool override /**< should element be overridden or error be returned if already existing */
2908 )
2909{
2910 uint32_t elemdistance;
2911 uint32_t pos;
2912
2913 assert(hashmap != NULL);
2914 assert(hashmap->slots != NULL);
2915 assert(hashmap->hashes != NULL);
2916 assert(hashmap->mask > 0);
2917 assert(hashval != 0);
2918
2919 pos = hashval>>(hashmap->shift);
2920 elemdistance = 0;
2921 while( TRUE ) /*lint !e716*/
2922 {
2923 uint32_t distance;
2924
2925 /* if position is empty or key equal insert element */
2926 if( hashmap->hashes[pos] == 0 )
2927 {
2928 hashmap->slots[pos].origin = origin;
2929 hashmap->slots[pos].image = image;
2930 hashmap->hashes[pos] = hashval;
2931 ++hashmap->nelements;
2932 return SCIP_OKAY;
2933 }
2934
2935 if( hashval == hashmap->hashes[pos] && origin == hashmap->slots[pos].origin )
2936 {
2937 if( override )
2938 {
2939 hashmap->slots[pos].origin = origin;
2940 hashmap->slots[pos].image = image;
2941 hashmap->hashes[pos] = hashval;
2942 return SCIP_OKAY;
2943 }
2944 else
2945 {
2947 }
2948 }
2949
2950 /* otherwise check if the current element at this position is closer to its hashvalue */
2951 distance = ELEM_DISTANCE(pos);
2952 if( distance < elemdistance )
2953 {
2955 uint32_t tmphash;
2956
2957 /* if this is the case we insert the new element here and find a new position for the old one */
2958 elemdistance = distance;
2959 tmphash = hashval;
2960 hashval = hashmap->hashes[pos];
2961 hashmap->hashes[pos] = tmphash;
2962 SCIPswapPointers(&hashmap->slots[pos].origin, &origin);
2963 tmp = image;
2964 image = hashmap->slots[pos].image;
2965 hashmap->slots[pos].image = tmp;
2966 }
2967
2968 /* continue until we have found an empty position */
2969 pos = (pos + 1) & hashmap->mask;
2970 ++elemdistance;
2971 }
2972}
2973
2974/** lookup origin in the hashmap. If element is found returns true and the position of the element,
2975 * otherwise returns FALSE.
2976 */
2977static
2979 SCIP_HASHMAP* hashmap, /**< hash table */
2980 void* origin, /**< origin to lookup */
2981 uint32_t* pos /**< pointer to store position of element, if exists */
2982 )
2983{
2984 uint32_t hashval;
2985 uint32_t elemdistance;
2986
2987 assert(hashmap != NULL);
2988 assert(hashmap->slots != NULL);
2989 assert(hashmap->hashes != NULL);
2990 assert(hashmap->mask > 0);
2991
2992 /* get the hash value */
2993 hashval = hashvalue((size_t)origin);
2994 assert(hashval != 0);
2995
2996 *pos = hashval>>(hashmap->shift);
2997 elemdistance = 0;
2998
2999 while( TRUE ) /*lint !e716*/
3000 {
3001 uint32_t distance;
3002
3003 /* slots is empty so element cannot be contained */
3004 if( hashmap->hashes[*pos] == 0 )
3005 return FALSE;
3006
3007 distance = ELEM_DISTANCE(*pos);
3008 /* element can not be contained since otherwise we would have swapped it with this one during insert */
3009 if( elemdistance > distance )
3010 return FALSE;
3011
3012 /* found element */
3013 if( hashmap->hashes[*pos] == hashval && hashmap->slots[*pos].origin == origin )
3014 return TRUE;
3015
3016 *pos = (*pos + 1) & hashmap->mask;
3017 ++elemdistance;
3018 }
3019}
3020
3021/** check if the load factor of the hashmap is too high and rebuild if necessary */
3022static
3024 SCIP_HASHMAP* hashmap /**< hash table */
3025 )
3026{
3027 assert(hashmap != NULL);
3028 assert(hashmap->shift < 32);
3029
3030 /* use integer arithmetic to approximately check if load factor is above 90% */
3031 if( ((((uint64_t)hashmap->nelements)<<10)>>(32-hashmap->shift) > 921) )
3032 {
3033 SCIP_HASHMAPENTRY* slots;
3034 uint32_t* hashes;
3035 uint32_t nslots;
3036 uint32_t newnslots;
3037 uint32_t i;
3038
3039 /* calculate new size (always power of two) */
3040 nslots = hashmap->mask + 1;
3041 --hashmap->shift;
3042 newnslots = 2*nslots;
3043 hashmap->mask = newnslots-1;
3044
3045 /* reallocate array */
3046 SCIP_ALLOC( BMSallocBlockMemoryArray(hashmap->blkmem, &slots, newnslots) );
3047 SCIP_ALLOC( BMSallocClearBlockMemoryArray(hashmap->blkmem, &hashes, newnslots) );
3048
3049 SCIPswapPointers((void**) &slots, (void**) &hashmap->slots);
3050 SCIPswapPointers((void**) &hashes, (void**) &hashmap->hashes);
3051 hashmap->nelements = 0;
3052
3053 /* reinsert all elements */
3054 for( i = 0; i < nslots; ++i )
3055 {
3056 /* using SCIP_CALL_ABORT since there are no allocations or duplicates
3057 * and thus no bad return codes when inserting the elements
3058 */
3059 if( hashes[i] != 0 )
3060 {
3061 SCIP_CALL_ABORT( hashmapInsert(hashmap, slots[i].origin, slots[i].image, hashes[i], FALSE) );
3062 }
3063 }
3064
3065 /* free old arrays */
3066 BMSfreeBlockMemoryArray(hashmap->blkmem, &hashes, nslots);
3067 BMSfreeBlockMemoryArray(hashmap->blkmem, &slots, nslots);
3068 }
3069
3070 return SCIP_OKAY;
3071}
3072
3073/** creates a hash map mapping pointers to pointers */
3075 SCIP_HASHMAP** hashmap, /**< pointer to store the created hash map */
3076 BMS_BLKMEM* blkmem, /**< block memory used to store hash map entries */
3077 int mapsize /**< size of the hash map */
3078 )
3079{
3080 uint32_t nslots;
3081
3082 assert(hashmap != NULL);
3083 assert(mapsize >= 0);
3084 assert(blkmem != NULL);
3085
3086 SCIP_ALLOC( BMSallocBlockMemory(blkmem, hashmap) );
3087
3088 /* dont create too small hashtables, i.e. at least size 32, and increase
3089 * the given size by divinding it by 0.9, since then no rebuilding will
3090 * be necessary if the given number of elements are inserted. Finally round
3091 * to the next power of two.
3092 */
3093 (*hashmap)->shift = 32;
3094 (*hashmap)->shift -= (unsigned int)ceil(log(MAX(32, mapsize / 0.9)) / log(2.0));
3095 nslots = 1u << (32 - (*hashmap)->shift);
3096 (*hashmap)->mask = nslots - 1;
3097 (*hashmap)->blkmem = blkmem;
3098 (*hashmap)->nelements = 0;
3099 (*hashmap)->hashmaptype = SCIP_HASHMAPTYPE_UNKNOWN;
3100
3101 SCIP_ALLOC( BMSallocBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->slots, nslots) );
3102 SCIP_ALLOC( BMSallocClearBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->hashes, nslots) );
3103
3104 return SCIP_OKAY;
3105}
3106
3107/** frees the hash map */
3109 SCIP_HASHMAP** hashmap /**< pointer to the hash map */
3110 )
3111{
3112 uint32_t nslots;
3113
3114 assert(hashmap != NULL);
3115 assert(*hashmap != NULL);
3116
3117 nslots = (*hashmap)->mask + 1;
3118#ifdef SCIP_DEBUG
3119 {
3120 uint32_t maxprobelen = 0;
3121 uint64_t probelensum = 0;
3122 uint32_t i;
3123
3124 assert(hashmap != NULL);
3125
3126 for( i = 0; i < nslots; ++i )
3127 {
3128 if( (*hashmap)->hashes[i] != 0 )
3129 {
3130 uint32_t probelen = ((i + (*hashmap)->mask + 1 - ((*hashmap)->hashes[i]>>((*hashmap)->shift))) & (*hashmap)->mask) + 1;
3131 probelensum += probelen;
3132 maxprobelen = MAX(probelen, maxprobelen);
3133 }
3134 }
3135
3136 SCIPdebugMessage("%u hash map entries, used %u/%u slots (%.1f%%)",
3137 (unsigned int)(*hashmap)->nelements, (unsigned int)(*hashmap)->nelements, (unsigned int)nslots,
3138 100.0*(SCIP_Real)(*hashmap)->nelements/(SCIP_Real)(nslots));
3139 if( (*hashmap)->nelements > 0 )
3140 SCIPdebugPrintf(", avg. probe length is %.1f, max. probe length is %u",
3141 (SCIP_Real)(probelensum)/(SCIP_Real)(*hashmap)->nelements, (unsigned int)maxprobelen);
3142 SCIPdebugPrintf("\n");
3143 }
3144#endif
3145
3146 /* free main hash map data structure */
3147 BMSfreeBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->hashes, nslots);
3148 BMSfreeBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->slots, nslots);
3149 BMSfreeBlockMemory((*hashmap)->blkmem, hashmap);
3150}
3151
3152/** inserts new origin->image pair in hash map
3153 *
3154 * @note multiple insertion of same element is checked and results in an error
3155 */
3157 SCIP_HASHMAP* hashmap, /**< hash map */
3158 void* origin, /**< origin to set image for */
3159 void* image /**< new image for origin */
3160 )
3161{
3162 uint32_t hashval;
3164
3165 assert(hashmap != NULL);
3166 assert(hashmap->slots != NULL);
3167 assert(hashmap->hashes != NULL);
3168 assert(hashmap->mask > 0);
3170
3171#ifndef NDEBUG
3172 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3174#endif
3175
3176 SCIP_CALL( hashmapCheckLoad(hashmap) );
3177
3178 /* get the hash value */
3179 hashval = hashvalue((size_t)origin);
3180
3181 /* append origin->image pair to hash map */
3182 img.ptr = image;
3183 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, FALSE) );
3184
3185 return SCIP_OKAY;
3186}
3187
3188/** inserts new origin->image pair in hash map
3189 *
3190 * @note multiple insertion of same element is checked and results in an error
3191 */
3193 SCIP_HASHMAP* hashmap, /**< hash map */
3194 void* origin, /**< origin to set image for */
3195 int image /**< new image for origin */
3196 )
3197{
3198 uint32_t hashval;
3200
3201 assert(hashmap != NULL);
3202 assert(hashmap->slots != NULL);
3203 assert(hashmap->hashes != NULL);
3204 assert(hashmap->mask > 0);
3205 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_INT);
3206
3207#ifndef NDEBUG
3208 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3210#endif
3211
3212 SCIP_CALL( hashmapCheckLoad(hashmap) );
3213
3214 /* get the hash value */
3215 hashval = hashvalue((size_t)origin);
3216
3217 /* append origin->image pair to hash map */
3218 img.integer = image;
3219 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, FALSE) );
3220
3221 return SCIP_OKAY;
3222}
3223
3224/** inserts new origin->image pair in hash map
3225 *
3226 * @note multiple insertion of same element is checked and results in an error
3227 */
3229 SCIP_HASHMAP* hashmap, /**< hash map */
3230 void* origin, /**< origin to set image for */
3231 SCIP_Real image /**< new image for origin */
3232 )
3233{
3234 uint32_t hashval;
3236
3237 assert(hashmap != NULL);
3238 assert(hashmap->slots != NULL);
3239 assert(hashmap->hashes != NULL);
3240 assert(hashmap->mask > 0);
3241 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_REAL);
3242
3243#ifndef NDEBUG
3244 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3246#endif
3247
3248 SCIP_CALL( hashmapCheckLoad(hashmap) );
3249
3250 /* get the hash value */
3251 hashval = hashvalue((size_t)origin);
3252
3253 /* append origin->image pair to hash map */
3254 img.real = image;
3255 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, FALSE) );
3256
3257 return SCIP_OKAY;
3258}
3259
3260/** retrieves image of given origin from the hash map, or NULL if no image exists */
3262 SCIP_HASHMAP* hashmap, /**< hash map */
3263 void* origin /**< origin to retrieve image for */
3264 )
3265{
3266 uint32_t pos;
3267
3268 assert(hashmap != NULL);
3269 assert(hashmap->slots != NULL);
3270 assert(hashmap->hashes != NULL);
3271 assert(hashmap->mask > 0);
3273
3274 if( hashmapLookup(hashmap, origin, &pos) )
3275 return hashmap->slots[pos].image.ptr;
3276
3277 return NULL;
3278}
3279
3280/** retrieves image of given origin from the hash map, or INT_MAX if no image exists */
3282 SCIP_HASHMAP* hashmap, /**< hash map */
3283 void* origin /**< origin to retrieve image for */
3284 )
3285{
3286 uint32_t pos;
3287
3288 assert(hashmap != NULL);
3289 assert(hashmap->slots != NULL);
3290 assert(hashmap->hashes != NULL);
3291 assert(hashmap->mask > 0);
3292 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_INT);
3293
3294 if( hashmapLookup(hashmap, origin, &pos) )
3295 return hashmap->slots[pos].image.integer;
3296
3297 return INT_MAX;
3298}
3299
3300/** retrieves image of given origin from the hash map, or SCIP_INVALID if no image exists */
3302 SCIP_HASHMAP* hashmap, /**< hash map */
3303 void* origin /**< origin to retrieve image for */
3304 )
3305{
3306 uint32_t pos;
3307
3308 assert(hashmap != NULL);
3309 assert(hashmap->slots != NULL);
3310 assert(hashmap->hashes != NULL);
3311 assert(hashmap->mask > 0);
3312 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_REAL);
3313
3314 if( hashmapLookup(hashmap, origin, &pos) )
3315 return hashmap->slots[pos].image.real;
3316
3317 return SCIP_INVALID;
3318}
3319
3320/** sets image for given origin in the hash map, either by modifying existing origin->image pair
3321 * or by appending a new origin->image pair
3322 */
3324 SCIP_HASHMAP* hashmap, /**< hash map */
3325 void* origin, /**< origin to set image for */
3326 void* image /**< new image for origin */
3327 )
3328{
3329 uint32_t hashval;
3331
3332 assert(hashmap != NULL);
3333 assert(hashmap->slots != NULL);
3334 assert(hashmap->mask > 0);
3336
3337#ifndef NDEBUG
3338 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3340#endif
3341
3342 SCIP_CALL( hashmapCheckLoad(hashmap) );
3343
3344 /* get the hash value */
3345 hashval = hashvalue((size_t)origin);
3346
3347 /* append origin->image pair to hash map */
3348 img.ptr = image;
3349 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, TRUE) );
3350
3351 return SCIP_OKAY;
3352}
3353
3354/** sets image for given origin in the hash map, either by modifying existing origin->image pair
3355 * or by appending a new origin->image pair
3356 */
3358 SCIP_HASHMAP* hashmap, /**< hash map */
3359 void* origin, /**< origin to set image for */
3360 int image /**< new image for origin */
3361 )
3362{
3363 uint32_t hashval;
3365
3366 assert(hashmap != NULL);
3367 assert(hashmap->slots != NULL);
3368 assert(hashmap->mask > 0);
3369 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_INT);
3370
3371#ifndef NDEBUG
3372 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3374#endif
3375
3376 SCIP_CALL( hashmapCheckLoad(hashmap) );
3377
3378 /* get the hash value */
3379 hashval = hashvalue((size_t)origin);
3380
3381 /* append origin->image pair to hash map */
3382 img.integer = image;
3383 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, TRUE) );
3384
3385 return SCIP_OKAY;
3386}
3387
3388/** sets image for given origin in the hash map, either by modifying existing origin->image pair
3389 * or by appending a new origin->image pair
3390 */
3392 SCIP_HASHMAP* hashmap, /**< hash map */
3393 void* origin, /**< origin to set image for */
3394 SCIP_Real image /**< new image for origin */
3395 )
3396{
3397 uint32_t hashval;
3399
3400 assert(hashmap != NULL);
3401 assert(hashmap->slots != NULL);
3402 assert(hashmap->mask > 0);
3403 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_REAL);
3404
3405#ifndef NDEBUG
3406 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3408#endif
3409
3410 SCIP_CALL( hashmapCheckLoad(hashmap) );
3411
3412 /* get the hash value */
3413 hashval = hashvalue((size_t)origin);
3414
3415 /* append origin->image pair to hash map */
3416 img.real = image;
3417 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, TRUE) );
3418
3419 return SCIP_OKAY;
3420}
3421
3422/** checks whether an image to the given origin exists in the hash map */
3424 SCIP_HASHMAP* hashmap, /**< hash map */
3425 void* origin /**< origin to search for */
3426 )
3427{
3428 uint32_t pos;
3429
3430 assert(hashmap != NULL);
3431 assert(hashmap->slots != NULL);
3432 assert(hashmap->hashes != NULL);
3433 assert(hashmap->mask > 0);
3434
3435 return hashmapLookup(hashmap, origin, &pos);
3436}
3437
3438/** removes origin->image pair from the hash map, if it exists */
3440 SCIP_HASHMAP* hashmap, /**< hash map */
3441 void* origin /**< origin to remove from the list */
3442 )
3443{
3444 uint32_t pos;
3445
3446 assert(hashmap != NULL);
3447 assert(hashmap->slots != NULL);
3448 assert(hashmap->mask > 0);
3449
3450 assert(origin != NULL);
3451
3452 if( hashmapLookup(hashmap, origin, &pos) )
3453 {
3454 /* remove element */
3455 hashmap->hashes[pos] = 0;
3456 --hashmap->nelements;
3457
3458 /* move other elements if necessary */
3459 while( TRUE ) /*lint !e716*/
3460 {
3461 uint32_t nextpos = (pos + 1) & hashmap->mask;
3462
3463 /* nothing to do since there is no chain that needs to be moved */
3464 if( hashmap->hashes[nextpos] == 0 )
3465 return SCIP_OKAY;
3466
3467 /* check if the element is the start of a new chain and return if that is the case */
3468 if( (hashmap->hashes[nextpos]>>(hashmap->shift)) == nextpos )
3469 return SCIP_OKAY;
3470
3471 /* element should be moved to the left and next element needs to be checked */
3472 hashmap->slots[pos].origin = hashmap->slots[nextpos].origin;
3473 hashmap->slots[pos].image = hashmap->slots[nextpos].image;
3474 hashmap->hashes[pos] = hashmap->hashes[nextpos];
3475 hashmap->hashes[nextpos] = 0;
3476
3477 pos = nextpos;
3478 }
3479 }
3480
3481 return SCIP_OKAY;
3482}
3483
3484/** prints statistics about hash map usage */
3486 SCIP_HASHMAP* hashmap, /**< hash map */
3487 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
3488 )
3489{
3490 uint32_t maxprobelen = 0;
3491 uint64_t probelensum = 0;
3492 uint32_t nslots;
3493 uint32_t i;
3494
3495 assert(hashmap != NULL);
3496
3497 nslots = hashmap->mask + 1;
3498
3499 /* compute the maximum and average probe length */
3500 for( i = 0; i < nslots; ++i )
3501 {
3502 if( hashmap->hashes[i] != 0 )
3503 {
3504 uint32_t probelen = ELEM_DISTANCE(i) + 1;
3505 probelensum += probelen;
3506 maxprobelen = MAX(probelen, maxprobelen);
3507 }
3508 }
3509
3510 /* print general hash map statistics */
3511 SCIPmessagePrintInfo(messagehdlr, "%u hash entries, used %u/%u slots (%.1f%%)",
3512 (unsigned int)hashmap->nelements, (unsigned int)hashmap->nelements,
3513 (unsigned int)nslots, 100.0*(SCIP_Real)hashmap->nelements/(SCIP_Real)(nslots));
3514
3515 /* if not empty print average and maximum probe length */
3516 if( hashmap->nelements > 0 )
3517 SCIPmessagePrintInfo(messagehdlr, ", avg. probe length is %.1f, max. probe length is %u",
3518 (SCIP_Real)(probelensum)/(SCIP_Real)hashmap->nelements, (unsigned int)maxprobelen);
3519 SCIPmessagePrintInfo(messagehdlr, "\n");
3520}
3521
3522/** indicates whether a hash map has no entries */
3524 SCIP_HASHMAP* hashmap /**< hash map */
3525 )
3526{
3527 assert(hashmap != NULL);
3528
3529 return hashmap->nelements == 0;
3530}
3531
3532/** gives the number of elements in a hash map */
3534 SCIP_HASHMAP* hashmap /**< hash map */
3535 )
3536{
3537 return (int) hashmap->nelements;
3538}
3539
3540/** gives the number of entries in the internal arrays of a hash map */
3542 SCIP_HASHMAP* hashmap /**< hash map */
3543 )
3544{
3545 return (int) hashmap->mask + 1;
3546}
3547
3548/** gives the hashmap entry at the given index or NULL if entry is empty */
3550 SCIP_HASHMAP* hashmap, /**< hash map */
3551 int entryidx /**< index of hash map entry */
3552 )
3553{
3554 assert(hashmap != NULL);
3555
3556 return hashmap->hashes[entryidx] == 0 ? NULL : &hashmap->slots[entryidx];
3557}
3558
3559/** gives the origin of the hashmap entry */
3561 SCIP_HASHMAPENTRY* entry /**< hash map entry */
3562 )
3563{
3564 assert(entry != NULL);
3565
3566 return entry->origin;
3567}
3568
3569/** gives the image of the hashmap entry */
3571 SCIP_HASHMAPENTRY* entry /**< hash map entry */
3572 )
3573{
3574 assert(entry != NULL);
3575
3576 return entry->image.ptr;
3577}
3578
3579/** gives the image of the hashmap entry */
3581 SCIP_HASHMAPENTRY* entry /**< hash map entry */
3582 )
3583{
3584 assert(entry != NULL);
3585
3586 return entry->image.integer;
3587}
3588
3589/** gives the image of the hashmap entry */
3591 SCIP_HASHMAPENTRY* entry /**< hash map entry */
3592 )
3593{
3594 assert(entry != NULL);
3595
3596 return entry->image.real;
3597}
3598
3599/** sets pointer image of a hashmap entry */
3601 SCIP_HASHMAPENTRY* entry, /**< hash map entry */
3602 void* image /**< new image */
3603 )
3604{
3605 assert(entry != NULL);
3606
3607 entry->image.ptr = image;
3608}
3609
3610/** sets integer image of a hashmap entry */
3612 SCIP_HASHMAPENTRY* entry, /**< hash map entry */
3613 int image /**< new image */
3614 )
3615{
3616 assert(entry != NULL);
3617
3618 entry->image.integer = image;
3619}
3620
3621/** sets real image of a hashmap entry */
3623 SCIP_HASHMAPENTRY* entry, /**< hash map entry */
3624 SCIP_Real image /**< new image */
3625 )
3626{
3627 assert(entry != NULL);
3628
3629 entry->image.real = image;
3630}
3631
3632/** removes all entries in a hash map. */
3634 SCIP_HASHMAP* hashmap /**< hash map */
3635 )
3636{
3637 assert(hashmap != NULL);
3638
3639 BMSclearMemoryArray(hashmap->hashes, hashmap->mask + 1);
3640
3641 hashmap->nelements = 0;
3642
3643 return SCIP_OKAY;
3644}
3645
3646
3647/*
3648 * Hash Set
3649 */
3650
3651/* redefine ELEM_DISTANCE macro for hashset */
3652#undef ELEM_DISTANCE
3653/* computes the distance from it's desired position for the element stored at pos */
3654#define ELEM_DISTANCE(pos) (((pos) + nslots - hashSetDesiredPos(hashset, hashset->slots[(pos)])) & mask)
3655
3656/* calculate desired position of element in hash set */
3657static
3659 SCIP_HASHSET* hashset, /**< the hash set */
3660 void* element /**< element to calculate position for */
3661 )
3662{
3663 return (uint32_t)((UINT64_C(0x9e3779b97f4a7c15) * (uintptr_t)element)>>(hashset->shift));
3664}
3665
3666static
3668 SCIP_HASHSET* hashset, /**< hash set */
3669 void* element /**< element to insert */
3670 )
3671{
3672 uint32_t elemdistance;
3673 uint32_t pos;
3674 uint32_t nslots;
3675 uint32_t mask;
3676
3677 assert(hashset != NULL);
3678 assert(hashset->slots != NULL);
3679 assert(element != NULL);
3680
3681 pos = hashSetDesiredPos(hashset, element);
3682 nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3683 mask = nslots - 1;
3684
3685 elemdistance = 0;
3686 while( TRUE ) /*lint !e716*/
3687 {
3688 uint32_t distance;
3689
3690 /* if position is empty or key equal insert element */
3691 if( hashset->slots[pos] == NULL )
3692 {
3693 hashset->slots[pos] = element;
3694 ++hashset->nelements;
3695 return;
3696 }
3697
3698 if( hashset->slots[pos] == element )
3699 return;
3700
3701 /* otherwise check if the current element at this position is closer to its hashvalue */
3702 distance = ELEM_DISTANCE(pos);
3703 if( distance < elemdistance )
3704 {
3705 /* if this is the case we insert the new element here and find a new position for the old one */
3706 elemdistance = distance;
3707 SCIPswapPointers(&hashset->slots[pos], &element);
3708 }
3709
3710 /* continue until we have found an empty position */
3711 pos = (pos + 1) & mask;
3712 ++elemdistance;
3713 }
3714}
3715
3716/** check if the load factor of the hash set is too high and rebuild if necessary */
3717static
3719 SCIP_HASHSET* hashset, /**< hash set */
3720 BMS_BLKMEM* blkmem /**< block memory used to store hash set entries */
3721 )
3722{
3723 assert(hashset != NULL);
3724 assert(hashset->shift < 64);
3725
3726 /* use integer arithmetic to approximately check if load factor is above 90% */
3727 if( ((((uint64_t)hashset->nelements)<<10)>>(64-hashset->shift) > 921) )
3728 {
3729 void** slots;
3730 uint32_t nslots;
3731 uint32_t newnslots;
3732 uint32_t i;
3733
3734 /* calculate new size (always power of two) */
3735 nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3736 newnslots = 2*nslots;
3737 --hashset->shift;
3738
3739 /* reallocate array */
3740 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &slots, newnslots) );
3741
3742 SCIPswapPointers((void**) &slots, (void**) &hashset->slots);
3743 hashset->nelements = 0;
3744
3745 /* reinsert all elements */
3746 for( i = 0; i < nslots; ++i )
3747 {
3748 if( slots[i] != NULL )
3749 hashsetInsert(hashset, slots[i]);
3750 }
3751
3752 BMSfreeBlockMemoryArray(blkmem, &slots, nslots);
3753 }
3754
3755 return SCIP_OKAY;
3756}
3757
3758/** creates a hash set of pointers */
3760 SCIP_HASHSET** hashset, /**< pointer to store the created hash set */
3761 BMS_BLKMEM* blkmem, /**< block memory used to store hash set entries */
3762 int size /**< initial size of the hash set; it is guaranteed that the set is not
3763 * resized if at most that many elements are inserted */
3764 )
3765{
3766 uint32_t nslots;
3767
3768 assert(hashset != NULL);
3769 assert(size >= 0);
3770 assert(blkmem != NULL);
3771
3772 SCIP_ALLOC( BMSallocBlockMemory(blkmem, hashset) );
3773
3774 /* do not create too small hashtables, i.e. at least size 32, and increase
3775 * the given size by dividing it by 0.9, since then no rebuilding will
3776 * be necessary if the given number of elements are inserted. Finally round
3777 * to the next power of two.
3778 */
3779 (*hashset)->shift = 64;
3780 (*hashset)->shift -= (unsigned int)ceil(log(MAX(8.0, size / 0.9)) / log(2.0));
3781 nslots = (uint32_t)SCIPhashsetGetNSlots(*hashset);
3782 (*hashset)->nelements = 0;
3783
3784 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*hashset)->slots, nslots) );
3785
3786 return SCIP_OKAY;
3787}
3788
3789/** frees the hash set */
3791 SCIP_HASHSET** hashset, /**< pointer to the hash set */
3792 BMS_BLKMEM* blkmem /**< block memory used to store hash set entries */
3793 )
3794{
3795 BMSfreeBlockMemoryArray(blkmem, &(*hashset)->slots, SCIPhashsetGetNSlots(*hashset));
3796 BMSfreeBlockMemory(blkmem, hashset);
3797}
3798
3799/** inserts new element into the hash set */
3801 SCIP_HASHSET* hashset, /**< hash set */
3802 BMS_BLKMEM* blkmem, /**< block memory used to store hash set entries */
3803 void* element /**< element to insert */
3804 )
3805{
3806 assert(hashset != NULL);
3807 assert(hashset->slots != NULL);
3808
3809 SCIP_CALL( hashsetCheckLoad(hashset, blkmem) );
3810
3811 hashsetInsert(hashset, element);
3812
3813 return SCIP_OKAY;
3814}
3815
3816/** checks whether an element exists in the hash set */
3818 SCIP_HASHSET* hashset, /**< hash set */
3819 void* element /**< element to search for */
3820 )
3821{
3822 uint32_t pos;
3823 uint32_t nslots;
3824 uint32_t mask;
3825 uint32_t elemdistance;
3826
3827 assert(hashset != NULL);
3828 assert(hashset->slots != NULL);
3829
3830 pos = hashSetDesiredPos(hashset, element);
3831 nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3832 mask = nslots - 1;
3833 elemdistance = 0;
3834
3835 while( TRUE ) /*lint !e716*/
3836 {
3837 uint32_t distance;
3838
3839 /* found element */
3840 if( hashset->slots[pos] == element )
3841 return TRUE;
3842
3843 /* slots is empty so element cannot be contained */
3844 if( hashset->slots[pos] == NULL )
3845 return FALSE;
3846
3847 distance = ELEM_DISTANCE(pos);
3848 /* element can not be contained since otherwise we would have swapped it with this one during insert */
3849 if( elemdistance > distance )
3850 return FALSE;
3851
3852 pos = (pos + 1) & mask;
3853 ++elemdistance;
3854 }
3855}
3856
3857/** removes an element from the hash set, if it exists */
3859 SCIP_HASHSET* hashset, /**< hash set */
3860 void* element /**< origin to remove from the list */
3861 )
3862{
3863 uint32_t pos;
3864 uint32_t nslots;
3865 uint32_t mask;
3866 uint32_t elemdistance;
3867
3868 assert(hashset != NULL);
3869 assert(hashset->slots != NULL);
3870 assert(element != NULL);
3871
3872 pos = hashSetDesiredPos(hashset, element);
3873 nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3874 mask = nslots - 1;
3875 elemdistance = 0;
3876
3877 while( TRUE ) /*lint !e716*/
3878 {
3879 uint32_t distance;
3880
3881 /* found element */
3882 if( hashset->slots[pos] == element )
3883 break;
3884
3885 /* slots is empty so element cannot be contained */
3886 if( hashset->slots[pos] == NULL )
3887 return SCIP_OKAY;
3888
3889 distance = ELEM_DISTANCE(pos);
3890 /* element can not be contained since otherwise we would have swapped it with this one during insert */
3891 if( elemdistance > distance )
3892 return SCIP_OKAY;
3893
3894 pos = (pos + 1) & mask;
3895 ++elemdistance;
3896 }
3897
3898 assert(hashset->slots[pos] == element);
3899 assert(SCIPhashsetExists(hashset, element));
3900
3901 /* remove element */
3902 --hashset->nelements;
3903
3904 /* move other elements if necessary */
3905 while( TRUE ) /*lint !e716*/
3906 {
3907 uint32_t nextpos = (pos + 1) & mask;
3908
3909 /* nothing to do since there is no chain that needs to be moved */
3910 if( hashset->slots[nextpos] == NULL )
3911 {
3912 hashset->slots[pos] = NULL;
3913 assert(!SCIPhashsetExists(hashset, element));
3914 return SCIP_OKAY;
3915 }
3916
3917 /* check if the element is the start of a new chain and return if that is the case */
3918 if( hashSetDesiredPos(hashset, hashset->slots[nextpos]) == nextpos )
3919 {
3920 hashset->slots[pos] = NULL;
3921 assert(!SCIPhashsetExists(hashset, element));
3922 return SCIP_OKAY;
3923 }
3924
3925 /* element should be moved to the left and next element needs to be checked */
3926 hashset->slots[pos] = hashset->slots[nextpos];
3927
3928 pos = nextpos;
3929 }
3930}
3931
3932/** prints statistics about hash set usage */
3934 SCIP_HASHSET* hashset, /**< hash set */
3935 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
3936 )
3937{
3938 uint32_t maxprobelen = 0;
3939 uint64_t probelensum = 0;
3940 uint32_t nslots;
3941 uint32_t mask;
3942 uint32_t i;
3943
3944 assert(hashset != NULL);
3945
3946 nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3947 mask = nslots - 1;
3948
3949 /* compute the maximum and average probe length */
3950 for( i = 0; i < nslots; ++i )
3951 {
3952 if( hashset->slots[i] != NULL )
3953 {
3954 uint32_t probelen = ((hashSetDesiredPos(hashset, hashset->slots[i]) + nslots - i) & mask) + 1;
3955 probelensum += probelen;
3956 maxprobelen = MAX(probelen, maxprobelen);
3957 }
3958 }
3959
3960 /* print general hash set statistics */
3961 SCIPmessagePrintInfo(messagehdlr, "%u hash entries, used %u/%u slots (%.1f%%)",
3962 (unsigned int)hashset->nelements, (unsigned int)hashset->nelements,
3963 (unsigned int)nslots, 100.0*(SCIP_Real)hashset->nelements/(SCIP_Real)(nslots));
3964
3965 /* if not empty print average and maximum probe length */
3966 if( hashset->nelements > 0 )
3967 SCIPmessagePrintInfo(messagehdlr, ", avg. probe length is %.1f, max. probe length is %u",
3968 (SCIP_Real)(probelensum)/(SCIP_Real)hashset->nelements, (unsigned int)maxprobelen);
3969 SCIPmessagePrintInfo(messagehdlr, "\n");
3970}
3971
3972/* In debug mode, the following methods are implemented as function calls to ensure
3973 * type validity.
3974 * In optimized mode, the methods are implemented as defines to improve performance.
3975 * However, we want to have them in the library anyways, so we have to undef the defines.
3976 */
3977
3978#undef SCIPhashsetIsEmpty
3979#undef SCIPhashsetGetNElements
3980#undef SCIPhashsetGetNSlots
3981#undef SCIPhashsetGetSlots
3982
3983/** indicates whether a hash set has no entries */
3985 SCIP_HASHSET* hashset /**< hash set */
3986 )
3987{
3988 return hashset->nelements == 0;
3989}
3990
3991/** gives the number of elements in a hash set */
3993 SCIP_HASHSET* hashset /**< hash set */
3994 )
3995{
3996 return (int)hashset->nelements;
3997}
3998
3999/** gives the number of slots of a hash set */
4001 SCIP_HASHSET* hashset /**< hash set */
4002 )
4003{
4004 return (int) (1u << (64 - hashset->shift));
4005}
4006
4007/** gives the array of hash set slots; contains all elements in indetermined order and may contain NULL values */
4009 SCIP_HASHSET* hashset /**< hash set */
4010 )
4011{
4012 return hashset->slots;
4013}
4014
4015/** removes all entries in a hash set. */
4017 SCIP_HASHSET* hashset /**< hash set */
4018 )
4019{
4021
4022 hashset->nelements = 0;
4023}
4024
4025/*
4026 * Dynamic Arrays
4027 */
4028
4029/** creates a dynamic array of real values */
4031 SCIP_REALARRAY** realarray, /**< pointer to store the real array */
4032 BMS_BLKMEM* blkmem /**< block memory */
4033 )
4034{
4035 assert(realarray != NULL);
4036 assert(blkmem != NULL);
4037
4038 SCIP_ALLOC( BMSallocBlockMemory(blkmem, realarray) );
4039 (*realarray)->blkmem = blkmem;
4040 (*realarray)->vals = NULL;
4041 (*realarray)->valssize = 0;
4042 (*realarray)->firstidx = -1;
4043 (*realarray)->minusedidx = INT_MAX;
4044 (*realarray)->maxusedidx = INT_MIN;
4045
4046 return SCIP_OKAY;
4047}
4048
4049/** creates a copy of a dynamic array of real values */
4051 SCIP_REALARRAY** realarray, /**< pointer to store the copied real array */
4052 BMS_BLKMEM* blkmem, /**< block memory */
4053 SCIP_REALARRAY* sourcerealarray /**< dynamic real array to copy */
4054 )
4055{
4056 assert(realarray != NULL);
4057 assert(sourcerealarray != NULL);
4058
4059 SCIP_CALL( SCIPrealarrayCreate(realarray, blkmem) );
4060 if( sourcerealarray->valssize > 0 )
4061 {
4062 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*realarray)->vals, sourcerealarray->vals, \
4063 sourcerealarray->valssize) );
4064 }
4065 (*realarray)->valssize = sourcerealarray->valssize;
4066 (*realarray)->firstidx = sourcerealarray->firstidx;
4067 (*realarray)->minusedidx = sourcerealarray->minusedidx;
4068 (*realarray)->maxusedidx = sourcerealarray->maxusedidx;
4069
4070 return SCIP_OKAY;
4071}
4072
4073/** frees a dynamic array of real values */
4075 SCIP_REALARRAY** realarray /**< pointer to the real array */
4076 )
4077{
4078 assert(realarray != NULL);
4079 assert(*realarray != NULL);
4080
4081 BMSfreeBlockMemoryArrayNull((*realarray)->blkmem, &(*realarray)->vals, (*realarray)->valssize);
4082 BMSfreeBlockMemory((*realarray)->blkmem, realarray);
4083
4084 return SCIP_OKAY;
4085}
4086
4087/** extends dynamic array to be able to store indices from minidx to maxidx */
4089 SCIP_REALARRAY* realarray, /**< dynamic real array */
4090 int arraygrowinit, /**< initial size of array */
4091 SCIP_Real arraygrowfac, /**< growing factor of array */
4092 int minidx, /**< smallest index to allocate storage for */
4093 int maxidx /**< largest index to allocate storage for */
4094 )
4095{
4096 int nused;
4097 int nfree;
4098 int newfirstidx;
4099 int i;
4100
4101 assert(realarray != NULL);
4102 assert(realarray->minusedidx == INT_MAX || realarray->firstidx >= 0);
4103 assert(realarray->maxusedidx == INT_MIN || realarray->firstidx >= 0);
4104 assert(realarray->minusedidx == INT_MAX || realarray->minusedidx >= realarray->firstidx);
4105 assert(realarray->maxusedidx == INT_MIN || realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4106 assert(0 <= minidx);
4107 assert(minidx <= maxidx);
4108
4109 minidx = MIN(minidx, realarray->minusedidx);
4110 maxidx = MAX(maxidx, realarray->maxusedidx);
4111 assert(0 <= minidx);
4112 assert(minidx <= maxidx);
4113
4114 SCIPdebugMessage("extending realarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
4115 (void*)realarray, realarray->firstidx, realarray->valssize, realarray->minusedidx, realarray->maxusedidx, minidx, maxidx);
4116
4117 /* check, whether we have to allocate additional memory, or shift the array */
4118 nused = maxidx - minidx + 1;
4119 if( nused > realarray->valssize )
4120 {
4121 SCIP_Real* newvals;
4122 int newvalssize;
4123
4124 /* allocate new memory storage */
4125 newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
4126 SCIP_ALLOC( BMSallocBlockMemoryArray(realarray->blkmem, &newvals, newvalssize) );
4127 nfree = newvalssize - nused;
4128 newfirstidx = minidx - nfree/2;
4129 newfirstidx = MAX(newfirstidx, 0);
4130 assert(newfirstidx <= minidx);
4131 assert(maxidx < newfirstidx + newvalssize);
4132
4133 /* initialize memory array by copying old values and setting new values to zero */
4134 if( realarray->firstidx != -1 )
4135 {
4136 for( i = 0; i < realarray->minusedidx - newfirstidx; ++i )
4137 newvals[i] = 0.0;
4138
4139 /* check for possible overflow or negative value */
4140 assert(realarray->maxusedidx - realarray->minusedidx + 1 > 0);
4141
4142 BMScopyMemoryArray(&newvals[realarray->minusedidx - newfirstidx],
4143 &(realarray->vals[realarray->minusedidx - realarray->firstidx]),
4144 realarray->maxusedidx - realarray->minusedidx + 1); /*lint !e866 !e776*/
4145 for( i = realarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
4146 newvals[i] = 0.0;
4147 }
4148 else
4149 {
4150 for( i = 0; i < newvalssize; ++i )
4151 newvals[i] = 0.0;
4152 }
4153
4154 /* free old memory storage, and set the new array parameters */
4155 BMSfreeBlockMemoryArrayNull(realarray->blkmem, &realarray->vals, realarray->valssize);
4156 realarray->vals = newvals;
4157 realarray->valssize = newvalssize;
4158 realarray->firstidx = newfirstidx;
4159 }
4160 else if( realarray->firstidx == -1 )
4161 {
4162 /* a sufficiently large memory storage exists, but it was cleared */
4163 nfree = realarray->valssize - nused;
4164 assert(nfree >= 0);
4165 realarray->firstidx = minidx - nfree/2;
4166 assert(realarray->firstidx <= minidx);
4167 assert(maxidx < realarray->firstidx + realarray->valssize);
4168#ifndef NDEBUG
4169 for( i = 0; i < realarray->valssize; ++i )
4170 assert(realarray->vals[i] == 0.0);
4171#endif
4172 }
4173 else if( minidx < realarray->firstidx )
4174 {
4175 /* a sufficiently large memory storage exists, but it has to be shifted to the right */
4176 nfree = realarray->valssize - nused;
4177 assert(nfree >= 0);
4178 newfirstidx = minidx - nfree/2;
4179 newfirstidx = MAX(newfirstidx, 0);
4180 assert(newfirstidx <= minidx);
4181 assert(maxidx < newfirstidx + realarray->valssize);
4182
4183 if( realarray->minusedidx <= realarray->maxusedidx )
4184 {
4185 int shift;
4186
4187 assert(realarray->firstidx <= realarray->minusedidx);
4188 assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4189
4190 /* shift used part of array to the right */
4191 shift = realarray->firstidx - newfirstidx;
4192 assert(shift > 0);
4193 for( i = realarray->maxusedidx - realarray->firstidx; i >= realarray->minusedidx - realarray->firstidx; --i )
4194 {
4195 assert(0 <= i + shift && i + shift < realarray->valssize);
4196 realarray->vals[i + shift] = realarray->vals[i];
4197 }
4198 /* clear the formerly used head of the array */
4199 for( i = 0; i < shift; ++i )
4200 realarray->vals[realarray->minusedidx - realarray->firstidx + i] = 0.0;
4201 }
4202 realarray->firstidx = newfirstidx;
4203 }
4204 else if( maxidx >= realarray->firstidx + realarray->valssize )
4205 {
4206 /* a sufficiently large memory storage exists, but it has to be shifted to the left */
4207 nfree = realarray->valssize - nused;
4208 assert(nfree >= 0);
4209 newfirstidx = minidx - nfree/2;
4210 newfirstidx = MAX(newfirstidx, 0);
4211 assert(newfirstidx <= minidx);
4212 assert(maxidx < newfirstidx + realarray->valssize);
4213
4214 if( realarray->minusedidx <= realarray->maxusedidx )
4215 {
4216 int shift;
4217
4218 assert(realarray->firstidx <= realarray->minusedidx);
4219 assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4220
4221 /* shift used part of array to the left */
4222 shift = newfirstidx - realarray->firstidx;
4223 assert(shift > 0);
4224 for( i = realarray->minusedidx - realarray->firstidx; i <= realarray->maxusedidx - realarray->firstidx; ++i )
4225 {
4226 assert(0 <= i - shift && i - shift < realarray->valssize);
4227 realarray->vals[i - shift] = realarray->vals[i];
4228 }
4229 /* clear the formerly used tail of the array */
4230 for( i = 0; i < shift; ++i )
4231 realarray->vals[realarray->maxusedidx - realarray->firstidx - i] = 0.0;
4232 }
4233 realarray->firstidx = newfirstidx;
4234 }
4235
4236 assert(minidx >= realarray->firstidx);
4237 assert(maxidx < realarray->firstidx + realarray->valssize);
4238
4239 return SCIP_OKAY;
4240}
4241
4242/** clears a dynamic real array */
4244 SCIP_REALARRAY* realarray /**< dynamic real array */
4245 )
4246{
4247 assert(realarray != NULL);
4248
4249 SCIPdebugMessage("clearing realarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
4250 (void*)realarray, realarray->firstidx, realarray->valssize, realarray->minusedidx, realarray->maxusedidx);
4251
4252 if( realarray->minusedidx <= realarray->maxusedidx )
4253 {
4254 assert(realarray->firstidx <= realarray->minusedidx);
4255 assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4256 assert(realarray->firstidx != -1);
4257 assert(realarray->valssize > 0);
4258
4259 /* clear the used part of array */
4260 BMSclearMemoryArray(&realarray->vals[realarray->minusedidx - realarray->firstidx],
4261 realarray->maxusedidx - realarray->minusedidx + 1); /*lint !e866*/
4262
4263 /* mark the array cleared */
4264 realarray->minusedidx = INT_MAX;
4265 realarray->maxusedidx = INT_MIN;
4266 }
4267 assert(realarray->minusedidx == INT_MAX);
4268 assert(realarray->maxusedidx == INT_MIN);
4269
4270 return SCIP_OKAY;
4271}
4272
4273/** gets value of entry in dynamic array */
4275 SCIP_REALARRAY* realarray, /**< dynamic real array */
4276 int idx /**< array index to get value for */
4277 )
4278{
4279 assert(realarray != NULL);
4280 assert(idx >= 0);
4281
4282 if( idx < realarray->minusedidx || idx > realarray->maxusedidx )
4283 return 0.0;
4284 else
4285 {
4286 assert(realarray->vals != NULL);
4287 assert(idx - realarray->firstidx >= 0);
4288 assert(idx - realarray->firstidx < realarray->valssize);
4289
4290 return realarray->vals[idx - realarray->firstidx];
4291 }
4292}
4293
4294/** sets value of entry in dynamic array */
4296 SCIP_REALARRAY* realarray, /**< dynamic real array */
4297 int arraygrowinit, /**< initial size of array */
4298 SCIP_Real arraygrowfac, /**< growing factor of array */
4299 int idx, /**< array index to set value for */
4300 SCIP_Real val /**< value to set array index to */
4301 )
4302{
4303 assert(realarray != NULL);
4304 assert(idx >= 0);
4305
4306 SCIPdebugMessage("setting realarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %g\n",
4307 (void*)realarray, realarray->firstidx, realarray->valssize, realarray->minusedidx, realarray->maxusedidx, idx, val);
4308
4309 if( val != 0.0 )
4310 {
4311 /* extend array to be able to store the index */
4312 SCIP_CALL( SCIPrealarrayExtend(realarray, arraygrowinit, arraygrowfac, idx, idx) );
4313 assert(idx >= realarray->firstidx);
4314 assert(idx < realarray->firstidx + realarray->valssize);
4315
4316 /* set the array value of the index */
4317 realarray->vals[idx - realarray->firstidx] = val;
4318
4319 /* update min/maxusedidx */
4320 realarray->minusedidx = MIN(realarray->minusedidx, idx);
4321 realarray->maxusedidx = MAX(realarray->maxusedidx, idx);
4322 }
4323 else if( idx >= realarray->firstidx && idx < realarray->firstidx + realarray->valssize )
4324 {
4325 /* set the array value of the index to zero */
4326 realarray->vals[idx - realarray->firstidx] = 0.0;
4327
4328 /* check, if we can tighten the min/maxusedidx */
4329 if( idx == realarray->minusedidx )
4330 {
4331 assert(realarray->maxusedidx >= 0);
4332 assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4333 do
4334 {
4335 realarray->minusedidx++;
4336 }
4337 while( realarray->minusedidx <= realarray->maxusedidx
4338 && realarray->vals[realarray->minusedidx - realarray->firstidx] == 0.0 );
4339
4340 if( realarray->minusedidx > realarray->maxusedidx )
4341 {
4342 realarray->minusedidx = INT_MAX;
4343 realarray->maxusedidx = INT_MIN;
4344 }
4345 }
4346 else if( idx == realarray->maxusedidx )
4347 {
4348 assert(realarray->minusedidx >= 0);
4349 assert(realarray->minusedidx < realarray->maxusedidx);
4350 assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4351 do
4352 {
4353 realarray->maxusedidx--;
4354 assert(realarray->minusedidx <= realarray->maxusedidx);
4355 }
4356 while( realarray->vals[realarray->maxusedidx - realarray->firstidx] == 0.0 );
4357 }
4358 }
4359
4360 return SCIP_OKAY;
4361}
4362
4363/** increases value of entry in dynamic array */
4365 SCIP_REALARRAY* realarray, /**< dynamic real array */
4366 int arraygrowinit, /**< initial size of array */
4367 SCIP_Real arraygrowfac, /**< growing factor of array */
4368 int idx, /**< array index to increase value for */
4369 SCIP_Real incval /**< value to increase array index */
4370 )
4371{
4372 SCIP_Real oldval;
4373
4374 oldval = SCIPrealarrayGetVal(realarray, idx);
4375 if( oldval != SCIP_INVALID ) /*lint !e777*/
4376 return SCIPrealarraySetVal(realarray, arraygrowinit, arraygrowfac, idx, oldval + incval);
4377 else
4378 return SCIP_OKAY;
4379}
4380
4381/** returns the minimal index of all stored non-zero elements */
4383 SCIP_REALARRAY* realarray /**< dynamic real array */
4384 )
4385{
4386 assert(realarray != NULL);
4387
4388 return realarray->minusedidx;
4389}
4390
4391/** returns the maximal index of all stored non-zero elements */
4393 SCIP_REALARRAY* realarray /**< dynamic real array */
4394 )
4395{
4396 assert(realarray != NULL);
4397
4398 return realarray->maxusedidx;
4399}
4400
4401/** creates a dynamic array of int values */
4403 SCIP_INTARRAY** intarray, /**< pointer to store the int array */
4404 BMS_BLKMEM* blkmem /**< block memory */
4405 )
4406{
4407 assert(intarray != NULL);
4408 assert(blkmem != NULL);
4409
4410 SCIP_ALLOC( BMSallocBlockMemory(blkmem, intarray) );
4411 (*intarray)->blkmem = blkmem;
4412 (*intarray)->vals = NULL;
4413 (*intarray)->valssize = 0;
4414 (*intarray)->firstidx = -1;
4415 (*intarray)->minusedidx = INT_MAX;
4416 (*intarray)->maxusedidx = INT_MIN;
4417
4418 return SCIP_OKAY;
4419}
4420
4421/** creates a copy of a dynamic array of int values */
4423 SCIP_INTARRAY** intarray, /**< pointer to store the copied int array */
4424 BMS_BLKMEM* blkmem, /**< block memory */
4425 SCIP_INTARRAY* sourceintarray /**< dynamic int array to copy */
4426 )
4427{
4428 assert(intarray != NULL);
4429 assert(sourceintarray != NULL);
4430
4431 SCIP_CALL( SCIPintarrayCreate(intarray, blkmem) );
4432 if( sourceintarray->valssize > 0 )
4433 {
4434 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*intarray)->vals, sourceintarray->vals, sourceintarray->valssize) );
4435 }
4436 (*intarray)->valssize = sourceintarray->valssize;
4437 (*intarray)->firstidx = sourceintarray->firstidx;
4438 (*intarray)->minusedidx = sourceintarray->minusedidx;
4439 (*intarray)->maxusedidx = sourceintarray->maxusedidx;
4440
4441 return SCIP_OKAY;
4442}
4443
4444/** frees a dynamic array of int values */
4446 SCIP_INTARRAY** intarray /**< pointer to the int array */
4447 )
4448{
4449 assert(intarray != NULL);
4450 assert(*intarray != NULL);
4451
4452 BMSfreeBlockMemoryArrayNull((*intarray)->blkmem, &(*intarray)->vals, (*intarray)->valssize);
4453 BMSfreeBlockMemory((*intarray)->blkmem, intarray);
4454
4455 return SCIP_OKAY;
4456}
4457
4458/** extends dynamic array to be able to store indices from minidx to maxidx */
4460 SCIP_INTARRAY* intarray, /**< dynamic int array */
4461 int arraygrowinit, /**< initial size of array */
4462 SCIP_Real arraygrowfac, /**< growing factor of array */
4463 int minidx, /**< smallest index to allocate storage for */
4464 int maxidx /**< largest index to allocate storage for */
4465 )
4466{
4467 int nused;
4468 int nfree;
4469 int newfirstidx;
4470 int i;
4471
4472 assert(intarray != NULL);
4473 assert(intarray->minusedidx == INT_MAX || intarray->firstidx >= 0);
4474 assert(intarray->maxusedidx == INT_MIN || intarray->firstidx >= 0);
4475 assert(intarray->minusedidx == INT_MAX || intarray->minusedidx >= intarray->firstidx);
4476 assert(intarray->maxusedidx == INT_MIN || intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4477 assert(0 <= minidx);
4478 assert(minidx <= maxidx);
4479
4480 minidx = MIN(minidx, intarray->minusedidx);
4481 maxidx = MAX(maxidx, intarray->maxusedidx);
4482 assert(0 <= minidx);
4483 assert(minidx <= maxidx);
4484
4485 SCIPdebugMessage("extending intarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
4486 (void*)intarray, intarray->firstidx, intarray->valssize, intarray->minusedidx, intarray->maxusedidx, minidx, maxidx);
4487
4488 /* check, whether we have to allocate additional memory, or shift the array */
4489 nused = maxidx - minidx + 1;
4490 if( nused > intarray->valssize )
4491 {
4492 int* newvals;
4493 int newvalssize;
4494
4495 /* allocate new memory storage */
4496 newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
4497 SCIP_ALLOC( BMSallocBlockMemoryArray(intarray->blkmem, &newvals, newvalssize) );
4498 nfree = newvalssize - nused;
4499 newfirstidx = minidx - nfree/2;
4500 newfirstidx = MAX(newfirstidx, 0);
4501 assert(newfirstidx <= minidx);
4502 assert(maxidx < newfirstidx + newvalssize);
4503
4504 /* initialize memory array by copying old values and setting new values to zero */
4505 if( intarray->firstidx != -1 )
4506 {
4507 for( i = 0; i < intarray->minusedidx - newfirstidx; ++i )
4508 newvals[i] = 0;
4509
4510 /* check for possible overflow or negative value */
4511 assert(intarray->maxusedidx - intarray->minusedidx + 1 > 0);
4512
4513 BMScopyMemoryArray(&newvals[intarray->minusedidx - newfirstidx],
4514 &intarray->vals[intarray->minusedidx - intarray->firstidx],
4515 intarray->maxusedidx - intarray->minusedidx + 1); /*lint !e866 !e776*/
4516 for( i = intarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
4517 newvals[i] = 0;
4518 }
4519 else
4520 {
4521 for( i = 0; i < newvalssize; ++i )
4522 newvals[i] = 0;
4523 }
4524
4525 /* free old memory storage, and set the new array parameters */
4526 BMSfreeBlockMemoryArrayNull(intarray->blkmem, &intarray->vals, intarray->valssize);
4527 intarray->vals = newvals;
4528 intarray->valssize = newvalssize;
4529 intarray->firstidx = newfirstidx;
4530 }
4531 else if( intarray->firstidx == -1 )
4532 {
4533 /* a sufficiently large memory storage exists, but it was cleared */
4534 nfree = intarray->valssize - nused;
4535 assert(nfree >= 0);
4536 intarray->firstidx = minidx - nfree/2;
4537 assert(intarray->firstidx <= minidx);
4538 assert(maxidx < intarray->firstidx + intarray->valssize);
4539#ifndef NDEBUG
4540 for( i = 0; i < intarray->valssize; ++i )
4541 assert(intarray->vals[i] == 0);
4542#endif
4543 }
4544 else if( minidx < intarray->firstidx )
4545 {
4546 /* a sufficiently large memory storage exists, but it has to be shifted to the right */
4547 nfree = intarray->valssize - nused;
4548 assert(nfree >= 0);
4549 newfirstidx = minidx - nfree/2;
4550 newfirstidx = MAX(newfirstidx, 0);
4551 assert(newfirstidx <= minidx);
4552 assert(maxidx < newfirstidx + intarray->valssize);
4553
4554 if( intarray->minusedidx <= intarray->maxusedidx )
4555 {
4556 int shift;
4557
4558 assert(intarray->firstidx <= intarray->minusedidx);
4559 assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4560
4561 /* shift used part of array to the right */
4562 shift = intarray->firstidx - newfirstidx;
4563 assert(shift > 0);
4564 for( i = intarray->maxusedidx - intarray->firstidx; i >= intarray->minusedidx - intarray->firstidx; --i )
4565 {
4566 assert(0 <= i + shift && i + shift < intarray->valssize);
4567 intarray->vals[i + shift] = intarray->vals[i];
4568 }
4569 /* clear the formerly used head of the array */
4570 for( i = 0; i < shift; ++i )
4571 intarray->vals[intarray->minusedidx - intarray->firstidx + i] = 0;
4572 }
4573 intarray->firstidx = newfirstidx;
4574 }
4575 else if( maxidx >= intarray->firstidx + intarray->valssize )
4576 {
4577 /* a sufficiently large memory storage exists, but it has to be shifted to the left */
4578 nfree = intarray->valssize - nused;
4579 assert(nfree >= 0);
4580 newfirstidx = minidx - nfree/2;
4581 newfirstidx = MAX(newfirstidx, 0);
4582 assert(newfirstidx <= minidx);
4583 assert(maxidx < newfirstidx + intarray->valssize);
4584
4585 if( intarray->minusedidx <= intarray->maxusedidx )
4586 {
4587 int shift;
4588
4589 assert(intarray->firstidx <= intarray->minusedidx);
4590 assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4591
4592 /* shift used part of array to the left */
4593 shift = newfirstidx - intarray->firstidx;
4594 assert(shift > 0);
4595 for( i = intarray->minusedidx - intarray->firstidx; i <= intarray->maxusedidx - intarray->firstidx; ++i )
4596 {
4597 assert(0 <= i - shift && i - shift < intarray->valssize);
4598 intarray->vals[i - shift] = intarray->vals[i];
4599 }
4600 /* clear the formerly used tail of the array */
4601 for( i = 0; i < shift; ++i )
4602 intarray->vals[intarray->maxusedidx - intarray->firstidx - i] = 0;
4603 }
4604 intarray->firstidx = newfirstidx;
4605 }
4606
4607 assert(minidx >= intarray->firstidx);
4608 assert(maxidx < intarray->firstidx + intarray->valssize);
4609
4610 return SCIP_OKAY;
4611}
4612
4613/** clears a dynamic int array */
4615 SCIP_INTARRAY* intarray /**< dynamic int array */
4616 )
4617{
4618 assert(intarray != NULL);
4619
4620 SCIPdebugMessage("clearing intarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
4621 (void*)intarray, intarray->firstidx, intarray->valssize, intarray->minusedidx, intarray->maxusedidx);
4622
4623 if( intarray->minusedidx <= intarray->maxusedidx )
4624 {
4625 assert(intarray->firstidx <= intarray->minusedidx);
4626 assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4627 assert(intarray->firstidx != -1);
4628 assert(intarray->valssize > 0);
4629
4630 /* clear the used part of array */
4631 BMSclearMemoryArray(&intarray->vals[intarray->minusedidx - intarray->firstidx],
4632 intarray->maxusedidx - intarray->minusedidx + 1); /*lint !e866*/
4633
4634 /* mark the array cleared */
4635 intarray->minusedidx = INT_MAX;
4636 intarray->maxusedidx = INT_MIN;
4637 }
4638 assert(intarray->minusedidx == INT_MAX);
4639 assert(intarray->maxusedidx == INT_MIN);
4640
4641 return SCIP_OKAY;
4642}
4643
4644/** gets value of entry in dynamic array */
4646 SCIP_INTARRAY* intarray, /**< dynamic int array */
4647 int idx /**< array index to get value for */
4648 )
4649{
4650 assert(intarray != NULL);
4651 assert(idx >= 0);
4652
4653 if( idx < intarray->minusedidx || idx > intarray->maxusedidx )
4654 return 0;
4655 else
4656 {
4657 assert(intarray->vals != NULL);
4658 assert(idx - intarray->firstidx >= 0);
4659 assert(idx - intarray->firstidx < intarray->valssize);
4660
4661 return intarray->vals[idx - intarray->firstidx];
4662 }
4663}
4664
4665/** sets value of entry in dynamic array */
4667 SCIP_INTARRAY* intarray, /**< dynamic int array */
4668 int arraygrowinit, /**< initial size of array */
4669 SCIP_Real arraygrowfac, /**< growing factor of array */
4670 int idx, /**< array index to set value for */
4671 int val /**< value to set array index to */
4672 )
4673{
4674 assert(intarray != NULL);
4675 assert(idx >= 0);
4676
4677 SCIPdebugMessage("setting intarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %d\n",
4678 (void*)intarray, intarray->firstidx, intarray->valssize, intarray->minusedidx, intarray->maxusedidx, idx, val);
4679
4680 if( val != 0 )
4681 {
4682 /* extend array to be able to store the index */
4683 SCIP_CALL( SCIPintarrayExtend(intarray, arraygrowinit, arraygrowfac, idx, idx) );
4684 assert(idx >= intarray->firstidx);
4685 assert(idx < intarray->firstidx + intarray->valssize);
4686
4687 /* set the array value of the index */
4688 intarray->vals[idx - intarray->firstidx] = val;
4689
4690 /* update min/maxusedidx */
4691 intarray->minusedidx = MIN(intarray->minusedidx, idx);
4692 intarray->maxusedidx = MAX(intarray->maxusedidx, idx);
4693 }
4694 else if( idx >= intarray->firstidx && idx < intarray->firstidx + intarray->valssize )
4695 {
4696 /* set the array value of the index to zero */
4697 intarray->vals[idx - intarray->firstidx] = 0;
4698
4699 /* check, if we can tighten the min/maxusedidx */
4700 if( idx == intarray->minusedidx )
4701 {
4702 assert(intarray->maxusedidx >= 0);
4703 assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4704 do
4705 {
4706 intarray->minusedidx++;
4707 }
4708 while( intarray->minusedidx <= intarray->maxusedidx
4709 && intarray->vals[intarray->minusedidx - intarray->firstidx] == 0 );
4710 if( intarray->minusedidx > intarray->maxusedidx )
4711 {
4712 intarray->minusedidx = INT_MAX;
4713 intarray->maxusedidx = INT_MIN;
4714 }
4715 }
4716 else if( idx == intarray->maxusedidx )
4717 {
4718 assert(intarray->minusedidx >= 0);
4719 assert(intarray->minusedidx < intarray->maxusedidx);
4720 assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4721 do
4722 {
4723 intarray->maxusedidx--;
4724 assert(intarray->minusedidx <= intarray->maxusedidx);
4725 }
4726 while( intarray->vals[intarray->maxusedidx - intarray->firstidx] == 0 );
4727 }
4728 }
4729
4730 return SCIP_OKAY;
4731}
4732
4733/** increases value of entry in dynamic array */
4735 SCIP_INTARRAY* intarray, /**< dynamic int array */
4736 int arraygrowinit, /**< initial size of array */
4737 SCIP_Real arraygrowfac, /**< growing factor of array */
4738 int idx, /**< array index to increase value for */
4739 int incval /**< value to increase array index */
4740 )
4741{
4742 return SCIPintarraySetVal(intarray, arraygrowinit, arraygrowfac, idx, SCIPintarrayGetVal(intarray, idx) + incval);
4743}
4744
4745/** returns the minimal index of all stored non-zero elements */
4747 SCIP_INTARRAY* intarray /**< dynamic int array */
4748 )
4749{
4750 assert(intarray != NULL);
4751
4752 return intarray->minusedidx;
4753}
4754
4755/** returns the maximal index of all stored non-zero elements */
4757 SCIP_INTARRAY* intarray /**< dynamic int array */
4758 )
4759{
4760 assert(intarray != NULL);
4761
4762 return intarray->maxusedidx;
4763}
4764
4765
4766/** creates a dynamic array of bool values */
4768 SCIP_BOOLARRAY** boolarray, /**< pointer to store the bool array */
4769 BMS_BLKMEM* blkmem /**< block memory */
4770 )
4771{
4772 assert(boolarray != NULL);
4773 assert(blkmem != NULL);
4774
4775 SCIP_ALLOC( BMSallocBlockMemory(blkmem, boolarray) );
4776 (*boolarray)->blkmem = blkmem;
4777 (*boolarray)->vals = NULL;
4778 (*boolarray)->valssize = 0;
4779 (*boolarray)->firstidx = -1;
4780 (*boolarray)->minusedidx = INT_MAX;
4781 (*boolarray)->maxusedidx = INT_MIN;
4782
4783 return SCIP_OKAY;
4784}
4785
4786/** creates a copy of a dynamic array of bool values */
4788 SCIP_BOOLARRAY** boolarray, /**< pointer to store the copied bool array */
4789 BMS_BLKMEM* blkmem, /**< block memory */
4790 SCIP_BOOLARRAY* sourceboolarray /**< dynamic bool array to copy */
4791 )
4792{
4793 assert(boolarray != NULL);
4794 assert(sourceboolarray != NULL);
4795
4796 SCIP_CALL( SCIPboolarrayCreate(boolarray, blkmem) );
4797 if( sourceboolarray->valssize > 0 )
4798 {
4799 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*boolarray)->vals, sourceboolarray->vals, \
4800 sourceboolarray->valssize) );
4801 }
4802 (*boolarray)->valssize = sourceboolarray->valssize;
4803 (*boolarray)->firstidx = sourceboolarray->firstidx;
4804 (*boolarray)->minusedidx = sourceboolarray->minusedidx;
4805 (*boolarray)->maxusedidx = sourceboolarray->maxusedidx;
4806
4807 return SCIP_OKAY;
4808}
4809
4810/** frees a dynamic array of bool values */
4812 SCIP_BOOLARRAY** boolarray /**< pointer to the bool array */
4813 )
4814{
4815 assert(boolarray != NULL);
4816 assert(*boolarray != NULL);
4817
4818 BMSfreeBlockMemoryArrayNull((*boolarray)->blkmem, &(*boolarray)->vals, (*boolarray)->valssize);
4819 BMSfreeBlockMemory((*boolarray)->blkmem, boolarray);
4820
4821 return SCIP_OKAY;
4822}
4823
4824/** extends dynamic array to be able to store indices from minidx to maxidx */
4826 SCIP_BOOLARRAY* boolarray, /**< dynamic bool array */
4827 int arraygrowinit, /**< initial size of array */
4828 SCIP_Real arraygrowfac, /**< growing factor of array */
4829 int minidx, /**< smallest index to allocate storage for */
4830 int maxidx /**< largest index to allocate storage for */
4831 )
4832{
4833 int nused;
4834 int nfree;
4835 int newfirstidx;
4836 int i;
4837
4838 assert(boolarray != NULL);
4839 assert(boolarray->minusedidx == INT_MAX || boolarray->firstidx >= 0);
4840 assert(boolarray->maxusedidx == INT_MIN || boolarray->firstidx >= 0);
4841 assert(boolarray->minusedidx == INT_MAX || boolarray->minusedidx >= boolarray->firstidx);
4842 assert(boolarray->maxusedidx == INT_MIN || boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
4843 assert(0 <= minidx);
4844 assert(minidx <= maxidx);
4845
4846 minidx = MIN(minidx, boolarray->minusedidx);
4847 maxidx = MAX(maxidx, boolarray->maxusedidx);
4848 assert(0 <= minidx);
4849 assert(minidx <= maxidx);
4850
4851 SCIPdebugMessage("extending boolarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
4852 (void*)boolarray, boolarray->firstidx, boolarray->valssize, boolarray->minusedidx, boolarray->maxusedidx, minidx, maxidx);
4853
4854 /* check, whether we have to allocate additional memory, or shift the array */
4855 nused = maxidx - minidx + 1;
4856 if( nused > boolarray->valssize )
4857 {
4858 SCIP_Bool* newvals;
4859 int newvalssize;
4860
4861 /* allocate new memory storage */
4862 newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
4863 SCIP_ALLOC( BMSallocBlockMemoryArray(boolarray->blkmem, &newvals, newvalssize) );
4864 nfree = newvalssize - nused;
4865 newfirstidx = minidx - nfree/2;
4866 newfirstidx = MAX(newfirstidx, 0);
4867 assert(newfirstidx <= minidx);
4868 assert(maxidx < newfirstidx + newvalssize);
4869
4870 /* initialize memory array by copying old values and setting new values to zero */
4871 if( boolarray->firstidx != -1 )
4872 {
4873 for( i = 0; i < boolarray->minusedidx - newfirstidx; ++i )
4874 newvals[i] = FALSE;
4875
4876 /* check for possible overflow or negative value */
4877 assert(boolarray->maxusedidx - boolarray->minusedidx + 1 > 0);
4878
4879 BMScopyMemoryArray(&newvals[boolarray->minusedidx - newfirstidx],
4880 &boolarray->vals[boolarray->minusedidx - boolarray->firstidx],
4881 boolarray->maxusedidx - boolarray->minusedidx + 1); /*lint !e866 !e776*/
4882 for( i = boolarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
4883 newvals[i] = FALSE;
4884 }
4885 else
4886 {
4887 for( i = 0; i < newvalssize; ++i )
4888 newvals[i] = FALSE;
4889 }
4890
4891 /* free old memory storage, and set the new array parameters */
4892 BMSfreeBlockMemoryArrayNull(boolarray->blkmem, &boolarray->vals, boolarray->valssize);
4893 boolarray->vals = newvals;
4894 boolarray->valssize = newvalssize;
4895 boolarray->firstidx = newfirstidx;
4896 }
4897 else if( boolarray->firstidx == -1 )
4898 {
4899 /* a sufficiently large memory storage exists, but it was cleared */
4900 nfree = boolarray->valssize - nused;
4901 assert(nfree >= 0);
4902 boolarray->firstidx = minidx - nfree/2;
4903 assert(boolarray->firstidx <= minidx);
4904 assert(maxidx < boolarray->firstidx + boolarray->valssize);
4905#ifndef NDEBUG
4906 for( i = 0; i < boolarray->valssize; ++i )
4907 assert(boolarray->vals[i] == FALSE);
4908#endif
4909 }
4910 else if( minidx < boolarray->firstidx )
4911 {
4912 /* a sufficiently large memory storage exists, but it has to be shifted to the right */
4913 nfree = boolarray->valssize - nused;
4914 assert(nfree >= 0);
4915 newfirstidx = minidx - nfree/2;
4916 newfirstidx = MAX(newfirstidx, 0);
4917 assert(newfirstidx <= minidx);
4918 assert(maxidx < newfirstidx + boolarray->valssize);
4919
4920 if( boolarray->minusedidx <= boolarray->maxusedidx )
4921 {
4922 int shift;
4923
4924 assert(boolarray->firstidx <= boolarray->minusedidx);
4925 assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
4926
4927 /* shift used part of array to the right */
4928 shift = boolarray->firstidx - newfirstidx;
4929 assert(shift > 0);
4930 for( i = boolarray->maxusedidx - boolarray->firstidx; i >= boolarray->minusedidx - boolarray->firstidx; --i )
4931 {
4932 assert(0 <= i + shift && i + shift < boolarray->valssize);
4933 boolarray->vals[i + shift] = boolarray->vals[i];
4934 }
4935 /* clear the formerly used head of the array */
4936 for( i = 0; i < shift; ++i )
4937 boolarray->vals[boolarray->minusedidx - boolarray->firstidx + i] = FALSE;
4938 }
4939 boolarray->firstidx = newfirstidx;
4940 }
4941 else if( maxidx >= boolarray->firstidx + boolarray->valssize )
4942 {
4943 /* a sufficiently large memory storage exists, but it has to be shifted to the left */
4944 nfree = boolarray->valssize - nused;
4945 assert(nfree >= 0);
4946 newfirstidx = minidx - nfree/2;
4947 newfirstidx = MAX(newfirstidx, 0);
4948 assert(newfirstidx <= minidx);
4949 assert(maxidx < newfirstidx + boolarray->valssize);
4950
4951 if( boolarray->minusedidx <= boolarray->maxusedidx )
4952 {
4953 int shift;
4954
4955 assert(boolarray->firstidx <= boolarray->minusedidx);
4956 assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
4957
4958 /* shift used part of array to the left */
4959 shift = newfirstidx - boolarray->firstidx;
4960 assert(shift > 0);
4961
4962 assert(0 <= boolarray->minusedidx - boolarray->firstidx - shift);
4963 assert(boolarray->maxusedidx - boolarray->firstidx - shift < boolarray->valssize);
4964 BMSmoveMemoryArray(&(boolarray->vals[boolarray->minusedidx - boolarray->firstidx - shift]),
4965 &(boolarray->vals[boolarray->minusedidx - boolarray->firstidx]),
4966 boolarray->maxusedidx - boolarray->minusedidx + 1); /*lint !e866*/
4967
4968 /* clear the formerly used tail of the array */
4969 for( i = 0; i < shift; ++i )
4970 boolarray->vals[boolarray->maxusedidx - boolarray->firstidx - i] = FALSE;
4971 }
4972 boolarray->firstidx = newfirstidx;
4973 }
4974
4975 assert(minidx >= boolarray->firstidx);
4976 assert(maxidx < boolarray->firstidx + boolarray->valssize);
4977
4978 return SCIP_OKAY;
4979}
4980
4981/** clears a dynamic bool array */
4983 SCIP_BOOLARRAY* boolarray /**< dynamic bool array */
4984 )
4985{
4986 assert(boolarray != NULL);
4987
4988 SCIPdebugMessage("clearing boolarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
4989 (void*)boolarray, boolarray->firstidx, boolarray->valssize, boolarray->minusedidx, boolarray->maxusedidx);
4990
4991 if( boolarray->minusedidx <= boolarray->maxusedidx )
4992 {
4993 assert(boolarray->firstidx <= boolarray->minusedidx);
4994 assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
4995 assert(boolarray->firstidx != -1);
4996 assert(boolarray->valssize > 0);
4997
4998 /* clear the used part of array */
4999 BMSclearMemoryArray(&boolarray->vals[boolarray->minusedidx - boolarray->firstidx],
5000 boolarray->maxusedidx - boolarray->minusedidx + 1); /*lint !e866*/
5001
5002 /* mark the array cleared */
5003 boolarray->minusedidx = INT_MAX;
5004 boolarray->maxusedidx = INT_MIN;
5005 }
5006 assert(boolarray->minusedidx == INT_MAX);
5007 assert(boolarray->maxusedidx == INT_MIN);
5008
5009 return SCIP_OKAY;
5010}
5011
5012/** gets value of entry in dynamic array */
5014 SCIP_BOOLARRAY* boolarray, /**< dynamic bool array */
5015 int idx /**< array index to get value for */
5016 )
5017{
5018 assert(boolarray != NULL);
5019 assert(idx >= 0);
5020
5021 if( idx < boolarray->minusedidx || idx > boolarray->maxusedidx )
5022 return FALSE;
5023 else
5024 {
5025 assert(boolarray->vals != NULL);
5026 assert(idx - boolarray->firstidx >= 0);
5027 assert(idx - boolarray->firstidx < boolarray->valssize);
5028
5029 return boolarray->vals[idx - boolarray->firstidx];
5030 }
5031}
5032
5033/** sets value of entry in dynamic array */
5035 SCIP_BOOLARRAY* boolarray, /**< dynamic bool array */
5036 int arraygrowinit, /**< initial size of array */
5037 SCIP_Real arraygrowfac, /**< growing factor of array */
5038 int idx, /**< array index to set value for */
5039 SCIP_Bool val /**< value to set array index to */
5040 )
5041{
5042 assert(boolarray != NULL);
5043 assert(idx >= 0);
5044
5045 SCIPdebugMessage("setting boolarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %u\n",
5046 (void*)boolarray, boolarray->firstidx, boolarray->valssize, boolarray->minusedidx, boolarray->maxusedidx, idx, val);
5047
5048 if( val != FALSE )
5049 {
5050 /* extend array to be able to store the index */
5051 SCIP_CALL( SCIPboolarrayExtend(boolarray, arraygrowinit, arraygrowfac, idx, idx) );
5052 assert(idx >= boolarray->firstidx);
5053 assert(idx < boolarray->firstidx + boolarray->valssize);
5054
5055 /* set the array value of the index */
5056 boolarray->vals[idx - boolarray->firstidx] = val;
5057
5058 /* update min/maxusedidx */
5059 boolarray->minusedidx = MIN(boolarray->minusedidx, idx);
5060 boolarray->maxusedidx = MAX(boolarray->maxusedidx, idx);
5061 }
5062 else if( idx >= boolarray->firstidx && idx < boolarray->firstidx + boolarray->valssize )
5063 {
5064 /* set the array value of the index to zero */
5065 boolarray->vals[idx - boolarray->firstidx] = FALSE;
5066
5067 /* check, if we can tighten the min/maxusedidx */
5068 if( idx == boolarray->minusedidx )
5069 {
5070 assert(boolarray->maxusedidx >= 0);
5071 assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
5072 do
5073 {
5074 boolarray->minusedidx++;
5075 }
5076 while( boolarray->minusedidx <= boolarray->maxusedidx
5077 && boolarray->vals[boolarray->minusedidx - boolarray->firstidx] == FALSE );
5078 if( boolarray->minusedidx > boolarray->maxusedidx )
5079 {
5080 boolarray->minusedidx = INT_MAX;
5081 boolarray->maxusedidx = INT_MIN;
5082 }
5083 }
5084 else if( idx == boolarray->maxusedidx )
5085 {
5086 assert(boolarray->minusedidx >= 0);
5087 assert(boolarray->minusedidx < boolarray->maxusedidx);
5088 assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
5089 do
5090 {
5091 boolarray->maxusedidx--;
5092 assert(boolarray->minusedidx <= boolarray->maxusedidx);
5093 }
5094 while( boolarray->vals[boolarray->maxusedidx - boolarray->firstidx] == FALSE );
5095 }
5096 }
5097
5098 return SCIP_OKAY;
5099}
5100
5101/** returns the minimal index of all stored non-zero elements */
5103 SCIP_BOOLARRAY* boolarray /**< dynamic bool array */
5104 )
5105{
5106 assert(boolarray != NULL);
5107
5108 return boolarray->minusedidx;
5109}
5110
5111/** returns the maximal index of all stored non-zero elements */
5113 SCIP_BOOLARRAY* boolarray /**< dynamic bool array */
5114 )
5115{
5116 assert(boolarray != NULL);
5117
5118 return boolarray->maxusedidx;
5119}
5120
5121
5122/** creates a dynamic array of pointer values */
5124 SCIP_PTRARRAY** ptrarray, /**< pointer to store the ptr array */
5125 BMS_BLKMEM* blkmem /**< block memory */
5126 )
5127{
5128 assert(ptrarray != NULL);
5129 assert(blkmem != NULL);
5130
5131 SCIP_ALLOC( BMSallocBlockMemory(blkmem, ptrarray) );
5132 (*ptrarray)->blkmem = blkmem;
5133 (*ptrarray)->vals = NULL;
5134 (*ptrarray)->valssize = 0;
5135 (*ptrarray)->firstidx = -1;
5136 (*ptrarray)->minusedidx = INT_MAX;
5137 (*ptrarray)->maxusedidx = INT_MIN;
5138
5139 return SCIP_OKAY;
5140}
5141
5142/** creates a copy of a dynamic array of pointer values */
5144 SCIP_PTRARRAY** ptrarray, /**< pointer to store the copied ptr array */
5145 BMS_BLKMEM* blkmem, /**< block memory */
5146 SCIP_PTRARRAY* sourceptrarray /**< dynamic ptr array to copy */
5147 )
5148{
5149 assert(ptrarray != NULL);
5150 assert(sourceptrarray != NULL);
5151
5152 SCIP_CALL( SCIPptrarrayCreate(ptrarray, blkmem) );
5153 if( sourceptrarray->valssize > 0 )
5154 {
5155 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*ptrarray)->vals, sourceptrarray->vals, sourceptrarray->valssize) );
5156 }
5157 (*ptrarray)->valssize = sourceptrarray->valssize;
5158 (*ptrarray)->firstidx = sourceptrarray->firstidx;
5159 (*ptrarray)->minusedidx = sourceptrarray->minusedidx;
5160 (*ptrarray)->maxusedidx = sourceptrarray->maxusedidx;
5161
5162 return SCIP_OKAY;
5163}
5164
5165/** frees a dynamic array of pointer values */
5167 SCIP_PTRARRAY** ptrarray /**< pointer to the ptr array */
5168 )
5169{
5170 assert(ptrarray != NULL);
5171 assert(*ptrarray != NULL);
5172
5173 BMSfreeBlockMemoryArrayNull((*ptrarray)->blkmem, &(*ptrarray)->vals, (*ptrarray)->valssize);
5174 BMSfreeBlockMemory((*ptrarray)->blkmem, ptrarray);
5175
5176 return SCIP_OKAY;
5177}
5178
5179/** extends dynamic array to be able to store indices from minidx to maxidx */
5181 SCIP_PTRARRAY* ptrarray, /**< dynamic ptr array */
5182 int arraygrowinit, /**< initial size of array */
5183 SCIP_Real arraygrowfac, /**< growing factor of array */
5184 int minidx, /**< smallest index to allocate storage for */
5185 int maxidx /**< largest index to allocate storage for */
5186 )
5187{
5188 int nused;
5189 int nfree;
5190 int newfirstidx;
5191 int i;
5192
5193 assert(ptrarray != NULL);
5194 assert(ptrarray->minusedidx == INT_MAX || ptrarray->firstidx >= 0);
5195 assert(ptrarray->maxusedidx == INT_MIN || ptrarray->firstidx >= 0);
5196 assert(ptrarray->minusedidx == INT_MAX || ptrarray->minusedidx >= ptrarray->firstidx);
5197 assert(ptrarray->maxusedidx == INT_MIN || ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5198 assert(0 <= minidx);
5199 assert(minidx <= maxidx);
5200
5201 minidx = MIN(minidx, ptrarray->minusedidx);
5202 maxidx = MAX(maxidx, ptrarray->maxusedidx);
5203 assert(0 <= minidx);
5204 assert(minidx <= maxidx);
5205
5206 SCIPdebugMessage("extending ptrarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
5207 (void*)ptrarray, ptrarray->firstidx, ptrarray->valssize, ptrarray->minusedidx, ptrarray->maxusedidx, minidx, maxidx);
5208
5209 /* check, whether we have to allocate additional memory, or shift the array */
5210 nused = maxidx - minidx + 1;
5211 if( nused > ptrarray->valssize )
5212 {
5213 void** newvals;
5214 int newvalssize;
5215
5216 /* allocate new memory storage */
5217 newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
5218 SCIP_ALLOC( BMSallocBlockMemoryArray(ptrarray->blkmem, &newvals, newvalssize) );
5219 nfree = newvalssize - nused;
5220 newfirstidx = minidx - nfree/2;
5221 newfirstidx = MAX(newfirstidx, 0);
5222 assert(newfirstidx <= minidx);
5223 assert(maxidx < newfirstidx + newvalssize);
5224
5225 /* initialize memory array by copying old values and setting new values to zero */
5226 if( ptrarray->firstidx != -1 )
5227 {
5228 for( i = 0; i < ptrarray->minusedidx - newfirstidx; ++i )
5229 newvals[i] = NULL;
5230
5231 /* check for possible overflow or negative value */
5232 assert(ptrarray->maxusedidx - ptrarray->minusedidx + 1 > 0);
5233
5234 BMScopyMemoryArray(&newvals[ptrarray->minusedidx - newfirstidx],
5235 &(ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx]),
5236 ptrarray->maxusedidx - ptrarray->minusedidx + 1); /*lint !e866 !e776*/
5237 for( i = ptrarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
5238 newvals[i] = NULL;
5239 }
5240 else
5241 {
5242 for( i = 0; i < newvalssize; ++i )
5243 newvals[i] = NULL;
5244 }
5245
5246 /* free old memory storage, and set the new array parameters */
5247 BMSfreeBlockMemoryArrayNull(ptrarray->blkmem, &ptrarray->vals, ptrarray->valssize);
5248 ptrarray->vals = newvals;
5249 ptrarray->valssize = newvalssize;
5250 ptrarray->firstidx = newfirstidx;
5251 }
5252 else if( ptrarray->firstidx == -1 )
5253 {
5254 /* a sufficiently large memory storage exists, but it was cleared */
5255 nfree = ptrarray->valssize - nused;
5256 assert(nfree >= 0);
5257 ptrarray->firstidx = minidx - nfree/2;
5258 assert(ptrarray->firstidx <= minidx);
5259 assert(maxidx < ptrarray->firstidx + ptrarray->valssize);
5260#ifndef NDEBUG
5261 for( i = 0; i < ptrarray->valssize; ++i )
5262 assert(ptrarray->vals[i] == NULL);
5263#endif
5264 }
5265 else if( minidx < ptrarray->firstidx )
5266 {
5267 /* a sufficiently large memory storage exists, but it has to be shifted to the right */
5268 nfree = ptrarray->valssize - nused;
5269 assert(nfree >= 0);
5270 newfirstidx = minidx - nfree/2;
5271 newfirstidx = MAX(newfirstidx, 0);
5272 assert(newfirstidx <= minidx);
5273 assert(maxidx < newfirstidx + ptrarray->valssize);
5274
5275 if( ptrarray->minusedidx <= ptrarray->maxusedidx )
5276 {
5277 int shift;
5278
5279 assert(ptrarray->firstidx <= ptrarray->minusedidx);
5280 assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5281
5282 /* shift used part of array to the right */
5283 shift = ptrarray->firstidx - newfirstidx;
5284 assert(shift > 0);
5285 for( i = ptrarray->maxusedidx - ptrarray->firstidx; i >= ptrarray->minusedidx - ptrarray->firstidx; --i )
5286 {
5287 assert(0 <= i + shift && i + shift < ptrarray->valssize);
5288 ptrarray->vals[i + shift] = ptrarray->vals[i];
5289 }
5290 /* clear the formerly used head of the array */
5291 for( i = 0; i < shift; ++i )
5292 ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx + i] = NULL;
5293 }
5294 ptrarray->firstidx = newfirstidx;
5295 }
5296 else if( maxidx >= ptrarray->firstidx + ptrarray->valssize )
5297 {
5298 /* a sufficiently large memory storage exists, but it has to be shifted to the left */
5299 nfree = ptrarray->valssize - nused;
5300 assert(nfree >= 0);
5301 newfirstidx = minidx - nfree/2;
5302 newfirstidx = MAX(newfirstidx, 0);
5303 assert(newfirstidx <= minidx);
5304 assert(maxidx < newfirstidx + ptrarray->valssize);
5305
5306 if( ptrarray->minusedidx <= ptrarray->maxusedidx )
5307 {
5308 int shift;
5309
5310 assert(ptrarray->firstidx <= ptrarray->minusedidx);
5311 assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5312
5313 /* shift used part of array to the left */
5314 shift = newfirstidx - ptrarray->firstidx;
5315 assert(shift > 0);
5316 for( i = ptrarray->minusedidx - ptrarray->firstidx; i <= ptrarray->maxusedidx - ptrarray->firstidx; ++i )
5317 {
5318 assert(0 <= i - shift && i - shift < ptrarray->valssize);
5319 ptrarray->vals[i - shift] = ptrarray->vals[i];
5320 }
5321 /* clear the formerly used tail of the array */
5322 for( i = 0; i < shift; ++i )
5323 ptrarray->vals[ptrarray->maxusedidx - ptrarray->firstidx - i] = NULL;
5324 }
5325 ptrarray->firstidx = newfirstidx;
5326 }
5327
5328 assert(minidx >= ptrarray->firstidx);
5329 assert(maxidx < ptrarray->firstidx + ptrarray->valssize);
5330
5331 return SCIP_OKAY;
5332}
5333
5334/** clears a dynamic pointer array */
5336 SCIP_PTRARRAY* ptrarray /**< dynamic ptr array */
5337 )
5338{
5339 assert(ptrarray != NULL);
5340
5341 SCIPdebugMessage("clearing ptrarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
5342 (void*)ptrarray, ptrarray->firstidx, ptrarray->valssize, ptrarray->minusedidx, ptrarray->maxusedidx);
5343
5344 if( ptrarray->minusedidx <= ptrarray->maxusedidx )
5345 {
5346 assert(ptrarray->firstidx <= ptrarray->minusedidx);
5347 assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5348 assert(ptrarray->firstidx != -1);
5349 assert(ptrarray->valssize > 0);
5350
5351 /* clear the used part of array */
5352 BMSclearMemoryArray(&ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx],
5353 ptrarray->maxusedidx - ptrarray->minusedidx + 1); /*lint !e866*/
5354
5355 /* mark the array cleared */
5356 ptrarray->minusedidx = INT_MAX;
5357 ptrarray->maxusedidx = INT_MIN;
5358 }
5359 assert(ptrarray->minusedidx == INT_MAX);
5360 assert(ptrarray->maxusedidx == INT_MIN);
5361
5362 return SCIP_OKAY;
5363}
5364
5365/** gets value of entry in dynamic array */
5367 SCIP_PTRARRAY* ptrarray, /**< dynamic ptr array */
5368 int idx /**< array index to get value for */
5369 )
5370{
5371 assert(ptrarray != NULL);
5372 assert(idx >= 0);
5373
5374 if( idx < ptrarray->minusedidx || idx > ptrarray->maxusedidx )
5375 return NULL;
5376 else
5377 {
5378 assert(ptrarray->vals != NULL);
5379 assert(idx - ptrarray->firstidx >= 0);
5380 assert(idx - ptrarray->firstidx < ptrarray->valssize);
5381
5382 return ptrarray->vals[idx - ptrarray->firstidx];
5383 }
5384}
5385
5386/** sets value of entry in dynamic array */
5388 SCIP_PTRARRAY* ptrarray, /**< dynamic ptr array */
5389 int arraygrowinit, /**< initial size of array */
5390 SCIP_Real arraygrowfac, /**< growing factor of array */
5391 int idx, /**< array index to set value for */
5392 void* val /**< value to set array index to */
5393 )
5394{
5395 assert(ptrarray != NULL);
5396 assert(idx >= 0);
5397
5398 SCIPdebugMessage("setting ptrarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %p\n",
5399 (void*)ptrarray, ptrarray->firstidx, ptrarray->valssize, ptrarray->minusedidx, ptrarray->maxusedidx, idx, val);
5400
5401 if( val != NULL )
5402 {
5403 /* extend array to be able to store the index */
5404 SCIP_CALL( SCIPptrarrayExtend(ptrarray, arraygrowinit, arraygrowfac, idx, idx) );
5405 assert(idx >= ptrarray->firstidx);
5406 assert(idx < ptrarray->firstidx + ptrarray->valssize);
5407
5408 /* set the array value of the index */
5409 ptrarray->vals[idx - ptrarray->firstidx] = val;
5410
5411 /* update min/maxusedidx */
5412 ptrarray->minusedidx = MIN(ptrarray->minusedidx, idx);
5413 ptrarray->maxusedidx = MAX(ptrarray->maxusedidx, idx);
5414 }
5415 else if( idx >= ptrarray->firstidx && idx < ptrarray->firstidx + ptrarray->valssize )
5416 {
5417 /* set the array value of the index to zero */
5418 ptrarray->vals[idx - ptrarray->firstidx] = NULL;
5419
5420 /* check, if we can tighten the min/maxusedidx */
5421 if( idx == ptrarray->minusedidx )
5422 {
5423 assert(ptrarray->maxusedidx >= 0);
5424 assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5425 do
5426 {
5427 ptrarray->minusedidx++;
5428 }
5429 while( ptrarray->minusedidx <= ptrarray->maxusedidx
5430 && ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx] == NULL );
5431 if( ptrarray->minusedidx > ptrarray->maxusedidx )
5432 {
5433 ptrarray->minusedidx = INT_MAX;
5434 ptrarray->maxusedidx = INT_MIN;
5435 }
5436 }
5437 else if( idx == ptrarray->maxusedidx )
5438 {
5439 assert(ptrarray->minusedidx >= 0);
5440 assert(ptrarray->minusedidx < ptrarray->maxusedidx);
5441 assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5442 do
5443 {
5444 ptrarray->maxusedidx--;
5445 assert(ptrarray->minusedidx <= ptrarray->maxusedidx);
5446 }
5447 while( ptrarray->vals[ptrarray->maxusedidx - ptrarray->firstidx] == NULL );
5448 }
5449 }
5450
5451 return SCIP_OKAY;
5452}
5453
5454/** returns the minimal index of all stored non-zero elements */
5456 SCIP_PTRARRAY* ptrarray /**< dynamic ptr array */
5457 )
5458{
5459 assert(ptrarray != NULL);
5460
5461 return ptrarray->minusedidx;
5462}
5463
5464/** returns the maximal index of all stored non-zero elements */
5466 SCIP_PTRARRAY* ptrarray /**< dynamic ptr array */
5467 )
5468{
5469 assert(ptrarray != NULL);
5470
5471 return ptrarray->maxusedidx;
5472}
5473
5474
5475/*
5476 * Sorting algorithms
5477 */
5478
5479/** default comparer for integers */
5481{
5482 int value1;
5483 int value2;
5484
5485 value1 = (int)(size_t)elem1;
5486 value2 = (int)(size_t)elem2;
5487
5488 if( value1 < value2 )
5489 return -1;
5490
5491 if( value2 < value1 )
5492 return 1;
5493
5494 return 0;
5495}
5496
5497/** implements argsort
5498 *
5499 * The data pointer is a lookup array of integers.
5500 */
5501SCIP_DECL_SORTINDCOMP(SCIPsortArgsortInt)
5502{
5503 int* args;
5504 args = (int*) dataptr;
5505
5506 if( args[ind1] < args[ind2] )
5507 return -1;
5508
5509 if( args[ind1] > args[ind2] )
5510 return 1;
5511
5512 return 0;
5513}
5514
5515
5516/** implements argsort
5517 *
5518 * The data pointer is a lookup array, which are pointer arrays.
5519 */
5520SCIP_DECL_SORTINDCOMP(SCIPsortArgsortPtr)
5521{
5522 void** args;
5523 args = (void*) dataptr;
5524
5525 if( args[ind1] < args[ind2] )
5526 return -1;
5527
5528 if( args[ind1] > args[ind2] )
5529 return 1;
5530
5531 return 0;
5532}
5533
5534
5535/* first all upwards-sorting methods */
5536
5537/** sort an indexed element set in non-decreasing order, resulting in a permutation index array */
5539 int* perm, /**< pointer to store the resulting permutation */
5540 SCIP_DECL_SORTINDCOMP((*indcomp)), /**< data element comparator */
5541 void* dataptr, /**< pointer to data field that is given to the external compare method */
5542 int len /**< number of elements to be sorted (valid index range) */
5543 )
5544{
5545 int pos;
5546
5547 assert(indcomp != NULL);
5548 assert(len == 0 || perm != NULL);
5549
5550 /* create identity permutation */
5551 for( pos = 0; pos < len; ++pos )
5552 perm[pos] = pos;
5553
5554 SCIPsortInd(perm, indcomp, dataptr, len);
5555}
5556
5557/* SCIPsortInd(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5558#define SORTTPL_NAMEEXT Ind
5559#define SORTTPL_KEYTYPE int
5560#define SORTTPL_INDCOMP
5561#include "scip/sorttpl.c" /*lint !e451*/
5562
5563
5564/* SCIPsortPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5565#define SORTTPL_NAMEEXT Ptr
5566#define SORTTPL_KEYTYPE void*
5567#define SORTTPL_PTRCOMP
5568#include "scip/sorttpl.c" /*lint !e451*/
5569
5570
5571/* SCIPsortPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5572#define SORTTPL_NAMEEXT PtrPtr
5573#define SORTTPL_KEYTYPE void*
5574#define SORTTPL_FIELD1TYPE void*
5575#define SORTTPL_PTRCOMP
5576#include "scip/sorttpl.c" /*lint !e451*/
5577
5578
5579/* SCIPsortPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5580#define SORTTPL_NAMEEXT PtrReal
5581#define SORTTPL_KEYTYPE void*
5582#define SORTTPL_FIELD1TYPE SCIP_Real
5583#define SORTTPL_PTRCOMP
5584#include "scip/sorttpl.c" /*lint !e451*/
5585
5586
5587/* SCIPsortPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5588#define SORTTPL_NAMEEXT PtrInt
5589#define SORTTPL_KEYTYPE void*
5590#define SORTTPL_FIELD1TYPE int
5591#define SORTTPL_PTRCOMP
5592#include "scip/sorttpl.c" /*lint !e451*/
5593
5594
5595/* SCIPsortPtrBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5596#define SORTTPL_NAMEEXT PtrBool
5597#define SORTTPL_KEYTYPE void*
5598#define SORTTPL_FIELD1TYPE SCIP_Bool
5599#define SORTTPL_PTRCOMP
5600#include "scip/sorttpl.c" /*lint !e451*/
5601
5602
5603/* SCIPsortPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5604#define SORTTPL_NAMEEXT PtrIntInt
5605#define SORTTPL_KEYTYPE void*
5606#define SORTTPL_FIELD1TYPE int
5607#define SORTTPL_FIELD2TYPE int
5608#define SORTTPL_PTRCOMP
5609#include "scip/sorttpl.c" /*lint !e451*/
5610
5611
5612/* SCIPsortPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5613#define SORTTPL_NAMEEXT PtrRealInt
5614#define SORTTPL_KEYTYPE void*
5615#define SORTTPL_FIELD1TYPE SCIP_Real
5616#define SORTTPL_FIELD2TYPE int
5617#define SORTTPL_PTRCOMP
5618#include "scip/sorttpl.c" /*lint !e451*/
5619
5620/* SCIPsortPtrRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5621#define SORTTPL_NAMEEXT PtrRealRealInt
5622#define SORTTPL_KEYTYPE void*
5623#define SORTTPL_FIELD1TYPE SCIP_Real
5624#define SORTTPL_FIELD2TYPE SCIP_Real
5625#define SORTTPL_FIELD3TYPE int
5626#define SORTTPL_PTRCOMP
5627#include "scip/sorttpl.c" /*lint !e451*/
5628
5629/* SCIPsortPtrRealRealBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5630#define SORTTPL_NAMEEXT PtrRealRealBoolBool
5631#define SORTTPL_KEYTYPE void*
5632#define SORTTPL_FIELD1TYPE SCIP_Real
5633#define SORTTPL_FIELD2TYPE SCIP_Real
5634#define SORTTPL_FIELD3TYPE SCIP_Bool
5635#define SORTTPL_FIELD4TYPE SCIP_Bool
5636#define SORTTPL_PTRCOMP
5637#include "scip/sorttpl.c" /*lint !e451*/
5638
5639/* SCIPsortPtrRealRealIntBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5640#define SORTTPL_NAMEEXT PtrRealRealIntBool
5641#define SORTTPL_KEYTYPE void*
5642#define SORTTPL_FIELD1TYPE SCIP_Real
5643#define SORTTPL_FIELD2TYPE SCIP_Real
5644#define SORTTPL_FIELD3TYPE int
5645#define SORTTPL_FIELD4TYPE SCIP_Bool
5646#define SORTTPL_PTRCOMP
5647#include "scip/sorttpl.c" /*lint !e451*/
5648
5649/* SCIPsortPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5650#define SORTTPL_NAMEEXT PtrRealBool
5651#define SORTTPL_KEYTYPE void*
5652#define SORTTPL_FIELD1TYPE SCIP_Real
5653#define SORTTPL_FIELD2TYPE SCIP_Bool
5654#define SORTTPL_PTRCOMP
5655#include "scip/sorttpl.c" /*lint !e451*/
5656
5657
5658/* SCIPsortPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5659#define SORTTPL_NAMEEXT PtrPtrInt
5660#define SORTTPL_KEYTYPE void*
5661#define SORTTPL_FIELD1TYPE void*
5662#define SORTTPL_FIELD2TYPE int
5663#define SORTTPL_PTRCOMP
5664#include "scip/sorttpl.c" /*lint !e451*/
5665
5666
5667/* SCIPsortPtrPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5668#define SORTTPL_NAMEEXT PtrPtrReal
5669#define SORTTPL_KEYTYPE void*
5670#define SORTTPL_FIELD1TYPE void*
5671#define SORTTPL_FIELD2TYPE SCIP_Real
5672#define SORTTPL_PTRCOMP
5673#include "scip/sorttpl.c" /*lint !e451*/
5674
5675
5676/* SCIPsortPtrRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5677#define SORTTPL_NAMEEXT PtrRealIntInt
5678#define SORTTPL_KEYTYPE void*
5679#define SORTTPL_FIELD1TYPE SCIP_Real
5680#define SORTTPL_FIELD2TYPE int
5681#define SORTTPL_FIELD3TYPE int
5682#define SORTTPL_PTRCOMP
5683#include "scip/sorttpl.c" /*lint !e451*/
5684
5685
5686/* SCIPsortPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5687#define SORTTPL_NAMEEXT PtrPtrIntInt
5688#define SORTTPL_KEYTYPE void*
5689#define SORTTPL_FIELD1TYPE void*
5690#define SORTTPL_FIELD2TYPE int
5691#define SORTTPL_FIELD3TYPE int
5692#define SORTTPL_PTRCOMP
5693#include "scip/sorttpl.c" /*lint !e451*/
5694
5695
5696/* SCIPsortPtrPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5697#define SORTTPL_NAMEEXT PtrPtrRealInt
5698#define SORTTPL_KEYTYPE void*
5699#define SORTTPL_FIELD1TYPE void*
5700#define SORTTPL_FIELD2TYPE SCIP_Real
5701#define SORTTPL_FIELD3TYPE int
5702#define SORTTPL_PTRCOMP
5703#include "scip/sorttpl.c" /*lint !e451*/
5704
5705
5706/* SCIPsortPtrPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5707#define SORTTPL_NAMEEXT PtrPtrRealBool
5708#define SORTTPL_KEYTYPE void*
5709#define SORTTPL_FIELD1TYPE void*
5710#define SORTTPL_FIELD2TYPE SCIP_Real
5711#define SORTTPL_FIELD3TYPE SCIP_Bool
5712#define SORTTPL_PTRCOMP
5713#include "scip/sorttpl.c" /*lint !e451*/
5714
5715
5716/* SCIPsortPtrPtrLongInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5717#define SORTTPL_NAMEEXT PtrPtrLongInt
5718#define SORTTPL_KEYTYPE void*
5719#define SORTTPL_FIELD1TYPE void*
5720#define SORTTPL_FIELD2TYPE SCIP_Longint
5721#define SORTTPL_FIELD3TYPE int
5722#define SORTTPL_PTRCOMP
5723#include "scip/sorttpl.c" /*lint !e451*/
5724
5725
5726/* SCIPsortPtrPtrLongIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5727#define SORTTPL_NAMEEXT PtrPtrLongIntInt
5728#define SORTTPL_KEYTYPE void*
5729#define SORTTPL_FIELD1TYPE void*
5730#define SORTTPL_FIELD2TYPE SCIP_Longint
5731#define SORTTPL_FIELD3TYPE int
5732#define SORTTPL_FIELD4TYPE int
5733#define SORTTPL_PTRCOMP
5734#include "scip/sorttpl.c" /*lint !e451*/
5735
5736
5737/* SCIPsortReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5738#define SORTTPL_NAMEEXT Real
5739#define SORTTPL_KEYTYPE SCIP_Real
5740#include "scip/sorttpl.c" /*lint !e451*/
5741
5742
5743/* SCIPsortRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5744#define SORTTPL_NAMEEXT RealBoolPtr
5745#define SORTTPL_KEYTYPE SCIP_Real
5746#define SORTTPL_FIELD1TYPE SCIP_Bool
5747#define SORTTPL_FIELD2TYPE void*
5748#include "scip/sorttpl.c" /*lint !e451*/
5749
5750
5751/* SCIPsortRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5752#define SORTTPL_NAMEEXT RealPtr
5753#define SORTTPL_KEYTYPE SCIP_Real
5754#define SORTTPL_FIELD1TYPE void*
5755#include "scip/sorttpl.c" /*lint !e451*/
5756
5757
5758/* SCIPsortRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5759#define SORTTPL_NAMEEXT RealInt
5760#define SORTTPL_KEYTYPE SCIP_Real
5761#define SORTTPL_FIELD1TYPE int
5762#include "scip/sorttpl.c" /*lint !e451*/
5763
5764
5765/* SCIPsortRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5766#define SORTTPL_NAMEEXT RealIntInt
5767#define SORTTPL_KEYTYPE SCIP_Real
5768#define SORTTPL_FIELD1TYPE int
5769#define SORTTPL_FIELD2TYPE int
5770#include "scip/sorttpl.c" /*lint !e451*/
5771
5772
5773/* SCIPsortRealIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5774#define SORTTPL_NAMEEXT RealIntLong
5775#define SORTTPL_KEYTYPE SCIP_Real
5776#define SORTTPL_FIELD1TYPE int
5777#define SORTTPL_FIELD2TYPE SCIP_Longint
5778#include "scip/sorttpl.c" /*lint !e451*/
5779
5780
5781/* SCIPsortRealIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5782#define SORTTPL_NAMEEXT RealIntPtr
5783#define SORTTPL_KEYTYPE SCIP_Real
5784#define SORTTPL_FIELD1TYPE int
5785#define SORTTPL_FIELD2TYPE void*
5786#include "scip/sorttpl.c" /*lint !e451*/
5787
5788
5789/* SCIPsortRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5790#define SORTTPL_NAMEEXT RealRealPtr
5791#define SORTTPL_KEYTYPE SCIP_Real
5792#define SORTTPL_FIELD1TYPE SCIP_Real
5793#define SORTTPL_FIELD2TYPE void*
5794#include "scip/sorttpl.c" /*lint !e451*/
5795
5796
5797/* SCIPsortRealLongRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5798#define SORTTPL_NAMEEXT RealLongRealInt
5799#define SORTTPL_KEYTYPE SCIP_Real
5800#define SORTTPL_FIELD1TYPE SCIP_Longint
5801#define SORTTPL_FIELD2TYPE SCIP_Real
5802#define SORTTPL_FIELD3TYPE int
5803#include "scip/sorttpl.c" /*lint !e451*/
5804
5805/* SCIPsortRealRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5806#define SORTTPL_NAMEEXT RealRealIntInt
5807#define SORTTPL_KEYTYPE SCIP_Real
5808#define SORTTPL_FIELD1TYPE SCIP_Real
5809#define SORTTPL_FIELD2TYPE int
5810#define SORTTPL_FIELD3TYPE int
5811#include "scip/sorttpl.c" /*lint !e451*/
5812
5813
5814/* SCIPsortRealRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5815#define SORTTPL_NAMEEXT RealRealRealInt
5816#define SORTTPL_KEYTYPE SCIP_Real
5817#define SORTTPL_FIELD1TYPE SCIP_Real
5818#define SORTTPL_FIELD2TYPE SCIP_Real
5819#define SORTTPL_FIELD3TYPE int
5820#include "scip/sorttpl.c" /*lint !e451*/
5821
5822
5823/* SCIPsortRealRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5824#define SORTTPL_NAMEEXT RealRealRealPtr
5825#define SORTTPL_KEYTYPE SCIP_Real
5826#define SORTTPL_FIELD1TYPE SCIP_Real
5827#define SORTTPL_FIELD2TYPE SCIP_Real
5828#define SORTTPL_FIELD3TYPE void*
5829#include "scip/sorttpl.c" /*lint !e451*/
5830
5831
5832/* SCIPsortRealPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5833#define SORTTPL_NAMEEXT RealPtrPtrInt
5834#define SORTTPL_KEYTYPE SCIP_Real
5835#define SORTTPL_FIELD1TYPE void*
5836#define SORTTPL_FIELD2TYPE void*
5837#define SORTTPL_FIELD3TYPE int
5838#include "scip/sorttpl.c" /*lint !e451*/
5839
5840
5841/* SCIPsortRealPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5842#define SORTTPL_NAMEEXT RealPtrPtrIntInt
5843#define SORTTPL_KEYTYPE SCIP_Real
5844#define SORTTPL_FIELD1TYPE void*
5845#define SORTTPL_FIELD2TYPE void*
5846#define SORTTPL_FIELD3TYPE int
5847#define SORTTPL_FIELD4TYPE int
5848#include "scip/sorttpl.c" /*lint !e451*/
5849
5850
5851/* SCIPsortRealRealRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5852#define SORTTPL_NAMEEXT RealRealRealBoolPtr
5853#define SORTTPL_KEYTYPE SCIP_Real
5854#define SORTTPL_FIELD1TYPE SCIP_Real
5855#define SORTTPL_FIELD2TYPE SCIP_Real
5856#define SORTTPL_FIELD3TYPE SCIP_Bool
5857#define SORTTPL_FIELD4TYPE void*
5858#include "scip/sorttpl.c" /*lint !e451*/
5859
5860
5861/* SCIPsortRealRealRealBoolBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5862#define SORTTPL_NAMEEXT RealRealRealBoolBoolPtr
5863#define SORTTPL_KEYTYPE SCIP_Real
5864#define SORTTPL_FIELD1TYPE SCIP_Real
5865#define SORTTPL_FIELD2TYPE SCIP_Real
5866#define SORTTPL_FIELD3TYPE SCIP_Bool
5867#define SORTTPL_FIELD4TYPE SCIP_Bool
5868#define SORTTPL_FIELD5TYPE void*
5869#include "scip/sorttpl.c" /*lint !e451*/
5870
5871
5872/* SCIPsortInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5873#define SORTTPL_NAMEEXT Int
5874#define SORTTPL_KEYTYPE int
5875#include "scip/sorttpl.c" /*lint !e451*/
5876
5877
5878/* SCIPsortIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5879#define SORTTPL_NAMEEXT IntInt
5880#define SORTTPL_KEYTYPE int
5881#define SORTTPL_FIELD1TYPE int
5882#include "scip/sorttpl.c" /*lint !e451*/
5883
5884
5885/* SCIPsortIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5886#define SORTTPL_NAMEEXT IntReal
5887#define SORTTPL_KEYTYPE int
5888#define SORTTPL_FIELD1TYPE SCIP_Real
5889#include "scip/sorttpl.c" /*lint !e451*/
5890
5891
5892/* SCIPsortIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5893#define SORTTPL_NAMEEXT IntPtr
5894#define SORTTPL_KEYTYPE int
5895#define SORTTPL_FIELD1TYPE void*
5896#include "scip/sorttpl.c" /*lint !e451*/
5897
5898
5899/* SCIPsortIntIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5900#define SORTTPL_NAMEEXT IntIntInt
5901#define SORTTPL_KEYTYPE int
5902#define SORTTPL_FIELD1TYPE int
5903#define SORTTPL_FIELD2TYPE int
5904#include "scip/sorttpl.c" /*lint !e451*/
5905
5906
5907/* SCIPsortIntIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5908#define SORTTPL_NAMEEXT IntIntLong
5909#define SORTTPL_KEYTYPE int
5910#define SORTTPL_FIELD1TYPE int
5911#define SORTTPL_FIELD2TYPE SCIP_Longint
5912#include "scip/sorttpl.c" /*lint !e451*/
5913
5914/* SCIPsortIntRealLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5915#define SORTTPL_NAMEEXT IntRealLong
5916#define SORTTPL_KEYTYPE int
5917#define SORTTPL_FIELD1TYPE SCIP_Real
5918#define SORTTPL_FIELD2TYPE SCIP_Longint
5919#include "scip/sorttpl.c" /*lint !e451*/
5920
5921
5922/* SCIPsortIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5923#define SORTTPL_NAMEEXT IntIntPtr
5924#define SORTTPL_KEYTYPE int
5925#define SORTTPL_FIELD1TYPE int
5926#define SORTTPL_FIELD2TYPE void*
5927#include "scip/sorttpl.c" /*lint !e451*/
5928
5929
5930/* SCIPsortIntIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5931#define SORTTPL_NAMEEXT IntIntReal
5932#define SORTTPL_KEYTYPE int
5933#define SORTTPL_FIELD1TYPE int
5934#define SORTTPL_FIELD2TYPE SCIP_Real
5935#include "scip/sorttpl.c" /*lint !e451*/
5936
5937
5938/* SCIPsortIntPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5939#define SORTTPL_NAMEEXT IntPtrReal
5940#define SORTTPL_KEYTYPE int
5941#define SORTTPL_FIELD1TYPE void*
5942#define SORTTPL_FIELD2TYPE SCIP_Real
5943#include "scip/sorttpl.c" /*lint !e451*/
5944
5945
5946/* SCIPsortIntIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5947#define SORTTPL_NAMEEXT IntIntIntPtr
5948#define SORTTPL_KEYTYPE int
5949#define SORTTPL_FIELD1TYPE int
5950#define SORTTPL_FIELD2TYPE int
5951#define SORTTPL_FIELD3TYPE void*
5952#include "scip/sorttpl.c" /*lint !e451*/
5953
5954/* SCIPsortIntIntIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5955#define SORTTPL_NAMEEXT IntIntIntReal
5956#define SORTTPL_KEYTYPE int
5957#define SORTTPL_FIELD1TYPE int
5958#define SORTTPL_FIELD2TYPE int
5959#define SORTTPL_FIELD3TYPE SCIP_Real
5960#include "scip/sorttpl.c" /*lint !e451*/
5961
5962/* SCIPsortIntPtrIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5963#define SORTTPL_NAMEEXT IntPtrIntReal
5964#define SORTTPL_KEYTYPE int
5965#define SORTTPL_FIELD1TYPE void*
5966#define SORTTPL_FIELD2TYPE int
5967#define SORTTPL_FIELD3TYPE SCIP_Real
5968#include "scip/sorttpl.c" /*lint !e451*/
5969
5970
5971/* SCIPsortLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5972#define SORTTPL_NAMEEXT Long
5973#define SORTTPL_KEYTYPE SCIP_Longint
5974#include "scip/sorttpl.c" /*lint !e451*/
5975
5976
5977/* SCIPsortLongPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5978#define SORTTPL_NAMEEXT LongPtr
5979#define SORTTPL_KEYTYPE SCIP_Longint
5980#define SORTTPL_FIELD1TYPE void*
5981#include "scip/sorttpl.c" /*lint !e451*/
5982
5983
5984/* SCIPsortLongPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5985#define SORTTPL_NAMEEXT LongPtrInt
5986#define SORTTPL_KEYTYPE SCIP_Longint
5987#define SORTTPL_FIELD1TYPE void*
5988#define SORTTPL_FIELD2TYPE int
5989#include "scip/sorttpl.c" /*lint !e451*/
5990
5991
5992/* SCIPsortLongPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5993#define SORTTPL_NAMEEXT LongPtrRealBool
5994#define SORTTPL_KEYTYPE SCIP_Longint
5995#define SORTTPL_FIELD1TYPE void*
5996#define SORTTPL_FIELD2TYPE SCIP_Real
5997#define SORTTPL_FIELD3TYPE SCIP_Bool
5998#include "scip/sorttpl.c" /*lint !e451*/
5999
6000
6001/* SCIPsortLongPtrRealRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6002#define SORTTPL_NAMEEXT LongPtrRealRealBool
6003#define SORTTPL_KEYTYPE SCIP_Longint
6004#define SORTTPL_FIELD1TYPE void*
6005#define SORTTPL_FIELD2TYPE SCIP_Real
6006#define SORTTPL_FIELD3TYPE SCIP_Real
6007#define SORTTPL_FIELD4TYPE SCIP_Bool
6008#include "scip/sorttpl.c" /*lint !e451*/
6009
6010
6011/* SCIPsortLongPtrRealRealIntBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6012#define SORTTPL_NAMEEXT LongPtrRealRealIntBool
6013#define SORTTPL_KEYTYPE SCIP_Longint
6014#define SORTTPL_FIELD1TYPE void*
6015#define SORTTPL_FIELD2TYPE SCIP_Real
6016#define SORTTPL_FIELD3TYPE SCIP_Real
6017#define SORTTPL_FIELD4TYPE int
6018#define SORTTPL_FIELD5TYPE SCIP_Bool
6019#include "scip/sorttpl.c" /*lint !e451*/
6020
6021
6022/* SCIPsortLongPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6023#define SORTTPL_NAMEEXT LongPtrPtrInt
6024#define SORTTPL_KEYTYPE SCIP_Longint
6025#define SORTTPL_FIELD1TYPE void*
6026#define SORTTPL_FIELD2TYPE void*
6027#define SORTTPL_FIELD3TYPE int
6028#include "scip/sorttpl.c" /*lint !e451*/
6029
6030
6031/* SCIPsortLongPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6032#define SORTTPL_NAMEEXT LongPtrPtrIntInt
6033#define SORTTPL_KEYTYPE SCIP_Longint
6034#define SORTTPL_FIELD1TYPE void*
6035#define SORTTPL_FIELD2TYPE void*
6036#define SORTTPL_FIELD3TYPE int
6037#define SORTTPL_FIELD4TYPE int
6038#include "scip/sorttpl.c" /*lint !e451*/
6039
6040
6041/* SCIPsortLongPtrPtrBoolInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6042#define SORTTPL_NAMEEXT LongPtrPtrBoolInt
6043#define SORTTPL_KEYTYPE SCIP_Longint
6044#define SORTTPL_FIELD1TYPE void*
6045#define SORTTPL_FIELD2TYPE void*
6046#define SORTTPL_FIELD3TYPE SCIP_Bool
6047#define SORTTPL_FIELD4TYPE int
6048#include "scip/sorttpl.c" /*lint !e451*/
6049
6050
6051/* SCIPsortPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6052#define SORTTPL_NAMEEXT PtrIntIntBoolBool
6053#define SORTTPL_KEYTYPE void*
6054#define SORTTPL_FIELD1TYPE int
6055#define SORTTPL_FIELD2TYPE int
6056#define SORTTPL_FIELD3TYPE SCIP_Bool
6057#define SORTTPL_FIELD4TYPE SCIP_Bool
6058#define SORTTPL_PTRCOMP
6059#include "scip/sorttpl.c" /*lint !e451*/
6060
6061
6062/* SCIPsortIntPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6063#define SORTTPL_NAMEEXT IntPtrIntIntBoolBool
6064#define SORTTPL_KEYTYPE int
6065#define SORTTPL_FIELD1TYPE void*
6066#define SORTTPL_FIELD2TYPE int
6067#define SORTTPL_FIELD3TYPE int
6068#define SORTTPL_FIELD4TYPE SCIP_Bool
6069#define SORTTPL_FIELD5TYPE SCIP_Bool
6070#include "scip/sorttpl.c" /*lint !e451*/
6071
6072
6073/* now all downwards-sorting methods */
6074
6075
6076/** sort an indexed element set in non-increasing order, resulting in a permutation index array */
6078 int* perm, /**< pointer to store the resulting permutation */
6079 SCIP_DECL_SORTINDCOMP((*indcomp)), /**< data element comparator */
6080 void* dataptr, /**< pointer to data field that is given to the external compare method */
6081 int len /**< number of elements to be sorted (valid index range) */
6082 )
6083{
6084 int pos;
6085
6086 assert(indcomp != NULL);
6087 assert(len == 0 || perm != NULL);
6088
6089 /* create identity permutation */
6090 for( pos = 0; pos < len; ++pos )
6091 perm[pos] = pos;
6092
6093 SCIPsortDownInd(perm, indcomp, dataptr, len);
6094}
6095
6096
6097/* SCIPsortDownInd(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6098#define SORTTPL_NAMEEXT DownInd
6099#define SORTTPL_KEYTYPE int
6100#define SORTTPL_INDCOMP
6101#define SORTTPL_BACKWARDS
6102#include "scip/sorttpl.c" /*lint !e451*/
6103
6104
6105/* SCIPsortDownPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6106#define SORTTPL_NAMEEXT DownPtr
6107#define SORTTPL_KEYTYPE void*
6108#define SORTTPL_PTRCOMP
6109#define SORTTPL_BACKWARDS
6110#include "scip/sorttpl.c" /*lint !e451*/
6111
6112
6113/* SCIPsortDownPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6114#define SORTTPL_NAMEEXT DownPtrPtr
6115#define SORTTPL_KEYTYPE void*
6116#define SORTTPL_FIELD1TYPE void*
6117#define SORTTPL_PTRCOMP
6118#define SORTTPL_BACKWARDS
6119#include "scip/sorttpl.c" /*lint !e451*/
6120
6121
6122/* SCIPsortDownPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6123#define SORTTPL_NAMEEXT DownPtrReal
6124#define SORTTPL_KEYTYPE void*
6125#define SORTTPL_FIELD1TYPE SCIP_Real
6126#define SORTTPL_PTRCOMP
6127#define SORTTPL_BACKWARDS
6128#include "scip/sorttpl.c" /*lint !e451*/
6129
6130
6131/* SCIPsortDownPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6132#define SORTTPL_NAMEEXT DownPtrInt
6133#define SORTTPL_KEYTYPE void*
6134#define SORTTPL_FIELD1TYPE int
6135#define SORTTPL_PTRCOMP
6136#define SORTTPL_BACKWARDS
6137#include "scip/sorttpl.c" /*lint !e451*/
6138
6139/* SCIPsortDownPtrBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6140#define SORTTPL_NAMEEXT DownPtrBool
6141#define SORTTPL_KEYTYPE void*
6142#define SORTTPL_FIELD1TYPE SCIP_Bool
6143#define SORTTPL_PTRCOMP
6144#define SORTTPL_BACKWARDS
6145#include "scip/sorttpl.c" /*lint !e451*/
6146
6147/* SCIPsortDownPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6148#define SORTTPL_NAMEEXT DownPtrIntInt
6149#define SORTTPL_KEYTYPE void*
6150#define SORTTPL_FIELD1TYPE int
6151#define SORTTPL_FIELD2TYPE int
6152#define SORTTPL_PTRCOMP
6153#define SORTTPL_BACKWARDS
6154#include "scip/sorttpl.c" /*lint !e451*/
6155
6156
6157/* SCIPsortDownPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6158#define SORTTPL_NAMEEXT DownPtrRealInt
6159#define SORTTPL_KEYTYPE void*
6160#define SORTTPL_FIELD1TYPE SCIP_Real
6161#define SORTTPL_FIELD2TYPE int
6162#define SORTTPL_PTRCOMP
6163#define SORTTPL_BACKWARDS
6164#include "scip/sorttpl.c" /*lint !e451*/
6165
6166
6167/* SCIPsortDownPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6168#define SORTTPL_NAMEEXT DownPtrRealBool
6169#define SORTTPL_KEYTYPE void*
6170#define SORTTPL_FIELD1TYPE SCIP_Real
6171#define SORTTPL_FIELD2TYPE SCIP_Bool
6172#define SORTTPL_PTRCOMP
6173#define SORTTPL_BACKWARDS
6174#include "scip/sorttpl.c" /*lint !e451*/
6175
6176
6177/* SCIPsortDownPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6178#define SORTTPL_NAMEEXT DownPtrPtrInt
6179#define SORTTPL_KEYTYPE void*
6180#define SORTTPL_FIELD1TYPE void*
6181#define SORTTPL_FIELD2TYPE int
6182#define SORTTPL_PTRCOMP
6183#define SORTTPL_BACKWARDS
6184#include "scip/sorttpl.c" /*lint !e451*/
6185
6186
6187/* SCIPsortDownPtrPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6188#define SORTTPL_NAMEEXT DownPtrPtrReal
6189#define SORTTPL_KEYTYPE void*
6190#define SORTTPL_FIELD1TYPE void*
6191#define SORTTPL_FIELD2TYPE SCIP_Real
6192#define SORTTPL_PTRCOMP
6193#define SORTTPL_BACKWARDS
6194#include "scip/sorttpl.c" /*lint !e451*/
6195
6196
6197/* SCIPsortDownPtrRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6198#define SORTTPL_NAMEEXT DownPtrRealIntInt
6199#define SORTTPL_KEYTYPE void*
6200#define SORTTPL_FIELD1TYPE SCIP_Real
6201#define SORTTPL_FIELD2TYPE int
6202#define SORTTPL_FIELD3TYPE int
6203#define SORTTPL_PTRCOMP
6204#define SORTTPL_BACKWARDS
6205#include "scip/sorttpl.c" /*lint !e451*/
6206
6207
6208/* SCIPsortDownPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6209#define SORTTPL_NAMEEXT DownPtrPtrIntInt
6210#define SORTTPL_KEYTYPE void*
6211#define SORTTPL_FIELD1TYPE void*
6212#define SORTTPL_FIELD2TYPE int
6213#define SORTTPL_FIELD3TYPE int
6214#define SORTTPL_PTRCOMP
6215#define SORTTPL_BACKWARDS
6216#include "scip/sorttpl.c" /*lint !e451*/
6217
6218
6219/* SCIPsortDownPtrPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6220#define SORTTPL_NAMEEXT DownPtrPtrRealInt
6221#define SORTTPL_KEYTYPE void*
6222#define SORTTPL_FIELD1TYPE void*
6223#define SORTTPL_FIELD2TYPE SCIP_Real
6224#define SORTTPL_FIELD3TYPE int
6225#define SORTTPL_PTRCOMP
6226#define SORTTPL_BACKWARDS
6227#include "scip/sorttpl.c" /*lint !e451*/
6228
6229
6230/* SCIPsortDownPtrPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6231#define SORTTPL_NAMEEXT DownPtrPtrRealBool
6232#define SORTTPL_KEYTYPE void*
6233#define SORTTPL_FIELD1TYPE void*
6234#define SORTTPL_FIELD2TYPE SCIP_Real
6235#define SORTTPL_FIELD3TYPE SCIP_Bool
6236#define SORTTPL_PTRCOMP
6237#define SORTTPL_BACKWARDS
6238#include "scip/sorttpl.c" /*lint !e451*/
6239
6240
6241/* SCIPsortDownPtrPtrLongInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6242#define SORTTPL_NAMEEXT DownPtrPtrLongInt
6243#define SORTTPL_KEYTYPE void*
6244#define SORTTPL_FIELD1TYPE void*
6245#define SORTTPL_FIELD2TYPE SCIP_Longint
6246#define SORTTPL_FIELD3TYPE int
6247#define SORTTPL_PTRCOMP
6248#define SORTTPL_BACKWARDS
6249#include "scip/sorttpl.c" /*lint !e451*/
6250
6251
6252/* SCIPsortDownPtrPtrLongIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6253#define SORTTPL_NAMEEXT DownPtrPtrLongIntInt
6254#define SORTTPL_KEYTYPE void*
6255#define SORTTPL_FIELD1TYPE void*
6256#define SORTTPL_FIELD2TYPE SCIP_Longint
6257#define SORTTPL_FIELD3TYPE int
6258#define SORTTPL_FIELD4TYPE int
6259#define SORTTPL_PTRCOMP
6260#define SORTTPL_BACKWARDS
6261#include "scip/sorttpl.c" /*lint !e451*/
6262
6263
6264/* SCIPsortDownReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6265#define SORTTPL_NAMEEXT DownReal
6266#define SORTTPL_KEYTYPE SCIP_Real
6267#define SORTTPL_BACKWARDS
6268#include "scip/sorttpl.c" /*lint !e451*/
6269
6270
6271/* SCIPsortDownRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6272#define SORTTPL_NAMEEXT DownRealBoolPtr
6273#define SORTTPL_KEYTYPE SCIP_Real
6274#define SORTTPL_FIELD1TYPE SCIP_Bool
6275#define SORTTPL_FIELD2TYPE void*
6276#define SORTTPL_BACKWARDS
6277#include "scip/sorttpl.c" /*lint !e451*/
6278
6279
6280/* SCIPsortDownRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6281#define SORTTPL_NAMEEXT DownRealPtr
6282#define SORTTPL_KEYTYPE SCIP_Real
6283#define SORTTPL_FIELD1TYPE void*
6284#define SORTTPL_BACKWARDS
6285#include "scip/sorttpl.c" /*lint !e451*/
6286
6287
6288/* SCIPsortDownRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6289#define SORTTPL_NAMEEXT DownRealInt
6290#define SORTTPL_KEYTYPE SCIP_Real
6291#define SORTTPL_FIELD1TYPE int
6292#define SORTTPL_BACKWARDS
6293#include "scip/sorttpl.c" /*lint !e451*/
6294
6295/* SCIPsortDownRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6296#define SORTTPL_NAMEEXT DownRealIntInt
6297#define SORTTPL_KEYTYPE SCIP_Real
6298#define SORTTPL_FIELD1TYPE int
6299#define SORTTPL_FIELD2TYPE int
6300#define SORTTPL_BACKWARDS
6301#include "scip/sorttpl.c" /*lint !e451*/
6302
6303/* SCIPsortDownRealIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6304#define SORTTPL_NAMEEXT DownRealIntLong
6305#define SORTTPL_KEYTYPE SCIP_Real
6306#define SORTTPL_FIELD1TYPE int
6307#define SORTTPL_FIELD2TYPE SCIP_Longint
6308#define SORTTPL_BACKWARDS
6309#include "scip/sorttpl.c" /*lint !e451*/
6310
6311
6312/* SCIPsortDownRealIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6313#define SORTTPL_NAMEEXT DownRealIntPtr
6314#define SORTTPL_KEYTYPE SCIP_Real
6315#define SORTTPL_FIELD1TYPE int
6316#define SORTTPL_FIELD2TYPE void*
6317#define SORTTPL_BACKWARDS
6318#include "scip/sorttpl.c" /*lint !e451*/
6319
6320
6321/* SCIPsortDownRealPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6322#define SORTTPL_NAMEEXT DownRealPtrPtr
6323#define SORTTPL_KEYTYPE SCIP_Real
6324#define SORTTPL_FIELD1TYPE void*
6325#define SORTTPL_FIELD2TYPE void*
6326#define SORTTPL_BACKWARDS
6327#include "scip/sorttpl.c" /*lint !e451*/
6328
6329/* SCIPsortDownRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6330#define SORTTPL_NAMEEXT DownRealRealInt
6331#define SORTTPL_KEYTYPE SCIP_Real
6332#define SORTTPL_FIELD1TYPE SCIP_Real
6333#define SORTTPL_FIELD2TYPE int
6334#define SORTTPL_BACKWARDS
6335#include "scip/sorttpl.c" /*lint !e451*/
6336
6337/* SCIPsortDownRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6338#define SORTTPL_NAMEEXT DownRealRealPtr
6339#define SORTTPL_KEYTYPE SCIP_Real
6340#define SORTTPL_FIELD1TYPE SCIP_Real
6341#define SORTTPL_FIELD2TYPE void*
6342#define SORTTPL_BACKWARDS
6343#include "scip/sorttpl.c" /*lint !e451*/
6344
6345/* SCIPsortDownRealRealPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6346#define SORTTPL_NAMEEXT DownRealRealPtrPtr
6347#define SORTTPL_KEYTYPE SCIP_Real
6348#define SORTTPL_FIELD1TYPE SCIP_Real
6349#define SORTTPL_FIELD2TYPE void*
6350#define SORTTPL_FIELD3TYPE void*
6351#define SORTTPL_BACKWARDS
6352#include "scip/sorttpl.c" /*lint !e451*/
6353
6354
6355/* SCIPsortDownRealLongRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6356#define SORTTPL_NAMEEXT DownRealLongRealInt
6357#define SORTTPL_KEYTYPE SCIP_Real
6358#define SORTTPL_FIELD1TYPE SCIP_Longint
6359#define SORTTPL_FIELD2TYPE SCIP_Real
6360#define SORTTPL_FIELD3TYPE int
6361#define SORTTPL_BACKWARDS
6362#include "scip/sorttpl.c" /*lint !e451*/
6363
6364
6365/* SCIPsortDownRealRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6366#define SORTTPL_NAMEEXT DownRealRealIntInt
6367#define SORTTPL_KEYTYPE SCIP_Real
6368#define SORTTPL_FIELD1TYPE SCIP_Real
6369#define SORTTPL_FIELD2TYPE int
6370#define SORTTPL_FIELD3TYPE int
6371#define SORTTPL_BACKWARDS
6372#include "scip/sorttpl.c" /*lint !e451*/
6373
6374
6375/* SCIPsortDownRealRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6376#define SORTTPL_NAMEEXT DownRealRealRealInt
6377#define SORTTPL_KEYTYPE SCIP_Real
6378#define SORTTPL_FIELD1TYPE SCIP_Real
6379#define SORTTPL_FIELD2TYPE SCIP_Real
6380#define SORTTPL_FIELD3TYPE int
6381#define SORTTPL_BACKWARDS
6382#include "scip/sorttpl.c" /*lint !e451*/
6383
6384
6385/* SCIPsortDownRealRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6386#define SORTTPL_NAMEEXT DownRealRealRealPtr
6387#define SORTTPL_KEYTYPE SCIP_Real
6388#define SORTTPL_FIELD1TYPE SCIP_Real
6389#define SORTTPL_FIELD2TYPE SCIP_Real
6390#define SORTTPL_FIELD3TYPE void*
6391#define SORTTPL_BACKWARDS
6392#include "scip/sorttpl.c" /*lint !e451*/
6393
6394
6395/* SCIPsortDownRealPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6396#define SORTTPL_NAMEEXT DownRealPtrPtrInt
6397#define SORTTPL_KEYTYPE SCIP_Real
6398#define SORTTPL_FIELD1TYPE void*
6399#define SORTTPL_FIELD2TYPE void*
6400#define SORTTPL_FIELD3TYPE int
6401#define SORTTPL_BACKWARDS
6402#include "scip/sorttpl.c" /*lint !e451*/
6403
6404/* SCIPsortDownRealPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6405#define SORTTPL_NAMEEXT DownRealPtrPtrIntInt
6406#define SORTTPL_KEYTYPE SCIP_Real
6407#define SORTTPL_FIELD1TYPE void*
6408#define SORTTPL_FIELD2TYPE void*
6409#define SORTTPL_FIELD3TYPE int
6410#define SORTTPL_FIELD4TYPE int
6411#define SORTTPL_BACKWARDS
6412#include "scip/sorttpl.c" /*lint !e451*/
6413
6414
6415/* SCIPsortDownRealRealRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6416#define SORTTPL_NAMEEXT DownRealRealRealBoolPtr
6417#define SORTTPL_KEYTYPE SCIP_Real
6418#define SORTTPL_FIELD1TYPE SCIP_Real
6419#define SORTTPL_FIELD2TYPE SCIP_Real
6420#define SORTTPL_FIELD3TYPE SCIP_Bool
6421#define SORTTPL_FIELD4TYPE void*
6422#define SORTTPL_BACKWARDS
6423#include "scip/sorttpl.c" /*lint !e451*/
6424
6425
6426/* SCIPsortDownRealRealRealBoolBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6427#define SORTTPL_NAMEEXT DownRealRealRealBoolBoolPtr
6428#define SORTTPL_KEYTYPE SCIP_Real
6429#define SORTTPL_FIELD1TYPE SCIP_Real
6430#define SORTTPL_FIELD2TYPE SCIP_Real
6431#define SORTTPL_FIELD3TYPE SCIP_Bool
6432#define SORTTPL_FIELD4TYPE SCIP_Bool
6433#define SORTTPL_FIELD5TYPE void*
6434#include "scip/sorttpl.c" /*lint !e451*/
6435
6436
6437/* SCIPsortDownInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6438#define SORTTPL_NAMEEXT DownInt
6439#define SORTTPL_KEYTYPE int
6440#define SORTTPL_BACKWARDS
6441#include "scip/sorttpl.c" /*lint !e451*/
6442
6443
6444/* SCIPsortDownIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6445#define SORTTPL_NAMEEXT DownIntInt
6446#define SORTTPL_KEYTYPE int
6447#define SORTTPL_FIELD1TYPE int
6448#define SORTTPL_BACKWARDS
6449#include "scip/sorttpl.c" /*lint !e451*/
6450
6451
6452/* SCIPsortDownIntIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6453#define SORTTPL_NAMEEXT DownIntIntReal
6454#define SORTTPL_KEYTYPE int
6455#define SORTTPL_FIELD1TYPE int
6456#define SORTTPL_FIELD2TYPE SCIP_Real
6457#define SORTTPL_BACKWARDS
6458#include "scip/sorttpl.c" /*lint !e451*/
6459
6460
6461/* SCIPsortDownIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6462#define SORTTPL_NAMEEXT DownIntReal
6463#define SORTTPL_KEYTYPE int
6464#define SORTTPL_FIELD1TYPE SCIP_Real
6465#define SORTTPL_BACKWARDS
6466#include "scip/sorttpl.c" /*lint !e451*/
6467
6468
6469/* SCIPsortDownIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6470#define SORTTPL_NAMEEXT DownIntPtr
6471#define SORTTPL_KEYTYPE int
6472#define SORTTPL_FIELD1TYPE void*
6473#define SORTTPL_BACKWARDS
6474#include "scip/sorttpl.c" /*lint !e451*/
6475
6476
6477/* SCIPsortDownIntIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6478#define SORTTPL_NAMEEXT DownIntIntInt
6479#define SORTTPL_KEYTYPE int
6480#define SORTTPL_FIELD1TYPE int
6481#define SORTTPL_FIELD2TYPE int
6482#define SORTTPL_BACKWARDS
6483#include "scip/sorttpl.c" /*lint !e451*/
6484
6485
6486/* SCIPsortDownIntIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6487#define SORTTPL_NAMEEXT DownIntIntLong
6488#define SORTTPL_KEYTYPE int
6489#define SORTTPL_FIELD1TYPE int
6490#define SORTTPL_FIELD2TYPE SCIP_Longint
6491#define SORTTPL_BACKWARDS
6492#include "scip/sorttpl.c" /*lint !e451*/
6493
6494
6495/* SCIPsortDownIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6496#define SORTTPL_NAMEEXT DownIntIntPtr
6497#define SORTTPL_KEYTYPE int
6498#define SORTTPL_FIELD1TYPE int
6499#define SORTTPL_FIELD2TYPE void*
6500#define SORTTPL_BACKWARDS
6501#include "scip/sorttpl.c" /*lint !e451*/
6502
6503
6504/* SCIPsortDownIntIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6505#define SORTTPL_NAMEEXT DownIntIntIntPtr
6506#define SORTTPL_KEYTYPE int
6507#define SORTTPL_FIELD1TYPE int
6508#define SORTTPL_FIELD2TYPE int
6509#define SORTTPL_FIELD3TYPE void*
6510#define SORTTPL_BACKWARDS
6511#include "scip/sorttpl.c" /*lint !e451*/
6512
6513
6514/* SCIPsortDownIntPtrIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6515#define SORTTPL_NAMEEXT DownIntPtrIntReal
6516#define SORTTPL_KEYTYPE int
6517#define SORTTPL_FIELD1TYPE void*
6518#define SORTTPL_FIELD2TYPE int
6519#define SORTTPL_FIELD3TYPE SCIP_Real
6520#define SORTTPL_BACKWARDS
6521#include "scip/sorttpl.c" /*lint !e451*/
6522
6523
6524/* SCIPsortDownLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6525#define SORTTPL_NAMEEXT DownLong
6526#define SORTTPL_KEYTYPE SCIP_Longint
6527#define SORTTPL_BACKWARDS
6528#include "scip/sorttpl.c" /*lint !e451*/
6529
6530
6531/* SCIPsortDownLongPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6532#define SORTTPL_NAMEEXT DownLongPtr
6533#define SORTTPL_KEYTYPE SCIP_Longint
6534#define SORTTPL_FIELD1TYPE void*
6535#define SORTTPL_BACKWARDS
6536#include "scip/sorttpl.c" /*lint !e451*/
6537
6538
6539/* SCIPsortDownLongPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6540#define SORTTPL_NAMEEXT DownLongPtrInt
6541#define SORTTPL_KEYTYPE SCIP_Longint
6542#define SORTTPL_FIELD1TYPE void*
6543#define SORTTPL_FIELD2TYPE int
6544#define SORTTPL_BACKWARDS
6545#include "scip/sorttpl.c" /*lint !e451*/
6546
6547
6548/* SCIPsortDownLongPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6549#define SORTTPL_NAMEEXT DownLongPtrRealBool
6550#define SORTTPL_KEYTYPE SCIP_Longint
6551#define SORTTPL_FIELD1TYPE void*
6552#define SORTTPL_FIELD2TYPE SCIP_Real
6553#define SORTTPL_FIELD3TYPE SCIP_Bool
6554#define SORTTPL_BACKWARDS
6555#include "scip/sorttpl.c" /*lint !e451*/
6556
6557
6558/* SCIPsortDownLongPtrRealRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6559#define SORTTPL_NAMEEXT DownLongPtrRealRealBool
6560#define SORTTPL_KEYTYPE SCIP_Longint
6561#define SORTTPL_FIELD1TYPE void*
6562#define SORTTPL_FIELD2TYPE SCIP_Real
6563#define SORTTPL_FIELD3TYPE SCIP_Real
6564#define SORTTPL_FIELD4TYPE SCIP_Bool
6565#define SORTTPL_BACKWARDS
6566#include "scip/sorttpl.c" /*lint !e451*/
6567
6568
6569/* SCIPsortLongPtrRealRealIntBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6570#define SORTTPL_NAMEEXT DownLongPtrRealRealIntBool
6571#define SORTTPL_KEYTYPE SCIP_Longint
6572#define SORTTPL_FIELD1TYPE void*
6573#define SORTTPL_FIELD2TYPE SCIP_Real
6574#define SORTTPL_FIELD3TYPE SCIP_Real
6575#define SORTTPL_FIELD4TYPE int
6576#define SORTTPL_FIELD5TYPE SCIP_Bool
6577#define SORTTPL_BACKWARDS
6578#include "scip/sorttpl.c" /*lint !e451*/
6579
6580
6581/* SCIPsortDownLongPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6582#define SORTTPL_NAMEEXT DownLongPtrPtrInt
6583#define SORTTPL_KEYTYPE SCIP_Longint
6584#define SORTTPL_FIELD1TYPE void*
6585#define SORTTPL_FIELD2TYPE void*
6586#define SORTTPL_FIELD3TYPE int
6587#define SORTTPL_BACKWARDS
6588#include "scip/sorttpl.c" /*lint !e451*/
6589
6590
6591/* SCIPsortDownLongPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6592#define SORTTPL_NAMEEXT DownLongPtrPtrIntInt
6593#define SORTTPL_KEYTYPE SCIP_Longint
6594#define SORTTPL_FIELD1TYPE void*
6595#define SORTTPL_FIELD2TYPE void*
6596#define SORTTPL_FIELD3TYPE int
6597#define SORTTPL_FIELD4TYPE int
6598#define SORTTPL_BACKWARDS
6599#include "scip/sorttpl.c" /*lint !e451*/
6600
6601
6602/* SCIPsortDownLongPtrPtrBoolInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6603#define SORTTPL_NAMEEXT DownLongPtrPtrBoolInt
6604#define SORTTPL_KEYTYPE SCIP_Longint
6605#define SORTTPL_FIELD1TYPE void*
6606#define SORTTPL_FIELD2TYPE void*
6607#define SORTTPL_FIELD3TYPE SCIP_Bool
6608#define SORTTPL_FIELD4TYPE int
6609#define SORTTPL_BACKWARDS
6610#include "scip/sorttpl.c" /*lint !e451*/
6611
6612
6613/* SCIPsortDownPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6614#define SORTTPL_NAMEEXT DownPtrIntIntBoolBool
6615#define SORTTPL_KEYTYPE void*
6616#define SORTTPL_FIELD1TYPE int
6617#define SORTTPL_FIELD2TYPE int
6618#define SORTTPL_FIELD3TYPE SCIP_Bool
6619#define SORTTPL_FIELD4TYPE SCIP_Bool
6620#define SORTTPL_PTRCOMP
6621#define SORTTPL_BACKWARDS
6622#include "scip/sorttpl.c" /*lint !e451*/
6623
6624
6625/* SCIPsortDownIntPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6626#define SORTTPL_NAMEEXT DownIntPtrIntIntBoolBool
6627#define SORTTPL_KEYTYPE int
6628#define SORTTPL_FIELD1TYPE void*
6629#define SORTTPL_FIELD2TYPE int
6630#define SORTTPL_FIELD3TYPE int
6631#define SORTTPL_FIELD4TYPE SCIP_Bool
6632#define SORTTPL_FIELD5TYPE SCIP_Bool
6633#define SORTTPL_BACKWARDS
6634#include "scip/sorttpl.c" /*lint !e451*/
6635
6636/*
6637 * Resulting activity
6638 */
6639
6640/** create a resource activity */
6642 SCIP_RESOURCEACTIVITY** activity, /**< pointer to store the resource activity */
6643 SCIP_VAR* var, /**< start time variable of the activity */
6644 int duration, /**< duration of the activity */
6645 int demand /**< demand of the activity */
6646 )
6647{
6648 assert(activity != NULL);
6649
6650 SCIP_ALLOC( BMSallocMemory(activity) );
6651
6652 (*activity)->var = var;
6653 (*activity)->duration = duration;
6654 (*activity)->demand = demand;
6655
6656 return SCIP_OKAY;
6657}
6658
6659/** frees a resource activity */
6661 SCIP_RESOURCEACTIVITY** activity /**< pointer to the resource activity */
6662 )
6663{
6664 assert(activity != NULL);
6665 assert(*activity != NULL);
6666
6667 BMSfreeMemory(activity);
6668}
6669
6670/* some simple variable functions implemented as defines */
6671
6672#ifndef NDEBUG
6673
6674/* In debug mode, the following methods are implemented as function calls to ensure
6675 * type validity.
6676 * In optimized mode, the methods are implemented as defines to improve performance.
6677 * However, we want to have them in the library anyways, so we have to undef the defines.
6678 */
6679
6680#undef SCIPactivityGetVar
6681#undef SCIPactivityGetDuration
6682#undef SCIPactivityGetDemand
6683#undef SCIPactivityGetEnergy
6684
6685/** returns the start time variable of the resource activity */
6687 SCIP_RESOURCEACTIVITY* activity /**< resource activity */
6688 )
6689{
6690 assert(activity != NULL);
6691
6692 return activity->var;
6693}
6694
6695/** returns the duration of the resource activity */
6697 SCIP_RESOURCEACTIVITY* activity /**< resource activity */
6698 )
6699{
6700 assert(activity != NULL);
6701
6702 return activity->duration;
6703}
6704
6705/** returns the demand of the resource activity */
6707 SCIP_RESOURCEACTIVITY* activity /**< resource activity */
6708 )
6709{
6710 assert(activity != NULL);
6711
6712 return activity->demand;
6713}
6714
6715/** returns the energy of the resource activity */
6717 SCIP_RESOURCEACTIVITY* activity /**< resource activity */
6718 )
6719{
6720 assert(activity != NULL);
6721
6722 return activity->duration * activity->demand ;
6723}
6724
6725#endif
6726
6727/*
6728 * Resource Profile
6729 */
6730
6731/** helper method to create a profile */
6732static
6734 SCIP_PROFILE** profile, /**< pointer to store the resource profile */
6735 int capacity /**< resource capacity */
6736 )
6737{
6738 SCIP_ALLOC( BMSallocMemory(profile) );
6739 BMSclearMemory(*profile);
6740
6741 (*profile)->arraysize = 10;
6742 SCIP_ALLOC( BMSallocMemoryArray(&(*profile)->timepoints, (*profile)->arraysize) );
6743 SCIP_ALLOC( BMSallocMemoryArray(&(*profile)->loads, (*profile)->arraysize) );
6744
6745 /* setup resource profile for use */
6746 (*profile)->ntimepoints = 1;
6747 (*profile)->timepoints[0] = 0;
6748 (*profile)->loads[0] = 0;
6749 (*profile)->capacity = capacity;
6750
6751 return SCIP_OKAY;
6752}
6753
6754/** creates resource profile */
6756 SCIP_PROFILE** profile, /**< pointer to store the resource profile */
6757 int capacity /**< resource capacity */
6758 )
6759{
6760 assert(profile != NULL);
6761 assert(capacity > 0);
6762
6763 SCIP_CALL_FINALLY( doProfileCreate(profile, capacity), SCIPprofileFree(profile) );
6764
6765 return SCIP_OKAY;
6766}
6767
6768/** frees given resource profile */
6770 SCIP_PROFILE** profile /**< pointer to the resource profile */
6771 )
6772{
6773 assert(profile != NULL);
6774
6775 /* free resource profile */
6776 if( *profile != NULL )
6777 {
6778 BMSfreeMemoryArrayNull(&(*profile)->loads);
6779 BMSfreeMemoryArrayNull(&(*profile)->timepoints);
6780 BMSfreeMemory(profile);
6781 }
6782}
6783
6784/** output of the given resource profile */
6786 SCIP_PROFILE* profile, /**< resource profile to output */
6787 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
6788 FILE* file /**< output file (or NULL for standard output) */
6789 )
6790{
6791 int t;
6792
6793 SCIPmessageFPrintInfo(messagehdlr, file, "Profile <%p> (capacity %d) --> ", (void*)profile, profile->capacity);
6794
6795 for( t = 0; t < profile->ntimepoints; ++t )
6796 {
6797 if( t == 0 )
6798 SCIPmessageFPrintInfo(messagehdlr, file, "%d:(%d,%d)", t, profile->timepoints[t], profile->loads[t]);
6799 else
6800 SCIPmessageFPrintInfo(messagehdlr, file, ", %d:(%d,%d)", t, profile->timepoints[t], profile->loads[t]);
6801 }
6802
6803 SCIPmessageFPrintInfo(messagehdlr, file,"\n");
6804}
6805
6806/** returns the capacity of the resource profile */
6808 SCIP_PROFILE* profile /**< resource profile to use */
6809 )
6810{
6811 assert(profile != NULL);
6812
6813 return profile->capacity;
6814}
6815
6816/** returns the number time points of the resource profile */
6818 SCIP_PROFILE* profile /**< resource profile to use */
6819 )
6820{
6821 assert(profile != NULL);
6822
6823 return profile->ntimepoints;
6824}
6825
6826/** returns the time points of the resource profile */
6828 SCIP_PROFILE* profile /**< resource profile to use */
6829 )
6830{
6831 assert(profile != NULL);
6832
6833 return profile->timepoints;
6834}
6835
6836/** returns the loads of the resource profile */
6838 SCIP_PROFILE* profile /**< resource profile to use */
6839 )
6840{
6841 assert(profile != NULL);
6842
6843 return profile->loads;
6844}
6845
6846/** returns the time point for given position of the resource profile */
6848 SCIP_PROFILE* profile, /**< resource profile to use */
6849 int pos /**< position */
6850 )
6851{
6852 assert(profile != NULL);
6853 assert(pos >= 0 && pos < profile->ntimepoints);
6854
6855 return profile->timepoints[pos];
6856}
6857
6858/** returns the loads of the resource profile at the given position */
6860 SCIP_PROFILE* profile, /**< resource profile */
6861 int pos /**< position */
6862 )
6863{
6864 assert(profile != NULL);
6865 assert(pos >= 0 && pos < profile->ntimepoints);
6866
6867 return profile->loads[pos];
6868}
6869
6870/** returns if the given time point exists in the resource profile and stores the position of the given time point if it
6871 * exists; otherwise the position of the next smaller existing time point is stored
6872 */
6874 SCIP_PROFILE* profile, /**< resource profile to search */
6875 int timepoint, /**< time point to search for */
6876 int* pos /**< pointer to store the position */
6877 )
6878{
6879 assert(profile != NULL);
6880 assert(timepoint >= 0);
6881 assert(profile->ntimepoints > 0);
6882 assert(profile->timepoints[0] == 0);
6883
6884 /* find the position of time point in the time points array via binary search */
6885 if( SCIPsortedvecFindInt(profile->timepoints, timepoint, profile->ntimepoints, pos) )
6886 return TRUE;
6887
6888 assert(*pos > 0);
6889 (*pos)--;
6890
6891 return FALSE;
6892}
6893
6894/* ensures that resource profile arrays is big enough */
6895static
6897 SCIP_PROFILE* profile, /**< resource profile to insert the time point */
6898 int neededsize /**< needed size */
6899 )
6900{
6901 assert(profile->arraysize > 0);
6902
6903 /* check whether the arrays are big enough */
6904 if( neededsize <= profile->arraysize )
6905 return SCIP_OKAY;
6906
6907 profile->arraysize *= 2;
6908
6909 SCIP_ALLOC( BMSreallocMemoryArray(&profile->timepoints, profile->arraysize) );
6910 SCIP_ALLOC( BMSreallocMemoryArray(&profile->loads, profile->arraysize) );
6911
6912 return SCIP_OKAY;
6913}
6914
6915/** inserts the given time point into the resource profile if it this time point does not exists yet; returns its
6916 * position in the time point array
6917 */
6918static
6920 SCIP_PROFILE* profile, /**< resource profile to insert the time point */
6921 int timepoint, /**< time point to insert */
6922 int* pos /**< pointer to store the insert position */
6923 )
6924{
6925 assert(profile != NULL);
6926 assert(timepoint >= 0);
6927 assert(profile->arraysize >= profile->ntimepoints);
6928
6929 /* get the position of the given time point in the resource profile array if it exists; otherwise the position of the
6930 * next smaller existing time point
6931 */
6932 if( !SCIPprofileFindLeft(profile, timepoint, pos) )
6933 {
6934 assert(*pos >= 0 && *pos < profile->ntimepoints);
6935 assert(timepoint >= profile->timepoints[*pos]);
6936
6937 /* ensure that the arrays are big enough */
6938 SCIP_CALL( ensureProfileSize(profile, profile->ntimepoints + 1) );
6939 assert(profile->arraysize > profile->ntimepoints);
6940
6941 /* insert new time point into the (sorted) resource profile */
6942 SCIPsortedvecInsertIntInt(profile->timepoints, profile->loads, timepoint, profile->loads[*pos],
6943 &profile->ntimepoints, pos);
6944 }
6945
6946#ifndef NDEBUG
6947 /* check if the time points are sorted */
6948 {
6949 int i;
6950 for( i = 1; i < profile->ntimepoints; ++i )
6951 assert(profile->timepoints[i-1] < profile->timepoints[i]);
6952 }
6953#endif
6954
6955 return SCIP_OKAY;
6956}
6957
6958/** updates the resource profile due to inserting of a core */
6959static
6961 SCIP_PROFILE* profile, /**< resource profile to update */
6962 int left, /**< left side of core interval */
6963 int right, /**< right side of core interval */
6964 int demand, /**< demand of the core */
6965 int* pos, /**< pointer to store the first position were it gets infeasible */
6966 SCIP_Bool* infeasible /**< pointer to store if the update is infeasible */
6967 )
6968{
6969 int startpos;
6970 int endpos;
6971 int i;
6972
6973 assert(profile != NULL);
6974 assert(profile->arraysize >= profile->ntimepoints);
6975 assert(left >= 0);
6976 assert(left < right);
6977 assert(infeasible != NULL);
6978
6979 (*infeasible) = FALSE;
6980 (*pos) = -1;
6981
6982 /* get position of the starttime in profile */
6983 SCIP_CALL( profileInsertTimepoint(profile, left, &startpos) );
6984 assert(profile->timepoints[startpos] == left);
6985
6986 /* get position of the endtime in profile */
6987 SCIP_CALL( profileInsertTimepoint(profile, right, &endpos) );
6988 assert(profile->timepoints[endpos] == right);
6989
6990 assert(startpos < endpos);
6991 assert(profile->arraysize >= profile->ntimepoints);
6992
6993 /* remove/add the given demand from the core */
6994 for( i = startpos; i < endpos; ++i )
6995 {
6996 profile->loads[i] += demand;
6997
6998 /* check if the core fits */
6999 if( profile->loads[i] > profile->capacity )
7000 {
7001 SCIPdebugMessage("core insertion detected infeasibility (pos %d)\n", i);
7002
7003 (*infeasible) = TRUE;
7004 (*pos) = i;
7005
7006 /* remove the partly inserted core since it does fit completely */
7007 for( ; i >= startpos; --i ) /*lint !e445*/
7008 profile->loads[i] -= demand;
7009
7010 break;
7011 }
7012 }
7013
7014 return SCIP_OKAY;
7015}
7016
7017/** insert a core into resource profile; if the core is non-empty the resource profile will be updated otherwise nothing
7018 * happens
7019 */
7021 SCIP_PROFILE* profile, /**< resource profile */
7022 int left, /**< left side of the core */
7023 int right, /**< right side of the core */
7024 int demand, /**< demand of the core */
7025 int* pos, /**< pointer to store the first position were it gets infeasible */
7026 SCIP_Bool* infeasible /**< pointer to store if the core does not fit due to capacity */
7027 )
7028{
7029 assert(profile != NULL);
7030 assert(left < right);
7031 assert(demand >= 0);
7032 assert(infeasible != NULL);
7033
7034 (*infeasible) = FALSE;
7035 (*pos) = -1;
7036
7037 /* insert core into the resource profile */
7038 SCIPdebugMessage("insert core [%d,%d] with demand %d\n", left, right, demand);
7039
7040 if( demand > 0 )
7041 {
7042 /* try to insert core into the resource profile */
7043 SCIP_CALL( profileUpdate(profile, left, right, demand, pos, infeasible) );
7044 }
7045
7046 return SCIP_OKAY;
7047}
7048
7049/** subtracts the demand from the resource profile during core time */
7051 SCIP_PROFILE* profile, /**< resource profile to use */
7052 int left, /**< left side of the core */
7053 int right, /**< right side of the core */
7054 int demand /**< demand of the core */
7055 )
7056{
7057 SCIP_Bool infeasible;
7058 int pos;
7059
7060 assert(left < right);
7061#ifndef NDEBUG
7062 {
7063 /* check if the left and right time points of the core correspond to a time point in the resource profile; this
7064 * should be the case since we added the core before to the resource profile
7065 */
7066 assert(SCIPprofileFindLeft(profile, left, &pos));
7067 assert(SCIPprofileFindLeft(profile, right, &pos));
7068 }
7069#endif
7070
7071 /* remove the core from the resource profile */
7072 SCIPdebugMessage("delete core [%d,%d] with demand %d\n", left, right, demand);
7073
7074 SCIP_CALL( profileUpdate(profile, left, right, -demand, &pos, &infeasible) );
7075 assert(!infeasible);
7076
7077 return SCIP_OKAY; /*lint !e438*/
7078}
7079
7080/** returns TRUE if the core (given by its demand and during) can be inserted at the given time point; otherwise FALSE */
7081static
7083 SCIP_PROFILE* profile, /**< resource profile to use */
7084 int pos, /**< pointer to store the position in the profile to start the serch */
7085 int lst, /**< latest start time */
7086 int duration, /**< duration of the core */
7087 int demand, /**< demand of the core */
7088 SCIP_Bool* infeasible /**< pointer store if the corer cannot be inserted */
7089 )
7090{
7091 int remainingduration;
7092 int startpos;
7093
7094 assert(profile != NULL);
7095 assert(pos >= 0);
7096 assert(pos < profile->ntimepoints);
7097 assert(duration > 0);
7098 assert(demand > 0);
7099 assert(profile->loads[profile->ntimepoints-1] == 0);
7100
7101 remainingduration = duration;
7102 startpos = pos;
7103 (*infeasible) = FALSE;
7104
7105 if( profile->timepoints[startpos] > lst )
7106 {
7107 (*infeasible) = TRUE;
7108 return pos;
7109 }
7110
7111 while( pos < profile->ntimepoints - 1 )
7112 {
7113 if( profile->loads[pos] + demand > profile->capacity )
7114 {
7115 SCIPdebugMessage("profile <%p>: core does not fit at time point %d (pos %d)\n", (void*)profile, profile->timepoints[pos], pos);
7116 startpos = pos + 1;
7117 remainingduration = duration;
7118
7119 if( profile->timepoints[startpos] > lst )
7120 {
7121 (*infeasible) = TRUE;
7122 return pos;
7123 }
7124 }
7125 else
7126 remainingduration -= profile->timepoints[pos+1] - profile->timepoints[pos];
7127
7128 if( remainingduration <= 0 )
7129 break;
7130
7131 pos++;
7132 }
7133
7134 return startpos;
7135}
7136
7137/** return the earliest possible starting point within the time interval [lb,ub] for a given core (given by its demand
7138 * and duration)
7139 */
7141 SCIP_PROFILE* profile, /**< resource profile to use */
7142 int est, /**< earliest starting time of the given core */
7143 int lst, /**< latest starting time of the given core */
7144 int duration, /**< duration of the core */
7145 int demand, /**< demand of the core */
7146 SCIP_Bool* infeasible /**< pointer store if the corer cannot be inserted */
7147 )
7148{
7149 SCIP_Bool found;
7150 int pos;
7151
7152 assert(profile != NULL);
7153 assert(est >= 0);
7154 assert(est <= lst);
7155 assert(duration >= 0);
7156 assert(demand >= 0);
7157 assert(infeasible != NULL);
7158 assert(profile->ntimepoints > 0);
7159 assert(profile->loads[profile->ntimepoints-1] == 0);
7160
7161 SCIPdebugMessage("profile <%p>: find earliest start time (demad %d, duration %d) [%d,%d]\n", (void*)profile, demand, duration, est, lst);
7162
7163 if( duration == 0 || demand == 0 )
7164 {
7165 *infeasible = FALSE;
7166 return est;
7167 }
7168
7169 found = SCIPprofileFindLeft(profile, est, &pos);
7170 SCIPdebugMessage("profile <%p>: earliest start time does %s exist as time point (pos %d)\n", (void*)profile, found ? "" : "not", pos);
7171
7172 /* if the position is the last time point in the profile, the core can be inserted at its earliest start time */
7173 if( pos == profile->ntimepoints - 1 )
7174 {
7175 (*infeasible) = FALSE;
7176 return est;
7177 }
7178
7179 if( found )
7180 {
7181 /* if the start time matches a time point in the profile we can just search */
7182 assert(profile->timepoints[pos] == est);
7183 pos = profileFindFeasibleStart(profile, pos, lst, duration, demand, infeasible);
7184
7185 assert(pos < profile->ntimepoints);
7186 est = profile->timepoints[pos];
7187 }
7188 else if( profile->loads[pos] + demand > profile->capacity )
7189 {
7190 /* if the the time point left to the start time has not enough free capacity we can just search the profile
7191 * starting from the next time point
7192 */
7193 assert(profile->timepoints[pos] <= est);
7194 pos = profileFindFeasibleStart(profile, pos+1, lst, duration, demand, infeasible);
7195
7196 assert(pos < profile->ntimepoints);
7197 est = profile->timepoints[pos];
7198 }
7199 else
7200 {
7201 int remainingduration;
7202
7203 /* check if the core can be placed at its earliest start time */
7204
7205 assert(pos < profile->ntimepoints - 1);
7206
7207 remainingduration = duration - (profile->timepoints[pos+1] - est);
7208 SCIPdebugMessage("remaining duration %d\n", remainingduration);
7209
7210 if( remainingduration <= 0 )
7211 (*infeasible) = FALSE;
7212 else
7213 {
7214 pos = profileFindFeasibleStart(profile, pos+1, profile->timepoints[pos+1], remainingduration, demand, infeasible);
7215 SCIPdebugMessage("remaining duration can%s be processed\n", *infeasible ? "not" : "");
7216
7217 if( *infeasible )
7218 {
7219 pos = profileFindFeasibleStart(profile, pos+1, lst, duration, demand, infeasible);
7220
7221 assert(pos < profile->ntimepoints);
7222 est = profile->timepoints[pos];
7223 }
7224 }
7225 }
7226
7227 return est;
7228}
7229
7230/** returns TRUE if the core (given by its demand and during) can be inserted at the given time point; otherwise FALSE */
7231static
7233 SCIP_PROFILE* profile, /**< resource profile to use */
7234 int pos, /**< pointer to store the position in the profile to start the search */
7235 int ect, /**< earliest completion time */
7236 int duration, /**< duration of the core */
7237 int demand, /**< demand of the core */
7238 SCIP_Bool* infeasible /**< pointer store if the corer cannot be inserted */
7239 )
7240{
7241 int remainingduration;
7242 int endpos;
7243
7244 assert(profile != NULL);
7245 assert(pos >= 0);
7246 assert(pos < profile->ntimepoints);
7247 assert(duration > 0);
7248 assert(demand > 0);
7249 assert(profile->ntimepoints > 0);
7250 assert(profile->loads[profile->ntimepoints-1] == 0);
7251
7252 remainingduration = duration;
7253 endpos = pos;
7254 (*infeasible) = TRUE;
7255
7256 if( profile->timepoints[endpos] < ect - duration )
7257 return pos;
7258
7259 while( pos > 0 )
7260 {
7261 if( profile->loads[pos-1] + demand > profile->capacity )
7262 {
7263 SCIPdebugMessage("profile <%p>: core does not fit at time point %d (pos %d)\n", (void*)profile, profile->timepoints[pos-1], pos-1);
7264
7265 endpos = pos - 1;
7266 remainingduration = duration;
7267
7268 if( profile->timepoints[endpos] < ect - duration )
7269 return pos;
7270 }
7271 else
7272 remainingduration -= profile->timepoints[pos] - profile->timepoints[pos-1];
7273
7274 if( remainingduration <= 0 )
7275 {
7276 *infeasible = FALSE;
7277 break;
7278 }
7279
7280 pos--;
7281 }
7282
7283 return endpos;
7284}
7285
7286/** return the latest possible starting point within the time interval [lb,ub] for a given core (given by its demand and
7287 * duration)
7288 */
7290 SCIP_PROFILE* profile, /**< resource profile to use */
7291 int est, /**< earliest possible start point */
7292 int lst, /**< latest possible start point */
7293 int duration, /**< duration of the core */
7294 int demand, /**< demand of the core */
7295 SCIP_Bool* infeasible /**< pointer store if the core cannot be inserted */
7296 )
7297{
7298 SCIP_Bool found;
7299 int ect;
7300 int lct;
7301 int pos;
7302
7303 assert(profile != NULL);
7304 assert(est >= 0);
7305 assert(est <= lst);
7306 assert(duration >= 0);
7307 assert(demand >= 0);
7308 assert(infeasible != NULL);
7309 assert(profile->ntimepoints > 0);
7310 assert(profile->loads[profile->ntimepoints-1] == 0);
7311
7312 if( duration == 0 || demand == 0 )
7313 {
7314 *infeasible = FALSE;
7315 return lst;
7316 }
7317
7318 ect = est + duration;
7319 lct = lst + duration;
7320
7321 found = SCIPprofileFindLeft(profile, lct, &pos);
7322 SCIPdebugMessage("profile <%p>: latest completion time %d does %s exist as time point (pos %d)\n", (void*)profile, lct, found ? "" : "not", pos);
7323
7324 if( found )
7325 {
7326 /* if the start time matches a time point in the profile we can just search */
7327 assert(profile->timepoints[pos] == lct);
7328 pos = profileFindDownFeasibleStart(profile, pos, ect, duration, demand, infeasible);
7329
7330 assert(pos < profile->ntimepoints && pos >= 0);
7331 lct = profile->timepoints[pos];
7332 }
7333 else if( profile->loads[pos] + demand > profile->capacity )
7334 {
7335 /* if the time point left to the start time has not enough free capacity we can just search the profile starting
7336 * from the next time point
7337 */
7338 assert(profile->timepoints[pos] < lct);
7339 pos = profileFindDownFeasibleStart(profile, pos, ect, duration, demand, infeasible);
7340
7341 assert(pos < profile->ntimepoints && pos >= 0);
7342 lct = profile->timepoints[pos];
7343 }
7344 else
7345 {
7346 int remainingduration;
7347
7348 /* check if the core can be placed at its latest start time */
7349 assert(profile->timepoints[pos] < lct);
7350
7351 remainingduration = duration - (lct - profile->timepoints[pos]);
7352
7353 if( remainingduration <= 0 )
7354 (*infeasible) = FALSE;
7355 else
7356 {
7357 pos = profileFindDownFeasibleStart(profile, pos, profile->timepoints[pos], remainingduration, demand, infeasible);
7358
7359 if( *infeasible )
7360 {
7361 pos = profileFindDownFeasibleStart(profile, pos, ect, duration, demand, infeasible);
7362
7363 assert(pos < profile->ntimepoints && pos >= 0);
7364 lct = profile->timepoints[pos];
7365 }
7366 }
7367 }
7368
7369 return lct - duration;
7370}
7371
7372/*
7373 * Directed graph
7374 */
7375
7376/** creates directed graph structure */
7378 SCIP_DIGRAPH** digraph, /**< pointer to store the created directed graph */
7379 BMS_BLKMEM* blkmem, /**< block memory to store the data */
7380 int nnodes /**< number of nodes */
7381 )
7382{
7383 assert(digraph != NULL);
7384 assert(blkmem != NULL);
7385 assert(nnodes > 0);
7386
7387 /* allocate memory for the graph and the arrays storing arcs and data */
7388 SCIP_ALLOC( BMSallocBlockMemory(blkmem, digraph) );
7389 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->successors, nnodes) );
7390 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->arcdata, nnodes) );
7391 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->successorssize, nnodes) );
7392 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->nsuccessors, nnodes) );
7393 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->nodedata, nnodes) );
7394
7395 /* store number of nodes */
7396 (*digraph)->nnodes = nnodes;
7397
7398 /* at the beginning, no components are stored */
7399 (*digraph)->blkmem = blkmem;
7400 (*digraph)->ncomponents = 0;
7401 (*digraph)->componentstartsize = 0;
7402 (*digraph)->components = NULL;
7403 (*digraph)->componentstarts = NULL;
7404
7405 /* all nodes are initially considered as non-articulation points */
7406 (*digraph)->narticulations = -1;
7407 (*digraph)->articulations = NULL;
7408 (*digraph)->articulationscheck = FALSE;
7409
7410 return SCIP_OKAY;
7411}
7412
7413/** resize directed graph structure */
7415 SCIP_DIGRAPH* digraph, /**< directed graph */
7416 int nnodes /**< new number of nodes */
7417 )
7418{
7419 int n;
7420 assert(digraph != NULL);
7421 assert(digraph->blkmem != NULL);
7422
7423 /* check if the digraph has already a proper size */
7424 if( nnodes <= digraph->nnodes )
7425 return SCIP_OKAY;
7426
7427 /* reallocate memory for increasing the arrays storing arcs and data */
7428 SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->successors, digraph->nnodes, nnodes) );
7429 SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->arcdata, digraph->nnodes, nnodes) );
7430 SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->successorssize, digraph->nnodes, nnodes) );
7431 SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->nsuccessors, digraph->nnodes, nnodes) );
7432 SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->nodedata, digraph->nnodes, nnodes) );
7433
7434 /* initialize the new node data structures */
7435 for( n = digraph->nnodes; n < nnodes; ++n )
7436 {
7437 digraph->nodedata[n] = NULL;
7438 digraph->arcdata[n] = NULL;
7439 digraph->successors[n] = NULL;
7440 digraph->successorssize[n] = 0;
7441 digraph->nsuccessors[n] = 0;
7442 }
7443
7444 /* store the new number of nodes */
7445 digraph->nnodes = nnodes;
7446
7447 return SCIP_OKAY;
7448}
7449
7450/** copies directed graph structure
7451 *
7452 * @note The data in nodedata is copied verbatim. This possibly has to be adapted by the user.
7453 */
7455 SCIP_DIGRAPH** targetdigraph, /**< pointer to store the copied directed graph */
7456 SCIP_DIGRAPH* sourcedigraph, /**< source directed graph */
7457 BMS_BLKMEM* targetblkmem /**< block memory to store the target block memory, or NULL to use the same
7458 * the same block memory as used for the \p sourcedigraph */
7459 )
7460{
7461 int ncomponents;
7462 int nnodes;
7463 int i;
7464 SCIP_Bool articulationscheck;
7465
7466 assert(sourcedigraph != NULL);
7467 assert(targetdigraph != NULL);
7468
7469 /* use the source digraph block memory if not specified otherwise */
7470 if( targetblkmem == NULL )
7471 targetblkmem = sourcedigraph->blkmem;
7472
7473 assert(targetblkmem != NULL);
7474
7475 SCIP_ALLOC( BMSallocBlockMemory(targetblkmem, targetdigraph) );
7476
7477 nnodes = sourcedigraph->nnodes;
7478 ncomponents = sourcedigraph->ncomponents;
7479 articulationscheck = sourcedigraph->articulationscheck;
7480 (*targetdigraph)->nnodes = nnodes;
7481 (*targetdigraph)->ncomponents = ncomponents;
7482 (*targetdigraph)->blkmem = targetblkmem;
7483
7484 /* copy arcs and data */
7485 SCIP_ALLOC( BMSallocClearBlockMemoryArray(targetblkmem, &(*targetdigraph)->successors, nnodes) );
7486 SCIP_ALLOC( BMSallocClearBlockMemoryArray(targetblkmem, &(*targetdigraph)->arcdata, nnodes) );
7487 SCIP_ALLOC( BMSallocClearBlockMemoryArray(targetblkmem, &(*targetdigraph)->nodedata, nnodes) );
7488
7489 /* copy lists of successors and arc data */
7490 for( i = 0; i < nnodes; ++i )
7491 {
7492 if( sourcedigraph->nsuccessors[i] > 0 )
7493 {
7494 assert(sourcedigraph->successors[i] != NULL);
7495 assert(sourcedigraph->arcdata[i] != NULL);
7496
7497 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &((*targetdigraph)->successors[i]),
7498 sourcedigraph->successors[i], sourcedigraph->nsuccessors[i]) ); /*lint !e866*/
7499 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &((*targetdigraph)->arcdata[i]),
7500 sourcedigraph->arcdata[i], sourcedigraph->nsuccessors[i]) ); /*lint !e866*/
7501 }
7502 /* copy node data - careful if these are pointers to some information -> need to be copied by hand */
7503 (*targetdigraph)->nodedata[i] = sourcedigraph->nodedata[i];
7504 }
7505
7506 /* use nsuccessors as size to save memory */
7507 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->successorssize, sourcedigraph->nsuccessors, nnodes) );
7508 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->nsuccessors, sourcedigraph->nsuccessors, nnodes) );
7509
7510 /* copy component data */
7511 if( ncomponents > 0 )
7512 {
7513 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->components, sourcedigraph->components,
7514 sourcedigraph->componentstarts[ncomponents]) );
7515 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->componentstarts,
7516 sourcedigraph->componentstarts,ncomponents + 1) ); /*lint !e776*/
7517 (*targetdigraph)->componentstartsize = ncomponents + 1;
7518 }
7519 else
7520 {
7521 (*targetdigraph)->components = NULL;
7522 (*targetdigraph)->componentstarts = NULL;
7523 (*targetdigraph)->componentstartsize = 0;
7524 }
7525
7526 /* copy the articulation point information if it has been computed and is up-to-date */
7527 if( articulationscheck )
7528 {
7529 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->articulations, sourcedigraph->articulations, sourcedigraph->narticulations) );
7530 (*targetdigraph)->narticulations = sourcedigraph->narticulations;
7531 (*targetdigraph)->articulationscheck = TRUE;
7532 }
7533 else
7534 {
7535 (*targetdigraph)->narticulations = -1;
7536 (*targetdigraph)->articulations = NULL;
7537 (*targetdigraph)->articulationscheck = FALSE;
7538 }
7539
7540 return SCIP_OKAY;
7541}
7542
7543/** sets the sizes of the successor lists for the nodes in a directed graph and allocates memory for the lists */
7545 SCIP_DIGRAPH* digraph, /**< directed graph */
7546 int* sizes /**< sizes of the successor lists */
7547 )
7548{
7549 int i;
7550 BMS_BLKMEM* blkmem;
7551
7552 assert(digraph != NULL);
7553 assert(digraph->nnodes > 0);
7554 blkmem = digraph->blkmem;
7555
7556 for( i = 0; i < digraph->nnodes; ++i )
7557 {
7558 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->successors[i], sizes[i]) ); /*lint !e866*/
7559 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->arcdata[i], sizes[i]) ); /*lint !e866*/
7560 digraph->successorssize[i] = sizes[i];
7561 digraph->nsuccessors[i] = 0;
7562 }
7563
7564 return SCIP_OKAY;
7565}
7566
7567/** frees given directed graph structure */
7569 SCIP_DIGRAPH** digraph /**< pointer to the directed graph */
7570 )
7571{
7572 int i;
7573 BMS_BLKMEM* blkmem;
7574 SCIP_DIGRAPH* digraphptr;
7575
7576 assert(digraph != NULL);
7577 assert(*digraph != NULL);
7578 assert((*digraph)->blkmem != NULL);
7579
7580 blkmem = (*digraph)->blkmem;
7581 digraphptr = *digraph;
7582
7583 /* free arrays storing the successor nodes and arc data */
7584 for( i = digraphptr->nnodes - 1; i >= 0; --i )
7585 {
7586 BMSfreeBlockMemoryArrayNull(blkmem, &digraphptr->successors[i], digraphptr->successorssize[i]);
7587 BMSfreeBlockMemoryArrayNull(blkmem, &digraphptr->arcdata[i], digraphptr->successorssize[i]);
7588 }
7589
7590 /* free components structure */
7591 SCIPdigraphFreeComponents(digraphptr);
7592 assert(digraphptr->ncomponents == 0);
7593 assert(digraphptr->componentstartsize == 0);
7594 assert(digraphptr->components == NULL);
7595 assert(digraphptr->componentstarts == NULL);
7596
7597 /* free the articulation points structure if it has been computed*/
7598 if( digraphptr->articulationscheck )
7599 BMSfreeBlockMemoryArray(blkmem, &digraphptr->articulations, digraphptr->narticulations);
7600
7601 /* free directed graph data structure */
7602 BMSfreeBlockMemoryArray(blkmem, &digraphptr->nodedata, digraphptr->nnodes);
7603 BMSfreeBlockMemoryArray(blkmem, &digraphptr->successorssize, digraphptr->nnodes);
7604 BMSfreeBlockMemoryArray(blkmem, &digraphptr->nsuccessors, digraphptr->nnodes);
7605 BMSfreeBlockMemoryArray(blkmem, &digraphptr->successors, digraphptr->nnodes);
7606 BMSfreeBlockMemoryArray(blkmem, &digraphptr->arcdata, digraphptr->nnodes);
7607
7608 BMSfreeBlockMemory(blkmem, digraph);
7609}
7610
7611#define STARTSUCCESSORSSIZE 5
7612
7613/** ensures that successors array of one node in a directed graph is big enough */
7614static
7616 SCIP_DIGRAPH* digraph, /**< directed graph */
7617 int idx, /**< index for which the size is ensured */
7618 int newsize /**< needed size */
7619 )
7620{
7621 BMS_BLKMEM* blkmem;
7622
7623 assert(digraph != NULL);
7624 assert(digraph->blkmem != NULL);
7625 assert(idx >= 0);
7626 assert(idx < digraph->nnodes);
7627 assert(newsize > 0);
7628 assert(digraph->successorssize[idx] == 0 || digraph->successors[idx] != NULL);
7629 assert(digraph->successorssize[idx] == 0 || digraph->arcdata[idx] != NULL);
7630
7631 blkmem = digraph->blkmem;
7632
7633 /* check whether array is big enough, and realloc, if needed */
7634 if( newsize > digraph->successorssize[idx] )
7635 {
7636 if( digraph->successors[idx] == NULL )
7637 {
7638 assert(digraph->arcdata[idx] == NULL);
7639 digraph->successorssize[idx] = STARTSUCCESSORSSIZE;
7640 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->successors[idx], digraph->successorssize[idx]) ); /*lint !e866*/
7641 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->arcdata[idx], digraph->successorssize[idx]) ); /*lint !e866*/
7642 }
7643 else
7644 {
7645 newsize = MAX(newsize, 2 * digraph->successorssize[idx]);
7646 assert(digraph->arcdata[idx] != NULL);
7647 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &digraph->successors[idx], digraph->successorssize[idx], newsize) ); /*lint !e866*/
7648 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &digraph->arcdata[idx], digraph->successorssize[idx], newsize) ); /*lint !e866*/
7649 digraph->successorssize[idx] = newsize;
7650 }
7651 }
7652
7653 assert(newsize <= digraph->successorssize[idx]);
7654
7655 return SCIP_OKAY;
7656}
7657
7658/** add (directed) arc and a related data to the directed graph structure
7659 *
7660 * @note if the arc is already contained, it is added a second time
7661 */
7663 SCIP_DIGRAPH* digraph, /**< directed graph */
7664 int startnode, /**< start node of the arc */
7665 int endnode, /**< start node of the arc */
7666 void* data /**< data that should be stored for the arc; or NULL */
7667 )
7668{
7669 assert(digraph != NULL);
7670 assert(startnode >= 0);
7671 assert(endnode >= 0);
7672 assert(startnode < digraph->nnodes);
7673 assert(endnode < digraph->nnodes);
7674
7675 SCIP_CALL( ensureSuccessorsSize(digraph, startnode, digraph->nsuccessors[startnode] + 1) );
7676
7677 /* add arc */
7678 digraph->successors[startnode][digraph->nsuccessors[startnode]] = endnode;
7679 digraph->arcdata[startnode][digraph->nsuccessors[startnode]] = data;
7680 digraph->nsuccessors[startnode]++;
7681
7682 /* the articulation points are not up-to-date */
7683 digraph->articulationscheck = FALSE;
7684
7685 return SCIP_OKAY;
7686}
7687
7688/** add (directed) arc to the directed graph structure, if it is not contained, yet
7689 *
7690 * @note if there already exists an arc from startnode to endnode, the new arc is not added,
7691 * even if its data is different
7692 */
7694 SCIP_DIGRAPH* digraph, /**< directed graph */
7695 int startnode, /**< start node of the arc */
7696 int endnode, /**< start node of the arc */
7697 void* data /**< data that should be stored for the arc; or NULL */
7698 )
7699{
7700 int nsuccessors;
7701 int i;
7702
7703 assert(digraph != NULL);
7704 assert(startnode >= 0);
7705 assert(endnode >= 0);
7706 assert(startnode < digraph->nnodes);
7707 assert(endnode < digraph->nnodes);
7708
7709 nsuccessors = digraph->nsuccessors[startnode];
7710
7711 /* search for the arc in existing arcs */
7712 for( i = 0; i < nsuccessors; ++i )
7713 if( digraph->successors[startnode][i] == endnode )
7714 return SCIP_OKAY;
7715
7716 SCIP_CALL( ensureSuccessorsSize(digraph, startnode, nsuccessors + 1) );
7717
7718 /* add arc */
7719 digraph->successors[startnode][nsuccessors] = endnode;
7720 digraph->arcdata[startnode][nsuccessors] = data;
7721 ++(digraph->nsuccessors[startnode]);
7722
7723 /* the articulation points are not up-to-date */
7724 digraph->articulationscheck = FALSE;
7725
7726 return SCIP_OKAY;
7727}
7728
7729/** sets the number of successors to a given value */
7731 SCIP_DIGRAPH* digraph, /**< directed graph */
7732 int node, /**< node for which the number of successors has to be changed */
7733 int nsuccessors /**< new number of successors */
7734 )
7735{
7736 assert(digraph != NULL);
7737 assert(node >= 0);
7738 assert(node < digraph->nnodes);
7739
7740 digraph->nsuccessors[node] = nsuccessors;
7741
7742 return SCIP_OKAY;
7743}
7744
7745/** returns the number of nodes of the given digraph */
7747 SCIP_DIGRAPH* digraph /**< directed graph */
7748 )
7749{
7750 assert(digraph != NULL);
7751
7752 return digraph->nnodes;
7753}
7754
7755/** returns the node data, or NULL if no data exist */
7757 SCIP_DIGRAPH* digraph, /**< directed graph */
7758 int node /**< node for which the node data is returned */
7759 )
7760{
7761 assert(digraph != NULL);
7762 assert(node >= 0);
7763 assert(node < digraph->nnodes);
7764
7765 return digraph->nodedata[node];
7766}
7767
7768/** sets the node data
7769 *
7770 * @note The old user pointer is not freed. This has to be done by the user
7771 */
7773 SCIP_DIGRAPH* digraph, /**< directed graph */
7774 void* dataptr, /**< user node data pointer, or NULL */
7775 int node /**< node for which the node data is returned */
7776 )
7777{
7778 assert(digraph != NULL);
7779 assert(node >= 0);
7780 assert(node < digraph->nnodes);
7781
7782 digraph->nodedata[node] = dataptr;
7783}
7784
7785/** returns the total number of arcs in the given digraph */
7787 SCIP_DIGRAPH* digraph /**< directed graph */
7788 )
7789{
7790 int i;
7791 int narcs;
7792
7793 assert(digraph != NULL);
7794
7795 /* count number of arcs */
7796 narcs = 0;
7797 for( i = 0; i < digraph->nnodes; ++i )
7798 narcs += digraph->nsuccessors[i];
7799
7800 return narcs;
7801}
7802
7803/** returns the number of successor nodes of the given node */
7805 SCIP_DIGRAPH* digraph, /**< directed graph */
7806 int node /**< node for which the number of outgoing arcs is returned */
7807 )
7808{
7809 assert(digraph != NULL);
7810 assert(node >= 0);
7811 assert(node < digraph->nnodes);
7812 assert(digraph->nsuccessors[node] >= 0);
7813 assert(digraph->nsuccessors[node] <= digraph->successorssize[node]);
7814
7815 return digraph->nsuccessors[node];
7816}
7817
7818/** returns the array of indices of the successor nodes; this array must not be changed from outside */
7820 SCIP_DIGRAPH* digraph, /**< directed graph */
7821 int node /**< node for which the array of outgoing arcs is returned */
7822 )
7823{
7824 assert(digraph != NULL);
7825 assert(node >= 0);
7826 assert(node < digraph->nnodes);
7827 assert(digraph->nsuccessors[node] >= 0);
7828 assert(digraph->nsuccessors[node] <= digraph->successorssize[node]);
7829 assert((digraph->nsuccessors[node] == 0) || (digraph->successors[node] != NULL));
7830
7831 return digraph->successors[node];
7832}
7833
7834/** returns the array of data corresponding to the arcs originating at the given node, or NULL if no data exist; this
7835 * array must not be changed from outside
7836 */
7838 SCIP_DIGRAPH* digraph, /**< directed graph */
7839 int node /**< node for which the data corresponding to the outgoing arcs is returned */
7840 )
7841{
7842 assert(digraph != NULL);
7843 assert(node >= 0);
7844 assert(node < digraph->nnodes);
7845 assert(digraph->nsuccessors[node] >= 0);
7846 assert(digraph->nsuccessors[node] <= digraph->successorssize[node]);
7847 assert(digraph->arcdata != NULL);
7848
7849 return digraph->arcdata[node];
7850}
7851
7852/** performs depth-first-search in the given directed graph from the given start node */
7853static
7855 SCIP_DIGRAPH* digraph, /**< directed graph */
7856 int startnode, /**< node to start the depth-first-search */
7857 SCIP_Bool* visited, /**< array to store for each node, whether it was already visited */
7858 int* dfsstack, /**< array of size number of nodes to store the stack;
7859 * only needed for performance reasons */
7860 int* stackadjvisited, /**< array of size number of nodes to store the number of adjacent nodes already visited
7861 * for each node on the stack; only needed for performance reasons */
7862 int* dfsnodes, /**< array of nodes that can be reached starting at startnode, in reverse dfs order */
7863 int* ndfsnodes /**< pointer to store number of nodes that can be reached starting at startnode */
7864 )
7865{
7866 int stackidx;
7867
7868 assert(digraph != NULL);
7869 assert(startnode >= 0);
7870 assert(startnode < digraph->nnodes);
7871 assert(visited != NULL);
7872 assert(visited[startnode] == FALSE);
7873 assert(dfsstack != NULL);
7874 assert(dfsnodes != NULL);
7875 assert(ndfsnodes != NULL);
7876
7877 /* put start node on the stack */
7878 dfsstack[0] = startnode;
7879 stackadjvisited[0] = 0;
7880 stackidx = 0;
7881
7882 while( stackidx >= 0 )
7883 {
7884 int currnode;
7885 int sadv;
7886
7887 /* get next node from stack */
7888 currnode = dfsstack[stackidx];
7889
7890 sadv = stackadjvisited[stackidx];
7891 assert( 0 <= sadv && sadv <= digraph->nsuccessors[currnode] );
7892
7893 /* mark current node as visited */
7894 assert( visited[currnode] == (sadv > 0) );
7895 visited[currnode] = TRUE;
7896
7897 /* iterate through the successor list until we reach unhandled node */
7898 while( sadv < digraph->nsuccessors[currnode] && visited[digraph->successors[currnode][sadv]] )
7899 ++sadv;
7900
7901 /* the current node was completely handled, remove it from stack */
7902 if( sadv == digraph->nsuccessors[currnode] )
7903 {
7904 --stackidx;
7905
7906 /* store node in the sorted nodes array */
7907 dfsnodes[(*ndfsnodes)++] = currnode;
7908 }
7909 /* handle next unhandled successor node */
7910 else
7911 {
7912 assert( ! visited[digraph->successors[currnode][sadv]] );
7913
7914 /* store current stackadjvisted index */
7915 stackadjvisited[stackidx] = sadv + 1;
7916
7917 /* put the successor node onto the stack */
7918 ++stackidx;
7919 dfsstack[stackidx] = digraph->successors[currnode][sadv];
7920 stackadjvisited[stackidx] = 0;
7921 assert( stackidx < digraph->nnodes );
7922 }
7923 }
7924}
7925
7926/** checks for articulation points in a given directed graph through a recursive depth-first-search.
7927 * starts from a given start node and keeps track of the nodes' discovery time in search for back edges.
7928 *
7929 * @note an articulation point is a node whose removal disconnects a connected graph or increases
7930 * the number of connected components in a disconnected graph
7931 */
7932static
7934 SCIP_DIGRAPH* digraph, /**< directed graph */
7935 int startnode, /**< node to start the depth-first-search */
7936 SCIP_Bool* visited, /**< array to store for each node, whether it was already visited */
7937 int* tdisc, /**< array of size number of nodes to store each node's discovery time */
7938 int* mindisc, /**< array of size number of nodes to store the discovery time of the earliest discovered vertex
7939 * to which startnode (or any node in the subtree rooted at it) is having a back edge */
7940 int* parent, /**< array to store the parent of each node in the DFS tree */
7941 SCIP_Bool* articulationflag, /**< array to mark whether a node is identified as an articulation point */
7942 int time /**< current discovery time in the DFS */
7943 )
7944{
7945 int n;
7946 int nchildren = 0;
7947 int nsucc;
7948 int* succnodes;
7949
7950 assert(digraph != NULL);
7951 assert(startnode >= 0);
7952 assert(startnode < digraph->nnodes);
7953 assert(visited != NULL);
7954 assert(visited[startnode] == FALSE);
7955 assert(tdisc != NULL);
7956 assert(mindisc != NULL);
7957 assert(parent != NULL);
7958 assert(articulationflag != NULL);
7959 assert(time >= 0);
7960
7961 nsucc = (int) SCIPdigraphGetNSuccessors(digraph, startnode);
7962 succnodes = (int*) SCIPdigraphGetSuccessors(digraph, startnode);
7963 visited[startnode] = TRUE;
7964 tdisc[startnode] = time + 1;
7965 mindisc[startnode] = time + 1;
7966
7967 /* process all the adjacent nodes to startnode */
7968 for( n = 0; n < nsucc; ++n)
7969 {
7970 if( !visited[succnodes[n]] )
7971 {
7972 parent[succnodes[n]] = startnode;
7973 ++nchildren;
7974 findArticulationPointsUtil(digraph, succnodes[n], visited, tdisc, mindisc, parent, articulationflag, time + 1);
7975 /* updated the mindisc of startnode when the DFS concludes for node n*/
7976 mindisc[startnode] = MIN(mindisc[startnode], mindisc[succnodes[n]]);
7977
7978 /* the root is an articulation point if it has more than 2 children*/
7979 if( parent[startnode] == -1 && nchildren > 1 )
7980 articulationflag[startnode] = TRUE;
7981 /* a vertex startnode is an articulation point if it is not the root and
7982 * there is no back edge from the subtree rooted at child n to any of the ancestors of startnode */
7983 if( parent[startnode] > -1 && mindisc[succnodes[n]] >= tdisc[startnode] )
7984 articulationflag[startnode] = TRUE;
7985 }
7986 else
7987 {
7988 if( parent[startnode] != succnodes[n] )
7989 mindisc[startnode] = MIN(mindisc[startnode], tdisc[succnodes[n]]);
7990 }
7991 }
7992
7993 if( articulationflag[startnode] )
7994 ++digraph->narticulations;
7995}
7996
7997/** identifies the articulation points in a given directed graph
7998 * uses the helper recursive function findArticulationPointsUtil
7999 */
8001 SCIP_DIGRAPH* digraph, /**< directed graph */
8002 int** articulations, /**< array to store the sorted node indices of the computed articulation points, or NULL */
8003 int* narticulations /**< number of the computed articulation points, or NULL */
8004 )
8005{
8006 SCIP_RETCODE retcode = SCIP_OKAY;
8007 BMS_BLKMEM* blkmem;
8008 SCIP_Bool* visited = NULL;
8009 SCIP_Bool* articulationflag = NULL;
8010 int* tdisc = NULL;
8011 int* mindisc = NULL;
8012 int* parent = NULL;
8013 int n;
8014 int articulationidx = 0;
8015 int time = 0;
8016
8017 assert(digraph != NULL);
8018 assert(digraph->nnodes > 0);
8019
8020 /* Only perform the computation if the articulation points are NOT up-to-date */
8021 if( !digraph->articulationscheck )
8022 {
8023 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&visited, digraph->nnodes), TERMINATE );
8024 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&tdisc, digraph->nnodes), TERMINATE );
8025 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&mindisc, digraph->nnodes), TERMINATE );
8026 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&parent, digraph->nnodes), TERMINATE );
8027 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&articulationflag, digraph->nnodes), TERMINATE );
8028
8029 assert(digraph->blkmem != NULL);
8030 blkmem = digraph->blkmem;
8031
8032 if( digraph->narticulations >= 0 ) /* case: articulations have already been computed but not up-to-date */
8033 BMSfreeBlockMemoryArray(blkmem, &digraph->articulations, digraph->narticulations);
8034
8035 /* Initialize the no. of articulation points ahead of the recursive computation */
8036 digraph->narticulations = 0;
8037
8038 for( n = 0; n < digraph->nnodes; ++n )
8039 {
8040 visited[n] = FALSE;
8041 parent[n] = -1;
8042 articulationflag[n] = FALSE;
8043 }
8044
8045 /* the function is called on every unvisited node in the graph to cover the disconnected graph case */
8046 for( n = 0; n < digraph->nnodes; ++n )
8047 {
8048 if( !visited[n] )
8049 findArticulationPointsUtil(digraph, n, visited, tdisc, mindisc, parent, articulationflag, time);
8050 }
8051
8052 /* allocation of the block memory for the node indices of the articulation points*/
8053 SCIP_ALLOC_TERMINATE( retcode, BMSallocBlockMemoryArray(blkmem, &digraph->articulations, digraph->narticulations), TERMINATE );
8054
8055 for( n = 0; n < digraph->nnodes; ++n )
8056 {
8057 if( articulationflag[n] )
8058 {
8059 digraph->articulations[articulationidx] = n;
8060 ++articulationidx;
8061 }
8062 }
8063 }
8064
8065 if( articulations != NULL )
8066 (*articulations) = digraph->articulations;
8067 if( narticulations != NULL )
8068 (*narticulations) = digraph->narticulations;
8069
8070 /* the articulation points are now up-to-date */
8071 digraph->articulationscheck = TRUE;
8072
8073/* cppcheck-suppress unusedLabel */
8074TERMINATE:
8075 BMSfreeMemoryArrayNull(&articulationflag);
8076 BMSfreeMemoryArrayNull(&parent);
8077 BMSfreeMemoryArrayNull(&mindisc);
8078 BMSfreeMemoryArrayNull(&tdisc);
8079 BMSfreeMemoryArrayNull(&visited);
8080
8081 return retcode;
8082}
8083
8084/** Compute undirected connected components on the given graph.
8085 *
8086 * @note For each arc, its reverse is added, so the graph does not need to be the directed representation of an
8087 * undirected graph.
8088 */
8090 SCIP_DIGRAPH* digraph, /**< directed graph */
8091 int minsize, /**< all components with less nodes are ignored */
8092 int* components, /**< array with as many slots as there are nodes in the directed graph
8093 * to store for each node the component to which it belongs
8094 * (components are numbered 0 to ncomponents - 1); or NULL, if components
8095 * are accessed one-by-one using SCIPdigraphGetComponent() */
8096 int* ncomponents /**< pointer to store the number of components; or NULL, if the
8097 * number of components is accessed by SCIPdigraphGetNComponents() */
8098 )
8099{
8100 BMS_BLKMEM* blkmem;
8101 SCIP_Bool* visited;
8102 int* ndirectedsuccessors;
8103 int* stackadjvisited;
8104 int* dfsstack;
8105 int ndfsnodes;
8106 int compstart;
8107 int v;
8108 int i;
8109 int j;
8110
8111 SCIP_RETCODE retcode = SCIP_OKAY;
8112
8113 assert(digraph != NULL);
8114 assert(digraph->nnodes > 0);
8115 assert(digraph->blkmem != NULL);
8116
8117 blkmem = digraph->blkmem;
8118
8119 /* first free the old components */
8120 if( digraph->ncomponents > 0 )
8121 {
8123 }
8124
8125 digraph->ncomponents = 0;
8126 digraph->componentstartsize = 10;
8127
8128 /* storage to hold components is stored in block memory */
8129 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->components, digraph->nnodes) );
8131
8132 /* allocate temporary arrays */
8133 SCIP_ALLOC_TERMINATE( retcode, BMSallocClearMemoryArray(&visited, digraph->nnodes), TERMINATE );
8134 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsstack, digraph->nnodes), TERMINATE );
8135 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&stackadjvisited, digraph->nnodes), TERMINATE );
8136 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&ndirectedsuccessors, digraph->nnodes), TERMINATE );
8137
8138 digraph->componentstarts[0] = 0;
8139
8140 /* store the number of directed arcs per node */
8141 BMScopyMemoryArray(ndirectedsuccessors, digraph->nsuccessors, digraph->nnodes);
8142
8143 /* add reverse arcs to the graph */
8144 for( i = digraph->nnodes - 1; i >= 0; --i )
8145 {
8146 for( j = 0; j < ndirectedsuccessors[i]; ++j )
8147 {
8148 SCIP_CALL_TERMINATE( retcode, SCIPdigraphAddArc(digraph, digraph->successors[i][j], i, NULL), TERMINATE );
8149 }
8150 }
8151
8152 for( v = 0; v < digraph->nnodes; ++v )
8153 {
8154 if( visited[v] )
8155 continue;
8156
8157 compstart = digraph->componentstarts[digraph->ncomponents];
8158 ndfsnodes = 0;
8159 depthFirstSearch(digraph, v, visited, dfsstack, stackadjvisited,
8160 &digraph->components[compstart], &ndfsnodes);
8161
8162 /* forget about this component if it is too small */
8163 if( ndfsnodes >= minsize )
8164 {
8165 digraph->ncomponents++;
8166
8167 /* enlarge componentstartsize array, if needed */
8168 if( digraph->ncomponents >= digraph->componentstartsize )
8169 {
8170 int newsize;
8171
8172 newsize = 2 * digraph->componentstartsize;
8173 assert(digraph->ncomponents < newsize);
8174
8175 SCIP_ALLOC_TERMINATE( retcode, BMSreallocBlockMemoryArray(blkmem, &digraph->componentstarts, digraph->componentstartsize, newsize), TERMINATE );
8176 digraph->componentstartsize = newsize;
8177 }
8178 digraph->componentstarts[digraph->ncomponents] = compstart + ndfsnodes;
8179
8180 /* store component number for contained nodes if array was given */
8181 if( components != NULL )
8182 {
8183 for( i = digraph->componentstarts[digraph->ncomponents] - 1; i >= compstart; --i )
8184 {
8185 components[digraph->components[i]] = digraph->ncomponents - 1;
8186 }
8187 }
8188 }
8189 }
8190
8191 /* restore the number of directed arcs per node */
8192 BMScopyMemoryArray(digraph->nsuccessors, ndirectedsuccessors, digraph->nnodes);
8193 BMSclearMemoryArray(visited, digraph->nnodes);
8194
8195 /* return number of components, if the pointer was given */
8196 if( ncomponents != NULL )
8197 (*ncomponents) = digraph->ncomponents;
8198
8199TERMINATE:
8200 if( retcode != SCIP_OKAY )
8201 {
8203 }
8204 /* coverity[uninit_use_in_call] */
8205 BMSfreeMemoryArrayNull(&ndirectedsuccessors);
8206 BMSfreeMemoryArrayNull(&stackadjvisited);
8207 BMSfreeMemoryArrayNull(&dfsstack);
8208 BMSfreeMemoryArrayNull(&visited);
8209
8210 return retcode;
8211}
8212
8213/** Performs an (almost) topological sort on the undirected components of the given directed graph. The undirected
8214 * components should be computed before using SCIPdigraphComputeUndirectedComponents().
8215 *
8216 * @note In general a topological sort is not unique. Note, that there might be directed cycles, that are randomly
8217 * broken, which is the reason for having only almost topologically sorted arrays.
8218 */
8220 SCIP_DIGRAPH* digraph /**< directed graph */
8221 )
8222{
8223 SCIP_Bool* visited = NULL;
8224 int* comps;
8225 int* compstarts;
8226 int* stackadjvisited = NULL;
8227 int* dfsstack = NULL;
8228 int* dfsnodes = NULL;
8229 int ndfsnodes;
8230 int ncomps;
8231 int i;
8232 int j;
8233 int k;
8234 int endidx;
8235 SCIP_RETCODE retcode = SCIP_OKAY;
8236
8237 assert(digraph != NULL);
8238
8239 ncomps = digraph->ncomponents;
8240 comps = digraph->components;
8241 compstarts = digraph->componentstarts;
8242
8243 SCIP_ALLOC_TERMINATE( retcode, BMSallocClearMemoryArray(&visited, digraph->nnodes), TERMINATE );
8244 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsnodes, digraph->nnodes), TERMINATE );
8245 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsstack, digraph->nnodes), TERMINATE );
8246 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&stackadjvisited, digraph->nnodes), TERMINATE );
8247
8248 /* sort the components (almost) topologically */
8249 for( i = 0; i < ncomps; ++i )
8250 {
8251 endidx = compstarts[i+1] - 1;
8252 ndfsnodes = 0;
8253 for( j = compstarts[i]; j < compstarts[i+1]; ++j )
8254 {
8255 if( visited[comps[j]] )
8256 continue;
8257
8258 /* perform depth first search, nodes visited in this call are appended to the list dfsnodes in reverse
8259 * dfs order, after the nodes already contained;
8260 * so at every point in time, the nodes in dfsnode are in reverse (almost) topological order
8261 */
8262 depthFirstSearch(digraph, comps[j], visited, dfsstack, stackadjvisited, dfsnodes, &ndfsnodes);
8263 }
8264 assert(endidx - ndfsnodes == compstarts[i] - 1);
8265
8266 /* copy reverse (almost) topologically sorted array of nodes reached by the dfs searches;
8267 * reverse their order to get an (almost) topologically sort
8268 */
8269 for( k = 0; k < ndfsnodes; ++k )
8270 {
8271 digraph->components[endidx - k] = dfsnodes[k];
8272 }
8273 }
8274
8275TERMINATE:
8276 BMSfreeMemoryArrayNull(&stackadjvisited);
8277 BMSfreeMemoryArrayNull(&dfsstack);
8278 BMSfreeMemoryArrayNull(&dfsnodes);
8279 BMSfreeMemoryArrayNull(&visited);
8280
8281 return retcode;
8282}
8283
8284/** returns the number of previously computed undirected components for the given directed graph */
8286 SCIP_DIGRAPH* digraph /**< directed graph */
8287 )
8288{
8289 assert(digraph != NULL);
8290 assert(digraph->componentstartsize > 0); /* components should have been computed */
8291
8292 return digraph->ncomponents;
8293}
8294
8295/** Returns the previously computed undirected component of the given number for the given directed graph.
8296 * If the components were sorted using SCIPdigraphTopoSortComponents(), the component is (almost) topologically sorted.
8297 */
8299 SCIP_DIGRAPH* digraph, /**< directed graph */
8300 int compidx, /**< number of the component to return */
8301 int** nodes, /**< pointer to store the nodes in the component; or NULL, if not needed */
8302 int* nnodes /**< pointer to store the number of nodes in the component;
8303 * or NULL, if not needed */
8304 )
8305{
8306 assert(digraph != NULL);
8307 assert(compidx >= 0);
8308 assert(compidx < digraph->ncomponents);
8309 assert(nodes != NULL || nnodes != NULL);
8310
8311 if( nodes != NULL )
8312 (*nodes) = &(digraph->components[digraph->componentstarts[compidx]]);
8313 if( nnodes != NULL )
8314 (*nnodes) = digraph->componentstarts[compidx + 1] - digraph->componentstarts[compidx];
8315}
8316
8317/* Performs Tarjan's algorithm for a given directed graph to obtain the strongly connected components
8318 * which are reachable from a given node.
8319 */
8320static
8322 SCIP_DIGRAPH* digraph, /**< directed graph */
8323 int v, /**< node to start the algorithm */
8324 int* lowlink, /**< array to store lowlink values */
8325 int* dfsidx, /**< array to store dfs indices */
8326 int* stack, /**< array to store a stack */
8327 int* stacksize, /**< pointer to store the size of the stack */
8328 SCIP_Bool* unprocessed, /**< array to store which node is unprocessed yet */
8329 SCIP_Bool* nodeinstack, /**< array to store which nodes are in the stack */
8330 int* maxdfs, /**< pointer to store index for DFS */
8331 int* strongcomponents, /**< array to store for each node the strongly connected
8332 * component to which it belongs (components are
8333 * numbered 0 to nstrongcomponents - 1); */
8334 int* nstrongcomponents, /**< pointer to store the number of computed components so far */
8335 int* strongcompstartidx, /**< array to store the start index of the computed components */
8336 int* nstorednodes /**< pointer to store the number of already stored nodes */
8337 )
8338{
8339 int i;
8340
8341 assert(digraph != NULL);
8342 assert(v >= 0);
8343 assert(v < digraph->nnodes);
8344 assert(lowlink != NULL);
8345 assert(dfsidx != NULL);
8346 assert(stack != NULL);
8347 assert(stacksize != NULL);
8348 assert(*stacksize >= 0);
8349 assert(*stacksize < digraph->nnodes);
8350 assert(unprocessed != NULL);
8351 assert(nodeinstack != NULL);
8352 assert(maxdfs != NULL);
8353 assert(strongcomponents != NULL);
8354 assert(nstrongcomponents != NULL);
8355 assert(strongcompstartidx != NULL);
8356 assert(nstorednodes != NULL);
8357 assert(*nstorednodes >= 0 && *nstorednodes < digraph->nnodes);
8358
8359 dfsidx[v] = *maxdfs;
8360 lowlink[v] = *maxdfs;
8361 *maxdfs += 1;
8362
8363 /* add v to the stack */
8364 stack[*stacksize] = v;
8365 *stacksize += 1;
8366 nodeinstack[v] = TRUE;
8367
8368 /* mark v as processed */
8369 unprocessed[v] = FALSE;
8370
8371 for( i = 0; i < digraph->nsuccessors[v]; ++i )
8372 {
8373 int w;
8374
8375 /* edge (v,w) */
8376 w = digraph->successors[v][i];
8377
8378 if( unprocessed[w] )
8379 {
8380 tarjan(digraph, w, lowlink, dfsidx, stack, stacksize, unprocessed, nodeinstack, maxdfs, strongcomponents,
8381 nstrongcomponents, strongcompstartidx, nstorednodes);
8382
8383 assert(lowlink[v] >= 0 && lowlink[v] < digraph->nnodes);
8384 assert(lowlink[w] >= 0 && lowlink[w] < digraph->nnodes);
8385
8386 /* update lowlink */
8387 lowlink[v] = MIN(lowlink[v], lowlink[w]);
8388 }
8389 else if( nodeinstack[w] )
8390 {
8391 assert(lowlink[v] >= 0 && lowlink[v] < digraph->nnodes);
8392 assert(dfsidx[w] >= 0 && dfsidx[w] < digraph->nnodes);
8393
8394 /* update lowlink */
8395 lowlink[v] = MIN(lowlink[v], dfsidx[w]);
8396 }
8397 }
8398
8399 /* found a root of a strong component */
8400 if( lowlink[v] == dfsidx[v] )
8401 {
8402 int w;
8403
8404 strongcompstartidx[*nstrongcomponents] = *nstorednodes;
8405 *nstrongcomponents += 1;
8406
8407 do
8408 {
8409 assert(*stacksize > 0);
8410
8411 /* stack.pop() */
8412 w = stack[*stacksize - 1];
8413 *stacksize -= 1;
8414 nodeinstack[w] = FALSE;
8415
8416 /* store the node in the corresponding component */
8417 strongcomponents[*nstorednodes] = w;
8418 *nstorednodes += 1;
8419 }
8420 while( v != w );
8421 }
8422}
8423
8424/** Computes all strongly connected components of an undirected connected component with Tarjan's Algorithm.
8425 * The resulting strongly connected components are sorted topologically (starting from the end of the
8426 * strongcomponents array).
8427 *
8428 * @note In general a topological sort of the strongly connected components is not unique.
8429 */
8431 SCIP_DIGRAPH* digraph, /**< directed graph */
8432 int compidx, /**< number of the undirected connected component */
8433 int* strongcomponents, /**< array to store the strongly connected components
8434 * (length >= size of the component) */
8435 int* strongcompstartidx, /**< array to store the start indices of the strongly connected
8436 * components (length >= size of the component) */
8437 int* nstrongcomponents /**< pointer to store the number of strongly connected
8438 * components */
8439 )
8440{
8441 int* lowlink = NULL;
8442 int* dfsidx = NULL;
8443 int* stack = NULL;
8444 int stacksize;
8445 SCIP_Bool* unprocessed = NULL;
8446 SCIP_Bool* nodeinstack = NULL;
8447 int maxdfs;
8448 int nstorednodes;
8449 int i;
8450 SCIP_RETCODE retcode;
8451
8452 assert(digraph != NULL);
8453 assert(compidx >= 0);
8454 assert(compidx < digraph->ncomponents);
8455 assert(strongcomponents != NULL);
8456 assert(strongcompstartidx != NULL);
8457 assert(nstrongcomponents != NULL);
8458
8459 retcode = SCIP_OKAY;
8460
8461 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&lowlink, digraph->nnodes), TERMINATE );
8462 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsidx, digraph->nnodes), TERMINATE );
8463 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&stack, digraph->nnodes), TERMINATE );
8464 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&unprocessed, digraph->nnodes), TERMINATE );
8465 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&nodeinstack, digraph->nnodes), TERMINATE );
8466
8467 for( i = 0; i < digraph->nnodes; ++i )
8468 {
8469 lowlink[i] = -1;
8470 dfsidx[i] = -1;
8471 stack[i] = -1;
8472 unprocessed[i] = TRUE;
8473 nodeinstack[i] = FALSE;
8474 }
8475
8476 nstorednodes = 0;
8477 stacksize = 0;
8478 maxdfs = 0;
8479 *nstrongcomponents = 0;
8480
8481 /* iterate over all nodes in the undirected connected component */
8482 for( i = digraph->componentstarts[compidx]; i < digraph->componentstarts[compidx + 1]; ++i )
8483 {
8484 int v;
8485
8486 v = digraph->components[i];
8487 assert(v >= 0 && v < digraph->nnodes);
8488
8489 /* call Tarjan's algorithm for unprocessed nodes */
8490 if( unprocessed[v] )
8491 {
8492 SCIPdebugMessage("apply Tarjan's algorithm for node %d\n", v);
8493 tarjan(digraph, v, lowlink, dfsidx, stack, &stacksize, unprocessed, nodeinstack, &maxdfs,
8494 strongcomponents, nstrongcomponents, strongcompstartidx, &nstorednodes);
8495 }
8496 }
8497
8498 /* we should have stored as many nodes as in the undirected connected component */
8499 assert(nstorednodes == digraph->componentstarts[compidx + 1] - digraph->componentstarts[compidx]);
8500
8501 /* to simplify the iteration over all strongly connected components */
8502 assert(*nstrongcomponents < digraph->nnodes + 1);
8503 strongcompstartidx[*nstrongcomponents] = nstorednodes;
8504
8505 assert(retcode == SCIP_OKAY);
8506
8507TERMINATE:
8508 BMSfreeMemoryArrayNull(&lowlink);
8509 BMSfreeMemoryArrayNull(&dfsidx);
8510 BMSfreeMemoryArrayNull(&stack);
8511 BMSfreeMemoryArrayNull(&unprocessed);
8512 BMSfreeMemoryArrayNull(&nodeinstack);
8513
8514 return retcode;
8515}
8516
8517/** frees the component information for the given directed graph */
8519 SCIP_DIGRAPH* digraph /**< directed graph */
8520 )
8521{
8522 BMS_BLKMEM* blkmem;
8523
8524 assert(digraph != NULL);
8525 assert(digraph->blkmem != NULL);
8526
8527 blkmem = digraph->blkmem;
8528
8529 /* free components structure */
8530 if( digraph->componentstartsize > 0 )
8531 {
8532 BMSfreeBlockMemoryArray(blkmem, &digraph->componentstarts, digraph->componentstartsize);
8533 BMSfreeBlockMemoryArray(blkmem, &digraph->components, digraph->nnodes);
8534 digraph->components = NULL;
8535 digraph->componentstarts = NULL;
8536 digraph->ncomponents = 0;
8537 digraph->componentstartsize = 0;
8538 }
8539#ifndef NDEBUG
8540 else
8541 {
8542 assert(digraph->components == NULL);
8543 assert(digraph->componentstarts == NULL);
8544 assert(digraph->ncomponents == 0);
8545 }
8546#endif
8547}
8548
8549/** output of the given directed graph via the given message handler */
8551 SCIP_DIGRAPH* digraph, /**< directed graph */
8552 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
8553 FILE* file /**< output file (or NULL for standard output) */
8554 )
8555{
8556 int n;
8557
8558 for( n = 0; n < digraph->nnodes; ++n )
8559 {
8560 int* successors;
8561 int nsuccessors;
8562 int m;
8563
8564 nsuccessors = digraph->nsuccessors[n];
8565 successors = digraph->successors[n];
8566
8567 SCIPmessageFPrintInfo(messagehdlr, file, "node %d --> ", n);
8568
8569 for( m = 0; m < nsuccessors ; ++m )
8570 {
8571 if( m == 0 )
8572 {
8573 SCIPmessageFPrintInfo(messagehdlr, file, "%d", successors[m]);
8574 }
8575 else
8576 {
8577 SCIPmessageFPrintInfo(messagehdlr, file, ", %d", successors[m]);
8578 }
8579 }
8580 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
8581 }
8582}
8583
8584/** prints the given directed graph structure in GML format into the given file */
8586 SCIP_DIGRAPH* digraph, /**< directed graph */
8587 FILE* file /**< file to write to */
8588 )
8589{
8590 int n;
8591
8592 /* write GML format opening */
8594
8595 /* write all nodes of the graph */
8596 for( n = 0; n < digraph->nnodes; ++n )
8597 {
8598 char label[SCIP_MAXSTRLEN];
8599
8600 (void)SCIPsnprintf(label, SCIP_MAXSTRLEN, "%d", n);
8601 SCIPgmlWriteNode(file, (unsigned int)n, label, "circle", NULL, NULL);
8602 }
8603
8604 /* write all edges */
8605 for( n = 0; n < digraph->nnodes; ++n )
8606 {
8607 int* successors;
8608 int nsuccessors;
8609 int m;
8610
8611 nsuccessors = digraph->nsuccessors[n];
8612 successors = digraph->successors[n];
8613
8614 for( m = 0; m < nsuccessors; ++m )
8615 {
8616 SCIPgmlWriteArc(file, (unsigned int)n, (unsigned int)successors[m], NULL, NULL);
8617 }
8618 }
8619 /* write GML format closing */
8620 SCIPgmlWriteClosing(file);
8621}
8622
8623/** output of the given directed graph via the given message handler */
8625 SCIP_DIGRAPH* digraph, /**< directed graph */
8626 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
8627 FILE* file /**< output file (or NULL for standard output) */
8628 )
8629{
8630 int c;
8631 int i;
8632
8633 for( c = 0; c < digraph->ncomponents; ++c )
8634 {
8635 int start = digraph->componentstarts[c];
8636 int end = digraph->componentstarts[c+1];
8637
8638 SCIPmessageFPrintInfo(messagehdlr, file, "Components %d --> ", c);
8639
8640 for( i = start; i < end; ++i )
8641 {
8642 if( i == start )
8643 {
8644 SCIPmessageFPrintInfo(messagehdlr, file, "%d", digraph->components[i]);
8645 }
8646 else
8647 {
8648 SCIPmessageFPrintInfo(messagehdlr, file, ", %d", digraph->components[i]);
8649 }
8650 }
8651 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
8652 }
8653}
8654
8655/*
8656 * Binary tree
8657 */
8658
8659/** creates a node for a binary tree */
8660static
8662 SCIP_BT* tree, /**< binary tree */
8663 SCIP_BTNODE** node /**< pointer to store the created node */
8664 )
8665{
8666 SCIP_ALLOC( BMSallocBlockMemory(tree->blkmem, node) );
8667
8668 (*node)->parent = NULL;
8669 (*node)->left = NULL;
8670 (*node)->right = NULL;
8671 (*node)->dataptr = NULL;
8672
8673 return SCIP_OKAY;
8674}
8675
8676/** creates a tree node with (optinal) user data */
8678 SCIP_BT* tree, /**< binary tree */
8679 SCIP_BTNODE** node, /**< pointer to store the created node */
8680 void* dataptr /**< user node data pointer, or NULL */
8681 )
8682{
8683 assert(tree != NULL);
8684 assert(node != NULL);
8685
8686 SCIP_CALL( btnodeCreateEmpty(tree, node) );
8687
8688 assert((*node)->parent == NULL);
8689 assert((*node)->left == NULL);
8690 assert((*node)->right == NULL);
8691
8692 /* initialize user data */
8693 (*node)->dataptr = dataptr;
8694
8695 return SCIP_OKAY;
8696}
8697
8698/** frees a tree leaf */
8699static
8701 SCIP_BT* tree, /**< binary tree */
8702 SCIP_BTNODE** node /**< pointer to node which has to be freed */
8703 )
8704{
8705 assert(tree != NULL);
8706 assert(node != NULL);
8707 assert(*node != NULL);
8708
8709 assert((*node)->left == NULL);
8710 assert((*node)->right == NULL);
8711
8712#if 0
8713 /* remove reference from parent node */
8714 if( (*node)->parent != NULL )
8715 {
8716 assert(*node != NULL);
8717
8718 assert((*node)->parent->left == *node || ((*node)->parent->right == *node));
8719
8720 if( (*node)->parent->left == *node )
8721 {
8722 (*node)->parent->left = NULL;
8723 }
8724 else
8725 {
8726 assert((*node)->parent->right == *node);
8727 (*node)->parent->right = NULL;
8728 }
8729 }
8730#endif
8731
8732 assert(*node != NULL);
8733 BMSfreeBlockMemory(tree->blkmem, node);
8734 assert(*node == NULL);
8735}
8736
8737/** frees the node including the rooted subtree
8738 *
8739 * @note The user pointer (object) is not freed. If needed, it has to be done by the user.
8740 */
8742 SCIP_BT* tree, /**< binary tree */
8743 SCIP_BTNODE** node /**< node to be freed */
8744 )
8745{
8746 assert(tree != NULL);
8747 assert(node != NULL);
8748 assert(*node != NULL);
8749
8750 if( (*node)->left != NULL )
8751 {
8752 SCIPbtnodeFree(tree, &(*node)->left);
8753 assert((*node)->left == NULL);
8754 }
8755
8756 if( (*node)->right != NULL )
8757 {
8758 SCIPbtnodeFree(tree, &(*node)->right);
8759 assert((*node)->right == NULL);
8760 }
8761
8762 btnodeFreeLeaf(tree, node);
8763 assert(*node == NULL);
8764}
8765
8766/* some simple variable functions implemented as defines */
8767
8768/* In debug mode, the following methods are implemented as function calls to ensure
8769 * type validity.
8770 * In optimized mode, the methods are implemented as defines to improve performance.
8771 * However, we want to have them in the library anyways, so we have to undef the defines.
8772 */
8773
8774#undef SCIPbtnodeGetData
8775#undef SCIPbtnodeGetKey
8776#undef SCIPbtnodeGetParent
8777#undef SCIPbtnodeGetLeftchild
8778#undef SCIPbtnodeGetRightchild
8779#undef SCIPbtnodeGetSibling
8780#undef SCIPbtnodeIsRoot
8781#undef SCIPbtnodeIsLeaf
8782#undef SCIPbtnodeIsLeftchild
8783#undef SCIPbtnodeIsRightchild
8784
8785/** returns the user data pointer stored in that node */
8787 SCIP_BTNODE* node /**< node */
8788 )
8789{
8790 assert(node != NULL);
8791
8792 return node->dataptr;
8793}
8794
8795/** returns the parent which can be NULL if the given node is the root */
8797 SCIP_BTNODE* node /**< node */
8798 )
8799{
8800 assert(node != NULL);
8801
8802 return node->parent;
8803}
8804
8805/** returns left child which can be NULL if the given node is a leaf */
8807 SCIP_BTNODE* node /**< node */
8808 )
8809{
8810 assert(node != NULL);
8811
8812 return node->left;
8813}
8814
8815/** returns right child which can be NULL if the given node is a leaf */
8817 SCIP_BTNODE* node /**< node */
8818 )
8819{
8820 assert(node != NULL);
8821
8822 return node->right;
8823}
8824
8825/** returns the sibling of the node or NULL if does not exist */
8827 SCIP_BTNODE* node /**< node */
8828 )
8829{
8830 SCIP_BTNODE* parent;
8831
8832 parent = SCIPbtnodeGetParent(node);
8833
8834 if( parent == NULL )
8835 return NULL;
8836
8837 if( SCIPbtnodeGetLeftchild(parent) == node )
8838 return SCIPbtnodeGetRightchild(parent);
8839
8840 assert(SCIPbtnodeGetRightchild(parent) == node);
8841
8842 return SCIPbtnodeGetLeftchild(parent);
8843}
8844
8845/** returns whether the node is a root node */
8847 SCIP_BTNODE* node /**< node */
8848 )
8849{
8850 assert(node != NULL);
8851
8852 return (node->parent == NULL);
8853}
8854
8855/** returns whether the node is a leaf */
8857 SCIP_BTNODE* node /**< node */
8858 )
8859{
8860 assert(node != NULL);
8861
8862 return (node->left == NULL && node->right == NULL);
8863}
8864
8865/** returns TRUE if the given node is left child */
8867 SCIP_BTNODE* node /**< node */
8868 )
8869{
8870 SCIP_BTNODE* parent;
8871
8872 if( SCIPbtnodeIsRoot(node) )
8873 return FALSE;
8874
8875 parent = SCIPbtnodeGetParent(node);
8876
8877 if( SCIPbtnodeGetLeftchild(parent) == node )
8878 return TRUE;
8879
8880 return FALSE;
8881}
8882
8883/** returns TRUE if the given node is right child */
8885 SCIP_BTNODE* node /**< node */
8886 )
8887{
8888 SCIP_BTNODE* parent;
8889
8890 if( SCIPbtnodeIsRoot(node) )
8891 return FALSE;
8892
8893 parent = SCIPbtnodeGetParent(node);
8894
8895 if( SCIPbtnodeGetRightchild(parent) == node )
8896 return TRUE;
8897
8898 return FALSE;
8899}
8900
8901/** sets the give node data
8902 *
8903 * @note The old user pointer is not freed.
8904 */
8906 SCIP_BTNODE* node, /**< node */
8907 void* dataptr /**< node user data pointer */
8908 )
8909{
8910 assert(node != NULL);
8911
8912 node->dataptr = dataptr;
8913}
8914
8915/** sets parent node
8916 *
8917 * @note The old parent including the rooted subtree is not delete.
8918 */
8920 SCIP_BTNODE* node, /**< node */
8921 SCIP_BTNODE* parent /**< new parent node, or NULL */
8922 )
8923{
8924 assert(node != NULL);
8925
8926 node->parent = parent;
8927}
8928
8929/** sets left child
8930 *
8931 * @note The old left child including the rooted subtree is not delete.
8932 */
8934 SCIP_BTNODE* node, /**< node */
8935 SCIP_BTNODE* left /**< new left child, or NULL */
8936 )
8937{
8938 assert(node != NULL);
8939
8940 node->left = left;
8941}
8942
8943/** sets right child
8944 *
8945 * @note The old right child including the rooted subtree is not delete.
8946 */
8948 SCIP_BTNODE* node, /**< node */
8949 SCIP_BTNODE* right /**< new right child, or NULL */
8950 )
8951{
8952 assert(node != NULL);
8953
8954 node->right = right;
8955}
8956
8957/** creates an binary tree */
8959 SCIP_BT** tree, /**< pointer to store the created binary tree */
8960 BMS_BLKMEM* blkmem /**< block memory used to createnode */
8961 )
8962{
8963 assert(tree != NULL);
8964 assert(blkmem != NULL);
8965
8966 SCIP_ALLOC( BMSallocBlockMemory(blkmem, tree) );
8967 (*tree)->blkmem = blkmem;
8968 (*tree)->root = NULL;
8969
8970 return SCIP_OKAY;
8971}
8972
8973/** frees binary tree
8974 *
8975 * @note The user pointers (object) of the nodes are not freed. If needed, it has to be done by the user.
8976 */
8978 SCIP_BT** tree /**< pointer to binary tree */
8979 )
8980{
8981 assert(tree != NULL);
8982
8983 if( (*tree)->root != NULL )
8984 {
8985 SCIPbtnodeFree(*tree, &((*tree)->root));
8986 }
8987
8988 BMSfreeBlockMemory((*tree)->blkmem, tree);
8989}
8990
8991/** prints the rooted subtree of the given binary tree node in GML format into the given file */
8992static
8994 SCIP_BTNODE* node, /**< binary tree node */
8995 FILE* file, /**< file to write to */
8996 int* nnodes /**< pointer to count the number of nodes */
8997 )
8998{
8999 SCIP_BTNODE* left;
9000 SCIP_BTNODE* right;
9001 char label[SCIP_MAXSTRLEN];
9002
9003 assert(node != NULL);
9004
9005 (*nnodes)++;
9006 (void)SCIPsnprintf(label, SCIP_MAXSTRLEN, "%d", *nnodes);
9007
9008 SCIPgmlWriteNode(file, (unsigned int)(size_t)node, label, "circle", NULL, NULL);
9009
9010 left = SCIPbtnodeGetLeftchild(node);
9011 right = SCIPbtnodeGetRightchild(node);
9012
9013 if( left != NULL )
9014 {
9015 btPrintSubtree(left, file, nnodes);
9016
9017 SCIPgmlWriteArc(file, (unsigned int)(size_t)node, (unsigned int)(size_t)left, NULL, NULL);
9018 }
9019
9020 if( right != NULL )
9021 {
9022 btPrintSubtree(right, file, nnodes);
9023
9024 SCIPgmlWriteArc(file, (unsigned int)(size_t)node, (unsigned int)(size_t)right, NULL, NULL);
9025 }
9026}
9027
9028/** prints the binary tree in GML format into the given file */
9030 SCIP_BT* tree, /**< binary tree */
9031 FILE* file /**< file to write to */
9032 )
9033{
9034 /* write GML opening */
9036
9037 if( !SCIPbtIsEmpty(tree) )
9038 {
9039 SCIP_BTNODE* root;
9040 int nnodes;
9041
9042 root = SCIPbtGetRoot(tree);
9043 assert(root != NULL);
9044
9045 nnodes = 0;
9046
9047 btPrintSubtree(root, file, &nnodes);
9048 }
9049
9050 /* write GML closing */
9051 SCIPgmlWriteClosing(file);
9052}
9053
9054/* some simple variable functions implemented as defines */
9055#undef SCIPbtIsEmpty
9056#undef SCIPbtGetRoot
9057
9058/** returns whether the binary tree is empty (has no nodes) */
9060 SCIP_BT* tree /**< binary tree */
9061 )
9062{
9063 assert(tree != NULL);
9064
9065 return (tree->root == NULL);
9066}
9067
9068/** returns the the root node of the binary or NULL if the binary tree is empty */
9070 SCIP_BT* tree /**< tree to be evaluated */
9071 )
9072{
9073 assert(tree != NULL);
9074
9075 return tree->root;
9076}
9077
9078/** sets root node
9079 *
9080 * @note The old root including the rooted subtree is not delete.
9081 */
9083 SCIP_BT* tree, /**< tree to be evaluated */
9084 SCIP_BTNODE* root /**< new root, or NULL */
9085 )
9086{
9087 assert(tree != NULL);
9088
9089 tree->root = root;
9090}
9091
9092
9093/*
9094 * Numerical methods
9095 */
9096
9097/** returns the machine epsilon: the smallest number eps > 0, for which 1.0 + eps > 1.0 */
9099 void
9100 )
9101{
9102 SCIP_Real eps;
9103 SCIP_Real lasteps;
9104 SCIP_Real one;
9105 SCIP_Real onepluseps;
9106
9107 one = 1.0;
9108 eps = 1.0;
9109 do
9110 {
9111 lasteps = eps;
9112 eps /= 2.0;
9113 onepluseps = one + eps;
9114 }
9115 while( onepluseps > one );
9116
9117 return lasteps;
9118}
9119
9120/** calculates the greatest common divisor of the two given values */
9122 SCIP_Longint val1, /**< first value of greatest common devisor calculation */
9123 SCIP_Longint val2 /**< second value of greatest common devisor calculation */
9124 )
9125{
9126 int t;
9127
9128 assert(val1 > 0);
9129 assert(val2 > 0);
9130
9131 t = 0;
9132 /* if val1 is even, divide it by 2 */
9133 while( !(val1 & 1) )
9134 {
9135 val1 >>= 1; /*lint !e704*/
9136
9137 /* if val2 is even too, divide it by 2 and increase t(=number of e) */
9138 if( !(val2 & 1) )
9139 {
9140 val2 >>= 1; /*lint !e704*/
9141 ++t;
9142 }
9143 /* only val1 can be odd */
9144 else
9145 {
9146 /* while val1 is even, divide it by 2 */
9147 while( !(val1 & 1) )
9148 val1 >>= 1; /*lint !e704*/
9149
9150 break;
9151 }
9152 }
9153
9154 /* while val2 is even, divide it by 2 */
9155 while( !(val2 & 1) )
9156 val2 >>= 1; /*lint !e704*/
9157
9158 /* the following if/else condition is only to make sure that we do not overflow when adding up both values before
9159 * dividing them by 4 in the following while loop
9160 */
9161 if( t == 0 )
9162 {
9163 if( val1 > val2 )
9164 {
9165 val1 -= val2;
9166
9167 /* divide val1 by 2 as long as possible */
9168 while( !(val1 & 1) )
9169 val1 >>= 1; /*lint !e704*/
9170 }
9171 else if( val1 < val2 )
9172 {
9173 val2 -= val1;
9174
9175 /* divide val2 by 2 as long as possible */
9176 while( !(val2 & 1) )
9177 val2 >>= 1; /*lint !e704*/
9178 }
9179 }
9180
9181 /* val1 and val2 are odd */
9182 while( val1 != val2 )
9183 {
9184 if( val1 > val2 )
9185 {
9186 /* we can stop if one value reached one */
9187 if( val2 == 1 )
9188 return (val2 << t); /*lint !e647 !e703*/
9189
9190 /* if ((val1 xor val2) and 2) = 2, then gcd(val1, val2) = gcd((val1 + val2)/4, val2),
9191 * and otherwise gcd(val1, val2) = gcd((val1 − val2)/4, val2)
9192 */
9193 if( ((val1 ^ val2) & 2) == 2 )
9194 val1 += val2;
9195 else
9196 val1 -= val2;
9197
9198 assert((val1 & 3) == 0);
9199 val1 >>= 2; /*lint !e704*/
9200
9201 /* if val1 is still even, divide it by 2 */
9202 while( !(val1 & 1) )
9203 val1 >>= 1; /*lint !e704*/
9204 }
9205 else
9206 {
9207 /* we can stop if one value reached one */
9208 if( val1 == 1 )
9209 return (val1 << t); /*lint !e647 !e703*/
9210
9211 /* if ((val2 xor val1) and 2) = 2, then gcd(val2, val1) = gcd((val2 + val1)/4, val1),
9212 * and otherwise gcd(val2, val1) = gcd((val2 − val1)/4, val1)
9213 */
9214 if( ((val2 ^ val1) & 2) == 2 )
9215 val2 += val1;
9216 else
9217 val2 -= val1;
9218
9219 assert((val2 & 3) == 0);
9220 val2 >>= 2; /*lint !e704*/
9221
9222 /* if val2 is still even, divide it by 2 */
9223 while( !(val2 & 1) )
9224 val2 >>= 1; /*lint !e704*/
9225 }
9226 }
9227
9228 return (val1 << t); /*lint !e703*/
9229}
9230
9231
9232/* for the MS compiler, the function nextafter is named _nextafter */
9233#if defined(_MSC_VER) && !defined(NO_NEXTAFTER)
9234#define nextafter(x,y) _nextafter(x,y)
9235#endif
9236
9237/* on systems where the function nextafter is not defined, we provide an implementation from Sun */
9238#ifdef NO_NEXTAFTER
9239/* The following implementation of the routine nextafter() comes with the following license:
9240 *
9241 * ====================================================
9242 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
9243 *
9244 * Developed at SunSoft, a Sun Microsystems, Inc. business.
9245 * Permission to use, copy, modify, and distribute this
9246 * software is freely granted, provided that this notice
9247 * is preserved.
9248 * ====================================================
9249 */
9250
9251#define __HI(x) *(1+(int*)&x)
9252#define __LO(x) *(int*)&x
9253#define __HIp(x) *(1+(int*)x)
9254#define __LOp(x) *(int*)x
9255
9256static
9257double nextafter(double x, double y)
9258{
9259 int hx;
9260 int hy;
9261 int ix;
9262 int iy;
9263 unsigned lx;
9264 unsigned ly;
9265
9266 /* cppcheck-suppress invalidPointerCast */
9267 hx = __HI(x); /* high word of x */
9268 /* cppcheck-suppress invalidPointerCast */
9269 lx = __LO(x); /* low word of x */
9270 /* cppcheck-suppress invalidPointerCast */
9271 hy = __HI(y); /* high word of y */
9272 /* cppcheck-suppress invalidPointerCast */
9273 ly = __LO(y); /* low word of y */
9274 ix = hx&0x7fffffff; /* |x| */
9275 iy = hy&0x7fffffff; /* |y| */
9276
9277 if( ((ix>=0x7ff00000) && ((ix-0x7ff00000)|lx) != 0 ) || /* x is nan */
9278 ( (iy>=0x7ff00000) && ((iy-0x7ff00000)|ly) != 0 )) /* y is nan */
9279 return x + y;
9280
9281 /* x == y, return x */
9282 if( x == y )
9283 return x;
9284
9285 /* x == 0 */
9286 if( (ix|lx) == 0 )
9287 {
9288 /* return +-minsubnormal */
9289 /* cppcheck-suppress invalidPointerCast */
9290 __HI(x) = hy&0x80000000;
9291 /* cppcheck-suppress invalidPointerCast */
9292 __LO(x) = 1;
9293 y = x * x;
9294 if ( y == x )
9295 return y;
9296 else
9297 return x; /* raise underflow flag */
9298 }
9299 /* x > 0 */
9300 if( hx >= 0 )
9301 {
9302 /* x > y, x -= ulp */
9303 if( hx > hy || ((hx == hy) && (lx > ly)) )
9304 {
9305 if ( lx == 0 )
9306 hx -= 1;
9307 lx -= 1;
9308 }
9309 else
9310 {
9311 /* x < y, x += ulp */
9312 lx += 1;
9313 if ( lx == 0 )
9314 hx += 1;
9315 }
9316 }
9317 else
9318 {
9319 /* x < 0 */
9320 if( hy >= 0 || hx > hy || ((hx == hy) && (lx > ly)) )
9321 {
9322 /* x < y, x -= ulp */
9323 if ( lx == 0 )
9324 hx -= 1;
9325 lx -= 1;
9326 }
9327 else
9328 {
9329 /* x > y, x += ulp */
9330 lx += 1;
9331 if( lx == 0 )
9332 hx += 1;
9333 }
9334 }
9335 hy = hx&0x7ff00000;
9336 /* overflow */
9337 if( hy >= 0x7ff00000 )
9338 return x + x;
9339 if( hy < 0x00100000 )
9340 {
9341 /* underflow */
9342 y = x*x;
9343 if( y != x )
9344 {
9345 /* raise underflow flag */
9346 /* cppcheck-suppress invalidPointerCast */
9347 __HI(y) = hx;
9348 /* cppcheck-suppress invalidPointerCast */
9349 __LO(y) = lx;
9350 return y;
9351 }
9352 }
9353
9354 /* cppcheck-suppress invalidPointerCast */
9355 __HI(x) = hx;
9356 /* cppcheck-suppress invalidPointerCast */
9357 __LO(x) = lx;
9358 return x;
9359}
9360#endif
9361
9362
9363/** returns the next representable value of from in the direction of to */
9365 SCIP_Real from, /**< value from which the next representable value should be returned */
9366 SCIP_Real to /**< direction in which the next representable value should be returned */
9367 )
9368{
9369 return nextafter(from, to);
9370}
9371
9372/** calculates the smallest common multiple of the two given values */
9374 SCIP_Longint val1, /**< first value of smallest common multiple calculation */
9375 SCIP_Longint val2 /**< second value of smallest common multiple calculation */
9376 )
9377{
9378 SCIP_Longint gcd;
9379
9380 assert(val1 > 0);
9381 assert(val2 > 0);
9382
9383 gcd = SCIPcalcGreComDiv(val1, val2);
9384
9385 return val1/gcd * val2;
9386}
9387
9388static 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,
9389 17.0, 18.0, 19.0, 25.0, -1.0};
9390
9391/** converts a real number into a (approximate) rational representation, and returns TRUE iff the conversion was
9392 * successful
9393 */
9395 SCIP_Real val, /**< real value r to convert into rational number */
9396 SCIP_Real mindelta, /**< minimal allowed difference r - q of real r and rational q = n/d */
9397 SCIP_Real maxdelta, /**< maximal allowed difference r - q of real r and rational q = n/d */
9398 SCIP_Longint maxdnom, /**< maximal denominator allowed */
9399 SCIP_Longint* nominator, /**< pointer to store the nominator n of the rational number */
9400 SCIP_Longint* denominator /**< pointer to store the denominator d of the rational number */
9401 )
9402{
9403 SCIP_Real a;
9404 SCIP_Real b;
9405 SCIP_Real g0;
9406 SCIP_Real g1;
9407 SCIP_Real gx;
9408 SCIP_Real h0;
9409 SCIP_Real h1;
9410 SCIP_Real hx;
9411 SCIP_Real delta0;
9412 SCIP_Real delta1;
9413 SCIP_Real epsilon;
9414 int i;
9415
9416 assert(mindelta < 0.0);
9417 assert(maxdelta > 0.0);
9418 assert(nominator != NULL);
9419 assert(denominator != NULL);
9420
9421 if( REALABS(val) >= ((SCIP_Real)SCIP_LONGINT_MAX) / maxdnom )
9422 return FALSE;
9423
9424 /* try the simple denominators first: each value of the simpledenoms table multiplied by powers of 10
9425 * is tried as denominator
9426 */
9427 for( i = 0; simplednoms[i] > 0.0; ++i )
9428 {
9429 SCIP_Real nom;
9430 SCIP_Real dnom;
9431 SCIP_Real ratval0;
9432 SCIP_Real ratval1;
9433
9434 /* try powers of 10 (including 10^0) */
9435 dnom = simplednoms[i];
9436 while( dnom <= maxdnom )
9437 {
9438 nom = floor(val * dnom);
9439 ratval0 = nom/dnom;
9440 ratval1 = (nom+1.0)/dnom;
9441 if( mindelta <= val - ratval0 && val - ratval1 <= maxdelta )
9442 {
9443 if( val - ratval0 <= maxdelta )
9444 {
9445 *nominator = (SCIP_Longint)nom;
9446 *denominator = (SCIP_Longint)dnom;
9447 return TRUE;
9448 }
9449 if( mindelta <= val - ratval1 )
9450 {
9451 *nominator = (SCIP_Longint)(nom+1.0);
9452 *denominator = (SCIP_Longint)dnom;
9453 return TRUE;
9454 }
9455 }
9456 dnom *= 10.0;
9457 }
9458 }
9459
9460 /* the simple denominators didn't work: calculate rational representation with arbitrary denominator */
9461 epsilon = MIN(-mindelta, maxdelta)/2.0;
9462
9463 b = val;
9464 a = EPSFLOOR(b, epsilon);
9465 g0 = a;
9466 h0 = 1.0;
9467 g1 = 1.0;
9468 h1 = 0.0;
9469 delta0 = val - g0/h0;
9470 delta1 = (delta0 < 0.0 ? val - (g0-1.0)/h0 : val - (g0+1.0)/h0);
9471
9472 while( (delta0 < mindelta || delta0 > maxdelta) && (delta1 < mindelta || delta1 > maxdelta) )
9473 {
9474 assert(EPSGT(b, a, epsilon));
9475 assert(h0 >= 0.0);
9476 assert(h1 >= 0.0);
9477
9478 b = 1.0 / (b - a);
9479 a = EPSFLOOR(b, epsilon);
9480
9481 assert(a >= 0.0);
9482 gx = g0;
9483 hx = h0;
9484
9485 g0 = a * g0 + g1;
9486 h0 = a * h0 + h1;
9487
9488 g1 = gx;
9489 h1 = hx;
9490
9491 if( h0 > maxdnom )
9492 return FALSE;
9493
9494 delta0 = val - g0/h0;
9495 delta1 = (delta0 < 0.0 ? val - (g0-1.0)/h0 : val - (g0+1.0)/h0);
9496 }
9497
9498 if( REALABS(g0) > (SCIP_Real)(SCIP_LONGINT_MAX >> 4) || h0 > (SCIP_Real)(SCIP_LONGINT_MAX >> 4) )
9499 return FALSE;
9500
9501 assert(h0 > 0.5);
9502
9503 if( delta0 < mindelta )
9504 {
9505 assert(mindelta <= delta1 && delta1 <= maxdelta);
9506 *nominator = (SCIP_Longint)(g0 - 1.0);
9507 *denominator = (SCIP_Longint)h0;
9508 }
9509 else if( delta0 > maxdelta )
9510 {
9511 assert(mindelta <= delta1 && delta1 <= maxdelta);
9512 *nominator = (SCIP_Longint)(g0 + 1.0);
9513 *denominator = (SCIP_Longint)h0;
9514 }
9515 else
9516 {
9517 *nominator = (SCIP_Longint)g0;
9518 *denominator = (SCIP_Longint)h0;
9519 }
9520 assert(*denominator >= 1);
9521 assert(val - (SCIP_Real)(*nominator)/(SCIP_Real)(*denominator) >= mindelta);
9522 assert(val - (SCIP_Real)(*nominator)/(SCIP_Real)(*denominator) <= maxdelta);
9523
9524 return TRUE;
9525}
9526
9527/** checks, whether the given scalar scales the given value to an integral number with error in the given bounds */
9528static
9530 SCIP_Real val, /**< value that should be scaled to an integral value */
9531 SCIP_Real scalar, /**< scalar that should be tried */
9532 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
9533 SCIP_Real maxdelta /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
9534 )
9535{
9536 SCIP_Real sval;
9537 SCIP_Real downval;
9538 SCIP_Real upval;
9539
9540 assert(mindelta <= 0.0);
9541 assert(maxdelta >= 0.0);
9542
9543 sval = val * scalar;
9544 downval = floor(sval);
9545 upval = ceil(sval);
9546
9547 return (SCIPrelDiff(sval, downval) <= maxdelta || SCIPrelDiff(sval, upval) >= mindelta);
9548}
9549
9550/** additional scalars that are tried in integrality scaling */
9551static const SCIP_Real scalars[] = {3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0};
9552static const int nscalars = 9;
9553
9554/** tries to find a value, such that all given values, if scaled with this value become integral in relative allowed
9555 * difference in between mindelta and maxdelta
9556 */
9558 SCIP_Real* vals, /**< values to scale */
9559 int nvals, /**< number of values to scale */
9560 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
9561 SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
9562 SCIP_Longint maxdnom, /**< maximal denominator allowed in rational numbers */
9563 SCIP_Real maxscale, /**< maximal allowed scalar */
9564 SCIP_Real* intscalar, /**< pointer to store scalar that would make the coefficients integral, or NULL */
9565 SCIP_Bool* success /**< stores whether returned value is valid */
9566 )
9567{
9568 SCIP_Real bestscalar;
9569 SCIP_Longint gcd;
9570 SCIP_Longint scm;
9571 SCIP_Longint nominator;
9572 SCIP_Longint denominator;
9573 SCIP_Real val;
9574 SCIP_Real minval;
9575 SCIP_Real absval;
9576 SCIP_Real scaleval;
9577 SCIP_Bool scalable;
9578 SCIP_Bool rational;
9579 int c;
9580 int s;
9581 int i;
9582
9583 assert(vals != NULL);
9584 assert(nvals >= 0);
9585 assert(maxdnom >= 1);
9586 assert(mindelta < 0.0);
9587 assert(maxdelta > 0.0);
9588 assert(success != NULL);
9589
9590 SCIPdebugMessage("trying to find rational representation for given values\n");
9591
9592 if( intscalar != NULL )
9593 *intscalar = SCIP_INVALID;
9594 *success = FALSE;
9595
9596 /* get minimal absolute non-zero value */
9597 minval = SCIP_REAL_MAX;
9598 for( c = 0; c < nvals; ++c )
9599 {
9600 val = vals[c];
9601 if( val < mindelta || val > maxdelta )
9602 {
9603 absval = REALABS(val);
9604 minval = MIN(minval, absval);
9605 }
9606 }
9607
9608 if( minval == SCIP_REAL_MAX ) /*lint !e777*/
9609 {
9610 /* all coefficients are zero (inside tolerances) */
9611 if( intscalar != NULL )
9612 *intscalar = 1.0;
9613 *success = TRUE;
9614 SCIPdebugMessage(" -> all values are zero (inside tolerances)\n");
9615
9616 return SCIP_OKAY;
9617 }
9618 assert(minval > MIN(-mindelta, maxdelta));
9619
9620 bestscalar = SCIP_INVALID;
9621
9622 for( i = 0; i < 2; ++i )
9623 {
9624 scalable = TRUE;
9625
9626 /* try, if values can be made integral multiplying them with the reciprocal of the smallest value and a power of 2 */
9627 if( i == 0 )
9628 scaleval = 1.0/minval;
9629 /* try, if values can be made integral by multiplying them by a power of 2 */
9630 else
9631 scaleval = 1.0;
9632
9633 for( c = 0; c < nvals && scalable; ++c )
9634 {
9635 /* check, if the value can be scaled with a simple scalar */
9636 val = vals[c];
9637 if( val == 0.0 ) /* zeros are allowed in the vals array */
9638 continue;
9639
9640 absval = REALABS(val);
9641 while( scaleval <= maxscale
9642 && (absval * scaleval < 0.5 || !isIntegralScalar(val, scaleval, mindelta, maxdelta)) )
9643 {
9644 for( s = 0; s < nscalars; ++s )
9645 {
9646 if( isIntegralScalar(val, scaleval * scalars[s], mindelta, maxdelta) )
9647 {
9648 scaleval *= scalars[s];
9649 break;
9650 }
9651 }
9652 if( s >= nscalars )
9653 scaleval *= 2.0;
9654 }
9655 scalable = (scaleval <= maxscale);
9656 SCIPdebugMessage(" -> val=%g, scaleval=%g, val*scaleval=%g, scalable=%u\n",
9657 val, scaleval, val*scaleval, scalable);
9658 }
9659 if( scalable )
9660 {
9661 /* make values integral by dividing them by the smallest value (and multiplying them with a power of 2) */
9662 assert(scaleval <= maxscale);
9663
9664 /* check if we found a better scaling value */
9665 if( scaleval < bestscalar )
9666 bestscalar = scaleval;
9667
9668 SCIPdebugMessage(" -> integrality could be achieved by scaling with %g\n", scaleval);
9669
9670 /* if the scalar is still the reciprocal of the minimal value, all coeffcients are the same and we do not get a better scalar */
9671 if( i == 0 && EPSEQ(scaleval, 1.0/minval, SCIP_DEFAULT_EPSILON) )
9672 {
9673 if( intscalar != NULL )
9674 *intscalar = bestscalar;
9675 *success = TRUE;
9676
9677 return SCIP_OKAY;
9678 }
9679 }
9680 }
9681
9682 /* convert each value into a rational number, calculate the greatest common divisor of the nominators
9683 * and the smallest common multiple of the denominators
9684 */
9685 gcd = 1;
9686 scm = 1;
9687 rational = TRUE;
9688
9689 /* first value (to initialize gcd) */
9690 for( c = 0; c < nvals && rational; ++c )
9691 {
9692 val = vals[c];
9693 if( val == 0.0 ) /* zeros are allowed in the vals array */
9694 continue;
9695
9696 rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &nominator, &denominator);
9697 if( rational && nominator != 0 )
9698 {
9699 assert(denominator > 0);
9700 gcd = ABS(nominator);
9701 scm = denominator;
9702 rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
9703 SCIPdebugMessage(" -> c=%d first rational: val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
9704 c, val, nominator, denominator, gcd, scm, rational);
9705 break;
9706 }
9707 }
9708
9709 /* remaining values */
9710 for( ++c; c < nvals && rational; ++c )
9711 {
9712 val = vals[c];
9713 if( val == 0.0 ) /* zeros are allowed in the vals array */
9714 continue;
9715
9716 rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &nominator, &denominator);
9717 if( rational && nominator != 0 )
9718 {
9719 assert(denominator > 0);
9720 gcd = SCIPcalcGreComDiv(gcd, ABS(nominator));
9721 scm *= denominator / SCIPcalcGreComDiv(scm, denominator);
9722 rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
9723 SCIPdebugMessage(" -> c=%d next rational : val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
9724 c, val, nominator, denominator, gcd, scm, rational);
9725 }
9726 else
9727 {
9728 SCIPdebugMessage(" -> failed to convert %g into a rational representation\n", val);
9729 }
9730 }
9731
9732 if( rational )
9733 {
9734 /* make values integral by multiplying them with the smallest common multiple of the denominators */
9735 assert((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
9736
9737 /* check if we found a better scaling value */
9738 if( (SCIP_Real)scm/(SCIP_Real)gcd < bestscalar )
9739 bestscalar = (SCIP_Real)scm/(SCIP_Real)gcd;
9740
9741 SCIPdebugMessage(" -> integrality could be achieved by scaling with %g (rational:%" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ")\n",
9742 (SCIP_Real)scm/(SCIP_Real)gcd, scm, gcd);
9743 }
9744
9745 if( bestscalar < SCIP_INVALID )
9746 {
9747 if( intscalar != NULL )
9748 *intscalar = bestscalar;
9749 *success = TRUE;
9750
9751 SCIPdebugMessage(" -> smallest value to achieve integrality is %g \n", bestscalar);
9752 }
9753
9754 return SCIP_OKAY;
9755}
9756
9757/* Inform compiler that this code accesses the floating-point environment, so that
9758 * certain optimizations should be omitted (http://www.cplusplus.com/reference/cfenv/FENV_ACCESS/).
9759 * Not supported by Clang (gives warning) and GCC (silently), at the moment.
9760 */
9761#if defined(__INTEL_COMPILER) || defined(_MSC_VER)
9762#pragma fenv_access (on)
9763#elif defined(__GNUC__) && !defined(__clang__)
9764#pragma STDC FENV_ACCESS ON
9765#endif
9766#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
9767#if defined(__clang__)
9768__attribute__((optnone))
9769#else
9770__attribute__((optimize(0)))
9771#endif
9772#endif
9773/** given a (usually very small) interval, tries to find a rational number with simple denominator (i.e. a small
9774 * number, probably multiplied with powers of 10) out of this interval; returns TRUE iff a valid rational
9775 * number inside the interval was found
9776 */
9778 SCIP_Real lb, /**< lower bound of the interval */
9779 SCIP_Real ub, /**< upper bound of the interval */
9780 SCIP_Longint maxdnom, /**< maximal denominator allowed for resulting rational number */
9781 SCIP_Longint* nominator, /**< pointer to store the nominator n of the rational number */
9782 SCIP_Longint* denominator /**< pointer to store the denominator d of the rational number */
9783 )
9784{
9785 SCIP_Real center;
9786 SCIP_Real delta;
9787
9788 assert(lb <= ub);
9789
9790 center = 0.5*(lb+ub);
9791
9792 /* in order to compute a rational number that is exactly within the bounds (as the user expects),
9793 * we computed the allowed delta with downward rounding, if available
9794 */
9796 {
9797 SCIP_ROUNDMODE roundmode;
9798
9799 roundmode = SCIPintervalGetRoundingMode();
9801
9802 delta = 0.5*(ub-lb);
9803
9804 SCIPintervalSetRoundingMode(roundmode);
9805 }
9806 else
9807 {
9808 delta = 0.5*(ub-lb);
9809 }
9810
9811 return SCIPrealToRational(center, -delta, +delta, maxdnom, nominator, denominator);
9812}
9813
9814#if defined(__INTEL_COMPILER) || defined(_MSC_VER)
9815#pragma fenv_access (off)
9816#elif defined(__GNUC__) && !defined(__clang__)
9817#pragma STDC FENV_ACCESS OFF
9818#endif
9819
9820/** given a (usually very small) interval, selects a value inside this interval; it is tried to select a rational number
9821 * with simple denominator (i.e. a small number, probably multiplied with powers of 10);
9822 * if no valid rational number inside the interval was found, selects the central value of the interval
9823 */
9825 SCIP_Real lb, /**< lower bound of the interval */
9826 SCIP_Real ub, /**< upper bound of the interval */
9827 SCIP_Longint maxdnom /**< maximal denominator allowed for resulting rational number */
9828 )
9829{
9830 SCIP_Real val;
9831
9832 val = 0.5*(lb+ub);
9833 if( lb < ub )
9834 {
9835 SCIP_Longint nominator;
9836 SCIP_Longint denominator;
9837 SCIP_Bool success;
9838
9839 /* try to find a "simple" rational number inside the interval */
9840 SCIPdebugMessage("simple rational in [%.9f,%.9f]:", lb, ub);
9841 success = SCIPfindSimpleRational(lb, ub, maxdnom, &nominator, &denominator);
9842 if( success )
9843 {
9844 val = (SCIP_Real)nominator/(SCIP_Real)denominator;
9845 SCIPdebugPrintf(" %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT " == %.9f\n", nominator, denominator, val);
9846
9847 if( val - lb < 0.0 || val - ub > 0.0 )
9848 {
9849 SCIPdebugPrintf(" value is out of interval bounds by %g -> failed\n", MAX(lb-val, val-ub));
9850 val = 0.5*(lb+ub);
9851 }
9852 }
9853 else
9854 {
9855 SCIPdebugPrintf(" failed\n");
9856 }
9857 }
9858
9859 return val;
9860}
9861
9862/** Performs the Newton Procedure from a given starting point to compute a root of the given function with
9863 * specified precision and maximum number of iterations. If the procedure fails, SCIP_INVALID is returned.
9864 */
9866 SCIP_DECL_NEWTONEVAL((*function)), /**< pointer to function for which roots are computed */
9867 SCIP_DECL_NEWTONEVAL((*derivative)), /**< pointer to derivative of above function */
9868 SCIP_Real* params, /**< parameters needed for function (can be NULL) */
9869 int nparams, /**< number of parameters (can be 0) */
9870 SCIP_Real x, /**< starting point */
9871 SCIP_Real eps, /**< tolerance */
9872 int k /**< iteration limit */
9873 )
9874{
9875 SCIP_Real result = x;
9876 int iteration = 0;
9877
9878 assert(function != NULL);
9879 assert(derivative != NULL);
9880 assert(params != NULL || nparams == 0);
9881 assert(eps > 0.0);
9882 assert(k >= 0);
9883 assert(x != SCIP_INVALID); /*lint !e777*/
9884
9885 while( iteration < k )
9886 {
9887 SCIP_Real deriv = derivative(result, params, nparams);
9888
9889 /* if we arrive at a stationary point, the procedure is aborted */
9890 if( REALABS(deriv) <= eps || deriv == SCIP_INVALID ) /*lint !e777*/
9891 return SCIP_INVALID;
9892
9893 result = result - function(result, params, nparams) / deriv;
9894
9895 /* if new point is within eps-range of 0, we are done */
9896 if( REALABS(function(result, params, nparams)) <= eps )
9897 break;
9898
9899 ++iteration;
9900 }
9901
9902 if( k == iteration )
9903 return SCIP_INVALID;
9904 else
9905 return result;
9906}
9907
9908
9909/*
9910 * Random Numbers
9911 */
9912
9913#if defined(NO_RAND_R) || defined(_WIN32) || defined(_WIN64)
9914
9915#define SCIP_RAND_MAX 32767
9916/** returns a random number between 0 and SCIP_RAND_MAX */
9917static
9918int getRand(
9919 unsigned int* seedp /**< pointer to seed value */
9920 )
9921{
9922 SCIP_Longint nextseed;
9923
9924 assert(seedp != NULL);
9925
9926 nextseed = (*seedp) * (SCIP_Longint)1103515245 + 12345;
9927 *seedp = (unsigned int)nextseed;
9928
9929 return (int)((unsigned int)(nextseed/(2*(SCIP_RAND_MAX+1))) % (SCIP_RAND_MAX+1));
9930}
9931
9932#else
9933
9934#define SCIP_RAND_MAX RAND_MAX
9935
9936/** returns a random number between 0 and SCIP_RAND_MAX */
9937static
9939 unsigned int* seedp /**< pointer to seed value */
9940 )
9941{
9942 return rand_r(seedp);
9943}
9944
9945#endif
9946
9947/** returns a random integer between minrandval and maxrandval */
9948static
9950 int minrandval, /**< minimal value to return */
9951 int maxrandval, /**< maximal value to return */
9952 unsigned int* seedp /**< pointer to seed value */
9953 )
9954{
9955 SCIP_Real randnumber;
9956
9957 randnumber = (SCIP_Real)getRand(seedp)/(SCIP_RAND_MAX+1.0);
9958 assert(randnumber >= 0.0);
9959 assert(randnumber < 1.0);
9960
9961 /* we multiply minrandval and maxrandval separately by randnumber in order to avoid overflow if they are more than INT_MAX
9962 * apart
9963 */
9964 return (int) (minrandval*(1.0 - randnumber) + maxrandval*randnumber + randnumber);
9965}
9966
9967/** returns a random real between minrandval and maxrandval */
9968static
9970 SCIP_Real minrandval, /**< minimal value to return */
9971 SCIP_Real maxrandval, /**< maximal value to return */
9972 unsigned int* seedp /**< pointer to seed value */
9973 )
9974{
9975 SCIP_Real randnumber;
9976
9977 randnumber = (SCIP_Real)getRand(seedp)/(SCIP_Real)SCIP_RAND_MAX;
9978 assert(randnumber >= 0.0);
9979 assert(randnumber <= 1.0);
9980
9981 /* we multiply minrandval and maxrandval separately by randnumber in order to avoid overflow if they are more than
9982 * SCIP_REAL_MAX apart
9983 */
9984 return minrandval*(1.0 - randnumber) + maxrandval*randnumber;
9985}
9986
9987/** returns a random integer between minrandval and maxrandval
9988 *
9989 * @deprecated Please use SCIPrandomGetInt() to request a random integer.
9990 */
9992 int minrandval, /**< minimal value to return */
9993 int maxrandval, /**< maximal value to return */
9994 unsigned int* seedp /**< pointer to seed value */
9995 )
9996{
9997 return getRandomInt(minrandval, maxrandval, seedp);
9998}
9999
10000/** returns a random real between minrandval and maxrandval
10001 *
10002 * @deprecated Please use SCIPrandomGetReal() to request a random real.
10003 */
10005 SCIP_Real minrandval, /**< minimal value to return */
10006 SCIP_Real maxrandval, /**< maximal value to return */
10007 unsigned int* seedp /**< pointer to seed value */
10008 )
10009{
10010 return getRandomReal(minrandval, maxrandval, seedp);
10011}
10012
10013
10014/* initial seeds for KISS random number generator */
10015#define DEFAULT_SEED UINT32_C(123456789)
10016#define DEFAULT_XOR UINT32_C(362436000)
10017#define DEFAULT_MWC UINT32_C(521288629)
10018#define DEFAULT_CST UINT32_C(7654321)
10019
10020
10021/** initializes a random number generator with a given start seed */
10023 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10024 unsigned int initseed /**< initial random seed */
10025 )
10026{
10027 assert(randnumgen != NULL);
10028
10029 /* use MAX() to avoid zero after over flowing */
10030 randnumgen->seed = MAX(SCIPhashTwo(DEFAULT_SEED, initseed), 1u);
10031 randnumgen->xor_seed = MAX(SCIPhashTwo(DEFAULT_XOR, initseed), 1u);
10032 randnumgen->mwc_seed = MAX(SCIPhashTwo(DEFAULT_MWC, initseed), 1u);
10033 randnumgen->cst_seed = SCIPhashTwo(DEFAULT_CST, initseed);
10034
10035 assert(randnumgen->seed > 0);
10036 assert(randnumgen->xor_seed > 0);
10037 assert(randnumgen->mwc_seed > 0);
10038}
10039
10040/** returns a random number between 0 and UINT32_MAX
10041 *
10042 * implementation of KISS random number generator developed by George Marsaglia.
10043 * KISS is combination of three different random number generators:
10044 * - Linear congruential generator
10045 * - Xorshift
10046 * - Lag-1 Multiply-with-carry
10047 *
10048 * KISS has a period of 2^123 and passes all statistical test part of BigCrush-Test of TestU01 [1].
10049 *
10050 * [1] http://dl.acm.org/citation.cfm?doid=1268776.1268777
10051 */
10052static
10054 SCIP_RANDNUMGEN* randnumgen /**< random number generator */
10055 )
10056{
10057 uint64_t t;
10058
10059 /* linear congruential */
10060 randnumgen->seed = (uint32_t) (randnumgen->seed * UINT64_C(1103515245) + UINT64_C(12345));
10061
10062 /* Xorshift */
10063 randnumgen->xor_seed ^= (randnumgen->xor_seed << 13);
10064 randnumgen->xor_seed ^= (randnumgen->xor_seed >> 17);
10065 randnumgen->xor_seed ^= (randnumgen->xor_seed << 5);
10066
10067 /* Multiply-with-carry */
10068 t = UINT64_C(698769069) * randnumgen->mwc_seed + randnumgen->cst_seed;
10069 randnumgen->cst_seed = (uint32_t) (t >> 32);
10070 randnumgen->mwc_seed = (uint32_t) t;
10071
10072 return randnumgen->seed + randnumgen->xor_seed + randnumgen->mwc_seed;
10073}
10074
10075/** creates and initializes a random number generator */
10077 SCIP_RANDNUMGEN** randnumgen, /**< random number generator */
10078 BMS_BLKMEM* blkmem, /**< block memory */
10079 unsigned int initialseed /**< initial random seed */
10080 )
10081{
10082 assert(randnumgen != NULL);
10083
10084 SCIP_ALLOC( BMSallocBlockMemory(blkmem, randnumgen) );
10085
10086 SCIPrandomSetSeed((*randnumgen), initialseed);
10087
10088 return SCIP_OKAY;
10089}
10090
10091/** frees a random number generator */
10093 SCIP_RANDNUMGEN** randnumgen, /**< random number generator */
10094 BMS_BLKMEM* blkmem /**< block memory */
10095 )
10096{
10097 assert(randnumgen != NULL);
10098 assert((*randnumgen) != NULL);
10099
10100 BMSfreeBlockMemory(blkmem, randnumgen);
10101
10102 return;
10103}
10104
10105
10106
10107/** returns a random integer between minrandval and maxrandval */
10109 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10110 int minrandval, /**< minimal value to return */
10111 int maxrandval /**< maximal value to return */
10112 )
10113{
10114 SCIP_Real randnumber;
10115 SCIP_Longint zeromax;
10116
10117 randnumber = (SCIP_Real)randomGetRand(randnumgen)/(UINT32_MAX+1.0);
10118 assert(randnumber >= 0.0);
10119 assert(randnumber < 1.0);
10120
10121 /* we need to shift the range to the non-negative integers to handle negative integer values correctly.
10122 * we use a long integer to avoid overflows.
10123 */
10124 zeromax = (SCIP_Longint)maxrandval - (SCIP_Longint)minrandval + 1;
10125
10126 return (int) ((SCIP_Longint)(zeromax * randnumber) + (SCIP_Longint)minrandval);
10127}
10128
10129/** returns a random real between minrandval and maxrandval */
10131 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10132 SCIP_Real minrandval, /**< minimal value to return */
10133 SCIP_Real maxrandval /**< maximal value to return */
10134 )
10135{
10136 SCIP_Real randnumber;
10137
10138 randnumber = (SCIP_Real)randomGetRand(randnumgen)/(SCIP_Real)UINT32_MAX;
10139 assert(randnumber >= 0.0);
10140 assert(randnumber <= 1.0);
10141
10142 /* we multiply minrandval and maxrandval separately by randnumber in order to avoid overflow if they are more than
10143 * SCIP_REAL_MAX apart
10144 */
10145 return minrandval*(1.0 - randnumber) + maxrandval*randnumber;
10146}
10147
10148/** randomly shuffles parts of an integer array using the Fisher-Yates algorithm */
10150 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10151 int* array, /**< array to be shuffled */
10152 int begin, /**< first included index that should be subject to shuffling
10153 * (0 for first array entry)
10154 */
10155 int end /**< first excluded index that should not be subject to shuffling
10156 * (array size for last array entry)
10157 */
10158 )
10159{
10160 int tmp;
10161 int i;
10162
10163 /* loop backwards through all elements and always swap the current last element to a random position */
10164 while( end > begin+1 )
10165 {
10166 --end;
10167
10168 /* get a random position into which the last entry should be shuffled */
10169 i = SCIPrandomGetInt(randnumgen, begin, end);
10170
10171 /* swap the last element and the random element */
10172 tmp = array[i];
10173 array[i] = array[end];
10174 array[end] = tmp;
10175 }
10176}
10177
10178/** randomly shuffles parts of an array using the Fisher-Yates algorithm */
10180 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10181 void** array, /**< array to be shuffled */
10182 int begin, /**< first included index that should be subject to shuffling
10183 * (0 for first array entry)
10184 */
10185 int end /**< first excluded index that should not be subject to shuffling
10186 * (array size for last array entry)
10187 */
10188 )
10189{
10190 void* tmp;
10191 int i;
10192
10193 /* loop backwards through all elements and always swap the current last element to a random position */
10194 while( end > begin+1 )
10195 {
10196 end--;
10197
10198 /* get a random position into which the last entry should be shuffled */
10199 i = SCIPrandomGetInt(randnumgen, begin, end);
10200
10201 /* swap the last element and the random element */
10202 tmp = array[i];
10203 array[i] = array[end];
10204 array[end] = tmp;
10205 }
10206}
10207
10208/** draws a random subset of disjoint elements from a given set of disjoint elements;
10209 * this implementation is suited for the case that nsubelems is considerably smaller then nelems
10210 */
10212 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10213 void** set, /**< original set, from which elements should be drawn */
10214 int nelems, /**< number of elements in original set */
10215 void** subset, /**< subset in which drawn elements should be stored */
10216 int nsubelems /**< number of elements that should be drawn and stored */
10217 )
10218{
10219 int i;
10220 int j;
10221
10222 /* if both sets are of equal size, we just copy the array */
10223 if( nelems == nsubelems)
10224 {
10225 BMScopyMemoryArray(subset,set,nelems);
10226 return SCIP_OKAY;
10227 }
10228
10229 /* abort, if size of subset is too big */
10230 if( nsubelems > nelems )
10231 {
10232 SCIPerrorMessage("Cannot create %d-elementary subset of %d-elementary set.\n", nsubelems, nelems);
10233 return SCIP_INVALIDDATA;
10234 }
10235#ifndef NDEBUG
10236 for( i = 0; i < nsubelems; i++ )
10237 for( j = 0; j < i; j++ )
10238 assert(set[i] != set[j]);
10239#endif
10240
10241 /* draw each element individually */
10242 i = 0;
10243 while( i < nsubelems )
10244 {
10245 int r;
10246
10247 r = SCIPrandomGetInt(randnumgen, 0, nelems-1);
10248 subset[i] = set[r];
10249
10250 /* if we get an element that we already had, we will draw again */
10251 for( j = 0; j < i; j++ )
10252 {
10253 if( subset[i] == subset[j] )
10254 {
10255 --i;
10256 break;
10257 }
10258 }
10259 ++i;
10260 }
10261 return SCIP_OKAY;
10262}
10263
10264/*
10265 * Additional math functions
10266 */
10267
10268/** calculates a binomial coefficient n over m, choose m elements out of n, maximal value will be 33 over 16 (because
10269 * 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
10270 * big numbers or an negative value m (and m < n) and -1 will be returned
10271 */
10273 int n, /**< number of different elements */
10274 int m /**< number to choose out of the above */
10275 )
10276{
10277 if( m == 0 || m >= n )
10278 return 1;
10279
10280 if( m < 0 )
10281 return -1;
10282
10283 /* symmetry of the binomial coefficient, choose smaller m */
10284 if( m > n/2 )
10285 m = n - m;
10286
10287 /* trivial case m == 1 */
10288 if( m == 1 )
10289 return n;
10290
10291 /* simple case m == 2 */
10292 if( m == 2 )
10293 {
10294 if( ((SCIP_Real)SCIP_LONGINT_MAX) / n >= (n-1) * 2 ) /*lint !e790*/
10295 return ((SCIP_Longint)n*(n-1)/2); /*lint !e647*/
10296 else
10297 return -1;
10298 }
10299
10300 /* abort on to big numbers */
10301 if( m > 16 || n > 33 )
10302 return -1;
10303
10304 /* simple case m == 3 */
10305 if( m == 3 )
10306 return (n*(n-1)*(n-2)/6); /*lint !e647*/
10307 else
10308 {
10309 /* first half of Pascal's triangle numbers(without the symmetric part) backwards from (33,16) over (32,16),
10310 * (33,15), (32,15),(31,15, (30,15), (33,14) to (8,4) (rest is calculated directly)
10311 *
10312 * due to this order we can extract the right binomial coefficient by (16-m)^2+(16-m)+(33-n)
10313 */
10314 static const SCIP_Longint binoms[182] = {
10315 1166803110, 601080390, 1037158320, 565722720, 300540195, 155117520, 818809200, 471435600, 265182525, 145422675,
10316 77558760, 40116600, 573166440, 347373600, 206253075, 119759850, 67863915, 37442160, 20058300, 10400600,
10317 354817320, 225792840, 141120525, 86493225, 51895935, 30421755, 17383860, 9657700, 5200300, 2704156, 193536720,
10318 129024480, 84672315, 54627300, 34597290, 21474180, 13037895, 7726160, 4457400, 2496144, 1352078, 705432,
10319 92561040, 64512240, 44352165, 30045015, 20030010, 13123110, 8436285, 5311735, 3268760, 1961256, 1144066,
10320 646646, 352716, 184756, 38567100, 28048800, 20160075, 14307150, 10015005, 6906900, 4686825, 3124550, 2042975,
10321 1307504, 817190, 497420, 293930, 167960, 92378, 48620, 13884156, 10518300, 7888725, 5852925, 4292145, 3108105,
10322 2220075, 1562275, 1081575, 735471, 490314, 319770, 203490, 125970, 75582, 43758, 24310, 12870, 4272048, 3365856,
10323 2629575, 2035800, 1560780, 1184040, 888030, 657800, 480700, 346104, 245157, 170544, 116280, 77520, 50388, 31824,
10324 19448, 11440, 6435, 3432, 1107568, 906192, 736281, 593775, 475020, 376740, 296010, 230230, 177100, 134596,
10325 100947, 74613, 54264, 38760, 27132, 18564, 12376, 8008, 5005, 3003, 1716, 924, 237336, 201376, 169911, 142506,
10326 118755, 98280, 80730, 65780, 53130, 42504, 33649, 26334, 20349, 15504, 11628, 8568, 6188, 4368, 3003, 2002,
10327 1287, 792, 462, 252, 40920, 35960, 31465, 27405, 23751, 20475, 17550, 14950, 12650, 10626, 8855, 7315, 5985,
10328 4845, 3876, 3060, 2380, 1820, 1365, 1001, 715, 495, 330, 210, 126, 70};
10329
10330 /* m can at most be 16 */
10331 const int t = 16-m;
10332 assert(t >= 0);
10333 assert(n <= 33);
10334
10335 /* binoms array hast exactly 182 elements */
10336 assert(t*(t+1)+(33-n) < 182);
10337
10338 return binoms[t*(t+1)+(33-n)]; /*lint !e662 !e661*/
10339 }
10340}
10341
10342#ifndef NDEBUG
10343/** calculates hash for floating-point number by using Fibonacci hashing */
10344#if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ * 10 >= 490 && !defined(__INTEL_COMPILER)
10345__attribute__((no_sanitize_undefined))
10346#endif
10347unsigned int SCIPcalcFibHash(
10348 SCIP_Real v /**< number to hash */
10349 )
10350{
10351 if( v >= 0 )
10352 return ((unsigned long long)(v * 2654435769)) % UINT_MAX;
10353 return ((unsigned long long)(-v * 683565275)) % UINT_MAX;
10354}
10355#endif
10356
10357/** negates a number */
10359 SCIP_Real x /**< value to negate */
10360 )
10361{
10362 return -x;
10363}
10364
10365/*
10366 * Permutations / Shuffling
10367 */
10368
10369/** swaps two ints */
10371 int* value1, /**< pointer to first integer */
10372 int* value2 /**< pointer to second integer */
10373 )
10374{
10375 int tmp;
10376
10377 tmp = *value1;
10378 *value1 = *value2;
10379 *value2 = tmp;
10380}
10381
10382/** swaps two real values */
10384 SCIP_Real* value1, /**< pointer to first real value */
10385 SCIP_Real* value2 /**< pointer to second real value */
10386 )
10387{
10388 SCIP_Real tmp;
10389
10390 tmp = *value1;
10391 *value1 = *value2;
10392 *value2 = tmp;
10393}
10394
10395/** swaps the addresses of two pointers */
10397 void** pointer1, /**< first pointer */
10398 void** pointer2 /**< second pointer */
10399 )
10400{
10401 void* tmp;
10402
10403 tmp = *pointer1;
10404 *pointer1 = *pointer2;
10405 *pointer2 = tmp;
10406}
10407
10408/** randomly shuffles parts of an integer array using the Fisher-Yates algorithm
10409 *
10410 * @deprecated Please use SCIPrandomPermuteIntArray()
10411 */
10413 int* array, /**< array to be shuffled */
10414 int begin, /**< first included index that should be subject to shuffling
10415 * (0 for first array entry)
10416 */
10417 int end, /**< first excluded index that should not be subject to shuffling
10418 * (array size for last array entry)
10419 */
10420 unsigned int* randseed /**< seed value for the random generator */
10421 )
10422{
10423 int tmp;
10424 int i;
10425
10426 /* loop backwards through all elements and always swap the current last element to a random position */
10427 while( end > begin+1 )
10428 {
10429 --end;
10430
10431 /* get a random position into which the last entry should be shuffled */
10432 i = getRandomInt(begin, end, randseed);
10433
10434 /* swap the last element and the random element */
10435 tmp = array[i];
10436 array[i] = array[end];
10437 array[end] = tmp;
10438 }
10439}
10440
10441
10442/** randomly shuffles parts of an array using the Fisher-Yates algorithm
10443 *
10444 * @deprecated Please use SCIPrandomPermuteArray()
10445 */
10447 void** array, /**< array to be shuffled */
10448 int begin, /**< first included index that should be subject to shuffling
10449 * (0 for first array entry)
10450 */
10451 int end, /**< first excluded index that should not be subject to shuffling
10452 * (array size for last array entry)
10453 */
10454 unsigned int* randseed /**< seed value for the random generator */
10455 )
10456{
10457 void* tmp;
10458 int i;
10459
10460 /* loop backwards through all elements and always swap the current last element to a random position */
10461 while( end > begin+1 )
10462 {
10463 end--;
10464
10465 /* get a random position into which the last entry should be shuffled */
10466 i = getRandomInt(begin, end, randseed);
10467
10468 /* swap the last element and the random element */
10469 tmp = array[i];
10470 array[i] = array[end];
10471 array[end] = tmp;
10472 }
10473}
10474
10475/** draws a random subset of disjoint elements from a given set of disjoint elements;
10476 * this implementation is suited for the case that nsubelems is considerably smaller then nelems
10477 *
10478 * @deprecated Please use SCIPrandomGetSubset()
10479 */
10481 void** set, /**< original set, from which elements should be drawn */
10482 int nelems, /**< number of elements in original set */
10483 void** subset, /**< subset in which drawn elements should be stored */
10484 int nsubelems, /**< number of elements that should be drawn and stored */
10485 unsigned int randseed /**< seed value for random generator */
10486 )
10487{
10488 int i;
10489 int j;
10490
10491 /* if both sets are of equal size, we just copy the array */
10492 if( nelems == nsubelems)
10493 {
10494 BMScopyMemoryArray(subset,set,nelems);
10495 return SCIP_OKAY;
10496 }
10497
10498 /* abort, if size of subset is too big */
10499 if( nsubelems > nelems )
10500 {
10501 SCIPerrorMessage("Cannot create %d-elementary subset of %d-elementary set.\n", nsubelems, nelems);
10502 return SCIP_INVALIDDATA;
10503 }
10504#ifndef NDEBUG
10505 for( i = 0; i < nsubelems; i++ )
10506 for( j = 0; j < i; j++ )
10507 assert(set[i] != set[j]);
10508#endif
10509
10510 /* draw each element individually */
10511 i = 0;
10512 while( i < nsubelems )
10513 {
10514 int r;
10515
10516 r = getRandomInt(0, nelems-1, &randseed);
10517 subset[i] = set[r];
10518
10519 /* if we get an element that we already had, we will draw again */
10520 for( j = 0; j < i; j++ )
10521 {
10522 if( subset[i] == subset[j] )
10523 {
10524 --i;
10525 break;
10526 }
10527 }
10528 ++i;
10529 }
10530 return SCIP_OKAY;
10531}
10532
10533
10534/*
10535 * Arrays
10536 */
10537
10538/** computes set intersection (duplicates removed) of two integer arrays that are ordered ascendingly
10539 *
10540 * @deprecated Switch to SCIPcomputeArraysIntersectionInt().
10541 */
10543 int* array1, /**< first array (in ascending order) */
10544 int narray1, /**< number of entries of first array */
10545 int* array2, /**< second array (in ascending order) */
10546 int narray2, /**< number of entries of second array */
10547 int* intersectarray, /**< intersection of array1 and array2
10548 * (note: it is possible to use array1 for this input argument) */
10549 int* nintersectarray /**< pointer to store number of entries of intersection array
10550 * (note: it is possible to use narray1 for this input argument) */
10551 )
10552{
10553 SCIPcomputeArraysIntersectionInt(array1, narray1, array2, narray2, intersectarray, nintersectarray);
10554
10555 return SCIP_OKAY;
10556}
10557
10558/** computes set intersection (duplicates removed) of two integer arrays that are ordered ascendingly */
10560 int* array1, /**< first array (in ascending order) */
10561 int narray1, /**< number of entries of first array */
10562 int* array2, /**< second array (in ascending order) */
10563 int narray2, /**< number of entries of second array */
10564 int* intersectarray, /**< intersection of array1 and array2
10565 * (note: it is possible to use array1 for this input argument) */
10566 int* nintersectarray /**< pointer to store number of entries of intersection array
10567 * (note: it is possible to use narray1 for this input argument) */
10568 )
10569{
10570 int cnt = 0;
10571 int k = 0;
10572 int v1;
10573 int v2;
10574
10575 assert( array1 != NULL );
10576 assert( array2 != NULL );
10577 assert( intersectarray != NULL );
10578 assert( nintersectarray != NULL );
10579
10580 /* determine intersection of array1 and array2 */
10581 for (v1 = 0; v1 < narray1; ++v1)
10582 {
10583 assert( v1 == 0 || array1[v1] >= array1[v1-1] );
10584
10585 /* skip duplicate entries */
10586 if ( v1+1 < narray1 && array1[v1] == array1[v1+1])
10587 continue;
10588
10589 for (v2 = k; v2 < narray2; ++v2)
10590 {
10591 assert( v2 == 0 || array2[v2] >= array2[v2-1] );
10592
10593 if ( array2[v2] > array1[v1] )
10594 {
10595 k = v2;
10596 break;
10597 }
10598 else if ( array2[v2] == array1[v1] )
10599 {
10600 intersectarray[cnt++] = array2[v2];
10601 k = v2 + 1;
10602 break;
10603 }
10604 }
10605 }
10606
10607 /* store size of intersection array */
10608 *nintersectarray = cnt;
10609}
10610
10611/** computes set intersection (duplicates removed) of two void-pointer arrays that are ordered ascendingly */
10613 void** array1, /**< pointer to first data array */
10614 int narray1, /**< number of entries of first array */
10615 void** array2, /**< pointer to second data array */
10616 int narray2, /**< number of entries of second array */
10617 SCIP_DECL_SORTPTRCOMP((*ptrcomp)), /**< data element comparator */
10618 void** intersectarray, /**< intersection of array1 and array2
10619 * (note: it is possible to use array1 for this input argument) */
10620 int* nintersectarray /**< pointer to store number of entries of intersection array
10621 * (note: it is possible to use narray1 for this input argument) */
10622 )
10623{
10624 int cnt = 0;
10625 int k = 0;
10626 int v1;
10627 int v2;
10628
10629 assert( array1 != NULL );
10630 assert( array2 != NULL );
10631 assert( ptrcomp != NULL );
10632 assert( intersectarray != NULL );
10633 assert( nintersectarray != NULL );
10634
10635 /* determine intersection of array1 and array2 */
10636 for( v1 = 0; v1 < narray1; ++v1 )
10637 {
10638 assert( v1 == 0 || (*ptrcomp)(array1[v1], array1[v1-1]) >= 0 );
10639
10640 /* skip duplicate entries */
10641 if( v1+1 < narray1 && array1[v1] == array1[v1+1] )
10642 continue;
10643
10644 for( v2 = k; v2 < narray2; ++v2 )
10645 {
10646 assert( v2 == 0 || (*ptrcomp)(array2[v2], array2[v2-1]) > 0 || array2[v2] == array2[v2-1] );
10647
10648 if( (*ptrcomp)(array2[v2], array1[v1]) > 0 )
10649 {
10650 k = v2;
10651 break;
10652 }
10653
10654 if( array2[v2] == array1[v1] )
10655 {
10656 intersectarray[cnt++] = array2[v2];
10657 k = v2 + 1;
10658 break;
10659 }
10660 }
10661 }
10662
10663 /* store size of intersection array */
10664 *nintersectarray = cnt;
10665}
10666
10667
10668/** computes set difference (duplicates removed) of two integer arrays that are ordered ascendingly
10669 *
10670 * @deprecated Switch to SCIPcomputeArraysSetminusInt().
10671 */
10673 int* array1, /**< first array (in ascending order) */
10674 int narray1, /**< number of entries of first array */
10675 int* array2, /**< second array (in ascending order) */
10676 int narray2, /**< number of entries of second array */
10677 int* setminusarray, /**< array to store entries of array1 that are not an entry of array2
10678 * (note: it is possible to use array1 for this input argument) */
10679 int* nsetminusarray /**< pointer to store number of entries of setminus array
10680 * (note: it is possible to use narray1 for this input argument) */
10681 )
10682{
10683 SCIPcomputeArraysSetminusInt(array1, narray1, array2, narray2, setminusarray, nsetminusarray);
10684
10685 return SCIP_OKAY;
10686}
10687
10688/** computes set difference (duplicates removed) of two integer arrays that are ordered ascendingly */
10690 int* array1, /**< first array (in ascending order) */
10691 int narray1, /**< number of entries of first array */
10692 int* array2, /**< second array (in ascending order) */
10693 int narray2, /**< number of entries of second array */
10694 int* setminusarray, /**< array to store entries of array1 that are not an entry of array2
10695 * (note: it is possible to use array1 for this input argument) */
10696 int* nsetminusarray /**< pointer to store number of entries of setminus array
10697 * (note: it is possible to use narray1 for this input argument) */
10698 )
10699{
10700 int cnt = 0;
10701 int v1 = 0;
10702 int v2 = 0;
10703
10704 assert( array1 != NULL );
10705 assert( array2 != NULL );
10706 assert( setminusarray != NULL );
10707 assert( nsetminusarray != NULL );
10708
10709 while ( v1 < narray1 )
10710 {
10711 int entry1;
10712
10713 assert( v1 == 0 || array1[v1] >= array1[v1-1] );
10714
10715 /* skip duplicate entries */
10716 while ( v1 + 1 < narray1 && array1[v1] == array1[v1 + 1] )
10717 ++v1;
10718
10719 entry1 = array1[v1];
10720
10721 while ( v2 < narray2 && array2[v2] < entry1 )
10722 ++v2;
10723
10724 if ( v2 >= narray2 || entry1 < array2[v2] )
10725 setminusarray[cnt++] = entry1;
10726 ++v1;
10727 }
10728
10729 /* store size of setminus array */
10730 *nsetminusarray = cnt;
10731}
10732
10733
10734/*
10735 * Strings
10736 */
10737
10738
10739/** copies characters from 'src' to 'dest', copying is stopped when either the 'stop' character is reached or after
10740 * 'cnt' characters have been copied, whichever comes first.
10741 *
10742 * @note undefined behavior on overlapping arrays
10743 */
10745 char* dest, /**< destination pointer to copy to */
10746 const char* src, /**< source pointer to copy from */
10747 char stop, /**< character when found stop copying */
10748 unsigned int cnt /**< maximal number of characters to copy */
10749 )
10750{
10751 if( dest == NULL || src == NULL || cnt == 0 )
10752 return -1;
10753 else
10754 {
10755 char* destination = dest;
10756
10757 while( cnt-- && (*destination++ = *src++) != stop ); /*lint !e722*/
10758
10759 return (int)(destination - dest);
10760 }
10761}
10762
10763/** prints an error message containing of the given string followed by a string describing the current system error
10764 *
10765 * Prefers to use the strerror_r method, which is threadsafe. On systems where this method does not exist,
10766 * NO_STRERROR_R should be defined (see INSTALL). In this case, strerror is used which is not guaranteed to be
10767 * threadsafe (on SUN-systems, it actually is).
10768 */
10770 const char* message /**< first part of the error message, e.g. the filename */
10771 )
10772{
10773#ifdef NO_STRERROR_R
10774 SCIPmessagePrintError("%s: %s\n", message, strerror(errno));
10775#else
10776 char buf[SCIP_MAXSTRLEN];
10777
10778#if defined(_WIN32) || defined(_WIN64)
10779 /* strerror_s returns 0 on success; the string is \0 terminated. */
10780 if ( strerror_s(buf, SCIP_MAXSTRLEN, errno) != 0 )
10781 SCIPmessagePrintError("Unknown error number %d or error message too long.\n", errno);
10782 SCIPmessagePrintError("%s: %s\n", message, buf);
10783#elif (_POSIX_C_SOURCE >= 200112L || __DARWIN_C_LEVEL > 200112L || _XOPEN_SOURCE >= 600) && ! defined(_GNU_SOURCE)
10784 /* We are in the POSIX/XSI case, where strerror_r returns 0 on success; \0 termination is unclear. */
10785 if ( strerror_r(errno, buf, SCIP_MAXSTRLEN) != 0 )
10786 SCIPmessagePrintError("Unknown error number %d.\n", errno);
10787 buf[SCIP_MAXSTRLEN - 1] = '\0';
10788 SCIPmessagePrintError("%s: %s\n", message, buf);
10789#else
10790 /* We are in the GNU case, where strerror_r returns a pointer to the error string. This string is possibly stored
10791 * in buf and is always \0 terminated.
10792 * However, if compiling on one system and executing on another system, we might actually call a different
10793 * variant of the strerror_r function than we had at compile time.
10794 */
10795 char* errordescr;
10796 *buf = '\0';
10797 errordescr = strerror_r(errno, buf, SCIP_MAXSTRLEN);
10798 if( *buf != '\0' )
10799 {
10800 /* strerror_r wrote into buf */
10801 SCIPmessagePrintError("%s: %s\n", message, buf);
10802 }
10803 else if( errordescr != NULL )
10804 {
10805 /* strerror_r returned something non-NULL */
10806 SCIPmessagePrintError("%s: %s\n", message, errordescr);
10807 }
10808 else
10809 {
10810 /* strerror_r did return NULL and did not write into buf */
10811 SCIPmessagePrintError("Could not obtain description for error %d.\n", errno);
10812 }
10813#endif
10814#endif
10815}
10816
10817/** extracts tokens from strings - wrapper method for strtok_r() */
10819 char* s, /**< string to parse */
10820 const char* delim, /**< delimiters for parsing */
10821 char** ptrptr /**< pointer to working char pointer - must stay the same while parsing */
10822 )
10823{
10824#ifdef SCIP_NO_STRTOK_R
10825 return strtok(s, delim);
10826#else
10827 return strtok_r(s, delim, ptrptr);
10828#endif
10829}
10830
10831/** translates the given string into a string where unescaped symbols ", ', and spaces are escaped with a \ prefix */
10833 char* t, /**< target buffer to store escaped string */
10834 int bufsize, /**< size of buffer t */
10835 const char* s /**< string to transform into escaped string */
10836 )
10837{
10838 int len;
10839 int i;
10840 int p;
10841
10842 assert(t != NULL);
10843 assert(bufsize > 0);
10844
10845 len = (int)strlen(s);
10846 for( p = 0, i = 0; i <= len && p < bufsize; ++i, ++p )
10847 {
10848 if( s[i] == '\\' )
10849 {
10850 t[p] = s[i];
10851 ++p;
10852 ++i;
10853 }
10854 else if( s[i] == ' ' || s[i] == '\"' || s[i] == '\'' )
10855 {
10856 t[p] = '\\';
10857 ++p;
10858 }
10859 if( i <= len && p < bufsize )
10860 t[p] = s[i];
10861 }
10862 t[bufsize-1] = '\0';
10863}
10864
10865/** increases string pointer as long as it refers to a space character or an explicit space control sequence */
10867 char** s /**< pointer to string pointer */
10868 )
10869{
10870 while( isspace(**s) || ( **s == '\\' && *(*s+1) != '\0' && strchr(SCIP_SPACECONTROL, *(*s+1)) ) )
10871 *s += **s == '\\' ? 2 : 1;
10872
10873 return SCIP_OKAY;
10874}
10875
10876/* safe version of snprintf */
10878 char* t, /**< target string */
10879 int len, /**< length of the string to copy */
10880 const char* s, /**< source string */
10881 ... /**< further parameters */
10882 )
10883{
10884 va_list ap;
10885 int n;
10886
10887 assert(t != NULL);
10888 assert(len > 0);
10889
10890 va_start(ap, s); /*lint !e826*/
10891
10892#if defined(_MSC_VER) && _MSC_VER < 1900
10893 n = _vsnprintf(t, (size_t) len, s, ap);
10894#else
10895 n = vsnprintf(t, (size_t) len, s, ap); /*lint !e571*/
10896#endif
10897 va_end(ap);
10898
10899 if( n < 0 || n >= len )
10900 {
10901#ifndef NDEBUG
10902 if( n < 0 )
10903 {
10904 SCIPerrorMessage("vsnprintf returned %d\n",n);
10905 }
10906#endif
10907 t[len-1] = '\0';
10908 }
10909 return n;
10910}
10911
10912/** safe version of strncpy
10913 *
10914 * Copies string in s to t using at most @a size-1 nonzero characters (strncpy copies size characters). It always adds
10915 * a terminating zero char. Does not pad the remaining string with zero characters (unlike strncpy). Returns the number
10916 * of copied nonzero characters, if the length of s is at most size - 1, and returns size otherwise. Thus, the original
10917 * string was truncated if the return value is size.
10918 */
10920 char* t, /**< target string */
10921 const char* s, /**< source string */
10922 int size /**< maximal size of t */
10923 )
10924{
10925 int n;
10926
10927 if( size <= 0 )
10928 return 0;
10929
10930 /* decrease size by 1 to create space for terminating zero char */
10931 --size;
10932 for( n = 0; n < size && *s != '\0'; n++ )
10933 *(t++) = *(s++);
10934 *t = '\0';
10935
10936 if( *s != '\0' )
10937 ++n;
10938
10939 return n;
10940}
10941
10942/** 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
10943 *
10944 * @return Returns TRUE if a value could be extracted, otherwise FALSE
10945 */
10947 const char* str, /**< string to search */
10948 int* value, /**< pointer to store the parsed value */
10949 char** endptr /**< pointer to store the final string position if successfully parsed, otherwise @p str */
10950 )
10951{
10952 assert(str != NULL);
10953 assert(value != NULL);
10954 assert(endptr != NULL);
10955
10956 /* init errno to detect possible errors */
10957 errno = 0;
10958
10959 *value = (int) strtol(str, endptr, 10);
10960
10961 if( *endptr != str && *endptr != NULL )
10962 {
10963 SCIPdebugMessage("parsed integer value <%d>\n", *value);
10964 return TRUE;
10965 }
10966 *endptr = (char*)str;
10967
10968 SCIPdebugMessage("failed parsing integer value <%s>\n", str);
10969
10970 return FALSE;
10971}
10972
10973/** 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
10974 *
10975 * @return Returns TRUE if a value could be extracted, otherwise FALSE
10976 */
10978 const char* str, /**< string to search */
10979 SCIP_Real* value, /**< pointer to store the parsed value */
10980 char** endptr /**< pointer to store the final string position if successfully parsed, otherwise @p str */
10981 )
10982{
10983 assert(str != NULL);
10984 assert(value != NULL);
10985 assert(endptr != NULL);
10986
10987 /* init errno to detect possible errors */
10988 errno = 0;
10989
10990 *value = strtod(str, endptr);
10991
10992 if( *endptr != str && *endptr != NULL )
10993 {
10994 SCIPdebugMessage("parsed real value <%g>\n", *value);
10995 return TRUE;
10996 }
10997 *endptr = (char*)str;
10998
10999 SCIPdebugMessage("failed parsing real value <%s>\n", str);
11000
11001 return FALSE;
11002}
11003
11004/** copies the first size characters between a start and end character of str into token, if no error occurred endptr
11005 * will point to the position after the read part, otherwise it will point to @p str
11006 */
11008 const char* str, /**< string to search */
11009 char startchar, /**< character which defines the beginning */
11010 char endchar, /**< character which defines the ending */
11011 char* token, /**< string to store the copy */
11012 int size, /**< size of the token char array */
11013 char** endptr /**< pointer to store the final string position if successfully parsed, otherwise @p str */
11014 )
11015{
11016 const char* copystr;
11017 int nchars;
11018
11019 assert(str != NULL);
11020 assert(token != NULL);
11021 assert(size > 0);
11022 assert(endptr != NULL);
11023
11024 nchars = 0;
11025
11026 copystr = str;
11027
11028 /* find starting character */
11029 while( *str != '\0' && *str != startchar )
11030 ++str;
11031
11032 /* did not find start character */
11033 if( *str == '\0' )
11034 {
11035 *endptr = (char*)copystr;
11036 return;
11037 }
11038
11039 /* skip start character */
11040 ++str;
11041
11042 /* copy string */
11043 while( *str != '\0' && *str != endchar && nchars < size-1 )
11044 {
11045 assert(nchars < SCIP_MAXSTRLEN);
11046 token[nchars] = *str;
11047 nchars++;
11048 ++str;
11049 }
11050
11051 /* add end to token */
11052 token[nchars] = '\0';
11053
11054 /* if section was longer than size, we want to reach the end of the parsing section anyway */
11055 if( nchars == (size-1) )
11056 while( *str != '\0' && *str != endchar )
11057 ++str;
11058
11059 /* did not find end character */
11060 if( *str == '\0' )
11061 {
11062 *endptr = (char*)copystr;
11063 return;
11064 }
11065
11066 /* skip end character */
11067 ++str;
11068
11069 SCIPdebugMessage("parsed section <%s>\n", token);
11070
11071 *endptr = (char*) str;
11072}
11073
11074/*
11075 * File methods
11076 */
11077
11078/** returns, whether the given file exists */
11080 const char* filename /**< file name */
11081 )
11082{
11083 FILE* f;
11084
11085 f = fopen(filename, "r");
11086 if( f == NULL )
11087 return FALSE;
11088
11089 fclose(f);
11090
11091 return TRUE;
11092}
11093
11094/** splits filename into path, name, and extension */
11096 char* filename, /**< filename to split; is destroyed (but not freed) during process */
11097 char** path, /**< pointer to store path, or NULL if not needed */
11098 char** name, /**< pointer to store name, or NULL if not needed */
11099 char** extension, /**< pointer to store extension, or NULL if not needed */
11100 char** compression /**< pointer to store compression extension, or NULL if not needed */
11101 )
11102{
11103 char* lastslash;
11104 char* lastbackslash;
11105 char* lastdot;
11106
11107 assert(filename != NULL);
11108
11109 if( path != NULL )
11110 *path = NULL;
11111 if( name != NULL )
11112 *name = NULL;
11113 if( extension != NULL )
11114 *extension = NULL;
11115 if( compression != NULL )
11116 *compression = NULL;
11117
11118 /* treat both slashes '/' and '\' as directory delimiters */
11119 lastslash = strrchr(filename, '/');
11120 lastbackslash = strrchr(filename, '\\');
11121 lastslash = MAX(lastslash, lastbackslash); /*lint !e613*/
11122 lastdot = strrchr(filename, '.');
11123 if( lastslash != NULL && lastdot != NULL && lastdot < lastslash ) /* is the last dot belonging to the path? */
11124 lastdot = NULL;
11125
11126 /* detect known compression extensions */
11127#ifdef SCIP_WITH_ZLIB
11128 if( lastdot != NULL )
11129 {
11130 char* compext;
11131
11132 compext = lastdot+1;
11133 if( strcmp(compext, "gz") == 0
11134 || strcmp(compext, "z") == 0
11135 || strcmp(compext, "Z") == 0 )
11136 {
11137 if( compression != NULL )
11138 *compression = compext;
11139 *lastdot = '\0';
11140 }
11141
11142 /* find again the last dot in the filename without compression extension */
11143 lastdot = strrchr(filename, '.');
11144 if( lastslash != NULL && lastdot != NULL && lastdot < lastslash ) /* is the last dot belonging to the path? */
11145 lastdot = NULL;
11146 }
11147#endif
11148
11149 if( lastslash == NULL )
11150 {
11151 if( name != NULL )
11152 *name = filename;
11153 }
11154 else
11155 {
11156 if( path != NULL )
11157 *path = filename;
11158 if( name != NULL )
11159 *name = lastslash+1;
11160 *lastslash = '\0';
11161 }
11162
11163 if( lastdot != NULL )
11164 {
11165 if( extension != NULL )
11166 *extension = lastdot+1;
11167 *lastdot = '\0';
11168 }
11169}
11170
11171/*
11172 * simple functions implemented as defines
11173 */
11174
11175/* In debug mode, the following methods are implemented as function calls to ensure
11176 * type validity.
11177 * In optimized mode, the methods are implemented as defines to improve performance.
11178 * However, we want to have them in the library anyways, so we have to undef the defines.
11179 */
11180
11181#undef SCIPrelDiff
11182
11183/** returns the relative difference: (val1-val2)/max(|val1|,|val2|,1.0) */
11185 SCIP_Real val1, /**< first value to be compared */
11186 SCIP_Real val2 /**< second value to be compared */
11187 )
11188{
11189 SCIP_Real absval1;
11190 SCIP_Real absval2;
11191 SCIP_Real quot;
11192
11193 absval1 = REALABS(val1);
11194 absval2 = REALABS(val2);
11195 quot = MAX3(1.0, absval1, absval2);
11196
11197 return (val1-val2)/quot;
11198}
11199
11200
11201/** computes the gap from the primal and the dual bound */
11203 SCIP_Real eps, /**< the value treated as zero */
11204 SCIP_Real inf, /**< the value treated as infinity */
11205 SCIP_Real primalbound, /**< the primal bound */
11206 SCIP_Real dualbound /**< the dual bound */
11207 )
11208{
11209 if( EPSEQ(primalbound, dualbound, eps) )
11210 return 0.0;
11211 else
11212 {
11213 SCIP_Real absdual = REALABS(dualbound);
11214 SCIP_Real absprimal = REALABS(primalbound);
11215
11216 if( EPSZ(dualbound, eps) || EPSZ(primalbound, eps) || absprimal >= inf || absdual >= inf ||
11217 primalbound * dualbound < 0.0 )
11218 return inf;
11219 else
11220 return REALABS((primalbound - dualbound)/MIN(absdual, absprimal));
11221 }
11222}
11223
11224/*
11225 * disjoint set (union-find) data structure
11226 */
11227
11228/** creates a disjoint set (union find) structure \p djset for \p ncomponents many components (of size one) */
11230 SCIP_DISJOINTSET** djset, /**< disjoint set (union find) data structure */
11231 BMS_BLKMEM* blkmem, /**< block memory */
11232 int ncomponents /**< number of components */
11233 )
11234{
11235 assert(djset != NULL);
11236 assert(blkmem != NULL);
11237
11238 /* allocate the necessary memory */
11239 assert(ncomponents > 0);
11240 SCIP_ALLOC( BMSallocBlockMemory(blkmem, djset) );
11241 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &((*djset)->parents), ncomponents) );
11242 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &((*djset)->sizes), ncomponents) );
11243 (*djset)->size = ncomponents;
11244
11245 /* clear the data structure */
11246 SCIPdisjointsetClear(*djset);
11247
11248 return SCIP_OKAY;
11249}
11250
11251/** clears the disjoint set (union find) structure \p djset */
11253 SCIP_DISJOINTSET* djset /**< disjoint set (union find) data structure */
11254 )
11255{
11256 int i;
11257
11258 djset->componentcount = djset->size;
11259
11260 /* reset all components to be unconnected */
11261 for( i = 0; i < djset->componentcount; i++ )
11262 {
11263 djset->parents[i] = i;
11264 djset->sizes[i] = 1;
11265 }
11266}
11267
11268/** finds and returns the component identifier of this \p element */
11270 SCIP_DISJOINTSET* djset, /**< disjoint set (union find) data structure */
11271 int element /**< element to be found */
11272 )
11273{
11274 int newelement;
11275 int root = element;
11276 int* parents = djset->parents;
11277
11278 /* find root of this element */
11279 while( root != parents[root] )
11280 {
11281 root = parents[root];
11282 }
11283
11284 /* compress the path to make future queries faster */
11285 while( element != root )
11286 {
11287 newelement = parents[element];
11288 parents[element] = root;
11289 element = newelement;
11290 }
11291
11292 return root;
11293}
11294
11295/** merges the components containing the elements \p p and \p q */
11297 SCIP_DISJOINTSET* djset, /**< disjoint set (union find) data structure */
11298 int p, /**< first element */
11299 int q, /**< second element */
11300 SCIP_Bool forcerepofp /**< force representative of p to be new representative */
11301 )
11302{
11303 int idp;
11304 int idq;
11305 int* sizes;
11306 int* parents;
11307
11308 assert(djset != NULL);
11309 assert(0 <= p);
11310 assert(0 <= q);
11311 assert(djset->size > p);
11312 assert(djset->size > q);
11313
11314 idp = SCIPdisjointsetFind(djset, p);
11315 idq = SCIPdisjointsetFind(djset, q);
11316
11317 /* if p and q lie in the same component, there is nothing to be done */
11318 if( idp == idq )
11319 return;
11320
11321 sizes = djset->sizes;
11322 parents = djset->parents;
11323
11324 if( forcerepofp )
11325 {
11326 parents[idq] = idp;
11327 sizes[idp] += sizes[idq];
11328 }
11329 else
11330 {
11331 if( sizes[idp] < sizes[idq] )
11332 {
11333 parents[idp] = idq;
11334 sizes[idq] += sizes[idp];
11335 }
11336 else
11337 {
11338 parents[idq] = idp;
11339 sizes[idp] += sizes[idq];
11340 }
11341 }
11342 /* one less component */
11343 djset->componentcount--;
11344}
11345
11346/** frees the disjoint set (union find) data structure */
11348 SCIP_DISJOINTSET** djset, /**< pointer to disjoint set (union find) data structure */
11349 BMS_BLKMEM* blkmem /**< block memory */
11350 )
11351{
11352 SCIP_DISJOINTSET* dsptr;
11353
11354 assert(djset != NULL);
11355 assert(*djset != NULL);
11356
11357 dsptr = *djset;
11358
11359 BMSfreeBlockMemoryArray(blkmem, &dsptr->sizes, dsptr->size);
11360 BMSfreeBlockMemoryArray(blkmem, &dsptr->parents, dsptr->size);
11361
11362 BMSfreeBlockMemory(blkmem, djset);
11363}
11364
11365/** returns the number of independent components in this disjoint set (union find) data structure */
11367 SCIP_DISJOINTSET* djset /**< disjoint set (union find) data structure */
11368 )
11369{
11370 assert(djset != NULL);
11371
11372 return djset->componentcount;
11373}
11374
11375/** returns the size (number of nodes) of this disjoint set (union find) data structure */
11377 SCIP_DISJOINTSET* djset /**< disjoint set (union find) data structure */
11378 )
11379{
11380 assert(djset != NULL);
11381
11382 return djset->size;
11383}
11384
11385/** checks whether a given string t appears at the beginning of the string s (up to spaces at beginning) */
11387 const char* s, /**< string to search in */
11388 const char* t, /**< string to search for */
11389 size_t tlen /**< length of t */
11390 )
11391{
11392 int idxctr = 0;
11393
11394 assert(s != NULL);
11395 assert(t != NULL);
11396
11397 /* skip whitespace at beginning */
11398 while( idxctr < SCIP_MAXSTRLEN && isspace((unsigned char)s[idxctr]) )
11399 ++idxctr;
11400 if( strncmp(&s[idxctr], t, tlen) == 0 )
11401 return TRUE;
11402 return FALSE;
11403}
SCIP_VAR * h
Definition: circlepacking.c:68
SCIP_VAR * w
Definition: circlepacking.c:67
SCIP_VAR * a
Definition: circlepacking.c:66
SCIP_VAR ** b
Definition: circlepacking.c:65
SCIP_VAR ** y
Definition: circlepacking.c:64
SCIP_Real * r
Definition: circlepacking.c:59
SCIP_VAR ** x
Definition: circlepacking.c:63
common defines and data types used in all packages of SCIP
#define NULL
Definition: def.h:267
#define SCIP_MAXSTRLEN
Definition: def.h:288
#define SCIP_Longint
Definition: def.h:158
#define SCIP_UNUSED(x)
Definition: def.h:428
#define LOG2(x)
Definition: def.h:230
#define SCIP_SPACECONTROL
Definition: def.h:289
#define SCIP_REAL_MAX
Definition: def.h:174
#define SCIP_INVALID
Definition: def.h:193
#define SCIP_Bool
Definition: def.h:91
#define SCIP_DEFAULT_EPSILON
Definition: def.h:179
#define MIN(x, y)
Definition: def.h:243
#define SCIP_ALLOC(x)
Definition: def.h:385
#define MAX3(x, y, z)
Definition: def.h:247
#define SCIP_ALLOC_TERMINATE(retcode, x, TERM)
Definition: def.h:405
#define SCIP_Real
Definition: def.h:173
#define ABS(x)
Definition: def.h:235
#define EPSEQ(x, y, eps)
Definition: def.h:198
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:239
#define SCIP_CALL_ABORT(x)
Definition: def.h:353
#define SCIP_CALL_TERMINATE(retcode, x, TERM)
Definition: def.h:395
#define SCIP_LONGINT_FORMAT
Definition: def.h:165
#define EPSFLOOR(x, eps)
Definition: def.h:206
#define REALABS(x)
Definition: def.h:197
#define EPSGT(x, y, eps)
Definition: def.h:201
#define SCIP_LONGINT_MAX
Definition: def.h:159
#define EPSZ(x, eps)
Definition: def.h:203
#define SCIP_CALL(x)
Definition: def.h:374
#define SCIP_CALL_FINALLY(x, y)
Definition: def.h:416
#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:10612
void SCIPcomputeArraysSetminusInt(int *array1, int narray1, int *array2, int narray2, int *setminusarray, int *nsetminusarray)
Definition: misc.c:10689
SCIP_RETCODE SCIPcomputeArraysIntersection(int *array1, int narray1, int *array2, int narray2, int *intersectarray, int *nintersectarray)
Definition: misc.c:10542
SCIP_RETCODE SCIPcomputeArraysSetminus(int *array1, int narray1, int *array2, int narray2, int *setminusarray, int *nsetminusarray)
Definition: misc.c:10672
void SCIPcomputeArraysIntersectionInt(int *array1, int narray1, int *array2, int narray2, int *intersectarray, int *nintersectarray)
Definition: misc.c:10559
void SCIPbtnodeSetRightchild(SCIP_BTNODE *node, SCIP_BTNODE *right)
Definition: misc.c:8947
SCIP_BTNODE * SCIPbtnodeGetRightchild(SCIP_BTNODE *node)
Definition: misc.c:8816
SCIP_Bool SCIPbtIsEmpty(SCIP_BT *tree)
Definition: misc.c:9059
SCIP_RETCODE SCIPbtCreate(SCIP_BT **tree, BMS_BLKMEM *blkmem)
Definition: misc.c:8958
void SCIPbtnodeFree(SCIP_BT *tree, SCIP_BTNODE **node)
Definition: misc.c:8741
SCIP_Bool SCIPbtnodeIsLeaf(SCIP_BTNODE *node)
Definition: misc.c:8856
void SCIPbtnodeSetData(SCIP_BTNODE *node, void *dataptr)
Definition: misc.c:8905
void * SCIPbtnodeGetData(SCIP_BTNODE *node)
Definition: misc.c:8786
SCIP_RETCODE SCIPbtnodeCreate(SCIP_BT *tree, SCIP_BTNODE **node, void *dataptr)
Definition: misc.c:8677
SCIP_Bool SCIPbtnodeIsRightchild(SCIP_BTNODE *node)
Definition: misc.c:8884
void SCIPbtnodeSetParent(SCIP_BTNODE *node, SCIP_BTNODE *parent)
Definition: misc.c:8919
SCIP_BTNODE * SCIPbtnodeGetSibling(SCIP_BTNODE *node)
Definition: misc.c:8826
SCIP_Bool SCIPbtnodeIsLeftchild(SCIP_BTNODE *node)
Definition: misc.c:8866
void SCIPbtnodeSetLeftchild(SCIP_BTNODE *node, SCIP_BTNODE *left)
Definition: misc.c:8933
SCIP_BTNODE * SCIPbtnodeGetParent(SCIP_BTNODE *node)
Definition: misc.c:8796
void SCIPbtFree(SCIP_BT **tree)
Definition: misc.c:8977
SCIP_BTNODE * SCIPbtnodeGetLeftchild(SCIP_BTNODE *node)
Definition: misc.c:8806
void SCIPbtSetRoot(SCIP_BT *tree, SCIP_BTNODE *root)
Definition: misc.c:9082
SCIP_Bool SCIPbtnodeIsRoot(SCIP_BTNODE *node)
Definition: misc.c:8846
SCIP_BTNODE * SCIPbtGetRoot(SCIP_BT *tree)
Definition: misc.c:9069
void SCIPbtPrintGml(SCIP_BT *tree, FILE *file)
Definition: misc.c:9029
void SCIPdigraphPrintComponents(SCIP_DIGRAPH *digraph, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: misc.c:8624
void ** SCIPdigraphGetSuccessorsData(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7837
void SCIPdigraphFreeComponents(SCIP_DIGRAPH *digraph)
Definition: misc.c:8518
int SCIPdigraphGetNSuccessors(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7804
SCIP_RETCODE SCIPdigraphComputeUndirectedComponents(SCIP_DIGRAPH *digraph, int minsize, int *components, int *ncomponents)
Definition: misc.c:8089
int SCIPdigraphGetNNodes(SCIP_DIGRAPH *digraph)
Definition: misc.c:7746
void SCIPdigraphPrintGml(SCIP_DIGRAPH *digraph, FILE *file)
Definition: misc.c:8585
void SCIPdigraphGetComponent(SCIP_DIGRAPH *digraph, int compidx, int **nodes, int *nnodes)
Definition: misc.c:8298
SCIP_RETCODE SCIPdigraphAddArc(SCIP_DIGRAPH *digraph, int startnode, int endnode, void *data)
Definition: misc.c:7662
SCIP_RETCODE SCIPdigraphTopoSortComponents(SCIP_DIGRAPH *digraph)
Definition: misc.c:8219
SCIP_RETCODE SCIPdigraphSetSizes(SCIP_DIGRAPH *digraph, int *sizes)
Definition: misc.c:7544
SCIP_RETCODE SCIPdigraphComputeDirectedComponents(SCIP_DIGRAPH *digraph, int compidx, int *strongcomponents, int *strongcompstartidx, int *nstrongcomponents)
Definition: misc.c:8430
SCIP_RETCODE SCIPdigraphAddArcSafe(SCIP_DIGRAPH *digraph, int startnode, int endnode, void *data)
Definition: misc.c:7693
void SCIPdigraphFree(SCIP_DIGRAPH **digraph)
Definition: misc.c:7568
int SCIPdigraphGetNArcs(SCIP_DIGRAPH *digraph)
Definition: misc.c:7786
void SCIPdigraphPrint(SCIP_DIGRAPH *digraph, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: misc.c:8550
void * SCIPdigraphGetNodeData(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7756
void SCIPdigraphSetNodeData(SCIP_DIGRAPH *digraph, void *dataptr, int node)
Definition: misc.c:7772
SCIP_RETCODE SCIPdigraphSetNSuccessors(SCIP_DIGRAPH *digraph, int node, int nsuccessors)
Definition: misc.c:7730
int * SCIPdigraphGetSuccessors(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7819
int SCIPdigraphGetNComponents(SCIP_DIGRAPH *digraph)
Definition: misc.c:8285
SCIP_RETCODE SCIPdigraphResize(SCIP_DIGRAPH *digraph, int nnodes)
Definition: misc.c:7414
SCIP_RETCODE SCIPdigraphGetArticulationPoints(SCIP_DIGRAPH *digraph, int **articulations, int *narticulations)
Definition: misc.c:8000
int SCIPdisjointsetGetSize(SCIP_DISJOINTSET *djset)
Definition: misc.c:11376
void SCIPdisjointsetClear(SCIP_DISJOINTSET *djset)
Definition: misc.c:11252
int SCIPdisjointsetGetComponentCount(SCIP_DISJOINTSET *djset)
Definition: misc.c:11366
int SCIPdisjointsetFind(SCIP_DISJOINTSET *djset, int element)
Definition: misc.c:11269
void SCIPdisjointsetUnion(SCIP_DISJOINTSET *djset, int p, int q, SCIP_Bool forcerepofp)
Definition: misc.c:11296
SCIP_Bool SCIPfileExists(const char *filename)
Definition: misc.c:11079
void SCIPsplitFilename(char *filename, char **path, char **name, char **extension, char **compression)
Definition: misc.c:11095
void SCIPdotWriteOpening(FILE *file)
Definition: misc.c:711
void SCIPdotWriteClosing(FILE *file)
Definition: misc.c:749
void SCIPdotWriteArc(FILE *file, int source, int target, const char *color)
Definition: misc.c:736
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:545
void SCIPgmlWriteNode(FILE *file, unsigned int id, const char *label, const char *nodetype, const char *fillcolor, const char *bordercolor)
Definition: misc.c:497
void SCIPgmlWriteClosing(FILE *file)
Definition: misc.c:699
void SCIPdotWriteNode(FILE *file, int node, const char *label, const char *nodetype, const char *fillcolor, const char *bordercolor)
Definition: misc.c:721
void SCIPgmlWriteOpening(FILE *file, SCIP_Bool directed)
Definition: misc.c:683
void SCIPgmlWriteEdge(FILE *file, unsigned int source, unsigned int target, const char *label, const char *color)
Definition: misc.c:595
void SCIPgmlWriteArc(FILE *file, unsigned int source, unsigned int target, const char *label, const char *color)
Definition: misc.c:639
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3108
void * SCIPhashmapEntryGetImage(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3570
SCIP_Real SCIPhashmapGetImageReal(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3301
SCIP_RETCODE SCIPhashmapInsertReal(SCIP_HASHMAP *hashmap, void *origin, SCIP_Real image)
Definition: misc.c:3228
void SCIPhashmapPrintStatistics(SCIP_HASHMAP *hashmap, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:3485
int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3281
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3261
SCIP_RETCODE SCIPhashmapSetImageReal(SCIP_HASHMAP *hashmap, void *origin, SCIP_Real image)
Definition: misc.c:3391
void SCIPhashmapEntrySetImageInt(SCIP_HASHMAPENTRY *entry, int image)
Definition: misc.c:3611
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:3156
SCIP_RETCODE SCIPhashmapSetImage(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:3323
int SCIPhashmapGetNElements(SCIP_HASHMAP *hashmap)
Definition: misc.c:3533
int SCIPhashmapEntryGetImageInt(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3580
void SCIPhashmapEntrySetImageReal(SCIP_HASHMAPENTRY *entry, SCIP_Real image)
Definition: misc.c:3622
int SCIPhashmapGetNEntries(SCIP_HASHMAP *hashmap)
Definition: misc.c:3541
SCIP_HASHMAPENTRY * SCIPhashmapGetEntry(SCIP_HASHMAP *hashmap, int entryidx)
Definition: misc.c:3549
void SCIPhashmapEntrySetImage(SCIP_HASHMAPENTRY *entry, void *image)
Definition: misc.c:3600
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3074
void * SCIPhashmapEntryGetOrigin(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3560
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3423
SCIP_RETCODE SCIPhashmapInsertInt(SCIP_HASHMAP *hashmap, void *origin, int image)
Definition: misc.c:3192
SCIP_Bool SCIPhashmapIsEmpty(SCIP_HASHMAP *hashmap)
Definition: misc.c:3523
SCIP_RETCODE SCIPhashmapRemoveAll(SCIP_HASHMAP *hashmap)
Definition: misc.c:3633
SCIP_Real SCIPhashmapEntryGetImageReal(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3590
SCIP_RETCODE SCIPhashmapRemove(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3439
SCIP_RETCODE SCIPhashmapSetImageInt(SCIP_HASHMAP *hashmap, void *origin, int image)
Definition: misc.c:3357
void SCIPhashsetFree(SCIP_HASHSET **hashset, BMS_BLKMEM *blkmem)
Definition: misc.c:3790
void SCIPhashsetPrintStatistics(SCIP_HASHSET *hashset, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:3933
SCIP_Bool SCIPhashsetExists(SCIP_HASHSET *hashset, void *element)
Definition: misc.c:3817
void ** SCIPhashsetGetSlots(SCIP_HASHSET *hashset)
Definition: misc.c:4008
int SCIPhashsetGetNElements(SCIP_HASHSET *hashset)
Definition: misc.c:3992
int SCIPhashsetGetNSlots(SCIP_HASHSET *hashset)
Definition: misc.c:4000
void SCIPhashsetRemoveAll(SCIP_HASHSET *hashset)
Definition: misc.c:4016
SCIP_Bool SCIPhashsetIsEmpty(SCIP_HASHSET *hashset)
Definition: misc.c:3984
SCIP_RETCODE SCIPhashsetInsert(SCIP_HASHSET *hashset, BMS_BLKMEM *blkmem, void *element)
Definition: misc.c:3800
SCIP_RETCODE SCIPhashsetCreate(SCIP_HASHSET **hashset, BMS_BLKMEM *blkmem, int size)
Definition: misc.c:3759
SCIP_RETCODE SCIPhashsetRemove(SCIP_HASHSET *hashset, void *element)
Definition: misc.c:3858
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2346
SCIP_Bool SCIPhashtableExists(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2659
#define SCIPhashTwo(a, b)
Definition: pub_misc.h:551
int SCIPhashtableGetNEntries(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2777
void SCIPhashtableClear(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2398
SCIP_RETCODE SCIPhashtableSafeInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2579
void * SCIPhashtableGetEntry(SCIP_HASHTABLE *hashtable, int entryidx)
Definition: misc.c:2785
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:2296
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition: misc.c:2608
void SCIPhashtableRemoveAll(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2755
SCIP_Real SCIPhashtableGetLoad(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2794
void SCIPhashtablePrintStatistics(SCIP_HASHTABLE *hashtable, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:2804
SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2677
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2547
SCIP_Longint SCIPhashtableGetNElements(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2767
SCIP_Longint SCIPmultihashGetNElements(SCIP_MULTIHASH *multihash)
Definition: misc.c:2231
void SCIPmultihashFree(SCIP_MULTIHASH **multihash)
Definition: misc.c:1993
SCIP_RETCODE SCIPmultihashInsert(SCIP_MULTIHASH *multihash, void *element)
Definition: misc.c:2024
SCIP_RETCODE SCIPmultihashRemove(SCIP_MULTIHASH *multihash, void *element)
Definition: misc.c:2176
void SCIPmultihashRemoveAll(SCIP_MULTIHASH *multihash)
Definition: misc.c:2210
SCIP_RETCODE SCIPmultihashSafeInsert(SCIP_MULTIHASH *multihash, void *element)
Definition: misc.c:2065
SCIP_DECL_HASHKEYEQ(SCIPhashKeyEqString)
Definition: misc.c:2842
int SCIPcalcMultihashSize(int minsize)
Definition: misc.c:1637
SCIP_Real SCIPmultihashGetLoad(SCIP_MULTIHASH *multihash)
Definition: misc.c:2241
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:1960
SCIP_DECL_HASHKEYVAL(SCIPhashKeyValString)
Definition: misc.c:2851
void * SCIPmultihashRetrieve(SCIP_MULTIHASH *multihash, void *key)
Definition: misc.c:2084
void * SCIPmultihashRetrieveNext(SCIP_MULTIHASH *multihash, SCIP_MULTIHASHLIST **multihashlist, void *key)
Definition: misc.c:2113
SCIP_Bool SCIPmultihashExists(SCIP_MULTIHASH *multihash, void *element)
Definition: misc.c:2149
void SCIPmultihashPrintStatistics(SCIP_MULTIHASH *multihash, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:2251
SCIP_DECL_HASHGETKEY(SCIPhashGetKeyStandard)
Definition: misc.c:2870
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9121
SCIP_Longint SCIPcalcBinomCoef(int n, int m)
Definition: misc.c:10272
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9373
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:9394
SCIP_Real SCIPselectSimpleValue(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom)
Definition: misc.c:9824
SCIP_Real SCIPcomputeGap(SCIP_Real eps, SCIP_Real inf, SCIP_Real primalbound, SCIP_Real dualbound)
Definition: misc.c:11202
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:9865
SCIP_Real SCIPnextafter(SCIP_Real from, SCIP_Real to)
Definition: misc.c:9364
SCIP_Real SCIPcalcMachineEpsilon(void)
Definition: misc.c:9098
unsigned int SCIPcalcFibHash(SCIP_Real v)
Definition: misc.c:10347
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:9557
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:11184
SCIP_Bool SCIPfindSimpleRational(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:9777
void SCIPswapInts(int *value1, int *value2)
Definition: misc.c:10370
void SCIPswapPointers(void **pointer1, void **pointer2)
Definition: misc.c:10396
void SCIPpermuteArray(void **array, int begin, int end, unsigned int *randseed)
Definition: misc.c:10446
void SCIPswapReals(SCIP_Real *value1, SCIP_Real *value2)
Definition: misc.c:10383
void SCIPrandomPermuteIntArray(SCIP_RANDNUMGEN *randnumgen, int *array, int begin, int end)
Definition: misc.c:10149
void SCIPrandomPermuteArray(SCIP_RANDNUMGEN *randnumgen, void **array, int begin, int end)
Definition: misc.c:10179
void SCIPpermuteIntArray(int *array, int begin, int end, unsigned int *randseed)
Definition: misc.c:10412
void ** SCIPpqueueElems(SCIP_PQUEUE *pqueue)
Definition: misc.c:1538
void SCIPpqueueDelPos(SCIP_PQUEUE *pqueue, int pos)
Definition: misc.c:1433
void SCIPpqueueClear(SCIP_PQUEUE *pqueue)
Definition: misc.c:1333
int SCIPpqueueFind(SCIP_PQUEUE *pqueue, void *elem)
Definition: misc.c:1549
void SCIPpqueueFree(SCIP_PQUEUE **pqueue)
Definition: misc.c:1322
SCIP_RETCODE SCIPpqueueInsert(SCIP_PQUEUE *pqueue, void *elem)
Definition: misc.c:1394
int SCIPpqueueNElems(SCIP_PQUEUE *pqueue)
Definition: misc.c:1527
SCIP_RETCODE SCIPpqueueCreate(SCIP_PQUEUE **pqueue, int initsize, SCIP_Real sizefac, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), SCIP_DECL_PQUEUEELEMCHGPOS((*elemchgpos)))
Definition: misc.c:1295
void * SCIPpqueueRemove(SCIP_PQUEUE *pqueue)
Definition: misc.c:1493
void * SCIPpqueueFirst(SCIP_PQUEUE *pqueue)
Definition: misc.c:1513
void SCIPintervalSetRoundingModeDownwards(void)
SCIP_ROUNDMODE SCIPintervalGetRoundingMode(void)
void SCIPintervalSetRoundingMode(SCIP_ROUNDMODE roundmode)
int SCIP_ROUNDMODE
Definition: intervalarith.h:64
SCIP_Bool SCIPintervalHasRoundingControl(void)
int SCIPqueueNElems(SCIP_QUEUE *queue)
Definition: misc.c:1247
unsigned int SCIPqueueRemoveUInt(SCIP_QUEUE *queue)
Definition: misc.c:1164
void SCIPqueueFree(SCIP_QUEUE **queue)
Definition: misc.c:1017
SCIP_RETCODE SCIPqueueInsertUInt(SCIP_QUEUE *queue, unsigned int elem)
Definition: misc.c:1105
SCIP_RETCODE SCIPqueueCreate(SCIP_QUEUE **queue, int initsize, SCIP_Real sizefac)
Definition: misc.c:993
void SCIPqueueClear(SCIP_QUEUE *queue)
Definition: misc.c:1028
SCIP_RETCODE SCIPqueueInsert(SCIP_QUEUE *queue, void *elem)
Definition: misc.c:1079
SCIP_Bool SCIPqueueIsEmpty(SCIP_QUEUE *queue)
Definition: misc.c:1234
void * SCIPqueueRemove(SCIP_QUEUE *queue)
Definition: misc.c:1130
void * SCIPqueueFirst(SCIP_QUEUE *queue)
Definition: misc.c:1198
unsigned int SCIPqueueFirstUInt(SCIP_QUEUE *queue)
Definition: misc.c:1216
SCIP_RETCODE SCIPgetRandomSubset(void **set, int nelems, void **subset, int nsubelems, unsigned int randseed)
Definition: misc.c:10480
SCIP_RETCODE SCIPrandomGetSubset(SCIP_RANDNUMGEN *randnumgen, void **set, int nelems, void **subset, int nsubelems)
Definition: misc.c:10211
SCIP_Real SCIPrandomGetReal(SCIP_RANDNUMGEN *randnumgen, SCIP_Real minrandval, SCIP_Real maxrandval)
Definition: misc.c:10130
int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
Definition: misc.c:10108
int SCIPgetRandomInt(int minrandval, int maxrandval, unsigned int *seedp)
Definition: misc.c:9991
SCIP_Real SCIPgetRandomReal(SCIP_Real minrandval, SCIP_Real maxrandval, unsigned int *seedp)
Definition: misc.c:10004
void SCIPregressionRemoveObservation(SCIP_REGRESSION *regression, SCIP_Real x, SCIP_Real y)
Definition: misc.c:349
void SCIPregressionAddObservation(SCIP_REGRESSION *regression, SCIP_Real x, SCIP_Real y)
Definition: misc.c:381
SCIP_Real SCIPregressionGetIntercept(SCIP_REGRESSION *regression)
Definition: misc.c:274
int SCIPregressionGetNObservations(SCIP_REGRESSION *regression)
Definition: misc.c:254
void SCIPregressionFree(SCIP_REGRESSION **regression)
Definition: misc.c:432
SCIP_RETCODE SCIPregressionCreate(SCIP_REGRESSION **regression)
Definition: misc.c:416
void SCIPregressionReset(SCIP_REGRESSION *regression)
Definition: misc.c:400
SCIP_Real SCIPregressionGetSlope(SCIP_REGRESSION *regression)
Definition: misc.c:264
SCIP_RETCODE SCIPactivityCreate(SCIP_RESOURCEACTIVITY **activity, SCIP_VAR *var, int duration, int demand)
Definition: misc.c:6641
int SCIPactivityGetDuration(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6696
int SCIPactivityGetEnergy(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6716
SCIP_VAR * SCIPactivityGetVar(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6686
int SCIPactivityGetDemand(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6706
void SCIPactivityFree(SCIP_RESOURCEACTIVITY **activity)
Definition: misc.c:6660
int SCIPprofileGetLatestFeasibleStart(SCIP_PROFILE *profile, int est, int lst, int duration, int demand, SCIP_Bool *infeasible)
Definition: misc.c:7289
int * SCIPprofileGetTimepoints(SCIP_PROFILE *profile)
Definition: misc.c:6827
SCIP_Bool SCIPprofileFindLeft(SCIP_PROFILE *profile, int timepoint, int *pos)
Definition: misc.c:6873
int SCIPprofileGetNTimepoints(SCIP_PROFILE *profile)
Definition: misc.c:6817
void SCIPprofileFree(SCIP_PROFILE **profile)
Definition: misc.c:6769
int SCIPprofileGetLoad(SCIP_PROFILE *profile, int pos)
Definition: misc.c:6859
int * SCIPprofileGetLoads(SCIP_PROFILE *profile)
Definition: misc.c:6837
SCIP_RETCODE SCIPprofileCreate(SCIP_PROFILE **profile, int capacity)
Definition: misc.c:6755
int SCIPprofileGetEarliestFeasibleStart(SCIP_PROFILE *profile, int est, int lst, int duration, int demand, SCIP_Bool *infeasible)
Definition: misc.c:7140
int SCIPprofileGetTime(SCIP_PROFILE *profile, int pos)
Definition: misc.c:6847
int SCIPprofileGetCapacity(SCIP_PROFILE *profile)
Definition: misc.c:6807
SCIP_RETCODE SCIPprofileDeleteCore(SCIP_PROFILE *profile, int left, int right, int demand)
Definition: misc.c:7050
SCIP_RETCODE SCIPprofileInsertCore(SCIP_PROFILE *profile, int left, int right, int demand, int *pos, SCIP_Bool *infeasible)
Definition: misc.c:7020
void SCIPprofilePrint(SCIP_PROFILE *profile, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: misc.c:6785
SCIP_Real SCIPnormalCDF(SCIP_Real mean, SCIP_Real variance, SCIP_Real value)
Definition: misc.c:196
SCIP_Real SCIPcomputeTwoSampleTTestValue(SCIP_Real meanx, SCIP_Real meany, SCIP_Real variancex, SCIP_Real variancey, SCIP_Real countx, SCIP_Real county)
Definition: misc.c:123
SCIP_Real SCIPnormalGetCriticalValue(SCIP_CONFIDENCELEVEL clevel)
Definition: misc.c:183
SCIP_Real SCIPstudentTGetCriticalValue(SCIP_CONFIDENCELEVEL clevel, int df)
Definition: misc.c:106
SCIP_Real SCIPerf(SCIP_Real x)
Definition: misc.c:156
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:6077
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:5538
SCIP_DECL_SORTPTRCOMP(SCIPsortCompInt)
Definition: misc.c:5480
void SCIPsortedvecInsertIntInt(int *intarray1, int *intarray2, int keyval, int field1val, int *len, int *pos)
void SCIPsortDownInd(int *indarray, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
SCIP_DECL_SORTINDCOMP(SCIPsortArgsortInt)
Definition: misc.c:5501
int SCIPsparseSolGetNVars(SCIP_SPARSESOL *sparsesol)
Definition: misc.c:839
SCIP_Longint * SCIPsparseSolGetLbs(SCIP_SPARSESOL *sparsesol)
Definition: misc.c:849
void SCIPsparseSolGetFirstSol(SCIP_SPARSESOL *sparsesol, SCIP_Longint *sol, int nvars)
Definition: misc.c:869
SCIP_RETCODE SCIPsparseSolCreate(SCIP_SPARSESOL **sparsesol, SCIP_VAR **vars, int nvars, SCIP_Bool cleared)
Definition: misc.c:763
SCIP_Longint * SCIPsparseSolGetUbs(SCIP_SPARSESOL *sparsesol)
Definition: misc.c:859
void SCIPsparseSolFree(SCIP_SPARSESOL **sparsesol)
Definition: misc.c:815
SCIP_Bool SCIPsparseSolGetNextSol(SCIP_SPARSESOL *sparsesol, SCIP_Longint *sol, int nvars)
Definition: misc.c:892
SCIP_VAR ** SCIPsparseSolGetVars(SCIP_SPARSESOL *sparsesol)
Definition: misc.c:829
SCIP_Bool SCIPstrToIntValue(const char *str, int *value, char **endptr)
Definition: misc.c:10946
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10877
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:10977
void SCIPescapeString(char *t, int bufsize, const char *s)
Definition: misc.c:10832
void SCIPstrCopySection(const char *str, char startchar, char endchar, char *token, int size, char **endptr)
Definition: misc.c:11007
void SCIPprintSysError(const char *message)
Definition: misc.c:10769
SCIP_Bool SCIPstrAtStart(const char *s, const char *t, size_t tlen)
Definition: misc.c:11386
SCIP_RETCODE SCIPskipSpace(char **s)
Definition: misc.c:10866
int SCIPstrncpy(char *t, const char *s, int size)
Definition: misc.c:10919
char * SCIPstrtok(char *s, const char *delim, char **ptrptr)
Definition: misc.c:10818
int SCIPmemccpy(char *dest, const char *src, char stop, unsigned int cnt)
Definition: misc.c:10744
static SCIP_RETCODE optimize(SCIP *scip, SCIP_SOL *worksol, SCIP_VAR **vars, int *blockstart, int *blockend, int nblocks, OPTTYPE opttype, SCIP_Real *activities, int nrows, SCIP_Bool *improvement, SCIP_Bool *varboundserr, SCIP_HEURDATA *heurdata)
Definition: heur_twoopt.c:936
interval arithmetics for provable bounds
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:462
#define BMSfreeMemory(ptr)
Definition: memory.h:145
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:465
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:451
#define BMSreallocMemoryArray(ptr, num)
Definition: memory.h:127
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:468
#define BMSduplicateMemoryArray(ptr, source, num)
Definition: memory.h:143
#define BMSclearMemory(ptr)
Definition: memory.h:129
#define BMSallocMemoryArray(ptr, num)
Definition: memory.h:123
#define BMSfreeMemoryArray(ptr)
Definition: memory.h:147
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition: memory.h:454
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:134
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:467
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:458
#define BMSmoveMemoryArray(ptr, source, num)
Definition: memory.h:138
#define BMSallocClearBlockMemoryArray(mem, ptr, num)
Definition: memory.h:455
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
#define BMSallocClearMemoryArray(ptr, num)
Definition: memory.h:125
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:437
#define BMSfreeMemoryArrayNull(ptr)
Definition: memory.h:148
#define BMSallocMemory(ptr)
Definition: memory.h:118
void SCIPmessagePrintError(const char *formatstr,...)
Definition: message.c:791
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:618
void SCIPmessagePrintInfo(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:594
SCIP_RETCODE SCIPrealarrayExtend(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
Definition: misc.c:4088
#define GMLNODEHEIGTH
Definition: misc.c:488
#define ELEM_DISTANCE(pos)
Definition: misc.c:3654
SCIP_Bool SCIPboolarrayGetVal(SCIP_BOOLARRAY *boolarray, int idx)
Definition: misc.c:5013
static void incrementalStatsUpdate(SCIP_Real value, SCIP_Real *meanptr, SCIP_Real *sumvarptr, int nobservations, SCIP_Bool add)
Definition: misc.c:323
static SCIP_RETCODE doProfileCreate(SCIP_PROFILE **profile, int capacity)
Definition: misc.c:6733
static int primetable[]
Definition: misc.c:1573
SCIP_RETCODE SCIPboolarrayFree(SCIP_BOOLARRAY **boolarray)
Definition: misc.c:4811
SCIP_RETCODE SCIPboolarrayCopy(SCIP_BOOLARRAY **boolarray, BMS_BLKMEM *blkmem, SCIP_BOOLARRAY *sourceboolarray)
Definition: misc.c:4787
static void pqueueElemChgPos(SCIP_PQUEUE *pqueue, void *elem, int oldpos, int newpos)
Definition: misc.c:1344
#define GMLNODEBORDERCOLOR
Definition: misc.c:493
#define SCIP_RAND_MAX
Definition: misc.c:9934
static void multihashlistFree(SCIP_MULTIHASHLIST **multihashlist, BMS_BLKMEM *blkmem)
Definition: misc.c:1673
static SCIP_RETCODE multihashlistAppend(SCIP_MULTIHASHLIST **multihashlist, BMS_BLKMEM *blkmem, void *element)
Definition: misc.c:1651
static SCIP_RETCODE hashtableCheckLoad(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2494
int SCIPptrarrayGetMaxIdx(SCIP_PTRARRAY *ptrarray)
Definition: misc.c:5465
#define DEFAULT_SEED
Definition: misc.c:10015
SCIP_RETCODE SCIPrealarraySetVal(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, SCIP_Real val)
Definition: misc.c:4295
SCIP_RETCODE SCIPintarraySetVal(SCIP_INTARRAY *intarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, int val)
Definition: misc.c:4666
static SCIP_Bool multihashlistRemove(SCIP_MULTIHASHLIST **multihashlist, BMS_BLKMEM *blkmem, void *element)
Definition: misc.c:1811
static const int primetablesize
Definition: misc.c:1625
#define SCIP_MULTIHASH_MAXSIZE
Definition: misc.c:1838
SCIP_RETCODE SCIPintarrayFree(SCIP_INTARRAY **intarray)
Definition: misc.c:4445
#define DEFAULT_MWC
Definition: misc.c:10017
#define PQ_RIGHTCHILD(p)
Definition: misc.c:1273
static SCIP_RETCODE queueResize(SCIP_QUEUE *queue, int minsize)
Definition: misc.c:974
static SCIP_RETCODE queueCheckSize(SCIP_QUEUE *queue)
Definition: misc.c:1040
static int profileFindFeasibleStart(SCIP_PROFILE *profile, int pos, int lst, int duration, int demand, SCIP_Bool *infeasible)
Definition: misc.c:7082
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:8321
#define DEFAULT_XOR
Definition: misc.c:10016
void SCIPdisjointsetFree(SCIP_DISJOINTSET **djset, BMS_BLKMEM *blkmem)
Definition: misc.c:11347
static void btnodeFreeLeaf(SCIP_BT *tree, SCIP_BTNODE **node)
Definition: misc.c:8700
static void depthFirstSearch(SCIP_DIGRAPH *digraph, int startnode, SCIP_Bool *visited, int *dfsstack, int *stackadjvisited, int *dfsnodes, int *ndfsnodes)
Definition: misc.c:7854
int SCIPptrarrayGetMinIdx(SCIP_PTRARRAY *ptrarray)
Definition: misc.c:5455
static SCIP_RETCODE profileUpdate(SCIP_PROFILE *profile, int left, int right, int demand, int *pos, SCIP_Bool *infeasible)
Definition: misc.c:6960
static SCIP_RETCODE ensureSuccessorsSize(SCIP_DIGRAPH *digraph, int idx, int newsize)
Definition: misc.c:7615
static SCIP_RETCODE profileInsertTimepoint(SCIP_PROFILE *profile, int timepoint, int *pos)
Definition: misc.c:6919
SCIP_RETCODE SCIPptrarrayExtend(SCIP_PTRARRAY *ptrarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
Definition: misc.c:5180
SCIP_RETCODE SCIPboolarrayExtend(SCIP_BOOLARRAY *boolarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
Definition: misc.c:4825
SCIP_RETCODE SCIPptrarrayCopy(SCIP_PTRARRAY **ptrarray, BMS_BLKMEM *blkmem, SCIP_PTRARRAY *sourceptrarray)
Definition: misc.c:5143
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:1728
static SCIP_RETCODE hashtableInsert(SCIP_HASHTABLE *hashtable, void *element, void *key, uint32_t hashval, SCIP_Bool override)
Definition: misc.c:2410
static void btPrintSubtree(SCIP_BTNODE *node, FILE *file, int *nnodes)
Definition: misc.c:8993
int SCIPboolarrayGetMaxIdx(SCIP_BOOLARRAY *boolarray)
Definition: misc.c:5112
static const SCIP_Real studentt_quartilesabove[]
Definition: misc.c:98
void SCIPrandomFree(SCIP_RANDNUMGEN **randnumgen, BMS_BLKMEM *blkmem)
Definition: misc.c:10092
static int getRand(unsigned int *seedp)
Definition: misc.c:9938
SCIP_RETCODE SCIPdisjointsetCreate(SCIP_DISJOINTSET **djset, BMS_BLKMEM *blkmem, int ncomponents)
Definition: misc.c:11229
SCIP_RETCODE SCIPrandomCreate(SCIP_RANDNUMGEN **randnumgen, BMS_BLKMEM *blkmem, unsigned int initialseed)
Definition: misc.c:10076
SCIP_RETCODE SCIPintarrayCopy(SCIP_INTARRAY **intarray, BMS_BLKMEM *blkmem, SCIP_INTARRAY *sourceintarray)
Definition: misc.c:4422
SCIP_RETCODE SCIPptrarrayClear(SCIP_PTRARRAY *ptrarray)
Definition: misc.c:5335
static SCIP_RETCODE hashmapInsert(SCIP_HASHMAP *hashmap, void *origin, SCIP_HASHMAPIMAGE image, uint32_t hashval, SCIP_Bool override)
Definition: misc.c:2902
int SCIPrealarrayGetMaxIdx(SCIP_REALARRAY *realarray)
Definition: misc.c:4392
SCIP_RETCODE SCIPdigraphCreate(SCIP_DIGRAPH **digraph, BMS_BLKMEM *blkmem, int nnodes)
Definition: misc.c:7377
static uint32_t hashSetDesiredPos(SCIP_HASHSET *hashset, void *element)
Definition: misc.c:3658
int SCIPintarrayGetMaxIdx(SCIP_INTARRAY *intarray)
Definition: misc.c:4756
SCIP_RETCODE SCIPintarrayCreate(SCIP_INTARRAY **intarray, BMS_BLKMEM *blkmem)
Definition: misc.c:4402
static SCIP_RETCODE hashsetCheckLoad(SCIP_HASHSET *hashset, BMS_BLKMEM *blkmem)
Definition: misc.c:3718
static void regressionRecompute(SCIP_REGRESSION *regression)
Definition: misc.c:285
#define STARTSUCCESSORSSIZE
Definition: misc.c:7611
SCIP_Real SCIPrealarrayGetVal(SCIP_REALARRAY *realarray, int idx)
Definition: misc.c:4274
SCIP_RETCODE SCIPptrarrayFree(SCIP_PTRARRAY **ptrarray)
Definition: misc.c:5166
SCIP_RETCODE SCIPintarrayClear(SCIP_INTARRAY *intarray)
Definition: misc.c:4614
#define GMLNODEWIDTH
Definition: misc.c:487
#define SCIP_MULTIHASH_RESIZE_PERCENTAGE
Definition: misc.c:1839
SCIP_RETCODE SCIPrealarrayIncVal(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, SCIP_Real incval)
Definition: misc.c:4364
int SCIPrealarrayGetMinIdx(SCIP_REALARRAY *realarray)
Definition: misc.c:4382
SCIP_RETCODE SCIPrealarrayCreate(SCIP_REALARRAY **realarray, BMS_BLKMEM *blkmem)
Definition: misc.c:4030
#define GMLFONTSIZE
Definition: misc.c:489
static const int nscalars
Definition: misc.c:9552
SCIP_RETCODE SCIPrealarrayClear(SCIP_REALARRAY *realarray)
Definition: misc.c:4243
int SCIPboolarrayGetMinIdx(SCIP_BOOLARRAY *boolarray)
Definition: misc.c:5102
static int calcGrowSize(int initsize, SCIP_Real growfac, int num)
Definition: misc.c:441
#define GMLNODETYPE
Definition: misc.c:490
static const SCIP_Real studentt_quartiles[]
Definition: misc.c:77
static const int studentt_maxdf
Definition: misc.c:103
#define PQ_PARENT(q)
Definition: misc.c:1271
static uint32_t randomGetRand(SCIP_RANDNUMGEN *randnumgen)
Definition: misc.c:10053
static uint32_t hashvalue(uint64_t input)
Definition: misc.c:1629
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:7933
static void queueCheckMarker(SCIP_QUEUE *queue)
Definition: misc.c:1065
static int profileFindDownFeasibleStart(SCIP_PROFILE *profile, int pos, int ect, int duration, int demand, SCIP_Bool *infeasible)
Definition: misc.c:7232
int SCIPintarrayGetMinIdx(SCIP_INTARRAY *intarray)
Definition: misc.c:4746
static SCIP_RETCODE pqueueResize(SCIP_PQUEUE *pqueue, int minsize)
Definition: misc.c:1278
SCIP_RETCODE SCIPrealarrayCopy(SCIP_REALARRAY **realarray, BMS_BLKMEM *blkmem, SCIP_REALARRAY *sourcerealarray)
Definition: misc.c:4050
static SCIP_RETCODE hashmapCheckLoad(SCIP_HASHMAP *hashmap)
Definition: misc.c:3023
void * SCIPptrarrayGetVal(SCIP_PTRARRAY *ptrarray, int idx)
Definition: misc.c:5366
void SCIPrandomSetSeed(SCIP_RANDNUMGEN *randnumgen, unsigned int initseed)
Definition: misc.c:10022
#define PQ_LEFTCHILD(p)
Definition: misc.c:1272
SCIP_RETCODE SCIPintarrayExtend(SCIP_INTARRAY *intarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
Definition: misc.c:4459
#define SCIP_MULTIHASH_GROW_FACTOR
Definition: misc.c:1840
static SCIP_RETCODE multihashResize(SCIP_MULTIHASH *multihash)
Definition: misc.c:1844
SCIP_RETCODE SCIPboolarrayCreate(SCIP_BOOLARRAY **boolarray, BMS_BLKMEM *blkmem)
Definition: misc.c:4767
static SCIP_RETCODE ensureProfileSize(SCIP_PROFILE *profile, int neededsize)
Definition: misc.c:6896
static SCIP_Bool isIntegralScalar(SCIP_Real val, SCIP_Real scalar, SCIP_Real mindelta, SCIP_Real maxdelta)
Definition: misc.c:9529
#define GMLEDGECOLOR
Definition: misc.c:492
SCIP_Real SCIPnegateReal(SCIP_Real x)
Definition: misc.c:10358
static SCIP_RETCODE btnodeCreateEmpty(SCIP_BT *tree, SCIP_BTNODE **node)
Definition: misc.c:8661
#define DEFAULT_CST
Definition: misc.c:10018
SCIP_RETCODE SCIPboolarrayClear(SCIP_BOOLARRAY *boolarray)
Definition: misc.c:4982
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:1778
SCIP_RETCODE SCIPintarrayIncVal(SCIP_INTARRAY *intarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, int incval)
Definition: misc.c:4734
int SCIPintarrayGetVal(SCIP_INTARRAY *intarray, int idx)
Definition: misc.c:4645
static SCIP_Bool hashmapLookup(SCIP_HASHMAP *hashmap, void *origin, uint32_t *pos)
Definition: misc.c:2978
static const SCIP_Real scalars[]
Definition: misc.c:9551
SCIP_RETCODE SCIPdigraphCopy(SCIP_DIGRAPH **targetdigraph, SCIP_DIGRAPH *sourcedigraph, BMS_BLKMEM *targetblkmem)
Definition: misc.c:7454
#define GMLNODEFILLCOLOR
Definition: misc.c:491
SCIP_RETCODE SCIPptrarrayCreate(SCIP_PTRARRAY **ptrarray, BMS_BLKMEM *blkmem)
Definition: misc.c:5123
SCIP_RETCODE SCIPptrarraySetVal(SCIP_PTRARRAY *ptrarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, void *val)
Definition: misc.c:5387
static const SCIP_Real simplednoms[]
Definition: misc.c:9388
static SCIP_Real getRandomReal(SCIP_Real minrandval, SCIP_Real maxrandval, unsigned int *seedp)
Definition: misc.c:9969
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:1697
SCIP_RETCODE SCIPrealarrayFree(SCIP_REALARRAY **realarray)
Definition: misc.c:4074
static void hashsetInsert(SCIP_HASHSET *hashset, void *element)
Definition: misc.c:3667
SCIP_RETCODE SCIPboolarraySetVal(SCIP_BOOLARRAY *boolarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, SCIP_Bool val)
Definition: misc.c:5034
static int getRandomInt(int minrandval, int maxrandval, unsigned int *seedp)
Definition: misc.c:9949
internal miscellaneous methods
#define M_SQRT2
Definition: misc_rowprep.c:59
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
BMS_BLKMEM * blkmem
Definition: struct_misc.h:181
SCIP_Bool * vals
Definition: struct_misc.h:182
SCIP_BTNODE * parent
Definition: struct_misc.h:240
void * dataptr
Definition: struct_misc.h:243
SCIP_BTNODE * left
Definition: struct_misc.h:241
SCIP_BTNODE * right
Definition: struct_misc.h:242
SCIP_BTNODE * root
Definition: struct_misc.h:249
BMS_BLKMEM * blkmem
Definition: struct_misc.h:250
SCIP_Bool articulationscheck
Definition: struct_misc.h:234
int ** successors
Definition: struct_misc.h:222
void ** nodedata
Definition: struct_misc.h:224
int * successorssize
Definition: struct_misc.h:225
void *** arcdata
Definition: struct_misc.h:223
int componentstartsize
Definition: struct_misc.h:231
int * articulations
Definition: struct_misc.h:229
int * componentstarts
Definition: struct_misc.h:228
int narticulations
Definition: struct_misc.h:233
BMS_BLKMEM * blkmem
Definition: struct_misc.h:221
int * components
Definition: struct_misc.h:227
int * nsuccessors
Definition: struct_misc.h:226
SCIP_HASHMAPIMAGE image
Definition: struct_misc.h:133
uint32_t nelements
Definition: struct_misc.h:144
BMS_BLKMEM * blkmem
Definition: struct_misc.h:139
SCIP_HASHMAPTYPE hashmaptype
Definition: struct_misc.h:145
uint32_t mask
Definition: struct_misc.h:143
uint32_t shift
Definition: struct_misc.h:142
SCIP_HASHMAPENTRY * slots
Definition: struct_misc.h:140
uint32_t * hashes
Definition: struct_misc.h:141
uint32_t nelements
Definition: struct_misc.h:153
void ** slots
Definition: struct_misc.h:151
uint32_t shift
Definition: struct_misc.h:152
void * userptr
Definition: struct_misc.h:95
uint32_t nelements
Definition: struct_misc.h:100
uint32_t shift
Definition: struct_misc.h:98
uint32_t mask
Definition: struct_misc.h:99
BMS_BLKMEM * blkmem
Definition: struct_misc.h:94
void ** slots
Definition: struct_misc.h:96
uint32_t * hashes
Definition: struct_misc.h:97
BMS_BLKMEM * blkmem
Definition: struct_misc.h:170
SCIP_MULTIHASHLIST * next
Definition: struct_misc.h:107
SCIP_MULTIHASHLIST ** lists
Definition: struct_misc.h:117
BMS_BLKMEM * blkmem
Definition: struct_misc.h:116
SCIP_Longint nelements
Definition: struct_misc.h:120
void ** slots
Definition: struct_misc.h:83
SCIP_Real sizefac
Definition: struct_misc.h:80
int * timepoints
Definition: struct_misc.h:211
void ** vals
Definition: struct_misc.h:193
BMS_BLKMEM * blkmem
Definition: struct_misc.h:192
SCIP_Real sizefac
Definition: struct_misc.h:62
int firstused
Definition: struct_misc.h:65
SCIP_QUEUEELEMENT * slots
Definition: struct_misc.h:63
int firstfree
Definition: struct_misc.h:64
uint32_t xor_seed
Definition: struct_misc.h:271
uint32_t cst_seed
Definition: struct_misc.h:273
uint32_t mwc_seed
Definition: struct_misc.h:272
SCIP_Real * vals
Definition: struct_misc.h:160
BMS_BLKMEM * blkmem
Definition: struct_misc.h:159
SCIP_Real slope
Definition: struct_misc.h:257
SCIP_Real meany
Definition: struct_misc.h:259
SCIP_Real meanx
Definition: struct_misc.h:258
SCIP_Real variancesumx
Definition: struct_misc.h:261
SCIP_Real corrcoef
Definition: struct_misc.h:263
SCIP_Real sumxy
Definition: struct_misc.h:260
SCIP_Real intercept
Definition: struct_misc.h:256
SCIP_Real variancesumy
Definition: struct_misc.h:262
SCIP_Longint * lbvalues
Definition: struct_misc.h:49
SCIP_VAR ** vars
Definition: struct_misc.h:48
SCIP_Longint * ubvalues
Definition: struct_misc.h:50
miscellaneous datastructures
Definition: heur_padm.c:135
@ SCIP_HASHMAPTYPE_REAL
Definition: type_misc.h:60
@ SCIP_HASHMAPTYPE_POINTER
Definition: type_misc.h:59
@ SCIP_HASHMAPTYPE_UNKNOWN
Definition: type_misc.h:58
@ SCIP_HASHMAPTYPE_INT
Definition: type_misc.h:61
#define SCIP_DECL_PQUEUEELEMCHGPOS(x)
Definition: type_misc.h:208
#define SCIP_DECL_NEWTONEVAL(x)
Definition: type_misc.h:205
enum SCIP_Confidencelevel SCIP_CONFIDENCELEVEL
Definition: type_misc.h:53
@ SCIP_INVALIDDATA
Definition: type_retcode.h:52
@ SCIP_KEYALREADYEXISTING
Definition: type_retcode.h:58
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
unsigned int uinteger
Definition: struct_misc.h:56