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