How to: Use Stochastic Programming to Solve Two-Stage Linear Models
You can use linear programming to minimize or maximize functions, and also account for fluctuating demand by using random parameters and recourse decisions. In this example, an oil refinery must procure crude oil from two sources. The objective is to minimize the purchase cost of crude oils of varying quality and to meet minimum production levels of 2,000 barrels of gasoline, 1,500 barrels of jet fuel, and 500 barrels of machine lubricant. Meanwhile, the suppliers cannot exceed their maximum daily production of crude oil. If demand cannot be met, the refinery must purchase pre-refined products at these prices: $38.40 for gas, $35.20 for jet fuel, and $28.80 for lubricant. The following table shows the costs and capabilities of the two different crude oils.
|
Source |
Saudi Arabia refining |
Venezuela refining |
|---|---|---|
|
Cost of crude oil |
$20 per barrel |
$15 per barrel |
|
Maximum daily production |
9,000 barrels |
6,000 barrels |
|
Refining percentages |
30% gasoline 40% jet fuel 20% lubricant 10% waste |
40% gasoline 20% jet fuel 30% lubricant 10% waste |
The following example uses Solver Foundation to create, solve, and adjust the refining model to account for demand. This example demonstrates how to use the Solver Foundation Services layer.
To use stochastic programming and Solver Foundation Services to account for demand
-
Create a console application named PetroChemStoch.
-
Add a reference to Microsoft Solver Foundation on the .NET tab.
-
Add the following Imports or using statements to the top of the Program code file.
-
In the Main method, add the following code to get the context environment for a solver and create a new model.
-
Create decision variables that represent the two sources of crude oil: Saudi Arabia and Venezuela. Then add the decisions to the model.
-
Create recourse decision variables that represent the demand for the three products: gas, jet fuel, and lubricant. If the refining process does not meet demand, pre-refined product must be purchased. Add the decisions to the model.
-
Add the costs of the crude oils and the demand for the three products to the model. Then specify that the solver should minimize the goal by setting the second parameter to GoalKind.Minimize.
-
Create and add random parameters that correspond to a normal bell-shaped probability distribution.
Dim gasDemand As RandomParameter = New NormalDistributionParameter("GasDemand", 1900, 50) Dim jetFuelDemand As RandomParameter = New NormalDistributionParameter("JetFuelDemand", 1500, 25) Dim lubricantDemand As RandomParameter = New NormalDistributionParameter("LubricantDemand", 500, 5) model.AddParameters(gasDemand, jetFuelDemand, lubricantDemand)
-
Add three second-stage constraints that evaluate the expected value of the recourse decision over all possible scenarios.
-
Solve the model and get the report.
-
Press F5 to build and run the code.
The Command window shows the following results.
===Solver Foundation Service Report===
Date: Date
Version: Version
Model Name: Default
Capabilities Applied: LP
Solve Time (ms): 235
Total Time (ms): 548
Solve Completion Status: Optimal
Solver Selected: Microsoft.SolverFoundation.Solvers.SimplexSolver
Directives:
Microsoft.SolverFoundation.Services.Directive
Algorithm: Primal
Arithmetic: Hybrid
Variables: 302 -> 302 + 301
Rows: 301 -> 301
Nonzeros: 1202
Eliminated Slack Variables: 0
Pricing (exact): SteepestEdge
Pricing (double): SteepestEdge
Basis: Slack
Pivot Count: 435
Phase 1 Pivots: 300 + 0
Phase 2 Pivots: 135 + 0
Factorings: 12 + 1
Degenerate Pivots: 0 (0.00 %)
Branches: 0
Stochastic Measures:
Stochastic Solution Type: Sampled
Sampling Method: LatinHypercube
Sample Count: 100
Random Seed: 123456
Solving Method: Deterministic Equivalent
EV: 90500
VSS: 338.107860596763
EVPI: 779.794594168023
===Solution Details===
Goals:
goal: 91279.5357087704
Decisions:
SA: 1961.5464827093
VZ: 3269.78028997898
Second stage decisions (Average [Min, Max]):
GasBuy: 21.8666417357027 [0, 140.348907941673]
JetFuelBuy: 61.42678017752 [0, 125.109005887119]
LubricantBuy: 0 [0, 0]