pythonlinear-programmingpyomo

Solving a LP Transportation Problem with Storage Constraints Using Pyomo Python


It's been a few years since I have done any optimization and I am set about solving a transportation problem using LP via Pyomo.

The minimization problem:

LP Minimization Problem

This one is simple enough to solve and I did something like this (changed around tutorial code from Pyomo docs):

from pyomo.environ import *
from pyomo.opt import SolverFactory

# create Pyomo model objects
demand = {'p1': 750, 'p2': 600, 'p3': 500, 'p4': 800}
supply = {'s1': 400, 's2': 600, 's3': 750, 's4': 300, 's5': 800}
combos = tuple(product(demand.keys(), supply.keys()))
vals = [114, 145, 153, 158, 163,
        155, 180, 190, 194, 202,
        135, 160, 172, 176, 185,
        142, 171, 180, 185, 194]
T = dict(zip(combos, vals))

# create model instance
model3 = ConcreteModel()
model3.dual = Suffix(direction=Suffix.IMPORT)

# define index sets
plants = list(demand.keys())
suppliers = list(supply.keys())

# define the decision
model3.x = Var(plants, suppliers, domain=NonNegativeReals)

# define objective
@model3.Objective(sense=minimize)
def cost(m):
    return sum([T[c,s]*model3.x[c,s] for c in plants for s in suppliers])

# constraints
@model3.Constraint(suppliers)
def src(m, s):
    return sum([model3.x[c,s] for c in plants]) <= supply[s]

@model3.Constraint(plants)
def dmd(m, c):
    return sum([model3.x[c,s] for s in suppliers]) == demand[c]

# solve    
results = SolverFactory('glpk').solve(model3)
results.write()

# print results
if 'ok' == str(results.Solver.status):
    print("Total Shipping Costs = ", model3.cost())
    print("\nShipping Table:")
    for s in suppliers:
        for c in plants:
            if model3.x[c,s]() > 0:
                print("Ship from ", s," to ", c, ":", model3.x[c,s]())
else:
    print("No Valid Solution Found")

This yields a solution which I know is correct:

Solution: 
- number of solutions: 0
  number of solutions displayed: 0
Total Shipping Costs =  443600.0

Shipping Table:
Ship from  s1  to  p1 : 150.0
Ship from  s1  to  p4 : 250.0
Ship from  s2  to  p2 : 100.0
Ship from  s2  to  p3 : 500.0
Ship from  s3  to  p2 : 200.0
Ship from  s3  to  p4 : 550.0
Ship from  s4  to  p2 : 300.0
Ship from  s5  to  p1 : 600.0

What I am stuck on is the following added constraint:

added constraint

I am fairly certain I should create a dict signifying this:

# added constraint
space_limit = [2, 1.5, 3, 1.2, 1.7]
supply_space = dict(zip(suppliers, space_limit))

I know I should add another constraint function, but I am at a loss for the syntax. I am struggling with unpacking Pyomo objects to see "what's under the hood" as I can't just print stuff out until it clicks.

Help would be appreciated!

My attempt (not the right answer):

@model3.Constraint(suppliers)
def capacity(m, s):
    return(sum([supply_space[s] * model3.x[c, s] for c in plants])) <= 2000

# solve
results = SolverFactory('glpk').solve(model3)
results.write()

# print results
if 'ok' == str(results.Solver.status):
    print("Total Shipping Costs = ", model3.cost())
    print("\nShipping Table:")
    for s in suppliers:
        for c in plants:
            if model3.x[c,s]() > 0:
                print("Ship from ", s," to ", c, ":", model3.x[c,s]())
else:
    print("No Valid Solution Found")

Solution

  • The restriction on storage only pertains to plant #4. Your constraint is close, but it needs to be scripted just for p4, and it is a summation across all suppliers, not a "per supplier" constraint. I'd expect something like this:

    model3.cap_constraint = Constraint(expr=sum(model3.x['p4', s] * supply_space[s] for s in suppliers) <= 2000)