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