Mercurial > public > think_complexity
comparison Graph.py @ 5:8e44660965ef
Completed chapter 2, exercise 3 on regular graphs.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Sat, 01 Dec 2012 16:51:39 -0600 |
parents | 9d0cf96b6a3b |
children | 950a34c7e26b |
comparison
equal
deleted
inserted
replaced
4:9d0cf96b6a3b | 5:8e44660965ef |
---|---|
5 | 5 |
6 Copyright 2011 Allen B. Downey. | 6 Copyright 2011 Allen B. Downey. |
7 Distributed under the GNU General Public License at gnu.org/licenses/gpl.html. | 7 Distributed under the GNU General Public License at gnu.org/licenses/gpl.html. |
8 """ | 8 """ |
9 import itertools | 9 import itertools |
10 | |
11 | |
12 class GraphError(Exception): | |
13 """Exception for Graph errors""" | |
14 pass | |
10 | 15 |
11 | 16 |
12 class Vertex(object): | 17 class Vertex(object): |
13 """A Vertex is a node in a graph.""" | 18 """A Vertex is a node in a graph.""" |
14 | 19 |
115 def out_edges(self, v): | 120 def out_edges(self, v): |
116 """Returns a list of edges connected to a given vertex v.""" | 121 """Returns a list of edges connected to a given vertex v.""" |
117 | 122 |
118 return self[v].values() | 123 return self[v].values() |
119 | 124 |
125 def remove_all_edges(self): | |
126 """Removes all edges in the graph.""" | |
127 for v in self.iterkeys(): | |
128 self[v] = {} | |
129 | |
120 def add_all_edges(self): | 130 def add_all_edges(self): |
121 """Makes the graph complete by adding edges between all pairs of | 131 """Makes the graph complete by adding edges between all pairs of |
122 vertices. | 132 vertices. |
123 | 133 |
124 """ | 134 """ |
125 # Clear all edges first | 135 # Clear all edges first |
126 for v in self.iterkeys(): | 136 self.remove_all_edges() |
127 self[v] = {} | 137 |
128 | 138 # For each combination of 2 vertices, create an edge between them: |
129 for v, w in itertools.combinations(self.iterkeys(), 2): | 139 for v, w in itertools.combinations(self.iterkeys(), 2): |
130 e = Edge(v, w) | 140 e = Edge(v, w) |
131 self[v][w] = e | 141 self[v][w] = e |
132 self[w][v] = e | 142 self[w][v] = e |
143 | |
144 def add_regular_edges(self, k): | |
145 """Makes the graph regular by making every vertex have k edges. | |
146 | |
147 It is not always possible to create a regular graph with a given degree. | |
148 If a graph has n vertices, then a regular graph can be constructed with | |
149 degree k if n >= k + 1 and n * k is even. If these conditions are not | |
150 met a GraphError exception is raised. | |
151 | |
152 """ | |
153 n = len(self.vertices()) | |
154 if n < k + 1: | |
155 raise GraphError("Can't make a regular graph with degree >= number" | |
156 " of vertices") | |
157 if (n * k) % 2 != 0: | |
158 raise GraphError("Can't make a regular graph of degree k and" | |
159 " order n where k * n is odd") | |
160 | |
161 # Remove all edges first | |
162 self.remove_all_edges() | |
163 | |
164 if k % 2 != 0: # if k is odd | |
165 self._add_regular_edges_even(k - 1) | |
166 self._add_regular_edges_odd() | |
167 else: | |
168 self._add_regular_edges_even(k) | |
169 | |
170 def _add_regular_edges_even(self, k): | |
171 """Make a regular graph with degree k. k must be even.""" | |
172 | |
173 vs = self.vertices() | |
174 vs2 = vs * 2 | |
175 | |
176 for i, v in enumerate(vs): | |
177 for j in range(1, k / 2 + 1): | |
178 w = vs2[i + j] | |
179 self.add_edge(Edge(v, w)) | |
180 | |
181 def _add_regular_edges_odd(self): | |
182 """Adds an extra edge across the graph to finish off a regular graph | |
183 with odd degree. The number of vertices must be even. | |
184 | |
185 """ | |
186 vs = self.vertices() | |
187 vs2 = vs * 2 | |
188 n = len(vs) | |
189 | |
190 for i in range(n / 2): | |
191 v = vs2[i] | |
192 w = vs2[i + n / 2] | |
193 self.add_edge(Edge(v, w)) | |
133 | 194 |
134 | 195 |
135 def main(script, *args): | 196 def main(script, *args): |
136 import pprint | 197 import pprint |
137 | 198 |