PySCIPOpt  4.3.0
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 import pdb
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 
75 if __name__ == "__main__":
76  I,J,d,M,f,c = make_data()
77  master, subprob = flp(I,J,d,M,f,c)
78  # initializing the default Benders' decomposition with the subproblem
79  master.setPresolve(SCIP_PARAMSETTING.OFF)
80  master.setBoolParam("misc/allowstrongdualreds", False)
81  master.setBoolParam("benders/copybenders", False)
82  master.initBendersDefault(subprob)
83 
84  # optimizing the problem using Benders' decomposition
85  master.optimize()
86 
87  # solving the subproblems to get the best solution
88  master.computeBestSolSubproblems()
89 
90  EPS = 1.e-6
91  y = master.data
92  facilities = [j for j in y if master.getVal(y[j]) > EPS]
93 
94  x, suby = subprob.data
95  edges = [(i,j) for (i,j) in x if subprob.getVal(x[i,j]) > EPS]
96 
97  print("Optimal value:", master.getObjVal())
98  print("Facilities at nodes:", facilities)
99  print("Edges:", edges)
100 
101  master.printStatistics()
102 
103  # since computeBestSolSubproblems() was called above, we need to free the
104  # subproblems. This must happen after the solution is extracted, otherwise
105  # the solution will be lost
106  master.freeBendersSubproblems()
107 
108  try: # plot the result using networkx and matplotlib
109  import networkx as NX
110  import matplotlib.pyplot as P
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