-
Notifications
You must be signed in to change notification settings - Fork 257
/
Copy pathflp.py
98 lines (78 loc) · 3.05 KB
/
flp.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
##@file flp.py
# @brief model for solving the capacitated facility location problem
"""
minimize the total (weighted) travel cost from n customers
to some facilities with fixed costs and capacities.
Copyright (c) by Joao Pedro PEDROSO and Mikio KUBO, 2012
"""
from pyscipopt import Model, quicksum, multidict
def flp(I, J, d, M, f, c):
"""flp -- model for the capacitated facility location problem
Parameters:
- I: set of customers
- J: set of facilities
- d[i]: demand for customer i
- M[j]: capacity of facility j
- f[j]: fixed cost for using a facility in point j
- c[i,j]: unit cost of servicing demand point i from facility j
Returns a model, ready to be solved.
"""
model = Model("flp")
x, y = {}, {}
for j in J:
y[j] = model.addVar(vtype="B", name="y(%s)" % j)
for i in I:
x[i, j] = model.addVar(vtype="C", name="x(%s,%s)" % (i, j))
for i in I:
model.addCons(quicksum(x[i, j] for j in J) == d[i], "Demand(%s)" % i)
for j in M:
model.addCons(quicksum(x[i, j] for i in I) <= M[j] * y[j], "Capacity(%s)" % i)
for (i, j) in x:
model.addCons(x[i, j] <= d[i] * y[j], "Strong(%s,%s)" % (i, j))
model.setObjective(
quicksum(f[j] * y[j] for j in J) +
quicksum(c[i, j] * x[i, j] for i in I for j in J),
"minimize")
model.data = x, y
return model
def make_data():
"""creates example data set"""
I, d = multidict({1: 80, 2: 270, 3: 250, 4: 160, 5: 180}) # demand
J, M, f = multidict({1: [500, 1000], 2: [500, 1000], 3: [500, 1000]}) # capacity, fixed costs
c = {(1, 1): 4, (1, 2): 6, (1, 3): 9, # transportation costs
(2, 1): 5, (2, 2): 4, (2, 3): 7,
(3, 1): 6, (3, 2): 3, (3, 3): 4,
(4, 1): 8, (4, 2): 5, (4, 3): 3,
(5, 1): 10, (5, 2): 8, (5, 3): 4,
}
return I, J, d, M, f, c
if __name__ == "__main__":
I, J, d, M, f, c = make_data()
model = flp(I, J, d, M, f, c)
model.optimize()
EPS = 1.e-6
x, y = model.data
edges = [(i, j) for (i, j) in x if model.getVal(x[i, j]) > EPS]
facilities = [j for j in y if model.getVal(y[j]) > EPS]
print("Optimal value:", model.getObjVal())
print("Facilities at nodes:", facilities)
print("Edges:", edges)
try: # plot the result using networkx and matplotlib
import networkx as NX
import matplotlib.pyplot as P
P.clf()
G = NX.Graph()
other = [j for j in y if j not in facilities]
customers = ["c%s" % i for i in d]
G.add_nodes_from(facilities)
G.add_nodes_from(other)
G.add_nodes_from(customers)
for (i, j) in edges:
G.add_edge("c%s" % i, j)
position = NX.drawing.layout.spring_layout(G)
NX.draw(G, position, node_color="y", nodelist=facilities)
NX.draw(G, position, node_color="g", nodelist=other)
NX.draw(G, position, node_color="b", nodelist=customers)
P.show()
except ImportError:
print("install 'networkx' and 'matplotlib' for plotting")