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