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