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 reader_sto.c 26 * @ingroup DEFPLUGINS_READER 27 * @brief STO file reader - the stochastic information of an instance in SMPS format 28 * @author Stephen J. Maher 29 */ 30 31 32 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/ 33 34 #include "blockmemshell/memory.h" 35 #include "scip/benders_default.h" 36 #include "scip/cons_linear.h" 37 #include "scip/pub_cons.h" 38 #include "scip/pub_fileio.h" 39 #include "scip/pub_message.h" 40 #include "scip/pub_misc.h" 41 #include "scip/pub_reader.h" 42 #include "scip/pub_var.h" 43 #include "scip/reader_cor.h" 44 #include "scip/reader_sto.h" 45 #include "scip/reader_tim.h" 46 #include "scip/scip_cons.h" 47 #include "scip/scip_debug.h" 48 #include "scip/scipdefplugins.h" 49 #include "scip/scip_general.h" 50 #include "scip/scip_mem.h" 51 #include "scip/scip_message.h" 52 #include "scip/scip_numerics.h" 53 #include "scip/scip_param.h" 54 #include "scip/scip_prob.h" 55 #include "scip/scip_reader.h" 56 #include "scip/scip_var.h" 57 #include <stdlib.h> 58 #include <string.h> 59 60 #define READER_NAME "storeader" 61 #define READER_DESC "file reader for stochastic information of stochastic programs in the SMPS file format" 62 #define READER_EXTENSION "sto" 63 64 #define DEFAULT_USEBENDERS FALSE /**< should Benders' decomposition be used for the stochastic program? */ 65 66 /* 67 * sto reader internal methods 68 */ 69 70 #define STO_MAX_LINELEN 1024 71 #define STO_MAX_NAMELEN 256 72 73 #define STO_DEFAULT_ARRAYSIZE 100 74 #define STO_DEFAULT_ENTRIESSIZE 20 75 #define STO_DEFAULT_BLOCKARRAYSIZE 5 76 #define STO_DEFAULT_CHILDRENSIZE 5 77 78 #define BLANK ' ' 79 80 typedef struct StoScenario STOSCENARIO; 81 82 /** STO reading data */ 83 struct SCIP_ReaderData 84 { 85 SCIP_Bool usebenders; 86 STOSCENARIO* scenariotree; /**< the multi stage scenario tree */ 87 int numscenarios; /**< the total number of scenarios in the scenario tree */ 88 }; 89 90 91 struct StoScenario 92 { 93 SCIP* scip; /**< the SCIP instance for the scenario. Used for benders. */ 94 SCIP** subproblems; /**< the SCIP instances for the subproblems */ 95 STOSCENARIO* parent; /**< parent scenario. */ 96 STOSCENARIO** children; /**< children scenarios. */ 97 int nchildren; /**< the number of children scenarios. */ 98 int childrensize; /**< the size of the children array. */ 99 int nsubproblems; /**< the number of subproblems */ 100 int stagenum; /**< the number of the stage */ 101 int scenarionum; /**< the scenario number of this stage */ 102 const char* stagename; /**< the stage name */ 103 const char* name; /**< the scenario name. */ 104 SCIP_Real probability; /**< the probability for this scenario. */ 105 SCIP_Real lowerbound; /**< the lower bound for this scenario */ 106 /* the following describes the modifications to the constraint matrix and rhs for each scenario. */ 107 const char** rownames; /**< the names of the rows with a changed value. */ 108 const char** colnames; /**< the names of the columns with a changed value. */ 109 SCIP_Real* values; /**< the values for the given row/column pair. */ 110 int nentries; /**< the number of row/column pairs */ 111 int entriessize; /**< the size of the row/colum arrays */ 112 }; 113 114 115 116 /** enum containing all sto sections */ 117 enum StoSection 118 { 119 STO_STOCH, 120 STO_SCENARIOS, 121 STO_BLOCKS, 122 STO_INDEP, 123 STO_ENDATA 124 }; 125 typedef enum StoSection STOSECTION; 126 127 /** enum containing the types of stochastic information */ 128 enum StoStochInfo 129 { 130 STO_STOCHINFO_NONE = -1, 131 STO_STOCHINFO_DISCRETE = 0, 132 STO_STOCHINFO_UNIFORM = 1, 133 STO_STOCHINFO_NORMAL = 2, 134 STO_STOCHINFO_SUB = 3, 135 STO_STOCHINFO_LINTR = 4 136 }; 137 typedef enum StoStochInfo STOSTOCHINFO; 138 139 /** sto input structure */ 140 struct StoInput 141 { 142 STOSECTION section; 143 STOSTOCHINFO stochinfotype; 144 SCIP_FILE* fp; 145 int lineno; 146 SCIP_Bool haserror; 147 char buf[STO_MAX_LINELEN]; 148 const char* f0; 149 const char* f1; 150 const char* f2; 151 const char* f3; 152 const char* f4; 153 const char* f5; 154 const char* f6; 155 char probname[STO_MAX_NAMELEN]; 156 char stochtype[STO_MAX_NAMELEN]; 157 }; 158 typedef struct StoInput STOINPUT; 159 160 /** creates a scenario structure */ 161 static 162 SCIP_RETCODE createScenarioData( 163 SCIP* scip, /**< SCIP data structure */ 164 STOSCENARIO** scenariodata /**< the scenario to be created */ 165 ) 166 { 167 assert(scip != NULL); 168 169 SCIPdebugMessage("Creating scenario data.\n"); 170 171 SCIP_CALL( SCIPallocBlockMemory(scip, scenariodata) ); 172 173 (*scenariodata)->scip = NULL; 174 (*scenariodata)->subproblems = NULL; 175 (*scenariodata)->parent = NULL; 176 (*scenariodata)->nchildren = 0; 177 (*scenariodata)->childrensize = STO_DEFAULT_CHILDRENSIZE; 178 (*scenariodata)->nsubproblems = 0; 179 (*scenariodata)->stagenum = -1; 180 (*scenariodata)->scenarionum = -1; 181 (*scenariodata)->stagename = NULL; 182 (*scenariodata)->name = NULL; 183 (*scenariodata)->probability = 1.0; 184 (*scenariodata)->lowerbound = -SCIPinfinity(scip); 185 (*scenariodata)->nentries = 0; 186 (*scenariodata)->entriessize = STO_DEFAULT_ENTRIESSIZE; 187 188 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*scenariodata)->children, (*scenariodata)->childrensize) ); 189 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*scenariodata)->rownames, (*scenariodata)->entriessize) ); 190 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*scenariodata)->colnames, (*scenariodata)->entriessize) ); 191 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*scenariodata)->values, (*scenariodata)->entriessize) ); 192 193 return SCIP_OKAY; 194 } 195 196 /** frees the memory used for the scenario tree */ 197 static 198 SCIP_RETCODE freeScenarioTree( 199 SCIP* scip, /**< the SCIP data structure */ 200 STOSCENARIO** scenariotree /**< the scenario tree */ 201 ) 202 { 203 int nchildren; 204 int i; 205 206 assert(scip != NULL); 207 assert(scenariotree != NULL); 208 assert(*scenariotree != NULL); 209 210 SCIPdebugMessage("Freeing scenario <%s> in stage <%s>\n", (*scenariotree)->name, 211 (*scenariotree)->stagename); 212 213 /* storing the number of children before starting the recursive freeing */ 214 nchildren = (*scenariotree)->nchildren; 215 216 while( (*scenariotree)->nchildren > 0 ) 217 { 218 SCIP_CALL( freeScenarioTree(scip, &(*scenariotree)->children[(*scenariotree)->nchildren - 1]) ); 219 (*scenariotree)->nchildren--; 220 } 221 222 for( i = (*scenariotree)->nentries - 1; i >= 0; i-- ) 223 { 224 SCIPfreeBlockMemoryArray(scip, &(*scenariotree)->colnames[i], strlen((*scenariotree)->colnames[i]) + 1); 225 SCIPfreeBlockMemoryArray(scip, &(*scenariotree)->rownames[i], strlen((*scenariotree)->rownames[i]) + 1); 226 } 227 228 SCIPfreeBlockMemoryArray(scip, &(*scenariotree)->values, (*scenariotree)->entriessize); 229 SCIPfreeBlockMemoryArray(scip, &(*scenariotree)->colnames, (*scenariotree)->entriessize); 230 SCIPfreeBlockMemoryArray(scip, &(*scenariotree)->rownames, (*scenariotree)->entriessize); 231 SCIPfreeBlockMemoryArray(scip, &(*scenariotree)->children, (*scenariotree)->childrensize); 232 233 SCIPfreeBlockMemoryArray(scip, &(*scenariotree)->name, strlen((*scenariotree)->name) + 1); 234 SCIPfreeBlockMemoryArray(scip, &(*scenariotree)->stagename, strlen((*scenariotree)->stagename) + 1); 235 236 /* freeing the subproblem SCIP instances */ 237 for( i = (*scenariotree)->nsubproblems - 1; i >= 0; i-- ) 238 SCIP_CALL( SCIPfree(&(*scenariotree)->subproblems[i]) ); 239 240 /* freeing the array that stores the subproblems */ 241 if( nchildren > 0 && (*scenariotree)->subproblems != NULL ) 242 SCIPfreeBlockMemoryArray(scip, &(*scenariotree)->subproblems, nchildren); 243 244 SCIPfreeBlockMemory(scip, scenariotree); 245 246 return SCIP_OKAY; 247 } 248 249 /** sets the SCIP pointer to the scenario */ 250 static 251 void setScenarioScip( 252 STOSCENARIO* scenario, /**< the scenario */ 253 SCIP* scip /**< the SCIP data structure */ 254 ) 255 { 256 assert(scenario != NULL); 257 assert(scip != NULL); 258 259 scenario->scip = scip; 260 } 261 262 /** returns the SCIP pointer to the scenario */ 263 static 264 SCIP* getScenarioScip( 265 STOSCENARIO* scenario /**< the scenario */ 266 ) 267 { 268 assert(scenario != NULL); 269 270 return scenario->scip; 271 } 272 273 /** creates the subproblem array. This array will be the same size as the number of children */ 274 static 275 SCIP_RETCODE createScenarioSubproblemArray( 276 SCIP* scip, /**< the SCIP data structure */ 277 STOSCENARIO* scenario /**< the scenario */ 278 ) 279 { 280 assert(scip != NULL); 281 assert(scenario != NULL); 282 283 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &scenario->subproblems, scenario->nchildren) ); 284 285 return SCIP_OKAY; 286 } 287 288 /** adds a scenario to the subproblem array */ 289 static 290 void addScenarioSubproblem( 291 STOSCENARIO* scenario, /**< the scenario */ 292 SCIP* subproblem /**< the subproblems data structure */ 293 ) 294 { 295 assert(scenario != NULL); 296 assert(subproblem != NULL); 297 298 assert(scenario->nsubproblems + 1 <= scenario->nchildren); 299 300 scenario->subproblems[scenario->nsubproblems] = subproblem; 301 scenario->nsubproblems++; 302 } 303 304 /** returns the subproblem array for the scenario */ 305 static 306 SCIP** getScenarioSubproblemArray( 307 STOSCENARIO* scenario /**< the scenario */ 308 ) 309 { 310 assert(scenario != NULL); 311 312 return scenario->subproblems; 313 } 314 315 /** returns the number of children for a given scenario */ 316 static 317 int getScenarioNChildren( 318 STOSCENARIO* scenario /**< the scenario */ 319 ) 320 { 321 assert(scenario != NULL); 322 323 return scenario->nchildren; 324 } 325 326 /** returns a given child for a given scenario */ 327 static 328 STOSCENARIO* getScenarioChild( 329 STOSCENARIO* scenario, /**< the scenario */ 330 int childnum /**< the number of the desired child */ 331 ) 332 { 333 assert(scenario != NULL); 334 assert(childnum >= 0 && childnum < scenario->nchildren); 335 336 return scenario->children[childnum]; 337 } 338 339 /** returns the parent of a scenario */ 340 static 341 STOSCENARIO* getScenarioParent( 342 STOSCENARIO* scenario /**< the scenario */ 343 ) 344 { 345 assert(scenario != NULL); 346 347 return scenario->parent; 348 } 349 350 /** sets the stage name */ 351 static 352 SCIP_RETCODE setScenarioStageName( 353 SCIP* scip, /**< the SCIP data structure */ 354 STOSCENARIO* scenario, /**< the scenario */ 355 const char* stagename /**< the stage name */ 356 ) 357 { 358 assert(scip != NULL); 359 assert(scenario != NULL); 360 361 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &scenario->stagename, stagename, strlen(stagename) + 1) ); 362 363 return SCIP_OKAY; 364 } 365 366 /** returns the stage name */ 367 static 368 const char* getScenarioStageName( 369 SCIP* scip, /**< the SCIP data structure */ 370 STOSCENARIO* scenario /**< the scenario */ 371 ) 372 { 373 assert(scip != NULL); 374 assert(scenario != NULL); 375 376 return scenario->stagename; 377 } 378 379 /** sets the stage num */ 380 static 381 SCIP_RETCODE setScenarioStageNum( 382 SCIP* scip, /**< the SCIP data structure */ 383 STOSCENARIO* scenario, /**< the scenario */ 384 int stagenum /**< the stage num */ 385 ) 386 { 387 assert(scip != NULL); 388 assert(scenario != NULL); 389 390 scenario->stagenum = stagenum; 391 392 return SCIP_OKAY; 393 } 394 395 /** returns the stage num */ 396 static 397 int getScenarioStageNum( 398 SCIP* scip, /**< the SCIP data structure */ 399 STOSCENARIO* scenario /**< the scenario */ 400 ) 401 { 402 assert(scip != NULL); 403 assert(scenario != NULL); 404 405 return scenario->stagenum; 406 } 407 408 /** sets the scenario name */ 409 static 410 SCIP_RETCODE setScenarioName( 411 SCIP* scip, /**< the SCIP data structure */ 412 STOSCENARIO* scenario, /**< the scenario */ 413 const char* name /**< the scenario name */ 414 ) 415 { 416 assert(scip != NULL); 417 assert(scenario != NULL); 418 419 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &scenario->name, name, strlen(name) + 1) ); 420 421 return SCIP_OKAY; 422 } 423 424 /** returns the scenario name */ 425 static 426 const char* getScenarioName( 427 STOSCENARIO* scenario /**< the scenario */ 428 ) 429 { 430 assert(scenario != NULL); 431 432 return scenario->name; 433 } 434 435 /** sets the scenario num */ 436 static 437 SCIP_RETCODE setScenarioNum( 438 SCIP* scip, /**< the SCIP data structure */ 439 STOSCENARIO* scenario, /**< the scenario */ 440 int scenarionum /**< the scenario num */ 441 ) 442 { 443 assert(scip != NULL); 444 assert(scenario != NULL); 445 446 scenario->scenarionum = scenarionum; 447 448 return SCIP_OKAY; 449 } 450 451 /** returns the scenario num */ 452 static 453 int getScenarioNum( 454 SCIP* scip, /**< the SCIP data structure */ 455 STOSCENARIO* scenario /**< the scenario */ 456 ) 457 { 458 assert(scip != NULL); 459 assert(scenario != NULL); 460 461 return scenario->scenarionum; 462 } 463 464 /** sets the scenario probability */ 465 static 466 SCIP_RETCODE setScenarioProbability( 467 SCIP* scip, /**< the SCIP data structure */ 468 STOSCENARIO* scenario, /**< the scenario */ 469 SCIP_Real probability /**< the scenario probability */ 470 ) 471 { 472 assert(scip != NULL); 473 assert(scenario != NULL); 474 475 scenario->probability = probability; 476 477 return SCIP_OKAY; 478 } 479 480 /** returns the scenario probability */ 481 static 482 SCIP_Real getScenarioProbability( 483 SCIP* scip, /**< the SCIP data structure */ 484 STOSCENARIO* scenario /**< the scenario */ 485 ) 486 { 487 assert(scip != NULL); 488 assert(scenario != NULL); 489 490 return scenario->probability; 491 } 492 493 /** sets the scenario lowerbound */ 494 static 495 SCIP_RETCODE setScenarioLowerbound( 496 SCIP* scip, /**< the SCIP data structure */ 497 STOSCENARIO* scenario, /**< the scenario */ 498 SCIP_Real lowerbound /**< the scenario lowerbound */ 499 ) 500 { 501 assert(scip != NULL); 502 assert(scenario != NULL); 503 504 scenario->lowerbound = lowerbound; 505 506 return SCIP_OKAY; 507 } 508 509 /** returns the scenario lowerbound */ 510 static 511 SCIP_Real getScenarioLowerbound( 512 SCIP* scip, /**< the SCIP data structure */ 513 STOSCENARIO* scenario /**< the scenario */ 514 ) 515 { 516 assert(scip != NULL); 517 assert(scenario != NULL); 518 519 return scenario->lowerbound; 520 } 521 522 /** add scenario entry */ 523 static 524 SCIP_RETCODE addScenarioEntry( 525 SCIP* scip, /**< the SCIP data structure */ 526 STOSCENARIO* scenario, /**< the scenario */ 527 const char* rowname, /**< the row name for the entry */ 528 const char* colname, /**< the col name for the entry */ 529 SCIP_Real value /**< the value for the entry */ 530 ) 531 { 532 assert(scip != NULL); 533 assert(scenario != NULL); 534 535 if( scenario->nentries + 1 > scenario->entriessize ) 536 { 537 int newsize; 538 newsize = SCIPcalcMemGrowSize(scip, scenario->nentries + 1); 539 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &scenario->rownames, scenario->entriessize, newsize) ); 540 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &scenario->colnames, scenario->entriessize, newsize) ); 541 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &scenario->values, scenario->entriessize, newsize) ); 542 scenario->entriessize = newsize; 543 } 544 545 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &scenario->rownames[scenario->nentries], rowname, strlen(rowname) + 1) ); /*lint !e866*/ 546 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &scenario->colnames[scenario->nentries], colname, strlen(colname) + 1) ); /*lint !e866*/ 547 548 scenario->values[scenario->nentries] = value; 549 scenario->nentries++; 550 551 return SCIP_OKAY; 552 } 553 554 /** returns the number of entries for a scenario */ 555 static 556 int getScenarioNEntries( 557 STOSCENARIO* scenario /**< the scenario */ 558 ) 559 { 560 assert(scenario != NULL); 561 562 return scenario->nentries; 563 } 564 565 /** returns an entry row for a scenario */ 566 static 567 const char* getScenarioEntryRow( 568 STOSCENARIO* scenario, /**< the scenario */ 569 int entry /**< the entry number */ 570 ) 571 { 572 assert(scenario != NULL); 573 assert(entry >= 0 && entry < scenario->nentries); 574 575 return scenario->rownames[entry]; 576 } 577 578 /** returns an entry column for a scenario */ 579 static 580 const char* getScenarioEntryCol( 581 STOSCENARIO* scenario, /**< the scenario */ 582 int entry /**< the entry number */ 583 ) 584 { 585 assert(scenario != NULL); 586 assert(entry >= 0 && entry < scenario->nentries); 587 588 return scenario->colnames[entry]; 589 } 590 591 /** returns an entry value for a scenario */ 592 static 593 SCIP_Real getScenarioEntryValue( 594 STOSCENARIO* scenario, /**< the scenario */ 595 int entry /**< the entry number */ 596 ) 597 { 598 assert(scenario != NULL); 599 assert(entry >= 0 && entry < scenario->nentries); 600 601 return scenario->values[entry]; 602 } 603 604 /** copies a scenario. 605 * In the case of blocks, the scenarios must be combined 606 */ 607 static 608 SCIP_RETCODE copyScenario( 609 SCIP* scip, /**< the SCIP data structure */ 610 STOSCENARIO* sourcescenario, /**< the source scenario */ 611 STOSCENARIO** targetscenario, /**< the target scenario */ 612 SCIP_Bool copyname /**< should the name be copied? */ 613 ) 614 { 615 SCIP_Real probability; 616 SCIP_Real lowerbound; 617 int i; 618 619 assert(scip != NULL); 620 assert(sourcescenario != NULL); 621 assert(targetscenario != NULL); 622 623 /* setting the stage name */ 624 if( copyname ) 625 { 626 SCIP_CALL( setScenarioName(scip, (*targetscenario), sourcescenario->name) ); 627 SCIP_CALL( setScenarioStageName(scip, (*targetscenario), sourcescenario->stagename) ); 628 SCIP_CALL( setScenarioNum(scip, (*targetscenario), sourcescenario->scenarionum) ); 629 SCIP_CALL( setScenarioStageNum(scip, (*targetscenario), sourcescenario->stagenum) ); 630 } 631 632 /* adding the entries from scenario 1 and 2 to the merged scenario */ 633 for( i = 0; i < sourcescenario->nentries; i++ ) 634 SCIP_CALL( addScenarioEntry(scip, (*targetscenario), sourcescenario->rownames[i], sourcescenario->colnames[i], 635 sourcescenario->values[i]) ); 636 637 /* setting the scenario probability */ 638 probability = getScenarioProbability(scip, sourcescenario); 639 SCIP_CALL( setScenarioProbability(scip, (*targetscenario), probability) ); 640 641 lowerbound = getScenarioLowerbound(scip, sourcescenario); 642 SCIP_CALL( setScenarioLowerbound(scip, (*targetscenario), lowerbound) ); 643 644 return SCIP_OKAY; 645 } 646 647 /** merge scenarios. 648 * In the case of blocks, the scenarios must be combined 649 */ 650 static 651 SCIP_RETCODE mergeScenarios( 652 SCIP* scip, /**< the SCIP data structure */ 653 STOSCENARIO* scenario1, /**< the first scenario */ 654 STOSCENARIO** mergedscenario /**< the merged scenario */ 655 ) 656 { 657 SCIP_Real probability; 658 int i; 659 660 assert(scip != NULL); 661 assert(scenario1 != NULL); 662 assert(mergedscenario != NULL); 663 664 /* adding the entries from scenario 1 and 2 to the merged scenario */ 665 for( i = 0; i < scenario1->nentries; i++ ) 666 SCIP_CALL( addScenarioEntry(scip, (*mergedscenario), scenario1->rownames[i], scenario1->colnames[i], 667 scenario1->values[i]) ); 668 669 /* setting the scenario probability */ 670 probability = getScenarioProbability(scip, scenario1)*getScenarioProbability(scip, (*mergedscenario)); 671 SCIP_CALL( setScenarioProbability(scip, (*mergedscenario), probability) ); 672 673 return SCIP_OKAY; 674 } 675 676 /** adds a child to a given scenario */ 677 static 678 SCIP_RETCODE scenarioAddChild( 679 SCIP* scip, /**< the SCIP data structure */ 680 STOSCENARIO** parent, /**< the parent scenario */ 681 STOSCENARIO* child /**< the child scenario */ 682 ) 683 { 684 STOSCENARIO* scenario; 685 686 assert(parent != NULL); 687 assert((*parent) != NULL); 688 assert(child != NULL); 689 690 if( (*parent)->nchildren + 1 > (*parent)->childrensize ) 691 SCIP_CALL( SCIPensureBlockMemoryArray(scip, &(*parent)->children, &(*parent)->childrensize, 692 (*parent)->nchildren + 1) ); 693 694 SCIP_CALL( createScenarioData(scip, &scenario) ); 695 SCIP_CALL( copyScenario(scip, child, &scenario, TRUE) ); 696 scenario->parent = (*parent); 697 698 (*parent)->children[(*parent)->nchildren] = scenario; 699 (*parent)->nchildren++; 700 701 return SCIP_OKAY; 702 } 703 704 /** recursively adds the scenarios to the reader data */ 705 static 706 SCIP_RETCODE buildScenarioTree( 707 SCIP* scip, /**< the SCIP data structure */ 708 STOSCENARIO** scenariotree, /**< the scenario tree */ 709 STOSCENARIO*** scenarios, /**< the array of scenarios */ 710 int* numscenarios, /**< the number of scenarios per stage */ 711 int numstages, /**< the number of stages */ 712 int stage /**< the number of the stage. Also the depth of the tree */ 713 ) 714 { 715 int stageindex; 716 int i; 717 718 assert(scip != NULL); 719 assert(scenariotree != NULL); 720 assert(stage >= 0 && stage < numstages); 721 722 /* finding the scenarios for this stage */ 723 for( i = 0; i < numstages; i++ ) 724 { 725 if( strcmp(getScenarioStageName(scip, scenarios[i][0]), SCIPtimGetStageName(scip, stage + 1)) == 0 ) 726 break; 727 } 728 assert(i < numstages); 729 730 stageindex = i; 731 732 /* adds each scenario to the scenario tree */ 733 for( i = 0; i < numscenarios[stageindex]; i++ ) 734 { 735 /* adding child to the scenario tree */ 736 SCIP_CALL( scenarioAddChild(scip, scenariotree, scenarios[stageindex][i]) ); 737 738 /* building the tree below the recently added child */ 739 if( stage < numstages - 1 ) 740 { 741 STOSCENARIO* child = getScenarioChild((*scenariotree), getScenarioNChildren((*scenariotree)) - 1); 742 SCIP_CALL( buildScenarioTree(scip, &child, scenarios, numscenarios, numstages, stage + 1) ); 743 } 744 } 745 746 return SCIP_OKAY; 747 } 748 749 750 /* adds the scenarios to the reader data */ 751 static 752 SCIP_RETCODE addScenariosToReaderdata( 753 SCIP* scip, /**< the SCIP data structure */ 754 SCIP_READERDATA* readerdata, /**< the reader data */ 755 STOSCENARIO*** scenarios, /**< the array of scenarios */ 756 int* numscenarios, /**< the number of scenarios per stage */ 757 int numscenariostages /**< the number of stages for which scenarios were collected */ 758 ) 759 { 760 int i; 761 762 assert(scip != NULL); 763 assert(readerdata != NULL); 764 assert(scenarios != NULL); 765 assert(numscenariostages == SCIPtimGetNStages(scip) - 1); 766 767 SCIP_CALL( buildScenarioTree(scip, &readerdata->scenariotree, scenarios, numscenarios, numscenariostages, 0) ); 768 769 /* setting the number of scenarios per stage in the TIME reader data */ 770 for( i = 0; i < numscenariostages; i++ ) 771 readerdata->numscenarios += numscenarios[i]; 772 773 return SCIP_OKAY; 774 } 775 776 777 /** finds a scenario with a given name */ 778 static 779 STOSCENARIO* findScenarioInTree( 780 STOSCENARIO* scenariotree, /**< the scenario tree to search */ 781 const char* scenname /**< the name of the scenario to search */ 782 ) 783 { 784 STOSCENARIO* retscen; 785 int i; 786 787 if( strcmp(getScenarioName(scenariotree), scenname) == 0 ) 788 return scenariotree; 789 else 790 { 791 retscen = NULL; 792 for( i = 0; i < getScenarioNChildren(scenariotree); i++ ) 793 { 794 retscen = findScenarioInTree(scenariotree->children[i], scenname); 795 if( retscen != NULL ) 796 return retscen; 797 } 798 } 799 800 return NULL; 801 } 802 803 804 /** inserts a scenario into the reader data scenario tree */ 805 static 806 SCIP_RETCODE insertScenarioInReaderdata( 807 SCIP* scip, /**< the SCIP data structure */ 808 SCIP_READERDATA* readerdata, /**< the reader data */ 809 STOSCENARIO* scenario, /**< the scenario to insert in the scenario tree */ 810 char* parentname /**< the parent scenario for the inserting scenario */ 811 ) 812 { 813 STOSCENARIO* parentscen; 814 815 assert(scip != NULL); 816 assert(readerdata != NULL); 817 assert(scenario != NULL); 818 819 /* searching for the parent scenario in the tree */ 820 parentscen = findScenarioInTree(readerdata->scenariotree, parentname); 821 822 /* adding the scenario as a child of the parent scenario */ 823 SCIP_CALL( scenarioAddChild(scip, &parentscen, scenario) ); 824 825 readerdata->numscenarios++; 826 827 return SCIP_OKAY; 828 } 829 830 831 /* builds the scenarios from the blocks for a given stage */ 832 static 833 SCIP_RETCODE buildScenariosFromBlocks( 834 SCIP* scip, /**< the SCIP data structure */ 835 STOSCENARIO*** blocks, /**< the block that form the scenarios */ 836 STOSCENARIO*** scenarios, /**< the array to store the scenarios */ 837 STOSCENARIO*** blocksforscen, /**< the blocks that will form the scenario */ 838 int* numblocksforscen, /**< the number of blocks that form the scenario */ 839 int numblocks, /**< the number of blocks */ 840 int* numblocksperblock, /**< the number of blocks for a given block */ 841 int* numscenarios, /**< the number of scenarios */ 842 int* scenariossize, /**< the size of scenarios array */ 843 const char* stage, /**< the stage for this scenario */ 844 int stagenum, /**< the number of the stage */ 845 int blocknum /**< the block number */ 846 ) 847 { 848 SCIP_Bool processed; 849 int i; 850 int j; 851 852 assert(scip != NULL); 853 assert(blocks != NULL); 854 assert(scenarios != NULL); 855 assert(blocksforscen != NULL); 856 857 processed = FALSE; 858 i = blocknum + 1; 859 while( !processed && i < numblocks ) 860 { 861 /* it is only necessary to process the next block in the list the belongs to the given stage. */ 862 if( strcmp(getScenarioStageName(scip, blocks[i][0]), stage) == 0 ) 863 { 864 processed = TRUE; 865 866 for( j = 0; j < numblocksperblock[i]; j++ ) 867 { 868 /* adding the blocks that will build the scenario */ 869 (*blocksforscen)[(*numblocksforscen)] = blocks[i][j]; 870 (*numblocksforscen)++; 871 SCIP_CALL( buildScenariosFromBlocks(scip, blocks, scenarios, blocksforscen, numblocksforscen, numblocks, 872 numblocksperblock, numscenarios, scenariossize, stage, stagenum + 1, i) ); 873 874 /* the last block needs to be removed so that a new block can be used in its place */ 875 (*numblocksforscen)--; 876 } 877 } 878 else 879 { 880 /* the index is only incremented if no block is processed. This is necessary because the value of i is used in 881 * the next if statement for identifying whether all blocks have been processed. 882 */ 883 i++; 884 } 885 } 886 887 /* when all blocks have been inspected, then it is possible to build the scenario */ 888 if( i == numblocks ) 889 { 890 char scenarioname[SCIP_MAXSTRLEN]; 891 892 /* ensuring the correct amount of memory is available */ 893 if( (*numscenarios) + 1 > (*scenariossize) ) 894 { 895 int newsize; 896 newsize = SCIPcalcMemGrowSize(scip, (*numscenarios) + 1); 897 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, scenarios, (*scenariossize), newsize) ); 898 (*scenariossize) = newsize; 899 } 900 901 SCIP_CALL( createScenarioData(scip, &(*scenarios)[(*numscenarios)]) ); 902 903 /* setting the scenario name */ 904 (void) SCIPsnprintf(scenarioname, SCIP_MAXSTRLEN, "Scenario_%s_%d", stage, (*numscenarios)); 905 SCIP_CALL( setScenarioName(scip, (*scenarios)[(*numscenarios)], scenarioname) ); 906 SCIP_CALL( setScenarioStageName(scip, (*scenarios)[(*numscenarios)], stage) ); 907 SCIP_CALL( setScenarioNum(scip, (*scenarios)[(*numscenarios)], (*numscenarios)) ); 908 SCIP_CALL( setScenarioStageNum(scip, (*scenarios)[(*numscenarios)], stagenum) ); 909 910 /* if there is only a single block for the scenario, then we simply copy the block. 911 * Otherwise, the blocks are merged into a single scenario */ 912 if( (*numblocksforscen) == 1 ) 913 SCIP_CALL( copyScenario(scip, (*blocksforscen)[0], &(*scenarios)[(*numscenarios)], FALSE) ); 914 else 915 { 916 SCIP_CALL( copyScenario(scip, (*blocksforscen)[0], &(*scenarios)[(*numscenarios)], FALSE) ); 917 for( i = 1; i < (*numblocksforscen); i++ ) 918 SCIP_CALL( mergeScenarios(scip, (*blocksforscen)[i], &(*scenarios)[(*numscenarios)]) ); 919 } 920 921 (*numscenarios)++; 922 } 923 924 return SCIP_OKAY; 925 } 926 927 928 /* creates the scenarios from the blocks */ 929 static 930 SCIP_RETCODE createScenariosFromBlocks( 931 SCIP* scip, /**< the SCIP data structure */ 932 SCIP_READERDATA* readerdata, /**< the reader data */ 933 STOSCENARIO*** blocks, /**< the block that form the scenarios */ 934 int numblocks, /**< the number of blocks */ 935 int* numblocksperblock, /**< the number of blocks for each block type */ 936 int numstages /**< the number of stages */ 937 ) 938 { 939 STOSCENARIO*** scenarios; 940 STOSCENARIO** blocksforscen; 941 int* numscenarios; 942 int* scenariossize; 943 int numblocksforscen; 944 int stagenum; 945 char periods[SCIP_MAXSTRLEN]; 946 int i; 947 int j; 948 949 assert(scip != NULL); 950 assert(blocks != NULL); 951 952 /* allocating the memory for the scenarios array */ 953 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &scenarios, numstages) ); 954 SCIP_CALL( SCIPallocBufferArray(scip, &numscenarios, numstages) ); 955 SCIP_CALL( SCIPallocBufferArray(scip, &scenariossize, numstages) ); 956 for( i = 0; i < numstages; i++ ) 957 { 958 scenariossize[i] = STO_DEFAULT_BLOCKARRAYSIZE; 959 numscenarios[i] = 0; 960 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &scenarios[i], scenariossize[i]) ); 961 } 962 963 /* allocating the memory for the block for scenario array */ 964 SCIP_CALL( SCIPallocBufferArray(scip, &blocksforscen, numblocks) ); 965 966 (void) SCIPsnprintf(periods, SCIP_MAXSTRLEN, ""); 967 968 stagenum = 0; 969 for( i = 0; i < numblocks; i++ ) 970 { 971 numblocksforscen = 0; 972 if( strstr(periods, getScenarioStageName(scip, blocks[i][0])) == NULL ) 973 { 974 /* recording the stage name as processed */ 975 (void) SCIPsnprintf(periods, SCIP_MAXSTRLEN, "%s_%s", periods, getScenarioStageName(scip, blocks[i][0])); 976 977 SCIP_CALL( buildScenariosFromBlocks(scip, blocks, &scenarios[stagenum], &blocksforscen, &numblocksforscen, 978 numblocks, numblocksperblock, &numscenarios[stagenum], &scenariossize[stagenum], 979 getScenarioStageName(scip, blocks[i][0]), stagenum, i - 1) ); 980 981 stagenum++; 982 } 983 } 984 985 /* adding the scenarios to the reader data */ 986 SCIP_CALL( setScenarioNum(scip, readerdata->scenariotree, 0) ); 987 SCIP_CALL( setScenarioStageNum(scip, readerdata->scenariotree, 0) ); 988 SCIP_CALL( addScenariosToReaderdata(scip, readerdata, scenarios, numscenarios, numstages) ); 989 990 SCIPfreeBufferArray(scip, &blocksforscen); 991 for( i = numstages - 1; i >= 0; i-- ) 992 { 993 for( j = numscenarios[i] - 1; j >= 0; j-- ) 994 SCIP_CALL( freeScenarioTree(scip, &scenarios[i][j]) ); 995 SCIPfreeBlockMemoryArray(scip, &scenarios[i], scenariossize[i]); 996 } 997 SCIPfreeBufferArray(scip, &scenariossize); 998 SCIPfreeBufferArray(scip, &numscenarios); 999 SCIPfreeBlockMemoryArray(scip, &scenarios, numstages); 1000 1001 return SCIP_OKAY; 1002 } 1003 1004 /** creates the reader data */ 1005 static 1006 SCIP_RETCODE createReaderdata( 1007 SCIP* scip, /**< SCIP data structure */ 1008 SCIP_READERDATA* readerdata /**< the reader data */ 1009 ) 1010 { 1011 assert(scip != NULL); 1012 assert(readerdata != NULL); 1013 1014 /* creating the initial scenario */ 1015 SCIP_CALL( createScenarioData(scip, &readerdata->scenariotree) ); 1016 1017 /* setting the scenario name and stage name */ 1018 SCIP_CALL( setScenarioName(scip, readerdata->scenariotree, "ROOT") ); 1019 SCIP_CALL( setScenarioStageName(scip, readerdata->scenariotree, SCIPtimGetStageName(scip, 0)) ); 1020 1021 return SCIP_OKAY; 1022 } 1023 1024 /** frees the reader data */ 1025 static 1026 SCIP_RETCODE freeReaderdata( 1027 SCIP* scip, /**< the SCIP data structure */ 1028 SCIP_READERDATA* readerdata /**< the reader data */ 1029 ) 1030 { 1031 assert(scip != NULL); 1032 assert(readerdata != NULL); 1033 1034 /* freeing the scenario tree */ 1035 if( readerdata->scenariotree != NULL ) 1036 SCIP_CALL( freeScenarioTree(scip, &readerdata->scenariotree) ); 1037 1038 SCIPfreeBlockMemory(scip, &readerdata); 1039 1040 return SCIP_OKAY; 1041 } 1042 1043 /** creates the sto input structure */ 1044 static 1045 SCIP_RETCODE stoinputCreate( 1046 SCIP* scip, /**< SCIP data structure */ 1047 STOINPUT** stoi, /**< sto input structure */ 1048 SCIP_FILE* fp /**< file object for the input file */ 1049 ) 1050 { 1051 assert(stoi != NULL); 1052 assert(fp != NULL); 1053 1054 SCIP_CALL( SCIPallocBlockMemory(scip, stoi) ); 1055 1056 (*stoi)->section = STO_STOCH; 1057 (*stoi)->stochinfotype = STO_STOCHINFO_NONE; 1058 (*stoi)->fp = fp; 1059 (*stoi)->lineno = 0; 1060 (*stoi)->haserror = FALSE; 1061 (*stoi)->buf [0] = '\0'; 1062 (*stoi)->probname[0] = '\0'; 1063 (*stoi)->stochtype[0] = '\0'; 1064 (*stoi)->f0 = NULL; 1065 (*stoi)->f1 = NULL; 1066 (*stoi)->f2 = NULL; 1067 (*stoi)->f3 = NULL; 1068 (*stoi)->f4 = NULL; 1069 (*stoi)->f5 = NULL; 1070 (*stoi)->f6 = NULL; 1071 1072 return SCIP_OKAY; 1073 } 1074 1075 /** free the sto input structure */ 1076 static 1077 void stoinputFree( 1078 SCIP* scip, /**< SCIP data structure */ 1079 STOINPUT** stoi /**< sto input structure */ 1080 ) 1081 { 1082 SCIPfreeBlockMemory(scip, stoi); 1083 } 1084 1085 /** returns the current section */ 1086 static 1087 STOSECTION stoinputSection( 1088 const STOINPUT* stoi /**< sto input structure */ 1089 ) 1090 { 1091 assert(stoi != NULL); 1092 1093 return stoi->section; 1094 } 1095 1096 /** returns the stochastic information type */ 1097 static 1098 STOSTOCHINFO stoinputStochInfoType( 1099 const STOINPUT* stoi /**< sto input structure */ 1100 ) 1101 { 1102 assert(stoi != NULL); 1103 1104 return stoi->stochinfotype; 1105 } 1106 1107 /** return the current value of field 0 */ 1108 static 1109 const char* stoinputField0( 1110 const STOINPUT* stoi /**< sto input structure */ 1111 ) 1112 { 1113 assert(stoi != NULL); 1114 1115 return stoi->f0; 1116 } 1117 1118 /** return the current value of field 1 */ 1119 static 1120 const char* stoinputField1( 1121 const STOINPUT* stoi /**< sto input structure */ 1122 ) 1123 { 1124 assert(stoi != NULL); 1125 1126 return stoi->f1; 1127 } 1128 1129 /** return the current value of field 2 */ 1130 static 1131 const char* stoinputField2( 1132 const STOINPUT* stoi /**< sto input structure */ 1133 ) 1134 { 1135 assert(stoi != NULL); 1136 1137 return stoi->f2; 1138 } 1139 1140 /** return the current value of field 3 */ 1141 static 1142 const char* stoinputField3( 1143 const STOINPUT* stoi /**< sto input structure */ 1144 ) 1145 { 1146 assert(stoi != NULL); 1147 1148 return stoi->f3; 1149 } 1150 1151 /** return the current value of field 4 */ 1152 static 1153 const char* stoinputField4( 1154 const STOINPUT* stoi /**< sto input structure */ 1155 ) 1156 { 1157 assert(stoi != NULL); 1158 1159 return stoi->f4; 1160 } 1161 1162 /** return the current value of field 5 */ 1163 static 1164 const char* stoinputField5( 1165 const STOINPUT* stoi /**< sto input structure */ 1166 ) 1167 { 1168 assert(stoi != NULL); 1169 1170 return stoi->f5; 1171 } 1172 1173 /** return the current value of field 6 */ 1174 static 1175 const char* stoinputField6( 1176 const STOINPUT* stoi /**< sto input structure */ 1177 ) 1178 { 1179 assert(stoi != NULL); 1180 1181 return stoi->f6; 1182 } 1183 1184 /** returns if an error was detected */ 1185 static 1186 SCIP_Bool stoinputHasError( 1187 const STOINPUT* stoi /**< sto input structure */ 1188 ) 1189 { 1190 assert(stoi != NULL); 1191 1192 return stoi->haserror; 1193 } 1194 1195 /** set the section in the sto input structure to given section */ 1196 static 1197 void stoinputSetSection( 1198 STOINPUT* stoi, /**< sto input structure */ 1199 STOSECTION section /**< section that is set */ 1200 ) 1201 { 1202 assert(stoi != NULL); 1203 1204 stoi->section = section; 1205 } 1206 1207 /** set the stochastic info type in the sto input structure */ 1208 static 1209 void stoinputSetStochInfoType( 1210 STOINPUT* stoi, /**< sto input structure */ 1211 STOSTOCHINFO stochinfotype /**< the stochastic infomation type */ 1212 ) 1213 { 1214 assert(stoi != NULL); 1215 1216 stoi->stochinfotype = stochinfotype; 1217 } 1218 1219 /** set the problem name in the sto input structure to given problem name */ 1220 static 1221 void stoinputSetProbname( 1222 STOINPUT* stoi, /**< sto input structure */ 1223 const char* probname /**< name of the problem to set */ 1224 ) 1225 { 1226 assert(stoi != NULL); 1227 assert(probname != NULL); 1228 assert(strlen(probname) < sizeof(stoi->probname)); 1229 1230 (void)SCIPmemccpy(stoi->probname, probname, '\0', STO_MAX_NAMELEN - 1); 1231 } 1232 1233 /** set the type name in the sto input structure to given objective name */ 1234 static 1235 void stoinputSetStochtype( 1236 STOINPUT* stoi, /**< sto input structure */ 1237 const char* stochtype /**< name of the scenario type */ 1238 ) 1239 { 1240 assert(stoi != NULL); 1241 assert(stochtype != NULL); 1242 assert(strlen(stochtype) < sizeof(stoi->stochtype)); 1243 1244 (void)SCIPmemccpy(stoi->stochtype, stochtype, '\0', STO_MAX_NAMELEN - 1); 1245 } 1246 1247 static 1248 void stoinputSyntaxerror( 1249 STOINPUT* stoi /**< sto input structure */ 1250 ) 1251 { 1252 assert(stoi != NULL); 1253 1254 SCIPerrorMessage("Syntax error in line %d\n", stoi->lineno); 1255 stoi->section = STO_ENDATA; 1256 stoi->haserror = TRUE; 1257 } 1258 1259 /** fill the line from \p pos up to column 80 with blanks. */ 1260 static 1261 void clearFrom( 1262 char* buf, /**< buffer to clear */ 1263 unsigned int pos /**< position to start the clearing process */ 1264 ) 1265 { 1266 unsigned int i; 1267 1268 for(i = pos; i < 80; i++) 1269 buf[i] = BLANK; 1270 buf[80] = '\0'; 1271 } 1272 1273 /** read a sto format data line and parse the fields. */ 1274 static 1275 SCIP_Bool stoinputReadLine( 1276 STOINPUT* stoi /**< sto input structure */ 1277 ) 1278 { 1279 unsigned int len; 1280 unsigned int i; 1281 char* s; 1282 SCIP_Bool is_marker; 1283 SCIP_Bool is_empty; 1284 char* nexttok; 1285 1286 do 1287 { 1288 stoi->f0 = stoi->f1 = stoi->f2 = stoi->f3 = stoi->f4 = stoi->f5 = stoi->f6 = 0; 1289 is_marker = FALSE; 1290 1291 /* Read until we have not a comment line. */ 1292 do 1293 { 1294 stoi->buf[STO_MAX_LINELEN-1] = '\0'; 1295 if( NULL == SCIPfgets(stoi->buf, (int) sizeof(stoi->buf), stoi->fp) ) 1296 return FALSE; 1297 stoi->lineno++; 1298 } 1299 while( *stoi->buf == '*' ); /* coverity[a_loop_bound] */ 1300 1301 /* Normalize line */ 1302 len = (unsigned int) strlen(stoi->buf); 1303 1304 for( i = 0; i < len; i++ ) 1305 { 1306 if( (stoi->buf[i] == '\t') || (stoi->buf[i] == '\n') || (stoi->buf[i] == '\r') ) 1307 stoi->buf[i] = BLANK; 1308 } 1309 1310 if( len < 80 ) 1311 clearFrom(stoi->buf, len); 1312 1313 SCIPdebugMessage("line %d: <%s>\n", stoi->lineno, stoi->buf); 1314 1315 assert(strlen(stoi->buf) >= 80); 1316 1317 /* Look for new section */ 1318 if( *stoi->buf != BLANK ) 1319 { 1320 stoi->f0 = SCIPstrtok(&stoi->buf[0], " ", &nexttok); 1321 1322 assert(stoi->f0 != 0); 1323 1324 stoi->f1 = SCIPstrtok(NULL, " ", &nexttok); 1325 1326 return TRUE; 1327 } 1328 1329 s = &stoi->buf[1]; 1330 1331 /* At this point it is not clear if we have a indicator field. 1332 * If there is none (e.g. empty) f1 will be the first name field. 1333 * If there is one, f2 will be the first name field. 1334 * 1335 * Initially comment marks '$' are only allowed in the beginning 1336 * of the 2nd and 3rd name field. We test all fields but the first. 1337 * This makes no difference, since if the $ is at the start of a value 1338 * field, the line will be erroneous anyway. 1339 */ 1340 do 1341 { 1342 if( NULL == (stoi->f1 = SCIPstrtok(s, " ", &nexttok)) ) 1343 break; 1344 1345 if( (NULL == (stoi->f2 = SCIPstrtok(NULL, " ", &nexttok))) || (*stoi->f2 == '$') ) 1346 { 1347 stoi->f2 = 0; 1348 break; 1349 } 1350 1351 if( (NULL == (stoi->f3 = SCIPstrtok(NULL, " ", &nexttok))) || (*stoi->f3 == '$') ) 1352 { 1353 stoi->f3 = 0; 1354 break; 1355 } 1356 1357 if( (NULL == (stoi->f4 = SCIPstrtok(NULL, " ", &nexttok))) || (*stoi->f4 == '$') ) 1358 { 1359 stoi->f4 = 0; 1360 break; 1361 } 1362 1363 if( (NULL == (stoi->f5 = SCIPstrtok(NULL, " ", &nexttok))) || (*stoi->f5 == '$') ) 1364 { 1365 stoi->f5 = 0; 1366 break; 1367 } 1368 1369 if( (NULL == (stoi->f6 = SCIPstrtok(NULL, " ", &nexttok))) || (*stoi->f6 == '$') ) 1370 stoi->f6 = 0; 1371 } 1372 while( FALSE ); 1373 1374 /* check for empty lines */ 1375 is_empty = (stoi->f0 == NULL && stoi->f1 == NULL); 1376 } 1377 while( is_marker || is_empty ); 1378 1379 return TRUE; 1380 } 1381 1382 /** Process STOCH section. */ 1383 static 1384 SCIP_RETCODE readStoch( 1385 SCIP* scip, /**< SCIP data structure */ 1386 STOINPUT* stoi /**< sto input structure */ 1387 ) 1388 { 1389 assert(stoi != NULL); 1390 1391 SCIPdebugMsg(scip, "read problem name\n"); 1392 1393 /* This has to be the Line with the NAME section. */ 1394 if( !stoinputReadLine(stoi) || stoinputField0(stoi) == NULL || strcmp(stoinputField0(stoi), "STOCH") ) 1395 { 1396 stoinputSyntaxerror(stoi); 1397 return SCIP_OKAY; 1398 } 1399 1400 /* Sometimes the name is omitted. */ 1401 stoinputSetProbname(stoi, (stoinputField1(stoi) == 0) ? "_STO_" : stoinputField1(stoi)); 1402 1403 /* This hat to be a new section */ 1404 /* coverity[tainted_data] */ 1405 if( !stoinputReadLine(stoi) || (stoinputField0(stoi) == NULL) ) 1406 { 1407 stoinputSyntaxerror(stoi); 1408 return SCIP_OKAY; 1409 } 1410 1411 /* setting the stochatic information section */ 1412 if( !strncmp(stoinputField0(stoi), "BLOCKS", 6) ) 1413 stoinputSetSection(stoi, STO_BLOCKS); 1414 else if( !strncmp(stoinputField0(stoi), "SCENARIOS", 9) ) 1415 stoinputSetSection(stoi, STO_SCENARIOS); 1416 else if( !strncmp(stoinputField0(stoi), "INDEP", 5) ) 1417 stoinputSetSection(stoi, STO_INDEP); 1418 else 1419 { 1420 stoinputSyntaxerror(stoi); 1421 return SCIP_OKAY; 1422 } 1423 1424 /* setting the stochastic information type */ 1425 if( !strncmp(stoinputField1(stoi), "DISCRETE", 8) ) 1426 stoinputSetStochInfoType(stoi, STO_STOCHINFO_DISCRETE); 1427 else if( !strncmp(stoinputField1(stoi), "UNIFORM", 7) ) 1428 stoinputSetStochInfoType(stoi, STO_STOCHINFO_UNIFORM); 1429 else if( !strncmp(stoinputField1(stoi), "NORMAL", 6) ) 1430 stoinputSetStochInfoType(stoi, STO_STOCHINFO_NORMAL); 1431 else if( !strncmp(stoinputField1(stoi), "SUB", 3) ) 1432 stoinputSetStochInfoType(stoi, STO_STOCHINFO_SUB); 1433 else if( !strncmp(stoinputField1(stoi), "LINTR", 5) ) 1434 stoinputSetStochInfoType(stoi, STO_STOCHINFO_LINTR); 1435 else 1436 { 1437 stoinputSyntaxerror(stoi); 1438 return SCIP_OKAY; 1439 } 1440 1441 return SCIP_OKAY; 1442 } 1443 1444 /** Process BLOCKS section. */ 1445 static 1446 SCIP_RETCODE readBlocks( 1447 STOINPUT* stoi, /**< sto input structure */ 1448 SCIP* scip, /**< SCIP data structure */ 1449 SCIP_READERDATA* readerdata /**< the reader data */ 1450 ) 1451 { 1452 STOSCENARIO*** blocks; 1453 int numblocks; 1454 int* numblocksperblock; 1455 int blockssize; 1456 int* blocksperblocksize; 1457 char BL[] = "BL"; 1458 int blocknum; 1459 int blockindex; 1460 int i; 1461 int j; 1462 char stagenames[SCIP_MAXSTRLEN]; 1463 int numstages; 1464 1465 SCIPdebugMsg(scip, "read Blocks\n"); 1466 1467 /* This has to be the Line with the name. */ 1468 if( stoinputField1(stoi) == NULL ) 1469 { 1470 stoinputSyntaxerror(stoi); 1471 return SCIP_OKAY; 1472 } 1473 1474 stoinputSetStochtype(stoi, stoinputField1(stoi)); 1475 1476 /* initializing the block data */ 1477 numblocks = 0; 1478 blockssize = STO_DEFAULT_ARRAYSIZE; 1479 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &blocks, STO_DEFAULT_ARRAYSIZE) ); 1480 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &numblocksperblock, STO_DEFAULT_ARRAYSIZE) ); 1481 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &blocksperblocksize, STO_DEFAULT_ARRAYSIZE) ); 1482 1483 blockindex = 0; 1484 blocknum = 0; 1485 1486 /* initializing the stage names record */ 1487 numstages = 0; 1488 (void) SCIPsnprintf(stagenames, SCIP_MAXSTRLEN, ""); 1489 1490 /* coverity[tainted_data] */ 1491 while( stoinputReadLine(stoi) ) 1492 { 1493 if( stoinputField0(stoi) != NULL ) 1494 { 1495 if( !strcmp(stoinputField0(stoi), "BLOCKS") ) 1496 { 1497 stoinputSetSection(stoi, STO_BLOCKS); 1498 if( strcmp(stoinputField1(stoi), "DISCRETE") ) 1499 { 1500 SCIPerrorMessage("Sorry, %s blocks stucture is not currently supported.\n", stoinputField1(stoi)); 1501 SCIPerrorMessage("Only DISCRETE blocks are supported.\n"); 1502 goto TERMINATE; 1503 } 1504 } 1505 else if( !strcmp(stoinputField0(stoi), "ENDATA") ) 1506 { 1507 SCIP_CALL( createScenariosFromBlocks(scip, readerdata, blocks, numblocks, numblocksperblock, numstages) ); 1508 stoinputSetSection(stoi, STO_ENDATA); 1509 } 1510 else 1511 stoinputSyntaxerror(stoi); 1512 1513 goto TERMINATE; 1514 } 1515 1516 if( strcmp(stoinputField1(stoi), BL) == 0 ) 1517 { 1518 SCIP_Bool foundblock = FALSE; 1519 1520 /* checking whether the stage has been added previously */ 1521 if( strstr(stagenames, stoinputField3(stoi)) == NULL ) 1522 { 1523 /* recording the stage name as processed */ 1524 (void) SCIPsnprintf(stagenames, SCIP_MAXSTRLEN, "%s_%s", stagenames, stoinputField3(stoi)); 1525 numstages++; 1526 } 1527 1528 /* determining whether a block name has previously been added */ 1529 for( i = 0; i < numblocks; i++ ) 1530 { 1531 if( strcmp(getScenarioName(blocks[i][0]), stoinputField2(stoi)) == 0 ) 1532 { 1533 foundblock = TRUE; 1534 break; 1535 } 1536 } 1537 blocknum = i; 1538 1539 /* if the block is found, then the memory for the blocks array must be ensured */ 1540 if( foundblock ) 1541 { 1542 /* ensuring enough memory is available for the blocks */ 1543 if( numblocksperblock[blocknum] + 1 > blocksperblocksize[blocknum] ) 1544 { 1545 int newsize; 1546 newsize = SCIPcalcMemGrowSize(scip, numblocksperblock[blocknum] + 1); 1547 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &blocks[blocknum], blocksperblocksize[blocknum], newsize) ); /*lint !e866*/ 1548 blocksperblocksize[blocknum] = newsize; 1549 } 1550 } 1551 else 1552 { 1553 /* ensuring enough memory is available for the blocks */ 1554 if( numblocks + 1 > blockssize ) 1555 { 1556 int newsize; 1557 newsize = SCIPcalcMemGrowSize(scip, numblocks + 1); 1558 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &blocks, blockssize, newsize) ); 1559 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &numblocksperblock, blockssize, newsize) ); 1560 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &blocksperblocksize, blockssize, newsize) ); 1561 blockssize = newsize; 1562 } 1563 1564 blocksperblocksize[blocknum] = STO_DEFAULT_BLOCKARRAYSIZE; 1565 numblocksperblock[blocknum] = 0; 1566 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &blocks[blocknum], blocksperblocksize[blocknum]) ); 1567 } 1568 1569 blockindex = numblocksperblock[blocknum]; 1570 1571 /* creating the scenario data structure */ 1572 SCIP_CALL( createScenarioData(scip, &blocks[blocknum][blockindex]) ); 1573 1574 SCIP_CALL( setScenarioName(scip, blocks[blocknum][blockindex], stoinputField2(stoi)) ); 1575 SCIP_CALL( setScenarioStageName(scip, blocks[blocknum][blockindex], stoinputField3(stoi)) ); 1576 SCIP_CALL( setScenarioProbability(scip, blocks[blocknum][blockindex], atof(stoinputField4(stoi))) ); 1577 numblocksperblock[blocknum]++; 1578 1579 if( !foundblock ) 1580 numblocks++; 1581 } 1582 else 1583 { 1584 SCIP_CALL( addScenarioEntry(scip, blocks[blocknum][blockindex], stoinputField2(stoi), stoinputField1(stoi), 1585 atof(stoinputField3(stoi))) ); 1586 } 1587 } 1588 stoinputSyntaxerror(stoi); 1589 1590 TERMINATE: 1591 1592 /* releasing the scenario data */ 1593 for( i = numblocks - 1; i >= 0; i-- ) 1594 { 1595 for( j = numblocksperblock[i] - 1; j >= 0; j-- ) 1596 SCIP_CALL( freeScenarioTree(scip, &blocks[i][j]) ); 1597 } 1598 1599 for( i = numblocks - 1; i >= 0; i-- ) 1600 SCIPfreeBlockMemoryArray(scip, &blocks[i], blocksperblocksize[i]); 1601 SCIPfreeBlockMemoryArray(scip, &blocksperblocksize, blockssize); 1602 SCIPfreeBlockMemoryArray(scip, &numblocksperblock, blockssize); 1603 SCIPfreeBlockMemoryArray(scip, &blocks, blockssize); 1604 1605 return SCIP_OKAY; 1606 } 1607 1608 1609 /** Process SCENARIOS section. */ 1610 static 1611 SCIP_RETCODE readScenarios( 1612 STOINPUT* stoi, /**< sto input structure */ 1613 SCIP* scip, /**< SCIP data structure */ 1614 SCIP_READERDATA* readerdata /**< the reader data */ 1615 ) 1616 { 1617 STOSCENARIO* scenario; 1618 char SC[] = "SC"; 1619 char wrongroot[] = "\'ROOT\'"; 1620 char parentname[SCIP_MAXSTRLEN]; 1621 char scennames[SCIP_MAXSTRLEN]; 1622 char tmpname[SCIP_MAXSTRLEN]; 1623 int numscenarios; 1624 SCIP_Bool addscenario; 1625 1626 SCIPdebugMsg(scip, "read SCENARIOS\n"); 1627 1628 /* This has to be the Line with the name. */ 1629 if( stoinputField1(stoi) == NULL ) 1630 { 1631 stoinputSyntaxerror(stoi); 1632 return SCIP_OKAY; 1633 } 1634 1635 stoinputSetStochtype(stoi, stoinputField1(stoi)); 1636 1637 /* initializing the scen names record */ 1638 numscenarios = 0; 1639 (void) SCIPsnprintf(scennames, SCIP_MAXSTRLEN, "ROOT"); 1640 1641 scenario = NULL; 1642 addscenario = FALSE; 1643 1644 /* initializing the root scenario in the reader data */ 1645 SCIP_CALL( setScenarioNum(scip, readerdata->scenariotree, 0) ); 1646 SCIP_CALL( setScenarioStageNum(scip, readerdata->scenariotree, 0) ); 1647 1648 /* coverity[tainted_data] */ 1649 while( stoinputReadLine(stoi) ) 1650 { 1651 if( stoinputField0(stoi) != NULL ) 1652 { 1653 /* if a scenario has been created that needs to be added to the scenario tree */ 1654 if( addscenario ) 1655 { 1656 SCIP_CALL( insertScenarioInReaderdata(scip, readerdata, scenario, parentname) ); 1657 1658 /* freeing the scenario */ 1659 SCIP_CALL( freeScenarioTree(scip, &scenario) ); 1660 } 1661 1662 if( !strcmp(stoinputField0(stoi), "SCENARIOS") ) 1663 { 1664 stoinputSetSection(stoi, STO_SCENARIOS); 1665 if( strcmp(stoinputField1(stoi), "DISCRETE") ) 1666 { 1667 SCIPerrorMessage("Sorry, %s scenarios is not currently supported.\n", stoinputField1(stoi)); 1668 SCIPerrorMessage("Only DISCRETE scenarios are supported.\n"); 1669 goto TERMINATE; 1670 } 1671 } 1672 else if( !strcmp(stoinputField0(stoi), "ENDATA") ) 1673 stoinputSetSection(stoi, STO_ENDATA); 1674 else 1675 stoinputSyntaxerror(stoi); 1676 1677 goto TERMINATE; 1678 } 1679 1680 if( strcmp(stoinputField1(stoi), SC) == 0 ) 1681 { 1682 int stagenum; 1683 1684 /* if a scenario has been created that needs to be added to the scenario tree */ 1685 if( addscenario ) 1686 { 1687 SCIP_CALL( insertScenarioInReaderdata(scip, readerdata, scenario, parentname) ); 1688 1689 /* freeing the scenario */ 1690 SCIP_CALL( freeScenarioTree(scip, &scenario) ); 1691 assert(scenario == NULL); 1692 } 1693 1694 if( strcmp(wrongroot, stoinputField3(stoi)) == 0 ) 1695 (void) SCIPsnprintf(parentname, SCIP_MAXSTRLEN, "%s", "ROOT"); 1696 else 1697 (void) SCIPsnprintf(parentname, SCIP_MAXSTRLEN, "%s", stoinputField3(stoi)); 1698 1699 /* checking whether the stage has been added previously */ 1700 if( strstr(scennames, stoinputField2(stoi)) == NULL ) 1701 { 1702 /* recording the stage name as processed */ 1703 (void) SCIPsnprintf(tmpname, SCIP_MAXSTRLEN, "%s_%s", scennames, stoinputField2(stoi)); 1704 (void) SCIPsnprintf(scennames, SCIP_MAXSTRLEN, "%s", tmpname); 1705 } 1706 1707 /* checking whether the "common" scenario has been added yet */ 1708 if( strstr(scennames, parentname) == NULL ) 1709 { 1710 SCIPerrorMessage("Scenario <%s> needs to be read before scenario <%s>\n", parentname, stoinputField2(stoi)); 1711 stoinputSyntaxerror(stoi); 1712 goto TERMINATE; 1713 } 1714 1715 /* the "common" scenario has been added before, so a child can be added to the scenario tree */ 1716 SCIP_CALL( createScenarioData(scip, &scenario) ); 1717 1718 SCIP_CALL( setScenarioName(scip, scenario, stoinputField2(stoi)) ); 1719 SCIP_CALL( setScenarioStageName(scip, scenario, stoinputField5(stoi)) ); 1720 SCIP_CALL( setScenarioNum(scip, scenario, numscenarios) ); 1721 1722 stagenum = SCIPtimFindStage(scip, stoinputField5(stoi)); 1723 if( stagenum < 0 ) 1724 { 1725 stoinputSyntaxerror(stoi); 1726 goto TERMINATE; 1727 } 1728 SCIP_CALL( setScenarioStageNum(scip, scenario, stagenum) ); 1729 SCIP_CALL( setScenarioProbability(scip, scenario, atof(stoinputField4(stoi))) ); 1730 if( stoinputField6(stoi) != NULL ) 1731 { 1732 SCIP_CALL( setScenarioLowerbound(scip, scenario, atof(stoinputField6(stoi))) ); 1733 } 1734 1735 numscenarios++; 1736 addscenario = TRUE; 1737 } 1738 else if( addscenario ) 1739 { 1740 SCIP_CALL( addScenarioEntry(scip, scenario, stoinputField2(stoi), stoinputField1(stoi), 1741 atof(stoinputField3(stoi))) ); 1742 } 1743 } 1744 stoinputSyntaxerror(stoi); 1745 1746 TERMINATE: 1747 1748 return SCIP_OKAY; 1749 } 1750 1751 1752 /** Process INDEP section. */ 1753 static 1754 SCIP_RETCODE readIndep( 1755 STOINPUT* stoi, /**< sto input structure */ 1756 SCIP* scip, /**< SCIP data structure */ 1757 SCIP_READERDATA* readerdata /**< the reader data */ 1758 ) 1759 { 1760 STOSCENARIO*** blocks; 1761 int numblocks; 1762 int* numblocksperblock; 1763 int blockssize; 1764 int* blocksperblocksize; 1765 int blocknum; 1766 int blockindex; 1767 int i; 1768 int j; 1769 char stagenames[SCIP_MAXSTRLEN]; 1770 int numstages; 1771 SCIP_Bool foundblock; 1772 1773 SCIP_Real probability; 1774 char currstagename[SCIP_MAXSTRLEN]; 1775 1776 SCIPdebugMsg(scip, "read Indep\n"); 1777 1778 /* This has to be the Line with the name. */ 1779 if( stoinputField1(stoi) == NULL ) 1780 { 1781 stoinputSyntaxerror(stoi); 1782 return SCIP_OKAY; 1783 } 1784 1785 stoinputSetStochtype(stoi, stoinputField1(stoi)); 1786 1787 /* initializing the block data */ 1788 numblocks = 0; 1789 blockssize = STO_DEFAULT_ARRAYSIZE; 1790 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &blocks, STO_DEFAULT_ARRAYSIZE) ); 1791 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &numblocksperblock, STO_DEFAULT_ARRAYSIZE) ); 1792 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &blocksperblocksize, STO_DEFAULT_ARRAYSIZE) ); 1793 1794 /* initializing the stage names record */ 1795 numstages = 0; 1796 (void) SCIPsnprintf(stagenames, SCIP_MAXSTRLEN, ""); 1797 1798 while( stoinputReadLine(stoi) ) 1799 { 1800 if( stoinputField0(stoi) != NULL ) 1801 { 1802 if( !strcmp(stoinputField0(stoi), "INDEP") ) 1803 { 1804 stoinputSetSection(stoi, STO_INDEP); 1805 } 1806 else if( !strcmp(stoinputField0(stoi), "ENDATA") ) 1807 { 1808 SCIP_CALL( createScenariosFromBlocks(scip, readerdata, blocks, numblocks, numblocksperblock, numstages) ); 1809 stoinputSetSection(stoi, STO_ENDATA); 1810 } 1811 else 1812 stoinputSyntaxerror(stoi); 1813 1814 goto TERMINATE; 1815 } 1816 1817 /* if the 5th input is NULL, then the 4th input is the probability. Otherwise, the 4th input is the stage name and 1818 * the 5th input is the probability. The stage name is redundant information, but sometimes included for more 1819 * information. 1820 */ 1821 if( stoinputField5(stoi) == NULL ) 1822 { 1823 probability = atof(stoinputField4(stoi)); 1824 (void) SCIPsnprintf(currstagename, SCIP_MAXSTRLEN, "%s", SCIPtimConsGetStageName(scip, stoinputField2(stoi))); 1825 } 1826 else 1827 { 1828 probability = atof(stoinputField5(stoi)); 1829 (void) SCIPsnprintf(currstagename, SCIP_MAXSTRLEN, "%s", stoinputField4(stoi)); 1830 } 1831 1832 /* checking whether the stage has been added previously */ 1833 if( strstr(stagenames, currstagename) == NULL ) 1834 { 1835 /* recording the stage name as processed */ 1836 (void) SCIPsnprintf(stagenames, SCIP_MAXSTRLEN, "%s_%s", stagenames, currstagename); 1837 1838 numstages++; 1839 } 1840 1841 foundblock = FALSE; 1842 1843 /* determining whether a block name has previously been added */ 1844 for( i = 0; i < numblocks; i++ ) 1845 { 1846 if( strcmp(getScenarioName(blocks[i][0]), stoinputField2(stoi)) == 0 ) 1847 { 1848 foundblock = TRUE; 1849 break; 1850 } 1851 } 1852 blocknum = i; 1853 1854 /* if the block is found, then the memory for the blocks array must be ensured */ 1855 if( foundblock ) 1856 { 1857 /* ensuring enough memory is available for the blocks */ 1858 if( numblocksperblock[blocknum] + 1 > blocksperblocksize[blocknum] ) 1859 { 1860 int newsize; 1861 newsize = SCIPcalcMemGrowSize(scip, numblocksperblock[blocknum] + 1); 1862 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &blocks[blocknum], blocksperblocksize[blocknum], newsize) ); /*lint !e866*/ 1863 blocksperblocksize[blocknum] = newsize; 1864 } 1865 } 1866 else 1867 { 1868 /* ensuring enough memory is available for the blocks */ 1869 if( numblocks + 1 > blockssize ) 1870 { 1871 int newsize; 1872 newsize = SCIPcalcMemGrowSize(scip, numblocks + 1); 1873 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &blocks, blockssize, newsize) ); 1874 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &numblocksperblock, blockssize, newsize) ); 1875 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &blocksperblocksize, blockssize, newsize) ); 1876 blockssize = newsize; 1877 } 1878 1879 blocksperblocksize[blocknum] = STO_DEFAULT_BLOCKARRAYSIZE; 1880 numblocksperblock[blocknum] = 0; 1881 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &blocks[blocknum], blocksperblocksize[blocknum]) ); 1882 } 1883 1884 blockindex = numblocksperblock[blocknum]; 1885 1886 /* creating the scenario data structure */ 1887 SCIP_CALL( createScenarioData(scip, &blocks[blocknum][blockindex]) ); 1888 1889 SCIP_CALL( setScenarioName(scip, blocks[blocknum][blockindex], stoinputField2(stoi)) ); 1890 SCIP_CALL( setScenarioStageName(scip, blocks[blocknum][blockindex], currstagename) ); 1891 SCIP_CALL( setScenarioProbability(scip, blocks[blocknum][blockindex], probability) ); 1892 numblocksperblock[blocknum]++; 1893 1894 if( !foundblock ) 1895 numblocks++; 1896 1897 SCIP_CALL( addScenarioEntry(scip, blocks[blocknum][blockindex], stoinputField2(stoi), stoinputField1(stoi), 1898 atof(stoinputField3(stoi))) ); 1899 } 1900 stoinputSyntaxerror(stoi); 1901 1902 TERMINATE: 1903 1904 /* releasing the scenario data */ 1905 for( i = numblocks - 1; i >= 0; i-- ) 1906 { 1907 for( j = numblocksperblock[i] - 1; j >= 0; j-- ) 1908 SCIP_CALL( freeScenarioTree(scip, &blocks[i][j]) ); 1909 } 1910 1911 for( i = numblocks - 1; i >= 0; i-- ) 1912 SCIPfreeBlockMemoryArray(scip, &blocks[i], blocksperblocksize[i]); 1913 SCIPfreeBlockMemoryArray(scip, &blocksperblocksize, blockssize); 1914 SCIPfreeBlockMemoryArray(scip, &numblocksperblock, blockssize); 1915 SCIPfreeBlockMemoryArray(scip, &blocks, blockssize); 1916 1917 return SCIP_OKAY; 1918 } 1919 1920 1921 /** computes the probability of a scenario */ 1922 static 1923 SCIP_Real computeScenarioProbability( 1924 SCIP* scip, /**< the SCIP data structure */ 1925 STOSCENARIO* scenario /**< the current scenario */ 1926 ) 1927 { 1928 STOSCENARIO* checkscen; 1929 SCIP_Real probability; 1930 1931 assert(scip != NULL); 1932 assert(scenario != NULL); 1933 1934 /* computing the probability for the scenario */ 1935 checkscen = scenario; 1936 probability = 1; 1937 while( checkscen != NULL ) 1938 { 1939 probability *= getScenarioProbability(scip, checkscen); 1940 checkscen = getScenarioParent(checkscen); 1941 } 1942 1943 return probability; 1944 } 1945 1946 /** gets the variable name */ 1947 static 1948 void getScenarioEntityName( 1949 char* name, /**< the name to be returned */ 1950 const char* varname, /**< the root of the variable name */ 1951 int stagenum, /**< the stage number */ 1952 int scenarionum /**< the scenario number */ 1953 ) 1954 { 1955 if( stagenum < 0 ) 1956 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_00_%d", varname, scenarionum); 1957 else 1958 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_%d", varname, stagenum, scenarionum); 1959 } 1960 1961 1962 /** add variables to the scenario */ 1963 static 1964 SCIP_RETCODE addScenarioVarsToProb( 1965 SCIP* scip, /**< the SCIP data structure */ 1966 STOSCENARIO* scenario, /**< the current scenario */ 1967 SCIP_HASHMAP* varmap, /**< the variable map from the original to the subproblem variables */ 1968 SCIP_VAR** vars, /**< the variables of the core problem associated with this scenario */ 1969 int nvars /**< the number of variables for this scenario */ 1970 ) 1971 { 1972 SCIP_Real probability; 1973 int i; 1974 char name[SCIP_MAXSTRLEN]; 1975 1976 assert(scip != NULL); 1977 assert(scenario != NULL); 1978 assert(vars != NULL); 1979 1980 /* computing the probability for the scenario */ 1981 probability = computeScenarioProbability(scip, scenario); 1982 1983 for( i = 0; i < nvars; i++ ) 1984 { 1985 SCIP_VAR* var; 1986 SCIP_Real obj; 1987 SCIP_VARTYPE vartype; 1988 1989 SCIPdebugMessage("Original problem variable <%s> is being duplicated for scenario %d\n", SCIPvarGetName(vars[i]), 1990 getScenarioNum(scip, scenario)); 1991 1992 if( SCIPvarIsDeleted(vars[i]) ) 1993 continue; 1994 1995 obj = SCIPvarGetObj(vars[i])*probability; 1996 1997 vartype = SCIPvarGetType(vars[i]); 1998 1999 /* creating a variable as a copy of the original variable. */ 2000 getScenarioEntityName(name, SCIPvarGetName(vars[i]), getScenarioStageNum(scip, scenario), getScenarioNum(scip, scenario)); 2001 SCIP_CALL( SCIPcreateVar(scip, &var, name, SCIPvarGetLbOriginal(vars[i]), SCIPvarGetUbOriginal(vars[i]), 2002 obj, vartype, SCIPvarIsInitial(vars[i]), SCIPvarIsRemovable(vars[i]), NULL, NULL, NULL, 2003 NULL, NULL) ); 2004 2005 SCIPdebugMessage("Adding variable <%s>\n", name); 2006 2007 SCIP_CALL( SCIPaddVar(scip, var) ); 2008 2009 /* inserting the scenario variable into the hashmap */ 2010 SCIP_CALL( SCIPhashmapInsert(varmap, vars[i], var) ); 2011 2012 SCIP_CALL( SCIPreleaseVar(scip, &var) ); 2013 } 2014 2015 return SCIP_OKAY; 2016 } 2017 2018 2019 /** finds the scenario variable to add to a constraint */ 2020 static 2021 SCIP_RETCODE findScenarioVar( 2022 SCIP* scip, /**< the SCIP data structure */ 2023 STOSCENARIO* scenario, /**< the current scenario */ 2024 SCIP_VAR* consvar, /**< the variable in the constraint that is being searched for */ 2025 SCIP_VAR** scenariovar /**< pointer to return the variable to be added to the constraint */ 2026 ) 2027 { 2028 STOSCENARIO* checkscen; 2029 char varname[SCIP_MAXSTRLEN]; 2030 2031 assert(scip != NULL); 2032 assert(scenario != NULL); 2033 assert(consvar != NULL); 2034 assert(scenariovar != NULL); 2035 2036 (*scenariovar) = NULL; 2037 2038 checkscen = scenario; 2039 2040 /* NOTE: if the variable does not exist, then we need to search the preceding scenarios. In the case of 2041 * decomposition, then we only check the preceding scenario. As such, a check count is used to limit the number 2042 * of scenario checks. */ 2043 while( (*scenariovar) == NULL ) 2044 { 2045 assert(checkscen != NULL); 2046 if( getScenarioStageNum(scip, checkscen) == 0 ) 2047 (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "%s", SCIPvarGetName(consvar)); 2048 else 2049 getScenarioEntityName(varname, SCIPvarGetName(consvar), getScenarioStageNum(scip, checkscen), 2050 getScenarioNum(scip, checkscen)); 2051 2052 (*scenariovar) = SCIPfindVar(scip, varname); 2053 2054 checkscen = getScenarioParent(checkscen); 2055 } 2056 2057 if( (*scenariovar) == NULL ) 2058 { 2059 SCIPerrorMessage("There is no scenario variable could be found.\n"); 2060 return SCIP_READERROR; 2061 } 2062 2063 return SCIP_OKAY; 2064 } 2065 2066 2067 /** create variable for the decomposed scenario */ 2068 static 2069 SCIP_RETCODE getScenarioDecompVar( 2070 SCIP* scip, /**< the SCIP data structure */ 2071 STOSCENARIO* scenario, /**< the current scenario */ 2072 SCIP_VAR* consvar, /**< the variable in the constraint that is being searched for */ 2073 SCIP_VAR** scenariovar, /**< pointer to return the variable to be added to the constraint */ 2074 SCIP_Bool* varadded /**< pointer to indicate whether a variable has been added */ 2075 ) 2076 { 2077 STOSCENARIO* checkscen; 2078 SCIP_VAR* searchvar; 2079 int checkcount; 2080 char varname[SCIP_MAXSTRLEN]; 2081 2082 assert(scip != NULL); 2083 assert(scenario != NULL); 2084 assert(consvar != NULL); 2085 2086 (*varadded) = FALSE; 2087 2088 /* finding the scenario that the consvar belongs to */ 2089 checkscen = scenario; 2090 searchvar = NULL; 2091 checkcount = 0; 2092 while( searchvar == NULL && checkcount < 2 ) 2093 { 2094 assert(checkscen != NULL); 2095 if( getScenarioStageNum(scip, checkscen) == 0 ) 2096 (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "%s", SCIPvarGetName(consvar)); 2097 else 2098 getScenarioEntityName(varname, SCIPvarGetName(consvar), getScenarioStageNum(scip, checkscen), 2099 getScenarioNum(scip, checkscen)); 2100 2101 /* first checking whether the variable is included in the scenario */ 2102 searchvar = SCIPfindVar(scip, varname); 2103 if( searchvar != NULL ) 2104 { 2105 (*scenariovar) = searchvar; 2106 return SCIP_OKAY; 2107 } 2108 2109 searchvar = SCIPfindVar(getScenarioScip(checkscen), varname); 2110 2111 checkscen = getScenarioParent(checkscen); 2112 checkcount++; 2113 } 2114 2115 if( searchvar != NULL ) 2116 { 2117 SCIP_VAR* var; 2118 /* creating a variable as a copy of the original variable. */ 2119 SCIP_CALL( SCIPcreateVar(scip, &var, varname, SCIPvarGetLbOriginal(searchvar), SCIPvarGetUbOriginal(searchvar), 2120 0.0, SCIPvarGetType(searchvar), SCIPvarIsInitial(searchvar), SCIPvarIsRemovable(searchvar), NULL, NULL, 2121 NULL, NULL, NULL) ); 2122 2123 SCIP_CALL( SCIPaddVar(scip, var) ); 2124 2125 (*scenariovar) = var; 2126 (*varadded) = TRUE; 2127 } 2128 2129 return SCIP_OKAY; 2130 } 2131 2132 2133 /** adds the constraint to the scenario problem */ 2134 static 2135 SCIP_RETCODE addScenarioConsToProb( 2136 SCIP* scip, /**< the SCIP data structure */ 2137 SCIP* scenarioscip, /**< the scenario SCIP data structure */ 2138 STOSCENARIO* scenario, /**< the current scenario */ 2139 SCIP_HASHMAP* varmap, /**< the variable map from the original to the subproblem variables */ 2140 SCIP_CONS** conss, /**< the constraints of the core problem associated with this scenario */ 2141 int nconss, /**< the number of constraints for this scenario */ 2142 SCIP_Bool decomp /**< is the problem being decomposed */ 2143 ) 2144 { 2145 int i; 2146 int j; 2147 char name[SCIP_MAXSTRLEN]; 2148 SCIP_Bool varadded; 2149 2150 assert(scip != NULL); 2151 assert(scenarioscip != NULL); 2152 assert(scenario != NULL); 2153 assert(conss != NULL); 2154 2155 /* Add constraints */ 2156 /* NOTE: It is assumed that the problems only have linear constraints */ 2157 for( i = 0; i < nconss; i++ ) 2158 { 2159 SCIP_CONS* cons; 2160 SCIP_VAR** consvars = NULL; 2161 int nconsvars; 2162 SCIP_Bool success1 = TRUE; 2163 SCIP_Bool success2 = TRUE; 2164 2165 if( SCIPconsIsDeleted(conss[i]) ) 2166 continue; 2167 2168 /* getting the number of variables in the constraints */ 2169 SCIP_CALL( SCIPgetConsNVars(scip, conss[i], &nconsvars, &success1) ); 2170 2171 if( success1 ) 2172 { 2173 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) ); 2174 SCIP_CALL( SCIPgetConsVars(scip, conss[i], consvars, nconsvars, &success2) ); 2175 2176 /* If the get variable callback is not implemented for the constraint, then the success flag will be returned 2177 * as FALSE. In this case, it is not possible to build the stochastic program, so an error will be returned. 2178 */ 2179 if( !success2 ) 2180 { 2181 SCIPfreeBufferArrayNull(scip, consvars); 2182 } 2183 } 2184 2185 if( !success1 || !success2 ) 2186 { 2187 SCIPerrorMessage("It is not possible to copy constraint <%s>. The stochastic program can not be built.\n", 2188 SCIPconsGetName(conss[i])); 2189 2190 return SCIP_READERROR; 2191 } 2192 2193 assert(consvars != NULL); 2194 for( j = 0; j < nconsvars; j++ ) 2195 { 2196 SCIP_VAR* scenariovar; 2197 2198 scenariovar = NULL; 2199 2200 varadded = FALSE; 2201 2202 if( decomp ) 2203 SCIP_CALL( getScenarioDecompVar(scenarioscip, scenario, consvars[j], &scenariovar, &varadded) ); 2204 else 2205 SCIP_CALL( findScenarioVar(scenarioscip, scenario, consvars[j], &scenariovar) ); 2206 2207 if( scenariovar != NULL ) 2208 { 2209 /* checking whether the variable is in the variable hashmap. If it doesn't exist, then it is added to the 2210 * variable hashmap 2211 */ 2212 if( !SCIPhashmapExists(varmap, consvars[j]) ) 2213 { 2214 SCIP_CALL( SCIPhashmapInsert(varmap, consvars[j], scenariovar) ); 2215 } 2216 } 2217 2218 if( varadded ) 2219 { 2220 SCIP_CALL( SCIPreleaseVar(scenarioscip, &scenariovar) ); 2221 } 2222 } 2223 2224 /* creating a linear constraint as a copy of the original constraint. */ 2225 getScenarioEntityName(name, SCIPconsGetName(conss[i]), getScenarioStageNum(scip, scenario), getScenarioNum(scip, scenario)); 2226 2227 /* copying the constraint from the original SCIP to the stochastic program */ 2228 SCIP_CALL( SCIPgetConsCopy(scip, scenarioscip, conss[i], &cons, SCIPconsGetHdlr(conss[i]), varmap, NULL, name, 2229 SCIPconsIsInitial(conss[i]), SCIPconsIsSeparated(conss[i]), SCIPconsIsEnforced(conss[i]), 2230 SCIPconsIsChecked(conss[i]), SCIPconsIsMarkedPropagate(conss[i]), SCIPconsIsLocal(conss[i]), 2231 SCIPconsIsModifiable(conss[i]), SCIPconsIsDynamic(conss[i]), SCIPconsIsRemovable(conss[i]), 2232 SCIPconsIsStickingAtNode(conss[i]), TRUE, &success1) ); 2233 2234 /* freeing the cons vars buffer array */ 2235 SCIPfreeBufferArray(scip, &consvars); 2236 2237 /* if the copy failed, then the scenarios can not be created. */ 2238 if( !success1 ) 2239 { 2240 SCIPerrorMessage("It is not possible to copy constraint <%s>. The stochastic program can not be built.\n", 2241 SCIPconsGetName(conss[i])); 2242 return SCIP_READERROR; 2243 } 2244 2245 SCIP_CALL( SCIPaddCons(scenarioscip, cons) ); 2246 SCIP_CALL( SCIPreleaseCons(scenarioscip, &cons) ); 2247 } 2248 2249 return SCIP_OKAY; 2250 } 2251 2252 /** add variables and constraint to problem */ 2253 static 2254 SCIP_RETCODE addScenarioVarsAndConsToProb( 2255 SCIP* scip, /**< the SCIP data structure of master problem */ 2256 STOSCENARIO* scenario, /**< the current scenario */ 2257 SCIP_Bool decomp /**< is the problem being decomposed */ 2258 ) 2259 { 2260 SCIP* scenarioscip; 2261 SCIP_BENDERS* benders; 2262 SCIP_HASHMAP* varmap; 2263 SCIP_CONS** conss; 2264 SCIP_VAR** vars; 2265 SCIP_Real probability; 2266 int nconss; 2267 int nvars; 2268 int nmastervars; 2269 int nentries; 2270 int stagenum; 2271 int i; 2272 char name[SCIP_MAXSTRLEN]; 2273 2274 assert(scip != NULL); 2275 assert(scenario != NULL); 2276 2277 stagenum = SCIPtimFindStage(scip, getScenarioStageName(scip, scenario)); 2278 if( stagenum < 0 || stagenum >= SCIPtimGetNStages(scip) ) 2279 { 2280 SCIPerrorMessage("Unable to build stochastic program - stage <%s> was not found\n", 2281 getScenarioStageName(scip, scenario)); 2282 return SCIP_READERROR; 2283 } 2284 2285 SCIPdebugMessage("Creating scenario at stage <%d>. Scenario: %d Stage: %d\n", stagenum, getScenarioNum(scip, scenario), 2286 getScenarioStageNum(scip, scenario)); 2287 2288 conss = SCIPtimGetStageConss(scip, stagenum); 2289 nconss = SCIPtimGetStageNConss(scip, stagenum); 2290 vars = SCIPtimGetStageVars(scip, stagenum); 2291 nvars = SCIPtimGetStageNVars(scip, stagenum); 2292 2293 nmastervars = SCIPgetNVars(scip); 2294 2295 /* this if 0 will be removed when the stochastic reader is merged with the Benders' branch */ 2296 if( decomp ) 2297 { 2298 SCIP_CALL( SCIPcreate(&scenarioscip) ); 2299 2300 getScenarioEntityName(name, SCIPgetProbName(scip), getScenarioStageNum(scip, scenario), getScenarioNum(scip, scenario)); 2301 2302 /* creating the problem */ 2303 SCIP_CALL( SCIPcreateProbBasic(scenarioscip, name) ); 2304 2305 /* we explicitly enable the use of a debug solution for this main SCIP instance */ 2306 SCIPenableDebugSol(scenarioscip); 2307 2308 /* include default SCIP plugins */ 2309 SCIP_CALL( SCIPincludeDefaultPlugins(scenarioscip) ); 2310 2311 /* activating the Benders' constraint handler for the scenario stages. 2312 * TODO: consider whether the two-phase method should be activated by default in the scenario stages. 2313 */ 2314 SCIP_CALL( SCIPsetBoolParam(scenarioscip, "constraints/benders/active", TRUE) ); 2315 2316 /* allocating memory for the subproblems */ 2317 if( getScenarioNChildren(scenario) > 0 ) 2318 SCIP_CALL( createScenarioSubproblemArray(scip, scenario) ); 2319 } 2320 else 2321 scenarioscip = scip; 2322 2323 /* adding the scenarioscip to the scenario */ 2324 setScenarioScip(scenario, scenarioscip); 2325 2326 /* creating the variable hashmap to copy the constraints */ 2327 SCIP_CALL( SCIPhashmapCreate(&varmap, SCIPblkmem(scenarioscip), nmastervars) ); 2328 2329 /* adding the variables to the scenario */ 2330 SCIP_CALL( addScenarioVarsToProb(scenarioscip, scenario, varmap, vars, nvars) ); 2331 2332 /* adding the constraints to the scenario */ 2333 SCIP_CALL( addScenarioConsToProb(scip, scenarioscip, scenario, varmap, conss, nconss, decomp) ); 2334 2335 /* destroying the hashmap */ 2336 SCIPhashmapFree(&varmap); 2337 2338 /* add the variables and constraints of the child scenarios */ 2339 for( i = 0; i < getScenarioNChildren(scenario); i++ ) 2340 { 2341 /* the master SCIP is always passed to the recursive function. The scenario SCIP instances are generated in the 2342 * function call. */ 2343 SCIP_CALL( addScenarioVarsAndConsToProb(scip, getScenarioChild(scenario, i), decomp) ); 2344 if( decomp ) 2345 addScenarioSubproblem(scenario, getScenarioScip(getScenarioChild(scenario, i))); 2346 } 2347 2348 /* adding the Benders' decomposition */ 2349 if( decomp && getScenarioNChildren(scenario) > 0 ) 2350 { 2351 SCIP_CALL( SCIPcreateBendersDefault(scenarioscip, getScenarioSubproblemArray(scenario), getScenarioNChildren(scenario)) ); 2352 2353 /* getting the default Benders' decomposition */ 2354 benders = SCIPfindBenders(scenarioscip, "default"); 2355 2356 /* updating the lower bounds for the subproblems */ 2357 for( i = 0; i < getScenarioNChildren(scenario); i++ ) 2358 SCIPbendersUpdateSubproblemLowerbound(benders, i, 2359 getScenarioLowerbound(scenarioscip, getScenarioChild(scenario, i))); 2360 } 2361 2362 /* computing the probability for the scenario */ 2363 probability = computeScenarioProbability(scenarioscip, scenario); 2364 2365 /* change the constraints for the given scenario */ 2366 nentries = getScenarioNEntries(scenario); 2367 for( i = 0; i < nentries; i++ ) 2368 { 2369 SCIP_CONS* cons; 2370 SCIP_VAR* var; 2371 char RHS[] = "RHS"; 2372 char rhs[] = "rhs"; 2373 char RIGHT[] = "RIGHT"; 2374 char MINI[] = "MINI"; 2375 char obj[] = "obj"; 2376 char OBJ[] = "OBJ"; 2377 2378 /* finding the constraint associated with the row */ 2379 getScenarioEntityName(name, getScenarioEntryRow(scenario, i), getScenarioStageNum(scenarioscip, scenario), 2380 getScenarioNum(scenarioscip, scenario)); 2381 cons = SCIPfindCons(scenarioscip, name); 2382 2383 if( strncmp(getScenarioEntryCol(scenario, i), RHS, 3) == 0 || 2384 strncmp(getScenarioEntryCol(scenario, i), rhs, 3) == 0 || 2385 strcmp(getScenarioEntryCol(scenario, i), RIGHT) == 0 ) 2386 { 2387 /* if the constraint is NULL, then it is not possible to make any changes to the scenario */ 2388 if( cons == NULL ) 2389 { 2390 SCIPerrorMessage("There is no constraint <%s> in the current scenario.\n", name); 2391 return SCIP_READERROR; 2392 } 2393 2394 /* if the constraint is an equality constraint, then the LHS must also be changed */ 2395 if( SCIPgetLhsLinear(scenarioscip, cons) >= SCIPgetRhsLinear(scenarioscip, cons) ) 2396 { 2397 SCIP_CALL( SCIPchgLhsLinear(scenarioscip, cons, getScenarioEntryValue(scenario, i)) ); 2398 SCIP_CALL( SCIPchgRhsLinear(scenarioscip, cons, getScenarioEntryValue(scenario, i)) ); 2399 } 2400 else if( SCIPisLT(scenarioscip, SCIPgetRhsLinear(scenarioscip, cons), SCIPinfinity(scenarioscip)) ) 2401 SCIP_CALL( SCIPchgRhsLinear(scenarioscip, cons, getScenarioEntryValue(scenario, i)) ); 2402 else if( SCIPisLT(scenarioscip, SCIPgetLhsLinear(scenarioscip, cons), SCIPinfinity(scenarioscip)) ) 2403 SCIP_CALL( SCIPchgLhsLinear(scenarioscip, cons, getScenarioEntryValue(scenario, i)) ); 2404 } 2405 else if( strstr(getScenarioEntryRow(scenario, i), MINI) != NULL || 2406 strstr(getScenarioEntryRow(scenario, i), obj) != NULL || 2407 strstr(getScenarioEntryRow(scenario, i), OBJ) != NULL ) 2408 { 2409 /* finding the variable associated with the column */ 2410 getScenarioEntityName(name, getScenarioEntryCol(scenario, i), getScenarioStageNum(scenarioscip, scenario), 2411 getScenarioNum(scenarioscip, scenario)); 2412 var = SCIPfindVar(scenarioscip, name); 2413 2414 /* changing the coefficient for the variable */ 2415 if( var == NULL ) 2416 { 2417 SCIPerrorMessage("There is no variable <%s> in the current scenario.\n", name); 2418 return SCIP_READERROR; 2419 } 2420 else 2421 { 2422 SCIP_CALL( SCIPchgVarObj(scenarioscip, var, getScenarioEntryValue(scenario, i)*probability) ); 2423 } 2424 } 2425 else 2426 { 2427 /* if the constraint is NULL, then it is not possible to make any changes to the scenario */ 2428 if( cons == NULL ) 2429 { 2430 SCIPerrorMessage("There is no constraint <%s> in the current scenario.\n", name); 2431 return SCIP_READERROR; 2432 } 2433 2434 /* finding the variable associated with the column */ 2435 getScenarioEntityName(name, getScenarioEntryCol(scenario, i), getScenarioStageNum(scenarioscip, scenario), 2436 getScenarioNum(scenarioscip, scenario)); 2437 var = SCIPfindVar(scenarioscip, name); 2438 2439 if( var == NULL ) 2440 { 2441 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s", getScenarioEntryCol(scenario, i)); 2442 var = SCIPfindVar(scenarioscip, name); 2443 } 2444 2445 /* changing the coefficient for the variable */ 2446 if( var == NULL ) 2447 { 2448 SCIPerrorMessage("There is no variable <%s> in the current scenario.\n", name); 2449 return SCIP_READERROR; 2450 } 2451 else 2452 { 2453 SCIP_CALL( SCIPchgCoefLinear(scenarioscip, cons, var, getScenarioEntryValue(scenario, i)) ); 2454 } 2455 } 2456 } 2457 2458 return SCIP_OKAY; 2459 } 2460 2461 /** removes the core variables and constriants for stage 2 and lower */ 2462 static 2463 SCIP_RETCODE removeCoreVariablesAndConstraints( 2464 SCIP* scip /**< the SCIP data structure */ 2465 ) 2466 { 2467 SCIP_CONS** conss; 2468 SCIP_VAR** vars; 2469 int nconss; 2470 int nvars; 2471 int numstages; 2472 int i; 2473 int j; 2474 SCIP_Bool deleted; 2475 2476 assert(scip != NULL); 2477 2478 numstages = SCIPtimGetNStages(scip); 2479 2480 /* looping through all stages to remove the variables and constraints. The first stage is not removed as these are 2481 * part of the complete problem */ 2482 for( i = 1; i < numstages; i++ ) 2483 { 2484 conss = SCIPtimGetStageConss(scip, i); 2485 vars = SCIPtimGetStageVars(scip, i); 2486 nconss = SCIPtimGetStageNConss(scip, i); 2487 nvars = SCIPtimGetStageNVars(scip, i); 2488 2489 /* removing constriants */ 2490 for( j = 0; j < nconss; j++ ) 2491 { 2492 if( !SCIPconsIsDeleted(conss[j]) ) 2493 SCIP_CALL( SCIPdelCons(scip, conss[j]) ); 2494 } 2495 2496 /* removing variables */ 2497 for( j = 0; j < nvars; j++ ) 2498 { 2499 if( !SCIPvarIsDeleted(vars[j]) ) 2500 { 2501 SCIP_CALL( SCIPdelVar(scip, vars[j], &deleted) ); 2502 assert(deleted); 2503 } 2504 } 2505 } 2506 2507 return SCIP_OKAY; 2508 } 2509 2510 2511 /* build the stochastic program completely as a MIP, i.e. no decomposition */ 2512 static 2513 SCIP_RETCODE buildFullProblem( 2514 SCIP* scip, /**< the SCIP data structure */ 2515 SCIP_READERDATA* readerdata /**< the reader data */ 2516 ) 2517 { 2518 int i; 2519 2520 assert(scip != NULL); 2521 assert(readerdata != NULL); 2522 2523 /* adding all variables and constraints for stages below the first stage. 2524 * The first stage is covered by the original problem. */ 2525 for( i = 0; i < getScenarioNChildren(readerdata->scenariotree); i++ ) 2526 SCIP_CALL( addScenarioVarsAndConsToProb(scip, getScenarioChild(readerdata->scenariotree, i), FALSE) ); 2527 2528 /* removing the variable and constraints that were included as part of the core file */ 2529 SCIP_CALL( removeCoreVariablesAndConstraints(scip) ); 2530 2531 return SCIP_OKAY; 2532 } 2533 2534 2535 /** builds the stochastic program using Benders' decomposition */ 2536 static 2537 SCIP_RETCODE buildDecompProblem( 2538 SCIP* scip, /**< the SCIP data structure */ 2539 SCIP_READERDATA* readerdata /**< the reader data */ 2540 ) 2541 { 2542 SCIP_BENDERS* benders; 2543 int i; 2544 2545 assert(scip != NULL); 2546 assert(readerdata != NULL); 2547 2548 SCIP_CALL( createScenarioSubproblemArray(scip, readerdata->scenariotree) ); 2549 2550 /* activating the Benders' constraint handler. The two-phase method is activated by default. If the user desires not 2551 * to use the two-phase method, then the setting in cons_benderslp must be explicitly changed. 2552 */ 2553 SCIP_CALL( SCIPsetBoolParam(scip, "constraints/benders/active", TRUE) ); 2554 2555 setScenarioScip(readerdata->scenariotree, scip); 2556 2557 /* adding all variables and constraints for stages below the first stage. 2558 * The first stage is covered by the original problem. */ 2559 for( i = 0; i < getScenarioNChildren(readerdata->scenariotree); i++ ) 2560 { 2561 SCIP_CALL( addScenarioVarsAndConsToProb(scip, getScenarioChild(readerdata->scenariotree, i), TRUE) ); 2562 addScenarioSubproblem(readerdata->scenariotree, getScenarioScip(getScenarioChild(readerdata->scenariotree, i))); 2563 } 2564 2565 /* creating the Benders' decomposition */ 2566 SCIP_CALL( SCIPcreateBendersDefault(scip, getScenarioSubproblemArray(readerdata->scenariotree), 2567 getScenarioNChildren(readerdata->scenariotree)) ); 2568 2569 /* getting the default Benders' decomposition */ 2570 benders = SCIPfindBenders(scip, "default"); 2571 2572 /* updating the lower bounds for the subproblems */ 2573 for( i = 0; i < getScenarioNChildren(readerdata->scenariotree); i++ ) 2574 { 2575 SCIPbendersUpdateSubproblemLowerbound(benders, i, 2576 getScenarioLowerbound(scip, getScenarioChild(readerdata->scenariotree, i))); 2577 } 2578 2579 /* removing the variable and constraints that were included as part of the core file */ 2580 SCIP_CALL( removeCoreVariablesAndConstraints(scip) ); 2581 2582 /* changing settings that are required for Benders' decomposition */ 2583 SCIP_CALL( SCIPsetPresolving(scip, SCIP_PARAMSETTING_OFF, TRUE) ); 2584 SCIP_CALL( SCIPsetIntParam(scip, "propagating/maxrounds", 0) ); 2585 SCIP_CALL( SCIPsetIntParam(scip, "propagating/maxroundsroot", 0) ); 2586 SCIP_CALL( SCIPsetIntParam(scip, "heuristics/trysol/freq", 1) ); 2587 2588 /* disabling aggregation since it can affect the mapping between the master and subproblem variables */ 2589 SCIP_CALL( SCIPsetBoolParam(scip, "presolving/donotaggr", TRUE) ); 2590 SCIP_CALL( SCIPsetBoolParam(scip, "presolving/donotmultaggr", TRUE) ); 2591 2592 return SCIP_OKAY; 2593 } 2594 2595 /** Read the stochastic information of an SMPS file instance in "STO File Format". */ 2596 static 2597 SCIP_RETCODE readSto( 2598 SCIP* scip, /**< SCIP data structure */ 2599 const char* filename, /**< name of the input file */ 2600 SCIP_READERDATA* readerdata /**< the reader data */ 2601 ) 2602 { 2603 SCIP_FILE* fp; 2604 STOINPUT* stoi; 2605 SCIP_RETCODE retcode; 2606 SCIP_Bool error = TRUE; 2607 SCIP_Bool unsupported = FALSE; 2608 2609 assert(scip != NULL); 2610 assert(filename != NULL); 2611 2612 fp = SCIPfopen(filename, "r"); 2613 if( fp == NULL ) 2614 { 2615 SCIPerrorMessage("cannot open file <%s> for reading\n", filename); 2616 SCIPprintSysError(filename); 2617 return SCIP_NOFILE; 2618 } 2619 2620 SCIP_CALL_FINALLY( stoinputCreate(scip, &stoi, fp), SCIPfclose(fp) ); 2621 SCIP_CALL_TERMINATE( retcode, createReaderdata(scip, readerdata), TERMINATE ); 2622 2623 SCIP_CALL_TERMINATE( retcode, readStoch(scip, stoi), TERMINATE ); 2624 2625 /* checking for supported stochastic information types */ 2626 if( stoinputStochInfoType(stoi) != STO_STOCHINFO_DISCRETE ) 2627 { 2628 SCIPinfoMessage(scip, NULL, "\nSorry, currently only STO files with the stochastic information as DISCRETE are supported.\n\n"); 2629 SCIPinfoMessage(scip, NULL, "NOTE: The problem provided by the COR file is loaded without stochastic information.\n\n"); 2630 unsupported = TRUE; 2631 } 2632 else 2633 { 2634 if( stoinputSection(stoi) == STO_BLOCKS ) 2635 { 2636 /* coverity[tainted_data] */ 2637 SCIP_CALL_TERMINATE( retcode, readBlocks(stoi, scip, readerdata), TERMINATE ); 2638 } 2639 2640 if( stoinputSection(stoi) == STO_SCENARIOS ) 2641 { 2642 /* if there are more than two stages, then the sto file is not read. */ 2643 if( SCIPtimGetNStages(scip) > 2 ) 2644 { 2645 SCIPinfoMessage(scip, NULL, "\nThe scenarios for the stochastic programs are defined in <%s> as SCENARIOS\n", filename); 2646 SCIPinfoMessage(scip, NULL, "Sorry, currently only two-stage stochastic programs are supported when scenarios are defined as SCENARIOS.\n\n"); 2647 SCIPinfoMessage(scip, NULL, "NOTE: The problem provided by the COR file is loaded without stochastic information.\n\n"); 2648 unsupported = TRUE; 2649 } 2650 else 2651 { 2652 SCIP_CALL_TERMINATE( retcode, readScenarios(stoi, scip, readerdata), TERMINATE ); 2653 } 2654 } 2655 2656 if( stoinputSection(stoi) == STO_INDEP ) 2657 { 2658 SCIP_CALL_TERMINATE( retcode, readIndep(stoi, scip, readerdata), TERMINATE ); 2659 } 2660 } 2661 2662 if( !unsupported && stoinputSection(stoi) != STO_ENDATA ) 2663 stoinputSyntaxerror(stoi); 2664 2665 error = stoinputHasError(stoi); 2666 2667 if( !error && !unsupported ) 2668 { 2669 if( readerdata->usebenders ) 2670 { 2671 SCIP_CALL_TERMINATE( retcode, buildDecompProblem(scip, readerdata), TERMINATE ); 2672 } 2673 else 2674 { 2675 SCIP_CALL_TERMINATE( retcode, buildFullProblem(scip, readerdata), TERMINATE ); 2676 } 2677 } 2678 2679 /* cppcheck-suppress unusedLabel */ 2680 TERMINATE: 2681 stoinputFree(scip, &stoi); 2682 SCIPfclose(fp); 2683 2684 if( error || retcode != SCIP_OKAY ) 2685 return SCIP_READERROR; 2686 else 2687 return SCIP_OKAY; 2688 } 2689 2690 2691 /* 2692 * Callback methods of reader 2693 */ 2694 2695 /** copy method for reader plugins (called when SCIP copies plugins) */ 2696 static 2697 SCIP_DECL_READERCOPY(readerCopySto) 2698 { /*lint --e{715}*/ 2699 assert(scip != NULL); 2700 assert(reader != NULL); 2701 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0); 2702 2703 /* call inclusion method of reader */ 2704 SCIP_CALL( SCIPincludeReaderSto(scip) ); 2705 2706 return SCIP_OKAY; 2707 } 2708 2709 /** destructor of reader to free user data (called when SCIP is exiting) */ 2710 static 2711 SCIP_DECL_READERFREE(readerFreeSto) 2712 { 2713 SCIP_READERDATA* readerdata; 2714 2715 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0); 2716 readerdata = SCIPreaderGetData(reader); 2717 assert(readerdata != NULL); 2718 2719 SCIP_CALL( freeReaderdata(scip, readerdata) ); 2720 2721 return SCIP_OKAY; 2722 } 2723 2724 /** problem reading method of reader */ 2725 static 2726 SCIP_DECL_READERREAD(readerReadSto) 2727 { /*lint --e{715}*/ 2728 SCIP_READER* correader; 2729 SCIP_READER* timreader; 2730 2731 assert(reader != NULL); 2732 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0); 2733 2734 correader = SCIPfindReader(scip, "correader"); 2735 timreader = SCIPfindReader(scip, "timreader"); 2736 2737 if( correader == NULL ) 2738 { 2739 SCIPwarningMessage(scip, "It is necessary to include the \"cor\" reader\n"); 2740 (*result) = SCIP_DIDNOTRUN; 2741 return SCIP_OKAY; 2742 } 2743 2744 if( timreader == NULL ) 2745 { 2746 SCIPwarningMessage(scip, "It is necessary to include the \"tim\" reader\n"); 2747 (*result) = SCIP_DIDNOTRUN; 2748 return SCIP_OKAY; 2749 } 2750 2751 /* checking whether the cor file has been read */ 2752 if( !SCIPcorHasRead(correader) ) 2753 { 2754 SCIPwarningMessage(scip, "The core file must be read before the time and stochastic files.\n"); 2755 (*result) = SCIP_DIDNOTRUN; 2756 return SCIP_OKAY; 2757 } 2758 2759 /* checking whether the tim file has been read */ 2760 if( !SCIPtimHasRead(timreader) ) 2761 { 2762 SCIPwarningMessage(scip, "The time file must be read before the stochastic files.\n"); 2763 (*result) = SCIP_DIDNOTRUN; 2764 return SCIP_OKAY; 2765 } 2766 2767 SCIP_CALL( SCIPreadSto(scip, filename, result) ); 2768 2769 return SCIP_OKAY; 2770 } 2771 2772 /* 2773 * sto file reader specific interface methods 2774 */ 2775 2776 /** includes the sto file reader in SCIP */ 2777 SCIP_RETCODE SCIPincludeReaderSto( 2778 SCIP* scip /**< SCIP data structure */ 2779 ) 2780 { 2781 SCIP_READERDATA* readerdata; 2782 SCIP_READER* reader; 2783 2784 /* create reader data */ 2785 SCIP_CALL( SCIPallocBlockMemory(scip, &readerdata) ); 2786 readerdata->scenariotree = NULL; 2787 readerdata->numscenarios = 0; 2788 2789 /* include reader */ 2790 SCIP_CALL( SCIPincludeReaderBasic(scip, &reader, READER_NAME, READER_DESC, READER_EXTENSION, readerdata) ); 2791 2792 /* set non fundamental callbacks via setter functions */ 2793 SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopySto) ); 2794 SCIP_CALL( SCIPsetReaderFree(scip, reader, readerFreeSto) ); 2795 SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadSto) ); 2796 2797 /* add decomposition parameters */ 2798 SCIP_CALL( SCIPaddBoolParam(scip, 2799 "reading/" READER_NAME "/usebenders", 2800 "should Benders' decomposition be used?", 2801 &readerdata->usebenders, FALSE, DEFAULT_USEBENDERS, NULL, NULL) ); 2802 2803 return SCIP_OKAY; 2804 } 2805 2806 2807 /** reads the stochastic information for a stochastic program that is in SMPS format */ 2808 SCIP_RETCODE SCIPreadSto( 2809 SCIP* scip, /**< SCIP data structure */ 2810 const char* filename, /**< full path and name of file to read, or NULL if stdin should be used */ 2811 SCIP_RESULT* result /**< pointer to store the result of the file reading call */ 2812 ) 2813 { 2814 SCIP_READER* reader; 2815 SCIP_READERDATA* readerdata; 2816 SCIP_RETCODE retcode; 2817 2818 assert(scip != NULL); 2819 assert(result != NULL); 2820 2821 reader = SCIPfindReader(scip, READER_NAME); 2822 assert(reader != NULL); 2823 readerdata = SCIPreaderGetData(reader); 2824 2825 retcode = readSto(scip, filename, readerdata); 2826 2827 if( retcode == SCIP_PLUGINNOTFOUND ) 2828 retcode = SCIP_READERROR; 2829 2830 if( retcode == SCIP_NOFILE || retcode == SCIP_READERROR ) 2831 return retcode; 2832 2833 SCIP_CALL( retcode ); 2834 2835 *result = SCIP_SUCCESS; 2836 2837 return SCIP_OKAY; 2838 } 2839 2840 /** returns the total number of scenarios added to the problem */ 2841 int SCIPstoGetNScenarios( 2842 SCIP* scip /**< SCIP data structure */ 2843 ) 2844 { 2845 SCIP_READER* reader; 2846 SCIP_READERDATA* readerdata; 2847 2848 reader = SCIPfindReader(scip, READER_NAME); 2849 2850 assert(reader != NULL); 2851 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0); 2852 2853 readerdata = SCIPreaderGetData(reader); 2854 assert(readerdata != NULL); 2855 2856 return readerdata->numscenarios; 2857 } 2858