Lindo Systems

! Water Reservoir model in LINGO;
! A watershed consists of one or more pools(or reservoirs, lakes
  dams).  Each period: decisions for each pool are:
    a) How much water to release, XGEN, to use to generate
         electricity, and
    b) How much additional water to release, XSPIL, beyond the 
       electricity generation capacity, e.g., because otherwise
       the pool would be too full.
   Each pool has at most one successor pool, into which water
    released this period, enters next period.
   Each period, in each pool,  there is a certain amount of
    outside water that flows into the pool, INFLO, from
    rainfall and snowmelt.
   A stretch of river is a pool with little storage capacity 
    and no generation capacity.
  The objective is to maximize the value of the electricity
 generated without violating any of the various capacity constraints;

! Keywords: Hydro electric, Reservoir modeling, River system, Water
            Electricity generation, Dam system, Dynamic network;
SETS:
 POOL: IMX, IMN, GMX, VAL, V0;
 TIME;
 PXT( POOL, TIME): XGEN, XSPIL, V, INFLO;
 PXP( POOL, POOL): LT;
ENDSETS
DATA:
 POOL = PL1  PL2  PL3;
! Value per unit of water used to generate electricity
   by pool;
  VAL =  300   320   330;
  IMN =  110   150   250; ! Min pool levels;
  IMX =  190   200   390; ! Max pool levels;
  V0  =  110   170   285; ! Initial pool level;
  GMX =   60    70    80; ! Max gen capacity;

 TIME = Jan Feb Mar Apr May;
! Inflow by period into each reservoir or pool
  from the outside world;
 INFLO=  50  52  65  95  85 ! PL1;
         65  65  60  55  50 ! PL2;
         70  75  72  60  52;! PL3;
     
 ! The pools are a simple linear system
      with PL1 -> PL2 -> PL3,
     and with Lead times from pool to pool;
      PXP,    LT = 
   PL1, PL2    2
   PL2, PL3    1;
ENDDATA

! Maximize the value of the water converted to
   electricity;
  MAX = @SUM(PXT(p,t): VAL(P)*XGEN(p,t));

! For the first period. Ending inventory=
  beginning inventory + inflow - outflo;
@FOR( POOL(p):
   V(p,1) = V0(p) + INFLO(p,1)   
             - XGEN(p,1) - XSPIL(p,1);
    );

! Later periods: Ending inventory =
  beginning inventory + inflow from outside world +
  inflow from upstream pools - outflo(gen and spill);
@FOR( PXT(p,t)| T #GT# 1:
   V(p,t) = V(p,t-1) + INFLO(p,t) 
            + @SUM(PXP(i,p)| t - LT(i,p) #GT# 0: XGEN(i,t-LT(i,p)) + XSPIL(i,t-LT(i,p)))
            - XGEN(p,t) - XSPIL(p,t);
    );

! Bounds. Cannot store more in a pool than capacity.
    Cannot generate more than generating capacity;
@FOR(PXT(p,t):
   @BND( IMN(p),  V(p,t), IMX(p));
   @BND(      0, XGEN(p,t), GMX(p));
     );