scenmerge.gms : Combining scenario results in a directory tree with gdxmerge

Description

This model generates a couple of scenario runs that are stored in
a directory tree. The name of the directory reflects the choices
in some scenario sets: a1/b2/c3/. Some result GDX files are stored
in a results directory at the leave nodes of the directory tree and
a recursive gdxmerge combines all scenario results.

Keywords: GAMS language features, scenario management, gdxmerge

  On the major platforms (Windows, Linux, Mac), GMSPYTHONLIB gets automatically set
  to use the internal Python installation in sysdir/GMSPython.

  The transport model with multipliers for a, b, and c via
  command line double dash parameters.


Reference

  • GAMS Development Corporation, Formulation and Language Example.

Small Model of Type : GAMS


Category : GAMS Model library


Main file : scenmerge.gms

$title Combining scenario results in a directory tree with gdxmerge (scenmerge,SEQ=427)

$onText
This model generates a couple of scenario runs that are stored in
a directory tree. The name of the directory reflects the choices
in some scenario sets: a1/b2/c3/. Some result GDX files are stored
in a results directory at the leave nodes of the directory tree and
a recursive gdxmerge combines all scenario results.

Keywords: GAMS language features, scenario management, gdxmerge
$offText

* On the major platforms (Windows, Linux, Mac), GMSPYTHONLIB gets automatically set 
* to use the internal Python installation in sysdir/GMSPython.
$if not setEnv GMSPYTHONLIB $abort.noError Embedded code Python not ready to be used
$log --- Using Python library %sysEnv.GMSPYTHONLIB%

$onecho > t.gms
* The transport model with multipliers for a, b, and c via
* command line double dash parameters.

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.8     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 a $set a 1
$if not set b $set b 1
$if not set c $set c 1

a(i) = %a%*a(i);
b(j) = %b%*b(j);
c(i,j) = %c%*c(i,j);

solve transport using lp minimizing z;

scalar tmodelstat; tmodelstat = transport.modelstat;
parameter p(j) 'commodity price'; p(j) = demand.m(j);
display x.l, x.m;
execute 'test -d results || mkdir results';
execute_unload 'results/input', a,b,c;
execute_unload 'results/report', x, z, p, tmodelstat;
$offecho
set a,b,c;
parameter
    ascen(a<) / a_low 0.9, a_med 1.0, a_high 1.1 /
    bscen(b<) / b_low 0.9, b_med 1.0, b_high 1.1 /
    cscen(c<) / c_low 0.9, c_med 1.0, c_high 1.1 /;
    
$set mkdir mkdir
$if %system.fileSys%==UNIX $set mkdir mkdir -p

loop((a,b,c),
   put_utility 'shell' / 'test -d ' a.tl:0 '%system.dirsep%' b.tl:0 '%system.dirsep%' c.tl:0 ' || %mkdir% ' a.tl:0 '%system.dirsep%' b.tl:0 '%system.dirsep%' c.tl:0
   put_utility 'exec.checkErrorLevel'  / 'gams t.gms lo=2 -idir "%gams.wdir%" -curdir ' a.tl:0 '/' b.tl:0 '/' c.tl:0 ' --a ' ascen(a):3:1 ' --b ' bscen(b):3:1 ' --c ' cscen(c):3:1
);

* Now walk the tree and combine recursively the results.
$set gdxdir results
embeddedCode Python:
import os
gd = -1
for root, dirs, files in os.walk(os.path.normpath(r"%gams.wdir% ".rstrip()), topdown=False):
  if '%gdxdir%' in dirs:
    if gd == -1:
      gd = root.count(os.path.sep) 
      gdr = root;
    elif not gd == root.count(os.path.sep):
      raise NameError('%gdxdir% subdirs found at different depths in the tree: ' + root + ' and ' + gdr)
    cmd = 'cd "' + root + '" && gdxmerge %gdxdir%' + os.path.sep + '* output=' + root.split(os.path.sep)[-1]
    gams.printLog('Merging %gdxdir% in ' + root)
    if not 0 == os.system(cmd + '>' + os.devnull):
      raise NameError('problems running: ' + cmd)
  elif root.count(os.path.sep) < gd:
    input = ''
    for d in dirs:  
      if os.path.isfile(os.path.join(root, d, d + '.gdx')):
        input = input + ' ' + os.path.join(d, d + '.gdx')
    if len(input):
      cmd = 'cd "' + root + '" && gdxmerge' + input + ' output=' + root.split(os.path.sep)[-1]
      gams.printLog('Merging' + input + ' in ' + root)
      if not 0 == os.system(cmd + '>' + os.devnull):
        raise NameError('problems running: ' + cmd)
gams.printLog('All done. Final result file: ' + root.split(os.path.sep)[-1] + '.gdx')
endEmbeddedCode