Description
GUSS is a procedure that facilitates optimization of a collection of related problems modifying data in those problems. GUSS allows one to solve the collection of models in a single pass without needing repeated solves or a LOOP over multiple solves. GUSS is not really a solver but rather organizes and passes data to and from another LP, NLP, MIP etc solver. This is all done in a faster fashion than say when using multiple solves through the GAMS Loop command. In particular GUSS runs the model repeatedly over user specified data for model parameters that collectively define alternative scenarios to be run. In doing this it repeatedly updates the base model with the altered scenario data, then solves the updated model for that scenario and saves user chosen results for each scenario. GUSS was developed by Michael R. Bussieck, Michael C. Ferris, and Timo Lohmann. It is documented in http://www.gams.com/modlib/adddocs/gusspaper.pdf and in the GUSS section of the solver manual. Use of GUSS for an existing model requires six steps 1. Definition of scenarios to run 2. Definition of parameters holding scenario specific data for the items in the model that to be changed 3. Definition of parameters that will hold scenario specific model results for the items that the user wished to save 4. Definition of a set that tells GUSS the scenarios to run, data to change and results to save 5. Modification of the solve statement to identify that scenarios will be run 6. Development of code to report the scenario results These 6 steps are demonstrated used the simple transport model
Small Model of Type : LP
Category : GAMS Model library
Main file : gussex1.gms
$title Simple GUSS Example (GUSSEX1,SEQ=398)
$onText
GUSS is a procedure that facilitates optimization of a collection of related
problems modifying data in those problems. GUSS allows one to solve the
collection of models in a single pass without needing repeated solves or a
LOOP over multiple solves. GUSS is not really a solver but rather organizes and
passes data to and from another LP, NLP, MIP etc solver. This is all done in a
faster fashion than say when using multiple solves through the GAMS Loop command.
In particular GUSS runs the model repeatedly over user specified data for model
parameters that collectively define alternative scenarios to be run. In doing
this it repeatedly updates the base model with the altered scenario data, then
solves the updated model for that scenario and saves user chosen results for
each scenario.
GUSS was developed by Michael R. Bussieck, Michael C. Ferris, and Timo Lohmann.
It is documented in http://www.gams.com/modlib/adddocs/gusspaper.pdf and in the
GUSS section of the solver manual.
Use of GUSS for an existing model requires six steps
1. Definition of scenarios to run
2. Definition of parameters holding scenario specific data for the items
in the model that to be changed
3. Definition of parameters that will hold scenario specific model results
for the items that the user wished to save
4. Definition of a set that tells GUSS the scenarios to run, data to change
and results to save
5. Modification of the solve statement to identify that scenarios will be run
6. Development of code to report the scenario results
These 6 steps are demonstrated used the simple transport model
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
$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.4 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 /;
Set ScenariosToRun 'scenarios' / base, run1, run2 /;
Table newsupply(ScenariosToRun,i) 'updater for a'
seattle san-diego
base 350 600
run1 300 650
run2 401 549;
Table newdemand(ScenariosToRun,j) 'updater for b'
new-york chicago topeka
base 325 300 275
run1 325 300 275
run2 350 300 250;
Set mattrib / system.GUSSModelAttributes /;
Parameter
xl(ScenariosToRun,i,j) 'collector for level of x'
xm(ScenariosToRun,i,j) 'collector for marginal of x'
demandl(ScenariosToRun,j) 'collector for level of demand'
demandm(ScenariosToRun,j) 'collector for marginal of demand'
srep(ScenariosToRun, mattrib) 'model attibutes like modelstat etc'
o(*) 'GUSS options' / SkipBaseCase 1 /;
Set dict / ScenariosToRun.scenario.''
o. opt .srep
a. param .newsupply
b. param .newdemand
x. level .xl
x. marginal.xm
demand. level .demandl
demand. marginal.demandm /;
solve transport using lp minimizing z scenario dict;
* The solve statement from the line above results can also be expressed
* in traditional GAMS syntax as follows:
$onText
loop(ScenariosToRun,
a(i) = newsupply(ScenariosToRun,i);
b(j) = newdemand(ScenariosToRun,j);
solve transport using lp minimizing z;
xl(ScenariosToRun,i,j) = x.l(i,j);
xm(ScenariosToRun,i,j) = x.m(i,j);
demandl(ScenariosToRun,j) = demand.l(j);
demandm(ScenariosToRun,j) = demand.m(j);
);
$offText
Set Error(scenariostorun) 'empty solution';
Error(scenariostorun) = sum((i,j), xl(scenariostorun,i,j)) = 0;
abort$card(error) 'Missing solution for some scenarios', error;
* Now rerun GUSS with scaleOpt=1 and compare solution
Parameter
sxl(ScenariosToRun,i,j) 'collector for level of x'
sxm(ScenariosToRun,i,j) 'collector for marginal of x'
sdemandl(ScenariosToRun,j) 'collector for level of demand'
sdemandm(ScenariosToRun,j) 'collector for marginal of demand';
Set sdict / ScenariosToRun.scenario.''
o. opt .srep
a. param .newsupply
b. param .newdemand
x. level .sxl
x. marginal.sxm
demand. level .sdemandl
demand. marginal.sdemandm /;
x.scale(i,j) = 10;
demand.scale(j) = 100;
transport.scaleOpt = 1;
solve transport using lp minimizing z scenario sdict;
abort$(smax((ScenariosToRun,i,j), abs(xl(ScenariosToRun,i,j)-sxl(ScenariosToRun,i,j))) > 1e-3) 'Wrong x.l scaled and unscaled:', xl, sxl;
abort$(smax((ScenariosToRun,i,j), abs(xm(ScenariosToRun,i,j)-sxm(ScenariosToRun,i,j))) > 1e-3) 'Wrong x.m scaled and unscaled:', xm, sxm;
abort$(smax((ScenariosToRun,j), abs(demandl(ScenariosToRun,j)-sdemandl(ScenariosToRun,j))) > 1e-3) 'Wrong demand.l scaled and unscaled:', demandl, sdemandl;
abort$(smax((ScenariosToRun,j), abs(demandm(ScenariosToRun,j)-sdemandm(ScenariosToRun,j))) > 1e-3) 'Wrong demand.m scaled and unscaled:', demandm, sdemandm;