changeset 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
files Graph.py RegularGraphTest.py
diffstat 2 files changed, 98 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/Graph.py	Thu Nov 29 20:37:03 2012 -0600
+++ b/Graph.py	Sat Dec 01 16:51:39 2012 -0600
@@ -9,6 +9,11 @@
 import itertools
 
 
+class GraphError(Exception):
+    """Exception for Graph errors"""
+    pass
+
+
 class Vertex(object):
     """A Vertex is a node in a graph."""
 
@@ -117,20 +122,76 @@
 
         return self[v].values()
 
+    def remove_all_edges(self):
+        """Removes all edges in the graph."""
+        for v in self.iterkeys():
+            self[v] = {}
+
     def add_all_edges(self):
         """Makes the graph complete by adding edges between all pairs of
         vertices.
 
         """
         # Clear all edges first
-        for v in self.iterkeys():
-            self[v] = {}
+        self.remove_all_edges()
 
+        # For each combination of 2 vertices, create an edge between them:
         for v, w in itertools.combinations(self.iterkeys(), 2):
             e = Edge(v, w)
             self[v][w] = e
             self[w][v] = e
 
+    def add_regular_edges(self, k):
+        """Makes the graph regular by making every vertex have k edges.
+
+        It is not always possible to create a regular graph with a given degree.
+        If a graph has n vertices, then a regular graph can be constructed with
+        degree k if n >= k + 1 and n * k is even. If these conditions are not
+        met a GraphError exception is raised.
+
+        """
+        n = len(self.vertices())
+        if n < k + 1:
+            raise GraphError("Can't make a regular graph with degree >= number"
+                             " of vertices")
+        if (n * k) % 2 != 0:
+            raise GraphError("Can't make a regular graph of degree k and"
+                             " order n where k * n is odd")
+
+        # Remove all edges first
+        self.remove_all_edges()
+
+        if k % 2 != 0:      # if k is odd
+            self._add_regular_edges_even(k - 1)
+            self._add_regular_edges_odd()
+        else:
+            self._add_regular_edges_even(k)
+
+    def _add_regular_edges_even(self, k):
+        """Make a regular graph with degree k. k must be even."""
+
+        vs = self.vertices()
+        vs2 = vs * 2
+
+        for i, v in enumerate(vs):
+            for j in range(1, k / 2 + 1):
+                w = vs2[i + j]
+                self.add_edge(Edge(v, w))
+
+    def _add_regular_edges_odd(self):
+        """Adds an extra edge across the graph to finish off a regular graph
+        with odd degree. The number of vertices must be even.
+
+        """
+        vs = self.vertices()
+        vs2 = vs * 2
+        n = len(vs)
+
+        for i in range(n / 2):
+            v = vs2[i]
+            w = vs2[i + n / 2]
+            self.add_edge(Edge(v, w))
+
 
 def main(script, *args):
     import pprint
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RegularGraphTest.py	Sat Dec 01 16:51:39 2012 -0600
@@ -0,0 +1,35 @@
+"""Tests our regular graph making abilities by displaying examples.
+
+"""
+import string
+
+from Graph import Vertex, Graph, GraphError
+from GraphWorld import GraphWorld, CircleLayout
+
+def main(script_name, n, k):
+
+    # Attempt to create a regular graph of order n and degree k
+
+    n, k = int(n), int(k)
+
+    labels = string.ascii_lowercase + string.ascii_uppercase
+    vs = [Vertex(c) for c in labels[:n]]
+
+    # create graph and layout
+    g = Graph(vs)
+    g.add_regular_edges(k)
+    layout = CircleLayout(g)
+
+    # draw the graph
+
+    gw = GraphWorld()
+    gw.show_graph(g, layout)
+    gw.mainloop()
+
+
+if __name__ == '__main__':
+    import sys
+    try:
+        main(*sys.argv)
+    except GraphError, ex:
+        sys.stderr.write("GraphError: {}\n".format(ex))