gussgrid.gms : Simple GUSS Grid example

Description

GUSS is a procedure that facilitates optimization of a collection of related
problems modifying data in those problems. Up to 24.3 GUSS could not be combined
with the GAMS Grid Facility. The GAMS Grid Facility allows to easily split the
scenarios set into multiple sets (e.g. number of CPUs/cores on the executing
machine) to utilize the parallel machine power.


Small Model of Type : LP


Category : GAMS Model library


Main file : gussgrid.gms

$title Simple GUSS Grid Example (GUSSGRID,SEQ=400)

$onText
GUSS is a procedure that facilitates optimization of a collection of related
problems modifying data in those problems. Up to 24.3 GUSS could not be combined
with the GAMS Grid Facility. The GAMS Grid Facility allows to easily split the
scenarios set into multiple sets (e.g. number of CPUs/cores on the executing
machine) to utilize the parallel machine power.


Bussieck, M R, Ferris, M C, and Lohmann, T, GUSS: Solving Collections of Data
Related Models within GAMS. In Kallrath, J, Ed, Algebraic Modeling Systems:
Modeling and Solving Real World Optimization Problems. Springer, Berlin
Heidelberg, 2012, pp. 35-56.

Keywords: linear programming, transportation problem, scheduling, GUSS, scenario
          analysis, grid facility
$offText

Set
   i 'canning plants' / seattle,  san-diego /
   j 'markets'        / new-york, chicago, topeka /;

Parameter
   a(i) 'capacity of plant i in cases'
        / seattle    350
          san-diego  600 /

   b(j) 'demand at market j in cases'
        / new-york   325
          chicago    300
          topeka     275 /;

Table d(i,j) 'distance in thousands of miles'
              new-york  chicago  topeka
   seattle         2.5      1.7     1.8
   san-diego       2.5              1.4;

Scalar f 'freight in dollars per case per thousand miles' / 90 /;

Parameter c(i,j) 'transport cost in thousands of dollars per case';
c(i,j) = f*d(i,j)/1000;

Variable
   x(i,j) 'shipment quantities in cases'
   z      'total transportation costs in thousands of dollars';

Positive Variable x;

Equation
   cost      'define objective function'
   supply(i) 'observe supply limit at plant i'
   demand(j) 'satisfy demand at market j';

cost..      z =e= sum((i,j), c(i,j)*x(i,j));

supply(i).. sum(j, x(i,j)) =l= a(i);

demand(j).. sum(i, x(i,j)) =g= b(j);

Model transport / all /;

$if not set whatrun $set whatrun 4_100
$goto %whatrun%

$label 4_10000
Set
   ScenariosToRun 'scenarios'        / s1*s10000  /
   cpu            'grid jobs to run' / cpu1*cpu4  /
   scpu(cpu,ScenariosToRun) / cpu1.(   s1* s2500)
                              cpu2.(s2501* s5000)
                              cpu3.(s5001* s7500)
                              cpu4.(s7501*s10000) /;

$goto cont
$label 4_100
Set
   ScenariosToRun 'scenarios'        / s1*s100   /
   cpu            'grid jobs to run' / cpu1*cpu4 /
   scpu(cpu,ScenariosToRun)    / cpu1.( s1* s25)
                                 cpu2.(s26* s50)
                                 cpu3.(s51* s75)
                                 cpu4.(s76*s100) /;

$goto cont
$label 1_10000
Set
   ScenariosToRun 'scenarios'        / s1*s10000 /
   cpu            'grid jobs to run' / cpu1      /
   scpu(cpu,ScenariosToRun) / cpu1.(s1*s10000)   /;

$goto  cont
$label cont
Alias (ScenariosToRun,s);

Parameter
   newsupply(s,*)    'updater for a'
   newdemand(s,*)    'updater for b'
   resultantx(s,i,j) 'collector for level of x';

newdemand(s,j) = normal(b(j),0.1);
newsupply(s,i) = normal(a(i),0.1);

* Make sure we don't go infeasible
newdemand(s,'total') = sum(j,newdemand(s,j));
newsupply(s,'total') = sum(i,newsupply(s,i));
newsupply(s,i)$(newdemand(s,'total') > newsupply(s,'total')) =
                newsupply(s,i)*(newdemand(s,'total') + 1)/newsupply(s,'total');

* Clear Total otherwise we get unmatched records in GUSS
newdemand(s,'total') = 0;
newsupply(s,'total') = 0;

Set
   gs(s) 'scenarios per GUSS run'
   dict  / gs. scenario.''
           a.  param   .newsupply
           b.  param   .newdemand
           x.  level   .resultantx /;

Parameter h(cpu) 'grid handles';
transport.solveLink = %solveLink.AsyncGrid%;

option limRow = 0, limCol = 0;

$eolCom //
loop(cpu,
   gs(s) = scpu(cpu,s);
   solve transport using lp minimizing z scenario dict;
   h(cpu) = transport.handle;  // save instance handle
);
* we use the handle parameter to indicate that the solution and the scenario
* results have been collected. By default (change with option solveopt) we do
* a merge of the solution and scenario results
scalar timedOut / 0 /;
repeat
   loop(cpu$handlecollect(h(cpu)),
      display$handledelete(h(cpu)) 'trouble deleting handles';
      h(cpu) = 0;   // indicate that we have loaded the solution
   );
   display$sleep(card(h)*0.2) 'was sleeping for some time';
   timedOut = (timeelapsed > 30);
until card(h) = 0 or timedOut;  // wait until all models are loaded or time limit reached
abort.noError$[timedOut] 'Time limit hit in collection loop';

Set xcollected(s);

option xcollected < resultantx;
abort$(card(xcollected) <> card(ScenariosToRun)) 'not all scenarios collected',
                                                  xcollected, resultantx;