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