Scippy

SCIP

Solving Constraint Integer Programs

misc.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file misc.c
26 * @ingroup OTHER_CFILES
27 * @brief miscellaneous methods
28 * @author Tobias Achterberg
29 * @author Gerald Gamrath
30 * @author Stefan Heinz
31 * @author Michael Winkler
32 * @author Kati Wolter
33 * @author Gregor Hendel
34 */
35
36/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
37
38#define _USE_MATH_DEFINES /* to get M_SQRT2 on Windows */ /*lint !750 */
39
40#include <assert.h>
41#include <string.h>
42#include <stdarg.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <errno.h>
46#include <ctype.h>
47#include <math.h>
48#ifndef _MSC_VER
49#include <strings.h>
50#endif
51
52#include "scip/def.h"
53#include "scip/pub_message.h"
54#include "scip/misc.h"
55#include "scip/intervalarith.h"
56#include "scip/pub_misc.h"
57
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].image = image;
2943 hashmap->hashes[pos] = hashval;
2944 return SCIP_OKAY;
2945 }
2946 else
2947 {
2949 }
2950 }
2951
2952 /* otherwise check if the current element at this position is closer to its hashvalue */
2953 distance = ELEM_DISTANCE(pos);
2954 if( distance < elemdistance )
2955 {
2957 uint32_t tmphash;
2958
2959 /* if this is the case we insert the new element here and find a new position for the old one */
2960 elemdistance = distance;
2961 tmphash = hashval;
2962 hashval = hashmap->hashes[pos];
2963 hashmap->hashes[pos] = tmphash;
2964 SCIPswapPointers(&hashmap->slots[pos].origin, &origin);
2965 tmp = image;
2966 image = hashmap->slots[pos].image;
2967 hashmap->slots[pos].image = tmp;
2968 }
2969
2970 /* continue until we have found an empty position */
2971 pos = (pos + 1) & hashmap->mask;
2972 ++elemdistance;
2973 }
2974}
2975
2976/** lookup origin in the hashmap. If element is found returns true and the position of the element,
2977 * otherwise returns FALSE.
2978 */
2979static
2981 SCIP_HASHMAP* hashmap, /**< hash table */
2982 void* origin, /**< origin to lookup */
2983 uint32_t* pos /**< pointer to store position of element, if exists */
2984 )
2985{
2986 uint32_t hashval;
2987 uint32_t elemdistance;
2988
2989 assert(hashmap != NULL);
2990 assert(hashmap->slots != NULL);
2991 assert(hashmap->hashes != NULL);
2992 assert(hashmap->mask > 0);
2993
2994 /* get the hash value */
2995 hashval = hashvalue((size_t)origin);
2996 assert(hashval != 0);
2997
2998 *pos = hashval>>(hashmap->shift);
2999 elemdistance = 0;
3000
3001 while( TRUE ) /*lint !e716*/
3002 {
3003 uint32_t distance;
3004
3005 /* slots is empty so element cannot be contained */
3006 if( hashmap->hashes[*pos] == 0 )
3007 return FALSE;
3008
3009 distance = ELEM_DISTANCE(*pos);
3010 /* element can not be contained since otherwise we would have swapped it with this one during insert */
3011 if( elemdistance > distance )
3012 return FALSE;
3013
3014 /* found element */
3015 if( hashmap->hashes[*pos] == hashval && hashmap->slots[*pos].origin == origin )
3016 return TRUE;
3017
3018 *pos = (*pos + 1) & hashmap->mask;
3019 ++elemdistance;
3020 }
3021}
3022
3023/** check if the load factor of the hashmap is too high and rebuild if necessary */
3024static
3026 SCIP_HASHMAP* hashmap /**< hash table */
3027 )
3028{
3029 assert(hashmap != NULL);
3030 assert(hashmap->shift < 32);
3031
3032 /* use integer arithmetic to approximately check if load factor is above 90% */
3033 if( ((((uint64_t)hashmap->nelements)<<10)>>(32-hashmap->shift) > 921) )
3034 {
3035 SCIP_HASHMAPENTRY* slots;
3036 uint32_t* hashes;
3037 uint32_t nslots;
3038 uint32_t newnslots;
3039 uint32_t i;
3040
3041 /* calculate new size (always power of two) */
3042 nslots = hashmap->mask + 1;
3043 --hashmap->shift;
3044 newnslots = 2*nslots;
3045 hashmap->mask = newnslots-1;
3046
3047 /* reallocate array */
3048 SCIP_ALLOC( BMSallocBlockMemoryArray(hashmap->blkmem, &slots, newnslots) );
3049 SCIP_ALLOC( BMSallocClearBlockMemoryArray(hashmap->blkmem, &hashes, newnslots) );
3050
3051 SCIPswapPointers((void**) &slots, (void**) &hashmap->slots);
3052 SCIPswapPointers((void**) &hashes, (void**) &hashmap->hashes);
3053 hashmap->nelements = 0;
3054
3055 /* reinsert all elements */
3056 for( i = 0; i < nslots; ++i )
3057 {
3058 /* using SCIP_CALL_ABORT since there are no allocations or duplicates
3059 * and thus no bad return codes when inserting the elements
3060 */
3061 if( hashes[i] != 0 )
3062 {
3063 SCIP_CALL_ABORT( hashmapInsert(hashmap, slots[i].origin, slots[i].image, hashes[i], FALSE) );
3064 }
3065 }
3066
3067 /* free old arrays */
3068 BMSfreeBlockMemoryArray(hashmap->blkmem, &hashes, nslots);
3069 BMSfreeBlockMemoryArray(hashmap->blkmem, &slots, nslots);
3070 }
3071
3072 return SCIP_OKAY;
3073}
3074
3075/** creates a hash map mapping pointers to pointers */
3077 SCIP_HASHMAP** hashmap, /**< pointer to store the created hash map */
3078 BMS_BLKMEM* blkmem, /**< block memory used to store hash map entries */
3079 int mapsize /**< size of the hash map */
3080 )
3081{
3082 uint32_t nslots;
3083
3084 assert(hashmap != NULL);
3085 assert(mapsize >= 0);
3086 assert(blkmem != NULL);
3087
3088 SCIP_ALLOC( BMSallocBlockMemory(blkmem, hashmap) );
3089
3090 /* dont create too small hashtables, i.e. at least size 32, and increase
3091 * the given size by divinding it by 0.9, since then no rebuilding will
3092 * be necessary if the given number of elements are inserted. Finally round
3093 * to the next power of two.
3094 */
3095 (*hashmap)->shift = 32;
3096 (*hashmap)->shift -= (unsigned int)ceil(log(MAX(32, mapsize / 0.9)) / log(2.0));
3097 nslots = 1u << (32 - (*hashmap)->shift);
3098 (*hashmap)->mask = nslots - 1;
3099 (*hashmap)->blkmem = blkmem;
3100 (*hashmap)->nelements = 0;
3101 (*hashmap)->hashmaptype = SCIP_HASHMAPTYPE_UNKNOWN;
3102
3103 SCIP_ALLOC( BMSallocBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->slots, nslots) );
3104 SCIP_ALLOC( BMSallocClearBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->hashes, nslots) );
3105
3106 return SCIP_OKAY;
3107}
3108
3109/** frees the hash map */
3111 SCIP_HASHMAP** hashmap /**< pointer to the hash map */
3112 )
3113{
3114 uint32_t nslots;
3115
3116 assert(hashmap != NULL);
3117 assert(*hashmap != NULL);
3118
3119 nslots = (*hashmap)->mask + 1;
3120#ifdef SCIP_DEBUG
3121 {
3122 uint32_t maxprobelen = 0;
3123 uint64_t probelensum = 0;
3124 uint32_t i;
3125
3126 assert(hashmap != NULL);
3127
3128 for( i = 0; i < nslots; ++i )
3129 {
3130 if( (*hashmap)->hashes[i] != 0 )
3131 {
3132 uint32_t probelen = ((i + (*hashmap)->mask + 1 - ((*hashmap)->hashes[i]>>((*hashmap)->shift))) & (*hashmap)->mask) + 1;
3133 probelensum += probelen;
3134 maxprobelen = MAX(probelen, maxprobelen);
3135 }
3136 }
3137
3138 SCIPdebugMessage("%u hash map entries, used %u/%u slots (%.1f%%)",
3139 (unsigned int)(*hashmap)->nelements, (unsigned int)(*hashmap)->nelements, (unsigned int)nslots,
3140 100.0*(SCIP_Real)(*hashmap)->nelements/(SCIP_Real)(nslots));
3141 if( (*hashmap)->nelements > 0 )
3142 SCIPdebugPrintf(", avg. probe length is %.1f, max. probe length is %u",
3143 (SCIP_Real)(probelensum)/(SCIP_Real)(*hashmap)->nelements, (unsigned int)maxprobelen);
3144 SCIPdebugPrintf("\n");
3145 }
3146#endif
3147
3148 /* free main hash map data structure */
3149 BMSfreeBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->hashes, nslots);
3150 BMSfreeBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->slots, nslots);
3151 BMSfreeBlockMemory((*hashmap)->blkmem, hashmap);
3152}
3153
3154/** inserts new origin->image pair in hash map
3155 *
3156 * @note multiple insertion of same element is checked and results in an error
3157 */
3159 SCIP_HASHMAP* hashmap, /**< hash map */
3160 void* origin, /**< origin to set image for */
3161 void* image /**< new image for origin */
3162 )
3163{
3164 uint32_t hashval;
3166
3167 assert(hashmap != NULL);
3168 assert(hashmap->slots != NULL);
3169 assert(hashmap->hashes != NULL);
3170 assert(hashmap->mask > 0);
3172
3173#ifndef NDEBUG
3174 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3176#endif
3177
3178 SCIP_CALL( hashmapCheckLoad(hashmap) );
3179
3180 /* get the hash value */
3181 hashval = hashvalue((size_t)origin);
3182
3183 /* append origin->image pair to hash map */
3184 img.ptr = image;
3185 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, FALSE) );
3186
3187 return SCIP_OKAY;
3188}
3189
3190/** inserts new origin->image pair in hash map
3191 *
3192 * @note multiple insertion of same element is checked and results in an error
3193 */
3195 SCIP_HASHMAP* hashmap, /**< hash map */
3196 void* origin, /**< origin to set image for */
3197 int image /**< new image for origin */
3198 )
3199{
3200 uint32_t hashval;
3202
3203 assert(hashmap != NULL);
3204 assert(hashmap->slots != NULL);
3205 assert(hashmap->hashes != NULL);
3206 assert(hashmap->mask > 0);
3207 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_INT);
3208
3209#ifndef NDEBUG
3210 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3212#endif
3213
3214 SCIP_CALL( hashmapCheckLoad(hashmap) );
3215
3216 /* get the hash value */
3217 hashval = hashvalue((size_t)origin);
3218
3219 /* append origin->image pair to hash map */
3220 img.integer = image;
3221 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, FALSE) );
3222
3223 return SCIP_OKAY;
3224}
3225
3226/** inserts new origin->image pair in hash map
3227 *
3228 * @note multiple insertion of same element is checked and results in an error
3229 */
3231 SCIP_HASHMAP* hashmap, /**< hash map */
3232 void* origin, /**< origin to set image for */
3233 SCIP_Real image /**< new image for origin */
3234 )
3235{
3236 uint32_t hashval;
3238
3239 assert(hashmap != NULL);
3240 assert(hashmap->slots != NULL);
3241 assert(hashmap->hashes != NULL);
3242 assert(hashmap->mask > 0);
3243 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_REAL);
3244
3245#ifndef NDEBUG
3246 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3248#endif
3249
3250 SCIP_CALL( hashmapCheckLoad(hashmap) );
3251
3252 /* get the hash value */
3253 hashval = hashvalue((size_t)origin);
3254
3255 /* append origin->image pair to hash map */
3256 img.real = image;
3257 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, FALSE) );
3258
3259 return SCIP_OKAY;
3260}
3261
3262/** retrieves image of given origin from the hash map, or NULL if no image exists */
3264 SCIP_HASHMAP* hashmap, /**< hash map */
3265 void* origin /**< origin to retrieve image for */
3266 )
3267{
3268 uint32_t pos;
3269
3270 assert(hashmap != NULL);
3271 assert(hashmap->slots != NULL);
3272 assert(hashmap->hashes != NULL);
3273 assert(hashmap->mask > 0);
3275
3276 if( hashmapLookup(hashmap, origin, &pos) )
3277 return hashmap->slots[pos].image.ptr;
3278
3279 return NULL;
3280}
3281
3282/** retrieves image of given origin from the hash map, or INT_MAX if no image exists */
3284 SCIP_HASHMAP* hashmap, /**< hash map */
3285 void* origin /**< origin to retrieve image for */
3286 )
3287{
3288 uint32_t pos;
3289
3290 assert(hashmap != NULL);
3291 assert(hashmap->slots != NULL);
3292 assert(hashmap->hashes != NULL);
3293 assert(hashmap->mask > 0);
3294 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_INT);
3295
3296 if( hashmapLookup(hashmap, origin, &pos) )
3297 return hashmap->slots[pos].image.integer;
3298
3299 return INT_MAX;
3300}
3301
3302/** retrieves image of given origin from the hash map, or SCIP_INVALID if no image exists */
3304 SCIP_HASHMAP* hashmap, /**< hash map */
3305 void* origin /**< origin to retrieve image for */
3306 )
3307{
3308 uint32_t pos;
3309
3310 assert(hashmap != NULL);
3311 assert(hashmap->slots != NULL);
3312 assert(hashmap->hashes != NULL);
3313 assert(hashmap->mask > 0);
3314 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_REAL);
3315
3316 if( hashmapLookup(hashmap, origin, &pos) )
3317 return hashmap->slots[pos].image.real;
3318
3319 return SCIP_INVALID;
3320}
3321
3322/** sets image for given origin in the hash map, either by modifying existing origin->image pair
3323 * or by appending a new origin->image pair
3324 */
3326 SCIP_HASHMAP* hashmap, /**< hash map */
3327 void* origin, /**< origin to set image for */
3328 void* image /**< new image for origin */
3329 )
3330{
3331 uint32_t hashval;
3333
3334 assert(hashmap != NULL);
3335 assert(hashmap->slots != NULL);
3336 assert(hashmap->mask > 0);
3338
3339#ifndef NDEBUG
3340 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3342#endif
3343
3344 SCIP_CALL( hashmapCheckLoad(hashmap) );
3345
3346 /* get the hash value */
3347 hashval = hashvalue((size_t)origin);
3348
3349 /* append origin->image pair to hash map */
3350 img.ptr = image;
3351 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, TRUE) );
3352
3353 return SCIP_OKAY;
3354}
3355
3356/** sets image for given origin in the hash map, either by modifying existing origin->image pair
3357 * or by appending a new origin->image pair
3358 */
3360 SCIP_HASHMAP* hashmap, /**< hash map */
3361 void* origin, /**< origin to set image for */
3362 int image /**< new image for origin */
3363 )
3364{
3365 uint32_t hashval;
3367
3368 assert(hashmap != NULL);
3369 assert(hashmap->slots != NULL);
3370 assert(hashmap->mask > 0);
3371 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_INT);
3372
3373#ifndef NDEBUG
3374 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3376#endif
3377
3378 SCIP_CALL( hashmapCheckLoad(hashmap) );
3379
3380 /* get the hash value */
3381 hashval = hashvalue((size_t)origin);
3382
3383 /* append origin->image pair to hash map */
3384 img.integer = image;
3385 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, TRUE) );
3386
3387 return SCIP_OKAY;
3388}
3389
3390/** sets image for given origin in the hash map, either by modifying existing origin->image pair
3391 * or by appending a new origin->image pair
3392 */
3394 SCIP_HASHMAP* hashmap, /**< hash map */
3395 void* origin, /**< origin to set image for */
3396 SCIP_Real image /**< new image for origin */
3397 )
3398{
3399 uint32_t hashval;
3401
3402 assert(hashmap != NULL);
3403 assert(hashmap->slots != NULL);
3404 assert(hashmap->mask > 0);
3405 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_REAL);
3406
3407#ifndef NDEBUG
3408 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3410#endif
3411
3412 SCIP_CALL( hashmapCheckLoad(hashmap) );
3413
3414 /* get the hash value */
3415 hashval = hashvalue((size_t)origin);
3416
3417 /* append origin->image pair to hash map */
3418 img.real = image;
3419 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, TRUE) );
3420
3421 return SCIP_OKAY;
3422}
3423
3424/** checks whether an image to the given origin exists in the hash map */
3426 SCIP_HASHMAP* hashmap, /**< hash map */
3427 void* origin /**< origin to search for */
3428 )
3429{
3430 uint32_t pos;
3431
3432 assert(hashmap != NULL);
3433 assert(hashmap->slots != NULL);
3434 assert(hashmap->hashes != NULL);
3435 assert(hashmap->mask > 0);
3436
3437 return hashmapLookup(hashmap, origin, &pos);
3438}
3439
3440/** removes origin->image pair from the hash map, if it exists */
3442 SCIP_HASHMAP* hashmap, /**< hash map */
3443 void* origin /**< origin to remove from the list */
3444 )
3445{
3446 uint32_t pos;
3447
3448 assert(hashmap != NULL);
3449 assert(hashmap->slots != NULL);
3450 assert(hashmap->mask > 0);
3451
3452 assert(origin != NULL);
3453
3454 if( hashmapLookup(hashmap, origin, &pos) )
3455 {
3456 /* remove element */
3457 hashmap->hashes[pos] = 0;
3458 --hashmap->nelements;
3459
3460 /* move other elements if necessary */
3461 while( TRUE ) /*lint !e716*/
3462 {
3463 uint32_t nextpos = (pos + 1) & hashmap->mask;
3464
3465 /* nothing to do since there is no chain that needs to be moved */
3466 if( hashmap->hashes[nextpos] == 0 )
3467 return SCIP_OKAY;
3468
3469 /* check if the element is the start of a new chain and return if that is the case */
3470 if( (hashmap->hashes[nextpos]>>(hashmap->shift)) == nextpos )
3471 return SCIP_OKAY;
3472
3473 /* element should be moved to the left and next element needs to be checked */
3474 hashmap->slots[pos].origin = hashmap->slots[nextpos].origin;
3475 hashmap->slots[pos].image = hashmap->slots[nextpos].image;
3476 hashmap->hashes[pos] = hashmap->hashes[nextpos];
3477 hashmap->hashes[nextpos] = 0;
3478
3479 pos = nextpos;
3480 }
3481 }
3482
3483 return SCIP_OKAY;
3484}
3485
3486/** prints statistics about hash map usage */
3488 SCIP_HASHMAP* hashmap, /**< hash map */
3489 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
3490 )
3491{
3492 uint32_t maxprobelen = 0;
3493 uint64_t probelensum = 0;
3494 uint32_t nslots;
3495 uint32_t i;
3496
3497 assert(hashmap != NULL);
3498
3499 nslots = hashmap->mask + 1;
3500
3501 /* compute the maximum and average probe length */
3502 for( i = 0; i < nslots; ++i )
3503 {
3504 if( hashmap->hashes[i] != 0 )
3505 {
3506 uint32_t probelen = ELEM_DISTANCE(i) + 1;
3507 probelensum += probelen;
3508 maxprobelen = MAX(probelen, maxprobelen);
3509 }
3510 }
3511
3512 /* print general hash map statistics */
3513 SCIPmessagePrintInfo(messagehdlr, "%u hash entries, used %u/%u slots (%.1f%%)",
3514 (unsigned int)hashmap->nelements, (unsigned int)hashmap->nelements,
3515 (unsigned int)nslots, 100.0*(SCIP_Real)hashmap->nelements/(SCIP_Real)(nslots));
3516
3517 /* if not empty print average and maximum probe length */
3518 if( hashmap->nelements > 0 )
3519 SCIPmessagePrintInfo(messagehdlr, ", avg. probe length is %.1f, max. probe length is %u",
3520 (SCIP_Real)(probelensum)/(SCIP_Real)hashmap->nelements, (unsigned int)maxprobelen);
3521 SCIPmessagePrintInfo(messagehdlr, "\n");
3522}
3523
3524/** indicates whether a hash map has no entries */
3526 SCIP_HASHMAP* hashmap /**< hash map */
3527 )
3528{
3529 assert(hashmap != NULL);
3530
3531 return hashmap->nelements == 0;
3532}
3533
3534/** gives the number of elements in a hash map */
3536 SCIP_HASHMAP* hashmap /**< hash map */
3537 )
3538{
3539 return (int) hashmap->nelements;
3540}
3541
3542/** gives the number of entries in the internal arrays of a hash map */
3544 SCIP_HASHMAP* hashmap /**< hash map */
3545 )
3546{
3547 return (int) hashmap->mask + 1;
3548}
3549
3550/** gives the hashmap entry at the given index or NULL if entry is empty */
3552 SCIP_HASHMAP* hashmap, /**< hash map */
3553 int entryidx /**< index of hash map entry */
3554 )
3555{
3556 assert(hashmap != NULL);
3557
3558 return hashmap->hashes[entryidx] == 0 ? NULL : &hashmap->slots[entryidx];
3559}
3560
3561/** gives the origin of the hashmap entry */
3563 SCIP_HASHMAPENTRY* entry /**< hash map entry */
3564 )
3565{
3566 assert(entry != NULL);
3567
3568 return entry->origin;
3569}
3570
3571/** gives the image of the hashmap entry */
3573 SCIP_HASHMAPENTRY* entry /**< hash map entry */
3574 )
3575{
3576 assert(entry != NULL);
3577
3578 return entry->image.ptr;
3579}
3580
3581/** gives the image of the hashmap entry */
3583 SCIP_HASHMAPENTRY* entry /**< hash map entry */
3584 )
3585{
3586 assert(entry != NULL);
3587
3588 return entry->image.integer;
3589}
3590
3591/** gives the image of the hashmap entry */
3593 SCIP_HASHMAPENTRY* entry /**< hash map entry */
3594 )
3595{
3596 assert(entry != NULL);
3597
3598 return entry->image.real;
3599}
3600
3601/** sets pointer image of a hashmap entry */
3603 SCIP_HASHMAPENTRY* entry, /**< hash map entry */
3604 void* image /**< new image */
3605 )
3606{
3607 assert(entry != NULL);
3608
3609 entry->image.ptr = image;
3610}
3611
3612/** sets integer image of a hashmap entry */
3614 SCIP_HASHMAPENTRY* entry, /**< hash map entry */
3615 int image /**< new image */
3616 )
3617{
3618 assert(entry != NULL);
3619
3620 entry->image.integer = image;
3621}
3622
3623/** sets real image of a hashmap entry */
3625 SCIP_HASHMAPENTRY* entry, /**< hash map entry */
3626 SCIP_Real image /**< new image */
3627 )
3628{
3629 assert(entry != NULL);
3630
3631 entry->image.real = image;
3632}
3633
3634/** removes all entries in a hash map. */
3636 SCIP_HASHMAP* hashmap /**< hash map */
3637 )
3638{
3639 assert(hashmap != NULL);
3640
3641 BMSclearMemoryArray(hashmap->hashes, hashmap->mask + 1);
3642
3643 hashmap->nelements = 0;
3644
3645 return SCIP_OKAY;
3646}
3647
3648
3649/*
3650 * Hash Set
3651 */
3652
3653/* redefine ELEM_DISTANCE macro for hashset */
3654#undef ELEM_DISTANCE
3655/* computes the distance from it's desired position for the element stored at pos */
3656#define ELEM_DISTANCE(pos) (((pos) + nslots - hashSetDesiredPos(hashset, hashset->slots[(pos)])) & mask)
3657
3658/* calculate desired position of element in hash set */
3659static
3661 SCIP_HASHSET* hashset, /**< the hash set */
3662 void* element /**< element to calculate position for */
3663 )
3664{
3665 return (uint32_t)((UINT64_C(0x9e3779b97f4a7c15) * (uintptr_t)element)>>(hashset->shift));
3666}
3667
3668static
3670 SCIP_HASHSET* hashset, /**< hash set */
3671 void* element /**< element to insert */
3672 )
3673{
3674 uint32_t elemdistance;
3675 uint32_t pos;
3676 uint32_t nslots;
3677 uint32_t mask;
3678
3679 assert(hashset != NULL);
3680 assert(hashset->slots != NULL);
3681 assert(element != NULL);
3682
3683 pos = hashSetDesiredPos(hashset, element);
3684 nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3685 mask = nslots - 1;
3686
3687 elemdistance = 0;
3688 while( TRUE ) /*lint !e716*/
3689 {
3690 uint32_t distance;
3691
3692 /* if position is empty or key equal insert element */
3693 if( hashset->slots[pos] == NULL )
3694 {
3695 hashset->slots[pos] = element;
3696 ++hashset->nelements;
3697 return;
3698 }
3699
3700 if( hashset->slots[pos] == element )
3701 return;
3702
3703 /* otherwise check if the current element at this position is closer to its hashvalue */
3704 distance = ELEM_DISTANCE(pos);
3705 if( distance < elemdistance )
3706 {
3707 /* if this is the case we insert the new element here and find a new position for the old one */
3708 elemdistance = distance;
3709 SCIPswapPointers(&hashset->slots[pos], &element);
3710 }
3711
3712 /* continue until we have found an empty position */
3713 pos = (pos + 1) & mask;
3714 ++elemdistance;
3715 }
3716}
3717
3718/** check if the load factor of the hash set is too high and rebuild if necessary */
3719static
3721 SCIP_HASHSET* hashset, /**< hash set */
3722 BMS_BLKMEM* blkmem /**< block memory used to store hash set entries */
3723 )
3724{
3725 assert(hashset != NULL);
3726 assert(hashset->shift < 64);
3727
3728 /* use integer arithmetic to approximately check if load factor is above 90% */
3729 if( ((((uint64_t)hashset->nelements)<<10)>>(64-hashset->shift) > 921) )
3730 {
3731 void** slots;
3732 uint32_t nslots;
3733 uint32_t newnslots;
3734 uint32_t i;
3735
3736 /* calculate new size (always power of two) */
3737 nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3738 newnslots = 2*nslots;
3739 --hashset->shift;
3740
3741 /* reallocate array */
3742 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &slots, newnslots) );
3743
3744 SCIPswapPointers((void**) &slots, (void**) &hashset->slots);
3745 hashset->nelements = 0;
3746
3747 /* reinsert all elements */
3748 for( i = 0; i < nslots; ++i )
3749 {
3750 if( slots[i] != NULL )
3751 hashsetInsert(hashset, slots[i]);
3752 }
3753
3754 BMSfreeBlockMemoryArray(blkmem, &slots, nslots);
3755 }
3756
3757 return SCIP_OKAY;
3758}
3759
3760/** creates a hash set of pointers */
3762 SCIP_HASHSET** hashset, /**< pointer to store the created hash set */
3763 BMS_BLKMEM* blkmem, /**< block memory used to store hash set entries */
3764 int size /**< initial size of the hash set; it is guaranteed that the set is not
3765 * resized if at most that many elements are inserted */
3766 )
3767{
3768 uint32_t nslots;
3769
3770 assert(hashset != NULL);
3771 assert(size >= 0);
3772 assert(blkmem != NULL);
3773
3774 SCIP_ALLOC( BMSallocBlockMemory(blkmem, hashset) );
3775
3776 /* do not create too small hashtables, i.e. at least size 32, and increase
3777 * the given size by dividing it by 0.9, since then no rebuilding will
3778 * be necessary if the given number of elements are inserted. Finally round
3779 * to the next power of two.
3780 */
3781 (*hashset)->shift = 64;
3782 (*hashset)->shift -= (unsigned int)ceil(log(MAX(8.0, size / 0.9)) / log(2.0));
3783 nslots = (uint32_t)SCIPhashsetGetNSlots(*hashset);
3784 (*hashset)->nelements = 0;
3785
3786 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*hashset)->slots, nslots) );
3787
3788 return SCIP_OKAY;
3789}
3790
3791/** frees the hash set */
3793 SCIP_HASHSET** hashset, /**< pointer to the hash set */
3794 BMS_BLKMEM* blkmem /**< block memory used to store hash set entries */
3795 )
3796{
3797 BMSfreeBlockMemoryArray(blkmem, &(*hashset)->slots, SCIPhashsetGetNSlots(*hashset));
3798 BMSfreeBlockMemory(blkmem, hashset);
3799}
3800
3801/** inserts new element into the hash set */
3803 SCIP_HASHSET* hashset, /**< hash set */
3804 BMS_BLKMEM* blkmem, /**< block memory used to store hash set entries */
3805 void* element /**< element to insert */
3806 )
3807{
3808 assert(hashset != NULL);
3809 assert(hashset->slots != NULL);
3810
3811 SCIP_CALL( hashsetCheckLoad(hashset, blkmem) );
3812
3813 hashsetInsert(hashset, element);
3814
3815 return SCIP_OKAY;
3816}
3817
3818/** checks whether an element exists in the hash set */
3820 SCIP_HASHSET* hashset, /**< hash set */
3821 void* element /**< element to search for */
3822 )
3823{
3824 uint32_t pos;
3825 uint32_t nslots;
3826 uint32_t mask;
3827 uint32_t elemdistance;
3828
3829 assert(hashset != NULL);
3830 assert(hashset->slots != NULL);
3831
3832 pos = hashSetDesiredPos(hashset, element);
3833 nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3834 mask = nslots - 1;
3835 elemdistance = 0;
3836
3837 while( TRUE ) /*lint !e716*/
3838 {
3839 uint32_t distance;
3840
3841 /* found element */
3842 if( hashset->slots[pos] == element )
3843 return TRUE;
3844
3845 /* slots is empty so element cannot be contained */
3846 if( hashset->slots[pos] == NULL )
3847 return FALSE;
3848
3849 distance = ELEM_DISTANCE(pos);
3850 /* element can not be contained since otherwise we would have swapped it with this one during insert */
3851 if( elemdistance > distance )
3852 return FALSE;
3853
3854 pos = (pos + 1) & mask;
3855 ++elemdistance;
3856 }
3857}
3858
3859/** removes an element from the hash set, if it exists */
3861 SCIP_HASHSET* hashset, /**< hash set */
3862 void* element /**< origin to remove from the list */
3863 )
3864{
3865 uint32_t pos;
3866 uint32_t nslots;
3867 uint32_t mask;
3868 uint32_t elemdistance;
3869
3870 assert(hashset != NULL);
3871 assert(hashset->slots != NULL);
3872 assert(element != NULL);
3873
3874 pos = hashSetDesiredPos(hashset, element);
3875 nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3876 mask = nslots - 1;
3877 elemdistance = 0;
3878
3879 while( TRUE ) /*lint !e716*/
3880 {
3881 uint32_t distance;
3882
3883 /* found element */
3884 if( hashset->slots[pos] == element )
3885 break;
3886
3887 /* slots is empty so element cannot be contained */
3888 if( hashset->slots[pos] == NULL )
3889 return SCIP_OKAY;
3890
3891 distance = ELEM_DISTANCE(pos);
3892 /* element can not be contained since otherwise we would have swapped it with this one during insert */
3893 if( elemdistance > distance )
3894 return SCIP_OKAY;
3895
3896 pos = (pos + 1) & mask;
3897 ++elemdistance;
3898 }
3899
3900 assert(hashset->slots[pos] == element);
3901 assert(SCIPhashsetExists(hashset, element));
3902
3903 /* remove element */
3904 --hashset->nelements;
3905
3906 /* move other elements if necessary */
3907 while( TRUE ) /*lint !e716*/
3908 {
3909 uint32_t nextpos = (pos + 1) & mask;
3910
3911 /* nothing to do since there is no chain that needs to be moved */
3912 if( hashset->slots[nextpos] == NULL )
3913 {
3914 hashset->slots[pos] = NULL;
3915 assert(!SCIPhashsetExists(hashset, element));
3916 return SCIP_OKAY;
3917 }
3918
3919 /* check if the element is the start of a new chain and return if that is the case */
3920 if( hashSetDesiredPos(hashset, hashset->slots[nextpos]) == nextpos )
3921 {
3922 hashset->slots[pos] = NULL;
3923 assert(!SCIPhashsetExists(hashset, element));
3924 return SCIP_OKAY;
3925 }
3926
3927 /* element should be moved to the left and next element needs to be checked */
3928 hashset->slots[pos] = hashset->slots[nextpos];
3929
3930 pos = nextpos;
3931 }
3932}
3933
3934/** prints statistics about hash set usage */
3936 SCIP_HASHSET* hashset, /**< hash set */
3937 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
3938 )
3939{
3940 uint32_t maxprobelen = 0;
3941 uint64_t probelensum = 0;
3942 uint32_t nslots;
3943 uint32_t mask;
3944 uint32_t i;
3945
3946 assert(hashset != NULL);
3947
3948 nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3949 mask = nslots - 1;
3950
3951 /* compute the maximum and average probe length */
3952 for( i = 0; i < nslots; ++i )
3953 {
3954 if( hashset->slots[i] != NULL )
3955 {
3956 uint32_t probelen = ((hashSetDesiredPos(hashset, hashset->slots[i]) + nslots - i) & mask) + 1;
3957 probelensum += probelen;
3958 maxprobelen = MAX(probelen, maxprobelen);
3959 }
3960 }
3961
3962 /* print general hash set statistics */
3963 SCIPmessagePrintInfo(messagehdlr, "%u hash entries, used %u/%u slots (%.1f%%)",
3964 (unsigned int)hashset->nelements, (unsigned int)hashset->nelements,
3965 (unsigned int)nslots, 100.0*(SCIP_Real)hashset->nelements/(SCIP_Real)(nslots));
3966
3967 /* if not empty print average and maximum probe length */
3968 if( hashset->nelements > 0 )
3969 SCIPmessagePrintInfo(messagehdlr, ", avg. probe length is %.1f, max. probe length is %u",
3970 (SCIP_Real)(probelensum)/(SCIP_Real)hashset->nelements, (unsigned int)maxprobelen);
3971 SCIPmessagePrintInfo(messagehdlr, "\n");
3972}
3973
3974/* In debug mode, the following methods are implemented as function calls to ensure
3975 * type validity.
3976 * In optimized mode, the methods are implemented as defines to improve performance.
3977 * However, we want to have them in the library anyways, so we have to undef the defines.
3978 */
3979
3980#undef SCIPhashsetIsEmpty
3981#undef SCIPhashsetGetNElements
3982#undef SCIPhashsetGetNSlots
3983#undef SCIPhashsetGetSlots
3984
3985/** indicates whether a hash set has no entries */
3987 SCIP_HASHSET* hashset /**< hash set */
3988 )
3989{
3990 return hashset->nelements == 0;
3991}
3992
3993/** gives the number of elements in a hash set */
3995 SCIP_HASHSET* hashset /**< hash set */
3996 )
3997{
3998 return (int)hashset->nelements;
3999}
4000
4001/** gives the number of slots of a hash set */
4003 SCIP_HASHSET* hashset /**< hash set */
4004 )
4005{
4006 return (int) (1u << (64 - hashset->shift));
4007}
4008
4009/** gives the array of hash set slots; contains all elements in indetermined order and may contain NULL values */
4011 SCIP_HASHSET* hashset /**< hash set */
4012 )
4013{
4014 return hashset->slots;
4015}
4016
4017/** removes all entries in a hash set. */
4019 SCIP_HASHSET* hashset /**< hash set */
4020 )
4021{
4023
4024 hashset->nelements = 0;
4025}
4026
4027/*
4028 * Dynamic Arrays
4029 */
4030
4031/** creates a dynamic array of real values */
4033 SCIP_REALARRAY** realarray, /**< pointer to store the real array */
4034 BMS_BLKMEM* blkmem /**< block memory */
4035 )
4036{
4037 assert(realarray != NULL);
4038 assert(blkmem != NULL);
4039
4040 SCIP_ALLOC( BMSallocBlockMemory(blkmem, realarray) );
4041 (*realarray)->blkmem = blkmem;
4042 (*realarray)->vals = NULL;
4043 (*realarray)->valssize = 0;
4044 (*realarray)->firstidx = -1;
4045 (*realarray)->minusedidx = INT_MAX;
4046 (*realarray)->maxusedidx = INT_MIN;
4047
4048 return SCIP_OKAY;
4049}
4050
4051/** creates a copy of a dynamic array of real values */
4053 SCIP_REALARRAY** realarray, /**< pointer to store the copied real array */
4054 BMS_BLKMEM* blkmem, /**< block memory */
4055 SCIP_REALARRAY* sourcerealarray /**< dynamic real array to copy */
4056 )
4057{
4058 assert(realarray != NULL);
4059 assert(sourcerealarray != NULL);
4060
4061 SCIP_CALL( SCIPrealarrayCreate(realarray, blkmem) );
4062 if( sourcerealarray->valssize > 0 )
4063 {
4064 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*realarray)->vals, sourcerealarray->vals, \
4065 sourcerealarray->valssize) );
4066 }
4067 (*realarray)->valssize = sourcerealarray->valssize;
4068 (*realarray)->firstidx = sourcerealarray->firstidx;
4069 (*realarray)->minusedidx = sourcerealarray->minusedidx;
4070 (*realarray)->maxusedidx = sourcerealarray->maxusedidx;
4071
4072 return SCIP_OKAY;
4073}
4074
4075/** frees a dynamic array of real values */
4077 SCIP_REALARRAY** realarray /**< pointer to the real array */
4078 )
4079{
4080 assert(realarray != NULL);
4081 assert(*realarray != NULL);
4082
4083 BMSfreeBlockMemoryArrayNull((*realarray)->blkmem, &(*realarray)->vals, (*realarray)->valssize);
4084 BMSfreeBlockMemory((*realarray)->blkmem, realarray);
4085
4086 return SCIP_OKAY;
4087}
4088
4089/** extends dynamic array to be able to store indices from minidx to maxidx */
4091 SCIP_REALARRAY* realarray, /**< dynamic real array */
4092 int arraygrowinit, /**< initial size of array */
4093 SCIP_Real arraygrowfac, /**< growing factor of array */
4094 int minidx, /**< smallest index to allocate storage for */
4095 int maxidx /**< largest index to allocate storage for */
4096 )
4097{
4098 int nused;
4099 int nfree;
4100 int newfirstidx;
4101 int i;
4102
4103 assert(realarray != NULL);
4104 assert(realarray->minusedidx == INT_MAX || realarray->firstidx >= 0);
4105 assert(realarray->maxusedidx == INT_MIN || realarray->firstidx >= 0);
4106 assert(realarray->minusedidx == INT_MAX || realarray->minusedidx >= realarray->firstidx);
4107 assert(realarray->maxusedidx == INT_MIN || realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4108 assert(0 <= minidx);
4109 assert(minidx <= maxidx);
4110
4111 minidx = MIN(minidx, realarray->minusedidx);
4112 maxidx = MAX(maxidx, realarray->maxusedidx);
4113 assert(0 <= minidx);
4114 assert(minidx <= maxidx);
4115
4116 SCIPdebugMessage("extending realarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
4117 (void*)realarray, realarray->firstidx, realarray->valssize, realarray->minusedidx, realarray->maxusedidx, minidx, maxidx);
4118
4119 /* check, whether we have to allocate additional memory, or shift the array */
4120 nused = maxidx - minidx + 1;
4121 if( nused > realarray->valssize )
4122 {
4123 SCIP_Real* newvals;
4124 int newvalssize;
4125
4126 /* allocate new memory storage */
4127 newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
4128 SCIP_ALLOC( BMSallocBlockMemoryArray(realarray->blkmem, &newvals, newvalssize) );
4129 nfree = newvalssize - nused;
4130 newfirstidx = minidx - nfree/2;
4131 newfirstidx = MAX(newfirstidx, 0);
4132 assert(newfirstidx <= minidx);
4133 assert(maxidx < newfirstidx + newvalssize);
4134
4135 /* initialize memory array by copying old values and setting new values to zero */
4136 if( realarray->firstidx != -1 )
4137 {
4138 for( i = 0; i < realarray->minusedidx - newfirstidx; ++i )
4139 newvals[i] = 0.0;
4140
4141 /* check for possible overflow or negative value */
4142 assert(realarray->maxusedidx - realarray->minusedidx + 1 > 0);
4143
4144 BMScopyMemoryArray(&newvals[realarray->minusedidx - newfirstidx],
4145 &(realarray->vals[realarray->minusedidx - realarray->firstidx]),
4146 realarray->maxusedidx - realarray->minusedidx + 1); /*lint !e866 !e776*/
4147 for( i = realarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
4148 newvals[i] = 0.0;
4149 }
4150 else
4151 {
4152 for( i = 0; i < newvalssize; ++i )
4153 newvals[i] = 0.0;
4154 }
4155
4156 /* free old memory storage, and set the new array parameters */
4157 BMSfreeBlockMemoryArrayNull(realarray->blkmem, &realarray->vals, realarray->valssize);
4158 realarray->vals = newvals;
4159 realarray->valssize = newvalssize;
4160 realarray->firstidx = newfirstidx;
4161 }
4162 else if( realarray->firstidx == -1 )
4163 {
4164 /* a sufficiently large memory storage exists, but it was cleared */
4165 nfree = realarray->valssize - nused;
4166 assert(nfree >= 0);
4167 realarray->firstidx = minidx - nfree/2;
4168 assert(realarray->firstidx <= minidx);
4169 assert(maxidx < realarray->firstidx + realarray->valssize);
4170#ifndef NDEBUG
4171 for( i = 0; i < realarray->valssize; ++i )
4172 assert(realarray->vals[i] == 0.0);
4173#endif
4174 }
4175 else if( minidx < realarray->firstidx )
4176 {
4177 /* a sufficiently large memory storage exists, but it has to be shifted to the right */
4178 nfree = realarray->valssize - nused;
4179 assert(nfree >= 0);
4180 newfirstidx = minidx - nfree/2;
4181 newfirstidx = MAX(newfirstidx, 0);
4182 assert(newfirstidx <= minidx);
4183 assert(maxidx < newfirstidx + realarray->valssize);
4184
4185 if( realarray->minusedidx <= realarray->maxusedidx )
4186 {
4187 int shift;
4188
4189 assert(realarray->firstidx <= realarray->minusedidx);
4190 assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4191
4192 /* shift used part of array to the right */
4193 shift = realarray->firstidx - newfirstidx;
4194 assert(shift > 0);
4195 for( i = realarray->maxusedidx - realarray->firstidx; i >= realarray->minusedidx - realarray->firstidx; --i )
4196 {
4197 assert(0 <= i + shift && i + shift < realarray->valssize);
4198 realarray->vals[i + shift] = realarray->vals[i];
4199 }
4200 /* clear the formerly used head of the array */
4201 for( i = 0; i < shift; ++i )
4202 realarray->vals[realarray->minusedidx - realarray->firstidx + i] = 0.0;
4203 }
4204 realarray->firstidx = newfirstidx;
4205 }
4206 else if( maxidx >= realarray->firstidx + realarray->valssize )
4207 {
4208 /* a sufficiently large memory storage exists, but it has to be shifted to the left */
4209 nfree = realarray->valssize - nused;
4210 assert(nfree >= 0);
4211 newfirstidx = minidx - nfree/2;
4212 newfirstidx = MAX(newfirstidx, 0);
4213 assert(newfirstidx <= minidx);
4214 assert(maxidx < newfirstidx + realarray->valssize);
4215
4216 if( realarray->minusedidx <= realarray->maxusedidx )
4217 {
4218 int shift;
4219
4220 assert(realarray->firstidx <= realarray->minusedidx);
4221 assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4222
4223 /* shift used part of array to the left */
4224 shift = newfirstidx - realarray->firstidx;
4225 assert(shift > 0);
4226 for( i = realarray->minusedidx - realarray->firstidx; i <= realarray->maxusedidx - realarray->firstidx; ++i )
4227 {
4228 assert(0 <= i - shift && i - shift < realarray->valssize);
4229 realarray->vals[i - shift] = realarray->vals[i];
4230 }
4231 /* clear the formerly used tail of the array */
4232 for( i = 0; i < shift; ++i )
4233 realarray->vals[realarray->maxusedidx - realarray->firstidx - i] = 0.0;
4234 }
4235 realarray->firstidx = newfirstidx;
4236 }
4237
4238 assert(minidx >= realarray->firstidx);
4239 assert(maxidx < realarray->firstidx + realarray->valssize);
4240
4241 return SCIP_OKAY;
4242}
4243
4244/** clears a dynamic real array */
4246 SCIP_REALARRAY* realarray /**< dynamic real array */
4247 )
4248{
4249 assert(realarray != NULL);
4250
4251 SCIPdebugMessage("clearing realarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
4252 (void*)realarray, realarray->firstidx, realarray->valssize, realarray->minusedidx, realarray->maxusedidx);
4253
4254 if( realarray->minusedidx <= realarray->maxusedidx )
4255 {
4256 assert(realarray->firstidx <= realarray->minusedidx);
4257 assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4258 assert(realarray->firstidx != -1);
4259 assert(realarray->valssize > 0);
4260
4261 /* clear the used part of array */
4262 BMSclearMemoryArray(&realarray->vals[realarray->minusedidx - realarray->firstidx],
4263 realarray->maxusedidx - realarray->minusedidx + 1); /*lint !e866*/
4264
4265 /* mark the array cleared */
4266 realarray->minusedidx = INT_MAX;
4267 realarray->maxusedidx = INT_MIN;
4268 }
4269 assert(realarray->minusedidx == INT_MAX);
4270 assert(realarray->maxusedidx == INT_MIN);
4271
4272 return SCIP_OKAY;
4273}
4274
4275/** gets value of entry in dynamic array */
4277 SCIP_REALARRAY* realarray, /**< dynamic real array */
4278 int idx /**< array index to get value for */
4279 )
4280{
4281 assert(realarray != NULL);
4282 assert(idx >= 0);
4283
4284 if( idx < realarray->minusedidx || idx > realarray->maxusedidx )
4285 return 0.0;
4286 else
4287 {
4288 assert(realarray->vals != NULL);
4289 assert(idx - realarray->firstidx >= 0);
4290 assert(idx - realarray->firstidx < realarray->valssize);
4291
4292 return realarray->vals[idx - realarray->firstidx];
4293 }
4294}
4295
4296/** sets value of entry in dynamic array */
4298 SCIP_REALARRAY* realarray, /**< dynamic real array */
4299 int arraygrowinit, /**< initial size of array */
4300 SCIP_Real arraygrowfac, /**< growing factor of array */
4301 int idx, /**< array index to set value for */
4302 SCIP_Real val /**< value to set array index to */
4303 )
4304{
4305 assert(realarray != NULL);
4306 assert(idx >= 0);
4307
4308 SCIPdebugMessage("setting realarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %g\n",
4309 (void*)realarray, realarray->firstidx, realarray->valssize, realarray->minusedidx, realarray->maxusedidx, idx, val);
4310
4311 if( val != 0.0 )
4312 {
4313 /* extend array to be able to store the index */
4314 SCIP_CALL( SCIPrealarrayExtend(realarray, arraygrowinit, arraygrowfac, idx, idx) );
4315 assert(idx >= realarray->firstidx);
4316 assert(idx < realarray->firstidx + realarray->valssize);
4317
4318 /* set the array value of the index */
4319 realarray->vals[idx - realarray->firstidx] = val;
4320
4321 /* update min/maxusedidx */
4322 realarray->minusedidx = MIN(realarray->minusedidx, idx);
4323 realarray->maxusedidx = MAX(realarray->maxusedidx, idx);
4324 }
4325 else if( idx >= realarray->firstidx && idx < realarray->firstidx + realarray->valssize )
4326 {
4327 /* set the array value of the index to zero */
4328 realarray->vals[idx - realarray->firstidx] = 0.0;
4329
4330 /* check, if we can tighten the min/maxusedidx */
4331 if( idx == realarray->minusedidx )
4332 {
4333 assert(realarray->maxusedidx >= 0);
4334 assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4335 do
4336 {
4337 realarray->minusedidx++;
4338 }
4339 while( realarray->minusedidx <= realarray->maxusedidx
4340 && realarray->vals[realarray->minusedidx - realarray->firstidx] == 0.0 );
4341
4342 if( realarray->minusedidx > realarray->maxusedidx )
4343 {
4344 realarray->minusedidx = INT_MAX;
4345 realarray->maxusedidx = INT_MIN;
4346 }
4347 }
4348 else if( idx == realarray->maxusedidx )
4349 {
4350 assert(realarray->minusedidx >= 0);
4351 assert(realarray->minusedidx < realarray->maxusedidx);
4352 assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4353 do
4354 {
4355 realarray->maxusedidx--;
4356 assert(realarray->minusedidx <= realarray->maxusedidx);
4357 }
4358 while( realarray->vals[realarray->maxusedidx - realarray->firstidx] == 0.0 );
4359 }
4360 }
4361
4362 return SCIP_OKAY;
4363}
4364
4365/** increases value of entry in dynamic array */
4367 SCIP_REALARRAY* realarray, /**< dynamic real array */
4368 int arraygrowinit, /**< initial size of array */
4369 SCIP_Real arraygrowfac, /**< growing factor of array */
4370 int idx, /**< array index to increase value for */
4371 SCIP_Real incval /**< value to increase array index */
4372 )
4373{
4374 SCIP_Real oldval;
4375
4376 oldval = SCIPrealarrayGetVal(realarray, idx);
4377 if( oldval != SCIP_INVALID ) /*lint !e777*/
4378 return SCIPrealarraySetVal(realarray, arraygrowinit, arraygrowfac, idx, oldval + incval);
4379 else
4380 return SCIP_OKAY;
4381}
4382
4383/** returns the minimal index of all stored non-zero elements */
4385 SCIP_REALARRAY* realarray /**< dynamic real array */
4386 )
4387{
4388 assert(realarray != NULL);
4389
4390 return realarray->minusedidx;
4391}
4392
4393/** returns the maximal index of all stored non-zero elements */
4395 SCIP_REALARRAY* realarray /**< dynamic real array */
4396 )
4397{
4398 assert(realarray != NULL);
4399
4400 return realarray->maxusedidx;
4401}
4402
4403/** creates a dynamic array of int values */
4405 SCIP_INTARRAY** intarray, /**< pointer to store the int array */
4406 BMS_BLKMEM* blkmem /**< block memory */
4407 )
4408{
4409 assert(intarray != NULL);
4410 assert(blkmem != NULL);
4411
4412 SCIP_ALLOC( BMSallocBlockMemory(blkmem, intarray) );
4413 (*intarray)->blkmem = blkmem;
4414 (*intarray)->vals = NULL;
4415 (*intarray)->valssize = 0;
4416 (*intarray)->firstidx = -1;
4417 (*intarray)->minusedidx = INT_MAX;
4418 (*intarray)->maxusedidx = INT_MIN;
4419
4420 return SCIP_OKAY;
4421}
4422
4423/** creates a copy of a dynamic array of int values */
4425 SCIP_INTARRAY** intarray, /**< pointer to store the copied int array */
4426 BMS_BLKMEM* blkmem, /**< block memory */
4427 SCIP_INTARRAY* sourceintarray /**< dynamic int array to copy */
4428 )
4429{
4430 assert(intarray != NULL);
4431 assert(sourceintarray != NULL);
4432
4433 SCIP_CALL( SCIPintarrayCreate(intarray, blkmem) );
4434 if( sourceintarray->valssize > 0 )
4435 {
4436 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*intarray)->vals, sourceintarray->vals, sourceintarray->valssize) );
4437 }
4438 (*intarray)->valssize = sourceintarray->valssize;
4439 (*intarray)->firstidx = sourceintarray->firstidx;
4440 (*intarray)->minusedidx = sourceintarray->minusedidx;
4441 (*intarray)->maxusedidx = sourceintarray->maxusedidx;
4442
4443 return SCIP_OKAY;
4444}
4445
4446/** frees a dynamic array of int values */
4448 SCIP_INTARRAY** intarray /**< pointer to the int array */
4449 )
4450{
4451 assert(intarray != NULL);
4452 assert(*intarray != NULL);
4453
4454 BMSfreeBlockMemoryArrayNull((*intarray)->blkmem, &(*intarray)->vals, (*intarray)->valssize);
4455 BMSfreeBlockMemory((*intarray)->blkmem, intarray);
4456
4457 return SCIP_OKAY;
4458}
4459
4460/** extends dynamic array to be able to store indices from minidx to maxidx */
4462 SCIP_INTARRAY* intarray, /**< dynamic int array */
4463 int arraygrowinit, /**< initial size of array */
4464 SCIP_Real arraygrowfac, /**< growing factor of array */
4465 int minidx, /**< smallest index to allocate storage for */
4466 int maxidx /**< largest index to allocate storage for */
4467 )
4468{
4469 int nused;
4470 int nfree;
4471 int newfirstidx;
4472 int i;
4473
4474 assert(intarray != NULL);
4475 assert(intarray->minusedidx == INT_MAX || intarray->firstidx >= 0);
4476 assert(intarray->maxusedidx == INT_MIN || intarray->firstidx >= 0);
4477 assert(intarray->minusedidx == INT_MAX || intarray->minusedidx >= intarray->firstidx);
4478 assert(intarray->maxusedidx == INT_MIN || intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4479 assert(0 <= minidx);
4480 assert(minidx <= maxidx);
4481
4482 minidx = MIN(minidx, intarray->minusedidx);
4483 maxidx = MAX(maxidx, intarray->maxusedidx);
4484 assert(0 <= minidx);
4485 assert(minidx <= maxidx);
4486
4487 SCIPdebugMessage("extending intarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
4488 (void*)intarray, intarray->firstidx, intarray->valssize, intarray->minusedidx, intarray->maxusedidx, minidx, maxidx);
4489
4490 /* check, whether we have to allocate additional memory, or shift the array */
4491 nused = maxidx - minidx + 1;
4492 if( nused > intarray->valssize )
4493 {
4494 int* newvals;
4495 int newvalssize;
4496
4497 /* allocate new memory storage */
4498 newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
4499 SCIP_ALLOC( BMSallocBlockMemoryArray(intarray->blkmem, &newvals, newvalssize) );
4500 nfree = newvalssize - nused;
4501 newfirstidx = minidx - nfree/2;
4502 newfirstidx = MAX(newfirstidx, 0);
4503 assert(newfirstidx <= minidx);
4504 assert(maxidx < newfirstidx + newvalssize);
4505
4506 /* initialize memory array by copying old values and setting new values to zero */
4507 if( intarray->firstidx != -1 )
4508 {
4509 for( i = 0; i < intarray->minusedidx - newfirstidx; ++i )
4510 newvals[i] = 0;
4511
4512 /* check for possible overflow or negative value */
4513 assert(intarray->maxusedidx - intarray->minusedidx + 1 > 0);
4514
4515 BMScopyMemoryArray(&newvals[intarray->minusedidx - newfirstidx],
4516 &intarray->vals[intarray->minusedidx - intarray->firstidx],
4517 intarray->maxusedidx - intarray->minusedidx + 1); /*lint !e866 !e776*/
4518 for( i = intarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
4519 newvals[i] = 0;
4520 }
4521 else
4522 {
4523 for( i = 0; i < newvalssize; ++i )
4524 newvals[i] = 0;
4525 }
4526
4527 /* free old memory storage, and set the new array parameters */
4528 BMSfreeBlockMemoryArrayNull(intarray->blkmem, &intarray->vals, intarray->valssize);
4529 intarray->vals = newvals;
4530 intarray->valssize = newvalssize;
4531 intarray->firstidx = newfirstidx;
4532 }
4533 else if( intarray->firstidx == -1 )
4534 {
4535 /* a sufficiently large memory storage exists, but it was cleared */
4536 nfree = intarray->valssize - nused;
4537 assert(nfree >= 0);
4538 intarray->firstidx = minidx - nfree/2;
4539 assert(intarray->firstidx <= minidx);
4540 assert(maxidx < intarray->firstidx + intarray->valssize);
4541#ifndef NDEBUG
4542 for( i = 0; i < intarray->valssize; ++i )
4543 assert(intarray->vals[i] == 0);
4544#endif
4545 }
4546 else if( minidx < intarray->firstidx )
4547 {
4548 /* a sufficiently large memory storage exists, but it has to be shifted to the right */
4549 nfree = intarray->valssize - nused;
4550 assert(nfree >= 0);
4551 newfirstidx = minidx - nfree/2;
4552 newfirstidx = MAX(newfirstidx, 0);
4553 assert(newfirstidx <= minidx);
4554 assert(maxidx < newfirstidx + intarray->valssize);
4555
4556 if( intarray->minusedidx <= intarray->maxusedidx )
4557 {
4558 int shift;
4559
4560 assert(intarray->firstidx <= intarray->minusedidx);
4561 assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4562
4563 /* shift used part of array to the right */
4564 shift = intarray->firstidx - newfirstidx;
4565 assert(shift > 0);
4566 for( i = intarray->maxusedidx - intarray->firstidx; i >= intarray->minusedidx - intarray->firstidx; --i )
4567 {
4568 assert(0 <= i + shift && i + shift < intarray->valssize);
4569 intarray->vals[i + shift] = intarray->vals[i];
4570 }
4571 /* clear the formerly used head of the array */
4572 for( i = 0; i < shift; ++i )
4573 intarray->vals[intarray->minusedidx - intarray->firstidx + i] = 0;
4574 }
4575 intarray->firstidx = newfirstidx;
4576 }
4577 else if( maxidx >= intarray->firstidx + intarray->valssize )
4578 {
4579 /* a sufficiently large memory storage exists, but it has to be shifted to the left */
4580 nfree = intarray->valssize - nused;
4581 assert(nfree >= 0);
4582 newfirstidx = minidx - nfree/2;
4583 newfirstidx = MAX(newfirstidx, 0);
4584 assert(newfirstidx <= minidx);
4585 assert(maxidx < newfirstidx + intarray->valssize);
4586
4587 if( intarray->minusedidx <= intarray->maxusedidx )
4588 {
4589 int shift;
4590
4591 assert(intarray->firstidx <= intarray->minusedidx);
4592 assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4593
4594 /* shift used part of array to the left */
4595 shift = newfirstidx - intarray->firstidx;
4596 assert(shift > 0);
4597 for( i = intarray->minusedidx - intarray->firstidx; i <= intarray->maxusedidx - intarray->firstidx; ++i )
4598 {
4599 assert(0 <= i - shift && i - shift < intarray->valssize);
4600 intarray->vals[i - shift] = intarray->vals[i];
4601 }
4602 /* clear the formerly used tail of the array */
4603 for( i = 0; i < shift; ++i )
4604 intarray->vals[intarray->maxusedidx - intarray->firstidx - i] = 0;
4605 }
4606 intarray->firstidx = newfirstidx;
4607 }
4608
4609 assert(minidx >= intarray->firstidx);
4610 assert(maxidx < intarray->firstidx + intarray->valssize);
4611
4612 return SCIP_OKAY;
4613}
4614
4615/** clears a dynamic int array */
4617 SCIP_INTARRAY* intarray /**< dynamic int array */
4618 )
4619{
4620 assert(intarray != NULL);
4621
4622 SCIPdebugMessage("clearing intarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
4623 (void*)intarray, intarray->firstidx, intarray->valssize, intarray->minusedidx, intarray->maxusedidx);
4624
4625 if( intarray->minusedidx <= intarray->maxusedidx )
4626 {
4627 assert(intarray->firstidx <= intarray->minusedidx);
4628 assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4629 assert(intarray->firstidx != -1);
4630 assert(intarray->valssize > 0);
4631
4632 /* clear the used part of array */
4633 BMSclearMemoryArray(&intarray->vals[intarray->minusedidx - intarray->firstidx],
4634 intarray->maxusedidx - intarray->minusedidx + 1); /*lint !e866*/
4635
4636 /* mark the array cleared */
4637 intarray->minusedidx = INT_MAX;
4638 intarray->maxusedidx = INT_MIN;
4639 }
4640 assert(intarray->minusedidx == INT_MAX);
4641 assert(intarray->maxusedidx == INT_MIN);
4642
4643 return SCIP_OKAY;
4644}
4645
4646/** gets value of entry in dynamic array */
4648 SCIP_INTARRAY* intarray, /**< dynamic int array */
4649 int idx /**< array index to get value for */
4650 )
4651{
4652 assert(intarray != NULL);
4653 assert(idx >= 0);
4654
4655 if( idx < intarray->minusedidx || idx > intarray->maxusedidx )
4656 return 0;
4657 else
4658 {
4659 assert(intarray->vals != NULL);
4660 assert(idx - intarray->firstidx >= 0);
4661 assert(idx - intarray->firstidx < intarray->valssize);
4662
4663 return intarray->vals[idx - intarray->firstidx];
4664 }
4665}
4666
4667/** sets value of entry in dynamic array */
4669 SCIP_INTARRAY* intarray, /**< dynamic int array */
4670 int arraygrowinit, /**< initial size of array */
4671 SCIP_Real arraygrowfac, /**< growing factor of array */
4672 int idx, /**< array index to set value for */
4673 int val /**< value to set array index to */
4674 )
4675{
4676 assert(intarray != NULL);
4677 assert(idx >= 0);
4678
4679 SCIPdebugMessage("setting intarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %d\n",
4680 (void*)intarray, intarray->firstidx, intarray->valssize, intarray->minusedidx, intarray->maxusedidx, idx, val);
4681
4682 if( val != 0 )
4683 {
4684 /* extend array to be able to store the index */
4685 SCIP_CALL( SCIPintarrayExtend(intarray, arraygrowinit, arraygrowfac, idx, idx) );
4686 assert(idx >= intarray->firstidx);
4687 assert(idx < intarray->firstidx + intarray->valssize);
4688
4689 /* set the array value of the index */
4690 intarray->vals[idx - intarray->firstidx] = val;
4691
4692 /* update min/maxusedidx */
4693 intarray->minusedidx = MIN(intarray->minusedidx, idx);
4694 intarray->maxusedidx = MAX(intarray->maxusedidx, idx);
4695 }
4696 else if( idx >= intarray->firstidx && idx < intarray->firstidx + intarray->valssize )
4697 {
4698 /* set the array value of the index to zero */
4699 intarray->vals[idx - intarray->firstidx] = 0;
4700
4701 /* check, if we can tighten the min/maxusedidx */
4702 if( idx == intarray->minusedidx )
4703 {
4704 assert(intarray->maxusedidx >= 0);
4705 assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4706 do
4707 {
4708 intarray->minusedidx++;
4709 }
4710 while( intarray->minusedidx <= intarray->maxusedidx
4711 && intarray->vals[intarray->minusedidx - intarray->firstidx] == 0 );
4712 if( intarray->minusedidx > intarray->maxusedidx )
4713 {
4714 intarray->minusedidx = INT_MAX;
4715 intarray->maxusedidx = INT_MIN;
4716 }
4717 }
4718 else if( idx == intarray->maxusedidx )
4719 {
4720 assert(intarray->minusedidx >= 0);
4721 assert(intarray->minusedidx < intarray->maxusedidx);
4722 assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4723 do
4724 {
4725 intarray->maxusedidx--;
4726 assert(intarray->minusedidx <= intarray->maxusedidx);
4727 }
4728 while( intarray->vals[intarray->maxusedidx - intarray->firstidx] == 0 );
4729 }
4730 }
4731
4732 return SCIP_OKAY;
4733}
4734
4735/** increases value of entry in dynamic array */
4737 SCIP_INTARRAY* intarray, /**< dynamic int array */
4738 int arraygrowinit, /**< initial size of array */
4739 SCIP_Real arraygrowfac, /**< growing factor of array */
4740 int idx, /**< array index to increase value for */
4741 int incval /**< value to increase array index */
4742 )
4743{
4744 return SCIPintarraySetVal(intarray, arraygrowinit, arraygrowfac, idx, SCIPintarrayGetVal(intarray, idx) + incval);
4745}
4746
4747/** returns the minimal index of all stored non-zero elements */
4749 SCIP_INTARRAY* intarray /**< dynamic int array */
4750 )
4751{
4752 assert(intarray != NULL);
4753
4754 return intarray->minusedidx;
4755}
4756
4757/** returns the maximal index of all stored non-zero elements */
4759 SCIP_INTARRAY* intarray /**< dynamic int array */
4760 )
4761{
4762 assert(intarray != NULL);
4763
4764 return intarray->maxusedidx;
4765}
4766
4767
4768/** creates a dynamic array of bool values */
4770 SCIP_BOOLARRAY** boolarray, /**< pointer to store the bool array */
4771 BMS_BLKMEM* blkmem /**< block memory */
4772 )
4773{
4774 assert(boolarray != NULL);
4775 assert(blkmem != NULL);
4776
4777 SCIP_ALLOC( BMSallocBlockMemory(blkmem, boolarray) );
4778 (*boolarray)->blkmem = blkmem;
4779 (*boolarray)->vals = NULL;
4780 (*boolarray)->valssize = 0;
4781 (*boolarray)->firstidx = -1;
4782 (*boolarray)->minusedidx = INT_MAX;
4783 (*boolarray)->maxusedidx = INT_MIN;
4784
4785 return SCIP_OKAY;
4786}
4787
4788/** creates a copy of a dynamic array of bool values */
4790 SCIP_BOOLARRAY** boolarray, /**< pointer to store the copied bool array */
4791 BMS_BLKMEM* blkmem, /**< block memory */
4792 SCIP_BOOLARRAY* sourceboolarray /**< dynamic bool array to copy */
4793 )
4794{
4795 assert(boolarray != NULL);
4796 assert(sourceboolarray != NULL);
4797
4798 SCIP_CALL( SCIPboolarrayCreate(boolarray, blkmem) );
4799 if( sourceboolarray->valssize > 0 )
4800 {
4801 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*boolarray)->vals, sourceboolarray->vals, \
4802 sourceboolarray->valssize) );
4803 }
4804 (*boolarray)->valssize = sourceboolarray->valssize;
4805 (*boolarray)->firstidx = sourceboolarray->firstidx;
4806 (*boolarray)->minusedidx = sourceboolarray->minusedidx;
4807 (*boolarray)->maxusedidx = sourceboolarray->maxusedidx;
4808
4809 return SCIP_OKAY;
4810}
4811
4812/** frees a dynamic array of bool values */
4814 SCIP_BOOLARRAY** boolarray /**< pointer to the bool array */
4815 )
4816{
4817 assert(boolarray != NULL);
4818 assert(*boolarray != NULL);
4819
4820 BMSfreeBlockMemoryArrayNull((*boolarray)->blkmem, &(*boolarray)->vals, (*boolarray)->valssize);
4821 BMSfreeBlockMemory((*boolarray)->blkmem, boolarray);
4822
4823 return SCIP_OKAY;
4824}
4825
4826/** extends dynamic array to be able to store indices from minidx to maxidx */
4828 SCIP_BOOLARRAY* boolarray, /**< dynamic bool array */
4829 int arraygrowinit, /**< initial size of array */
4830 SCIP_Real arraygrowfac, /**< growing factor of array */
4831 int minidx, /**< smallest index to allocate storage for */
4832 int maxidx /**< largest index to allocate storage for */
4833 )
4834{
4835 int nused;
4836 int nfree;
4837 int newfirstidx;
4838 int i;
4839
4840 assert(boolarray != NULL);
4841 assert(boolarray->minusedidx == INT_MAX || boolarray->firstidx >= 0);
4842 assert(boolarray->maxusedidx == INT_MIN || boolarray->firstidx >= 0);
4843 assert(boolarray->minusedidx == INT_MAX || boolarray->minusedidx >= boolarray->firstidx);
4844 assert(boolarray->maxusedidx == INT_MIN || boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
4845 assert(0 <= minidx);
4846 assert(minidx <= maxidx);
4847
4848 minidx = MIN(minidx, boolarray->minusedidx);
4849 maxidx = MAX(maxidx, boolarray->maxusedidx);
4850 assert(0 <= minidx);
4851 assert(minidx <= maxidx);
4852
4853 SCIPdebugMessage("extending boolarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
4854 (void*)boolarray, boolarray->firstidx, boolarray->valssize, boolarray->minusedidx, boolarray->maxusedidx, minidx, maxidx);
4855
4856 /* check, whether we have to allocate additional memory, or shift the array */
4857 nused = maxidx - minidx + 1;
4858 if( nused > boolarray->valssize )
4859 {
4860 SCIP_Bool* newvals;
4861 int newvalssize;
4862
4863 /* allocate new memory storage */
4864 newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
4865 SCIP_ALLOC( BMSallocBlockMemoryArray(boolarray->blkmem, &newvals, newvalssize) );
4866 nfree = newvalssize - nused;
4867 newfirstidx = minidx - nfree/2;
4868 newfirstidx = MAX(newfirstidx, 0);
4869 assert(newfirstidx <= minidx);
4870 assert(maxidx < newfirstidx + newvalssize);
4871
4872 /* initialize memory array by copying old values and setting new values to zero */
4873 if( boolarray->firstidx != -1 )
4874 {
4875 for( i = 0; i < boolarray->minusedidx - newfirstidx; ++i )
4876 newvals[i] = FALSE;
4877
4878 /* check for possible overflow or negative value */
4879 assert(boolarray->maxusedidx - boolarray->minusedidx + 1 > 0);
4880
4881 BMScopyMemoryArray(&newvals[boolarray->minusedidx - newfirstidx],
4882 &boolarray->vals[boolarray->minusedidx - boolarray->firstidx],
4883 boolarray->maxusedidx - boolarray->minusedidx + 1); /*lint !e866 !e776*/
4884 for( i = boolarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
4885 newvals[i] = FALSE;
4886 }
4887 else
4888 {
4889 for( i = 0; i < newvalssize; ++i )
4890 newvals[i] = FALSE;
4891 }
4892
4893 /* free old memory storage, and set the new array parameters */
4894 BMSfreeBlockMemoryArrayNull(boolarray->blkmem, &boolarray->vals, boolarray->valssize);
4895 boolarray->vals = newvals;
4896 boolarray->valssize = newvalssize;
4897 boolarray->firstidx = newfirstidx;
4898 }
4899 else if( boolarray->firstidx == -1 )
4900 {
4901 /* a sufficiently large memory storage exists, but it was cleared */
4902 nfree = boolarray->valssize - nused;
4903 assert(nfree >= 0);
4904 boolarray->firstidx = minidx - nfree/2;
4905 assert(boolarray->firstidx <= minidx);
4906 assert(maxidx < boolarray->firstidx + boolarray->valssize);
4907#ifndef NDEBUG
4908 for( i = 0; i < boolarray->valssize; ++i )
4909 assert(boolarray->vals[i] == FALSE);
4910#endif
4911 }
4912 else if( minidx < boolarray->firstidx )
4913 {
4914 /* a sufficiently large memory storage exists, but it has to be shifted to the right */
4915 nfree = boolarray->valssize - nused;
4916 assert(nfree >= 0);
4917 newfirstidx = minidx - nfree/2;
4918 newfirstidx = MAX(newfirstidx, 0);
4919 assert(newfirstidx <= minidx);
4920 assert(maxidx < newfirstidx + boolarray->valssize);
4921
4922 if( boolarray->minusedidx <= boolarray->maxusedidx )
4923 {
4924 int shift;
4925
4926 assert(boolarray->firstidx <= boolarray->minusedidx);
4927 assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
4928
4929 /* shift used part of array to the right */
4930 shift = boolarray->firstidx - newfirstidx;
4931 assert(shift > 0);
4932 for( i = boolarray->maxusedidx - boolarray->firstidx; i >= boolarray->minusedidx - boolarray->firstidx; --i )
4933 {
4934 assert(0 <= i + shift && i + shift < boolarray->valssize);
4935 boolarray->vals[i + shift] = boolarray->vals[i];
4936 }
4937 /* clear the formerly used head of the array */
4938 for( i = 0; i < shift; ++i )
4939 boolarray->vals[boolarray->minusedidx - boolarray->firstidx + i] = FALSE;
4940 }
4941 boolarray->firstidx = newfirstidx;
4942 }
4943 else if( maxidx >= boolarray->firstidx + boolarray->valssize )
4944 {
4945 /* a sufficiently large memory storage exists, but it has to be shifted to the left */
4946 nfree = boolarray->valssize - nused;
4947 assert(nfree >= 0);
4948 newfirstidx = minidx - nfree/2;
4949 newfirstidx = MAX(newfirstidx, 0);
4950 assert(newfirstidx <= minidx);
4951 assert(maxidx < newfirstidx + boolarray->valssize);
4952
4953 if( boolarray->minusedidx <= boolarray->maxusedidx )
4954 {
4955 int shift;
4956
4957 assert(boolarray->firstidx <= boolarray->minusedidx);
4958 assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
4959
4960 /* shift used part of array to the left */
4961 shift = newfirstidx - boolarray->firstidx;
4962 assert(shift > 0);
4963
4964 assert(0 <= boolarray->minusedidx - boolarray->firstidx - shift);
4965 assert(boolarray->maxusedidx - boolarray->firstidx - shift < boolarray->valssize);
4966 BMSmoveMemoryArray(&(boolarray->vals[boolarray->minusedidx - boolarray->firstidx - shift]),
4967 &(boolarray->vals[boolarray->minusedidx - boolarray->firstidx]),
4968 boolarray->maxusedidx - boolarray->minusedidx + 1); /*lint !e866*/
4969
4970 /* clear the formerly used tail of the array */
4971 for( i = 0; i < shift; ++i )
4972 boolarray->vals[boolarray->maxusedidx - boolarray->firstidx - i] = FALSE;
4973 }
4974 boolarray->firstidx = newfirstidx;
4975 }
4976
4977 assert(minidx >= boolarray->firstidx);
4978 assert(maxidx < boolarray->firstidx + boolarray->valssize);
4979
4980 return SCIP_OKAY;
4981}
4982
4983/** clears a dynamic bool array */
4985 SCIP_BOOLARRAY* boolarray /**< dynamic bool array */
4986 )
4987{
4988 assert(boolarray != NULL);
4989
4990 SCIPdebugMessage("clearing boolarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
4991 (void*)boolarray, boolarray->firstidx, boolarray->valssize, boolarray->minusedidx, boolarray->maxusedidx);
4992
4993 if( boolarray->minusedidx <= boolarray->maxusedidx )
4994 {
4995 assert(boolarray->firstidx <= boolarray->minusedidx);
4996 assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
4997 assert(boolarray->firstidx != -1);
4998 assert(boolarray->valssize > 0);
4999
5000 /* clear the used part of array */
5001 BMSclearMemoryArray(&boolarray->vals[boolarray->minusedidx - boolarray->firstidx],
5002 boolarray->maxusedidx - boolarray->minusedidx + 1); /*lint !e866*/
5003
5004 /* mark the array cleared */
5005 boolarray->minusedidx = INT_MAX;
5006 boolarray->maxusedidx = INT_MIN;
5007 }
5008 assert(boolarray->minusedidx == INT_MAX);
5009 assert(boolarray->maxusedidx == INT_MIN);
5010
5011 return SCIP_OKAY;
5012}
5013
5014/** gets value of entry in dynamic array */
5016 SCIP_BOOLARRAY* boolarray, /**< dynamic bool array */
5017 int idx /**< array index to get value for */
5018 )
5019{
5020 assert(boolarray != NULL);
5021 assert(idx >= 0);
5022
5023 if( idx < boolarray->minusedidx || idx > boolarray->maxusedidx )
5024 return FALSE;
5025 else
5026 {
5027 assert(boolarray->vals != NULL);
5028 assert(idx - boolarray->firstidx >= 0);
5029 assert(idx - boolarray->firstidx < boolarray->valssize);
5030
5031 return boolarray->vals[idx - boolarray->firstidx];
5032 }
5033}
5034
5035/** sets value of entry in dynamic array */
5037 SCIP_BOOLARRAY* boolarray, /**< dynamic bool array */
5038 int arraygrowinit, /**< initial size of array */
5039 SCIP_Real arraygrowfac, /**< growing factor of array */
5040 int idx, /**< array index to set value for */
5041 SCIP_Bool val /**< value to set array index to */
5042 )
5043{
5044 assert(boolarray != NULL);
5045 assert(idx >= 0);
5046
5047 SCIPdebugMessage("setting boolarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %u\n",
5048 (void*)boolarray, boolarray->firstidx, boolarray->valssize, boolarray->minusedidx, boolarray->maxusedidx, idx, val);
5049
5050 if( val != FALSE )
5051 {
5052 /* extend array to be able to store the index */
5053 SCIP_CALL( SCIPboolarrayExtend(boolarray, arraygrowinit, arraygrowfac, idx, idx) );
5054 assert(idx >= boolarray->firstidx);
5055 assert(idx < boolarray->firstidx + boolarray->valssize);
5056
5057 /* set the array value of the index */
5058 boolarray->vals[idx - boolarray->firstidx] = val;
5059
5060 /* update min/maxusedidx */
5061 boolarray->minusedidx = MIN(boolarray->minusedidx, idx);
5062 boolarray->maxusedidx = MAX(boolarray->maxusedidx, idx);
5063 }
5064 else if( idx >= boolarray->firstidx && idx < boolarray->firstidx + boolarray->valssize )
5065 {
5066 /* set the array value of the index to zero */
5067 boolarray->vals[idx - boolarray->firstidx] = FALSE;
5068
5069 /* check, if we can tighten the min/maxusedidx */
5070 if( idx == boolarray->minusedidx )
5071 {
5072 assert(boolarray->maxusedidx >= 0);
5073 assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
5074 do
5075 {
5076 boolarray->minusedidx++;
5077 }
5078 while( boolarray->minusedidx <= boolarray->maxusedidx
5079 && boolarray->vals[boolarray->minusedidx - boolarray->firstidx] == FALSE );
5080 if( boolarray->minusedidx > boolarray->maxusedidx )
5081 {
5082 boolarray->minusedidx = INT_MAX;
5083 boolarray->maxusedidx = INT_MIN;
5084 }
5085 }
5086 else if( idx == boolarray->maxusedidx )
5087 {
5088 assert(boolarray->minusedidx >= 0);
5089 assert(boolarray->minusedidx < boolarray->maxusedidx);
5090 assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
5091 do
5092 {
5093 boolarray->maxusedidx--;
5094 assert(boolarray->minusedidx <= boolarray->maxusedidx);
5095 }
5096 while( boolarray->vals[boolarray->maxusedidx - boolarray->firstidx] == FALSE );
5097 }
5098 }
5099
5100 return SCIP_OKAY;
5101}
5102
5103/** returns the minimal index of all stored non-zero elements */
5105 SCIP_BOOLARRAY* boolarray /**< dynamic bool array */
5106 )
5107{
5108 assert(boolarray != NULL);
5109
5110 return boolarray->minusedidx;
5111}
5112
5113/** returns the maximal index of all stored non-zero elements */
5115 SCIP_BOOLARRAY* boolarray /**< dynamic bool array */
5116 )
5117{
5118 assert(boolarray != NULL);
5119
5120 return boolarray->maxusedidx;
5121}
5122
5123
5124/** creates a dynamic array of pointer values */
5126 SCIP_PTRARRAY** ptrarray, /**< pointer to store the ptr array */
5127 BMS_BLKMEM* blkmem /**< block memory */
5128 )
5129{
5130 assert(ptrarray != NULL);
5131 assert(blkmem != NULL);
5132
5133 SCIP_ALLOC( BMSallocBlockMemory(blkmem, ptrarray) );
5134 (*ptrarray)->blkmem = blkmem;
5135 (*ptrarray)->vals = NULL;
5136 (*ptrarray)->valssize = 0;
5137 (*ptrarray)->firstidx = -1;
5138 (*ptrarray)->minusedidx = INT_MAX;
5139 (*ptrarray)->maxusedidx = INT_MIN;
5140
5141 return SCIP_OKAY;
5142}
5143
5144/** creates a copy of a dynamic array of pointer values */
5146 SCIP_PTRARRAY** ptrarray, /**< pointer to store the copied ptr array */
5147 BMS_BLKMEM* blkmem, /**< block memory */
5148 SCIP_PTRARRAY* sourceptrarray /**< dynamic ptr array to copy */
5149 )
5150{
5151 assert(ptrarray != NULL);
5152 assert(sourceptrarray != NULL);
5153
5154 SCIP_CALL( SCIPptrarrayCreate(ptrarray, blkmem) );
5155 if( sourceptrarray->valssize > 0 )
5156 {
5157 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*ptrarray)->vals, sourceptrarray->vals, sourceptrarray->valssize) );
5158 }
5159 (*ptrarray)->valssize = sourceptrarray->valssize;
5160 (*ptrarray)->firstidx = sourceptrarray->firstidx;
5161 (*ptrarray)->minusedidx = sourceptrarray->minusedidx;
5162 (*ptrarray)->maxusedidx = sourceptrarray->maxusedidx;
5163
5164 return SCIP_OKAY;
5165}
5166
5167/** frees a dynamic array of pointer values */
5169 SCIP_PTRARRAY** ptrarray /**< pointer to the ptr array */
5170 )
5171{
5172 assert(ptrarray != NULL);
5173 assert(*ptrarray != NULL);
5174
5175 BMSfreeBlockMemoryArrayNull((*ptrarray)->blkmem, &(*ptrarray)->vals, (*ptrarray)->valssize);
5176 BMSfreeBlockMemory((*ptrarray)->blkmem, ptrarray);
5177
5178 return SCIP_OKAY;
5179}
5180
5181/** extends dynamic array to be able to store indices from minidx to maxidx */
5183 SCIP_PTRARRAY* ptrarray, /**< dynamic ptr array */
5184 int arraygrowinit, /**< initial size of array */
5185 SCIP_Real arraygrowfac, /**< growing factor of array */
5186 int minidx, /**< smallest index to allocate storage for */
5187 int maxidx /**< largest index to allocate storage for */
5188 )
5189{
5190 int nused;
5191 int nfree;
5192 int newfirstidx;
5193 int i;
5194
5195 assert(ptrarray != NULL);
5196 assert(ptrarray->minusedidx == INT_MAX || ptrarray->firstidx >= 0);
5197 assert(ptrarray->maxusedidx == INT_MIN || ptrarray->firstidx >= 0);
5198 assert(ptrarray->minusedidx == INT_MAX || ptrarray->minusedidx >= ptrarray->firstidx);
5199 assert(ptrarray->maxusedidx == INT_MIN || ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5200 assert(0 <= minidx);
5201 assert(minidx <= maxidx);
5202
5203 minidx = MIN(minidx, ptrarray->minusedidx);
5204 maxidx = MAX(maxidx, ptrarray->maxusedidx);
5205 assert(0 <= minidx);
5206 assert(minidx <= maxidx);
5207
5208 SCIPdebugMessage("extending ptrarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
5209 (void*)ptrarray, ptrarray->firstidx, ptrarray->valssize, ptrarray->minusedidx, ptrarray->maxusedidx, minidx, maxidx);
5210
5211 /* check, whether we have to allocate additional memory, or shift the array */
5212 nused = maxidx - minidx + 1;
5213 if( nused > ptrarray->valssize )
5214 {
5215 void** newvals;
5216 int newvalssize;
5217
5218 /* allocate new memory storage */
5219 newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
5220 SCIP_ALLOC( BMSallocBlockMemoryArray(ptrarray->blkmem, &newvals, newvalssize) );
5221 nfree = newvalssize - nused;
5222 newfirstidx = minidx - nfree/2;
5223 newfirstidx = MAX(newfirstidx, 0);
5224 assert(newfirstidx <= minidx);
5225 assert(maxidx < newfirstidx + newvalssize);
5226
5227 /* initialize memory array by copying old values and setting new values to zero */
5228 if( ptrarray->firstidx != -1 )
5229 {
5230 for( i = 0; i < ptrarray->minusedidx - newfirstidx; ++i )
5231 newvals[i] = NULL;
5232
5233 /* check for possible overflow or negative value */
5234 assert(ptrarray->maxusedidx - ptrarray->minusedidx + 1 > 0);
5235
5236 BMScopyMemoryArray(&newvals[ptrarray->minusedidx - newfirstidx],
5237 &(ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx]),
5238 ptrarray->maxusedidx - ptrarray->minusedidx + 1); /*lint !e866 !e776*/
5239 for( i = ptrarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
5240 newvals[i] = NULL;
5241 }
5242 else
5243 {
5244 for( i = 0; i < newvalssize; ++i )
5245 newvals[i] = NULL;
5246 }
5247
5248 /* free old memory storage, and set the new array parameters */
5249 BMSfreeBlockMemoryArrayNull(ptrarray->blkmem, &ptrarray->vals, ptrarray->valssize);
5250 ptrarray->vals = newvals;
5251 ptrarray->valssize = newvalssize;
5252 ptrarray->firstidx = newfirstidx;
5253 }
5254 else if( ptrarray->firstidx == -1 )
5255 {
5256 /* a sufficiently large memory storage exists, but it was cleared */
5257 nfree = ptrarray->valssize - nused;
5258 assert(nfree >= 0);
5259 ptrarray->firstidx = minidx - nfree/2;
5260 assert(ptrarray->firstidx <= minidx);
5261 assert(maxidx < ptrarray->firstidx + ptrarray->valssize);
5262#ifndef NDEBUG
5263 for( i = 0; i < ptrarray->valssize; ++i )
5264 assert(ptrarray->vals[i] == NULL);
5265#endif
5266 }
5267 else if( minidx < ptrarray->firstidx )
5268 {
5269 /* a sufficiently large memory storage exists, but it has to be shifted to the right */
5270 nfree = ptrarray->valssize - nused;
5271 assert(nfree >= 0);
5272 newfirstidx = minidx - nfree/2;
5273 newfirstidx = MAX(newfirstidx, 0);
5274 assert(newfirstidx <= minidx);
5275 assert(maxidx < newfirstidx + ptrarray->valssize);
5276
5277 if( ptrarray->minusedidx <= ptrarray->maxusedidx )
5278 {
5279 int shift;
5280
5281 assert(ptrarray->firstidx <= ptrarray->minusedidx);
5282 assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5283
5284 /* shift used part of array to the right */
5285 shift = ptrarray->firstidx - newfirstidx;
5286 assert(shift > 0);
5287 for( i = ptrarray->maxusedidx - ptrarray->firstidx; i >= ptrarray->minusedidx - ptrarray->firstidx; --i )
5288 {
5289 assert(0 <= i + shift && i + shift < ptrarray->valssize);
5290 ptrarray->vals[i + shift] = ptrarray->vals[i];
5291 }
5292 /* clear the formerly used head of the array */
5293 for( i = 0; i < shift; ++i )
5294 ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx + i] = NULL;
5295 }
5296 ptrarray->firstidx = newfirstidx;
5297 }
5298 else if( maxidx >= ptrarray->firstidx + ptrarray->valssize )
5299 {
5300 /* a sufficiently large memory storage exists, but it has to be shifted to the left */
5301 nfree = ptrarray->valssize - nused;
5302 assert(nfree >= 0);
5303 newfirstidx = minidx - nfree/2;
5304 newfirstidx = MAX(newfirstidx, 0);
5305 assert(newfirstidx <= minidx);
5306 assert(maxidx < newfirstidx + ptrarray->valssize);
5307
5308 if( ptrarray->minusedidx <= ptrarray->maxusedidx )
5309 {
5310 int shift;
5311
5312 assert(ptrarray->firstidx <= ptrarray->minusedidx);
5313 assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5314
5315 /* shift used part of array to the left */
5316 shift = newfirstidx - ptrarray->firstidx;
5317 assert(shift > 0);
5318 for( i = ptrarray->minusedidx - ptrarray->firstidx; i <= ptrarray->maxusedidx - ptrarray->firstidx; ++i )
5319 {
5320 assert(0 <= i - shift && i - shift < ptrarray->valssize);
5321 ptrarray->vals[i - shift] = ptrarray->vals[i];
5322 }
5323 /* clear the formerly used tail of the array */
5324 for( i = 0; i < shift; ++i )
5325 ptrarray->vals[ptrarray->maxusedidx - ptrarray->firstidx - i] = NULL;
5326 }
5327 ptrarray->firstidx = newfirstidx;
5328 }
5329
5330 assert(minidx >= ptrarray->firstidx);
5331 assert(maxidx < ptrarray->firstidx + ptrarray->valssize);
5332
5333 return SCIP_OKAY;
5334}
5335
5336/** clears a dynamic pointer array */
5338 SCIP_PTRARRAY* ptrarray /**< dynamic ptr array */
5339 )
5340{
5341 assert(ptrarray != NULL);
5342
5343 SCIPdebugMessage("clearing ptrarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
5344 (void*)ptrarray, ptrarray->firstidx, ptrarray->valssize, ptrarray->minusedidx, ptrarray->maxusedidx);
5345
5346 if( ptrarray->minusedidx <= ptrarray->maxusedidx )
5347 {
5348 assert(ptrarray->firstidx <= ptrarray->minusedidx);
5349 assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5350 assert(ptrarray->firstidx != -1);
5351 assert(ptrarray->valssize > 0);
5352
5353 /* clear the used part of array */
5354 BMSclearMemoryArray(&ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx],
5355 ptrarray->maxusedidx - ptrarray->minusedidx + 1); /*lint !e866*/
5356
5357 /* mark the array cleared */
5358 ptrarray->minusedidx = INT_MAX;
5359 ptrarray->maxusedidx = INT_MIN;
5360 }
5361 assert(ptrarray->minusedidx == INT_MAX);
5362 assert(ptrarray->maxusedidx == INT_MIN);
5363
5364 return SCIP_OKAY;
5365}
5366
5367/** gets value of entry in dynamic array */
5369 SCIP_PTRARRAY* ptrarray, /**< dynamic ptr array */
5370 int idx /**< array index to get value for */
5371 )
5372{
5373 assert(ptrarray != NULL);
5374 assert(idx >= 0);
5375
5376 if( idx < ptrarray->minusedidx || idx > ptrarray->maxusedidx )
5377 return NULL;
5378 else
5379 {
5380 assert(ptrarray->vals != NULL);
5381 assert(idx - ptrarray->firstidx >= 0);
5382 assert(idx - ptrarray->firstidx < ptrarray->valssize);
5383
5384 return ptrarray->vals[idx - ptrarray->firstidx];
5385 }
5386}
5387
5388/** sets value of entry in dynamic array */
5390 SCIP_PTRARRAY* ptrarray, /**< dynamic ptr array */
5391 int arraygrowinit, /**< initial size of array */
5392 SCIP_Real arraygrowfac, /**< growing factor of array */
5393 int idx, /**< array index to set value for */
5394 void* val /**< value to set array index to */
5395 )
5396{
5397 assert(ptrarray != NULL);
5398 assert(idx >= 0);
5399
5400 SCIPdebugMessage("setting ptrarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %p\n",
5401 (void*)ptrarray, ptrarray->firstidx, ptrarray->valssize, ptrarray->minusedidx, ptrarray->maxusedidx, idx, val);
5402
5403 if( val != NULL )
5404 {
5405 /* extend array to be able to store the index */
5406 SCIP_CALL( SCIPptrarrayExtend(ptrarray, arraygrowinit, arraygrowfac, idx, idx) );
5407 assert(idx >= ptrarray->firstidx);
5408 assert(idx < ptrarray->firstidx + ptrarray->valssize);
5409
5410 /* set the array value of the index */
5411 ptrarray->vals[idx - ptrarray->firstidx] = val;
5412
5413 /* update min/maxusedidx */
5414 ptrarray->minusedidx = MIN(ptrarray->minusedidx, idx);
5415 ptrarray->maxusedidx = MAX(ptrarray->maxusedidx, idx);
5416 }
5417 else if( idx >= ptrarray->firstidx && idx < ptrarray->firstidx + ptrarray->valssize )
5418 {
5419 /* set the array value of the index to zero */
5420 ptrarray->vals[idx - ptrarray->firstidx] = NULL;
5421
5422 /* check, if we can tighten the min/maxusedidx */
5423 if( idx == ptrarray->minusedidx )
5424 {
5425 assert(ptrarray->maxusedidx >= 0);
5426 assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5427 do
5428 {
5429 ptrarray->minusedidx++;
5430 }
5431 while( ptrarray->minusedidx <= ptrarray->maxusedidx
5432 && ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx] == NULL );
5433 if( ptrarray->minusedidx > ptrarray->maxusedidx )
5434 {
5435 ptrarray->minusedidx = INT_MAX;
5436 ptrarray->maxusedidx = INT_MIN;
5437 }
5438 }
5439 else if( idx == ptrarray->maxusedidx )
5440 {
5441 assert(ptrarray->minusedidx >= 0);
5442 assert(ptrarray->minusedidx < ptrarray->maxusedidx);
5443 assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5444 do
5445 {
5446 ptrarray->maxusedidx--;
5447 assert(ptrarray->minusedidx <= ptrarray->maxusedidx);
5448 }
5449 while( ptrarray->vals[ptrarray->maxusedidx - ptrarray->firstidx] == NULL );
5450 }
5451 }
5452
5453 return SCIP_OKAY;
5454}
5455
5456/** returns the minimal index of all stored non-zero elements */
5458 SCIP_PTRARRAY* ptrarray /**< dynamic ptr array */
5459 )
5460{
5461 assert(ptrarray != NULL);
5462
5463 return ptrarray->minusedidx;
5464}
5465
5466/** returns the maximal index of all stored non-zero elements */
5468 SCIP_PTRARRAY* ptrarray /**< dynamic ptr array */
5469 )
5470{
5471 assert(ptrarray != NULL);
5472
5473 return ptrarray->maxusedidx;
5474}
5475
5476
5477/*
5478 * Sorting algorithms
5479 */
5480
5481/** default comparer for integers */
5483{
5484 int value1;
5485 int value2;
5486
5487 value1 = (int)(size_t)elem1;
5488 value2 = (int)(size_t)elem2;
5489
5490 if( value1 < value2 )
5491 return -1;
5492
5493 if( value2 < value1 )
5494 return 1;
5495
5496 return 0;
5497}
5498
5499/** implements argsort
5500 *
5501 * The data pointer is a lookup array of integers.
5502 */
5503SCIP_DECL_SORTINDCOMP(SCIPsortArgsortInt)
5504{
5505 int* args;
5506 args = (int*) dataptr;
5507
5508 if( args[ind1] < args[ind2] )
5509 return -1;
5510
5511 if( args[ind1] > args[ind2] )
5512 return 1;
5513
5514 return 0;
5515}
5516
5517
5518/** implements argsort
5519 *
5520 * The data pointer is a lookup array, which are pointer arrays.
5521 */
5522SCIP_DECL_SORTINDCOMP(SCIPsortArgsortPtr)
5523{
5524 void** args;
5525 args = (void*) dataptr;
5526
5527 if( args[ind1] < args[ind2] )
5528 return -1;
5529
5530 if( args[ind1] > args[ind2] )
5531 return 1;
5532
5533 return 0;
5534}
5535
5536
5537/* first all upwards-sorting methods */
5538
5539/** sort an indexed element set in non-decreasing order, resulting in a permutation index array */
5541 int* perm, /**< pointer to store the resulting permutation */
5542 SCIP_DECL_SORTINDCOMP((*indcomp)), /**< data element comparator */
5543 void* dataptr, /**< pointer to data field that is given to the external compare method */
5544 int len /**< number of elements to be sorted (valid index range) */
5545 )
5546{
5547 int pos;
5548
5549 assert(indcomp != NULL);
5550 assert(len == 0 || perm != NULL);
5551
5552 /* create identity permutation */
5553 for( pos = 0; pos < len; ++pos )
5554 perm[pos] = pos;
5555
5556 SCIPsortInd(perm, indcomp, dataptr, len);
5557}
5558
5559/* SCIPsortInd(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5560#define SORTTPL_NAMEEXT Ind
5561#define SORTTPL_KEYTYPE int
5562#define SORTTPL_INDCOMP
5563#include "scip/sorttpl.c" /*lint !e451*/
5564
5565
5566/* SCIPsortPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5567#define SORTTPL_NAMEEXT Ptr
5568#define SORTTPL_KEYTYPE void*
5569#define SORTTPL_PTRCOMP
5570#include "scip/sorttpl.c" /*lint !e451*/
5571
5572
5573/* SCIPsortPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5574#define SORTTPL_NAMEEXT PtrPtr
5575#define SORTTPL_KEYTYPE void*
5576#define SORTTPL_FIELD1TYPE void*
5577#define SORTTPL_PTRCOMP
5578#include "scip/sorttpl.c" /*lint !e451*/
5579
5580
5581/* SCIPsortPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5582#define SORTTPL_NAMEEXT PtrReal
5583#define SORTTPL_KEYTYPE void*
5584#define SORTTPL_FIELD1TYPE SCIP_Real
5585#define SORTTPL_PTRCOMP
5586#include "scip/sorttpl.c" /*lint !e451*/
5587
5588
5589/* SCIPsortPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5590#define SORTTPL_NAMEEXT PtrInt
5591#define SORTTPL_KEYTYPE void*
5592#define SORTTPL_FIELD1TYPE int
5593#define SORTTPL_PTRCOMP
5594#include "scip/sorttpl.c" /*lint !e451*/
5595
5596
5597/* SCIPsortPtrBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5598#define SORTTPL_NAMEEXT PtrBool
5599#define SORTTPL_KEYTYPE void*
5600#define SORTTPL_FIELD1TYPE SCIP_Bool
5601#define SORTTPL_PTRCOMP
5602#include "scip/sorttpl.c" /*lint !e451*/
5603
5604
5605/* SCIPsortPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5606#define SORTTPL_NAMEEXT PtrIntInt
5607#define SORTTPL_KEYTYPE void*
5608#define SORTTPL_FIELD1TYPE int
5609#define SORTTPL_FIELD2TYPE int
5610#define SORTTPL_PTRCOMP
5611#include "scip/sorttpl.c" /*lint !e451*/
5612
5613
5614/* SCIPsortPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5615#define SORTTPL_NAMEEXT PtrRealInt
5616#define SORTTPL_KEYTYPE void*
5617#define SORTTPL_FIELD1TYPE SCIP_Real
5618#define SORTTPL_FIELD2TYPE int
5619#define SORTTPL_PTRCOMP
5620#include "scip/sorttpl.c" /*lint !e451*/
5621
5622/* SCIPsortPtrRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5623#define SORTTPL_NAMEEXT PtrRealRealInt
5624#define SORTTPL_KEYTYPE void*
5625#define SORTTPL_FIELD1TYPE SCIP_Real
5626#define SORTTPL_FIELD2TYPE SCIP_Real
5627#define SORTTPL_FIELD3TYPE int
5628#define SORTTPL_PTRCOMP
5629#include "scip/sorttpl.c" /*lint !e451*/
5630
5631/* SCIPsortPtrRealRealBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5632#define SORTTPL_NAMEEXT PtrRealRealBoolBool
5633#define SORTTPL_KEYTYPE void*
5634#define SORTTPL_FIELD1TYPE SCIP_Real
5635#define SORTTPL_FIELD2TYPE SCIP_Real
5636#define SORTTPL_FIELD3TYPE SCIP_Bool
5637#define SORTTPL_FIELD4TYPE SCIP_Bool
5638#define SORTTPL_PTRCOMP
5639#include "scip/sorttpl.c" /*lint !e451*/
5640
5641/* SCIPsortPtrRealRealIntBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5642#define SORTTPL_NAMEEXT PtrRealRealIntBool
5643#define SORTTPL_KEYTYPE void*
5644#define SORTTPL_FIELD1TYPE SCIP_Real
5645#define SORTTPL_FIELD2TYPE SCIP_Real
5646#define SORTTPL_FIELD3TYPE int
5647#define SORTTPL_FIELD4TYPE SCIP_Bool
5648#define SORTTPL_PTRCOMP
5649#include "scip/sorttpl.c" /*lint !e451*/
5650
5651/* SCIPsortPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5652#define SORTTPL_NAMEEXT PtrRealBool
5653#define SORTTPL_KEYTYPE void*
5654#define SORTTPL_FIELD1TYPE SCIP_Real
5655#define SORTTPL_FIELD2TYPE SCIP_Bool
5656#define SORTTPL_PTRCOMP
5657#include "scip/sorttpl.c" /*lint !e451*/
5658
5659
5660/* SCIPsortPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5661#define SORTTPL_NAMEEXT PtrPtrInt
5662#define SORTTPL_KEYTYPE void*
5663#define SORTTPL_FIELD1TYPE void*
5664#define SORTTPL_FIELD2TYPE int
5665#define SORTTPL_PTRCOMP
5666#include "scip/sorttpl.c" /*lint !e451*/
5667
5668
5669/* SCIPsortPtrPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5670#define SORTTPL_NAMEEXT PtrPtrReal
5671#define SORTTPL_KEYTYPE void*
5672#define SORTTPL_FIELD1TYPE void*
5673#define SORTTPL_FIELD2TYPE SCIP_Real
5674#define SORTTPL_PTRCOMP
5675#include "scip/sorttpl.c" /*lint !e451*/
5676
5677
5678/* SCIPsortPtrRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5679#define SORTTPL_NAMEEXT PtrRealIntInt
5680#define SORTTPL_KEYTYPE void*
5681#define SORTTPL_FIELD1TYPE SCIP_Real
5682#define SORTTPL_FIELD2TYPE int
5683#define SORTTPL_FIELD3TYPE int
5684#define SORTTPL_PTRCOMP
5685#include "scip/sorttpl.c" /*lint !e451*/
5686
5687
5688/* SCIPsortPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5689#define SORTTPL_NAMEEXT PtrPtrIntInt
5690#define SORTTPL_KEYTYPE void*
5691#define SORTTPL_FIELD1TYPE void*
5692#define SORTTPL_FIELD2TYPE int
5693#define SORTTPL_FIELD3TYPE int
5694#define SORTTPL_PTRCOMP
5695#include "scip/sorttpl.c" /*lint !e451*/
5696
5697
5698/* SCIPsortPtrPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5699#define SORTTPL_NAMEEXT PtrPtrRealInt
5700#define SORTTPL_KEYTYPE void*
5701#define SORTTPL_FIELD1TYPE void*
5702#define SORTTPL_FIELD2TYPE SCIP_Real
5703#define SORTTPL_FIELD3TYPE int
5704#define SORTTPL_PTRCOMP
5705#include "scip/sorttpl.c" /*lint !e451*/
5706
5707
5708/* SCIPsortPtrPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5709#define SORTTPL_NAMEEXT PtrPtrRealBool
5710#define SORTTPL_KEYTYPE void*
5711#define SORTTPL_FIELD1TYPE void*
5712#define SORTTPL_FIELD2TYPE SCIP_Real
5713#define SORTTPL_FIELD3TYPE SCIP_Bool
5714#define SORTTPL_PTRCOMP
5715#include "scip/sorttpl.c" /*lint !e451*/
5716
5717
5718/* SCIPsortPtrPtrLongInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5719#define SORTTPL_NAMEEXT PtrPtrLongInt
5720#define SORTTPL_KEYTYPE void*
5721#define SORTTPL_FIELD1TYPE void*
5722#define SORTTPL_FIELD2TYPE SCIP_Longint
5723#define SORTTPL_FIELD3TYPE int
5724#define SORTTPL_PTRCOMP
5725#include "scip/sorttpl.c" /*lint !e451*/
5726
5727
5728/* SCIPsortPtrPtrLongIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5729#define SORTTPL_NAMEEXT PtrPtrLongIntInt
5730#define SORTTPL_KEYTYPE void*
5731#define SORTTPL_FIELD1TYPE void*
5732#define SORTTPL_FIELD2TYPE SCIP_Longint
5733#define SORTTPL_FIELD3TYPE int
5734#define SORTTPL_FIELD4TYPE int
5735#define SORTTPL_PTRCOMP
5736#include "scip/sorttpl.c" /*lint !e451*/
5737
5738
5739/* SCIPsortReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5740#define SORTTPL_NAMEEXT Real
5741#define SORTTPL_KEYTYPE SCIP_Real
5742#include "scip/sorttpl.c" /*lint !e451*/
5743
5744
5745/* SCIPsortRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5746#define SORTTPL_NAMEEXT RealBoolPtr
5747#define SORTTPL_KEYTYPE SCIP_Real
5748#define SORTTPL_FIELD1TYPE SCIP_Bool
5749#define SORTTPL_FIELD2TYPE void*
5750#include "scip/sorttpl.c" /*lint !e451*/
5751
5752
5753/* SCIPsortRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5754#define SORTTPL_NAMEEXT RealPtr
5755#define SORTTPL_KEYTYPE SCIP_Real
5756#define SORTTPL_FIELD1TYPE void*
5757#include "scip/sorttpl.c" /*lint !e451*/
5758
5759
5760/* SCIPsortRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5761#define SORTTPL_NAMEEXT RealInt
5762#define SORTTPL_KEYTYPE SCIP_Real
5763#define SORTTPL_FIELD1TYPE int
5764#include "scip/sorttpl.c" /*lint !e451*/
5765
5766
5767/* SCIPsortRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5768#define SORTTPL_NAMEEXT RealIntInt
5769#define SORTTPL_KEYTYPE SCIP_Real
5770#define SORTTPL_FIELD1TYPE int
5771#define SORTTPL_FIELD2TYPE int
5772#include "scip/sorttpl.c" /*lint !e451*/
5773
5774
5775/* SCIPsortRealIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5776#define SORTTPL_NAMEEXT RealIntLong
5777#define SORTTPL_KEYTYPE SCIP_Real
5778#define SORTTPL_FIELD1TYPE int
5779#define SORTTPL_FIELD2TYPE SCIP_Longint
5780#include "scip/sorttpl.c" /*lint !e451*/
5781
5782
5783/* SCIPsortRealIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5784#define SORTTPL_NAMEEXT RealIntPtr
5785#define SORTTPL_KEYTYPE SCIP_Real
5786#define SORTTPL_FIELD1TYPE int
5787#define SORTTPL_FIELD2TYPE void*
5788#include "scip/sorttpl.c" /*lint !e451*/
5789
5790
5791/* SCIPsortRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5792#define SORTTPL_NAMEEXT RealRealPtr
5793#define SORTTPL_KEYTYPE SCIP_Real
5794#define SORTTPL_FIELD1TYPE SCIP_Real
5795#define SORTTPL_FIELD2TYPE void*
5796#include "scip/sorttpl.c" /*lint !e451*/
5797
5798
5799/* SCIPsortRealLongRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5800#define SORTTPL_NAMEEXT RealLongRealInt
5801#define SORTTPL_KEYTYPE SCIP_Real
5802#define SORTTPL_FIELD1TYPE SCIP_Longint
5803#define SORTTPL_FIELD2TYPE SCIP_Real
5804#define SORTTPL_FIELD3TYPE int
5805#include "scip/sorttpl.c" /*lint !e451*/
5806
5807/* SCIPsortRealRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5808#define SORTTPL_NAMEEXT RealRealIntInt
5809#define SORTTPL_KEYTYPE SCIP_Real
5810#define SORTTPL_FIELD1TYPE SCIP_Real
5811#define SORTTPL_FIELD2TYPE int
5812#define SORTTPL_FIELD3TYPE int
5813#include "scip/sorttpl.c" /*lint !e451*/
5814
5815
5816/* SCIPsortRealRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5817#define SORTTPL_NAMEEXT RealRealRealInt
5818#define SORTTPL_KEYTYPE SCIP_Real
5819#define SORTTPL_FIELD1TYPE SCIP_Real
5820#define SORTTPL_FIELD2TYPE SCIP_Real
5821#define SORTTPL_FIELD3TYPE int
5822#include "scip/sorttpl.c" /*lint !e451*/
5823
5824
5825/* SCIPsortRealRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5826#define SORTTPL_NAMEEXT RealRealRealPtr
5827#define SORTTPL_KEYTYPE SCIP_Real
5828#define SORTTPL_FIELD1TYPE SCIP_Real
5829#define SORTTPL_FIELD2TYPE SCIP_Real
5830#define SORTTPL_FIELD3TYPE void*
5831#include "scip/sorttpl.c" /*lint !e451*/
5832
5833
5834/* SCIPsortRealPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5835#define SORTTPL_NAMEEXT RealPtrPtrInt
5836#define SORTTPL_KEYTYPE SCIP_Real
5837#define SORTTPL_FIELD1TYPE void*
5838#define SORTTPL_FIELD2TYPE void*
5839#define SORTTPL_FIELD3TYPE int
5840#include "scip/sorttpl.c" /*lint !e451*/
5841
5842
5843/* SCIPsortRealPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5844#define SORTTPL_NAMEEXT RealPtrPtrIntInt
5845#define SORTTPL_KEYTYPE SCIP_Real
5846#define SORTTPL_FIELD1TYPE void*
5847#define SORTTPL_FIELD2TYPE void*
5848#define SORTTPL_FIELD3TYPE int
5849#define SORTTPL_FIELD4TYPE int
5850#include "scip/sorttpl.c" /*lint !e451*/
5851
5852
5853/* SCIPsortRealRealRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5854#define SORTTPL_NAMEEXT RealRealRealBoolPtr
5855#define SORTTPL_KEYTYPE SCIP_Real
5856#define SORTTPL_FIELD1TYPE SCIP_Real
5857#define SORTTPL_FIELD2TYPE SCIP_Real
5858#define SORTTPL_FIELD3TYPE SCIP_Bool
5859#define SORTTPL_FIELD4TYPE void*
5860#include "scip/sorttpl.c" /*lint !e451*/
5861
5862
5863/* SCIPsortRealRealRealBoolBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5864#define SORTTPL_NAMEEXT RealRealRealBoolBoolPtr
5865#define SORTTPL_KEYTYPE SCIP_Real
5866#define SORTTPL_FIELD1TYPE SCIP_Real
5867#define SORTTPL_FIELD2TYPE SCIP_Real
5868#define SORTTPL_FIELD3TYPE SCIP_Bool
5869#define SORTTPL_FIELD4TYPE SCIP_Bool
5870#define SORTTPL_FIELD5TYPE void*
5871#include "scip/sorttpl.c" /*lint !e451*/
5872
5873
5874/* SCIPsortInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5875#define SORTTPL_NAMEEXT Int
5876#define SORTTPL_KEYTYPE int
5877#include "scip/sorttpl.c" /*lint !e451*/
5878
5879
5880/* SCIPsortIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5881#define SORTTPL_NAMEEXT IntInt
5882#define SORTTPL_KEYTYPE int
5883#define SORTTPL_FIELD1TYPE int
5884#include "scip/sorttpl.c" /*lint !e451*/
5885
5886
5887/* SCIPsortIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5888#define SORTTPL_NAMEEXT IntReal
5889#define SORTTPL_KEYTYPE int
5890#define SORTTPL_FIELD1TYPE SCIP_Real
5891#include "scip/sorttpl.c" /*lint !e451*/
5892
5893
5894/* SCIPsortIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5895#define SORTTPL_NAMEEXT IntPtr
5896#define SORTTPL_KEYTYPE int
5897#define SORTTPL_FIELD1TYPE void*
5898#include "scip/sorttpl.c" /*lint !e451*/
5899
5900
5901/* SCIPsortIntIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5902#define SORTTPL_NAMEEXT IntIntInt
5903#define SORTTPL_KEYTYPE int
5904#define SORTTPL_FIELD1TYPE int
5905#define SORTTPL_FIELD2TYPE int
5906#include "scip/sorttpl.c" /*lint !e451*/
5907
5908
5909/* SCIPsortIntIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5910#define SORTTPL_NAMEEXT IntIntLong
5911#define SORTTPL_KEYTYPE int
5912#define SORTTPL_FIELD1TYPE int
5913#define SORTTPL_FIELD2TYPE SCIP_Longint
5914#include "scip/sorttpl.c" /*lint !e451*/
5915
5916/* SCIPsortIntRealLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5917#define SORTTPL_NAMEEXT IntRealLong
5918#define SORTTPL_KEYTYPE int
5919#define SORTTPL_FIELD1TYPE SCIP_Real
5920#define SORTTPL_FIELD2TYPE SCIP_Longint
5921#include "scip/sorttpl.c" /*lint !e451*/
5922
5923
5924/* SCIPsortIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5925#define SORTTPL_NAMEEXT IntIntPtr
5926#define SORTTPL_KEYTYPE int
5927#define SORTTPL_FIELD1TYPE int
5928#define SORTTPL_FIELD2TYPE void*
5929#include "scip/sorttpl.c" /*lint !e451*/
5930
5931
5932/* SCIPsortIntIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5933#define SORTTPL_NAMEEXT IntIntReal
5934#define SORTTPL_KEYTYPE int
5935#define SORTTPL_FIELD1TYPE int
5936#define SORTTPL_FIELD2TYPE SCIP_Real
5937#include "scip/sorttpl.c" /*lint !e451*/
5938
5939
5940/* SCIPsortIntPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5941#define SORTTPL_NAMEEXT IntPtrReal
5942#define SORTTPL_KEYTYPE int
5943#define SORTTPL_FIELD1TYPE void*
5944#define SORTTPL_FIELD2TYPE SCIP_Real
5945#include "scip/sorttpl.c" /*lint !e451*/
5946
5947
5948/* SCIPsortIntIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5949#define SORTTPL_NAMEEXT IntIntIntPtr
5950#define SORTTPL_KEYTYPE int
5951#define SORTTPL_FIELD1TYPE int
5952#define SORTTPL_FIELD2TYPE int
5953#define SORTTPL_FIELD3TYPE void*
5954#include "scip/sorttpl.c" /*lint !e451*/
5955
5956/* SCIPsortIntIntIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5957#define SORTTPL_NAMEEXT IntIntIntReal
5958#define SORTTPL_KEYTYPE int
5959#define SORTTPL_FIELD1TYPE int
5960#define SORTTPL_FIELD2TYPE int
5961#define SORTTPL_FIELD3TYPE SCIP_Real
5962#include "scip/sorttpl.c" /*lint !e451*/
5963
5964/* SCIPsortIntPtrIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5965#define SORTTPL_NAMEEXT IntPtrIntReal
5966#define SORTTPL_KEYTYPE int
5967#define SORTTPL_FIELD1TYPE void*
5968#define SORTTPL_FIELD2TYPE int
5969#define SORTTPL_FIELD3TYPE SCIP_Real
5970#include "scip/sorttpl.c" /*lint !e451*/
5971
5972
5973/* SCIPsortLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5974#define SORTTPL_NAMEEXT Long
5975#define SORTTPL_KEYTYPE SCIP_Longint
5976#include "scip/sorttpl.c" /*lint !e451*/
5977
5978
5979/* SCIPsortLongPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5980#define SORTTPL_NAMEEXT LongPtr
5981#define SORTTPL_KEYTYPE SCIP_Longint
5982#define SORTTPL_FIELD1TYPE void*
5983#include "scip/sorttpl.c" /*lint !e451*/
5984
5985
5986/* SCIPsortLongPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5987#define SORTTPL_NAMEEXT LongPtrInt
5988#define SORTTPL_KEYTYPE SCIP_Longint
5989#define SORTTPL_FIELD1TYPE void*
5990#define SORTTPL_FIELD2TYPE int
5991#include "scip/sorttpl.c" /*lint !e451*/
5992
5993
5994/* SCIPsortLongPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5995#define SORTTPL_NAMEEXT LongPtrRealBool
5996#define SORTTPL_KEYTYPE SCIP_Longint
5997#define SORTTPL_FIELD1TYPE void*
5998#define SORTTPL_FIELD2TYPE SCIP_Real
5999#define SORTTPL_FIELD3TYPE SCIP_Bool
6000#include "scip/sorttpl.c" /*lint !e451*/
6001
6002
6003/* SCIPsortLongPtrRealRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6004#define SORTTPL_NAMEEXT LongPtrRealRealBool
6005#define SORTTPL_KEYTYPE SCIP_Longint
6006#define SORTTPL_FIELD1TYPE void*
6007#define SORTTPL_FIELD2TYPE SCIP_Real
6008#define SORTTPL_FIELD3TYPE SCIP_Real
6009#define SORTTPL_FIELD4TYPE SCIP_Bool
6010#include "scip/sorttpl.c" /*lint !e451*/
6011
6012
6013/* SCIPsortLongPtrRealRealIntBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6014#define SORTTPL_NAMEEXT LongPtrRealRealIntBool
6015#define SORTTPL_KEYTYPE SCIP_Longint
6016#define SORTTPL_FIELD1TYPE void*
6017#define SORTTPL_FIELD2TYPE SCIP_Real
6018#define SORTTPL_FIELD3TYPE SCIP_Real
6019#define SORTTPL_FIELD4TYPE int
6020#define SORTTPL_FIELD5TYPE SCIP_Bool
6021#include "scip/sorttpl.c" /*lint !e451*/
6022
6023
6024/* SCIPsortLongPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6025#define SORTTPL_NAMEEXT LongPtrPtrInt
6026#define SORTTPL_KEYTYPE SCIP_Longint
6027#define SORTTPL_FIELD1TYPE void*
6028#define SORTTPL_FIELD2TYPE void*
6029#define SORTTPL_FIELD3TYPE int
6030#include "scip/sorttpl.c" /*lint !e451*/
6031
6032
6033/* SCIPsortLongPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6034#define SORTTPL_NAMEEXT LongPtrPtrIntInt
6035#define SORTTPL_KEYTYPE SCIP_Longint
6036#define SORTTPL_FIELD1TYPE void*
6037#define SORTTPL_FIELD2TYPE void*
6038#define SORTTPL_FIELD3TYPE int
6039#define SORTTPL_FIELD4TYPE int
6040#include "scip/sorttpl.c" /*lint !e451*/
6041
6042
6043/* SCIPsortLongPtrPtrBoolInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6044#define SORTTPL_NAMEEXT LongPtrPtrBoolInt
6045#define SORTTPL_KEYTYPE SCIP_Longint
6046#define SORTTPL_FIELD1TYPE void*
6047#define SORTTPL_FIELD2TYPE void*
6048#define SORTTPL_FIELD3TYPE SCIP_Bool
6049#define SORTTPL_FIELD4TYPE int
6050#include "scip/sorttpl.c" /*lint !e451*/
6051
6052
6053/* SCIPsortPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6054#define SORTTPL_NAMEEXT PtrIntIntBoolBool
6055#define SORTTPL_KEYTYPE void*
6056#define SORTTPL_FIELD1TYPE int
6057#define SORTTPL_FIELD2TYPE int
6058#define SORTTPL_FIELD3TYPE SCIP_Bool
6059#define SORTTPL_FIELD4TYPE SCIP_Bool
6060#define SORTTPL_PTRCOMP
6061#include "scip/sorttpl.c" /*lint !e451*/
6062
6063
6064/* SCIPsortIntPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6065#define SORTTPL_NAMEEXT IntPtrIntIntBoolBool
6066#define SORTTPL_KEYTYPE int
6067#define SORTTPL_FIELD1TYPE void*
6068#define SORTTPL_FIELD2TYPE int
6069#define SORTTPL_FIELD3TYPE int
6070#define SORTTPL_FIELD4TYPE SCIP_Bool
6071#define SORTTPL_FIELD5TYPE SCIP_Bool
6072#include "scip/sorttpl.c" /*lint !e451*/
6073
6074
6075/* now all downwards-sorting methods */
6076
6077
6078/** sort an indexed element set in non-increasing order, resulting in a permutation index array */
6080 int* perm, /**< pointer to store the resulting permutation */
6081 SCIP_DECL_SORTINDCOMP((*indcomp)), /**< data element comparator */
6082 void* dataptr, /**< pointer to data field that is given to the external compare method */
6083 int len /**< number of elements to be sorted (valid index range) */
6084 )
6085{
6086 int pos;
6087
6088 assert(indcomp != NULL);
6089 assert(len == 0 || perm != NULL);
6090
6091 /* create identity permutation */
6092 for( pos = 0; pos < len; ++pos )
6093 perm[pos] = pos;
6094
6095 SCIPsortDownInd(perm, indcomp, dataptr, len);
6096}
6097
6098
6099/* SCIPsortDownInd(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6100#define SORTTPL_NAMEEXT DownInd
6101#define SORTTPL_KEYTYPE int
6102#define SORTTPL_INDCOMP
6103#define SORTTPL_BACKWARDS
6104#include "scip/sorttpl.c" /*lint !e451*/
6105
6106
6107/* SCIPsortDownPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6108#define SORTTPL_NAMEEXT DownPtr
6109#define SORTTPL_KEYTYPE void*
6110#define SORTTPL_PTRCOMP
6111#define SORTTPL_BACKWARDS
6112#include "scip/sorttpl.c" /*lint !e451*/
6113
6114
6115/* SCIPsortDownPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6116#define SORTTPL_NAMEEXT DownPtrPtr
6117#define SORTTPL_KEYTYPE void*
6118#define SORTTPL_FIELD1TYPE void*
6119#define SORTTPL_PTRCOMP
6120#define SORTTPL_BACKWARDS
6121#include "scip/sorttpl.c" /*lint !e451*/
6122
6123
6124/* SCIPsortDownPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6125#define SORTTPL_NAMEEXT DownPtrReal
6126#define SORTTPL_KEYTYPE void*
6127#define SORTTPL_FIELD1TYPE SCIP_Real
6128#define SORTTPL_PTRCOMP
6129#define SORTTPL_BACKWARDS
6130#include "scip/sorttpl.c" /*lint !e451*/
6131
6132
6133/* SCIPsortDownPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6134#define SORTTPL_NAMEEXT DownPtrInt
6135#define SORTTPL_KEYTYPE void*
6136#define SORTTPL_FIELD1TYPE int
6137#define SORTTPL_PTRCOMP
6138#define SORTTPL_BACKWARDS
6139#include "scip/sorttpl.c" /*lint !e451*/
6140
6141/* SCIPsortDownPtrBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6142#define SORTTPL_NAMEEXT DownPtrBool
6143#define SORTTPL_KEYTYPE void*
6144#define SORTTPL_FIELD1TYPE SCIP_Bool
6145#define SORTTPL_PTRCOMP
6146#define SORTTPL_BACKWARDS
6147#include "scip/sorttpl.c" /*lint !e451*/
6148
6149/* SCIPsortDownPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6150#define SORTTPL_NAMEEXT DownPtrIntInt
6151#define SORTTPL_KEYTYPE void*
6152#define SORTTPL_FIELD1TYPE int
6153#define SORTTPL_FIELD2TYPE int
6154#define SORTTPL_PTRCOMP
6155#define SORTTPL_BACKWARDS
6156#include "scip/sorttpl.c" /*lint !e451*/
6157
6158
6159/* SCIPsortDownPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6160#define SORTTPL_NAMEEXT DownPtrRealInt
6161#define SORTTPL_KEYTYPE void*
6162#define SORTTPL_FIELD1TYPE SCIP_Real
6163#define SORTTPL_FIELD2TYPE int
6164#define SORTTPL_PTRCOMP
6165#define SORTTPL_BACKWARDS
6166#include "scip/sorttpl.c" /*lint !e451*/
6167
6168
6169/* SCIPsortDownPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6170#define SORTTPL_NAMEEXT DownPtrRealBool
6171#define SORTTPL_KEYTYPE void*
6172#define SORTTPL_FIELD1TYPE SCIP_Real
6173#define SORTTPL_FIELD2TYPE SCIP_Bool
6174#define SORTTPL_PTRCOMP
6175#define SORTTPL_BACKWARDS
6176#include "scip/sorttpl.c" /*lint !e451*/
6177
6178
6179/* SCIPsortDownPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6180#define SORTTPL_NAMEEXT DownPtrPtrInt
6181#define SORTTPL_KEYTYPE void*
6182#define SORTTPL_FIELD1TYPE void*
6183#define SORTTPL_FIELD2TYPE int
6184#define SORTTPL_PTRCOMP
6185#define SORTTPL_BACKWARDS
6186#include "scip/sorttpl.c" /*lint !e451*/
6187
6188
6189/* SCIPsortDownPtrPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6190#define SORTTPL_NAMEEXT DownPtrPtrReal
6191#define SORTTPL_KEYTYPE void*
6192#define SORTTPL_FIELD1TYPE void*
6193#define SORTTPL_FIELD2TYPE SCIP_Real
6194#define SORTTPL_PTRCOMP
6195#define SORTTPL_BACKWARDS
6196#include "scip/sorttpl.c" /*lint !e451*/
6197
6198
6199/* SCIPsortDownPtrRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6200#define SORTTPL_NAMEEXT DownPtrRealIntInt
6201#define SORTTPL_KEYTYPE void*
6202#define SORTTPL_FIELD1TYPE SCIP_Real
6203#define SORTTPL_FIELD2TYPE int
6204#define SORTTPL_FIELD3TYPE int
6205#define SORTTPL_PTRCOMP
6206#define SORTTPL_BACKWARDS
6207#include "scip/sorttpl.c" /*lint !e451*/
6208
6209
6210/* SCIPsortDownPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6211#define SORTTPL_NAMEEXT DownPtrPtrIntInt
6212#define SORTTPL_KEYTYPE void*
6213#define SORTTPL_FIELD1TYPE void*
6214#define SORTTPL_FIELD2TYPE int
6215#define SORTTPL_FIELD3TYPE int
6216#define SORTTPL_PTRCOMP
6217#define SORTTPL_BACKWARDS
6218#include "scip/sorttpl.c" /*lint !e451*/
6219
6220
6221/* SCIPsortDownPtrPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6222#define SORTTPL_NAMEEXT DownPtrPtrRealInt
6223#define SORTTPL_KEYTYPE void*
6224#define SORTTPL_FIELD1TYPE void*
6225#define SORTTPL_FIELD2TYPE SCIP_Real
6226#define SORTTPL_FIELD3TYPE int
6227#define SORTTPL_PTRCOMP
6228#define SORTTPL_BACKWARDS
6229#include "scip/sorttpl.c" /*lint !e451*/
6230
6231
6232/* SCIPsortDownPtrPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6233#define SORTTPL_NAMEEXT DownPtrPtrRealBool
6234#define SORTTPL_KEYTYPE void*
6235#define SORTTPL_FIELD1TYPE void*
6236#define SORTTPL_FIELD2TYPE SCIP_Real
6237#define SORTTPL_FIELD3TYPE SCIP_Bool
6238#define SORTTPL_PTRCOMP
6239#define SORTTPL_BACKWARDS
6240#include "scip/sorttpl.c" /*lint !e451*/
6241
6242
6243/* SCIPsortDownPtrPtrLongInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6244#define SORTTPL_NAMEEXT DownPtrPtrLongInt
6245#define SORTTPL_KEYTYPE void*
6246#define SORTTPL_FIELD1TYPE void*
6247#define SORTTPL_FIELD2TYPE SCIP_Longint
6248#define SORTTPL_FIELD3TYPE int
6249#define SORTTPL_PTRCOMP
6250#define SORTTPL_BACKWARDS
6251#include "scip/sorttpl.c" /*lint !e451*/
6252
6253
6254/* SCIPsortDownPtrPtrLongIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6255#define SORTTPL_NAMEEXT DownPtrPtrLongIntInt
6256#define SORTTPL_KEYTYPE void*
6257#define SORTTPL_FIELD1TYPE void*
6258#define SORTTPL_FIELD2TYPE SCIP_Longint
6259#define SORTTPL_FIELD3TYPE int
6260#define SORTTPL_FIELD4TYPE int
6261#define SORTTPL_PTRCOMP
6262#define SORTTPL_BACKWARDS
6263#include "scip/sorttpl.c" /*lint !e451*/
6264
6265
6266/* SCIPsortDownReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6267#define SORTTPL_NAMEEXT DownReal
6268#define SORTTPL_KEYTYPE SCIP_Real
6269#define SORTTPL_BACKWARDS
6270#include "scip/sorttpl.c" /*lint !e451*/
6271
6272
6273/* SCIPsortDownRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6274#define SORTTPL_NAMEEXT DownRealBoolPtr
6275#define SORTTPL_KEYTYPE SCIP_Real
6276#define SORTTPL_FIELD1TYPE SCIP_Bool
6277#define SORTTPL_FIELD2TYPE void*
6278#define SORTTPL_BACKWARDS
6279#include "scip/sorttpl.c" /*lint !e451*/
6280
6281
6282/* SCIPsortDownRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6283#define SORTTPL_NAMEEXT DownRealPtr
6284#define SORTTPL_KEYTYPE SCIP_Real
6285#define SORTTPL_FIELD1TYPE void*
6286#define SORTTPL_BACKWARDS
6287#include "scip/sorttpl.c" /*lint !e451*/
6288
6289
6290/* SCIPsortDownRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6291#define SORTTPL_NAMEEXT DownRealInt
6292#define SORTTPL_KEYTYPE SCIP_Real
6293#define SORTTPL_FIELD1TYPE int
6294#define SORTTPL_BACKWARDS
6295#include "scip/sorttpl.c" /*lint !e451*/
6296
6297/* SCIPsortDownRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6298#define SORTTPL_NAMEEXT DownRealIntInt
6299#define SORTTPL_KEYTYPE SCIP_Real
6300#define SORTTPL_FIELD1TYPE int
6301#define SORTTPL_FIELD2TYPE int
6302#define SORTTPL_BACKWARDS
6303#include "scip/sorttpl.c" /*lint !e451*/
6304
6305/* SCIPsortDownRealIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6306#define SORTTPL_NAMEEXT DownRealIntLong
6307#define SORTTPL_KEYTYPE SCIP_Real
6308#define SORTTPL_FIELD1TYPE int
6309#define SORTTPL_FIELD2TYPE SCIP_Longint
6310#define SORTTPL_BACKWARDS
6311#include "scip/sorttpl.c" /*lint !e451*/
6312
6313
6314/* SCIPsortDownRealIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6315#define SORTTPL_NAMEEXT DownRealIntPtr
6316#define SORTTPL_KEYTYPE SCIP_Real
6317#define SORTTPL_FIELD1TYPE int
6318#define SORTTPL_FIELD2TYPE void*
6319#define SORTTPL_BACKWARDS
6320#include "scip/sorttpl.c" /*lint !e451*/
6321
6322
6323/* SCIPsortDownRealPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6324#define SORTTPL_NAMEEXT DownRealPtrPtr
6325#define SORTTPL_KEYTYPE SCIP_Real
6326#define SORTTPL_FIELD1TYPE void*
6327#define SORTTPL_FIELD2TYPE void*
6328#define SORTTPL_BACKWARDS
6329#include "scip/sorttpl.c" /*lint !e451*/
6330
6331/* SCIPsortDownRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6332#define SORTTPL_NAMEEXT DownRealRealInt
6333#define SORTTPL_KEYTYPE SCIP_Real
6334#define SORTTPL_FIELD1TYPE SCIP_Real
6335#define SORTTPL_FIELD2TYPE int
6336#define SORTTPL_BACKWARDS
6337#include "scip/sorttpl.c" /*lint !e451*/
6338
6339/* SCIPsortDownRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6340#define SORTTPL_NAMEEXT DownRealRealPtr
6341#define SORTTPL_KEYTYPE SCIP_Real
6342#define SORTTPL_FIELD1TYPE SCIP_Real
6343#define SORTTPL_FIELD2TYPE void*
6344#define SORTTPL_BACKWARDS
6345#include "scip/sorttpl.c" /*lint !e451*/
6346
6347/* SCIPsortDownRealRealPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6348#define SORTTPL_NAMEEXT DownRealRealPtrPtr
6349#define SORTTPL_KEYTYPE SCIP_Real
6350#define SORTTPL_FIELD1TYPE SCIP_Real
6351#define SORTTPL_FIELD2TYPE void*
6352#define SORTTPL_FIELD3TYPE void*
6353#define SORTTPL_BACKWARDS
6354#include "scip/sorttpl.c" /*lint !e451*/
6355
6356
6357/* SCIPsortDownRealLongRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6358#define SORTTPL_NAMEEXT DownRealLongRealInt
6359#define SORTTPL_KEYTYPE SCIP_Real
6360#define SORTTPL_FIELD1TYPE SCIP_Longint
6361#define SORTTPL_FIELD2TYPE SCIP_Real
6362#define SORTTPL_FIELD3TYPE int
6363#define SORTTPL_BACKWARDS
6364#include "scip/sorttpl.c" /*lint !e451*/
6365
6366
6367/* SCIPsortDownRealRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6368#define SORTTPL_NAMEEXT DownRealRealIntInt
6369#define SORTTPL_KEYTYPE SCIP_Real
6370#define SORTTPL_FIELD1TYPE SCIP_Real
6371#define SORTTPL_FIELD2TYPE int
6372#define SORTTPL_FIELD3TYPE int
6373#define SORTTPL_BACKWARDS
6374#include "scip/sorttpl.c" /*lint !e451*/
6375
6376
6377/* SCIPsortDownRealRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6378#define SORTTPL_NAMEEXT DownRealRealRealInt
6379#define SORTTPL_KEYTYPE SCIP_Real
6380#define SORTTPL_FIELD1TYPE SCIP_Real
6381#define SORTTPL_FIELD2TYPE SCIP_Real
6382#define SORTTPL_FIELD3TYPE int
6383#define SORTTPL_BACKWARDS
6384#include "scip/sorttpl.c" /*lint !e451*/
6385
6386
6387/* SCIPsortDownRealRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6388#define SORTTPL_NAMEEXT DownRealRealRealPtr
6389#define SORTTPL_KEYTYPE SCIP_Real
6390#define SORTTPL_FIELD1TYPE SCIP_Real
6391#define SORTTPL_FIELD2TYPE SCIP_Real
6392#define SORTTPL_FIELD3TYPE void*
6393#define SORTTPL_BACKWARDS
6394#include "scip/sorttpl.c" /*lint !e451*/
6395
6396
6397/* SCIPsortDownRealPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6398#define SORTTPL_NAMEEXT DownRealPtrPtrInt
6399#define SORTTPL_KEYTYPE SCIP_Real
6400#define SORTTPL_FIELD1TYPE void*
6401#define SORTTPL_FIELD2TYPE void*
6402#define SORTTPL_FIELD3TYPE int
6403#define SORTTPL_BACKWARDS
6404#include "scip/sorttpl.c" /*lint !e451*/
6405
6406/* SCIPsortDownRealPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6407#define SORTTPL_NAMEEXT DownRealPtrPtrIntInt
6408#define SORTTPL_KEYTYPE SCIP_Real
6409#define SORTTPL_FIELD1TYPE void*
6410#define SORTTPL_FIELD2TYPE void*
6411#define SORTTPL_FIELD3TYPE int
6412#define SORTTPL_FIELD4TYPE int
6413#define SORTTPL_BACKWARDS
6414#include "scip/sorttpl.c" /*lint !e451*/
6415
6416
6417/* SCIPsortDownRealRealRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6418#define SORTTPL_NAMEEXT DownRealRealRealBoolPtr
6419#define SORTTPL_KEYTYPE SCIP_Real
6420#define SORTTPL_FIELD1TYPE SCIP_Real
6421#define SORTTPL_FIELD2TYPE SCIP_Real
6422#define SORTTPL_FIELD3TYPE SCIP_Bool
6423#define SORTTPL_FIELD4TYPE void*
6424#define SORTTPL_BACKWARDS
6425#include "scip/sorttpl.c" /*lint !e451*/
6426
6427
6428/* SCIPsortDownRealRealRealBoolBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6429#define SORTTPL_NAMEEXT DownRealRealRealBoolBoolPtr
6430#define SORTTPL_KEYTYPE SCIP_Real
6431#define SORTTPL_FIELD1TYPE SCIP_Real
6432#define SORTTPL_FIELD2TYPE SCIP_Real
6433#define SORTTPL_FIELD3TYPE SCIP_Bool
6434#define SORTTPL_FIELD4TYPE SCIP_Bool
6435#define SORTTPL_FIELD5TYPE void*
6436#include "scip/sorttpl.c" /*lint !e451*/
6437
6438
6439/* SCIPsortDownInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6440#define SORTTPL_NAMEEXT DownInt
6441#define SORTTPL_KEYTYPE int
6442#define SORTTPL_BACKWARDS
6443#include "scip/sorttpl.c" /*lint !e451*/
6444
6445
6446/* SCIPsortDownIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6447#define SORTTPL_NAMEEXT DownIntInt
6448#define SORTTPL_KEYTYPE int
6449#define SORTTPL_FIELD1TYPE int
6450#define SORTTPL_BACKWARDS
6451#include "scip/sorttpl.c" /*lint !e451*/
6452
6453
6454/* SCIPsortDownIntIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6455#define SORTTPL_NAMEEXT DownIntIntReal
6456#define SORTTPL_KEYTYPE int
6457#define SORTTPL_FIELD1TYPE int
6458#define SORTTPL_FIELD2TYPE SCIP_Real
6459#define SORTTPL_BACKWARDS
6460#include "scip/sorttpl.c" /*lint !e451*/
6461
6462
6463/* SCIPsortDownIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6464#define SORTTPL_NAMEEXT DownIntReal
6465#define SORTTPL_KEYTYPE int
6466#define SORTTPL_FIELD1TYPE SCIP_Real
6467#define SORTTPL_BACKWARDS
6468#include "scip/sorttpl.c" /*lint !e451*/
6469
6470
6471/* SCIPsortDownIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6472#define SORTTPL_NAMEEXT DownIntPtr
6473#define SORTTPL_KEYTYPE int
6474#define SORTTPL_FIELD1TYPE void*
6475#define SORTTPL_BACKWARDS
6476#include "scip/sorttpl.c" /*lint !e451*/
6477
6478
6479/* SCIPsortDownIntIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6480#define SORTTPL_NAMEEXT DownIntIntInt
6481#define SORTTPL_KEYTYPE int
6482#define SORTTPL_FIELD1TYPE int
6483#define SORTTPL_FIELD2TYPE int
6484#define SORTTPL_BACKWARDS
6485#include "scip/sorttpl.c" /*lint !e451*/
6486
6487
6488/* SCIPsortDownIntIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6489#define SORTTPL_NAMEEXT DownIntIntLong
6490#define SORTTPL_KEYTYPE int
6491#define SORTTPL_FIELD1TYPE int
6492#define SORTTPL_FIELD2TYPE SCIP_Longint
6493#define SORTTPL_BACKWARDS
6494#include "scip/sorttpl.c" /*lint !e451*/
6495
6496
6497/* SCIPsortDownIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6498#define SORTTPL_NAMEEXT DownIntIntPtr
6499#define SORTTPL_KEYTYPE int
6500#define SORTTPL_FIELD1TYPE int
6501#define SORTTPL_FIELD2TYPE void*
6502#define SORTTPL_BACKWARDS
6503#include "scip/sorttpl.c" /*lint !e451*/
6504
6505
6506/* SCIPsortDownIntIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6507#define SORTTPL_NAMEEXT DownIntIntIntPtr
6508#define SORTTPL_KEYTYPE int
6509#define SORTTPL_FIELD1TYPE int
6510#define SORTTPL_FIELD2TYPE int
6511#define SORTTPL_FIELD3TYPE void*
6512#define SORTTPL_BACKWARDS
6513#include "scip/sorttpl.c" /*lint !e451*/
6514
6515
6516/* SCIPsortDownIntPtrIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6517#define SORTTPL_NAMEEXT DownIntPtrIntReal
6518#define SORTTPL_KEYTYPE int
6519#define SORTTPL_FIELD1TYPE void*
6520#define SORTTPL_FIELD2TYPE int
6521#define SORTTPL_FIELD3TYPE SCIP_Real
6522#define SORTTPL_BACKWARDS
6523#include "scip/sorttpl.c" /*lint !e451*/
6524
6525
6526/* SCIPsortDownLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6527#define SORTTPL_NAMEEXT DownLong
6528#define SORTTPL_KEYTYPE SCIP_Longint
6529#define SORTTPL_BACKWARDS
6530#include "scip/sorttpl.c" /*lint !e451*/
6531
6532
6533/* SCIPsortDownLongPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6534#define SORTTPL_NAMEEXT DownLongPtr
6535#define SORTTPL_KEYTYPE SCIP_Longint
6536#define SORTTPL_FIELD1TYPE void*
6537#define SORTTPL_BACKWARDS
6538#include "scip/sorttpl.c" /*lint !e451*/
6539
6540
6541/* SCIPsortDownLongPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6542#define SORTTPL_NAMEEXT DownLongPtrInt
6543#define SORTTPL_KEYTYPE SCIP_Longint
6544#define SORTTPL_FIELD1TYPE void*
6545#define SORTTPL_FIELD2TYPE int
6546#define SORTTPL_BACKWARDS
6547#include "scip/sorttpl.c" /*lint !e451*/
6548
6549
6550/* SCIPsortDownLongPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6551#define SORTTPL_NAMEEXT DownLongPtrRealBool
6552#define SORTTPL_KEYTYPE SCIP_Longint
6553#define SORTTPL_FIELD1TYPE void*
6554#define SORTTPL_FIELD2TYPE SCIP_Real
6555#define SORTTPL_FIELD3TYPE SCIP_Bool
6556#define SORTTPL_BACKWARDS
6557#include "scip/sorttpl.c" /*lint !e451*/
6558
6559
6560/* SCIPsortDownLongPtrRealRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6561#define SORTTPL_NAMEEXT DownLongPtrRealRealBool
6562#define SORTTPL_KEYTYPE SCIP_Longint
6563#define SORTTPL_FIELD1TYPE void*
6564#define SORTTPL_FIELD2TYPE SCIP_Real
6565#define SORTTPL_FIELD3TYPE SCIP_Real
6566#define SORTTPL_FIELD4TYPE SCIP_Bool
6567#define SORTTPL_BACKWARDS
6568#include "scip/sorttpl.c" /*lint !e451*/
6569
6570
6571/* SCIPsortLongPtrRealRealIntBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6572#define SORTTPL_NAMEEXT DownLongPtrRealRealIntBool
6573#define SORTTPL_KEYTYPE SCIP_Longint
6574#define SORTTPL_FIELD1TYPE void*
6575#define SORTTPL_FIELD2TYPE SCIP_Real
6576#define SORTTPL_FIELD3TYPE SCIP_Real
6577#define SORTTPL_FIELD4TYPE int
6578#define SORTTPL_FIELD5TYPE SCIP_Bool
6579#define SORTTPL_BACKWARDS
6580#include "scip/sorttpl.c" /*lint !e451*/
6581
6582
6583/* SCIPsortDownLongPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6584#define SORTTPL_NAMEEXT DownLongPtrPtrInt
6585#define SORTTPL_KEYTYPE SCIP_Longint
6586#define SORTTPL_FIELD1TYPE void*
6587#define SORTTPL_FIELD2TYPE void*
6588#define SORTTPL_FIELD3TYPE int
6589#define SORTTPL_BACKWARDS
6590#include "scip/sorttpl.c" /*lint !e451*/
6591
6592
6593/* SCIPsortDownLongPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6594#define SORTTPL_NAMEEXT DownLongPtrPtrIntInt
6595#define SORTTPL_KEYTYPE SCIP_Longint
6596#define SORTTPL_FIELD1TYPE void*
6597#define SORTTPL_FIELD2TYPE void*
6598#define SORTTPL_FIELD3TYPE int
6599#define SORTTPL_FIELD4TYPE int
6600#define SORTTPL_BACKWARDS
6601#include "scip/sorttpl.c" /*lint !e451*/
6602
6603
6604/* SCIPsortDownLongPtrPtrBoolInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6605#define SORTTPL_NAMEEXT DownLongPtrPtrBoolInt
6606#define SORTTPL_KEYTYPE SCIP_Longint
6607#define SORTTPL_FIELD1TYPE void*
6608#define SORTTPL_FIELD2TYPE void*
6609#define SORTTPL_FIELD3TYPE SCIP_Bool
6610#define SORTTPL_FIELD4TYPE int
6611#define SORTTPL_BACKWARDS
6612#include "scip/sorttpl.c" /*lint !e451*/
6613
6614
6615/* SCIPsortDownPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6616#define SORTTPL_NAMEEXT DownPtrIntIntBoolBool
6617#define SORTTPL_KEYTYPE void*
6618#define SORTTPL_FIELD1TYPE int
6619#define SORTTPL_FIELD2TYPE int
6620#define SORTTPL_FIELD3TYPE SCIP_Bool
6621#define SORTTPL_FIELD4TYPE SCIP_Bool
6622#define SORTTPL_PTRCOMP
6623#define SORTTPL_BACKWARDS
6624#include "scip/sorttpl.c" /*lint !e451*/
6625
6626
6627/* SCIPsortDownIntPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6628#define SORTTPL_NAMEEXT DownIntPtrIntIntBoolBool
6629#define SORTTPL_KEYTYPE int
6630#define SORTTPL_FIELD1TYPE void*
6631#define SORTTPL_FIELD2TYPE int
6632#define SORTTPL_FIELD3TYPE int
6633#define SORTTPL_FIELD4TYPE SCIP_Bool
6634#define SORTTPL_FIELD5TYPE SCIP_Bool
6635#define SORTTPL_BACKWARDS
6636#include "scip/sorttpl.c" /*lint !e451*/
6637
6638/*
6639 * Resulting activity
6640 */
6641
6642/** create a resource activity */
6644 SCIP_RESOURCEACTIVITY** activity, /**< pointer to store the resource activity */
6645 SCIP_VAR* var, /**< start time variable of the activity */
6646 int duration, /**< duration of the activity */
6647 int demand /**< demand of the activity */
6648 )
6649{
6650 assert(activity != NULL);
6651
6652 SCIP_ALLOC( BMSallocMemory(activity) );
6653
6654 (*activity)->var = var;
6655 (*activity)->duration = duration;
6656 (*activity)->demand = demand;
6657
6658 return SCIP_OKAY;
6659}
6660
6661/** frees a resource activity */
6663 SCIP_RESOURCEACTIVITY** activity /**< pointer to the resource activity */
6664 )
6665{
6666 assert(activity != NULL);
6667 assert(*activity != NULL);
6668
6669 BMSfreeMemory(activity);
6670}
6671
6672/* some simple variable functions implemented as defines */
6673
6674#ifndef NDEBUG
6675
6676/* In debug mode, the following methods are implemented as function calls to ensure
6677 * type validity.
6678 * In optimized mode, the methods are implemented as defines to improve performance.
6679 * However, we want to have them in the library anyways, so we have to undef the defines.
6680 */
6681
6682#undef SCIPactivityGetVar
6683#undef SCIPactivityGetDuration
6684#undef SCIPactivityGetDemand
6685#undef SCIPactivityGetEnergy
6686
6687/** returns the start time variable of the resource activity */
6689 SCIP_RESOURCEACTIVITY* activity /**< resource activity */
6690 )
6691{
6692 assert(activity != NULL);
6693
6694 return activity->var;
6695}
6696
6697/** returns the duration of the resource activity */
6699 SCIP_RESOURCEACTIVITY* activity /**< resource activity */
6700 )
6701{
6702 assert(activity != NULL);
6703
6704 return activity->duration;
6705}
6706
6707/** returns the demand of the resource activity */
6709 SCIP_RESOURCEACTIVITY* activity /**< resource activity */
6710 )
6711{
6712 assert(activity != NULL);
6713
6714 return activity->demand;
6715}
6716
6717/** returns the energy of the resource activity */
6719 SCIP_RESOURCEACTIVITY* activity /**< resource activity */
6720 )
6721{
6722 assert(activity != NULL);
6723
6724 return activity->duration * activity->demand ;
6725}
6726
6727#endif
6728
6729/*
6730 * Resource Profile
6731 */
6732
6733/** helper method to create a profile */
6734static
6736 SCIP_PROFILE** profile, /**< pointer to store the resource profile */
6737 int capacity /**< resource capacity */
6738 )
6739{
6740 SCIP_ALLOC( BMSallocMemory(profile) );
6741 BMSclearMemory(*profile);
6742
6743 (*profile)->arraysize = 10;
6744 SCIP_ALLOC( BMSallocMemoryArray(&(*profile)->timepoints, (*profile)->arraysize) );
6745 SCIP_ALLOC( BMSallocMemoryArray(&(*profile)->loads, (*profile)->arraysize) );
6746
6747 /* setup resource profile for use */
6748 (*profile)->ntimepoints = 1;
6749 (*profile)->timepoints[0] = 0;
6750 (*profile)->loads[0] = 0;
6751 (*profile)->capacity = capacity;
6752
6753 return SCIP_OKAY;
6754}
6755
6756/** creates resource profile */
6758 SCIP_PROFILE** profile, /**< pointer to store the resource profile */
6759 int capacity /**< resource capacity */
6760 )
6761{
6762 assert(profile != NULL);
6763 assert(capacity > 0);
6764
6765 SCIP_CALL_FINALLY( doProfileCreate(profile, capacity), SCIPprofileFree(profile) );
6766
6767 return SCIP_OKAY;
6768}
6769
6770/** frees given resource profile */
6772 SCIP_PROFILE** profile /**< pointer to the resource profile */
6773 )
6774{
6775 assert(profile != NULL);
6776
6777 /* free resource profile */
6778 if( *profile != NULL )
6779 {
6780 BMSfreeMemoryArrayNull(&(*profile)->loads);
6781 BMSfreeMemoryArrayNull(&(*profile)->timepoints);
6782 BMSfreeMemory(profile);
6783 }
6784}
6785
6786/** output of the given resource profile */
6788 SCIP_PROFILE* profile, /**< resource profile to output */
6789 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
6790 FILE* file /**< output file (or NULL for standard output) */
6791 )
6792{
6793 int t;
6794
6795 SCIPmessageFPrintInfo(messagehdlr, file, "Profile <%p> (capacity %d) --> ", (void*)profile, profile->capacity);
6796
6797 for( t = 0; t < profile->ntimepoints; ++t )
6798 {
6799 if( t == 0 )
6800 SCIPmessageFPrintInfo(messagehdlr, file, "%d:(%d,%d)", t, profile->timepoints[t], profile->loads[t]);
6801 else
6802 SCIPmessageFPrintInfo(messagehdlr, file, ", %d:(%d,%d)", t, profile->timepoints[t], profile->loads[t]);
6803 }
6804
6805 SCIPmessageFPrintInfo(messagehdlr, file,"\n");
6806}
6807
6808/** returns the capacity of the resource profile */
6810 SCIP_PROFILE* profile /**< resource profile to use */
6811 )
6812{
6813 assert(profile != NULL);
6814
6815 return profile->capacity;
6816}
6817
6818/** returns the number time points of the resource profile */
6820 SCIP_PROFILE* profile /**< resource profile to use */
6821 )
6822{
6823 assert(profile != NULL);
6824
6825 return profile->ntimepoints;
6826}
6827
6828/** returns the time points of the resource profile */
6830 SCIP_PROFILE* profile /**< resource profile to use */
6831 )
6832{
6833 assert(profile != NULL);
6834
6835 return profile->timepoints;
6836}
6837
6838/** returns the loads of the resource profile */
6840 SCIP_PROFILE* profile /**< resource profile to use */
6841 )
6842{
6843 assert(profile != NULL);
6844
6845 return profile->loads;
6846}
6847
6848/** returns the time point for given position of the resource profile */
6850 SCIP_PROFILE* profile, /**< resource profile to use */
6851 int pos /**< position */
6852 )
6853{
6854 assert(profile != NULL);
6855 assert(pos >= 0 && pos < profile->ntimepoints);
6856
6857 return profile->timepoints[pos];
6858}
6859
6860/** returns the loads of the resource profile at the given position */
6862 SCIP_PROFILE* profile, /**< resource profile */
6863 int pos /**< position */
6864 )
6865{
6866 assert(profile != NULL);
6867 assert(pos >= 0 && pos < profile->ntimepoints);
6868
6869 return profile->loads[pos];
6870}
6871
6872/** returns if the given time point exists in the resource profile and stores the position of the given time point if it
6873 * exists; otherwise the position of the next smaller existing time point is stored
6874 */
6876 SCIP_PROFILE* profile, /**< resource profile to search */
6877 int timepoint, /**< time point to search for */
6878 int* pos /**< pointer to store the position */
6879 )
6880{
6881 assert(profile != NULL);
6882 assert(timepoint >= 0);
6883 assert(profile->ntimepoints > 0);
6884 assert(profile->timepoints[0] == 0);
6885
6886 /* find the position of time point in the time points array via binary search */
6887 if( SCIPsortedvecFindInt(profile->timepoints, timepoint, profile->ntimepoints, pos) )
6888 return TRUE;
6889
6890 assert(*pos > 0);
6891 (*pos)--;
6892
6893 return FALSE;
6894}
6895
6896/* ensures that resource profile arrays is big enough */
6897static
6899 SCIP_PROFILE* profile, /**< resource profile to insert the time point */
6900 int neededsize /**< needed size */
6901 )
6902{
6903 assert(profile->arraysize > 0);
6904
6905 /* check whether the arrays are big enough */
6906 if( neededsize <= profile->arraysize )
6907 return SCIP_OKAY;
6908
6909 profile->arraysize *= 2;
6910
6911 SCIP_ALLOC( BMSreallocMemoryArray(&profile->timepoints, profile->arraysize) );
6912 SCIP_ALLOC( BMSreallocMemoryArray(&profile->loads, profile->arraysize) );
6913
6914 return SCIP_OKAY;
6915}
6916
6917/** inserts the given time point into the resource profile if it this time point does not exists yet; returns its
6918 * position in the time point array
6919 */
6920static
6922 SCIP_PROFILE* profile, /**< resource profile to insert the time point */
6923 int timepoint, /**< time point to insert */
6924 int* pos /**< pointer to store the insert position */
6925 )
6926{
6927 assert(profile != NULL);
6928 assert(timepoint >= 0);
6929 assert(profile->arraysize >= profile->ntimepoints);
6930
6931 /* get the position of the given time point in the resource profile array if it exists; otherwise the position of the
6932 * next smaller existing time point
6933 */
6934 if( !SCIPprofileFindLeft(profile, timepoint, pos) )
6935 {
6936 assert(*pos >= 0 && *pos < profile->ntimepoints);
6937 assert(timepoint >= profile->timepoints[*pos]);
6938
6939 /* ensure that the arrays are big enough */
6940 SCIP_CALL( ensureProfileSize(profile, profile->ntimepoints + 1) );
6941 assert(profile->arraysize > profile->ntimepoints);
6942
6943 /* insert new time point into the (sorted) resource profile */
6944 SCIPsortedvecInsertIntInt(profile->timepoints, profile->loads, timepoint, profile->loads[*pos],
6945 &profile->ntimepoints, pos);
6946 }
6947
6948#ifndef NDEBUG
6949 /* check if the time points are sorted */
6950 {
6951 int i;
6952 for( i = 1; i < profile->ntimepoints; ++i )
6953 assert(profile->timepoints[i-1] < profile->timepoints[i]);
6954 }
6955#endif
6956
6957 return SCIP_OKAY;
6958}
6959
6960/** updates the resource profile due to inserting of a core */
6961static
6963 SCIP_PROFILE* profile, /**< resource profile to update */
6964 int left, /**< left side of core interval */
6965 int right, /**< right side of core interval */
6966 int demand, /**< demand of the core */
6967 int* pos, /**< pointer to store the first position were it gets infeasible */
6968 SCIP_Bool* infeasible /**< pointer to store if the update is infeasible */
6969 )
6970{
6971 int startpos;
6972 int endpos;
6973 int i;
6974
6975 assert(profile != NULL);
6976 assert(profile->arraysize >= profile->ntimepoints);
6977 assert(left >= 0);
6978 assert(left < right);
6979 assert(infeasible != NULL);
6980
6981 (*infeasible) = FALSE;
6982 (*pos) = -1;
6983
6984 /* get position of the starttime in profile */
6985 SCIP_CALL( profileInsertTimepoint(profile, left, &startpos) );
6986 assert(profile->timepoints[startpos] == left);
6987
6988 /* get position of the endtime in profile */
6989 SCIP_CALL( profileInsertTimepoint(profile, right, &endpos) );
6990 assert(profile->timepoints[endpos] == right);
6991
6992 assert(startpos < endpos);
6993 assert(profile->arraysize >= profile->ntimepoints);
6994
6995 /* remove/add the given demand from the core */
6996 for( i = startpos; i < endpos; ++i )
6997 {
6998 profile->loads[i] += demand;
6999
7000 /* check if the core fits */
7001 if( profile->loads[i] > profile->capacity )
7002 {
7003 SCIPdebugMessage("core insertion detected infeasibility (pos %d)\n", i);
7004
7005 (*infeasible) = TRUE;
7006 (*pos) = i;
7007
7008 /* remove the partly inserted core since it does fit completely */
7009 for( ; i >= startpos; --i ) /*lint !e445*/
7010 profile->loads[i] -= demand;
7011
7012 break;
7013 }
7014 }
7015
7016 return SCIP_OKAY;
7017}
7018
7019/** insert a core into resource profile; if the core is non-empty the resource profile will be updated otherwise nothing
7020 * happens
7021 */
7023 SCIP_PROFILE* profile, /**< resource profile */
7024 int left, /**< left side of the core */
7025 int right, /**< right side of the core */
7026 int demand, /**< demand of the core */
7027 int* pos, /**< pointer to store the first position were it gets infeasible */
7028 SCIP_Bool* infeasible /**< pointer to store if the core does not fit due to capacity */
7029 )
7030{
7031 assert(profile != NULL);
7032 assert(left < right);
7033 assert(demand >= 0);
7034 assert(infeasible != NULL);
7035
7036 (*infeasible) = FALSE;
7037 (*pos) = -1;
7038
7039 /* insert core into the resource profile */
7040 SCIPdebugMessage("insert core [%d,%d] with demand %d\n", left, right, demand);
7041
7042 if( demand > 0 )
7043 {
7044 /* try to insert core into the resource profile */
7045 SCIP_CALL( profileUpdate(profile, left, right, demand, pos, infeasible) );
7046 }
7047
7048 return SCIP_OKAY;
7049}
7050
7051/** subtracts the demand from the resource profile during core time */
7053 SCIP_PROFILE* profile, /**< resource profile to use */
7054 int left, /**< left side of the core */
7055 int right, /**< right side of the core */
7056 int demand /**< demand of the core */
7057 )
7058{
7059 SCIP_Bool infeasible;
7060 int pos;
7061
7062 assert(left < right);
7063#ifndef NDEBUG
7064 {
7065 /* check if the left and right time points of the core correspond to a time point in the resource profile; this
7066 * should be the case since we added the core before to the resource profile
7067 */
7068 assert(SCIPprofileFindLeft(profile, left, &pos));
7069 assert(SCIPprofileFindLeft(profile, right, &pos));
7070 }
7071#endif
7072
7073 /* remove the core from the resource profile */
7074 SCIPdebugMessage("delete core [%d,%d] with demand %d\n", left, right, demand);
7075
7076 SCIP_CALL( profileUpdate(profile, left, right, -demand, &pos, &infeasible) );
7077 assert(!infeasible);
7078
7079 return SCIP_OKAY; /*lint !e438*/
7080}
7081
7082/** returns TRUE if the core (given by its demand and during) can be inserted at the given time point; otherwise FALSE */
7083static
7085 SCIP_PROFILE* profile, /**< resource profile to use */
7086 int pos, /**< pointer to store the position in the profile to start the serch */
7087 int lst, /**< latest start time */
7088 int duration, /**< duration of the core */
7089 int demand, /**< demand of the core */
7090 SCIP_Bool* infeasible /**< pointer store if the corer cannot be inserted */
7091 )
7092{
7093 int remainingduration;
7094 int startpos;
7095
7096 assert(profile != NULL);
7097 assert(pos >= 0);
7098 assert(pos < profile->ntimepoints);
7099 assert(duration > 0);
7100 assert(demand > 0);
7101 assert(profile->loads[profile->ntimepoints-1] == 0);
7102
7103 remainingduration = duration;
7104 startpos = pos;
7105 (*infeasible) = FALSE;
7106
7107 if( profile->timepoints[startpos] > lst )
7108 {
7109 (*infeasible) = TRUE;
7110 return pos;
7111 }
7112
7113 while( pos < profile->ntimepoints - 1 )
7114 {
7115 if( profile->loads[pos] + demand > profile->capacity )
7116 {
7117 SCIPdebugMessage("profile <%p>: core does not fit at time point %d (pos %d)\n", (void*)profile, profile->timepoints[pos], pos);
7118 startpos = pos + 1;
7119 remainingduration = duration;
7120
7121 if( profile->timepoints[startpos] > lst )
7122 {
7123 (*infeasible) = TRUE;
7124 return pos;
7125 }
7126 }
7127 else
7128 remainingduration -= profile->timepoints[pos+1] - profile->timepoints[pos];
7129
7130 if( remainingduration <= 0 )
7131 break;
7132
7133 pos++;
7134 }
7135
7136 return startpos;
7137}
7138
7139/** return the earliest possible starting point within the time interval [lb,ub] for a given core (given by its demand
7140 * and duration)
7141 */
7143 SCIP_PROFILE* profile, /**< resource profile to use */
7144 int est, /**< earliest starting time of the given core */
7145 int lst, /**< latest starting time of the given core */
7146 int duration, /**< duration of the core */
7147 int demand, /**< demand of the core */
7148 SCIP_Bool* infeasible /**< pointer store if the corer cannot be inserted */
7149 )
7150{
7151 SCIP_Bool found;
7152 int pos;
7153
7154 assert(profile != NULL);
7155 assert(est >= 0);
7156 assert(est <= lst);
7157 assert(duration >= 0);
7158 assert(demand >= 0);
7159 assert(infeasible != NULL);
7160 assert(profile->ntimepoints > 0);
7161 assert(profile->loads[profile->ntimepoints-1] == 0);
7162
7163 SCIPdebugMessage("profile <%p>: find earliest start time (demad %d, duration %d) [%d,%d]\n", (void*)profile, demand, duration, est, lst);
7164
7165 if( duration == 0 || demand == 0 )
7166 {
7167 *infeasible = FALSE;
7168 return est;
7169 }
7170
7171 found = SCIPprofileFindLeft(profile, est, &pos);
7172 SCIPdebugMessage("profile <%p>: earliest start time does %s exist as time point (pos %d)\n", (void*)profile, found ? "" : "not", pos);
7173
7174 /* if the position is the last time point in the profile, the core can be inserted at its earliest start time */
7175 if( pos == profile->ntimepoints - 1 )
7176 {
7177 (*infeasible) = FALSE;
7178 return est;
7179 }
7180
7181 if( found )
7182 {
7183 /* if the start time matches a time point in the profile we can just search */
7184 assert(profile->timepoints[pos] == est);
7185 pos = profileFindFeasibleStart(profile, pos, lst, duration, demand, infeasible);
7186
7187 assert(pos < profile->ntimepoints);
7188 est = profile->timepoints[pos];
7189 }
7190 else if( profile->loads[pos] + demand > profile->capacity )
7191 {
7192 /* if the the time point left to the start time has not enough free capacity we can just search the profile
7193 * starting from the next time point
7194 */
7195 assert(profile->timepoints[pos] <= est);
7196 pos = profileFindFeasibleStart(profile, pos+1, lst, duration, demand, infeasible);
7197
7198 assert(pos < profile->ntimepoints);
7199 est = profile->timepoints[pos];
7200 }
7201 else
7202 {
7203 int remainingduration;
7204
7205 /* check if the core can be placed at its earliest start time */
7206
7207 assert(pos < profile->ntimepoints - 1);
7208
7209 remainingduration = duration - (profile->timepoints[pos+1] - est);
7210 SCIPdebugMessage("remaining duration %d\n", remainingduration);
7211
7212 if( remainingduration <= 0 )
7213 (*infeasible) = FALSE;
7214 else
7215 {
7216 pos = profileFindFeasibleStart(profile, pos+1, profile->timepoints[pos+1], remainingduration, demand, infeasible);
7217 SCIPdebugMessage("remaining duration can%s be processed\n", *infeasible ? "not" : "");
7218
7219 if( *infeasible )
7220 {
7221 pos = profileFindFeasibleStart(profile, pos+1, lst, duration, demand, infeasible);
7222
7223 assert(pos < profile->ntimepoints);
7224 est = profile->timepoints[pos];
7225 }
7226 }
7227 }
7228
7229 return est;
7230}
7231
7232/** returns TRUE if the core (given by its demand and during) can be inserted at the given time point; otherwise FALSE */
7233static
7235 SCIP_PROFILE* profile, /**< resource profile to use */
7236 int pos, /**< pointer to store the position in the profile to start the search */
7237 int ect, /**< earliest completion time */
7238 int duration, /**< duration of the core */
7239 int demand, /**< demand of the core */
7240 SCIP_Bool* infeasible /**< pointer store if the corer cannot be inserted */
7241 )
7242{
7243 int remainingduration;
7244 int endpos;
7245
7246 assert(profile != NULL);
7247 assert(pos >= 0);
7248 assert(pos < profile->ntimepoints);
7249 assert(duration > 0);
7250 assert(demand > 0);
7251 assert(profile->ntimepoints > 0);
7252 assert(profile->loads[profile->ntimepoints-1] == 0);
7253
7254 remainingduration = duration;
7255 endpos = pos;
7256 (*infeasible) = TRUE;
7257
7258 if( profile->timepoints[endpos] < ect - duration )
7259 return pos;
7260
7261 while( pos > 0 )
7262 {
7263 if( profile->loads[pos-1] + demand > profile->capacity )
7264 {
7265 SCIPdebugMessage("profile <%p>: core does not fit at time point %d (pos %d)\n", (void*)profile, profile->timepoints[pos-1], pos-1);
7266
7267 endpos = pos - 1;
7268 remainingduration = duration;
7269
7270 if( profile->timepoints[endpos] < ect - duration )
7271 return pos;
7272 }
7273 else
7274 remainingduration -= profile->timepoints[pos] - profile->timepoints[pos-1];
7275
7276 if( remainingduration <= 0 )
7277 {
7278 *infeasible = FALSE;
7279 break;
7280 }
7281
7282 pos--;
7283 }
7284
7285 return endpos;
7286}
7287
7288/** return the latest possible starting point within the time interval [lb,ub] for a given core (given by its demand and
7289 * duration)
7290 */
7292 SCIP_PROFILE* profile, /**< resource profile to use */
7293 int est, /**< earliest possible start point */
7294 int lst, /**< latest possible start point */
7295 int duration, /**< duration of the core */
7296 int demand, /**< demand of the core */
7297 SCIP_Bool* infeasible /**< pointer store if the core cannot be inserted */
7298 )
7299{
7300 SCIP_Bool found;
7301 int ect;
7302 int lct;
7303 int pos;
7304
7305 assert(profile != NULL);
7306 assert(est >= 0);
7307 assert(est <= lst);
7308 assert(duration >= 0);
7309 assert(demand >= 0);
7310 assert(infeasible != NULL);
7311 assert(profile->ntimepoints > 0);
7312 assert(profile->loads[profile->ntimepoints-1] == 0);
7313
7314 if( duration == 0 || demand == 0 )
7315 {
7316 *infeasible = FALSE;
7317 return lst;
7318 }
7319
7320 ect = est + duration;
7321 lct = lst + duration;
7322
7323 found = SCIPprofileFindLeft(profile, lct, &pos);
7324 SCIPdebugMessage("profile <%p>: latest completion time %d does %s exist as time point (pos %d)\n", (void*)profile, lct, found ? "" : "not", pos);
7325
7326 if( found )
7327 {
7328 /* if the start time matches a time point in the profile we can just search */
7329 assert(profile->timepoints[pos] == lct);
7330 pos = profileFindDownFeasibleStart(profile, pos, ect, duration, demand, infeasible);
7331
7332 assert(pos < profile->ntimepoints && pos >= 0);
7333 lct = profile->timepoints[pos];
7334 }
7335 else if( profile->loads[pos] + demand > profile->capacity )
7336 {
7337 /* if the time point left to the start time has not enough free capacity we can just search the profile starting
7338 * from the next time point
7339 */
7340 assert(profile->timepoints[pos] < lct);
7341 pos = profileFindDownFeasibleStart(profile, pos, ect, duration, demand, infeasible);
7342
7343 assert(pos < profile->ntimepoints && pos >= 0);
7344 lct = profile->timepoints[pos];
7345 }
7346 else
7347 {
7348 int remainingduration;
7349
7350 /* check if the core can be placed at its latest start time */
7351 assert(profile->timepoints[pos] < lct);
7352
7353 remainingduration = duration - (lct - profile->timepoints[pos]);
7354
7355 if( remainingduration <= 0 )
7356 (*infeasible) = FALSE;
7357 else
7358 {
7359 pos = profileFindDownFeasibleStart(profile, pos, profile->timepoints[pos], remainingduration, demand, infeasible);
7360
7361 if( *infeasible )
7362 {
7363 pos = profileFindDownFeasibleStart(profile, pos, ect, duration, demand, infeasible);
7364
7365 assert(pos < profile->ntimepoints && pos >= 0);
7366 lct = profile->timepoints[pos];
7367 }
7368 }
7369 }
7370
7371 return lct - duration;
7372}
7373
7374/*
7375 * Directed graph
7376 */
7377
7378/** creates directed graph structure */
7380 SCIP_DIGRAPH** digraph, /**< pointer to store the created directed graph */
7381 BMS_BLKMEM* blkmem, /**< block memory to store the data */
7382 int nnodes /**< number of nodes */
7383 )
7384{
7385 assert(digraph != NULL);
7386 assert(blkmem != NULL);
7387 assert(nnodes > 0);
7388
7389 /* allocate memory for the graph and the arrays storing arcs and data */
7390 SCIP_ALLOC( BMSallocBlockMemory(blkmem, digraph) );
7391 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->successors, nnodes) );
7392 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->arcdata, nnodes) );
7393 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->successorssize, nnodes) );
7394 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->nsuccessors, nnodes) );
7395 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->nodedata, nnodes) );
7396
7397 /* store number of nodes */
7398 (*digraph)->nnodes = nnodes;
7399
7400 /* at the beginning, no components are stored */
7401 (*digraph)->blkmem = blkmem;
7402 (*digraph)->ncomponents = 0;
7403 (*digraph)->componentstartsize = 0;
7404 (*digraph)->components = NULL;
7405 (*digraph)->componentstarts = NULL;
7406
7407 /* all nodes are initially considered as non-articulation points */
7408 (*digraph)->narticulations = -1;
7409 (*digraph)->articulations = NULL;
7410 (*digraph)->articulationscheck = FALSE;
7411
7412 return SCIP_OKAY;
7413}
7414
7415/** resize directed graph structure */
7417 SCIP_DIGRAPH* digraph, /**< directed graph */
7418 int nnodes /**< new number of nodes */
7419 )
7420{
7421 int n;
7422 assert(digraph != NULL);
7423 assert(digraph->blkmem != NULL);
7424
7425 /* check if the digraph has already a proper size */
7426 if( nnodes <= digraph->nnodes )
7427 return SCIP_OKAY;
7428
7429 /* reallocate memory for increasing the arrays storing arcs and data */
7430 SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->successors, digraph->nnodes, nnodes) );
7431 SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->arcdata, digraph->nnodes, nnodes) );
7432 SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->successorssize, digraph->nnodes, nnodes) );
7433 SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->nsuccessors, digraph->nnodes, nnodes) );
7434 SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->nodedata, digraph->nnodes, nnodes) );
7435
7436 /* initialize the new node data structures */
7437 for( n = digraph->nnodes; n < nnodes; ++n )
7438 {
7439 digraph->nodedata[n] = NULL;
7440 digraph->arcdata[n] = NULL;
7441 digraph->successors[n] = NULL;
7442 digraph->successorssize[n] = 0;
7443 digraph->nsuccessors[n] = 0;
7444 }
7445
7446 /* store the new number of nodes */
7447 digraph->nnodes = nnodes;
7448
7449 return SCIP_OKAY;
7450}
7451
7452/** copies directed graph structure
7453 *
7454 * @note The data in nodedata is copied verbatim. This possibly has to be adapted by the user.
7455 */
7457 SCIP_DIGRAPH** targetdigraph, /**< pointer to store the copied directed graph */
7458 SCIP_DIGRAPH* sourcedigraph, /**< source directed graph */
7459 BMS_BLKMEM* targetblkmem /**< block memory to store the target block memory, or NULL to use the same
7460 * the same block memory as used for the \p sourcedigraph */
7461 )
7462{
7463 int ncomponents;
7464 int nnodes;
7465 int i;
7466 SCIP_Bool articulationscheck;
7467
7468 assert(sourcedigraph != NULL);
7469 assert(targetdigraph != NULL);
7470
7471 /* use the source digraph block memory if not specified otherwise */
7472 if( targetblkmem == NULL )
7473 targetblkmem = sourcedigraph->blkmem;
7474
7475 assert(targetblkmem != NULL);
7476
7477 SCIP_ALLOC( BMSallocBlockMemory(targetblkmem, targetdigraph) );
7478
7479 nnodes = sourcedigraph->nnodes;
7480 ncomponents = sourcedigraph->ncomponents;
7481 articulationscheck = sourcedigraph->articulationscheck;
7482 (*targetdigraph)->nnodes = nnodes;
7483 (*targetdigraph)->ncomponents = ncomponents;
7484 (*targetdigraph)->blkmem = targetblkmem;
7485
7486 /* copy arcs and data */
7487 SCIP_ALLOC( BMSallocClearBlockMemoryArray(targetblkmem, &(*targetdigraph)->successors, nnodes) );
7488 SCIP_ALLOC( BMSallocClearBlockMemoryArray(targetblkmem, &(*targetdigraph)->arcdata, nnodes) );
7489 SCIP_ALLOC( BMSallocClearBlockMemoryArray(targetblkmem, &(*targetdigraph)->nodedata, nnodes) );
7490
7491 /* copy lists of successors and arc data */
7492 for( i = 0; i < nnodes; ++i )
7493 {
7494 if( sourcedigraph->nsuccessors[i] > 0 )
7495 {
7496 assert(sourcedigraph->successors[i] != NULL);
7497 assert(sourcedigraph->arcdata[i] != NULL);
7498
7499 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &((*targetdigraph)->successors[i]),
7500 sourcedigraph->successors[i], sourcedigraph->nsuccessors[i]) ); /*lint !e866*/
7501 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &((*targetdigraph)->arcdata[i]),
7502 sourcedigraph->arcdata[i], sourcedigraph->nsuccessors[i]) ); /*lint !e866*/
7503 }
7504 /* copy node data - careful if these are pointers to some information -> need to be copied by hand */
7505 (*targetdigraph)->nodedata[i] = sourcedigraph->nodedata[i];
7506 }
7507
7508 /* use nsuccessors as size to save memory */
7509 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->successorssize, sourcedigraph->nsuccessors, nnodes) );
7510 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->nsuccessors, sourcedigraph->nsuccessors, nnodes) );
7511
7512 /* copy component data */
7513 if( ncomponents > 0 )
7514 {
7515 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->components, sourcedigraph->components,
7516 sourcedigraph->componentstarts[ncomponents]) );
7517 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->componentstarts,
7518 sourcedigraph->componentstarts,ncomponents + 1) ); /*lint !e776*/
7519 (*targetdigraph)->componentstartsize = ncomponents + 1;
7520 }
7521 else
7522 {
7523 (*targetdigraph)->components = NULL;
7524 (*targetdigraph)->componentstarts = NULL;
7525 (*targetdigraph)->componentstartsize = 0;
7526 }
7527
7528 /* copy the articulation point information if it has been computed and is up-to-date */
7529 if( articulationscheck )
7530 {
7531 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->articulations, sourcedigraph->articulations, sourcedigraph->narticulations) );
7532 (*targetdigraph)->narticulations = sourcedigraph->narticulations;
7533 (*targetdigraph)->articulationscheck = TRUE;
7534 }
7535 else
7536 {
7537 (*targetdigraph)->narticulations = -1;
7538 (*targetdigraph)->articulations = NULL;
7539 (*targetdigraph)->articulationscheck = FALSE;
7540 }
7541
7542 return SCIP_OKAY;
7543}
7544
7545/** sets the sizes of the successor lists for the nodes in a directed graph and allocates memory for the lists */
7547 SCIP_DIGRAPH* digraph, /**< directed graph */
7548 int* sizes /**< sizes of the successor lists */
7549 )
7550{
7551 int i;
7552 BMS_BLKMEM* blkmem;
7553
7554 assert(digraph != NULL);
7555 assert(digraph->nnodes > 0);
7556 blkmem = digraph->blkmem;
7557
7558 for( i = 0; i < digraph->nnodes; ++i )
7559 {
7560 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->successors[i], sizes[i]) ); /*lint !e866*/
7561 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->arcdata[i], sizes[i]) ); /*lint !e866*/
7562 digraph->successorssize[i] = sizes[i];
7563 digraph->nsuccessors[i] = 0;
7564 }
7565
7566 return SCIP_OKAY;
7567}
7568
7569/** frees given directed graph structure */
7571 SCIP_DIGRAPH** digraph /**< pointer to the directed graph */
7572 )
7573{
7574 int i;
7575 BMS_BLKMEM* blkmem;
7576 SCIP_DIGRAPH* digraphptr;
7577
7578 assert(digraph != NULL);
7579 assert(*digraph != NULL);
7580 assert((*digraph)->blkmem != NULL);
7581
7582 blkmem = (*digraph)->blkmem;
7583 digraphptr = *digraph;
7584
7585 /* free arrays storing the successor nodes and arc data */
7586 for( i = digraphptr->nnodes - 1; i >= 0; --i )
7587 {
7588 BMSfreeBlockMemoryArrayNull(blkmem, &digraphptr->successors[i], digraphptr->successorssize[i]);
7589 BMSfreeBlockMemoryArrayNull(blkmem, &digraphptr->arcdata[i], digraphptr->successorssize[i]);
7590 }
7591
7592 /* free components structure */
7593 SCIPdigraphFreeComponents(digraphptr);
7594 assert(digraphptr->ncomponents == 0);
7595 assert(digraphptr->componentstartsize == 0);
7596 assert(digraphptr->components == NULL);
7597 assert(digraphptr->componentstarts == NULL);
7598
7599 /* free the articulation points structure if it has been computed*/
7600 if( digraphptr->articulationscheck )
7601 BMSfreeBlockMemoryArray(blkmem, &digraphptr->articulations, digraphptr->narticulations);
7602
7603 /* free directed graph data structure */
7604 BMSfreeBlockMemoryArray(blkmem, &digraphptr->nodedata, digraphptr->nnodes);
7605 BMSfreeBlockMemoryArray(blkmem, &digraphptr->successorssize, digraphptr->nnodes);
7606 BMSfreeBlockMemoryArray(blkmem, &digraphptr->nsuccessors, digraphptr->nnodes);
7607 BMSfreeBlockMemoryArray(blkmem, &digraphptr->successors, digraphptr->nnodes);
7608 BMSfreeBlockMemoryArray(blkmem, &digraphptr->arcdata, digraphptr->nnodes);
7609
7610 BMSfreeBlockMemory(blkmem, digraph);
7611}
7612
7613#define STARTSUCCESSORSSIZE 5
7614
7615/** ensures that successors array of one node in a directed graph is big enough */
7616static
7618 SCIP_DIGRAPH* digraph, /**< directed graph */
7619 int idx, /**< index for which the size is ensured */
7620 int newsize /**< needed size */
7621 )
7622{
7623 BMS_BLKMEM* blkmem;
7624
7625 assert(digraph != NULL);
7626 assert(digraph->blkmem != NULL);
7627 assert(idx >= 0);
7628 assert(idx < digraph->nnodes);
7629 assert(newsize > 0);
7630 assert(digraph->successorssize[idx] == 0 || digraph->successors[idx] != NULL);
7631 assert(digraph->successorssize[idx] == 0 || digraph->arcdata[idx] != NULL);
7632
7633 blkmem = digraph->blkmem;
7634
7635 /* check whether array is big enough, and realloc, if needed */
7636 if( newsize > digraph->successorssize[idx] )
7637 {
7638 if( digraph->successors[idx] == NULL )
7639 {
7640 assert(digraph->arcdata[idx] == NULL);
7641 digraph->successorssize[idx] = STARTSUCCESSORSSIZE;
7642 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->successors[idx], digraph->successorssize[idx]) ); /*lint !e866*/
7643 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->arcdata[idx], digraph->successorssize[idx]) ); /*lint !e866*/
7644 }
7645 else
7646 {
7647 newsize = MAX(newsize, 2 * digraph->successorssize[idx]);
7648 assert(digraph->arcdata[idx] != NULL);
7649 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &digraph->successors[idx], digraph->successorssize[idx], newsize) ); /*lint !e866*/
7650 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &digraph->arcdata[idx], digraph->successorssize[idx], newsize) ); /*lint !e866*/
7651 digraph->successorssize[idx] = newsize;
7652 }
7653 }
7654
7655 assert(newsize <= digraph->successorssize[idx]);
7656
7657 return SCIP_OKAY;
7658}
7659
7660/** add (directed) arc and a related data to the directed graph structure
7661 *
7662 * @note if the arc is already contained, it is added a second time
7663 */
7665 SCIP_DIGRAPH* digraph, /**< directed graph */
7666 int startnode, /**< start node of the arc */
7667 int endnode, /**< start node of the arc */
7668 void* data /**< data that should be stored for the arc; or NULL */
7669 )
7670{
7671 assert(digraph != NULL);
7672 assert(startnode >= 0);
7673 assert(endnode >= 0);
7674 assert(startnode < digraph->nnodes);
7675 assert(endnode < digraph->nnodes);
7676
7677 SCIP_CALL( ensureSuccessorsSize(digraph, startnode, digraph->nsuccessors[startnode] + 1) );
7678
7679 /* add arc */
7680 digraph->successors[startnode][digraph->nsuccessors[startnode]] = endnode;
7681 digraph->arcdata[startnode][digraph->nsuccessors[startnode]] = data;
7682 digraph->nsuccessors[startnode]++;
7683
7684 /* the articulation points are not up-to-date */
7685 digraph->articulationscheck = FALSE;
7686
7687 return SCIP_OKAY;
7688}
7689
7690/** add (directed) arc to the directed graph structure, if it is not contained, yet
7691 *
7692 * @note if there already exists an arc from startnode to endnode, the new arc is not added,
7693 * even if its data is different
7694 */
7696 SCIP_DIGRAPH* digraph, /**< directed graph */
7697 int startnode, /**< start node of the arc */
7698 int endnode, /**< start node of the arc */
7699 void* data /**< data that should be stored for the arc; or NULL */
7700 )
7701{
7702 int nsuccessors;
7703 int i;
7704
7705 assert(digraph != NULL);
7706 assert(startnode >= 0);
7707 assert(endnode >= 0);
7708 assert(startnode < digraph->nnodes);
7709 assert(endnode < digraph->nnodes);
7710
7711 nsuccessors = digraph->nsuccessors[startnode];
7712
7713 /* search for the arc in existing arcs */
7714 for( i = 0; i < nsuccessors; ++i )
7715 if( digraph->successors[startnode][i] == endnode )
7716 return SCIP_OKAY;
7717
7718 SCIP_CALL( ensureSuccessorsSize(digraph, startnode, nsuccessors + 1) );
7719
7720 /* add arc */
7721 digraph->successors[startnode][nsuccessors] = endnode;
7722 digraph->arcdata[startnode][nsuccessors] = data;
7723 ++(digraph->nsuccessors[startnode]);
7724
7725 /* the articulation points are not up-to-date */
7726 digraph->articulationscheck = FALSE;
7727
7728 return SCIP_OKAY;
7729}
7730
7731/** sets the number of successors to a given value */
7733 SCIP_DIGRAPH* digraph, /**< directed graph */
7734 int node, /**< node for which the number of successors has to be changed */
7735 int nsuccessors /**< new number of successors */
7736 )
7737{
7738 assert(digraph != NULL);
7739 assert(node >= 0);
7740 assert(node < digraph->nnodes);
7741
7742 digraph->nsuccessors[node] = nsuccessors;
7743
7744 return SCIP_OKAY;
7745}
7746
7747/** returns the number of nodes of the given digraph */
7749 SCIP_DIGRAPH* digraph /**< directed graph */
7750 )
7751{
7752 assert(digraph != NULL);
7753
7754 return digraph->nnodes;
7755}
7756
7757/** returns the node data, or NULL if no data exist */
7759 SCIP_DIGRAPH* digraph, /**< directed graph */
7760 int node /**< node for which the node data is returned */
7761 )
7762{
7763 assert(digraph != NULL);
7764 assert(node >= 0);
7765 assert(node < digraph->nnodes);
7766
7767 return digraph->nodedata[node];
7768}
7769
7770/** sets the node data
7771 *
7772 * @note The old user pointer is not freed. This has to be done by the user
7773 */
7775 SCIP_DIGRAPH* digraph, /**< directed graph */
7776 void* dataptr, /**< user node data pointer, or NULL */
7777 int node /**< node for which the node data is returned */
7778 )
7779{
7780 assert(digraph != NULL);
7781 assert(node >= 0);
7782 assert(node < digraph->nnodes);
7783
7784 digraph->nodedata[node] = dataptr;
7785}
7786
7787/** returns the total number of arcs in the given digraph */
7789 SCIP_DIGRAPH* digraph /**< directed graph */
7790 )
7791{
7792 int i;
7793 int narcs;
7794
7795 assert(digraph != NULL);
7796
7797 /* count number of arcs */
7798 narcs = 0;
7799 for( i = 0; i < digraph->nnodes; ++i )
7800 narcs += digraph->nsuccessors[i];
7801
7802 return narcs;
7803}
7804
7805/** returns the number of successor nodes of the given node */
7807 SCIP_DIGRAPH* digraph, /**< directed graph */
7808 int node /**< node for which the number of outgoing arcs is returned */
7809 )
7810{
7811 assert(digraph != NULL);
7812 assert(node >= 0);
7813 assert(node < digraph->nnodes);
7814 assert(digraph->nsuccessors[node] >= 0);
7815 assert(digraph->nsuccessors[node] <= digraph->successorssize[node]);
7816
7817 return digraph->nsuccessors[node];
7818}
7819
7820/** returns the array of indices of the successor nodes; this array must not be changed from outside */
7822 SCIP_DIGRAPH* digraph, /**< directed graph */
7823 int node /**< node for which the array of outgoing arcs is returned */
7824 )
7825{
7826 assert(digraph != NULL);
7827 assert(node >= 0);
7828 assert(node < digraph->nnodes);
7829 assert(digraph->nsuccessors[node] >= 0);
7830 assert(digraph->nsuccessors[node] <= digraph->successorssize[node]);
7831 assert((digraph->nsuccessors[node] == 0) || (digraph->successors[node] != NULL));
7832
7833 return digraph->successors[node];
7834}
7835
7836/** returns the array of data corresponding to the arcs originating at the given node, or NULL if no data exist; this
7837 * array must not be changed from outside
7838 */
7840 SCIP_DIGRAPH* digraph, /**< directed graph */
7841 int node /**< node for which the data corresponding to the outgoing arcs is returned */
7842 )
7843{
7844 assert(digraph != NULL);
7845 assert(node >= 0);
7846 assert(node < digraph->nnodes);
7847 assert(digraph->nsuccessors[node] >= 0);
7848 assert(digraph->nsuccessors[node] <= digraph->successorssize[node]);
7849 assert(digraph->arcdata != NULL);
7850
7851 return digraph->arcdata[node];
7852}
7853
7854/** performs depth-first-search in the given directed graph from the given start node */
7855static
7857 SCIP_DIGRAPH* digraph, /**< directed graph */
7858 int startnode, /**< node to start the depth-first-search */
7859 SCIP_Bool* visited, /**< array to store for each node, whether it was already visited */
7860 int* dfsstack, /**< array of size number of nodes to store the stack;
7861 * only needed for performance reasons */
7862 int* stackadjvisited, /**< array of size number of nodes to store the number of adjacent nodes already visited
7863 * for each node on the stack; only needed for performance reasons */
7864 int* dfsnodes, /**< array of nodes that can be reached starting at startnode, in reverse dfs order */
7865 int* ndfsnodes /**< pointer to store number of nodes that can be reached starting at startnode */
7866 )
7867{
7868 int stackidx;
7869
7870 assert(digraph != NULL);
7871 assert(startnode >= 0);
7872 assert(startnode < digraph->nnodes);
7873 assert(visited != NULL);
7874 assert(visited[startnode] == FALSE);
7875 assert(dfsstack != NULL);
7876 assert(dfsnodes != NULL);
7877 assert(ndfsnodes != NULL);
7878
7879 /* put start node on the stack */
7880 dfsstack[0] = startnode;
7881 stackadjvisited[0] = 0;
7882 stackidx = 0;
7883
7884 while( stackidx >= 0 )
7885 {
7886 int currnode;
7887 int sadv;
7888
7889 /* get next node from stack */
7890 currnode = dfsstack[stackidx];
7891
7892 sadv = stackadjvisited[stackidx];
7893 assert( 0 <= sadv && sadv <= digraph->nsuccessors[currnode] );
7894
7895 /* mark current node as visited */
7896 assert( visited[currnode] == (sadv > 0) );
7897 visited[currnode] = TRUE;
7898
7899 /* iterate through the successor list until we reach unhandled node */
7900 while( sadv < digraph->nsuccessors[currnode] && visited[digraph->successors[currnode][sadv]] )
7901 ++sadv;
7902
7903 /* the current node was completely handled, remove it from stack */
7904 if( sadv == digraph->nsuccessors[currnode] )
7905 {
7906 --stackidx;
7907
7908 /* store node in the sorted nodes array */
7909 dfsnodes[(*ndfsnodes)++] = currnode;
7910 }
7911 /* handle next unhandled successor node */
7912 else
7913 {
7914 assert( ! visited[digraph->successors[currnode][sadv]] );
7915
7916 /* store current stackadjvisted index */
7917 stackadjvisited[stackidx] = sadv + 1;
7918
7919 /* put the successor node onto the stack */
7920 ++stackidx;
7921 dfsstack[stackidx] = digraph->successors[currnode][sadv];
7922 stackadjvisited[stackidx] = 0;
7923 assert( stackidx < digraph->nnodes );
7924 }
7925 }
7926}
7927
7928/** checks for articulation points in a given directed graph through a recursive depth-first-search.
7929 * starts from a given start node and keeps track of the nodes' discovery time in search for back edges.
7930 *
7931 * @note an articulation point is a node whose removal disconnects a connected graph or increases
7932 * the number of connected components in a disconnected graph
7933 */
7934static
7936 SCIP_DIGRAPH* digraph, /**< directed graph */
7937 int startnode, /**< node to start the depth-first-search */
7938 SCIP_Bool* visited, /**< array to store for each node, whether it was already visited */
7939 int* tdisc, /**< array of size number of nodes to store each node's discovery time */
7940 int* mindisc, /**< array of size number of nodes to store the discovery time of the earliest discovered vertex
7941 * to which startnode (or any node in the subtree rooted at it) is having a back edge */
7942 int* parent, /**< array to store the parent of each node in the DFS tree */
7943 SCIP_Bool* articulationflag, /**< array to mark whether a node is identified as an articulation point */
7944 int time /**< current discovery time in the DFS */
7945 )
7946{
7947 int n;
7948 int nchildren = 0;
7949 int nsucc;
7950 int* succnodes;
7951
7952 assert(digraph != NULL);
7953 assert(startnode >= 0);
7954 assert(startnode < digraph->nnodes);
7955 assert(visited != NULL);
7956 assert(visited[startnode] == FALSE);
7957 assert(tdisc != NULL);
7958 assert(mindisc != NULL);
7959 assert(parent != NULL);
7960 assert(articulationflag != NULL);
7961 assert(time >= 0);
7962
7963 nsucc = (int) SCIPdigraphGetNSuccessors(digraph, startnode);
7964 succnodes = (int*) SCIPdigraphGetSuccessors(digraph, startnode);
7965 visited[startnode] = TRUE;
7966 tdisc[startnode] = time + 1;
7967 mindisc[startnode] = time + 1;
7968
7969 /* process all the adjacent nodes to startnode */
7970 for( n = 0; n < nsucc; ++n)
7971 {
7972 if( !visited[succnodes[n]] )
7973 {
7974 parent[succnodes[n]] = startnode;
7975 ++nchildren;
7976 findArticulationPointsUtil(digraph, succnodes[n], visited, tdisc, mindisc, parent, articulationflag, time + 1);
7977 /* updated the mindisc of startnode when the DFS concludes for node n*/
7978 mindisc[startnode] = MIN(mindisc[startnode], mindisc[succnodes[n]]);
7979
7980 /* the root is an articulation point if it has more than 2 children*/
7981 if( parent[startnode] == -1 && nchildren > 1 )
7982 articulationflag[startnode] = TRUE;
7983 /* a vertex startnode is an articulation point if it is not the root and
7984 * there is no back edge from the subtree rooted at child n to any of the ancestors of startnode */
7985 if( parent[startnode] > -1 && mindisc[succnodes[n]] >= tdisc[startnode] )
7986 articulationflag[startnode] = TRUE;
7987 }
7988 else
7989 {
7990 if( parent[startnode] != succnodes[n] )
7991 mindisc[startnode] = MIN(mindisc[startnode], tdisc[succnodes[n]]);
7992 }
7993 }
7994
7995 if( articulationflag[startnode] )
7996 ++digraph->narticulations;
7997}
7998
7999/** identifies the articulation points in a given directed graph
8000 * uses the helper recursive function findArticulationPointsUtil
8001 */
8003 SCIP_DIGRAPH* digraph, /**< directed graph */
8004 int** articulations, /**< array to store the sorted node indices of the computed articulation points, or NULL */
8005 int* narticulations /**< number of the computed articulation points, or NULL */
8006 )
8007{
8008 SCIP_RETCODE retcode = SCIP_OKAY;
8009 BMS_BLKMEM* blkmem;
8010 SCIP_Bool* visited = NULL;
8011 SCIP_Bool* articulationflag = NULL;
8012 int* tdisc = NULL;
8013 int* mindisc = NULL;
8014 int* parent = NULL;
8015 int n;
8016 int articulationidx = 0;
8017 int time = 0;
8018
8019 assert(digraph != NULL);
8020 assert(digraph->nnodes > 0);
8021
8022 /* Only perform the computation if the articulation points are NOT up-to-date */
8023 if( !digraph->articulationscheck )
8024 {
8025 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&visited, digraph->nnodes), TERMINATE );
8026 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&tdisc, digraph->nnodes), TERMINATE );
8027 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&mindisc, digraph->nnodes), TERMINATE );
8028 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&parent, digraph->nnodes), TERMINATE );
8029 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&articulationflag, digraph->nnodes), TERMINATE );
8030
8031 assert(digraph->blkmem != NULL);
8032 blkmem = digraph->blkmem;
8033
8034 if( digraph->narticulations >= 0 ) /* case: articulations have already been computed but not up-to-date */
8035 BMSfreeBlockMemoryArray(blkmem, &digraph->articulations, digraph->narticulations);
8036
8037 /* Initialize the no. of articulation points ahead of the recursive computation */
8038 digraph->narticulations = 0;
8039
8040 for( n = 0; n < digraph->nnodes; ++n )
8041 {
8042 visited[n] = FALSE;
8043 parent[n] = -1;
8044 articulationflag[n] = FALSE;
8045 }
8046
8047 /* the function is called on every unvisited node in the graph to cover the disconnected graph case */
8048 for( n = 0; n < digraph->nnodes; ++n )
8049 {
8050 if( !visited[n] )
8051 findArticulationPointsUtil(digraph, n, visited, tdisc, mindisc, parent, articulationflag, time);
8052 }
8053
8054 /* allocation of the block memory for the node indices of the articulation points*/
8055 SCIP_ALLOC_TERMINATE( retcode, BMSallocBlockMemoryArray(blkmem, &digraph->articulations, digraph->narticulations), TERMINATE );
8056
8057 for( n = 0; n < digraph->nnodes; ++n )
8058 {
8059 if( articulationflag[n] )
8060 {
8061 digraph->articulations[articulationidx] = n;
8062 ++articulationidx;
8063 }
8064 }
8065 }
8066
8067 if( articulations != NULL )
8068 (*articulations) = digraph->articulations;
8069 if( narticulations != NULL )
8070 (*narticulations) = digraph->narticulations;
8071
8072 /* the articulation points are now up-to-date */
8073 digraph->articulationscheck = TRUE;
8074
8075TERMINATE:
8076 BMSfreeMemoryArrayNull(&articulationflag);
8077 BMSfreeMemoryArrayNull(&parent);
8078 BMSfreeMemoryArrayNull(&mindisc);
8079 BMSfreeMemoryArrayNull(&tdisc);
8080 BMSfreeMemoryArrayNull(&visited);
8081
8082 return retcode;
8083}
8084
8085/** Compute undirected connected components on the given graph.
8086 *
8087 * @note For each arc, its reverse is added, so the graph does not need to be the directed representation of an
8088 * undirected graph.
8089 */
8091 SCIP_DIGRAPH* digraph, /**< directed graph */
8092 int minsize, /**< all components with less nodes are ignored */
8093 int* components, /**< array with as many slots as there are nodes in the directed graph
8094 * to store for each node the component to which it belongs
8095 * (components are numbered 0 to ncomponents - 1); or NULL, if components
8096 * are accessed one-by-one using SCIPdigraphGetComponent() */
8097 int* ncomponents /**< pointer to store the number of components; or NULL, if the
8098 * number of components is accessed by SCIPdigraphGetNComponents() */
8099 )
8100{
8101 BMS_BLKMEM* blkmem;
8102 SCIP_Bool* visited;
8103 int* ndirectedsuccessors;
8104 int* stackadjvisited;
8105 int* dfsstack;
8106 int ndfsnodes;
8107 int compstart;
8108 int v;
8109 int i;
8110 int j;
8111
8112 SCIP_RETCODE retcode = SCIP_OKAY;
8113
8114 assert(digraph != NULL);
8115 assert(digraph->nnodes > 0);
8116 assert(digraph->blkmem != NULL);
8117
8118 blkmem = digraph->blkmem;
8119
8120 /* first free the old components */
8121 if( digraph->ncomponents > 0 )
8122 {
8124 }
8125
8126 digraph->ncomponents = 0;
8127 digraph->componentstartsize = 10;
8128
8129 /* storage to hold components is stored in block memory */
8130 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->components, digraph->nnodes) );
8132
8133 /* allocate temporary arrays */
8134 SCIP_ALLOC_TERMINATE( retcode, BMSallocClearMemoryArray(&visited, digraph->nnodes), TERMINATE );
8135 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsstack, digraph->nnodes), TERMINATE );
8136 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&stackadjvisited, digraph->nnodes), TERMINATE );
8137 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&ndirectedsuccessors, digraph->nnodes), TERMINATE );
8138
8139 digraph->componentstarts[0] = 0;
8140
8141 /* store the number of directed arcs per node */
8142 BMScopyMemoryArray(ndirectedsuccessors, digraph->nsuccessors, digraph->nnodes);
8143
8144 /* add reverse arcs to the graph */
8145 for( i = digraph->nnodes - 1; i >= 0; --i )
8146 {
8147 for( j = 0; j < ndirectedsuccessors[i]; ++j )
8148 {
8149 SCIP_CALL_TERMINATE( retcode, SCIPdigraphAddArc(digraph, digraph->successors[i][j], i, NULL), TERMINATE );
8150 }
8151 }
8152
8153 for( v = 0; v < digraph->nnodes; ++v )
8154 {
8155 if( visited[v] )
8156 continue;
8157
8158 compstart = digraph->componentstarts[digraph->ncomponents];
8159 ndfsnodes = 0;
8160 depthFirstSearch(digraph, v, visited, dfsstack, stackadjvisited,
8161 &digraph->components[compstart], &ndfsnodes);
8162
8163 /* forget about this component if it is too small */
8164 if( ndfsnodes >= minsize )
8165 {
8166 digraph->ncomponents++;
8167
8168 /* enlarge componentstartsize array, if needed */
8169 if( digraph->ncomponents >= digraph->componentstartsize )
8170 {
8171 int newsize;
8172
8173 newsize = 2 * digraph->componentstartsize;
8174 assert(digraph->ncomponents < newsize);
8175
8176 SCIP_ALLOC_TERMINATE( retcode, BMSreallocBlockMemoryArray(blkmem, &digraph->componentstarts, digraph->componentstartsize, newsize), TERMINATE );
8177 digraph->componentstartsize = newsize;
8178 }
8179 digraph->componentstarts[digraph->ncomponents] = compstart + ndfsnodes;
8180
8181 /* store component number for contained nodes if array was given */
8182 if( components != NULL )
8183 {
8184 for( i = digraph->componentstarts[digraph->ncomponents] - 1; i >= compstart; --i )
8185 {
8186 components[digraph->components[i]] = digraph->ncomponents - 1;
8187 }
8188 }
8189 }
8190 }
8191
8192 /* restore the number of directed arcs per node */
8193 BMScopyMemoryArray(digraph->nsuccessors, ndirectedsuccessors, digraph->nnodes);
8194 BMSclearMemoryArray(visited, digraph->nnodes);
8195
8196 /* return number of components, if the pointer was given */
8197 if( ncomponents != NULL )
8198 (*ncomponents) = digraph->ncomponents;
8199
8200TERMINATE:
8201 if( retcode != SCIP_OKAY )
8202 {
8204 }
8205 /* coverity[uninit_use_in_call] */
8206 BMSfreeMemoryArrayNull(&ndirectedsuccessors);
8207 BMSfreeMemoryArrayNull(&stackadjvisited);
8208 BMSfreeMemoryArrayNull(&dfsstack);
8209 BMSfreeMemoryArrayNull(&visited);
8210
8211 return retcode;
8212}
8213
8214/** Performs an (almost) topological sort on the undirected components of the given directed graph. The undirected
8215 * components should be computed before using SCIPdigraphComputeUndirectedComponents().
8216 *
8217 * @note In general a topological sort is not unique. Note, that there might be directed cycles, that are randomly
8218 * broken, which is the reason for having only almost topologically sorted arrays.
8219 */
8221 SCIP_DIGRAPH* digraph /**< directed graph */
8222 )
8223{
8224 SCIP_Bool* visited = NULL;
8225 int* comps;
8226 int* compstarts;
8227 int* stackadjvisited = NULL;
8228 int* dfsstack = NULL;
8229 int* dfsnodes = NULL;
8230 int ndfsnodes;
8231 int ncomps;
8232 int i;
8233 int j;
8234 int k;
8235 int endidx;
8236 SCIP_RETCODE retcode = SCIP_OKAY;
8237
8238 assert(digraph != NULL);
8239
8240 ncomps = digraph->ncomponents;
8241 comps = digraph->components;
8242 compstarts = digraph->componentstarts;
8243
8244 SCIP_ALLOC_TERMINATE( retcode, BMSallocClearMemoryArray(&visited, digraph->nnodes), TERMINATE );
8245 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsnodes, digraph->nnodes), TERMINATE );
8246 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsstack, digraph->nnodes), TERMINATE );
8247 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&stackadjvisited, digraph->nnodes), TERMINATE );
8248
8249 /* sort the components (almost) topologically */
8250 for( i = 0; i < ncomps; ++i )
8251 {
8252 endidx = compstarts[i+1] - 1;
8253 ndfsnodes = 0;
8254 for( j = compstarts[i]; j < compstarts[i+1]; ++j )
8255 {
8256 if( visited[comps[j]] )
8257 continue;
8258
8259 /* perform depth first search, nodes visited in this call are appended to the list dfsnodes in reverse
8260 * dfs order, after the nodes already contained;
8261 * so at every point in time, the nodes in dfsnode are in reverse (almost) topological order
8262 */
8263 depthFirstSearch(digraph, comps[j], visited, dfsstack, stackadjvisited, dfsnodes, &ndfsnodes);
8264 }
8265 assert(endidx - ndfsnodes == compstarts[i] - 1);
8266
8267 /* copy reverse (almost) topologically sorted array of nodes reached by the dfs searches;
8268 * reverse their order to get an (almost) topologically sort
8269 */
8270 for( k = 0; k < ndfsnodes; ++k )
8271 {
8272 digraph->components[endidx - k] = dfsnodes[k];
8273 }
8274 }
8275
8276TERMINATE:
8277 BMSfreeMemoryArrayNull(&stackadjvisited);
8278 BMSfreeMemoryArrayNull(&dfsstack);
8279 BMSfreeMemoryArrayNull(&dfsnodes);
8280 BMSfreeMemoryArrayNull(&visited);
8281
8282 return retcode;
8283}
8284
8285/** returns the number of previously computed undirected components for the given directed graph */
8287 SCIP_DIGRAPH* digraph /**< directed graph */
8288 )
8289{
8290 assert(digraph != NULL);
8291 assert(digraph->componentstartsize > 0); /* components should have been computed */
8292
8293 return digraph->ncomponents;
8294}
8295
8296/** Returns the previously computed undirected component of the given number for the given directed graph.
8297 * If the components were sorted using SCIPdigraphTopoSortComponents(), the component is (almost) topologically sorted.
8298 */
8300 SCIP_DIGRAPH* digraph, /**< directed graph */
8301 int compidx, /**< number of the component to return */
8302 int** nodes, /**< pointer to store the nodes in the component; or NULL, if not needed */
8303 int* nnodes /**< pointer to store the number of nodes in the component;
8304 * or NULL, if not needed */
8305 )
8306{
8307 assert(digraph != NULL);
8308 assert(compidx >= 0);
8309 assert(compidx < digraph->ncomponents);
8310 assert(nodes != NULL || nnodes != NULL);
8311
8312 if( nodes != NULL )
8313 (*nodes) = &(digraph->components[digraph->componentstarts[compidx]]);
8314 if( nnodes != NULL )
8315 (*nnodes) = digraph->componentstarts[compidx + 1] - digraph->componentstarts[compidx];
8316}
8317
8318/* Performs Tarjan's algorithm for a given directed graph to obtain the strongly connected components
8319 * which are reachable from a given node.
8320 */
8321static
8323 SCIP_DIGRAPH* digraph, /**< directed graph */
8324 int v, /**< node to start the algorithm */
8325 int* lowlink, /**< array to store lowlink values */
8326 int* dfsidx, /**< array to store dfs indices */
8327 int* stack, /**< array to store a stack */
8328 int* stacksize, /**< pointer to store the size of the stack */
8329 SCIP_Bool* unprocessed, /**< array to store which node is unprocessed yet */
8330 SCIP_Bool* nodeinstack, /**< array to store which nodes are in the stack */
8331 int* maxdfs, /**< pointer to store index for DFS */
8332 int* strongcomponents, /**< array to store for each node the strongly connected
8333 * component to which it belongs (components are
8334 * numbered 0 to nstrongcomponents - 1); */
8335 int* nstrongcomponents, /**< pointer to store the number of computed components so far */
8336 int* strongcompstartidx, /**< array to store the start index of the computed components */
8337 int* nstorednodes /**< pointer to store the number of already stored nodes */
8338 )
8339{
8340 int i;
8341
8342 assert(digraph != NULL);
8343 assert(v >= 0);
8344 assert(v < digraph->nnodes);
8345 assert(lowlink != NULL);
8346 assert(dfsidx != NULL);
8347 assert(stack != NULL);
8348 assert(stacksize != NULL);
8349 assert(*stacksize >= 0);
8350 assert(*stacksize < digraph->nnodes);
8351 assert(unprocessed != NULL);
8352 assert(nodeinstack != NULL);
8353 assert(maxdfs != NULL);
8354 assert(strongcomponents != NULL);
8355 assert(nstrongcomponents != NULL);
8356 assert(strongcompstartidx != NULL);
8357 assert(nstorednodes != NULL);
8358 assert(*nstorednodes >= 0 && *nstorednodes < digraph->nnodes);
8359
8360 dfsidx[v] = *maxdfs;
8361 lowlink[v] = *maxdfs;
8362 *maxdfs += 1;
8363
8364 /* add v to the stack */
8365 stack[*stacksize] = v;
8366 *stacksize += 1;
8367 nodeinstack[v] = TRUE;
8368
8369 /* mark v as processed */
8370 unprocessed[v] = FALSE;
8371
8372 for( i = 0; i < digraph->nsuccessors[v]; ++i )
8373 {
8374 int w;
8375
8376 /* edge (v,w) */
8377 w = digraph->successors[v][i];
8378
8379 if( unprocessed[w] )
8380 {
8381 tarjan(digraph, w, lowlink, dfsidx, stack, stacksize, unprocessed, nodeinstack, maxdfs, strongcomponents,
8382 nstrongcomponents, strongcompstartidx, nstorednodes);
8383
8384 assert(lowlink[v] >= 0 && lowlink[v] < digraph->nnodes);
8385 assert(lowlink[w] >= 0 && lowlink[w] < digraph->nnodes);
8386
8387 /* update lowlink */
8388 lowlink[v] = MIN(lowlink[v], lowlink[w]);
8389 }
8390 else if( nodeinstack[w] )
8391 {
8392 assert(lowlink[v] >= 0 && lowlink[v] < digraph->nnodes);
8393 assert(dfsidx[w] >= 0 && dfsidx[w] < digraph->nnodes);
8394
8395 /* update lowlink */
8396 lowlink[v] = MIN(lowlink[v], dfsidx[w]);
8397 }
8398 }
8399
8400 /* found a root of a strong component */
8401 if( lowlink[v] == dfsidx[v] )
8402 {
8403 int w;
8404
8405 strongcompstartidx[*nstrongcomponents] = *nstorednodes;
8406 *nstrongcomponents += 1;
8407
8408 do
8409 {
8410 assert(*stacksize > 0);
8411
8412 /* stack.pop() */
8413 w = stack[*stacksize - 1];
8414 *stacksize -= 1;
8415 nodeinstack[w] = FALSE;
8416
8417 /* store the node in the corresponding component */
8418 strongcomponents[*nstorednodes] = w;
8419 *nstorednodes += 1;
8420 }
8421 while( v != w );
8422 }
8423}
8424
8425/** Computes all strongly connected components of an undirected connected component with Tarjan's Algorithm.
8426 * The resulting strongly connected components are sorted topologically (starting from the end of the
8427 * strongcomponents array).
8428 *
8429 * @note In general a topological sort of the strongly connected components is not unique.
8430 */
8432 SCIP_DIGRAPH* digraph, /**< directed graph */
8433 int compidx, /**< number of the undirected connected component */
8434 int* strongcomponents, /**< array to store the strongly connected components
8435 * (length >= size of the component) */
8436 int* strongcompstartidx, /**< array to store the start indices of the strongly connected
8437 * components (length >= size of the component) */
8438 int* nstrongcomponents /**< pointer to store the number of strongly connected
8439 * components */
8440 )
8441{
8442 int* lowlink = NULL;
8443 int* dfsidx = NULL;
8444 int* stack = NULL;
8445 int stacksize;
8446 SCIP_Bool* unprocessed = NULL;
8447 SCIP_Bool* nodeinstack = NULL;
8448 int maxdfs;
8449 int nstorednodes;
8450 int i;
8451 SCIP_RETCODE retcode;
8452
8453 assert(digraph != NULL);
8454 assert(compidx >= 0);
8455 assert(compidx < digraph->ncomponents);
8456 assert(strongcomponents != NULL);
8457 assert(strongcompstartidx != NULL);
8458 assert(nstrongcomponents != NULL);
8459
8460 retcode = SCIP_OKAY;
8461
8462 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&lowlink, digraph->nnodes), TERMINATE );
8463 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsidx, digraph->nnodes), TERMINATE );
8464 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&stack, digraph->nnodes), TERMINATE );
8465 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&unprocessed, digraph->nnodes), TERMINATE );
8466 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&nodeinstack, digraph->nnodes), TERMINATE );
8467
8468 for( i = 0; i < digraph->nnodes; ++i )
8469 {
8470 lowlink[i] = -1;
8471 dfsidx[i] = -1;
8472 stack[i] = -1;
8473 unprocessed[i] = TRUE;
8474 nodeinstack[i] = FALSE;
8475 }
8476
8477 nstorednodes = 0;
8478 stacksize = 0;
8479 maxdfs = 0;
8480 *nstrongcomponents = 0;
8481
8482 /* iterate over all nodes in the undirected connected component */
8483 for( i = digraph->componentstarts[compidx]; i < digraph->componentstarts[compidx + 1]; ++i )
8484 {
8485 int v;
8486
8487 v = digraph->components[i];
8488 assert(v >= 0 && v < digraph->nnodes);
8489
8490 /* call Tarjan's algorithm for unprocessed nodes */
8491 if( unprocessed[v] )
8492 {
8493 SCIPdebugMessage("apply Tarjan's algorithm for node %d\n", v);
8494 tarjan(digraph, v, lowlink, dfsidx, stack, &stacksize, unprocessed, nodeinstack, &maxdfs,
8495 strongcomponents, nstrongcomponents, strongcompstartidx, &nstorednodes);
8496 }
8497 }
8498
8499 /* we should have stored as many nodes as in the undirected connected component */
8500 assert(nstorednodes == digraph->componentstarts[compidx + 1] - digraph->componentstarts[compidx]);
8501
8502 /* to simplify the iteration over all strongly connected components */
8503 assert(*nstrongcomponents < digraph->nnodes + 1);
8504 strongcompstartidx[*nstrongcomponents] = nstorednodes;
8505
8506 assert(retcode == SCIP_OKAY);
8507
8508TERMINATE:
8509 BMSfreeMemoryArrayNull(&lowlink);
8510 BMSfreeMemoryArrayNull(&dfsidx);
8511 BMSfreeMemoryArrayNull(&stack);
8512 BMSfreeMemoryArrayNull(&unprocessed);
8513 BMSfreeMemoryArrayNull(&nodeinstack);
8514
8515 return retcode;
8516}
8517
8518/** frees the component information for the given directed graph */
8520 SCIP_DIGRAPH* digraph /**< directed graph */
8521 )
8522{
8523 BMS_BLKMEM* blkmem;
8524
8525 assert(digraph != NULL);
8526 assert(digraph->blkmem != NULL);
8527
8528 blkmem = digraph->blkmem;
8529
8530 /* free components structure */
8531 if( digraph->componentstartsize > 0 )
8532 {
8533 BMSfreeBlockMemoryArray(blkmem, &digraph->componentstarts, digraph->componentstartsize);
8534 BMSfreeBlockMemoryArray(blkmem, &digraph->components, digraph->nnodes);
8535 digraph->components = NULL;
8536 digraph->componentstarts = NULL;
8537 digraph->ncomponents = 0;
8538 digraph->componentstartsize = 0;
8539 }
8540#ifndef NDEBUG
8541 else
8542 {
8543 assert(digraph->components == NULL);
8544 assert(digraph->componentstarts == NULL);
8545 assert(digraph->ncomponents == 0);
8546 }
8547#endif
8548}
8549
8550/** output of the given directed graph via the given message handler */
8552 SCIP_DIGRAPH* digraph, /**< directed graph */
8553 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
8554 FILE* file /**< output file (or NULL for standard output) */
8555 )
8556{
8557 int n;
8558
8559 for( n = 0; n < digraph->nnodes; ++n )
8560 {
8561 int* successors;
8562 int nsuccessors;
8563 int m;
8564
8565 nsuccessors = digraph->nsuccessors[n];
8566 successors = digraph->successors[n];
8567
8568 SCIPmessageFPrintInfo(messagehdlr, file, "node %d --> ", n);
8569
8570 for( m = 0; m < nsuccessors ; ++m )
8571 {
8572 if( m == 0 )
8573 {
8574 SCIPmessageFPrintInfo(messagehdlr, file, "%d", successors[m]);
8575 }
8576 else
8577 {
8578 SCIPmessageFPrintInfo(messagehdlr, file, ", %d", successors[m]);
8579 }
8580 }
8581 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
8582 }
8583}
8584
8585/** prints the given directed graph structure in GML format into the given file */
8587 SCIP_DIGRAPH* digraph, /**< directed graph */
8588 FILE* file /**< file to write to */
8589 )
8590{
8591 int n;
8592
8593 /* write GML format opening */
8595
8596 /* write all nodes of the graph */
8597 for( n = 0; n < digraph->nnodes; ++n )
8598 {
8599 char label[SCIP_MAXSTRLEN];
8600
8601 (void)SCIPsnprintf(label, SCIP_MAXSTRLEN, "%d", n);
8602 SCIPgmlWriteNode(file, (unsigned int)n, label, "circle", NULL, NULL);
8603 }
8604
8605 /* write all edges */
8606 for( n = 0; n < digraph->nnodes; ++n )
8607 {
8608 int* successors;
8609 int nsuccessors;
8610 int m;
8611
8612 nsuccessors = digraph->nsuccessors[n];
8613 successors = digraph->successors[n];
8614
8615 for( m = 0; m < nsuccessors; ++m )
8616 {
8617 SCIPgmlWriteArc(file, (unsigned int)n, (unsigned int)successors[m], NULL, NULL);
8618 }
8619 }
8620 /* write GML format closing */
8621 SCIPgmlWriteClosing(file);
8622}
8623
8624/** output of the given directed graph via the given message handler */
8626 SCIP_DIGRAPH* digraph, /**< directed graph */
8627 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
8628 FILE* file /**< output file (or NULL for standard output) */
8629 )
8630{
8631 int c;
8632 int i;
8633
8634 for( c = 0; c < digraph->ncomponents; ++c )
8635 {
8636 int start = digraph->componentstarts[c];
8637 int end = digraph->componentstarts[c+1];
8638
8639 SCIPmessageFPrintInfo(messagehdlr, file, "Components %d --> ", c);
8640
8641 for( i = start; i < end; ++i )
8642 {
8643 if( i == start )
8644 {
8645 SCIPmessageFPrintInfo(messagehdlr, file, "%d", digraph->components[i]);
8646 }
8647 else
8648 {
8649 SCIPmessageFPrintInfo(messagehdlr, file, ", %d", digraph->components[i]);
8650 }
8651 }
8652 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
8653 }
8654}
8655
8656/*
8657 * Binary tree
8658 */
8659
8660/** creates a node for a binary tree */
8661static
8663 SCIP_BT* tree, /**< binary tree */
8664 SCIP_BTNODE** node /**< pointer to store the created node */
8665 )
8666{
8667 SCIP_ALLOC( BMSallocBlockMemory(tree->blkmem, node) );
8668
8669 (*node)->parent = NULL;
8670 (*node)->left = NULL;
8671 (*node)->right = NULL;
8672 (*node)->dataptr = NULL;
8673
8674 return SCIP_OKAY;
8675}
8676
8677/** creates a tree node with (optinal) user data */
8679 SCIP_BT* tree, /**< binary tree */
8680 SCIP_BTNODE** node, /**< pointer to store the created node */
8681 void* dataptr /**< user node data pointer, or NULL */
8682 )
8683{
8684 assert(tree != NULL);
8685 assert(node != NULL);
8686
8687 SCIP_CALL( btnodeCreateEmpty(tree, node) );
8688
8689 assert((*node)->parent == NULL);
8690 assert((*node)->left == NULL);
8691 assert((*node)->right == NULL);
8692
8693 /* initialize user data */
8694 (*node)->dataptr = dataptr;
8695
8696 return SCIP_OKAY;
8697}
8698
8699/** frees a tree leaf */
8700static
8702 SCIP_BT* tree, /**< binary tree */
8703 SCIP_BTNODE** node /**< pointer to node which has to be freed */
8704 )
8705{
8706 assert(tree != NULL);
8707 assert(node != NULL);
8708 assert(*node != NULL);
8709
8710 assert((*node)->left == NULL);
8711 assert((*node)->right == NULL);
8712
8713#ifdef SCIP_DISABLED_CODE
8714 /* remove reference from parent node */
8715 if( (*node)->parent != NULL )
8716 {
8717 assert(*node != NULL);
8718
8719 assert((*node)->parent->left == *node || ((*node)->parent->right == *node));
8720
8721 if( (*node)->parent->left == *node )
8722 {
8723 (*node)->parent->left = NULL;
8724 }
8725 else
8726 {
8727 assert((*node)->parent->right == *node);
8728 (*node)->parent->right = NULL;
8729 }
8730 }
8731#endif
8732
8733 assert(*node != NULL);
8734 BMSfreeBlockMemory(tree->blkmem, node);
8735 assert(*node == NULL);
8736}
8737
8738/** frees the node including the rooted subtree
8739 *
8740 * @note The user pointer (object) is not freed. If needed, it has to be done by the user.
8741 */
8743 SCIP_BT* tree, /**< binary tree */
8744 SCIP_BTNODE** node /**< node to be freed */
8745 )
8746{
8747 assert(tree != NULL);
8748 assert(node != NULL);
8749 assert(*node != NULL);
8750
8751 if( (*node)->left != NULL )
8752 {
8753 SCIPbtnodeFree(tree, &(*node)->left);
8754 assert((*node)->left == NULL);
8755 }
8756
8757 if( (*node)->right != NULL )
8758 {
8759 SCIPbtnodeFree(tree, &(*node)->right);
8760 assert((*node)->right == NULL);
8761 }
8762
8763 btnodeFreeLeaf(tree, node);
8764 assert(*node == NULL);
8765}
8766
8767/* some simple variable functions implemented as defines */
8768
8769/* In debug mode, the following methods are implemented as function calls to ensure
8770 * type validity.
8771 * In optimized mode, the methods are implemented as defines to improve performance.
8772 * However, we want to have them in the library anyways, so we have to undef the defines.
8773 */
8774
8775#undef SCIPbtnodeGetData
8776#undef SCIPbtnodeGetKey
8777#undef SCIPbtnodeGetParent
8778#undef SCIPbtnodeGetLeftchild
8779#undef SCIPbtnodeGetRightchild
8780#undef SCIPbtnodeGetSibling
8781#undef SCIPbtnodeIsRoot
8782#undef SCIPbtnodeIsLeaf
8783#undef SCIPbtnodeIsLeftchild
8784#undef SCIPbtnodeIsRightchild
8785
8786/** returns the user data pointer stored in that node */
8788 SCIP_BTNODE* node /**< node */
8789 )
8790{
8791 assert(node != NULL);
8792
8793 return node->dataptr;
8794}
8795
8796/** returns the parent which can be NULL if the given node is the root */
8798 SCIP_BTNODE* node /**< node */
8799 )
8800{
8801 assert(node != NULL);
8802
8803 return node->parent;
8804}
8805
8806/** returns left child which can be NULL if the given node is a leaf */
8808 SCIP_BTNODE* node /**< node */
8809 )
8810{
8811 assert(node != NULL);
8812
8813 return node->left;
8814}
8815
8816/** returns right child which can be NULL if the given node is a leaf */
8818 SCIP_BTNODE* node /**< node */
8819 )
8820{
8821 assert(node != NULL);
8822
8823 return node->right;
8824}
8825
8826/** returns the sibling of the node or NULL if does not exist */
8828 SCIP_BTNODE* node /**< node */
8829 )
8830{
8831 SCIP_BTNODE* parent;
8832
8833 parent = SCIPbtnodeGetParent(node);
8834
8835 if( parent == NULL )
8836 return NULL;
8837
8838 if( SCIPbtnodeGetLeftchild(parent) == node )
8839 return SCIPbtnodeGetRightchild(parent);
8840
8841 assert(SCIPbtnodeGetRightchild(parent) == node);
8842
8843 return SCIPbtnodeGetLeftchild(parent);
8844}
8845
8846/** returns whether the node is a root node */
8848 SCIP_BTNODE* node /**< node */
8849 )
8850{
8851 assert(node != NULL);
8852
8853 return (node->parent == NULL);
8854}
8855
8856/** returns whether the node is a leaf */
8858 SCIP_BTNODE* node /**< node */
8859 )
8860{
8861 assert(node != NULL);
8862
8863 return (node->left == NULL && node->right == NULL);
8864}
8865
8866/** returns TRUE if the given node is left child */
8868 SCIP_BTNODE* node /**< node */
8869 )
8870{
8871 SCIP_BTNODE* parent;
8872
8873 if( SCIPbtnodeIsRoot(node) )
8874 return FALSE;
8875
8876 parent = SCIPbtnodeGetParent(node);
8877
8878 if( SCIPbtnodeGetLeftchild(parent) == node )
8879 return TRUE;
8880
8881 return FALSE;
8882}
8883
8884/** returns TRUE if the given node is right child */
8886 SCIP_BTNODE* node /**< node */
8887 )
8888{
8889 SCIP_BTNODE* parent;
8890
8891 if( SCIPbtnodeIsRoot(node) )
8892 return FALSE;
8893
8894 parent = SCIPbtnodeGetParent(node);
8895
8896 if( SCIPbtnodeGetRightchild(parent) == node )
8897 return TRUE;
8898
8899 return FALSE;
8900}
8901
8902/** sets the give node data
8903 *
8904 * @note The old user pointer is not freed.
8905 */
8907 SCIP_BTNODE* node, /**< node */
8908 void* dataptr /**< node user data pointer */
8909 )
8910{
8911 assert(node != NULL);
8912
8913 node->dataptr = dataptr;
8914}
8915
8916/** sets parent node
8917 *
8918 * @note The old parent including the rooted subtree is not delete.
8919 */
8921 SCIP_BTNODE* node, /**< node */
8922 SCIP_BTNODE* parent /**< new parent node, or NULL */
8923 )
8924{
8925 assert(node != NULL);
8926
8927 node->parent = parent;
8928}
8929
8930/** sets left child
8931 *
8932 * @note The old left child including the rooted subtree is not delete.
8933 */
8935 SCIP_BTNODE* node, /**< node */
8936 SCIP_BTNODE* left /**< new left child, or NULL */
8937 )
8938{
8939 assert(node != NULL);
8940
8941 node->left = left;
8942}
8943
8944/** sets right child
8945 *
8946 * @note The old right child including the rooted subtree is not delete.
8947 */
8949 SCIP_BTNODE* node, /**< node */
8950 SCIP_BTNODE* right /**< new right child, or NULL */
8951 )
8952{
8953 assert(node != NULL);
8954
8955 node->right = right;
8956}
8957
8958/** creates an binary tree */
8960 SCIP_BT** tree, /**< pointer to store the created binary tree */
8961 BMS_BLKMEM* blkmem /**< block memory used to createnode */
8962 )
8963{
8964 assert(tree != NULL);
8965 assert(blkmem != NULL);
8966
8967 SCIP_ALLOC( BMSallocBlockMemory(blkmem, tree) );
8968 (*tree)->blkmem = blkmem;
8969 (*tree)->root = NULL;
8970
8971 return SCIP_OKAY;
8972}
8973
8974/** frees binary tree
8975 *
8976 * @note The user pointers (object) of the nodes are not freed. If needed, it has to be done by the user.
8977 */
8979 SCIP_BT** tree /**< pointer to binary tree */
8980 )
8981{
8982 assert(tree != NULL);
8983
8984 if( (*tree)->root != NULL )
8985 {
8986 SCIPbtnodeFree(*tree, &((*tree)->root));
8987 }
8988
8989 BMSfreeBlockMemory((*tree)->blkmem, tree);
8990}
8991
8992/** prints the rooted subtree of the given binary tree node in GML format into the given file */
8993static
8995 SCIP_BTNODE* node, /**< binary tree node */
8996 FILE* file, /**< file to write to */
8997 int* nnodes /**< pointer to count the number of nodes */
8998 )
8999{
9000 SCIP_BTNODE* left;
9001 SCIP_BTNODE* right;
9002 char label[SCIP_MAXSTRLEN];
9003
9004 assert(node != NULL);
9005
9006 (*nnodes)++;
9007 (void)SCIPsnprintf(label, SCIP_MAXSTRLEN, "%d", *nnodes);
9008
9009 SCIPgmlWriteNode(file, (unsigned int)(size_t)node, label, "circle", NULL, NULL);
9010
9011 left = SCIPbtnodeGetLeftchild(node);
9012 right = SCIPbtnodeGetRightchild(node);
9013
9014 if( left != NULL )
9015 {
9016 btPrintSubtree(left, file, nnodes);
9017
9018 SCIPgmlWriteArc(file, (unsigned int)(size_t)node, (unsigned int)(size_t)left, NULL, NULL);
9019 }
9020
9021 if( right != NULL )
9022 {
9023 btPrintSubtree(right, file, nnodes);
9024
9025 SCIPgmlWriteArc(file, (unsigned int)(size_t)node, (unsigned int)(size_t)right, NULL, NULL);
9026 }
9027}
9028
9029/** prints the binary tree in GML format into the given file */
9031 SCIP_BT* tree, /**< binary tree */
9032 FILE* file /**< file to write to */
9033 )
9034{
9035 /* write GML opening */
9037
9038 if( !SCIPbtIsEmpty(tree) )
9039 {
9040 SCIP_BTNODE* root;
9041 int nnodes;
9042
9043 root = SCIPbtGetRoot(tree);
9044 assert(root != NULL);
9045
9046 nnodes = 0;
9047
9048 btPrintSubtree(root, file, &nnodes);
9049 }
9050
9051 /* write GML closing */
9052 SCIPgmlWriteClosing(file);
9053}
9054
9055/* some simple variable functions implemented as defines */
9056#undef SCIPbtIsEmpty
9057#undef SCIPbtGetRoot
9058
9059/** returns whether the binary tree is empty (has no nodes) */
9061 SCIP_BT* tree /**< binary tree */
9062 )
9063{
9064 assert(tree != NULL);
9065
9066 return (tree->root == NULL);
9067}
9068
9069/** returns the the root node of the binary or NULL if the binary tree is empty */
9071 SCIP_BT* tree /**< tree to be evaluated */
9072 )
9073{
9074 assert(tree != NULL);
9075
9076 return tree->root;
9077}
9078
9079/** sets root node
9080 *
9081 * @note The old root including the rooted subtree is not delete.
9082 */
9084 SCIP_BT* tree, /**< tree to be evaluated */
9085 SCIP_BTNODE* root /**< new root, or NULL */
9086 )
9087{
9088 assert(tree != NULL);
9089
9090 tree->root = root;
9091}
9092
9093
9094/*
9095 * Numerical methods
9096 */
9097
9098/** returns the machine epsilon: the smallest number eps > 0, for which 1.0 + eps > 1.0 */
9100 void
9101 )
9102{
9103 SCIP_Real eps;
9104 SCIP_Real lasteps;
9105 SCIP_Real one;
9106 SCIP_Real onepluseps;
9107
9108 one = 1.0;
9109 eps = 1.0;
9110 do
9111 {
9112 lasteps = eps;
9113 eps /= 2.0;
9114 onepluseps = one + eps;
9115 }
9116 while( onepluseps > one );
9117
9118 return lasteps;
9119}
9120
9121/** calculates the greatest common divisor of the two given values */
9123 SCIP_Longint val1, /**< first value of greatest common devisor calculation */
9124 SCIP_Longint val2 /**< second value of greatest common devisor calculation */
9125 )
9126{
9127 int t;
9128
9129 assert(val1 > 0);
9130 assert(val2 > 0);
9131
9132 t = 0;
9133 /* if val1 is even, divide it by 2 */
9134 while( !(val1 & 1) )
9135 {
9136 val1 >>= 1; /*lint !e704*/
9137
9138 /* if val2 is even too, divide it by 2 and increase t(=number of e) */
9139 if( !(val2 & 1) )
9140 {
9141 val2 >>= 1; /*lint !e704*/
9142 ++t;
9143 }
9144 /* only val1 can be odd */
9145 else
9146 {
9147 /* while val1 is even, divide it by 2 */
9148 while( !(val1 & 1) )
9149 val1 >>= 1; /*lint !e704*/
9150
9151 break;
9152 }
9153 }
9154
9155 /* while val2 is even, divide it by 2 */
9156 while( !(val2 & 1) )
9157 val2 >>= 1; /*lint !e704*/
9158
9159 /* the following if/else condition is only to make sure that we do not overflow when adding up both values before
9160 * dividing them by 4 in the following while loop
9161 */
9162 if( t == 0 )
9163 {
9164 if( val1 > val2 )
9165 {
9166 val1 -= val2;
9167
9168 /* divide val1 by 2 as long as possible */
9169 while( !(val1 & 1) )
9170 val1 >>= 1; /*lint !e704*/
9171 }
9172 else if( val1 < val2 )
9173 {
9174 val2 -= val1;
9175
9176 /* divide val2 by 2 as long as possible */
9177 while( !(val2 & 1) )
9178 val2 >>= 1; /*lint !e704*/
9179 }
9180 }
9181
9182 /* val1 and val2 are odd */
9183 while( val1 != val2 )
9184 {
9185 if( val1 > val2 )
9186 {
9187 /* we can stop if one value reached one */
9188 if( val2 == 1 )
9189 return (val2 << t); /*lint !e647 !e703*/
9190
9191 /* if ((val1 xor val2) and 2) = 2, then gcd(val1, val2) = gcd((val1 + val2)/4, val2),
9192 * and otherwise gcd(val1, val2) = gcd((val1 − val2)/4, val2)
9193 */
9194 if( ((val1 ^ val2) & 2) == 2 )
9195 val1 += val2;
9196 else
9197 val1 -= val2;
9198
9199 assert((val1 & 3) == 0);
9200 val1 >>= 2; /*lint !e704*/
9201
9202 /* if val1 is still even, divide it by 2 */
9203 while( !(val1 & 1) )
9204 val1 >>= 1; /*lint !e704*/
9205 }
9206 else
9207 {
9208 /* we can stop if one value reached one */
9209 if( val1 == 1 )
9210 return (val1 << t); /*lint !e647 !e703*/
9211
9212 /* if ((val2 xor val1) and 2) = 2, then gcd(val2, val1) = gcd((val2 + val1)/4, val1),
9213 * and otherwise gcd(val2, val1) = gcd((val2 − val1)/4, val1)
9214 */
9215 if( ((val2 ^ val1) & 2) == 2 )
9216 val2 += val1;
9217 else
9218 val2 -= val1;
9219
9220 assert((val2 & 3) == 0);
9221 val2 >>= 2; /*lint !e704*/
9222
9223 /* if val2 is still even, divide it by 2 */
9224 while( !(val2 & 1) )
9225 val2 >>= 1; /*lint !e704*/
9226 }
9227 }
9228
9229 return (val1 << t); /*lint !e703*/
9230}
9231
9232
9233/* for the MS compiler, the function nextafter is named _nextafter */
9234#if defined(_MSC_VER) && !defined(NO_NEXTAFTER)
9235#define nextafter(x,y) _nextafter(x,y)
9236#endif
9237
9238/* on systems where the function nextafter is not defined, we provide an implementation from Sun */
9239#ifdef NO_NEXTAFTER
9240/* The following implementation of the routine nextafter() comes with the following license:
9241 *
9242 * ====================================================
9243 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
9244 *
9245 * Developed at SunSoft, a Sun Microsystems, Inc. business.
9246 * Permission to use, copy, modify, and distribute this
9247 * software is freely granted, provided that this notice
9248 * is preserved.
9249 * ====================================================
9250 */
9251
9252#define __HI(x) *(1+(int*)&x)
9253#define __LO(x) *(int*)&x
9254#define __HIp(x) *(1+(int*)x)
9255#define __LOp(x) *(int*)x
9256
9257static
9258double nextafter(double x, double y)
9259{
9260 int hx;
9261 int hy;
9262 int ix;
9263 int iy;
9264 unsigned lx;
9265 unsigned ly;
9266
9267 /* cppcheck-suppress invalidPointerCast */
9268 hx = __HI(x); /* high word of x */
9269 /* cppcheck-suppress invalidPointerCast */
9270 lx = __LO(x); /* low word of x */
9271 /* cppcheck-suppress invalidPointerCast */
9272 hy = __HI(y); /* high word of y */
9273 /* cppcheck-suppress invalidPointerCast */
9274 ly = __LO(y); /* low word of y */
9275 ix = hx&0x7fffffff; /* |x| */
9276 iy = hy&0x7fffffff; /* |y| */
9277
9278 if( ((ix>=0x7ff00000) && ((ix-0x7ff00000)|lx) != 0 ) || /* x is nan */
9279 ( (iy>=0x7ff00000) && ((iy-0x7ff00000)|ly) != 0 )) /* y is nan */
9280 return x + y;
9281
9282 /* x == y, return x */
9283 if( x == y )
9284 return x;
9285
9286 /* x == 0 */
9287 if( (ix|lx) == 0 )
9288 {
9289 /* return +-minsubnormal */
9290 /* cppcheck-suppress invalidPointerCast */
9291 __HI(x) = hy&0x80000000;
9292 /* cppcheck-suppress invalidPointerCast */
9293 __LO(x) = 1;
9294 y = x * x;
9295 if ( y == x )
9296 return y;
9297 else
9298 return x; /* raise underflow flag */
9299 }
9300 /* x > 0 */
9301 if( hx >= 0 )
9302 {
9303 /* x > y, x -= ulp */
9304 if( hx > hy || ((hx == hy) && (lx > ly)) )
9305 {
9306 if ( lx == 0 )
9307 hx -= 1;
9308 lx -= 1;
9309 }
9310 else
9311 {
9312 /* x < y, x += ulp */
9313 lx += 1;
9314 if ( lx == 0 )
9315 hx += 1;
9316 }
9317 }
9318 else
9319 {
9320 /* x < 0 */
9321 if( hy >= 0 || hx > hy || ((hx == hy) && (lx > ly)) )
9322 {
9323 /* x < y, x -= ulp */
9324 if ( lx == 0 )
9325 hx -= 1;
9326 lx -= 1;
9327 }
9328 else
9329 {
9330 /* x > y, x += ulp */
9331 lx += 1;
9332 if( lx == 0 )
9333 hx += 1;
9334 }
9335 }
9336 hy = hx&0x7ff00000;
9337 /* overflow */
9338 if( hy >= 0x7ff00000 )
9339 return x + x;
9340 if( hy < 0x00100000 )
9341 {
9342 /* underflow */
9343 y = x*x;
9344 if( y != x )
9345 {
9346 /* raise underflow flag */
9347 /* cppcheck-suppress invalidPointerCast */
9348 __HI(y) = hx;
9349 /* cppcheck-suppress invalidPointerCast */
9350 __LO(y) = lx;
9351 return y;
9352 }
9353 }
9354
9355 /* cppcheck-suppress invalidPointerCast */
9356 __HI(x) = hx;
9357 /* cppcheck-suppress invalidPointerCast */
9358 __LO(x) = lx;
9359 return x;
9360}
9361#endif
9362
9363
9364/** returns the next representable value of from in the direction of to */
9366 SCIP_Real from, /**< value from which the next representable value should be returned */
9367 SCIP_Real to /**< direction in which the next representable value should be returned */
9368 )
9369{
9370 return nextafter(from, to);
9371}
9372
9373/** calculates the smallest common multiple of the two given values */
9375 SCIP_Longint val1, /**< first value of smallest common multiple calculation */
9376 SCIP_Longint val2 /**< second value of smallest common multiple calculation */
9377 )
9378{
9379 SCIP_Longint gcd;
9380
9381 assert(val1 > 0);
9382 assert(val2 > 0);
9383
9384 gcd = SCIPcalcGreComDiv(val1, val2);
9385
9386 return val1/gcd * val2;
9387}
9388
9389static 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,
9390 17.0, 18.0, 19.0, 25.0, -1.0};
9391
9392/** converts a real number into a (approximate) rational representation, and returns TRUE iff the conversion was
9393 * successful
9394 */
9396 SCIP_Real val, /**< real value r to convert into rational number */
9397 SCIP_Real mindelta, /**< minimal allowed difference r - q of real r and rational q = n/d */
9398 SCIP_Real maxdelta, /**< maximal allowed difference r - q of real r and rational q = n/d */
9399 SCIP_Longint maxdnom, /**< maximal denominator allowed */
9400 SCIP_Longint* numerator, /**< pointer to store the numerator n of the rational number */
9401 SCIP_Longint* denominator /**< pointer to store the denominator d of the rational number */
9402 )
9403{
9404 SCIP_Real a;
9405 SCIP_Real b;
9406 SCIP_Real g0;
9407 SCIP_Real g1;
9408 SCIP_Real gx;
9409 SCIP_Real h0;
9410 SCIP_Real h1;
9411 SCIP_Real hx;
9412 SCIP_Real delta0;
9413 SCIP_Real delta1;
9414 SCIP_Real epsilon;
9415 int i;
9416
9417 assert(mindelta <= 0.0);
9418 assert(maxdelta >= 0.0);
9419 assert(numerator != NULL);
9420 assert(denominator != NULL);
9421
9422 if( REALABS(val) >= ((SCIP_Real)SCIP_LONGINT_MAX) / maxdnom )
9423 return FALSE;
9424
9425 /* try the simple denominators first: each value of the simpledenoms table multiplied by powers of 10
9426 * is tried as denominator
9427 */
9428 for( i = 0; simplednoms[i] > 0.0; ++i )
9429 {
9430 SCIP_Real nom;
9431 SCIP_Real dnom;
9432 SCIP_Real ratval0;
9433 SCIP_Real ratval1;
9434
9435 /* try powers of 10 (including 10^0) */
9436 dnom = simplednoms[i];
9437 while( dnom <= maxdnom )
9438 {
9439 nom = floor(val * dnom);
9440 ratval0 = nom/dnom;
9441 ratval1 = (nom+1.0)/dnom;
9442 if( mindelta <= val - ratval0 && val - ratval1 <= maxdelta )
9443 {
9444 if( val - ratval0 <= maxdelta )
9445 {
9446 *numerator = (SCIP_Longint)nom;
9447 *denominator = (SCIP_Longint)dnom;
9448 return TRUE;
9449 }
9450 if( mindelta <= val - ratval1 )
9451 {
9452 *numerator = (SCIP_Longint)(nom+1.0);
9453 *denominator = (SCIP_Longint)dnom;
9454 return TRUE;
9455 }
9456 }
9457 dnom *= 10.0;
9458 }
9459 }
9460
9461 /* the simple denominators didn't work: calculate rational representation with arbitrary denominator */
9462 epsilon = MIN(-mindelta, maxdelta)/2.0;
9463
9464 b = val;
9465 a = EPSFLOOR(b, epsilon);
9466 g0 = a;
9467 h0 = 1.0;
9468 g1 = 1.0;
9469 h1 = 0.0;
9470 delta0 = val - g0/h0;
9471 delta1 = (delta0 < 0.0 ? val - (g0-1.0)/h0 : val - (g0+1.0)/h0);
9472
9473 while( (delta0 < mindelta || delta0 > maxdelta) && (delta1 < mindelta || delta1 > maxdelta) )
9474 {
9475 assert(EPSGT(b, a, epsilon));
9476 assert(h0 >= 0.0);
9477 assert(h1 >= 0.0);
9478
9479 b = 1.0 / (b - a);
9480 a = EPSFLOOR(b, epsilon);
9481
9482 assert(a >= 0.0);
9483 gx = g0;
9484 hx = h0;
9485
9486 g0 = a * g0 + g1;
9487 h0 = a * h0 + h1;
9488
9489 g1 = gx;
9490 h1 = hx;
9491
9492 if( h0 > maxdnom )
9493 return FALSE;
9494
9495 delta0 = val - g0/h0;
9496 delta1 = (delta0 < 0.0 ? val - (g0-1.0)/h0 : val - (g0+1.0)/h0);
9497 }
9498
9499 if( REALABS(g0) > (SCIP_Real)(SCIP_LONGINT_MAX >> 4) || h0 > (SCIP_Real)(SCIP_LONGINT_MAX >> 4) )
9500 return FALSE;
9501
9502 assert(h0 > 0.5);
9503
9504 if( delta0 < mindelta )
9505 {
9506 assert(mindelta <= delta1 && delta1 <= maxdelta);
9507 *numerator = (SCIP_Longint)(g0 - 1.0);
9508 *denominator = (SCIP_Longint)h0;
9509 }
9510 else if( delta0 > maxdelta )
9511 {
9512 assert(mindelta <= delta1 && delta1 <= maxdelta);
9513 *numerator = (SCIP_Longint)(g0 + 1.0);
9514 *denominator = (SCIP_Longint)h0;
9515 }
9516 else
9517 {
9518 *numerator = (SCIP_Longint)g0;
9519 *denominator = (SCIP_Longint)h0;
9520 }
9521 assert(*denominator >= 1);
9522 assert(val - (SCIP_Real)(*numerator)/(SCIP_Real)(*denominator) >= mindelta);
9523 assert(val - (SCIP_Real)(*numerator)/(SCIP_Real)(*denominator) <= maxdelta);
9524
9525 return TRUE;
9526}
9527
9528/** checks, whether the given scalar scales the given value to an integral number with error in the given bounds */
9529static
9531 SCIP_Real val, /**< value that should be scaled to an integral value */
9532 SCIP_Real scalar, /**< scalar that should be tried */
9533 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
9534 SCIP_Real maxdelta /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
9535 )
9536{
9537 SCIP_Real sval;
9538 SCIP_Real downval;
9539 SCIP_Real upval;
9540
9541 assert(mindelta <= 0.0);
9542 assert(maxdelta >= 0.0);
9543
9544 sval = val * scalar;
9545 downval = floor(sval);
9546 upval = ceil(sval);
9547
9548 return (SCIPrelDiff(sval, downval) <= maxdelta || SCIPrelDiff(sval, upval) >= mindelta);
9549}
9550
9551/** additional scalars that are tried in integrality scaling */
9552static const SCIP_Real scalars[] = {3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0};
9553static const int nscalars = 9;
9554
9555/** tries to find a value, such that all given values, if scaled with this value become integral in relative allowed
9556 * difference in between mindelta and maxdelta
9557 */
9559 SCIP_Real* vals, /**< values to scale */
9560 int nvals, /**< number of values to scale */
9561 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
9562 SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
9563 SCIP_Longint maxdnom, /**< maximal denominator allowed in rational numbers */
9564 SCIP_Real maxscale, /**< maximal allowed scalar */
9565 SCIP_Real* intscalar, /**< pointer to store scalar that would make the coefficients integral, or NULL */
9566 SCIP_Bool* success /**< stores whether returned value is valid */
9567 )
9568{
9569 SCIP_Real bestscalar;
9570 SCIP_Longint gcd;
9571 SCIP_Longint scm;
9572 SCIP_Longint numerator;
9573 SCIP_Longint denominator;
9574 SCIP_Real val;
9575 SCIP_Real minval;
9576 SCIP_Real absval;
9577 SCIP_Real scaleval;
9578 SCIP_Bool scalable;
9579 SCIP_Bool rational;
9580 int c;
9581 int s;
9582 int i;
9583
9584 assert(vals != NULL);
9585 assert(nvals >= 0);
9586 assert(maxdnom >= 1);
9587 assert(mindelta < 0.0);
9588 assert(maxdelta > 0.0);
9589 assert(success != NULL);
9590
9591 SCIPdebugMessage("trying to find rational representation for given values\n");
9592
9593 if( intscalar != NULL )
9594 *intscalar = SCIP_INVALID;
9595 *success = FALSE;
9596
9597 /* get minimal absolute non-zero value */
9598 minval = SCIP_REAL_MAX;
9599 for( c = 0; c < nvals; ++c )
9600 {
9601 val = vals[c];
9602 if( val < mindelta || val > maxdelta )
9603 {
9604 absval = REALABS(val);
9605 minval = MIN(minval, absval);
9606 }
9607 }
9608
9609 if( minval == SCIP_REAL_MAX ) /*lint !e777*/
9610 {
9611 /* all coefficients are zero (inside tolerances) */
9612 if( intscalar != NULL )
9613 *intscalar = 1.0;
9614 *success = TRUE;
9615 SCIPdebugMessage(" -> all values are zero (inside tolerances)\n");
9616
9617 return SCIP_OKAY;
9618 }
9619 assert(minval > MIN(-mindelta, maxdelta));
9620
9621 bestscalar = SCIP_INVALID;
9622
9623 for( i = 0; i < 2; ++i )
9624 {
9625 scalable = TRUE;
9626
9627 /* try, if values can be made integral multiplying them with the reciprocal of the smallest value and a power of 2 */
9628 if( i == 0 )
9629 scaleval = 1.0/minval;
9630 /* try, if values can be made integral by multiplying them by a power of 2 */
9631 else
9632 scaleval = 1.0;
9633
9634 for( c = 0; c < nvals && scalable; ++c )
9635 {
9636 /* check, if the value can be scaled with a simple scalar */
9637 val = vals[c];
9638 if( val == 0.0 ) /* zeros are allowed in the vals array */
9639 continue;
9640
9641 absval = REALABS(val);
9642 while( scaleval <= maxscale
9643 && (absval * scaleval < 0.5 || !isIntegralScalar(val, scaleval, mindelta, maxdelta)) )
9644 {
9645 for( s = 0; s < nscalars; ++s )
9646 {
9647 if( isIntegralScalar(val, scaleval * scalars[s], mindelta, maxdelta) )
9648 {
9649 scaleval *= scalars[s];
9650 break;
9651 }
9652 }
9653 if( s >= nscalars )
9654 scaleval *= 2.0;
9655 }
9656 scalable = (scaleval <= maxscale);
9657 SCIPdebugMessage(" -> val=%g, scaleval=%g, val*scaleval=%g, scalable=%u\n",
9658 val, scaleval, val*scaleval, scalable);
9659 }
9660 if( scalable )
9661 {
9662 /* make values integral by dividing them by the smallest value (and multiplying them with a power of 2) */
9663 assert(scaleval <= maxscale);
9664
9665 /* check if we found a better scaling value */
9666 if( scaleval < bestscalar )
9667 bestscalar = scaleval;
9668
9669 SCIPdebugMessage(" -> integrality could be achieved by scaling with %g\n", scaleval);
9670
9671 /* if the scalar is still the reciprocal of the minimal value, all coeffcients are the same and we do not get a better scalar */
9672 if( i == 0 && EPSEQ(scaleval, 1.0/minval, SCIP_DEFAULT_EPSILON) )
9673 {
9674 if( intscalar != NULL )
9675 *intscalar = bestscalar;
9676 *success = TRUE;
9677
9678 return SCIP_OKAY;
9679 }
9680 }
9681 }
9682
9683 /* convert each value into a rational number, calculate the greatest common divisor of the numerators
9684 * and the smallest common multiple of the denominators
9685 */
9686 gcd = 1;
9687 scm = 1;
9688 rational = TRUE;
9689
9690 /* first value (to initialize gcd) */
9691 for( c = 0; c < nvals && rational; ++c )
9692 {
9693 val = vals[c];
9694 if( val == 0.0 ) /* zeros are allowed in the vals array */
9695 continue;
9696
9697 rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &numerator, &denominator);
9698 if( rational && numerator != 0 )
9699 {
9700 assert(denominator > 0);
9701 gcd = ABS(numerator);
9702 scm = denominator;
9703 rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
9704 SCIPdebugMessage(" -> c=%d first rational: val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
9705 c, val, numerator, denominator, gcd, scm, rational);
9706 break;
9707 }
9708 }
9709
9710 /* remaining values */
9711 for( ++c; c < nvals && rational; ++c )
9712 {
9713 val = vals[c];
9714 if( val == 0.0 ) /* zeros are allowed in the vals array */
9715 continue;
9716
9717 rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &numerator, &denominator);
9718 if( rational && numerator != 0 )
9719 {
9720 assert(denominator > 0);
9721 gcd = SCIPcalcGreComDiv(gcd, ABS(numerator));
9722 scm *= denominator / SCIPcalcGreComDiv(scm, denominator);
9723 rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
9724 SCIPdebugMessage(" -> c=%d next rational : val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
9725 c, val, numerator, denominator, gcd, scm, rational);
9726 }
9727 else
9728 {
9729 SCIPdebugMessage(" -> failed to convert %g into a rational representation\n", val);
9730 }
9731 }
9732
9733 if( rational )
9734 {
9735 /* make values integral by multiplying them with the smallest common multiple of the denominators */
9736 assert((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
9737
9738 /* check if we found a better scaling value */
9739 if( (SCIP_Real)scm/(SCIP_Real)gcd < bestscalar )
9740 bestscalar = (SCIP_Real)scm/(SCIP_Real)gcd;
9741
9742 SCIPdebugMessage(" -> integrality could be achieved by scaling with %g (rational:%" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ")\n",
9743 (SCIP_Real)scm/(SCIP_Real)gcd, scm, gcd);
9744 }
9745
9746 if( bestscalar < SCIP_INVALID )
9747 {
9748 if( intscalar != NULL )
9749 *intscalar = bestscalar;
9750 *success = TRUE;
9751
9752 SCIPdebugMessage(" -> smallest value to achieve integrality is %g \n", bestscalar);
9753 }
9754
9755 return SCIP_OKAY;
9756}
9757
9758/* Inform compiler that this code accesses the floating-point environment, so that
9759 * certain optimizations should be omitted (http://www.cplusplus.com/reference/cfenv/FENV_ACCESS/).
9760 * Not supported by Clang (gives warning) and GCC (silently), at the moment.
9761 */
9762#if defined(__INTEL_COMPILER) || defined(_MSC_VER)
9763#pragma fenv_access (on)
9764#elif defined(__GNUC__) && !defined(__clang__)
9765#pragma STDC FENV_ACCESS ON
9766#endif
9767#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
9768#if defined(__clang__)
9769__attribute__((optnone))
9770#else
9771__attribute__((optimize(0)))
9772#endif
9773#endif
9774/** given a (usually very small) interval, tries to find a rational number with simple denominator (i.e. a small
9775 * number, probably multiplied with powers of 10) out of this interval; returns TRUE iff a valid rational
9776 * number inside the interval was found
9777 */
9779 SCIP_Real lb, /**< lower bound of the interval */
9780 SCIP_Real ub, /**< upper bound of the interval */
9781 SCIP_Longint maxdnom, /**< maximal denominator allowed for resulting rational number */
9782 SCIP_Longint* numerator, /**< pointer to store the numerator n of the rational number */
9783 SCIP_Longint* denominator /**< pointer to store the denominator d of the rational number */
9784 )
9785{
9786 SCIP_Real center;
9787 SCIP_Real delta;
9788
9789 assert(lb <= ub);
9790
9791 center = 0.5*(lb+ub);
9792
9793 /* in order to compute a rational number that is exactly within the bounds (as the user expects),
9794 * we computed the allowed delta with downward rounding, if available
9795 */
9797 {
9798 SCIP_ROUNDMODE roundmode;
9799
9800 roundmode = SCIPintervalGetRoundingMode();
9802
9803 delta = 0.5*(ub-lb);
9804
9805 SCIPintervalSetRoundingMode(roundmode);
9806 }
9807 else
9808 {
9809 delta = 0.5*(ub-lb);
9810 }
9811
9812 return SCIPrealToRational(center, -delta, +delta, maxdnom, numerator, denominator);
9813}
9814
9815#if defined(__INTEL_COMPILER) || defined(_MSC_VER)
9816#pragma fenv_access (off)
9817#elif defined(__GNUC__) && !defined(__clang__)
9818#pragma STDC FENV_ACCESS OFF
9819#endif
9820
9821/** given a (usually very small) interval, selects a value inside this interval; it is tried to select a rational number
9822 * with simple denominator (i.e. a small number, probably multiplied with powers of 10);
9823 * if no valid rational number inside the interval was found, selects the central value of the interval
9824 */
9826 SCIP_Real lb, /**< lower bound of the interval */
9827 SCIP_Real ub, /**< upper bound of the interval */
9828 SCIP_Longint maxdnom /**< maximal denominator allowed for resulting rational number */
9829 )
9830{
9831 SCIP_Real val;
9832
9833 val = 0.5*(lb+ub);
9834 if( lb < ub )
9835 {
9836 SCIP_Longint numerator;
9837 SCIP_Longint denominator;
9838 SCIP_Bool success;
9839
9840 /* try to find a "simple" rational number inside the interval */
9841 SCIPdebugMessage("simple rational in [%.9f,%.9f]:", lb, ub);
9842 success = SCIPfindSimpleRational(lb, ub, maxdnom, &numerator, &denominator);
9843 if( success )
9844 {
9845 val = (SCIP_Real)numerator/(SCIP_Real)denominator;
9846 SCIPdebugPrintf(" %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT " == %.9f\n", numerator, denominator, val);
9847
9848 if( val - lb < 0.0 || val - ub > 0.0 )
9849 {
9850 SCIPdebugPrintf(" value is out of interval bounds by %g -> failed\n", MAX(lb-val, val-ub));
9851 val = 0.5*(lb+ub);
9852 }
9853 }
9854 else
9855 {
9856 SCIPdebugPrintf(" failed\n");
9857 }
9858 }
9859
9860 return val;
9861}
9862
9863/** Performs the Newton Procedure from a given starting point to compute a root of the given function with
9864 * specified precision and maximum number of iterations. If the procedure fails, SCIP_INVALID is returned.
9865 */
9867 SCIP_DECL_NEWTONEVAL((*function)), /**< pointer to function for which roots are computed */
9868 SCIP_DECL_NEWTONEVAL((*derivative)), /**< pointer to derivative of above function */
9869 SCIP_Real* params, /**< parameters needed for function (can be NULL) */
9870 int nparams, /**< number of parameters (can be 0) */
9871 SCIP_Real x, /**< starting point */
9872 SCIP_Real eps, /**< tolerance */
9873 int k /**< iteration limit */
9874 )
9875{
9876 SCIP_Real result = x;
9877 int iteration = 0;
9878
9879 assert(function != NULL);
9880 assert(derivative != NULL);
9881 assert(params != NULL || nparams == 0);
9882 assert(eps > 0.0);
9883 assert(k >= 0);
9884 assert(x != SCIP_INVALID); /*lint !e777*/
9885
9886 while( iteration < k )
9887 {
9888 SCIP_Real deriv = derivative(result, params, nparams);
9889
9890 /* if we arrive at a stationary point, the procedure is aborted */
9891 if( REALABS(deriv) <= eps || deriv == SCIP_INVALID ) /*lint !e777*/
9892 return SCIP_INVALID;
9893
9894 result = result - function(result, params, nparams) / deriv;
9895
9896 /* if new point is within eps-range of 0, we are done */
9897 if( REALABS(function(result, params, nparams)) <= eps )
9898 break;
9899
9900 ++iteration;
9901 }
9902
9903 if( k == iteration )
9904 return SCIP_INVALID;
9905 else
9906 return result;
9907}
9908
9909
9910/*
9911 * Random Numbers
9912 */
9913
9914#if defined(NO_RAND_R) || defined(_WIN32) || defined(_WIN64)
9915
9916#define SCIP_RAND_MAX 32767
9917/** returns a random number between 0 and SCIP_RAND_MAX */
9918static
9919int getRand(
9920 unsigned int* seedp /**< pointer to seed value */
9921 )
9922{
9923 SCIP_Longint nextseed;
9924
9925 assert(seedp != NULL);
9926
9927 nextseed = (*seedp) * (SCIP_Longint)1103515245 + 12345;
9928 *seedp = (unsigned int)nextseed;
9929
9930 return (int)((unsigned int)(nextseed/(2*(SCIP_RAND_MAX+1))) % (SCIP_RAND_MAX+1));
9931}
9932
9933#else
9934
9935#define SCIP_RAND_MAX RAND_MAX
9936
9937/** returns a random number between 0 and SCIP_RAND_MAX */
9938static
9940 unsigned int* seedp /**< pointer to seed value */
9941 )
9942{
9943 return rand_r(seedp);
9944}
9945
9946#endif
9947
9948/** returns a random integer between minrandval and maxrandval */
9949static
9951 int minrandval, /**< minimal value to return */
9952 int maxrandval, /**< maximal value to return */
9953 unsigned int* seedp /**< pointer to seed value */
9954 )
9955{
9956 SCIP_Real randnumber;
9957
9958 randnumber = (SCIP_Real)getRand(seedp)/(SCIP_RAND_MAX+1.0);
9959 assert(randnumber >= 0.0);
9960 assert(randnumber < 1.0);
9961
9962 /* we multiply minrandval and maxrandval separately by randnumber in order to avoid overflow if they are more than INT_MAX
9963 * apart
9964 */
9965 return (int) (minrandval*(1.0 - randnumber) + maxrandval*randnumber + randnumber);
9966}
9967
9968/** returns a random real between minrandval and maxrandval */
9969static
9971 SCIP_Real minrandval, /**< minimal value to return */
9972 SCIP_Real maxrandval, /**< maximal value to return */
9973 unsigned int* seedp /**< pointer to seed value */
9974 )
9975{
9976 SCIP_Real randnumber;
9977
9978 randnumber = (SCIP_Real)getRand(seedp)/(SCIP_Real)SCIP_RAND_MAX;
9979 assert(randnumber >= 0.0);
9980 assert(randnumber <= 1.0);
9981
9982 /* we multiply minrandval and maxrandval separately by randnumber in order to avoid overflow if they are more than
9983 * SCIP_REAL_MAX apart
9984 */
9985 return minrandval*(1.0 - randnumber) + maxrandval*randnumber;
9986}
9987
9988/** returns a random integer between minrandval and maxrandval
9989 *
9990 * @deprecated Please use SCIPrandomGetInt() to request a random integer.
9991 */
9993 int minrandval, /**< minimal value to return */
9994 int maxrandval, /**< maximal value to return */
9995 unsigned int* seedp /**< pointer to seed value */
9996 )
9997{
9998 return getRandomInt(minrandval, maxrandval, seedp);
9999}
10000
10001/** returns a random real between minrandval and maxrandval
10002 *
10003 * @deprecated Please use SCIPrandomGetReal() to request a random real.
10004 */
10006 SCIP_Real minrandval, /**< minimal value to return */
10007 SCIP_Real maxrandval, /**< maximal value to return */
10008 unsigned int* seedp /**< pointer to seed value */
10009 )
10010{
10011 return getRandomReal(minrandval, maxrandval, seedp);
10012}
10013
10014
10015/* initial seeds for KISS random number generator */
10016#define DEFAULT_SEED UINT32_C(123456789)
10017#define DEFAULT_XOR UINT32_C(362436000)
10018#define DEFAULT_MWC UINT32_C(521288629)
10019#define DEFAULT_CST UINT32_C(7654321)
10020
10021
10022/** initializes a random number generator with a given start seed */
10024 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10025 unsigned int initseed /**< initial random seed */
10026 )
10027{
10028 assert(randnumgen != NULL);
10029
10030 /* use MAX() to avoid zero after over flowing */
10031 randnumgen->seed = MAX(SCIPhashTwo(DEFAULT_SEED, initseed), 1u);
10032 randnumgen->xor_seed = MAX(SCIPhashTwo(DEFAULT_XOR, initseed), 1u);
10033 randnumgen->mwc_seed = MAX(SCIPhashTwo(DEFAULT_MWC, initseed), 1u);
10034 randnumgen->cst_seed = SCIPhashTwo(DEFAULT_CST, initseed);
10035
10036 assert(randnumgen->seed > 0);
10037 assert(randnumgen->xor_seed > 0);
10038 assert(randnumgen->mwc_seed > 0);
10039}
10040
10041/** returns a random number between 0 and UINT32_MAX
10042 *
10043 * implementation of KISS random number generator developed by George Marsaglia.
10044 * KISS is combination of three different random number generators:
10045 * - Linear congruential generator
10046 * - Xorshift
10047 * - Lag-1 Multiply-with-carry
10048 *
10049 * KISS has a period of 2^123 and passes all statistical test part of BigCrush-Test of TestU01 [1].
10050 *
10051 * [1] http://dl.acm.org/citation.cfm?doid=1268776.1268777
10052 */
10053static
10055 SCIP_RANDNUMGEN* randnumgen /**< random number generator */
10056 )
10057{
10058 uint64_t t;
10059
10060 /* linear congruential */
10061 randnumgen->seed = (uint32_t) (randnumgen->seed * UINT64_C(1103515245) + UINT64_C(12345));
10062
10063 /* Xorshift */
10064 randnumgen->xor_seed ^= (randnumgen->xor_seed << 13);
10065 randnumgen->xor_seed ^= (randnumgen->xor_seed >> 17);
10066 randnumgen->xor_seed ^= (randnumgen->xor_seed << 5);
10067
10068 /* Multiply-with-carry */
10069 t = UINT64_C(698769069) * randnumgen->mwc_seed + randnumgen->cst_seed;
10070 randnumgen->cst_seed = (uint32_t) (t >> 32);
10071 randnumgen->mwc_seed = (uint32_t) t;
10072
10073 return randnumgen->seed + randnumgen->xor_seed + randnumgen->mwc_seed;
10074}
10075
10076/** creates and initializes a random number generator */
10078 SCIP_RANDNUMGEN** randnumgen, /**< random number generator */
10079 BMS_BLKMEM* blkmem, /**< block memory */
10080 unsigned int initialseed /**< initial random seed */
10081 )
10082{
10083 assert(randnumgen != NULL);
10084
10085 SCIP_ALLOC( BMSallocBlockMemory(blkmem, randnumgen) );
10086
10087 SCIPrandomSetSeed((*randnumgen), initialseed);
10088
10089 return SCIP_OKAY;
10090}
10091
10092/** frees a random number generator */
10094 SCIP_RANDNUMGEN** randnumgen, /**< random number generator */
10095 BMS_BLKMEM* blkmem /**< block memory */
10096 )
10097{
10098 assert(randnumgen != NULL);
10099 assert((*randnumgen) != NULL);
10100
10101 BMSfreeBlockMemory(blkmem, randnumgen);
10102
10103 return;
10104}
10105
10106
10107
10108/** returns a random integer between minrandval and maxrandval */
10110 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10111 int minrandval, /**< minimal value to return */
10112 int maxrandval /**< maximal value to return */
10113 )
10114{
10115 SCIP_Real randnumber;
10116 SCIP_Longint zeromax;
10117
10118 randnumber = (SCIP_Real)randomGetRand(randnumgen)/(UINT32_MAX+1.0);
10119 assert(randnumber >= 0.0);
10120 assert(randnumber < 1.0);
10121
10122 /* we need to shift the range to the non-negative integers to handle negative integer values correctly.
10123 * we use a long integer to avoid overflows.
10124 */
10125 zeromax = (SCIP_Longint)maxrandval - (SCIP_Longint)minrandval + 1;
10126
10127 return (int) ((SCIP_Longint)(zeromax * randnumber) + (SCIP_Longint)minrandval);
10128}
10129
10130/** returns a random real between minrandval and maxrandval */
10132 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10133 SCIP_Real minrandval, /**< minimal value to return */
10134 SCIP_Real maxrandval /**< maximal value to return */
10135 )
10136{
10137 SCIP_Real randnumber;
10138
10139 randnumber = (SCIP_Real)randomGetRand(randnumgen)/(SCIP_Real)UINT32_MAX;
10140 assert(randnumber >= 0.0);
10141 assert(randnumber <= 1.0);
10142
10143 /* we multiply minrandval and maxrandval separately by randnumber in order to avoid overflow if they are more than
10144 * SCIP_REAL_MAX apart
10145 */
10146 return minrandval*(1.0 - randnumber) + maxrandval*randnumber;
10147}
10148
10149/** randomly shuffles parts of an integer array using the Fisher-Yates algorithm */
10151 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10152 int* array, /**< array to be shuffled */
10153 int begin, /**< first included index that should be subject to shuffling
10154 * (0 for first array entry)
10155 */
10156 int end /**< first excluded index that should not be subject to shuffling
10157 * (array size for last array entry)
10158 */
10159 )
10160{
10161 int tmp;
10162 int i;
10163
10164 /* loop backwards through all elements and always swap the current last element to a random position */
10165 while( end > begin+1 )
10166 {
10167 --end;
10168
10169 /* get a random position into which the last entry should be shuffled */
10170 i = SCIPrandomGetInt(randnumgen, begin, end);
10171
10172 /* swap the last element and the random element */
10173 tmp = array[i];
10174 array[i] = array[end];
10175 array[end] = tmp;
10176 }
10177}
10178
10179/** randomly shuffles parts of an array using the Fisher-Yates algorithm */
10181 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10182 void** array, /**< array to be shuffled */
10183 int begin, /**< first included index that should be subject to shuffling
10184 * (0 for first array entry)
10185 */
10186 int end /**< first excluded index that should not be subject to shuffling
10187 * (array size for last array entry)
10188 */
10189 )
10190{
10191 void* tmp;
10192 int i;
10193
10194 /* loop backwards through all elements and always swap the current last element to a random position */
10195 while( end > begin+1 )
10196 {
10197 end--;
10198
10199 /* get a random position into which the last entry should be shuffled */
10200 i = SCIPrandomGetInt(randnumgen, begin, end);
10201
10202 /* swap the last element and the random element */
10203 tmp = array[i];
10204 array[i] = array[end];
10205 array[end] = tmp;
10206 }
10207}
10208
10209/** draws a random subset of disjoint elements from a given set of disjoint elements;
10210 * this implementation is suited for the case that nsubelems is considerably smaller then nelems
10211 */
10213 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10214 void** set, /**< original set, from which elements should be drawn */
10215 int nelems, /**< number of elements in original set */
10216 void** subset, /**< subset in which drawn elements should be stored */
10217 int nsubelems /**< number of elements that should be drawn and stored */
10218 )
10219{
10220 int i;
10221 int j;
10222
10223 /* if both sets are of equal size, we just copy the array */
10224 if( nelems == nsubelems)
10225 {
10226 BMScopyMemoryArray(subset,set,nelems);
10227 return SCIP_OKAY;
10228 }
10229
10230 /* abort, if size of subset is too big */
10231 if( nsubelems > nelems )
10232 {
10233 SCIPerrorMessage("Cannot create %d-elementary subset of %d-elementary set.\n", nsubelems, nelems);
10234 return SCIP_INVALIDDATA;
10235 }
10236#ifndef NDEBUG
10237 for( i = 0; i < nsubelems; i++ )
10238 for( j = 0; j < i; j++ )
10239 assert(set[i] != set[j]);
10240#endif
10241
10242 /* draw each element individually */
10243 i = 0;
10244 while( i < nsubelems )
10245 {
10246 int r;
10247
10248 r = SCIPrandomGetInt(randnumgen, 0, nelems-1);
10249 subset[i] = set[r];
10250
10251 /* if we get an element that we already had, we will draw again */
10252 for( j = 0; j < i; j++ )
10253 {
10254 if( subset[i] == subset[j] )
10255 {
10256 --i;
10257 break;
10258 }
10259 }
10260 ++i;
10261 }
10262 return SCIP_OKAY;
10263}
10264
10265/*
10266 * Additional math functions
10267 */
10268
10269/** calculates a binomial coefficient n over m, choose m elements out of n, maximal value will be 33 over 16 (because
10270 * 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
10271 * big numbers or an negative value m (and m < n) and -1 will be returned
10272 */
10274 int n, /**< number of different elements */
10275 int m /**< number to choose out of the above */
10276 )
10277{
10278 if( m == 0 || m >= n )
10279 return 1;
10280
10281 if( m < 0 )
10282 return -1;
10283
10284 /* symmetry of the binomial coefficient, choose smaller m */
10285 if( m > n/2 )
10286 m = n - m;
10287
10288 /* trivial case m == 1 */
10289 if( m == 1 )
10290 return n;
10291
10292 /* simple case m == 2 */
10293 if( m == 2 )
10294 {
10295 if( ((SCIP_Real)SCIP_LONGINT_MAX) / n >= (n-1) * 2 ) /*lint !e790*/
10296 return ((SCIP_Longint)n*(n-1)/2); /*lint !e647*/
10297 else
10298 return -1;
10299 }
10300
10301 /* abort on to big numbers */
10302 if( m > 16 || n > 33 )
10303 return -1;
10304
10305 /* simple case m == 3 */
10306 if( m == 3 )
10307 return (n*(n-1)*(n-2)/6); /*lint !e647*/
10308 else
10309 {
10310 /* first half of Pascal's triangle numbers(without the symmetric part) backwards from (33,16) over (32,16),
10311 * (33,15), (32,15),(31,15, (30,15), (33,14) to (8,4) (rest is calculated directly)
10312 *
10313 * due to this order we can extract the right binomial coefficient by (16-m)^2+(16-m)+(33-n)
10314 */
10315 static const SCIP_Longint binoms[182] = {
10316 1166803110, 601080390, 1037158320, 565722720, 300540195, 155117520, 818809200, 471435600, 265182525, 145422675,
10317 77558760, 40116600, 573166440, 347373600, 206253075, 119759850, 67863915, 37442160, 20058300, 10400600,
10318 354817320, 225792840, 141120525, 86493225, 51895935, 30421755, 17383860, 9657700, 5200300, 2704156, 193536720,
10319 129024480, 84672315, 54627300, 34597290, 21474180, 13037895, 7726160, 4457400, 2496144, 1352078, 705432,
10320 92561040, 64512240, 44352165, 30045015, 20030010, 13123110, 8436285, 5311735, 3268760, 1961256, 1144066,
10321 646646, 352716, 184756, 38567100, 28048800, 20160075, 14307150, 10015005, 6906900, 4686825, 3124550, 2042975,
10322 1307504, 817190, 497420, 293930, 167960, 92378, 48620, 13884156, 10518300, 7888725, 5852925, 4292145, 3108105,
10323 2220075, 1562275, 1081575, 735471, 490314, 319770, 203490, 125970, 75582, 43758, 24310, 12870, 4272048, 3365856,
10324 2629575, 2035800, 1560780, 1184040, 888030, 657800, 480700, 346104, 245157, 170544, 116280, 77520, 50388, 31824,
10325 19448, 11440, 6435, 3432, 1107568, 906192, 736281, 593775, 475020, 376740, 296010, 230230, 177100, 134596,
10326 100947, 74613, 54264, 38760, 27132, 18564, 12376, 8008, 5005, 3003, 1716, 924, 237336, 201376, 169911, 142506,
10327 118755, 98280, 80730, 65780, 53130, 42504, 33649, 26334, 20349, 15504, 11628, 8568, 6188, 4368, 3003, 2002,
10328 1287, 792, 462, 252, 40920, 35960, 31465, 27405, 23751, 20475, 17550, 14950, 12650, 10626, 8855, 7315, 5985,
10329 4845, 3876, 3060, 2380, 1820, 1365, 1001, 715, 495, 330, 210, 126, 70};
10330
10331 /* m can at most be 16 */
10332 const int t = 16-m;
10333 assert(t >= 0);
10334 assert(n <= 33);
10335
10336 /* binoms array hast exactly 182 elements */
10337 assert(t*(t+1)+(33-n) < 182);
10338
10339 return binoms[t*(t+1)+(33-n)]; /*lint !e662 !e661*/
10340 }
10341}
10342
10343#ifndef NDEBUG
10344/** calculates hash for floating-point number by using Fibonacci hashing */
10345#if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ * 10 >= 490 && !defined(__INTEL_COMPILER)
10346__attribute__((no_sanitize_undefined))
10347#endif
10348unsigned int SCIPcalcFibHash(
10349 SCIP_Real v /**< number to hash */
10350 )
10351{
10352 if( v >= 0 )
10353 return ((unsigned long long)(v * 2654435769)) % UINT_MAX;
10354 return ((unsigned long long)(-v * 683565275)) % UINT_MAX;
10355}
10356#endif
10357
10358/** negates a number */
10360 SCIP_Real x /**< value to negate */
10361 )
10362{
10363 return -x;
10364}
10365
10366/*
10367 * Permutations / Shuffling
10368 */
10369
10370/** swaps two ints */
10372 int* value1, /**< pointer to first integer */
10373 int* value2 /**< pointer to second integer */
10374 )
10375{
10376 int tmp;
10377
10378 tmp = *value1;
10379 *value1 = *value2;
10380 *value2 = tmp;
10381}
10382
10383/** swaps two real values */
10385 SCIP_Real* value1, /**< pointer to first real value */
10386 SCIP_Real* value2 /**< pointer to second real value */
10387 )
10388{
10389 SCIP_Real tmp;
10390
10391 tmp = *value1;
10392 *value1 = *value2;
10393 *value2 = tmp;
10394}
10395
10396/** swaps the addresses of two pointers */
10398 void** pointer1, /**< first pointer */
10399 void** pointer2 /**< second pointer */
10400 )
10401{
10402 void* tmp;
10403
10404 tmp = *pointer1;
10405 *pointer1 = *pointer2;
10406 *pointer2 = tmp;
10407}
10408
10409/** randomly shuffles parts of an integer array using the Fisher-Yates algorithm
10410 *
10411 * @deprecated Please use SCIPrandomPermuteIntArray()
10412 */
10414 int* array, /**< array to be shuffled */
10415 int begin, /**< first included index that should be subject to shuffling
10416 * (0 for first array entry)
10417 */
10418 int end, /**< first excluded index that should not be subject to shuffling
10419 * (array size for last array entry)
10420 */
10421 unsigned int* randseed /**< seed value for the random generator */
10422 )
10423{
10424 int tmp;
10425 int i;
10426
10427 /* loop backwards through all elements and always swap the current last element to a random position */
10428 while( end > begin+1 )
10429 {
10430 --end;
10431
10432 /* get a random position into which the last entry should be shuffled */
10433 i = getRandomInt(begin, end, randseed);
10434
10435 /* swap the last element and the random element */
10436 tmp = array[i];
10437 array[i] = array[end];
10438 array[end] = tmp;
10439 }
10440}
10441
10442
10443/** randomly shuffles parts of an array using the Fisher-Yates algorithm
10444 *
10445 * @deprecated Please use SCIPrandomPermuteArray()
10446 */
10448 void** array, /**< array to be shuffled */
10449 int begin, /**< first included index that should be subject to shuffling
10450 * (0 for first array entry)
10451 */
10452 int end, /**< first excluded index that should not be subject to shuffling
10453 * (array size for last array entry)
10454 */
10455 unsigned int* randseed /**< seed value for the random generator */
10456 )
10457{
10458 void* tmp;
10459 int i;
10460
10461 /* loop backwards through all elements and always swap the current last element to a random position */
10462 while( end > begin+1 )
10463 {
10464 end--;
10465
10466 /* get a random position into which the last entry should be shuffled */
10467 i = getRandomInt(begin, end, randseed);
10468
10469 /* swap the last element and the random element */
10470 tmp = array[i];
10471 array[i] = array[end];
10472 array[end] = tmp;
10473 }
10474}
10475
10476/** draws a random subset of disjoint elements from a given set of disjoint elements;
10477 * this implementation is suited for the case that nsubelems is considerably smaller then nelems
10478 *
10479 * @deprecated Please use SCIPrandomGetSubset()
10480 */
10482 void** set, /**< original set, from which elements should be drawn */
10483 int nelems, /**< number of elements in original set */
10484 void** subset, /**< subset in which drawn elements should be stored */
10485 int nsubelems, /**< number of elements that should be drawn and stored */
10486 unsigned int randseed /**< seed value for random generator */
10487 )
10488{
10489 int i;
10490 int j;
10491
10492 /* if both sets are of equal size, we just copy the array */
10493 if( nelems == nsubelems)
10494 {
10495 BMScopyMemoryArray(subset,set,nelems);
10496 return SCIP_OKAY;
10497 }
10498
10499 /* abort, if size of subset is too big */
10500 if( nsubelems > nelems )
10501 {
10502 SCIPerrorMessage("Cannot create %d-elementary subset of %d-elementary set.\n", nsubelems, nelems);
10503 return SCIP_INVALIDDATA;
10504 }
10505#ifndef NDEBUG
10506 for( i = 0; i < nsubelems; i++ )
10507 for( j = 0; j < i; j++ )
10508 assert(set[i] != set[j]);
10509#endif
10510
10511 /* draw each element individually */
10512 i = 0;
10513 while( i < nsubelems )
10514 {
10515 int r;
10516
10517 r = getRandomInt(0, nelems-1, &randseed);
10518 subset[i] = set[r];
10519
10520 /* if we get an element that we already had, we will draw again */
10521 for( j = 0; j < i; j++ )
10522 {
10523 if( subset[i] == subset[j] )
10524 {
10525 --i;
10526 break;
10527 }
10528 }
10529 ++i;
10530 }
10531 return SCIP_OKAY;
10532}
10533
10534
10535/*
10536 * Arrays
10537 */
10538
10539/** computes set intersection (duplicates removed) of two integer arrays that are ordered ascendingly
10540 *
10541 * @deprecated Switch to SCIPcomputeArraysIntersectionInt().
10542 */
10544 int* array1, /**< first array (in ascending order) */
10545 int narray1, /**< number of entries of first array */
10546 int* array2, /**< second array (in ascending order) */
10547 int narray2, /**< number of entries of second array */
10548 int* intersectarray, /**< intersection of array1 and array2
10549 * (note: it is possible to use array1 for this input argument) */
10550 int* nintersectarray /**< pointer to store number of entries of intersection array
10551 * (note: it is possible to use narray1 for this input argument) */
10552 )
10553{
10554 SCIPcomputeArraysIntersectionInt(array1, narray1, array2, narray2, intersectarray, nintersectarray);
10555
10556 return SCIP_OKAY;
10557}
10558
10559/** computes set intersection (duplicates removed) of two integer arrays that are ordered ascendingly */
10561 int* array1, /**< first array (in ascending order) */
10562 int narray1, /**< number of entries of first array */
10563 int* array2, /**< second array (in ascending order) */
10564 int narray2, /**< number of entries of second array */
10565 int* intersectarray, /**< intersection of array1 and array2
10566 * (note: it is possible to use array1 for this input argument) */
10567 int* nintersectarray /**< pointer to store number of entries of intersection array
10568 * (note: it is possible to use narray1 for this input argument) */
10569 )
10570{
10571 int cnt = 0;
10572 int k = 0;
10573 int v1;
10574 int v2;
10575
10576 assert( array1 != NULL );
10577 assert( array2 != NULL );
10578 assert( intersectarray != NULL );
10579 assert( nintersectarray != NULL );
10580
10581 /* determine intersection of array1 and array2 */
10582 for (v1 = 0; v1 < narray1; ++v1)
10583 {
10584 assert( v1 == 0 || array1[v1] >= array1[v1-1] );
10585
10586 /* skip duplicate entries */
10587 if ( v1+1 < narray1 && array1[v1] == array1[v1+1])
10588 continue;
10589
10590 for (v2 = k; v2 < narray2; ++v2)
10591 {
10592 assert( v2 == 0 || array2[v2] >= array2[v2-1] );
10593
10594 if ( array2[v2] > array1[v1] )
10595 {
10596 k = v2;
10597 break;
10598 }
10599 else if ( array2[v2] == array1[v1] )
10600 {
10601 intersectarray[cnt++] = array2[v2];
10602 k = v2 + 1;
10603 break;
10604 }
10605 }
10606 }
10607
10608 /* store size of intersection array */
10609 *nintersectarray = cnt;
10610}
10611
10612/** computes set intersection (duplicates removed) of two void-pointer arrays that are ordered ascendingly */
10614 void** array1, /**< pointer to first data array */
10615 int narray1, /**< number of entries of first array */
10616 void** array2, /**< pointer to second data array */
10617 int narray2, /**< number of entries of second array */
10618 SCIP_DECL_SORTPTRCOMP((*ptrcomp)), /**< data element comparator */
10619 void** intersectarray, /**< intersection of array1 and array2
10620 * (note: it is possible to use array1 for this input argument) */
10621 int* nintersectarray /**< pointer to store number of entries of intersection array
10622 * (note: it is possible to use narray1 for this input argument) */
10623 )
10624{
10625 int cnt = 0;
10626 int k = 0;
10627 int v1;
10628 int v2;
10629
10630 assert( array1 != NULL );
10631 assert( array2 != NULL );
10632 assert( ptrcomp != NULL );
10633 assert( intersectarray != NULL );
10634 assert( nintersectarray != NULL );
10635
10636 /* determine intersection of array1 and array2 */
10637 for( v1 = 0; v1 < narray1; ++v1 )
10638 {
10639 assert( v1 == 0 || (*ptrcomp)(array1[v1], array1[v1-1]) >= 0 );
10640
10641 /* skip duplicate entries */
10642 if( v1+1 < narray1 && array1[v1] == array1[v1+1] )
10643 continue;
10644
10645 for( v2 = k; v2 < narray2; ++v2 )
10646 {
10647 assert( v2 == 0 || (*ptrcomp)(array2[v2], array2[v2-1]) > 0 || array2[v2] == array2[v2-1] );
10648
10649 if( (*ptrcomp)(array2[v2], array1[v1]) > 0 )
10650 {
10651 k = v2;
10652 break;
10653 }
10654
10655 if( array2[v2] == array1[v1] )
10656 {
10657 intersectarray[cnt++] = array2[v2];
10658 k = v2 + 1;
10659 break;
10660 }
10661 }
10662 }
10663
10664 /* store size of intersection array */
10665 *nintersectarray = cnt;
10666}
10667
10668
10669/** computes set difference (duplicates removed) of two integer arrays that are ordered ascendingly
10670 *
10671 * @deprecated Switch to SCIPcomputeArraysSetminusInt().
10672 */
10674 int* array1, /**< first array (in ascending order) */
10675 int narray1, /**< number of entries of first array */
10676 int* array2, /**< second array (in ascending order) */
10677 int narray2, /**< number of entries of second array */
10678 int* setminusarray, /**< array to store entries of array1 that are not an entry of array2
10679 * (note: it is possible to use array1 for this input argument) */
10680 int* nsetminusarray /**< pointer to store number of entries of setminus array
10681 * (note: it is possible to use narray1 for this input argument) */
10682 )
10683{
10684 SCIPcomputeArraysSetminusInt(array1, narray1, array2, narray2, setminusarray, nsetminusarray);
10685
10686 return SCIP_OKAY;
10687}
10688
10689/** computes set difference (duplicates removed) of two integer arrays that are ordered ascendingly */
10691 int* array1, /**< first array (in ascending order) */
10692 int narray1, /**< number of entries of first array */
10693 int* array2, /**< second array (in ascending order) */
10694 int narray2, /**< number of entries of second array */
10695 int* setminusarray, /**< array to store entries of array1 that are not an entry of array2
10696 * (note: it is possible to use array1 for this input argument) */
10697 int* nsetminusarray /**< pointer to store number of entries of setminus array
10698 * (note: it is possible to use narray1 for this input argument) */
10699 )
10700{
10701 int cnt = 0;
10702 int v1 = 0;
10703 int v2 = 0;
10704
10705 assert( array1 != NULL );
10706 assert( array2 != NULL );
10707 assert( setminusarray != NULL );
10708 assert( nsetminusarray != NULL );
10709
10710 while ( v1 < narray1 )
10711 {
10712 int entry1;
10713
10714 assert( v1 == 0 || array1[v1] >= array1[v1-1] );
10715
10716 /* skip duplicate entries */
10717 while ( v1 + 1 < narray1 && array1[v1] == array1[v1 + 1] )
10718 ++v1;
10719
10720 entry1 = array1[v1];
10721
10722 while ( v2 < narray2 && array2[v2] < entry1 )
10723 ++v2;
10724
10725 if ( v2 >= narray2 || entry1 < array2[v2] )
10726 setminusarray[cnt++] = entry1;
10727 ++v1;
10728 }
10729
10730 /* store size of setminus array */
10731 *nsetminusarray = cnt;
10732}
10733
10734
10735/*
10736 * Strings
10737 */
10738
10739
10740/** copies characters from 'src' to 'dest', copying is stopped when either the 'stop' character is reached or after
10741 * 'cnt' characters have been copied, whichever comes first.
10742 *
10743 * @note undefined behavior on overlapping arrays
10744 */
10746 char* dest, /**< destination pointer to copy to */
10747 const char* src, /**< source pointer to copy from */
10748 char stop, /**< character when found stop copying */
10749 unsigned int cnt /**< maximal number of characters to copy */
10750 )
10751{
10752 if( dest == NULL || src == NULL || cnt == 0 )
10753 return -1;
10754 else
10755 {
10756 char* destination = dest;
10757
10758 while( cnt-- && (*destination++ = *src++) != stop ); /*lint !e722*/
10759
10760 return (int)(destination - dest);
10761 }
10762}
10763
10764/** prints an error message containing of the given string followed by a string describing the current system error
10765 *
10766 * Prefers to use the strerror_r method, which is threadsafe. On systems where this method does not exist,
10767 * NO_STRERROR_R should be defined (see INSTALL). In this case, strerror is used which is not guaranteed to be
10768 * threadsafe (on SUN-systems, it actually is).
10769 */
10771 const char* message /**< first part of the error message, e.g. the filename */
10772 )
10773{
10774#ifdef NO_STRERROR_R
10775 SCIPmessagePrintError("%s: %s\n", message, strerror(errno));
10776#else
10777 char buf[SCIP_MAXSTRLEN];
10778
10779#if defined(_WIN32) || defined(_WIN64)
10780 /* strerror_s returns 0 on success; the string is \0 terminated. */
10781 if ( strerror_s(buf, SCIP_MAXSTRLEN, errno) != 0 )
10782 SCIPmessagePrintError("Unknown error number %d or error message too long.\n", errno);
10783 SCIPmessagePrintError("%s: %s\n", message, buf);
10784#elif (_POSIX_C_SOURCE >= 200112L || __DARWIN_C_LEVEL > 200112L || _XOPEN_SOURCE >= 600) && ! defined(_GNU_SOURCE)
10785 /* We are in the POSIX/XSI case, where strerror_r returns 0 on success; \0 termination is unclear. */
10786 if ( strerror_r(errno, buf, SCIP_MAXSTRLEN) != 0 )
10787 SCIPmessagePrintError("Unknown error number %d.\n", errno);
10788 buf[SCIP_MAXSTRLEN - 1] = '\0';
10789 SCIPmessagePrintError("%s: %s\n", message, buf);
10790#else
10791 /* We are in the GNU case, where strerror_r returns a pointer to the error string. This string is possibly stored
10792 * in buf and is always \0 terminated.
10793 * However, if compiling on one system and executing on another system, we might actually call a different
10794 * variant of the strerror_r function than we had at compile time.
10795 */
10796 char* errordescr;
10797 *buf = '\0';
10798 errordescr = strerror_r(errno, buf, SCIP_MAXSTRLEN);
10799 if( *buf != '\0' )
10800 {
10801 /* strerror_r wrote into buf */
10802 SCIPmessagePrintError("%s: %s\n", message, buf);
10803 }
10804 else if( errordescr != NULL )
10805 {
10806 /* strerror_r returned something non-NULL */
10807 SCIPmessagePrintError("%s: %s\n", message, errordescr);
10808 }
10809 else
10810 {
10811 /* strerror_r did return NULL and did not write into buf */
10812 SCIPmessagePrintError("Could not obtain description for error %d.\n", errno);
10813 }
10814#endif
10815#endif
10816}
10817
10818/** extracts tokens from strings - wrapper method for strtok_r() */
10820 char* s, /**< string to parse */
10821 const char* delim, /**< delimiters for parsing */
10822 char** ptrptr /**< pointer to working char pointer - must stay the same while parsing */
10823 )
10824{
10825#ifdef SCIP_NO_STRTOK_R
10826 return strtok(s, delim);
10827#else
10828 return strtok_r(s, delim, ptrptr);
10829#endif
10830}
10831
10832/** translates the given string into a string where unescaped symbols ", ', and spaces are escaped with a \ prefix */
10834 char* t, /**< target buffer to store escaped string */
10835 int bufsize, /**< size of buffer t */
10836 const char* s /**< string to transform into escaped string */
10837 )
10838{
10839 int len;
10840 int i;
10841 int p;
10842
10843 assert(t != NULL);
10844 assert(bufsize > 0);
10845
10846 len = (int)strlen(s);
10847 for( p = 0, i = 0; i <= len && p < bufsize; ++i, ++p )
10848 {
10849 if( s[i] == '\\' )
10850 {
10851 t[p] = s[i];
10852 ++p;
10853 ++i;
10854 }
10855 else if( s[i] == ' ' || s[i] == '\"' || s[i] == '\'' )
10856 {
10857 t[p] = '\\';
10858 ++p;
10859 }
10860 if( i <= len && p < bufsize )
10861 t[p] = s[i];
10862 }
10863 t[bufsize-1] = '\0';
10864}
10865
10866/** increases string pointer as long as it refers to a space character or an explicit space control sequence */
10868 char** s /**< pointer to string pointer */
10869 )
10870{
10871 while( isspace(**s) || ( **s == '\\' && *(*s+1) != '\0' && strchr(SCIP_SPACECONTROL, *(*s+1)) ) )
10872 *s += **s == '\\' ? 2 : 1;
10873
10874 return SCIP_OKAY;
10875}
10876
10877/* safe version of snprintf */
10879 char* t, /**< target string */
10880 int len, /**< length of the string to copy */
10881 const char* s, /**< source string */
10882 ... /**< further parameters */
10883 )
10884{
10885 va_list ap;
10886 int n;
10887
10888 assert(t != NULL);
10889 assert(len > 0);
10890
10891 va_start(ap, s); /*lint !e826*/
10892
10893#if defined(_MSC_VER) && _MSC_VER < 1900
10894 n = _vsnprintf(t, (size_t) len, s, ap);
10895#else
10896 n = vsnprintf(t, (size_t) len, s, ap); /*lint !e571*/
10897#endif
10898 va_end(ap);
10899
10900 if( n < 0 || n >= len )
10901 {
10902#ifndef NDEBUG
10903 if( n < 0 )
10904 {
10905 SCIPerrorMessage("vsnprintf returned %d\n",n);
10906 }
10907#endif
10908 t[len-1] = '\0';
10909 }
10910 return n;
10911}
10912
10913/** portable version of strcasecmp for case-insensitive comparison of two strings */
10915 const char* s1, /**< first string */
10916 const char* s2 /**< second string */
10917 )
10918{
10919#ifdef _MSC_VER
10920 return _stricmp(s1, s2);
10921#else
10922 return strcasecmp(s1, s2);
10923#endif
10924}
10925
10926/** portable version of strncasecmp for case-insensitive comparison of two strings up to a given number of characters */
10928 const char* s1, /**< first string */
10929 const char* s2, /**< second string */
10930 int length /**< maximal length to compare */
10931 )
10932{
10933 assert(length >= 0);
10934#ifdef _MSC_VER
10935 return _strnicmp(s1, s2, (size_t)length);
10936#else
10937 return strncasecmp(s1, s2, (size_t)length); /*lint !e571*/
10938#endif
10939}
10940
10941/** safe version of strncpy
10942 *
10943 * Copies string in s to t using at most @a size-1 nonzero characters (strncpy copies size characters). It always adds
10944 * a terminating zero char. Does not pad the remaining string with zero characters (unlike strncpy). Returns the number
10945 * of copied nonzero characters, if the length of s is at most size - 1, and returns size otherwise. Thus, the original
10946 * string was truncated if the return value is size.
10947 */
10949 char* t, /**< target string */
10950 const char* s, /**< source string */
10951 int size /**< maximal size of t */
10952 )
10953{
10954 int n;
10955
10956 if( size <= 0 )
10957 return 0;
10958
10959 /* decrease size by 1 to create space for terminating zero char */
10960 --size;
10961 for( n = 0; n < size && *s != '\0'; n++ )
10962 *(t++) = *(s++);
10963 *t = '\0';
10964
10965 if( *s != '\0' )
10966 ++n;
10967
10968 return n;
10969}
10970
10971/** 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
10972 *
10973 * @return Returns TRUE if a value could be extracted, otherwise FALSE
10974 */
10976 const char* str, /**< string to search */
10977 int* value, /**< pointer to store the parsed value */
10978 char** endptr /**< pointer to store the final string position if successfully parsed, otherwise @p str */
10979 )
10980{
10981 assert(str != NULL);
10982 assert(value != NULL);
10983 assert(endptr != NULL);
10984
10985 /* init errno to detect possible errors */
10986 errno = 0;
10987
10988 *value = (int) strtol(str, endptr, 10);
10989
10990 if( *endptr != str && *endptr != NULL )
10991 {
10992 SCIPdebugMessage("parsed integer value <%d>\n", *value);
10993 return TRUE;
10994 }
10995 *endptr = (char*)str;
10996
10997 SCIPdebugMessage("failed parsing integer value <%s>\n", str);
10998
10999 return FALSE;
11000}
11001
11002/** 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
11003 *
11004 * @return Returns TRUE if a value could be extracted, otherwise FALSE
11005 */
11007 const char* str, /**< string to search */
11008 SCIP_Real* value, /**< pointer to store the parsed value */
11009 char** endptr /**< pointer to store the final string position if successfully parsed, otherwise @p str */
11010 )
11011{
11012 assert(str != NULL);
11013 assert(value != NULL);
11014 assert(endptr != NULL);
11015
11016 /* init errno to detect possible errors */
11017 errno = 0;
11018
11019 *value = strtod(str, endptr);
11020
11021 if( *endptr != str && *endptr != NULL )
11022 {
11023 SCIPdebugMessage("parsed real value <%g>\n", *value);
11024 return TRUE;
11025 }
11026 *endptr = (char*)str;
11027
11028 SCIPdebugMessage("failed parsing real value <%s>\n", str);
11029
11030 return FALSE;
11031}
11032
11033/** copies the first size characters between a start and end character of str into token, if no error occurred endptr
11034 * will point to the position after the read part, otherwise it will point to @p str
11035 */
11037 const char* str, /**< string to search */
11038 char startchar, /**< character which defines the beginning */
11039 char endchar, /**< character which defines the ending */
11040 char* token, /**< string to store the copy */
11041 int size, /**< size of the token char array */
11042 char** endptr /**< pointer to store the final string position if successfully parsed, otherwise @p str */
11043 )
11044{
11045 const char* copystr;
11046 int nchars;
11047
11048 assert(str != NULL);
11049 assert(token != NULL);
11050 assert(size > 0);
11051 assert(endptr != NULL);
11052
11053 nchars = 0;
11054
11055 copystr = str;
11056
11057 /* find starting character */
11058 while( *str != '\0' && *str != startchar )
11059 ++str;
11060
11061 /* did not find start character */
11062 if( *str == '\0' )
11063 {
11064 *endptr = (char*)copystr;
11065 return;
11066 }
11067
11068 /* skip start character */
11069 ++str;
11070
11071 /* copy string */
11072 while( *str != '\0' && *str != endchar && nchars < size-1 )
11073 {
11074 assert(nchars < SCIP_MAXSTRLEN);
11075 token[nchars] = *str;
11076 nchars++;
11077 ++str;
11078 }
11079
11080 /* add end to token */
11081 token[nchars] = '\0';
11082
11083 /* if section was longer than size, we want to reach the end of the parsing section anyway */
11084 if( nchars == (size-1) )
11085 while( *str != '\0' && *str != endchar )
11086 ++str;
11087
11088 /* did not find end character */
11089 if( *str == '\0' )
11090 {
11091 *endptr = (char*)copystr;
11092 return;
11093 }
11094
11095 /* skip end character */
11096 ++str;
11097
11098 SCIPdebugMessage("parsed section <%s>\n", token);
11099
11100 *endptr = (char*) str;
11101}
11102
11103/*
11104 * File methods
11105 */
11106
11107/** returns, whether the given file exists */
11109 const char* filename /**< file name */
11110 )
11111{
11112 FILE* f;
11113
11114 f = fopen(filename, "r");
11115 if( f == NULL )
11116 return FALSE;
11117
11118 fclose(f);
11119
11120 return TRUE;
11121}
11122
11123/** splits filename into path, name, and extension */
11125 char* filename, /**< filename to split; is destroyed (but not freed) during process */
11126 char** path, /**< pointer to store path, or NULL if not needed */
11127 char** name, /**< pointer to store name, or NULL if not needed */
11128 char** extension, /**< pointer to store extension, or NULL if not needed */
11129 char** compression /**< pointer to store compression extension, or NULL if not needed */
11130 )
11131{
11132 char* lastslash;
11133 char* lastbackslash;
11134 char* lastdot;
11135
11136 assert(filename != NULL);
11137
11138 if( path != NULL )
11139 *path = NULL;
11140 if( name != NULL )
11141 *name = NULL;
11142 if( extension != NULL )
11143 *extension = NULL;
11144 if( compression != NULL )
11145 *compression = NULL;
11146
11147 /* treat both slashes '/' and '\' as directory delimiters */
11148 lastslash = strrchr(filename, '/');
11149 lastbackslash = strrchr(filename, '\\');
11150 lastslash = MAX(lastslash, lastbackslash); /*lint !e613*/
11151 lastdot = strrchr(filename, '.');
11152 if( lastslash != NULL && lastdot != NULL && lastdot < lastslash ) /* is the last dot belonging to the path? */
11153 lastdot = NULL;
11154
11155 /* detect known compression extensions */
11156#ifdef SCIP_WITH_ZLIB
11157 if( lastdot != NULL )
11158 {
11159 char* compext;
11160
11161 compext = lastdot+1;
11162 if( strcmp(compext, "gz") == 0
11163 || strcmp(compext, "z") == 0
11164 || strcmp(compext, "Z") == 0 )
11165 {
11166 if( compression != NULL )
11167 *compression = compext;
11168 *lastdot = '\0';
11169 }
11170
11171 /* find again the last dot in the filename without compression extension */
11172 lastdot = strrchr(filename, '.');
11173 if( lastslash != NULL && lastdot != NULL && lastdot < lastslash ) /* is the last dot belonging to the path? */
11174 lastdot = NULL;
11175 }
11176#endif
11177
11178 if( lastslash == NULL )
11179 {
11180 if( name != NULL )
11181 *name = filename;
11182 }
11183 else
11184 {
11185 if( path != NULL )
11186 *path = filename;
11187 if( name != NULL )
11188 *name = lastslash+1;
11189 *lastslash = '\0';
11190 }
11191
11192 if( lastdot != NULL )
11193 {
11194 if( extension != NULL )
11195 *extension = lastdot+1;
11196 *lastdot = '\0';
11197 }
11198}
11199
11200/*
11201 * simple functions implemented as defines
11202 */
11203
11204/* In debug mode, the following methods are implemented as function calls to ensure
11205 * type validity.
11206 * In optimized mode, the methods are implemented as defines to improve performance.
11207 * However, we want to have them in the library anyways, so we have to undef the defines.
11208 */
11209
11210#undef SCIPrelDiff
11211
11212/** returns the relative difference: (val1-val2)/max(|val1|,|val2|,1.0) */
11214 SCIP_Real val1, /**< first value to be compared */
11215 SCIP_Real val2 /**< second value to be compared */
11216 )
11217{
11218 SCIP_Real absval1;
11219 SCIP_Real absval2;
11220 SCIP_Real quot;
11221
11222 absval1 = REALABS(val1);
11223 absval2 = REALABS(val2);
11224 quot = MAX3(1.0, absval1, absval2);
11225
11226 return (val1-val2)/quot;
11227}
11228
11229
11230/** computes the gap from the primal and the dual bound */
11232 SCIP_Real eps, /**< the value treated as zero */
11233 SCIP_Real inf, /**< the value treated as infinity */
11234 SCIP_Real primalbound, /**< the primal bound */
11235 SCIP_Real dualbound /**< the dual bound */
11236 )
11237{
11238 if( EPSEQ(primalbound, dualbound, eps) )
11239 return 0.0;
11240 else
11241 {
11242 SCIP_Real absdual = REALABS(dualbound);
11243 SCIP_Real absprimal = REALABS(primalbound);
11244
11245 if( EPSZ(dualbound, eps) || EPSZ(primalbound, eps) || absprimal >= inf || absdual >= inf ||
11246 primalbound * dualbound < 0.0 )
11247 return inf;
11248 else
11249 return REALABS((primalbound - dualbound)/MIN(absdual, absprimal));
11250 }
11251}
11252
11253/*
11254 * disjoint set (union-find) data structure
11255 */
11256
11257/** creates a disjoint set (union find) structure \p djset for \p ncomponents many components (of size one) */
11259 SCIP_DISJOINTSET** djset, /**< disjoint set (union find) data structure */
11260 BMS_BLKMEM* blkmem, /**< block memory */
11261 int ncomponents /**< number of components */
11262 )
11263{
11264 assert(djset != NULL);
11265 assert(blkmem != NULL);
11266
11267 /* allocate the necessary memory */
11268 assert(ncomponents > 0);
11269 SCIP_ALLOC( BMSallocBlockMemory(blkmem, djset) );
11270 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &((*djset)->parents), ncomponents) );
11271 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &((*djset)->sizes), ncomponents) );
11272 (*djset)->size = ncomponents;
11273
11274 /* clear the data structure */
11275 SCIPdisjointsetClear(*djset);
11276
11277 return SCIP_OKAY;
11278}
11279
11280/** clears the disjoint set (union find) structure \p djset */
11282 SCIP_DISJOINTSET* djset /**< disjoint set (union find) data structure */
11283 )
11284{
11285 int i;
11286
11287 djset->componentcount = djset->size;
11288
11289 /* reset all components to be unconnected */
11290 for( i = 0; i < djset->componentcount; i++ )
11291 {
11292 djset->parents[i] = i;
11293 djset->sizes[i] = 1;
11294 }
11295}
11296
11297/** finds and returns the component identifier of this \p element */
11299 SCIP_DISJOINTSET* djset, /**< disjoint set (union find) data structure */
11300 int element /**< element to be found */
11301 )
11302{
11303 int newelement;
11304 int root = element;
11305 int* parents = djset->parents;
11306
11307 /* find root of this element */
11308 while( root != parents[root] )
11309 {
11310 root = parents[root];
11311 }
11312
11313 /* compress the path to make future queries faster */
11314 while( element != root )
11315 {
11316 newelement = parents[element];
11317 parents[element] = root;
11318 element = newelement;
11319 }
11320
11321 return root;
11322}
11323
11324/** merges the components containing the elements \p p and \p q */
11326 SCIP_DISJOINTSET* djset, /**< disjoint set (union find) data structure */
11327 int p, /**< first element */
11328 int q, /**< second element */
11329 SCIP_Bool forcerepofp /**< force representative of p to be new representative */
11330 )
11331{
11332 int idp;
11333 int idq;
11334 int* sizes;
11335 int* parents;
11336
11337 assert(djset != NULL);
11338 assert(0 <= p);
11339 assert(0 <= q);
11340 assert(djset->size > p);
11341 assert(djset->size > q);
11342
11343 idp = SCIPdisjointsetFind(djset, p);
11344 idq = SCIPdisjointsetFind(djset, q);
11345
11346 /* if p and q lie in the same component, there is nothing to be done */
11347 if( idp == idq )
11348 return;
11349
11350 sizes = djset->sizes;
11351 parents = djset->parents;
11352
11353 if( forcerepofp )
11354 {
11355 parents[idq] = idp;
11356 sizes[idp] += sizes[idq];
11357 }
11358 else
11359 {
11360 if( sizes[idp] < sizes[idq] )
11361 {
11362 parents[idp] = idq;
11363 sizes[idq] += sizes[idp];
11364 }
11365 else
11366 {
11367 parents[idq] = idp;
11368 sizes[idp] += sizes[idq];
11369 }
11370 }
11371 /* one less component */
11372 djset->componentcount--;
11373}
11374
11375/** frees the disjoint set (union find) data structure */
11377 SCIP_DISJOINTSET** djset, /**< pointer to disjoint set (union find) data structure */
11378 BMS_BLKMEM* blkmem /**< block memory */
11379 )
11380{
11381 SCIP_DISJOINTSET* dsptr;
11382
11383 assert(djset != NULL);
11384 assert(*djset != NULL);
11385
11386 dsptr = *djset;
11387
11388 BMSfreeBlockMemoryArray(blkmem, &dsptr->sizes, dsptr->size);
11389 BMSfreeBlockMemoryArray(blkmem, &dsptr->parents, dsptr->size);
11390
11391 BMSfreeBlockMemory(blkmem, djset);
11392}
11393
11394/** returns the number of independent components in this disjoint set (union find) data structure */
11396 SCIP_DISJOINTSET* djset /**< disjoint set (union find) data structure */
11397 )
11398{
11399 assert(djset != NULL);
11400
11401 return djset->componentcount;
11402}
11403
11404/** returns the size (number of nodes) of this disjoint set (union find) data structure */
11406 SCIP_DISJOINTSET* djset /**< disjoint set (union find) data structure */
11407 )
11408{
11409 assert(djset != NULL);
11410
11411 return djset->size;
11412}
11413
11414/** checks whether a given string t appears at the beginning of the string s (up to spaces at beginning) */
11416 const char* s, /**< string to search in */
11417 const char* t, /**< string to search for */
11418 size_t tlen /**< length of t */
11419 )
11420{
11421 int idxctr = 0;
11422
11423 assert(s != NULL);
11424 assert(t != NULL);
11425
11426 /* skip whitespace at beginning */
11427 while( idxctr < SCIP_MAXSTRLEN && isspace((unsigned char)s[idxctr]) )
11428 ++idxctr;
11429 if( strncmp(&s[idxctr], t, tlen) == 0 )
11430 return TRUE;
11431 return FALSE;
11432}
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:262
#define SCIP_MAXSTRLEN
Definition: def.h:283
#define SCIP_Longint
Definition: def.h:157
#define SCIP_UNUSED(x)
Definition: def.h:423
#define LOG2(x)
Definition: def.h:225
#define SCIP_SPACECONTROL
Definition: def.h:284
#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:238
#define SCIP_ALLOC(x)
Definition: def.h:380
#define MAX3(x, y, z)
Definition: def.h:242
#define SCIP_ALLOC_TERMINATE(retcode, x, TERM)
Definition: def.h:400
#define SCIP_Real
Definition: def.h:172
#define ABS(x)
Definition: def.h:230
#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:234
#define SCIP_CALL_ABORT(x)
Definition: def.h:348
#define SCIP_CALL_TERMINATE(retcode, x, TERM)
Definition: def.h:390
#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:369
#define SCIP_CALL_FINALLY(x, y)
Definition: def.h:411
#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:10613
void SCIPcomputeArraysSetminusInt(int *array1, int narray1, int *array2, int narray2, int *setminusarray, int *nsetminusarray)
Definition: misc.c:10690
SCIP_RETCODE SCIPcomputeArraysIntersection(int *array1, int narray1, int *array2, int narray2, int *intersectarray, int *nintersectarray)
Definition: misc.c:10543
SCIP_RETCODE SCIPcomputeArraysSetminus(int *array1, int narray1, int *array2, int narray2, int *setminusarray, int *nsetminusarray)
Definition: misc.c:10673
void SCIPcomputeArraysIntersectionInt(int *array1, int narray1, int *array2, int narray2, int *intersectarray, int *nintersectarray)
Definition: misc.c:10560
void SCIPbtnodeSetRightchild(SCIP_BTNODE *node, SCIP_BTNODE *right)
Definition: misc.c:8948
SCIP_BTNODE * SCIPbtnodeGetRightchild(SCIP_BTNODE *node)
Definition: misc.c:8817
SCIP_Bool SCIPbtIsEmpty(SCIP_BT *tree)
Definition: misc.c:9060
SCIP_RETCODE SCIPbtCreate(SCIP_BT **tree, BMS_BLKMEM *blkmem)
Definition: misc.c:8959
void SCIPbtnodeFree(SCIP_BT *tree, SCIP_BTNODE **node)
Definition: misc.c:8742
SCIP_Bool SCIPbtnodeIsLeaf(SCIP_BTNODE *node)
Definition: misc.c:8857
void SCIPbtnodeSetData(SCIP_BTNODE *node, void *dataptr)
Definition: misc.c:8906
void * SCIPbtnodeGetData(SCIP_BTNODE *node)
Definition: misc.c:8787
SCIP_RETCODE SCIPbtnodeCreate(SCIP_BT *tree, SCIP_BTNODE **node, void *dataptr)
Definition: misc.c:8678
SCIP_Bool SCIPbtnodeIsRightchild(SCIP_BTNODE *node)
Definition: misc.c:8885
void SCIPbtnodeSetParent(SCIP_BTNODE *node, SCIP_BTNODE *parent)
Definition: misc.c:8920
SCIP_BTNODE * SCIPbtnodeGetSibling(SCIP_BTNODE *node)
Definition: misc.c:8827
SCIP_Bool SCIPbtnodeIsLeftchild(SCIP_BTNODE *node)
Definition: misc.c:8867
void SCIPbtnodeSetLeftchild(SCIP_BTNODE *node, SCIP_BTNODE *left)
Definition: misc.c:8934
SCIP_BTNODE * SCIPbtnodeGetParent(SCIP_BTNODE *node)
Definition: misc.c:8797
void SCIPbtFree(SCIP_BT **tree)
Definition: misc.c:8978
SCIP_BTNODE * SCIPbtnodeGetLeftchild(SCIP_BTNODE *node)
Definition: misc.c:8807
void SCIPbtSetRoot(SCIP_BT *tree, SCIP_BTNODE *root)
Definition: misc.c:9083
SCIP_Bool SCIPbtnodeIsRoot(SCIP_BTNODE *node)
Definition: misc.c:8847
SCIP_BTNODE * SCIPbtGetRoot(SCIP_BT *tree)
Definition: misc.c:9070
void SCIPbtPrintGml(SCIP_BT *tree, FILE *file)
Definition: misc.c:9030
void SCIPdigraphPrintComponents(SCIP_DIGRAPH *digraph, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: misc.c:8625
void ** SCIPdigraphGetSuccessorsData(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7839
void SCIPdigraphFreeComponents(SCIP_DIGRAPH *digraph)
Definition: misc.c:8519
int SCIPdigraphGetNSuccessors(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7806
SCIP_RETCODE SCIPdigraphComputeUndirectedComponents(SCIP_DIGRAPH *digraph, int minsize, int *components, int *ncomponents)
Definition: misc.c:8090
int SCIPdigraphGetNNodes(SCIP_DIGRAPH *digraph)
Definition: misc.c:7748
void SCIPdigraphPrintGml(SCIP_DIGRAPH *digraph, FILE *file)
Definition: misc.c:8586
void SCIPdigraphGetComponent(SCIP_DIGRAPH *digraph, int compidx, int **nodes, int *nnodes)
Definition: misc.c:8299
SCIP_RETCODE SCIPdigraphAddArc(SCIP_DIGRAPH *digraph, int startnode, int endnode, void *data)
Definition: misc.c:7664
SCIP_RETCODE SCIPdigraphTopoSortComponents(SCIP_DIGRAPH *digraph)
Definition: misc.c:8220
SCIP_RETCODE SCIPdigraphSetSizes(SCIP_DIGRAPH *digraph, int *sizes)
Definition: misc.c:7546
SCIP_RETCODE SCIPdigraphComputeDirectedComponents(SCIP_DIGRAPH *digraph, int compidx, int *strongcomponents, int *strongcompstartidx, int *nstrongcomponents)
Definition: misc.c:8431
SCIP_RETCODE SCIPdigraphAddArcSafe(SCIP_DIGRAPH *digraph, int startnode, int endnode, void *data)
Definition: misc.c:7695
void SCIPdigraphFree(SCIP_DIGRAPH **digraph)
Definition: misc.c:7570
int SCIPdigraphGetNArcs(SCIP_DIGRAPH *digraph)
Definition: misc.c:7788
void SCIPdigraphPrint(SCIP_DIGRAPH *digraph, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: misc.c:8551
void * SCIPdigraphGetNodeData(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7758
void SCIPdigraphSetNodeData(SCIP_DIGRAPH *digraph, void *dataptr, int node)
Definition: misc.c:7774
SCIP_RETCODE SCIPdigraphSetNSuccessors(SCIP_DIGRAPH *digraph, int node, int nsuccessors)
Definition: misc.c:7732
int * SCIPdigraphGetSuccessors(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7821
int SCIPdigraphGetNComponents(SCIP_DIGRAPH *digraph)
Definition: misc.c:8286
SCIP_RETCODE SCIPdigraphResize(SCIP_DIGRAPH *digraph, int nnodes)
Definition: misc.c:7416
SCIP_RETCODE SCIPdigraphGetArticulationPoints(SCIP_DIGRAPH *digraph, int **articulations, int *narticulations)
Definition: misc.c:8002
int SCIPdisjointsetGetSize(SCIP_DISJOINTSET *djset)
Definition: misc.c:11405
void SCIPdisjointsetClear(SCIP_DISJOINTSET *djset)
Definition: misc.c:11281
int SCIPdisjointsetGetComponentCount(SCIP_DISJOINTSET *djset)
Definition: misc.c:11395
int SCIPdisjointsetFind(SCIP_DISJOINTSET *djset, int element)
Definition: misc.c:11298
void SCIPdisjointsetUnion(SCIP_DISJOINTSET *djset, int p, int q, SCIP_Bool forcerepofp)
Definition: misc.c:11325
SCIP_Bool SCIPfileExists(const char *filename)
Definition: misc.c:11108
void SCIPsplitFilename(char *filename, char **path, char **name, char **extension, char **compression)
Definition: misc.c:11124
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:3110
void * SCIPhashmapEntryGetImage(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3572
SCIP_Real SCIPhashmapGetImageReal(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3303
SCIP_RETCODE SCIPhashmapInsertReal(SCIP_HASHMAP *hashmap, void *origin, SCIP_Real image)
Definition: misc.c:3230
void SCIPhashmapPrintStatistics(SCIP_HASHMAP *hashmap, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:3487
int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3283
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3263
SCIP_RETCODE SCIPhashmapSetImageReal(SCIP_HASHMAP *hashmap, void *origin, SCIP_Real image)
Definition: misc.c:3393
void SCIPhashmapEntrySetImageInt(SCIP_HASHMAPENTRY *entry, int image)
Definition: misc.c:3613
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:3158
SCIP_RETCODE SCIPhashmapSetImage(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:3325
int SCIPhashmapGetNElements(SCIP_HASHMAP *hashmap)
Definition: misc.c:3535
int SCIPhashmapEntryGetImageInt(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3582
void SCIPhashmapEntrySetImageReal(SCIP_HASHMAPENTRY *entry, SCIP_Real image)
Definition: misc.c:3624
int SCIPhashmapGetNEntries(SCIP_HASHMAP *hashmap)
Definition: misc.c:3543
SCIP_HASHMAPENTRY * SCIPhashmapGetEntry(SCIP_HASHMAP *hashmap, int entryidx)
Definition: misc.c:3551
void SCIPhashmapEntrySetImage(SCIP_HASHMAPENTRY *entry, void *image)
Definition: misc.c:3602
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3076
void * SCIPhashmapEntryGetOrigin(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3562
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3425
SCIP_RETCODE SCIPhashmapInsertInt(SCIP_HASHMAP *hashmap, void *origin, int image)
Definition: misc.c:3194
SCIP_Bool SCIPhashmapIsEmpty(SCIP_HASHMAP *hashmap)
Definition: misc.c:3525
SCIP_RETCODE SCIPhashmapRemoveAll(SCIP_HASHMAP *hashmap)
Definition: misc.c:3635
SCIP_Real SCIPhashmapEntryGetImageReal(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3592
SCIP_RETCODE SCIPhashmapRemove(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3441
SCIP_RETCODE SCIPhashmapSetImageInt(SCIP_HASHMAP *hashmap, void *origin, int image)
Definition: misc.c:3359
void SCIPhashsetFree(SCIP_HASHSET **hashset, BMS_BLKMEM *blkmem)
Definition: misc.c:3792
void SCIPhashsetPrintStatistics(SCIP_HASHSET *hashset, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:3935
SCIP_Bool SCIPhashsetExists(SCIP_HASHSET *hashset, void *element)
Definition: misc.c:3819
void ** SCIPhashsetGetSlots(SCIP_HASHSET *hashset)
Definition: misc.c:4010
int SCIPhashsetGetNElements(SCIP_HASHSET *hashset)
Definition: misc.c:3994
int SCIPhashsetGetNSlots(SCIP_HASHSET *hashset)
Definition: misc.c:4002
void SCIPhashsetRemoveAll(SCIP_HASHSET *hashset)
Definition: misc.c:4018
SCIP_Bool SCIPhashsetIsEmpty(SCIP_HASHSET *hashset)
Definition: misc.c:3986
SCIP_RETCODE SCIPhashsetInsert(SCIP_HASHSET *hashset, BMS_BLKMEM *blkmem, void *element)
Definition: misc.c:3802
SCIP_RETCODE SCIPhashsetCreate(SCIP_HASHSET **hashset, BMS_BLKMEM *blkmem, int size)
Definition: misc.c:3761
SCIP_RETCODE SCIPhashsetRemove(SCIP_HASHSET *hashset, void *element)
Definition: misc.c:3860
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:9122
SCIP_Longint SCIPcalcBinomCoef(int n, int m)
Definition: misc.c:10273
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9374
SCIP_Real SCIPselectSimpleValue(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom)
Definition: misc.c:9825
SCIP_Real SCIPcomputeGap(SCIP_Real eps, SCIP_Real inf, SCIP_Real primalbound, SCIP_Real dualbound)
Definition: misc.c:11231
SCIP_Bool SCIPfindSimpleRational(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom, SCIP_Longint *numerator, SCIP_Longint *denominator)
Definition: misc.c:9778
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:9866
SCIP_Real SCIPnextafter(SCIP_Real from, SCIP_Real to)
Definition: misc.c:9365
SCIP_Real SCIPcalcMachineEpsilon(void)
Definition: misc.c:9099
unsigned int SCIPcalcFibHash(SCIP_Real v)
Definition: misc.c:10348
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *numerator, SCIP_Longint *denominator)
Definition: misc.c:9395
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:9558
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:11213
void SCIPswapInts(int *value1, int *value2)
Definition: misc.c:10371
void SCIPrandomPermuteIntArray(SCIP_RANDNUMGEN *randnumgen, int *array, int begin, int end)
Definition: misc.c:10150
void SCIPswapPointers(void **pointer1, void **pointer2)
Definition: misc.c:10397
void SCIPpermuteArray(void **array, int begin, int end, unsigned int *randseed)
Definition: misc.c:10447
void SCIPswapReals(SCIP_Real *value1, SCIP_Real *value2)
Definition: misc.c:10384
void SCIPrandomPermuteArray(SCIP_RANDNUMGEN *randnumgen, void **array, int begin, int end)
Definition: misc.c:10180
void SCIPpermuteIntArray(int *array, int begin, int end, unsigned int *randseed)
Definition: misc.c:10413
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:10481
SCIP_Real SCIPrandomGetReal(SCIP_RANDNUMGEN *randnumgen, SCIP_Real minrandval, SCIP_Real maxrandval)
Definition: misc.c:10131
SCIP_RETCODE SCIPrandomGetSubset(SCIP_RANDNUMGEN *randnumgen, void **set, int nelems, void **subset, int nsubelems)
Definition: misc.c:10212
int SCIPgetRandomInt(int minrandval, int maxrandval, unsigned int *seedp)
Definition: misc.c:9992
SCIP_Real SCIPgetRandomReal(SCIP_Real minrandval, SCIP_Real maxrandval, unsigned int *seedp)
Definition: misc.c:10005
int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
Definition: misc.c:10109
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:6643
int SCIPactivityGetDuration(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6698
int SCIPactivityGetEnergy(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6718
SCIP_VAR * SCIPactivityGetVar(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6688
int SCIPactivityGetDemand(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6708
void SCIPactivityFree(SCIP_RESOURCEACTIVITY **activity)
Definition: misc.c:6662
SCIP_RETCODE SCIPprofileInsertCore(SCIP_PROFILE *profile, int left, int right, int demand, int *pos, SCIP_Bool *infeasible)
Definition: misc.c:7022
int * SCIPprofileGetTimepoints(SCIP_PROFILE *profile)
Definition: misc.c:6829
int SCIPprofileGetLatestFeasibleStart(SCIP_PROFILE *profile, int est, int lst, int duration, int demand, SCIP_Bool *infeasible)
Definition: misc.c:7291
SCIP_Bool SCIPprofileFindLeft(SCIP_PROFILE *profile, int timepoint, int *pos)
Definition: misc.c:6875
int SCIPprofileGetEarliestFeasibleStart(SCIP_PROFILE *profile, int est, int lst, int duration, int demand, SCIP_Bool *infeasible)
Definition: misc.c:7142
int SCIPprofileGetNTimepoints(SCIP_PROFILE *profile)
Definition: misc.c:6819
void SCIPprofileFree(SCIP_PROFILE **profile)
Definition: misc.c:6771
int SCIPprofileGetLoad(SCIP_PROFILE *profile, int pos)
Definition: misc.c:6861
int * SCIPprofileGetLoads(SCIP_PROFILE *profile)
Definition: misc.c:6839
SCIP_RETCODE SCIPprofileCreate(SCIP_PROFILE **profile, int capacity)
Definition: misc.c:6757
int SCIPprofileGetTime(SCIP_PROFILE *profile, int pos)
Definition: misc.c:6849
int SCIPprofileGetCapacity(SCIP_PROFILE *profile)
Definition: misc.c:6809
SCIP_RETCODE SCIPprofileDeleteCore(SCIP_PROFILE *profile, int left, int right, int demand)
Definition: misc.c:7052
void SCIPprofilePrint(SCIP_PROFILE *profile, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: misc.c:6787
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:6079
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:5540
SCIP_DECL_SORTPTRCOMP(SCIPsortCompInt)
Definition: misc.c:5482
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:5503
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:10975
int SCIPstrcasecmp(const char *s1, const char *s2)
Definition: misc.c:10914
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10878
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:11006
void SCIPescapeString(char *t, int bufsize, const char *s)
Definition: misc.c:10833
void SCIPstrCopySection(const char *str, char startchar, char endchar, char *token, int size, char **endptr)
Definition: misc.c:11036
void SCIPprintSysError(const char *message)
Definition: misc.c:10770
SCIP_Bool SCIPstrAtStart(const char *s, const char *t, size_t tlen)
Definition: misc.c:11415
SCIP_RETCODE SCIPskipSpace(char **s)
Definition: misc.c:10867
int SCIPstrncpy(char *t, const char *s, int size)
Definition: misc.c:10948
int SCIPstrncasecmp(const char *s1, const char *s2, int length)
Definition: misc.c:10927
char * SCIPstrtok(char *s, const char *delim, char **ptrptr)
Definition: misc.c:10819
int SCIPmemccpy(char *dest, const char *src, char stop, unsigned int cnt)
Definition: misc.c:10745
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:4090
#define GMLNODEHEIGTH
Definition: misc.c:491
#define ELEM_DISTANCE(pos)
Definition: misc.c:3656
SCIP_Bool SCIPboolarrayGetVal(SCIP_BOOLARRAY *boolarray, int idx)
Definition: misc.c:5015
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:6735
static int primetable[]
Definition: misc.c:1576
SCIP_RETCODE SCIPboolarrayFree(SCIP_BOOLARRAY **boolarray)
Definition: misc.c:4813
SCIP_RETCODE SCIPboolarrayCopy(SCIP_BOOLARRAY **boolarray, BMS_BLKMEM *blkmem, SCIP_BOOLARRAY *sourceboolarray)
Definition: misc.c:4789
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:9935
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:5467
#define DEFAULT_SEED
Definition: misc.c:10016
SCIP_RETCODE SCIPrealarraySetVal(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, SCIP_Real val)
Definition: misc.c:4297
SCIP_RETCODE SCIPintarraySetVal(SCIP_INTARRAY *intarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, int val)
Definition: misc.c:4668
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:4447
#define DEFAULT_MWC
Definition: misc.c:10018
#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:7084
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:8322
#define DEFAULT_XOR
Definition: misc.c:10017
void SCIPdisjointsetFree(SCIP_DISJOINTSET **djset, BMS_BLKMEM *blkmem)
Definition: misc.c:11376
static void btnodeFreeLeaf(SCIP_BT *tree, SCIP_BTNODE **node)
Definition: misc.c:8701
static void depthFirstSearch(SCIP_DIGRAPH *digraph, int startnode, SCIP_Bool *visited, int *dfsstack, int *stackadjvisited, int *dfsnodes, int *ndfsnodes)
Definition: misc.c:7856
int SCIPptrarrayGetMinIdx(SCIP_PTRARRAY *ptrarray)
Definition: misc.c:5457
static SCIP_RETCODE profileUpdate(SCIP_PROFILE *profile, int left, int right, int demand, int *pos, SCIP_Bool *infeasible)
Definition: misc.c:6962
static SCIP_RETCODE ensureSuccessorsSize(SCIP_DIGRAPH *digraph, int idx, int newsize)
Definition: misc.c:7617
static SCIP_RETCODE profileInsertTimepoint(SCIP_PROFILE *profile, int timepoint, int *pos)
Definition: misc.c:6921
SCIP_RETCODE SCIPptrarrayExtend(SCIP_PTRARRAY *ptrarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
Definition: misc.c:5182
SCIP_RETCODE SCIPboolarrayExtend(SCIP_BOOLARRAY *boolarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
Definition: misc.c:4827
SCIP_RETCODE SCIPptrarrayCopy(SCIP_PTRARRAY **ptrarray, BMS_BLKMEM *blkmem, SCIP_PTRARRAY *sourceptrarray)
Definition: misc.c:5145
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:8994
int SCIPboolarrayGetMaxIdx(SCIP_BOOLARRAY *boolarray)
Definition: misc.c:5114
static const SCIP_Real studentt_quartilesabove[]
Definition: misc.c:101
void SCIPrandomFree(SCIP_RANDNUMGEN **randnumgen, BMS_BLKMEM *blkmem)
Definition: misc.c:10093
static int getRand(unsigned int *seedp)
Definition: misc.c:9939
SCIP_RETCODE SCIPdisjointsetCreate(SCIP_DISJOINTSET **djset, BMS_BLKMEM *blkmem, int ncomponents)
Definition: misc.c:11258
SCIP_RETCODE SCIPrandomCreate(SCIP_RANDNUMGEN **randnumgen, BMS_BLKMEM *blkmem, unsigned int initialseed)
Definition: misc.c:10077
SCIP_RETCODE SCIPintarrayCopy(SCIP_INTARRAY **intarray, BMS_BLKMEM *blkmem, SCIP_INTARRAY *sourceintarray)
Definition: misc.c:4424
SCIP_RETCODE SCIPptrarrayClear(SCIP_PTRARRAY *ptrarray)
Definition: misc.c:5337
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:4394
SCIP_RETCODE SCIPdigraphCreate(SCIP_DIGRAPH **digraph, BMS_BLKMEM *blkmem, int nnodes)
Definition: misc.c:7379
static uint32_t hashSetDesiredPos(SCIP_HASHSET *hashset, void *element)
Definition: misc.c:3660
int SCIPintarrayGetMaxIdx(SCIP_INTARRAY *intarray)
Definition: misc.c:4758
SCIP_RETCODE SCIPintarrayCreate(SCIP_INTARRAY **intarray, BMS_BLKMEM *blkmem)
Definition: misc.c:4404
static SCIP_RETCODE hashsetCheckLoad(SCIP_HASHSET *hashset, BMS_BLKMEM *blkmem)
Definition: misc.c:3720
static void regressionRecompute(SCIP_REGRESSION *regression)
Definition: misc.c:288
#define STARTSUCCESSORSSIZE
Definition: misc.c:7613
SCIP_Real SCIPrealarrayGetVal(SCIP_REALARRAY *realarray, int idx)
Definition: misc.c:4276
SCIP_RETCODE SCIPptrarrayFree(SCIP_PTRARRAY **ptrarray)
Definition: misc.c:5168
SCIP_RETCODE SCIPintarrayClear(SCIP_INTARRAY *intarray)
Definition: misc.c:4616
#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:4366
int SCIPrealarrayGetMinIdx(SCIP_REALARRAY *realarray)
Definition: misc.c:4384
SCIP_RETCODE SCIPrealarrayCreate(SCIP_REALARRAY **realarray, BMS_BLKMEM *blkmem)
Definition: misc.c:4032
#define GMLFONTSIZE
Definition: misc.c:492
static const int nscalars
Definition: misc.c:9553
SCIP_RETCODE SCIPrealarrayClear(SCIP_REALARRAY *realarray)
Definition: misc.c:4245
int SCIPboolarrayGetMinIdx(SCIP_BOOLARRAY *boolarray)
Definition: misc.c:5104
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:10054
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:7935
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:7234
int SCIPintarrayGetMinIdx(SCIP_INTARRAY *intarray)
Definition: misc.c:4748
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:4052
static SCIP_RETCODE hashmapCheckLoad(SCIP_HASHMAP *hashmap)
Definition: misc.c:3025
void * SCIPptrarrayGetVal(SCIP_PTRARRAY *ptrarray, int idx)
Definition: misc.c:5368
void SCIPrandomSetSeed(SCIP_RANDNUMGEN *randnumgen, unsigned int initseed)
Definition: misc.c:10023
#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:4461
#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:4769
static SCIP_RETCODE ensureProfileSize(SCIP_PROFILE *profile, int neededsize)
Definition: misc.c:6898
static SCIP_Bool isIntegralScalar(SCIP_Real val, SCIP_Real scalar, SCIP_Real mindelta, SCIP_Real maxdelta)
Definition: misc.c:9530
#define GMLEDGECOLOR
Definition: misc.c:495
SCIP_Real SCIPnegateReal(SCIP_Real x)
Definition: misc.c:10359
static SCIP_RETCODE btnodeCreateEmpty(SCIP_BT *tree, SCIP_BTNODE **node)
Definition: misc.c:8662
#define DEFAULT_CST
Definition: misc.c:10019
SCIP_RETCODE SCIPboolarrayClear(SCIP_BOOLARRAY *boolarray)
Definition: misc.c:4984
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:4736
int SCIPintarrayGetVal(SCIP_INTARRAY *intarray, int idx)
Definition: misc.c:4647
static SCIP_Bool hashmapLookup(SCIP_HASHMAP *hashmap, void *origin, uint32_t *pos)
Definition: misc.c:2980
static const SCIP_Real scalars[]
Definition: misc.c:9552
SCIP_RETCODE SCIPdigraphCopy(SCIP_DIGRAPH **targetdigraph, SCIP_DIGRAPH *sourcedigraph, BMS_BLKMEM *targetblkmem)
Definition: misc.c:7456
#define GMLNODEFILLCOLOR
Definition: misc.c:494
SCIP_RETCODE SCIPptrarrayCreate(SCIP_PTRARRAY **ptrarray, BMS_BLKMEM *blkmem)
Definition: misc.c:5125
SCIP_RETCODE SCIPptrarraySetVal(SCIP_PTRARRAY *ptrarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, void *val)
Definition: misc.c:5389
static const SCIP_Real simplednoms[]
Definition: misc.c:9389
static SCIP_Real getRandomReal(SCIP_Real minrandval, SCIP_Real maxrandval, unsigned int *seedp)
Definition: misc.c:9970
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:4076
static void hashsetInsert(SCIP_HASHSET *hashset, void *element)
Definition: misc.c:3669
SCIP_RETCODE SCIPboolarraySetVal(SCIP_BOOLARRAY *boolarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, SCIP_Bool val)
Definition: misc.c:5036
static int getRandomInt(int minrandval, int maxrandval, unsigned int *seedp)
Definition: misc.c:9950
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