Hookstark
Hookstark

Reputation: 1159

Pyomo (Transportation theory): including a constraint that limits to just one the number of sources/factories

I'm trying to solve the classical 'Transportation theory' to optimize the production and transportation of goods from 3 factories to 5 distribution centers.

There are:

I'm able to solve it with Pyomo:

from pyomo.environ import *
import pyomo.environ as pyo

model = ConcreteModel()

model.i = Set(initialize=['Factory A','Factory B', 'Factory C'])
model.j = Set(initialize=['DC 1', 'DC 2', 'DC 3', 'DC 4', 'DC 5'])
model.a = Param(model.i, initialize={'Factory A':1000,'Factory B':4000, 'Factory C':2000}) #Weekly_capacities
model.b = Param(model.j, initialize={'DC 1':500,'DC 2':900,'DC 3':1800, 'DC 4':200, 'DC 5':700 }) #Weekly_demands

# Transportation costs
costs = {('Factory A', 'DC 1'): 2,('Factory A', 'DC 2'): 4, ('Factory A', 'DC 3'): 5, ('Factory A', 'DC 4'): 2, ('Factory A', 'DC 5'): 1, \
    ('Factory B', 'DC 1'): 3, ('Factory B', 'DC 2'): 1, ('Factory B', 'DC 3'): 3, ('Factory B', 'DC 4'): 2, ('Factory B', 'DC 5'): 3, \
    ('Factory C', 'DC 1'): 1, ('Factory C', 'DC 2'): 3, ('Factory C', 'DC 3'): 3, ('Factory C', 'DC 4'): 1, ('Factory C', 'DC 5'): 5}

model.d = Param(model.i, model.j, initialize=costs)

def f_costs(model, i, j):
    return model.d[i,j]
model.c = Param(model.i, model.j, initialize=f_costs)

model.x = Var(model.i, model.j, bounds=(0.0,None)) #Production

def f_supply(model, i):
    return sum(model.x[i,j] for j in model.j) <= model.a[i]
model.supply = Constraint(model.i, rule=f_supply)

def f_demand(model, j):
    return sum(model.x[i,j] for i in model.i) >= model.b[j]  
model.demand = Constraint(model.j, rule=f_demand)

def f_objetive(model):
    return sum(model.c[i,j]*model.x[i,j] for i in model.i for j in model.j)
model.objetive = Objective(rule=f_objetive, sense=minimize)

def pyomo_postprocess(options=None, instance=None, results=None):
    model.x.display()

opt = SolverFactory("glpk")
results = opt.solve(model)
pyomo_postprocess(None, None, results)

Solution:

x : Size=15, Index=x_index
    Key                   : Lower : Value  : Upper : Fixed : Stale : Domain
    ('Factory A', 'DC 1') :   0.0 :    0.0 :  None : False : False :  Reals
    ('Factory A', 'DC 2') :   0.0 :    0.0 :  None : False : False :  Reals
    ('Factory A', 'DC 3') :   0.0 :    0.0 :  None : False : False :  Reals
    ('Factory A', 'DC 4') :   0.0 :    0.0 :  None : False : False :  Reals
    ('Factory A', 'DC 5') :   0.0 :  700.0 :  None : False : False :  Reals
    ('Factory B', 'DC 1') :   0.0 :    0.0 :  None : False : False :  Reals
    ('Factory B', 'DC 2') :   0.0 :  900.0 :  None : False : False :  Reals
    ('Factory B', 'DC 3') :   0.0 :  500.0 :  None : False : False :  Reals
    ('Factory B', 'DC 4') :   0.0 :    0.0 :  None : False : False :  Reals
    ('Factory B', 'DC 5') :   0.0 :    0.0 :  None : False : False :  Reals
    ('Factory C', 'DC 1') :   0.0 :  500.0 :  None : False : False :  Reals
    ('Factory C', 'DC 2') :   0.0 :    0.0 :  None : False : False :  Reals
    ('Factory C', 'DC 3') :   0.0 : 1300.0 :  None : False : False :  Reals
    ('Factory C', 'DC 4') :   0.0 :  200.0 :  None : False : False :  Reals
    ('Factory C', 'DC 5') :   0.0 :    0.0 :  None : False : False :  Reals

However, due to my business and my logistics, I need that the supply of each one of the Distribution Centers comes exclusively from just one factory (and not from two or three). For instance, 'DC 3' is receiving the goods from 'Factory B' and 'Factory C' and I would like to force it to just 'Factory B' or just 'Factory C'.

Is there any way to include a Pyomo constraint to limit the number of sources for the Distribution Costs?

Upvotes: 0

Views: 112

Answers (1)

Erwin Kalvelagen
Erwin Kalvelagen

Reputation: 16772

You need binary variables for this. I'll use math notation below as this is much less unwieldy than Pyomo code. The standard transportation model looks like:

 min sum((i,j), c[i,j]*x[i,j])
 sum(j, x[i,j]) <= a[i]   ∀i
 sum(i, x[i,j]) >= b[j]   ∀j
 x[i,j] >= 0

Now add binary variables y[i,j] and use:

 min sum((i,j), c[i,j]*x[i,j])
 sum(j, x[i,j]) <= a[i]   ∀i
 sum(i, x[i,j]) >= b[j]   ∀j
 x[i,j] <= M[i,j]*y[i,j]  ∀i,j
 sum(i,y[i,j]) = 1        ∀j
 x[i,j] >= 0
 y[i,j] ∈ {0,1}

here M[i,j] is an upper bound on x[i,j]. E.g.

  M[i,j] = min(a[i],b[j])

Upvotes: 1

Related Questions