'Transportation Problem : how to addresing variable from range(len()) for constraint? (transitioning from excel)
I'm new on using phyton for optimization (usually I simple use Ms.Excel) and this is my first time asking on stackoverflow. Usually in Ms. Excel you can add constraint from selecting cells, now i'm struggling to do the same in python. The code that I use is on the end of the page.
I want to express that warehouse(1) + warehouse(2) = 15. warehouse 1 and warehouse 2 need 15 to be delivered in total, but the codes using range for the name of the warehouse so I don't know how to do that. my demand is on array so python must have assign the warehouse name in order. So, how do I express those? My friend say If.. elif... else.. might be help, but how? ( he don't know either )
I might using gp.multidict instead so it's possible to address the variable manually, but my actual data is around 2000 so it's too much to do that one by one.
Sorry for my bad english :") Any idea? Any idea or help will very much appreciated. Thank you very much.
gp.multidict :
production, a = gp.multidict({
'A1': 7, 'A2': 4, 'A3': 9}) # Place of Origin
sales, b = gp.multidict({
'B1': 3, 'B2': 6, 'B3': 5, 'B4': 6}) # place of sales
route, cost = gp.multidict({
('A1', 'B1'): 3,
('A1', 'B2'): 11,
('A1', 'B3'): 3,a
('A1', 'B4'): 10,
('A2', 'B1'): 1,
('A2', 'B2'): 9,
('A2', 'B3'): 2,
('A2', 'B4'): 8,
('A3', 'B1'): 7,
('A3', 'B2'): 4,
('A3', 'B3'): 10,
('A3', 'B4'): 5})
my code :
import gurobipy as gp
from gurobipy import GRB
# Warehouse demand in thousands of units
demand = [15, 18, 14, 20]
# Plant capacity in thousands of units
capacity = [20, 22, 17, 19, 18]
# Fixed costs for each plant
fixedCosts = [12000, 15000, 17000, 13000, 16000]
# Transportation costs per thousand units
transCosts = [[4000, 2000, 3000, 2500, 4500],
[2500, 2600, 3400, 3000, 4000],
[1200, 1800, 2600, 4100, 3000],
[2200, 2600, 3100, 3700, 3200]]
# Range of plants and warehouses
plants = range(len(capacity))
warehouses = range(len(demand))
# Model
m = gp.Model("facility")
# Plant open decision variables: open[p] == 1 if plant p is open.
open = m.addVars(plants,
vtype=GRB.BINARY,
obj=fixedCosts,
name="open")
# The objective is to minimize the total fixed and variable costs
m.ModelSense = GRB.MINIMIZE
# Production constraints
m.addConstrs(
(transport.sum('*', p) <= capacity[p]*open[p] for p in plants), "Capacity")
# Demand constraints
m.addConstrs(
(transport.sum(w) == demand[w] for w in warehouses),
"Demand")
# Save model
m.write('facilityPY.lp')
# First open all plants
for p in plants:
open[p].Start = 1.0
# Now close the plant with the highest fixed cost
print('Initial guess:')
maxFixed = max(fixedCosts)
for p in plants:
if fixedCosts[p] == maxFixed:
open[p].Start = 0.0
print('Closing plant %s' % p)
break
print('')
# Use barrier to solve root relaxation
m.Params.Method = 2
# Solve
m.optimize()
# Print solution
print('\nTOTAL COSTS: %g' % m.ObjVal)
print('SOLUTION:')
for p in plants:
if open[p].X > 0.99:
print('Plant %s open' % p)
for w in warehouses:
if transport[w, p].X > 0:
print(' Transport %g units to warehouse %s' %
(transport[w, p].X, w))
else:
print('Plant %s closed!' % p)
Solution 1:[1]
I don't see where the variable "transport" is defined but I think it's defined over plants and warehouses, e.g., transport(i,j) is how much is sent from plant j to warehouse i.
So you define the set of plants and set of warehouses over a range, and each plant and warehouse will be correspondent to the same index in the coefficient.
For example
# The sets your variables defined over
plants = range(len(capacity))
warehouses = range(len(demand))
# First variable for transport
transport= m.addVars(warehouses,plants) # of course you can add the type and name here
# The second variable for whether to open a warehouse that you already defined
open = m.addVars(plants,
vtype=GRB.BINARY,
obj=fixedCosts,
name="open")
Now plant 1 is the one correspondent to the first element of the capacity list and the second plant is correspondent to the second element and so on. Similarly, the you link the demand list to the warehouses. So transport(0,0) is the amount transported from the the plant with capacity of 20 to the warehouse with demand of 15 at the transCosts(0,0) of 4000.
Now if you want warehouse(1) + warehouse(2) = 15 just look at the demand list and see which warehouse you call 1 and 2. I assumed it's the first two warehouses, i.e., index 0 and index 1, so your constraint will be:
m.addConstrs(
(transport.sum(i, '*') == 15 for i in [0,1]))
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
