Mercurial > public > think_complexity
comparison Graph.py @ 1:de3ae15ebbfa
Exercise 2: created Graph.py.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Thu, 29 Nov 2012 20:06:54 -0600 |
parents | |
children | 9d0cf96b6a3b |
comparison
equal
deleted
inserted
replaced
0:04e3a6590139 | 1:de3ae15ebbfa |
---|---|
1 """ Code example from Complexity and Computation, a book about | |
2 exploring complexity science with Python. Available free from | |
3 | |
4 http://greenteapress.com/complexity | |
5 | |
6 Copyright 2011 Allen B. Downey. | |
7 Distributed under the GNU General Public License at gnu.org/licenses/gpl.html. | |
8 """ | |
9 import itertools | |
10 | |
11 | |
12 class Vertex(object): | |
13 """A Vertex is a node in a graph.""" | |
14 | |
15 def __init__(self, label=''): | |
16 self.label = label | |
17 | |
18 def __repr__(self): | |
19 """Returns a string representation of this object that can | |
20 be evaluated as a Python expression.""" | |
21 return 'Vertex(%s)' % repr(self.label) | |
22 | |
23 __str__ = __repr__ | |
24 """The str and repr forms of this object are the same.""" | |
25 | |
26 | |
27 class Edge(tuple): | |
28 """An Edge is a list of two vertices.""" | |
29 | |
30 def __new__(cls, *vs): | |
31 """The Edge constructor takes two vertices.""" | |
32 if len(vs) != 2: | |
33 raise ValueError, 'Edges must connect exactly two vertices.' | |
34 return tuple.__new__(cls, vs) | |
35 | |
36 def __repr__(self): | |
37 """Return a string representation of this object that can | |
38 be evaluated as a Python expression.""" | |
39 return 'Edge(%s, %s)' % (repr(self[0]), repr(self[1])) | |
40 | |
41 __str__ = __repr__ | |
42 """The str and repr forms of this object are the same.""" | |
43 | |
44 | |
45 class Graph(dict): | |
46 """A Graph is a dictionary of dictionaries. The outer | |
47 dictionary maps from a vertex to an inner dictionary. | |
48 The inner dictionary maps from other vertices to edges. | |
49 | |
50 For vertices a and b, graph[a][b] maps | |
51 to the edge that connects a->b, if it exists.""" | |
52 | |
53 def __init__(self, vs=[], es=[]): | |
54 """Creates a new graph. | |
55 vs: list of vertices; | |
56 es: list of edges. | |
57 """ | |
58 for v in vs: | |
59 self.add_vertex(v) | |
60 | |
61 for e in es: | |
62 self.add_edge(e) | |
63 | |
64 def add_vertex(self, v): | |
65 """Add a vertex to the graph.""" | |
66 self[v] = {} | |
67 | |
68 def add_edge(self, e): | |
69 """Adds and edge to the graph by adding an entry in both directions. | |
70 | |
71 If there is already an edge connecting these Vertices, the | |
72 new edge replaces it. | |
73 """ | |
74 v, w = e | |
75 self[v][w] = e | |
76 self[w][v] = e | |
77 | |
78 def get_edge(self, v, w): | |
79 """Returns the edge object that exists between the two vertices v & w, | |
80 or None if no such edge exists. | |
81 | |
82 """ | |
83 try: | |
84 return self[v][w] | |
85 except KeyError: | |
86 return None | |
87 | |
88 def remove_edge(self, e): | |
89 """Removes the edge e from the graph.""" | |
90 | |
91 for x in self.iterkeys(): | |
92 remove = [k for k, v in self[x].iteritems() if v is e] | |
93 for k in remove: | |
94 del self[x][k] | |
95 | |
96 def vertices(self): | |
97 """Returns a list of the vertices in the graph.""" | |
98 | |
99 return self.keys() | |
100 | |
101 def edges(self): | |
102 """"Returns a list of the edges in the graph.""" | |
103 | |
104 edge_set = set() | |
105 for x in self.iterkeys(): | |
106 for e in self[x].itervalues(): | |
107 edge_set.add(e) | |
108 | |
109 return list(edge_set) | |
110 | |
111 def out_vertices(self, v): | |
112 """Returns a list of vertices that are adjacent to the given vertex v. | |
113 | |
114 """ | |
115 return self[v].keys() | |
116 | |
117 def out_edges(self, v): | |
118 """Returns a list of edges connected to a given vertex v.""" | |
119 | |
120 return self[v].values() | |
121 | |
122 def add_all_edges(self): | |
123 """Makes the graph complete by adding edges between all pairs of | |
124 vertices. | |
125 | |
126 """ | |
127 # Clear all edges first | |
128 for v in self.iterkeys(): | |
129 self[v] = {} | |
130 | |
131 for v, w in itertools.combinations(self.iterkeys(), 2): | |
132 e = Edge(v, w) | |
133 self[v][w] = e | |
134 self[w][v] = e | |
135 | |
136 | |
137 def main(script, *args): | |
138 import pprint | |
139 | |
140 v = Vertex('v') | |
141 print v | |
142 w = Vertex('w') | |
143 print w | |
144 e = Edge(v, w) | |
145 print e | |
146 g = Graph([v,w], [e]) | |
147 pprint.pprint(g) | |
148 | |
149 print "g.get_edge(v, w): ", g.get_edge(v, w) | |
150 x = Vertex('x') | |
151 print "g.get_edge(v, x): ", g.get_edge(v, x) | |
152 | |
153 g.remove_edge(e) | |
154 pprint.pprint(g) | |
155 | |
156 print "vertices: ", g.vertices() | |
157 print "edges: ", g.edges() | |
158 | |
159 g.add_edge(e) | |
160 u = Vertex('u') | |
161 e1 = Edge(u, v) | |
162 e2 = Edge(u, w) | |
163 g.add_vertex(u) | |
164 g.add_edge(e1) | |
165 g.add_edge(e2) | |
166 print "Adding vertex u and edges:" | |
167 pprint.pprint(g) | |
168 print "vertices: ", g.vertices() | |
169 print "edges: ", g.edges() | |
170 | |
171 print "Out vertices for v: ", g.out_vertices(v) | |
172 print "Out edges for v: ", g.out_edges(v) | |
173 | |
174 x = Vertex('x') | |
175 g.add_vertex(x) | |
176 g.add_all_edges() | |
177 pprint.pprint(g) | |
178 | |
179 | |
180 if __name__ == '__main__': | |
181 import sys | |
182 main(*sys.argv) |