comparison SmallWorldGraph.py @ 23:74c9d126bd05

Working on the SmallWorldGraph exercises.
author Brian Neal <bgneal@gmail.com>
date Wed, 02 Jan 2013 16:50:55 -0600
parents
children 5c2c4ce095ef
comparison
equal deleted inserted replaced
22:84e183b40c63 23:74c9d126bd05
1 """This module contains the SmallWorldGraph class for 4.4, exercise 4.
2
3 """
4 import itertools
5 import random
6
7 from Graph import Edge
8 from RandomGraph import RandomGraph
9
10
11 class SmallWorldGraph(RandomGraph):
12 """A small world graph for 4.4, exercise 4 in Think Complexity."""
13
14 def __init__(self, vs, k, p):
15 """Create a small world graph. Parameters:
16 vs - a list of vertices
17 k - regular graph parameter k: the number of edges between vertices
18 p - probability for rewiring.
19
20 First a regular graph is created from the list of vertices and parameter
21 k, which specifies how many edges each vertex should have. Then the
22 rewire() method is called with parameter p to rewire the graph according
23 to the algorithm by Watts and Strogatz.
24
25 """
26 super(SmallWorldGraph, self).__init__(vs=vs)
27 self.add_regular_edges(k)
28 self.rewire(p)
29
30 def rewire(self, p):
31 """Assuming the graph is initially a regular graph, rewires the graph
32 using the Watts and Strogatz algorithm.
33
34 """
35 # We iterate over the edges in a random order:
36 edges = self.edges()
37 random.shuffle(edges)
38 vertices = self.vertices()
39
40 for e in edges:
41 if random.random() < p:
42 v, w = e # remember the 2 vertices this edge connected
43 self.remove_edge(e) # remove from graph
44
45 # pick another vertex to connect to v; duplicate edges are
46 # forbidden
47 while True:
48 x = random.choice(vertices)
49 if v is not x and not self.get_edge(v, x):
50 self.add_edge(Edge(v, x))
51 break
52
53 def clustering_coefficient(self):
54 """Compute the clustering coefficient for this graph as defined by Watts
55 and Strogatz.
56
57 """
58 cv = {}
59 for v in self:
60 # consider a node and its neighbors
61 nodes = self.out_vertices(v)
62 nodes.append(v)
63
64 # compute the maximum number of possible edges between these nodes
65 # if they were all connected to each other:
66 n = len(nodes)
67 if n == 1:
68 # edge case of only 1 node; handle this case to avoid division
69 # by zero in the general case
70 cv[v] = 1.0
71 continue
72
73 possible = n * (n - 1) / 2.0
74
75 # now compute how many edges actually exist between the nodes
76 actual = 0
77 for x, y in itertools.combinations(nodes, 2):
78 if self.get_edge(x, y):
79 actual += 1
80
81 # the fraction of actual / possible is this nodes C sub v value
82 cv[v] = actual / possible
83
84 # The clustering coefficient is the average of all C sub v values
85 if len(cv):
86 return sum(cv.values()) / float(len(cv))
87 return 0.0