PySCIPOpt  5.1.1
Python Interface for the SCIP Optimization Suite
kmedian.py
Go to the documentation of this file.
1 
3 """
4 minimize the total (weighted) travel cost for servicing
5 a set of customers from k facilities.
6 
7 Copyright (c) by Joao Pedro PEDROSO and Mikio KUBO, 2012
8 """
9 import math
10 import random
11 
12 from pyscipopt import Model, quicksum
13 
14 
15 def kmedian(I, J, c, k):
16  """kmedian -- minimize total cost of servicing customers from k facilities
17  Parameters:
18  - I: set of customers
19  - J: set of potential facilities
20  - c[i,j]: cost of servicing customer i from facility j
21  - k: number of facilities to be used
22  Returns a model, ready to be solved.
23  """
24 
25  model = Model("k-median")
26  x, y = {}, {}
27 
28  for j in J:
29  y[j] = model.addVar(vtype="B", name="y(%s)" % j)
30  for i in I:
31  x[i, j] = model.addVar(vtype="B", name="x(%s,%s)" % (i, j))
32 
33  for i in I:
34  model.addCons(quicksum(x[i, j] for j in J) == 1, "Assign(%s)" % i)
35  for j in J:
36  model.addCons(x[i, j] <= y[j], "Strong(%s,%s)" % (i, j))
37  model.addCons(quicksum(y[j] for j in J) == k, "Facilities")
38 
39  model.setObjective(quicksum(c[i, j] * x[i, j] for i in I for j in J), "minimize")
40  model.data = x, y
41 
42  return model
43 
44 
45 def distance(x1, y1, x2, y2):
46  """return distance of two points"""
47  return math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
48 
49 
50 def make_data(n, m, same=True):
51  """creates example data set"""
52  if same == True:
53  I = range(n)
54  J = range(m)
55  x = [random.random() for i in range(max(m, n))] # positions of the points in the plane
56  y = [random.random() for i in range(max(m, n))]
57  else:
58  I = range(n)
59  J = range(n, n + m)
60  x = [random.random() for i in range(n + m)] # positions of the points in the plane
61  y = [random.random() for i in range(n + m)]
62  c = {}
63  for i in I:
64  for j in J:
65  c[i, j] = distance(x[i], y[i], x[j], y[j])
66 
67  return I, J, c, x, y
68 
69 
70 if __name__ == "__main__":
71 
72  random.seed(67)
73  n = 200
74  m = n
75  I, J, c, x_pos, y_pos = make_data(n, m, same=True)
76  k = 20
77  model = kmedian(I, J, c, k)
78  # model.Params.Threads = 1
79  model.optimize()
80  EPS = 1.e-6
81  x, y = model.data
82  edges = [(i, j) for (i, j) in x if model.getVal(x[i, j]) > EPS]
83  facilities = [j for j in y if model.getVal(y[j]) > EPS]
84 
85  print("Optimal value:", model.getObjVal())
86  print("Selected facilities:", facilities)
87  print("Edges:", edges)
88  print("max c:", max([c[i, j] for (i, j) in edges]))
89 
90  try: # plot the result using networkx and matplotlib
91  import networkx as NX
92  import matplotlib.pyplot as P
93 
94  P.clf()
95  G = NX.Graph()
96 
97  facilities = set(j for j in J if model.getVal(y[j]) > EPS)
98  other = set(j for j in J if j not in facilities)
99  client = set(i for i in I if i not in facilities and i not in other)
100  G.add_nodes_from(facilities)
101  G.add_nodes_from(client)
102  G.add_nodes_from(other)
103  for (i, j) in edges:
104  G.add_edge(i, j)
105 
106  position = {}
107  for i in range(len(x_pos)):
108  position[i] = (x_pos[i], y_pos[i])
109 
110  NX.draw(G, position, with_labels=False, node_color="w", nodelist=facilities)
111  NX.draw(G, position, with_labels=False, node_color="c", nodelist=other, node_size=50)
112  NX.draw(G, position, with_labels=False, node_color="g", nodelist=client, node_size=50)
113  P.show()
114  except ImportError:
115  print("install 'networkx' and 'matplotlib' for plotting")
pyscipopt.expr.quicksum
def quicksum(termlist)
Definition: expr.pxi:357
kmedian.distance
def distance(x1, y1, x2, y2)
Definition: kmedian.py:45
kmedian.make_data
def make_data(n, m, same=True)
Definition: kmedian.py:50
kmedian.kmedian
def kmedian(I, J, c, k)
Definition: kmedian.py:15
set
kmedian
Definition: kmedian.py:1