Download Optimization Models
The slick_oil.py file uses advanced data input methods and takes greater advantage of Pyomo's model-building capabilities compared to slick_oil_simple.py, which relies on hard-coded data values. Both versions are useful for learning how to construct models, and they will both generate the same .mps file.
Model Description
Play an interactive version of this model
You are the supply chain manager for the Slick Oil company, overseeing a network of 6 oil wells and 5 refineries. Each action in your network involves specific costs and capacity limits. Recently, you signed a contract with a new customer to deliver 100 barrels of oil.
Your objective is to deliver the oil to the customer at the lowest possible cost while ensuring you do not exceed the capacity limits of the wells or refineries. The layout of your network is available on the interactive page linked above.
Mathematical Formulation
Sets
\(L\) Set of all lanes
\(L_i\) Set of lanes from well \(i\)
\(L_j\) Set of lanes to refinery \(j\)
\(W\) Set of wells
\(R\) Set of refineries
Coefficients
\(C_i\) Cost per barrel of oil from well \(i\)
\(C_j\) Cost per barrel of oil processed at refinery \(j\)
\(U_i\) Capacity, in number of barrels, at well \(i\)
\(U_j\) Capacity, in number of barrels, at refinery \(j\)
Decision Variables
\(X_i\) Number of barrels of oil to move from well \(i\) to refinery \(j\)
Objective
\( \max \sum_{(i,j) \in L} X_{ij} (C_i + C_j) \)
Constraints
Demand of 100 barrels of oil must be satisfied
\( \sum_{(i,j) \in L} X_{ij} = 100 \)
Capacity at the wells cannot be exceeded
\( \sum_{j \in L_i} X_{ij} \le U_i \forall i \in W \)
Capacity at the refineries cannot be exceeded
\( \sum_{i \in L_j} X_{ij} \le U_j \forall j \in R \)
Flow has to be non-negative
\( X_{i,j} \ge 0 \forall (i,j) \in L \)
Solution
The minimum cost of moving the oil through the network is $100. This optimal solution is achieved by sending:
- 40 barrels from Well 1 to Refinery A
- 40 barrels from Well 3 to Refinery B
- 20 barrels from Well 6 to Refinery C
Python Pyomo File
Below is the Python code that uses Pyomo to formulate this optimization model.
slick_oil.py
import pyomo.environ as pyo
def slickoil():
model = pyo.ConcreteModel(name='Slick_Oil')
model.wells = ['Well1', 'Well2', 'Well3', 'Well4', 'Well5', 'Well6']
model.refineries = ['RefineryA', 'RefineryB', 'RefineryC', 'RefineryD', 'RefineryE']
model.pipelines = [('Well1', 'RefineryA'), ('Well1', 'RefineryB'),
('Well2', 'RefineryB'), ('Well2', 'RefineryC'), ('Well2', 'RefineryD'),
('Well3', 'RefineryB'), ('Well3', 'RefineryC'), ('Well3', 'RefineryE'),
('Well4', 'RefineryA'), ('Well4', 'RefineryE'),
('Well5', 'RefineryD'), ('Well5', 'RefineryE'),
('Well6', 'RefineryC'), ('Well6', 'RefineryE')]
model.flows = pyo.Var(model.pipelines, within=pyo.NonNegativeReals)
model.constraint_values = {'Wells': {'Well1': 40, 'Well2': 50, 'Well3': 40,
'Well4': 100, 'Well5': 100, 'Well6': 100},
'Refineries': {'RefineryA': 100, 'RefineryB': 40,
'RefineryC': 80, 'RefineryD': 100,
'RefineryE': 80},
'Demand': 100}
well_costs = {'Well1': 3, 'Well2': 12, 'Well3': 4, 'Well4': 6, 'Well5': 10, 'Well6': 2.5}
refinery_costs = {'RefineryA': 4, 'RefineryB': 2, 'RefineryC': 6,
'RefineryD': 1, 'RefineryE': 8}
# Define the objective as minimize the costs of getting the oil to the customer
model.obj = pyo.Objective(expr=sum(model.flows[(well, refinery)]
* (well_costs[well] + refinery_costs[refinery])
for (well, refinery) in model.pipelines),
sense=pyo.minimize)
def demand_constraint(mdl):
return (sum(mdl.flows[(well, refinery)]
for (well, refinery) in mdl.pipelines) >= 100)
model.demand_constraint = pyo.Constraint(rule=demand_constraint)
def well_constraints(mdl, input_well):
return (sum(mdl.flows[(well, refinery)]
for (well, refinery) in mdl.pipelines if well == input_well)
<= mdl.constraint_values['Wells'][input_well])
model.well_constraints = pyo.Constraint(model.wells, rule=well_constraints)
def refinery_constraints(mdl, input_refinery):
return (sum(mdl.flows[(well, refinery)]
for (well, refinery) in mdl.pipelines if refinery == input_refinery)
<= mdl.constraint_values['Refineries'][input_refinery])
model.refinery_constraints = pyo.Constraint(model.refineries, rule=refinery_constraints)
model.write("slick_oil.mps", io_options={"symbolic_solver_labels": True})
if __name__ == '__main__':
slickoil()
Note that the .mps file generated directly from Pyomo may appear slightly different than the one available for download on this page. This version has been cleaned up for readability, though it performs the same as the one generated directly by Pyomo.
Comments
0 comments
Please sign in to leave a comment.