Stochastic Formulation

Verbal formulation of the natural gas planning problem

Minimize the first-period cost + 
         the "expected value" of second-period costs

subject to the requirements: 
 -Meet demand in each time period and each scenario by purchasing 
    gas or using it from storage
 -Store gas that is not used in the current time period
 -Storage can never be less than 0 (no borrowing)
Because the first-period decision must be the same for each scenario, there is only one scenario in the first period. This forces our decision to have the nonanticipativity property, i.e., we cannot anticipate the future.

In order to create a mathematical version of this model, we need to define some variables:

 
 Buy[Year][Scen]   = amount of gas purchased in Year 
                     if scenario Scen occurs
 Use[Year][Scen]   = amount of gas used from storage in Year
                     if scenario Scen occurs
 Store[Year][Scen] = amount of gas to store in Year
                     if scenario Scen occurs

and some parameters:

 
 Cost[Year][Scen]   = price per unit of natural gas in Year 
                      if Scen occurs
 Demand[Year][Scen] = demand for gas during Year 
                      if Scen occurs
 StorageCost        = cost to store 1 unit of gas for one year
                      if Scen occurs
 Prob[Scen]         = probability second-period Scen occurs


Mathematical Formulation

Minimize (Price[1][1] * Buy[1][1] + sum Store[1][1] * StorageCost) +
         sum Scen Prob[Scen] * (Price[2][Scen] * Buy[2][Scen] +
                                Store[2][Scen] * StorageCost)

subject to:

  First-period constraints

  Buy[1][1] + Use[1][1] >= Demand[1][1]
  Store[1] = Store[0] + Buy[1] - Demand[1]
  Use[1] <= Store[0]

  Second-period constraints (repeated for all Scenarios)

  Buy[2][Scen] + Use[2][Scen] >= Demand[2][Scen]
  Store[2][Scen] = Store[1][1] + Buy[2][Scen] - Demand[1][Scen]
  Use[2][Scen] <= Store[1][1]


The AMPL code actually used is provided below.


param LastPeriod > 0;            # Number of periods in the model

param LastScenario{-1..LastPeriod} >= 0;

param PurchasePrice{t in 0..LastPeriod,0..LastScenario[t]} >= 0;
param Demand       {t in 0..LastPeriod,0..LastScenario[t]} >= 0;
param Probability  {t in 0..LastPeriod,0..LastScenario[t]} >= 0;
param Parent       {t in 0..LastPeriod,0..LastScenario[t]} >= 0;

param StorageCost > 0;

# VARIABLES #

var Purchase       {t in 0..LastPeriod, 0..LastScenario[t]} >= 0;
var UseFromStorage {t in 0..LastPeriod, 0..LastScenario[t]} >= 0;
var Storage        {t in -1..LastPeriod,0..LastScenario[t]} >= 0;

# OBJECTIVE FUNCTION #

minimize TotalCost:
  sum{t in 0..LastPeriod, s in 0..LastScenario[t]} 
    Probability[t,s] * 
    (PurchasePrice[t,s] * Purchase[t,s] + StorageCost * Storage[t,s]);

# CONSTRAINTS #

subject to MeetDemand{t in 0..LastPeriod, s in 0..LastScenario[t]}:
  Purchase[t,s] + UseFromStorage[t,s] >= Demand[t,s];

subject to StorageBalance{t in 0..LastPeriod, s in 0..LastScenario[t]}:
  Storage[t,s] = Storage[t-1,Parent[t,s]] + Purchase[t,s] - Demand[t,s];

subject to UseLessThanHave{t in 0..LastPeriod, s in 0..LastScenario[t]}:
  UseFromStorage[t,s] <= Storage[t-1,Parent[t,s]];

subject to InitialStorage:
  Storage[-1,0] = 0;