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