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_tim.c 26 * @ingroup DEFPLUGINS_READER 27 * @brief TIM file reader - the stage information for a stochastic programming instance in SMPS format 28 * @author Stephen J. Maher 29 */ 30 31 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/ 32 33 #include "scip/pub_cons.h" 34 #include "scip/pub_fileio.h" 35 #include "scip/pub_message.h" 36 #include "scip/pub_misc.h" 37 #include "scip/pub_reader.h" 38 #include "scip/reader_cor.h" 39 #include "scip/reader_tim.h" 40 #include "scip/scip_mem.h" 41 #include "scip/scip_message.h" 42 #include "scip/scip_numerics.h" 43 #include "scip/scip_prob.h" 44 #include "scip/scip_reader.h" 45 #include <string.h> 46 47 #define READER_NAME "timreader" 48 #define READER_DESC "file reader for the TIME file of a stochastic program in SMPS format" 49 #define READER_EXTENSION "tim" 50 51 /* 52 * tim reader internal methods 53 */ 54 55 #define TIM_MAX_LINELEN 1025 56 #define TIM_MAX_NAMELEN 256 57 #define TIM_DEFAULT_STAGESIZE 10 58 #define TIM_DEFAULT_ARRAYSIZE 100 59 60 #define BLANK ' ' 61 62 struct TimStage 63 { 64 SCIP_VAR** vars; 65 SCIP_CONS** conss; 66 SCIP_HASHMAP* varnametovar; 67 SCIP_HASHMAP* consnametocons; 68 int nvars; 69 int nconss; 70 int varssize; 71 int conssize; 72 }; 73 typedef struct TimStage TIMSTAGE; 74 75 /** TIM reading data */ 76 struct SCIP_ReaderData 77 { 78 SCIP_Bool read; /**< flag to indicate whether the time file has been read */ 79 int nstages; /**< the number of stages in the stochastic program */ 80 const char** stagestartvars; /**< the variables that start each stage */ 81 const char** stagestartcons; /**< the constraints that start each stage */ 82 const char** stagenames; /**< the name of the stage */ 83 TIMSTAGE** stages; /**< the stages for the stochastic program */ 84 }; 85 86 /** enum containing all tim sections */ 87 enum TimSection 88 { 89 TIM_TIME, 90 TIM_PERIODS, 91 TIM_ENDATA 92 }; 93 typedef enum TimSection TIMSECTION; 94 95 /** tim input structure */ 96 struct TimInput 97 { 98 TIMSECTION section; 99 SCIP_FILE* fp; 100 int lineno; 101 SCIP_Bool haserror; 102 char buf[TIM_MAX_LINELEN]; 103 const char* f0; 104 const char* f1; 105 const char* f2; 106 const char* f3; 107 char probname[TIM_MAX_NAMELEN]; 108 const char** stagestartvars; 109 const char** stagestartcons; 110 const char** stagenames; 111 int nstages; 112 int stagesize; 113 }; 114 typedef struct TimInput TIMINPUT; 115 116 /** adds the variable to the given stage */ 117 static 118 SCIP_RETCODE addVariableToStage( 119 SCIP* scip, /**< SCIP data structure */ 120 TIMSTAGE* stage, /**< the stage structure */ 121 const char* varname /**< the name of the variable to add to the stage */ 122 ) 123 { 124 SCIP_VAR* var; 125 126 assert(scip != NULL); 127 assert(stage != NULL); 128 129 var = SCIPfindVar(scip, varname); 130 131 if( var == NULL ) 132 { 133 SCIPwarningMessage(scip, "This is an error. All variables should in the problem.\n"); 134 return SCIP_OKAY; 135 } 136 137 /* adding the variable to the hashmap */ 138 SCIP_CALL( SCIPhashmapInsert(stage->varnametovar, (void*) varname, var) ); 139 140 /* adding the variable to the variable storage */ 141 SCIP_CALL( SCIPensureBlockMemoryArray(scip, &stage->vars, &stage->varssize, stage->nvars + 1) ); 142 stage->vars[stage->nvars] = var; 143 stage->nvars++; 144 145 return SCIP_OKAY; 146 } 147 148 /** adds the constraint to the given stage */ 149 static 150 SCIP_RETCODE addConstraintToStage( 151 SCIP* scip, /**< SCIP data structure */ 152 TIMSTAGE* stage, /**< the stage structure */ 153 const char* consname /**< the name of the constraint to add to the stage */ 154 ) 155 { 156 SCIP_CONS* cons; 157 158 assert(scip != NULL); 159 assert(stage != NULL); 160 161 cons = SCIPfindCons(scip, consname); 162 163 if( cons == NULL ) 164 { 165 SCIPwarningMessage(scip, "This is an error. All constraints should in the problem.\n"); 166 return SCIP_OKAY; 167 } 168 169 /* adding the constraint to the hashmap */ 170 SCIP_CALL( SCIPhashmapInsert(stage->consnametocons, (void*) consname, cons) ); 171 172 /* adding the constraint to the constraint storage */ 173 SCIP_CALL( SCIPensureBlockMemoryArray(scip, &stage->conss, &stage->conssize, stage->nconss + 1) ); 174 stage->conss[stage->nconss] = cons; 175 stage->nconss++; 176 177 return SCIP_OKAY; 178 } 179 180 /** creates the stage data */ 181 static 182 SCIP_RETCODE createStages( 183 SCIP* scip, /**< SCIP data structure */ 184 SCIP_READER* reader, /**< the reader structure */ 185 SCIP_READER* correader /**< the reader structure for the core file */ 186 ) 187 { 188 SCIP_READERDATA* readerdata; 189 int stage; 190 int i; 191 192 assert(scip != NULL); 193 assert(reader != NULL); 194 assert(correader != NULL); 195 196 readerdata = SCIPreaderGetData(reader); 197 assert(readerdata != NULL); 198 199 stage = 0; 200 201 /* assigning the variables to the stages */ 202 for( i = 0; i < SCIPcorGetNVarNames(correader); i++ ) 203 { 204 /* the first variable in the var names list should be the start of the first stage */ 205 assert((stage == 0 && i == 0 && strcmp(SCIPcorGetVarName(correader, i), readerdata->stagestartvars[stage]) == 0) 206 || i > 0); 207 /* checking whether the next stage has been found */ 208 if( i > 0 && stage < readerdata->nstages - 1 209 && strcmp(SCIPcorGetVarName(correader, i), readerdata->stagestartvars[stage + 1]) == 0 ) 210 stage++; 211 212 /* adding the variable to the stage */ 213 SCIP_CALL( addVariableToStage(scip, readerdata->stages[stage], SCIPcorGetVarName(correader, i)) ); 214 } 215 216 stage = 0; 217 218 /* assigning the constraint to the stages */ 219 for( i = 0; i < SCIPcorGetNConsNames(correader); i++ ) 220 { 221 /* checking whether the next stage has been found */ 222 if( i > 0 && stage < readerdata->nstages - 1 223 && strcmp(SCIPcorGetConsName(correader, i), readerdata->stagestartcons[stage + 1]) == 0 ) 224 stage++; 225 226 /* adding the consiable to the stage */ 227 SCIP_CALL( addConstraintToStage(scip, readerdata->stages[stage], SCIPcorGetConsName(correader, i)) ); 228 } 229 230 return SCIP_OKAY; 231 } 232 233 /** creates the reader data for the time input data */ 234 static 235 SCIP_RETCODE createReaderdata( 236 SCIP* scip, /**< SCIP data structure */ 237 SCIP_READER* reader, /**< the reader structure */ 238 TIMINPUT* timi /**< tim input structure */ 239 ) 240 { 241 SCIP_READERDATA* readerdata; 242 int hashmapsize; 243 int nvars; 244 int i; 245 246 assert(scip != NULL); 247 assert(reader != NULL); 248 assert(timi != NULL); 249 250 readerdata = SCIPreaderGetData(reader); 251 252 assert(readerdata != NULL); 253 254 /* getting the total number of variables in the problem. The hash maps will be of size nvars/nstages. */ 255 nvars = SCIPgetNVars(scip); 256 257 readerdata->read = TRUE; 258 readerdata->nstages = timi->nstages; 259 260 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &readerdata->stagestartvars, readerdata->nstages) ); 261 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &readerdata->stagestartcons, readerdata->nstages) ); 262 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &readerdata->stagenames, readerdata->nstages) ); 263 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &readerdata->stages, readerdata->nstages) ); 264 265 for( i = 0; i < readerdata->nstages; i++ ) 266 { 267 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &readerdata->stagestartvars[i], 268 timi->stagestartvars[i], strlen(timi->stagestartvars[i]) + 1) ); /*lint !e866*/ 269 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &readerdata->stagestartcons[i], 270 timi->stagestartcons[i], strlen(timi->stagestartcons[i]) + 1) ); /*lint !e866*/ 271 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &readerdata->stagenames[i], 272 timi->stagenames[i], strlen(timi->stagenames[i]) + 1) ); /*lint !e866*/ 273 274 /* creating the data for the stages */ 275 SCIP_CALL( SCIPallocBlockMemory(scip, &readerdata->stages[i]) ); /*lint !e866*/ 276 readerdata->stages[i]->nvars = 0; 277 readerdata->stages[i]->nconss = 0; 278 readerdata->stages[i]->varssize = TIM_DEFAULT_ARRAYSIZE; 279 readerdata->stages[i]->conssize = TIM_DEFAULT_ARRAYSIZE; 280 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &readerdata->stages[i]->vars, readerdata->stages[i]->varssize) ); /*lint !e866*/ 281 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &readerdata->stages[i]->conss, readerdata->stages[i]->conssize) ); /*lint !e866*/ 282 283 /* creating the hashmaps */ 284 hashmapsize = (int) SCIPceil(scip, (SCIP_Real) nvars/(SCIP_Real) readerdata->nstages); 285 SCIP_CALL( SCIPhashmapCreate(&readerdata->stages[i]->varnametovar, SCIPblkmem(scip), hashmapsize) ); 286 SCIP_CALL( SCIPhashmapCreate(&readerdata->stages[i]->consnametocons, SCIPblkmem(scip), hashmapsize) ); 287 } 288 289 return SCIP_OKAY; 290 } 291 292 /** free the reader data */ 293 static 294 void freeReaderdata( 295 SCIP* scip, /**< SCIP data structure */ 296 SCIP_READER* reader /**< the reader structure */ 297 ) 298 { 299 SCIP_READERDATA* readerdata; 300 int i; 301 302 assert(scip != NULL); 303 assert(reader != NULL); 304 305 readerdata = SCIPreaderGetData(reader); 306 307 assert(readerdata != NULL); 308 309 /* only free the reader data is a file has been read */ 310 if( readerdata->read ) 311 { 312 for( i = 0; i < readerdata->nstages; i++ ) 313 { 314 /* freeing the hashmaps */ 315 SCIPhashmapFree(&readerdata->stages[i]->consnametocons); 316 SCIPhashmapFree(&readerdata->stages[i]->varnametovar); 317 318 SCIPfreeBlockMemoryArray(scip, &readerdata->stagestartvars[i], strlen(readerdata->stagestartvars[i]) + 1); 319 SCIPfreeBlockMemoryArray(scip, &readerdata->stagestartcons[i], strlen(readerdata->stagestartcons[i]) + 1); 320 SCIPfreeBlockMemoryArray(scip, &readerdata->stagenames[i], strlen(readerdata->stagenames[i]) + 1); 321 322 /* freeing the memory for the stage data */ 323 SCIPfreeBlockMemoryArray(scip, &readerdata->stages[i]->vars, readerdata->stages[i]->varssize); 324 SCIPfreeBlockMemoryArray(scip, &readerdata->stages[i]->conss, readerdata->stages[i]->conssize); 325 SCIPfreeBlockMemory(scip, &readerdata->stages[i]); /*lint !e866*/ 326 } 327 328 SCIPfreeBlockMemoryArray(scip, &readerdata->stages, readerdata->nstages); 329 SCIPfreeBlockMemoryArray(scip, &readerdata->stagenames, readerdata->nstages); 330 SCIPfreeBlockMemoryArray(scip, &readerdata->stagestartcons, readerdata->nstages); 331 SCIPfreeBlockMemoryArray(scip, &readerdata->stagestartvars, readerdata->nstages); 332 } 333 334 SCIPfreeBlockMemory(scip, &readerdata); 335 } 336 337 338 /** creates the tim input structure */ 339 static 340 SCIP_RETCODE timinputCreate( 341 SCIP* scip, /**< SCIP data structure */ 342 TIMINPUT** timi, /**< tim input structure */ 343 SCIP_FILE* fp /**< file object for the input file */ 344 ) 345 { 346 assert(timi != NULL); 347 assert(fp != NULL); 348 349 SCIP_CALL( SCIPallocBlockMemory(scip, timi) ); 350 351 (*timi)->section = TIM_TIME; 352 (*timi)->fp = fp; 353 (*timi)->lineno = 0; 354 (*timi)->haserror = FALSE; 355 (*timi)->buf [0] = '\0'; 356 (*timi)->probname[0] = '\0'; 357 (*timi)->f0 = NULL; 358 (*timi)->f1 = NULL; 359 (*timi)->f2 = NULL; 360 (*timi)->f3 = NULL; 361 (*timi)->nstages = 0; 362 (*timi)->stagesize = TIM_DEFAULT_STAGESIZE; 363 364 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*timi)->stagestartvars, (*timi)->stagesize) ); 365 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*timi)->stagestartcons, (*timi)->stagesize) ); 366 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*timi)->stagenames, (*timi)->stagesize) ); 367 368 return SCIP_OKAY; 369 } 370 371 /** free the tim input structure */ 372 static 373 void timinputFree( 374 SCIP* scip, /**< SCIP data structure */ 375 TIMINPUT** timi /**< tim input structure */ 376 ) 377 { 378 int i; 379 380 for( i = 0; i < (*timi)->nstages; i++ ) 381 { 382 SCIPfreeBlockMemoryArray(scip, &(*timi)->stagestartvars[i], strlen((*timi)->stagestartvars[i]) + 1); 383 SCIPfreeBlockMemoryArray(scip, &(*timi)->stagestartcons[i], strlen((*timi)->stagestartcons[i]) + 1); 384 SCIPfreeBlockMemoryArray(scip, &(*timi)->stagenames[i], strlen((*timi)->stagenames[i]) + 1); 385 } 386 387 SCIPfreeBlockMemoryArray(scip, &(*timi)->stagestartvars, (*timi)->stagesize); 388 SCIPfreeBlockMemoryArray(scip, &(*timi)->stagestartcons, (*timi)->stagesize); 389 SCIPfreeBlockMemoryArray(scip, &(*timi)->stagenames, (*timi)->stagesize); 390 391 SCIPfreeBlockMemory(scip, timi); 392 } 393 394 /** returns the current section */ 395 static 396 TIMSECTION timinputSection( 397 const TIMINPUT* timi /**< tim input structure */ 398 ) 399 { 400 assert(timi != NULL); 401 402 return timi->section; 403 } 404 405 /** return the current value of field 0 */ 406 static 407 const char* timinputField0( 408 const TIMINPUT* timi /**< tim input structure */ 409 ) 410 { 411 assert(timi != NULL); 412 413 return timi->f0; 414 } 415 416 /** return the current value of field 1 */ 417 static 418 const char* timinputField1( 419 const TIMINPUT* timi /**< tim input structure */ 420 ) 421 { 422 assert(timi != NULL); 423 424 return timi->f1; 425 } 426 427 /** return the current value of field 2 */ 428 static 429 const char* timinputField2( 430 const TIMINPUT* timi /**< tim input structure */ 431 ) 432 { 433 assert(timi != NULL); 434 435 return timi->f2; 436 } 437 438 /** return the current value of field 3 */ 439 static 440 const char* timinputField3( 441 const TIMINPUT* timi /**< tim input structure */ 442 ) 443 { 444 assert(timi != NULL); 445 446 return timi->f3; 447 } 448 449 /** returns if an error was detected */ 450 static 451 SCIP_Bool timinputHasError( 452 const TIMINPUT* timi /**< tim input structure */ 453 ) 454 { 455 assert(timi != NULL); 456 457 return timi->haserror; 458 } 459 460 /** set the section in the tim input structure to given section */ 461 static 462 void timinputSetSection( 463 TIMINPUT* timi, /**< tim input structure */ 464 TIMSECTION section /**< section that is set */ 465 ) 466 { 467 assert(timi != NULL); 468 469 timi->section = section; 470 } 471 472 /** set the problem name in the tim input structure to given problem name */ 473 static 474 void timinputSetProbname( 475 TIMINPUT* timi, /**< tim input structure */ 476 const char* probname /**< name of the problem to set */ 477 ) 478 { 479 assert(timi != NULL); 480 assert(probname != NULL); 481 assert(strlen(probname) < sizeof(timi->probname)); 482 483 (void)SCIPmemccpy(timi->probname, probname, '\0', TIM_MAX_NAMELEN - 1); 484 } 485 486 /** set the problem var name that starts a stage in the tim input structure to given objective name */ 487 static 488 SCIP_RETCODE timinputSetStageStartVar( 489 TIMINPUT* timi, /**< tim input structure */ 490 SCIP* scip, /**< SCIP data structure */ 491 const char* varname, /**< name of the variable that starts the stage */ 492 int stagenum /**< the stage number the variable starts */ 493 ) 494 { 495 assert(timi != NULL); 496 assert(varname != NULL); 497 498 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &timi->stagestartvars[stagenum], varname, strlen(varname) + 1) ); /*lint !e866*/ 499 500 return SCIP_OKAY; 501 } 502 503 /** set the problem constraint name that starts a stage in the tim input structure to given objective name */ 504 static 505 SCIP_RETCODE timinputSetStageStartCons( 506 TIMINPUT* timi, /**< tim input structure */ 507 SCIP* scip, /**< SCIP data structure */ 508 const char* consname, /**< name of the constraint that starts the stage */ 509 int stagenum /**< the stage number the constraint starts */ 510 ) 511 { 512 assert(timi != NULL); 513 assert(consname != NULL); 514 515 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &timi->stagestartcons[stagenum], consname, strlen(consname) + 1) ); /*lint !e866*/ 516 517 return SCIP_OKAY; 518 } 519 520 /** set the stage name in the tim input structure to given objective name */ 521 static 522 SCIP_RETCODE timinputSetStageName( 523 TIMINPUT* timi, /**< tim input structure */ 524 SCIP* scip, /**< SCIP data structure */ 525 const char* stagename, /**< name of the stage */ 526 int stagenum /**< the stage number the constraint starts */ 527 ) 528 { 529 assert(timi != NULL); 530 assert(stagename != NULL); 531 532 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &timi->stagenames[stagenum], stagename, strlen(stagename) + 1) ); /*lint !e866*/ 533 534 return SCIP_OKAY; 535 } 536 537 static 538 void timinputSyntaxerror( 539 TIMINPUT* timi /**< tim input structure */ 540 ) 541 { 542 assert(timi != NULL); 543 544 SCIPerrorMessage("Syntax error in line %d\n", timi->lineno); 545 timi->section = TIM_ENDATA; 546 timi->haserror = TRUE; 547 } 548 549 /** fill the line from \p pos up to column 80 with blanks. */ 550 static 551 void clearFrom( 552 char* buf, /**< buffer to clear */ 553 unsigned int pos /**< position to start the clearing process */ 554 ) 555 { 556 unsigned int i; 557 558 for(i = pos; i < 80; i++) 559 buf[i] = BLANK; 560 buf[80] = '\0'; 561 } 562 563 /** read a tim format data line and parse the fields. */ 564 static 565 SCIP_Bool timinputReadLine( 566 TIMINPUT* timi /**< tim input structure */ 567 ) 568 { 569 unsigned int len; 570 unsigned int i; 571 char* s; 572 SCIP_Bool is_empty; 573 char* nexttok; 574 575 do 576 { 577 timi->f0 = timi->f1 = timi->f2 = timi->f3 = 0; 578 579 /* Read until we have not a comment line. */ 580 do 581 { 582 timi->buf[TIM_MAX_LINELEN-1] = '\0'; 583 if( NULL == SCIPfgets(timi->buf, (int) sizeof(timi->buf), timi->fp) ) 584 return FALSE; 585 timi->lineno++; 586 } 587 while( *timi->buf == '*' ); /* coverity[a_loop_bound] */ 588 589 /* Normalize line */ 590 len = (unsigned int) strlen(timi->buf); 591 592 for( i = 0; i < len; i++ ) 593 if( (timi->buf[i] == '\t') || (timi->buf[i] == '\n') || (timi->buf[i] == '\r') ) 594 timi->buf[i] = BLANK; 595 596 if( len < 80 ) 597 clearFrom(timi->buf, len); 598 599 SCIPdebugMessage("line %d: <%s>\n", timi->lineno, timi->buf); 600 601 assert(strlen(timi->buf) >= 80); 602 603 /* Look for new section */ 604 if( *timi->buf != BLANK ) 605 { 606 timi->f0 = SCIPstrtok(&timi->buf[0], " ", &nexttok); 607 608 assert(timi->f0 != 0); 609 610 timi->f1 = SCIPstrtok(NULL, " ", &nexttok); 611 612 return TRUE; 613 } 614 615 s = &timi->buf[1]; 616 617 /* At this point it is not clear if we have a indicator field. 618 * If there is none (e.g. empty) f1 will be the first name field. 619 * If there is one, f2 will be the first name field. 620 * 621 * Initially comment marks '$' are only allowed in the beginning 622 * of the 2nd and 3rd name field. We test all fields but the first. 623 * This makes no difference, since if the $ is at the start of a value 624 * field, the line will be erroneous anyway. 625 */ 626 do 627 { 628 if( NULL == (timi->f1 = SCIPstrtok(s, " ", &nexttok)) ) 629 break; 630 631 if( (NULL == (timi->f2 = SCIPstrtok(NULL, " ", &nexttok))) || (*timi->f2 == '$') ) 632 { 633 timi->f2 = 0; 634 break; 635 } 636 637 if( (NULL == (timi->f3 = SCIPstrtok(NULL, " ", &nexttok))) || (*timi->f3 == '$') ) 638 { 639 timi->f3 = 0; 640 break; 641 } 642 } 643 while( FALSE ); 644 645 /* check for empty lines */ 646 is_empty = (timi->f0 == NULL && timi->f1 == NULL); 647 } 648 while( is_empty ); 649 650 return TRUE; 651 } 652 653 /** Process TIME section. */ 654 static 655 SCIP_RETCODE readTime( 656 SCIP* scip, /**< SCIP data structure */ 657 TIMINPUT* timi /**< tim input structure */ 658 ) 659 { 660 SCIPdebugMsg(scip, "read problem name from TIME section\n"); 661 662 /* This has to be the Line with the TIME section. */ 663 if( !timinputReadLine(timi) || timinputField0(timi) == NULL || strcmp(timinputField0(timi), "TIME") ) 664 { 665 timinputSyntaxerror(timi); 666 return SCIP_OKAY; 667 } 668 669 /* Sometimes the name is omitted. */ 670 timinputSetProbname(timi, (timinputField1(timi) == 0) ? "_TIM_" : timinputField1(timi)); 671 672 /* This has to be a new section */ 673 /* coverity[tainted_data] */ 674 if( !timinputReadLine(timi) || (timinputField0(timi) == NULL) ) 675 { 676 timinputSyntaxerror(timi); 677 return SCIP_OKAY; 678 } 679 680 if( strncmp(timinputField0(timi), "PERIODS", 7) == 0 ) 681 timinputSetSection(timi, TIM_PERIODS); 682 else 683 { 684 timinputSyntaxerror(timi); 685 return SCIP_OKAY; 686 } 687 688 return SCIP_OKAY; 689 } 690 691 /** Process PERIODS section. */ 692 static 693 SCIP_RETCODE readPeriods( 694 TIMINPUT* timi, /**< tim input structure */ 695 SCIP* scip /**< SCIP data structure */ 696 ) 697 { 698 SCIPdebugMsg(scip, "read Periods\n"); 699 700 /* coverity[tainted_data_sink_lv_call] */ 701 /* coverity[tainted_data] */ 702 while( timinputReadLine(timi) ) 703 { 704 if( timinputField0(timi) != NULL ) 705 { 706 if( strcmp(timinputField0(timi), "PERIODS") == 0 ) 707 timinputSetSection(timi, TIM_PERIODS); 708 else if( strcmp(timinputField0(timi), "ENDATA") == 0 ) 709 timinputSetSection(timi, TIM_ENDATA); 710 else 711 timinputSyntaxerror(timi); 712 713 return SCIP_OKAY; 714 } 715 716 if( timi->nstages + 1 >= timi->stagesize ) 717 { 718 SCIP_CALL( SCIPensureBlockMemoryArray(scip, &timi->stagestartvars, &timi->stagesize, timi->nstages + 1) ); 719 SCIP_CALL( SCIPensureBlockMemoryArray(scip, &timi->stagestartcons, &timi->stagesize, timi->nstages + 1) ); 720 SCIP_CALL( SCIPensureBlockMemoryArray(scip, &timi->stagenames, &timi->stagesize, timi->nstages + 1) ); 721 } 722 723 SCIP_CALL( timinputSetStageStartVar(timi, scip, timinputField1(timi), timi->nstages) ); 724 SCIP_CALL( timinputSetStageStartCons(timi, scip, timinputField2(timi), timi->nstages) ); 725 SCIP_CALL( timinputSetStageName(timi, scip, timinputField3(timi), timi->nstages) ); 726 727 timi->nstages++; 728 } 729 timinputSyntaxerror(timi); 730 731 return SCIP_OKAY; 732 } 733 734 735 /** Read time data for the SMPS file format. */ 736 static 737 SCIP_RETCODE readTim( 738 SCIP* scip, /**< SCIP data structure */ 739 SCIP_READER* reader, /**< the file reader itself */ 740 const char* filename /**< name of the input file */ 741 ) 742 { 743 SCIP_FILE* fp; 744 TIMINPUT* timi; 745 SCIP_RETCODE retcode; 746 SCIP_Bool error = TRUE; 747 748 assert(scip != NULL); 749 assert(filename != NULL); 750 751 fp = SCIPfopen(filename, "r"); 752 if( fp == NULL ) 753 { 754 SCIPerrorMessage("cannot open file <%s> for reading\n", filename); 755 SCIPprintSysError(filename); 756 757 return SCIP_NOFILE; 758 } 759 760 SCIP_CALL_FINALLY( timinputCreate(scip, &timi, fp), SCIPfclose(fp) ); 761 762 SCIP_CALL_TERMINATE( retcode, readTime(scip, timi), TERMINATE ); 763 764 while( timinputSection(timi) == TIM_PERIODS ) 765 { 766 /* coverity[tainted_data] */ 767 SCIP_CALL_TERMINATE( retcode, readPeriods(timi, scip), TERMINATE ); 768 } 769 if( timinputSection(timi) != TIM_ENDATA ) 770 timinputSyntaxerror(timi); 771 772 error = timinputHasError(timi); 773 774 if( !error ) 775 { 776 SCIP_CALL_TERMINATE( retcode, createReaderdata(scip, reader, timi), TERMINATE ); 777 } 778 779 /* cppcheck-suppress unusedLabel */ 780 TERMINATE: 781 timinputFree(scip, &timi); 782 SCIPfclose(fp); 783 784 if( error ) 785 return SCIP_READERROR; 786 else 787 return SCIP_OKAY; 788 } 789 790 /* 791 * Callback methods of reader 792 */ 793 794 /** copy method for reader plugins (called when SCIP copies plugins) */ 795 static 796 SCIP_DECL_READERCOPY(readerCopyTim) 797 { /*lint --e{715}*/ 798 assert(scip != NULL); 799 assert(reader != NULL); 800 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0); 801 802 /* call inclusion method of reader */ 803 SCIP_CALL( SCIPincludeReaderTim(scip) ); 804 805 return SCIP_OKAY; 806 } 807 808 /** destructor of reader to free user data (called when SCIP is exiting) */ 809 static 810 SCIP_DECL_READERFREE(readerFreeTim) 811 { 812 freeReaderdata(scip, reader); 813 814 return SCIP_OKAY; 815 } 816 817 /** reads the stage information for a stochastic programming instance in SMPS format */ 818 static 819 SCIP_DECL_READERREAD(readerReadTim) 820 { /*lint --e{715}*/ 821 SCIP_READER* correader; 822 823 assert(reader != NULL); 824 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0); 825 826 correader = SCIPfindReader(scip, "correader"); 827 828 if( correader == NULL ) 829 { 830 SCIPwarningMessage(scip, "It is necessary to include the \"cor\" reader\n"); 831 (*result) = SCIP_DIDNOTRUN; 832 return SCIP_OKAY; 833 } 834 835 /* checking whether the cor file has been read */ 836 if( !SCIPcorHasRead(correader) ) 837 { 838 SCIPwarningMessage(scip, "The core file must be read before the time and stochastic files.\n"); 839 (*result) = SCIP_DIDNOTRUN; 840 return SCIP_OKAY; 841 } 842 843 SCIP_CALL( SCIPreadTim(scip, filename, result) ); 844 845 return SCIP_OKAY; 846 } 847 848 849 /* 850 * tim file reader specific interface methods 851 */ 852 853 /** includes the tim file reader in SCIP */ 854 SCIP_RETCODE SCIPincludeReaderTim( 855 SCIP* scip /**< SCIP data structure */ 856 ) 857 { 858 SCIP_READERDATA* readerdata; 859 SCIP_READER* reader; 860 861 /* create reader data */ 862 SCIP_CALL( SCIPallocBlockMemory(scip, &readerdata) ); 863 readerdata->read = FALSE; 864 865 /* include reader */ 866 SCIP_CALL( SCIPincludeReaderBasic(scip, &reader, READER_NAME, READER_DESC, READER_EXTENSION, readerdata) ); 867 868 /* set non fundamental callbacks via setter functions */ 869 SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyTim) ); 870 SCIP_CALL( SCIPsetReaderFree(scip, reader, readerFreeTim) ); 871 SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadTim) ); 872 873 return SCIP_OKAY; 874 } 875 876 877 /** reads problem from file */ 878 SCIP_RETCODE SCIPreadTim( 879 SCIP* scip, /**< SCIP data structure */ 880 const char* filename, /**< full path and name of file to read, or NULL if stdin should be used */ 881 SCIP_RESULT* result /**< pointer to store the result of the file reading call */ 882 ) 883 { 884 SCIP_READER* reader; 885 SCIP_RETCODE retcode; 886 SCIP_READERDATA* readerdata; 887 888 assert(scip != NULL); 889 assert(result != NULL); 890 891 reader = SCIPfindReader(scip, READER_NAME); 892 assert(reader != NULL); 893 894 retcode = readTim(scip, reader, filename); 895 896 if( retcode == SCIP_PLUGINNOTFOUND ) 897 retcode = SCIP_READERROR; 898 899 if( retcode == SCIP_NOFILE || retcode == SCIP_READERROR ) 900 return retcode; 901 902 SCIP_CALL( retcode ); 903 904 /* creating the stages */ 905 SCIP_CALL( createStages(scip, reader, SCIPfindReader(scip, "correader")) ); 906 907 /* setting the read flag to TRUE */ 908 readerdata = SCIPreaderGetData(reader); 909 readerdata->read = TRUE; 910 911 *result = SCIP_SUCCESS; 912 913 return SCIP_OKAY; 914 } 915 916 /* 917 * Interface methods for the cor and sto files 918 */ 919 920 /* return whether the tim file has been read */ 921 SCIP_Bool SCIPtimHasRead( 922 SCIP_READER* reader /**< the file reader itself */ 923 ) 924 { 925 SCIP_READERDATA* readerdata; 926 927 assert(reader != NULL); 928 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0); 929 930 readerdata = SCIPreaderGetData(reader); 931 assert(readerdata != NULL); 932 933 return readerdata->read; 934 } 935 936 937 /* returns the number of stages */ 938 int SCIPtimGetNStages( 939 SCIP* scip /**< SCIP data structure */ 940 ) 941 { 942 SCIP_READER* reader; 943 SCIP_READERDATA* readerdata; 944 945 reader = SCIPfindReader(scip, READER_NAME); 946 947 assert(reader != NULL); 948 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0); 949 950 readerdata = SCIPreaderGetData(reader); 951 assert(readerdata != NULL); 952 953 return readerdata->nstages; 954 } 955 956 /* returns the name for a given stage */ 957 const char* SCIPtimGetStageName( 958 SCIP* scip, /**< SCIP data structure */ 959 int stagenum /**< the number of the requested stage */ 960 ) 961 { 962 SCIP_READER* reader; 963 SCIP_READERDATA* readerdata; 964 965 reader = SCIPfindReader(scip, READER_NAME); 966 967 assert(reader != NULL); 968 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0); 969 970 readerdata = SCIPreaderGetData(reader); 971 assert(readerdata != NULL); 972 assert(stagenum >= 0 && stagenum < readerdata->nstages); 973 974 return readerdata->stagenames[stagenum]; 975 } 976 977 /* returns the stage name for a given constraint name */ 978 const char* SCIPtimConsGetStageName( 979 SCIP* scip, /**< SCIP data structure */ 980 const char* consname /**< the constraint to search for */ 981 ) 982 { 983 SCIP_READER* reader; 984 SCIP_READERDATA* readerdata; 985 int stagenum; 986 int i; 987 int j; 988 989 reader = SCIPfindReader(scip, READER_NAME); 990 991 assert(reader != NULL); 992 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0); 993 994 readerdata = SCIPreaderGetData(reader); 995 assert(readerdata != NULL); 996 997 /* looping over all stages to find the provided constraint */ 998 stagenum = -1; 999 for( i = 0; i < readerdata->nstages; i++ ) 1000 { 1001 for( j = 0; j < readerdata->stages[i]->nconss; j++ ) 1002 { 1003 if( strcmp(SCIPconsGetName(readerdata->stages[i]->conss[j]), consname) == 0 ) 1004 { 1005 stagenum = i; 1006 break; 1007 } 1008 } 1009 1010 if( stagenum >= 0 ) 1011 break; 1012 } 1013 assert(stagenum >= 0 && stagenum < readerdata->nstages); 1014 1015 return readerdata->stagenames[stagenum]; 1016 } 1017 1018 /* returns the number for a given stage */ 1019 int SCIPtimFindStage( 1020 SCIP* scip, /**< SCIP data structure */ 1021 const char* stage /**< the name of the requested stage */ 1022 ) 1023 { 1024 SCIP_READER* reader; 1025 SCIP_READERDATA* readerdata; 1026 int i; 1027 int stagenum; 1028 1029 reader = SCIPfindReader(scip, READER_NAME); 1030 1031 assert(reader != NULL); 1032 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0); 1033 1034 readerdata = SCIPreaderGetData(reader); 1035 assert(readerdata != NULL); 1036 1037 stagenum = -1; 1038 for( i = 0; i < readerdata->nstages; i++ ) 1039 { 1040 if( strcmp(readerdata->stagenames[i], stage) == 0 ) 1041 { 1042 stagenum = i; 1043 break; 1044 } 1045 } 1046 1047 if( stagenum < 0 ) 1048 { 1049 SCIPerrorMessage("Stage <%s> was not found in the TIM file. Check the SMPS files (COR, TIM and STO)\n", stage); 1050 SCIPABORT(); 1051 } 1052 1053 return stagenum; 1054 } 1055 1056 /* returns the array of variables for a given stage */ 1057 SCIP_VAR** SCIPtimGetStageVars( 1058 SCIP* scip, /**< SCIP data structure */ 1059 int stagenum /**< the number of the requested stage */ 1060 ) 1061 { 1062 SCIP_READER* reader; 1063 SCIP_READERDATA* readerdata; 1064 1065 reader = SCIPfindReader(scip, READER_NAME); 1066 1067 assert(reader != NULL); 1068 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0); 1069 1070 readerdata = SCIPreaderGetData(reader); 1071 assert(readerdata != NULL); 1072 assert(stagenum >= 0 && stagenum < readerdata->nstages); 1073 1074 return readerdata->stages[stagenum]->vars; 1075 } 1076 1077 /* returns an array of constraints for a given stage */ 1078 SCIP_CONS** SCIPtimGetStageConss( 1079 SCIP* scip, /**< SCIP data structure */ 1080 int stagenum /**< the number of the requested stage */ 1081 ) 1082 { 1083 SCIP_READER* reader; 1084 SCIP_READERDATA* readerdata; 1085 1086 reader = SCIPfindReader(scip, READER_NAME); 1087 1088 assert(reader != NULL); 1089 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0); 1090 1091 readerdata = SCIPreaderGetData(reader); 1092 assert(readerdata != NULL); 1093 assert(stagenum >= 0 && stagenum < readerdata->nstages); 1094 1095 return readerdata->stages[stagenum]->conss; 1096 } 1097 1098 /* returns the number of variables for a given stage */ 1099 int SCIPtimGetStageNVars( 1100 SCIP* scip, /**< SCIP data structure */ 1101 int stagenum /**< the number of the requested stage */ 1102 ) 1103 { 1104 SCIP_READER* reader; 1105 SCIP_READERDATA* readerdata; 1106 1107 reader = SCIPfindReader(scip, READER_NAME); 1108 1109 assert(reader != NULL); 1110 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0); 1111 1112 readerdata = SCIPreaderGetData(reader); 1113 assert(readerdata != NULL); 1114 assert(stagenum >= 0 && stagenum < readerdata->nstages); 1115 1116 return readerdata->stages[stagenum]->nvars; 1117 } 1118 1119 /* returns the number of constraints for a given stage */ 1120 int SCIPtimGetStageNConss( 1121 SCIP* scip, /**< SCIP data structure */ 1122 int stagenum /**< the number of the requested stage */ 1123 ) 1124 { 1125 SCIP_READER* reader; 1126 SCIP_READERDATA* readerdata; 1127 1128 reader = SCIPfindReader(scip, READER_NAME); 1129 1130 assert(reader != NULL); 1131 assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0); 1132 1133 readerdata = SCIPreaderGetData(reader); 1134 assert(readerdata != NULL); 1135 assert(stagenum >= 0 && stagenum < readerdata->nstages); 1136 1137 return readerdata->stages[stagenum]->nconss; 1138 } 1139