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