PySCIPOpt  5.1.1
Python Interface for the SCIP Optimization Suite
flp-benders.py
Go to the documentation of this file.
1 
3 """
4 minimize the total (weighted) travel cost from n customers
5 to some facilities with fixed costs and capacities.
6 
7 Copyright (c) by Joao Pedro PEDROSO and Mikio KUBO, 2012
8 """
9 from pyscipopt import Model, quicksum, multidict, SCIP_PARAMSETTING
10 
11 
12 def flp(I, J, d, M, f, c):
13  """flp -- model for the capacitated facility location problem
14  Parameters:
15  - I: set of customers
16  - J: set of facilities
17  - d[i]: demand for customer i
18  - M[j]: capacity of facility j
19  - f[j]: fixed cost for using a facility in point j
20  - c[i,j]: unit cost of servicing demand point i from facility j
21  Returns a model, ready to be solved.
22  """
23 
24  master = Model("flp-master")
25  subprob = Model("flp-subprob")
26 
27  # creating the problem
28  y = {}
29  for j in J:
30  y[j] = master.addVar(vtype="B", name="y(%s)" % j)
31 
32  master.setObjective(
33  quicksum(f[j] * y[j] for j in J),
34  "minimize")
35  master.data = y
36 
37  # creating the subproblem
38  x, y = {}, {}
39  for j in J:
40  y[j] = subprob.addVar(vtype="B", name="y(%s)" % j)
41  for i in I:
42  x[i, j] = subprob.addVar(vtype="C", name="x(%s,%s)" % (i, j))
43 
44  for i in I:
45  subprob.addCons(quicksum(x[i, j] for j in J) == d[i], "Demand(%s)" % i)
46 
47  for j in M:
48  subprob.addCons(quicksum(x[i, j] for i in I) <= M[j] * y[j], "Capacity(%s)" % i)
49 
50  for (i, j) in x:
51  subprob.addCons(x[i, j] <= d[i] * y[j], "Strong(%s,%s)" % (i, j))
52 
53  subprob.setObjective(
54  quicksum(c[i, j] * x[i, j] for i in I for j in J),
55  "minimize")
56  subprob.data = x, y
57 
58  return master, subprob
59 
60 
61 def make_data():
62  """creates example data set"""
63  I, d = multidict({1: 80, 2: 270, 3: 250, 4: 160, 5: 180}) # demand
64  J, M, f = multidict({1: [500, 1000], 2: [500, 1000], 3: [500, 1000]}) # capacity, fixed costs
65  c = {(1, 1): 4, (1, 2): 6, (1, 3): 9, # transportation costs
66  (2, 1): 5, (2, 2): 4, (2, 3): 7,
67  (3, 1): 6, (3, 2): 3, (3, 3): 4,
68  (4, 1): 8, (4, 2): 5, (4, 3): 3,
69  (5, 1): 10, (5, 2): 8, (5, 3): 4,
70  }
71  return I, J, d, M, f, c
72 
73 
74 if __name__ == "__main__":
75  I, J, d, M, f, c = make_data()
76  master, subprob = flp(I, J, d, M, f, c)
77  # initializing the default Benders' decomposition with the subproblem
78  master.setPresolve(SCIP_PARAMSETTING.OFF)
79  master.setBoolParam("misc/allowstrongdualreds", False)
80  master.setBoolParam("benders/copybenders", False)
81  master.initBendersDefault(subprob)
82 
83  # optimizing the problem using Benders' decomposition
84  master.optimize()
85 
86  # solving the subproblems to get the best solution
87  master.computeBestSolSubproblems()
88 
89  EPS = 1.e-6
90  y = master.data
91  facilities = [j for j in y if master.getVal(y[j]) > EPS]
92 
93  x, suby = subprob.data
94  edges = [(i, j) for (i, j) in x if subprob.getVal(x[i, j]) > EPS]
95 
96  print("Optimal value:", master.getObjVal())
97  print("Facilities at nodes:", facilities)
98  print("Edges:", edges)
99 
100  master.printStatistics()
101 
102  # since computeBestSolSubproblems() was called above, we need to free the
103  # subproblems. This must happen after the solution is extracted, otherwise
104  # the solution will be lost
105  master.freeBendersSubproblems()
106 
107  try: # plot the result using networkx and matplotlib
108  import networkx as NX
109  import matplotlib.pyplot as P
110 
111  P.clf()
112  G = NX.Graph()
113 
114  other = [j for j in y if j not in facilities]
115  customers = ["c%s" % i for i in d]
116  G.add_nodes_from(facilities)
117  G.add_nodes_from(other)
118  G.add_nodes_from(customers)
119  for (i, j) in edges:
120  G.add_edge("c%s" % i, j)
121 
122  position = NX.drawing.layout.spring_layout(G)
123  NX.draw(G, position, node_color="y", nodelist=facilities)
124  NX.draw(G, position, node_color="g", nodelist=other)
125  NX.draw(G, position, node_color="b", nodelist=customers)
126  P.show()
127  except ImportError:
128  print("install 'networkx' and 'matplotlib' for plotting")
pyscipopt.expr.quicksum
def quicksum(termlist)
Definition: expr.pxi:357
flp-benders.flp
def flp(I, J, d, M, f, c)
Definition: flp-benders.py:12
flp-benders.make_data
def make_data()
Definition: flp-benders.py:61
pyscipopt.Multidict.multidict
def multidict(D)
Definition: Multidict.py:3
flp
Definition: flp.py:1