Subversion Repositories programming

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
376 ira 1
#!/usr/bin/env python
2
 
3
__author__    = "Ira W. Snyder (devel@irasnyder.com)"
4
__copyright__ = "Copyright (c) 2006 Ira W. Snyder (devel@irasnyder.com)"
5
__license__   = "GNU GPL v2 (or, at your option, any later version)"
6
 
379 ira 7
class Edge (object):
8
	def __init__ (self, color='black', label=''):
9
		self.color = color
10
		self.label = label
11
 
376 ira 12
class Graph:
13
	"""Class that will handle weighted, undirected graphs. It can have
14
	   arbitrary data stored at each vertex. Note that the simple way
15
	   of creating a graph does not allow you to assign data, you must
16
	   do it manually."""
17
 
18
	def __init__ (self, vertices=[], edges=[]):
19
		"""Constructor"""
20
		self.vertices = {}
21
		self.edges = {}
22
 
23
		for v in vertices:
24
			self.add_vertex (v)
25
 
26
		for e in edges:
27
			(v1, v2) = e
28
			self.add_edge (v1, v2)
29
 
30
	def __get_key (self, v1, v2):
31
		"""Create a key for this set of nodes"""
32
		key = [v1, v2]
33
		key.sort ()
34
		return tuple (key)
35
 
36
	def add_vertex (self, label, data=0):
37
		"""Add a vertex to the graph"""
38
		if self.has_vertex (label):
39
			raise ValueError
40
 
41
		# Create vertex and set the value
379 ira 42
		self.set_vertex_value (label, data)
376 ira 43
 
379 ira 44
	def add_edge (self, v1, v2, color='black', label=''):
376 ira 45
		"""Add an edge from v1 to v2 (undirected)"""
46
 
47
		key = self.__get_key (v1, v2)
48
 
49
		if self.has_vertex (v1) and self.has_vertex (v2):
379 ira 50
			self.edges[key] = Edge (color, label)
376 ira 51
		else:
52
			raise ValueError
53
 
54
	def has_edge (self, v1, v2):
55
		"""Check if an edge exists in this graph"""
56
 
57
		key = self.__get_key (v1, v2)
58
 
59
		if key in self.edges.keys():
60
			return True
61
 
62
		return False
63
 
64
	def has_vertex (self, label):
65
		"""Check if a vertex exists in this graph"""
66
		return label in self.vertices.keys ()
67
 
68
	def get_children (self, v):
69
		"""Get a list of all children of v. In this graph, that
70
		   means any adjacent nodes."""
71
		children = set()
72
 
73
		# Check that the vertex exists
74
		if not self.has_vertex (v):
75
			raise ValueError
76
 
77
		for k in self.edges.keys ():
78
			if v in k:
79
				for i in k:
80
					if i != v:
81
						children.add (i)
82
 
83
		return list(children)
84
 
379 ira 85
	def set_vertex_value (self, v, data):
376 ira 86
		"""Store some data at a vertex"""
87
		self.vertices[v] = data
88
 
379 ira 89
	def get_vertex_value (self, v):
376 ira 90
		"""Get the data at a vertex"""
91
		return self.vertices[v]
92
 
379 ira 93
	def set_edge_color (self, v1, v2, color):
94
		if not self.has_edge (v1, v2):
95
			raise ValueError
376 ira 96
 
379 ira 97
		key = self.__get_key (v1, v2)
98
		self.edges[key].color = color
99
 
100
	def get_edge_color (self, v1, v2):
101
		if not self.has_edge (v1, v2):
102
			raise ValueError
103
 
104
		key = self.__get_key (v1, v2)
105
		return self.edges[key].color
106
 
107
	def get_edge_label (self, v1, v2):
108
		if not self.has_edge (v1, v2):
109
			raise ValueError
110
 
111
		key = self.__get_key (v1, v2)
112
		return self.edges[key].label
113
 
114
	def set_edge_label (self, v1, v2, label):
115
		if not self.has_edge (v1, v2):
116
			raise ValueError
117
 
118
		key = self.__get_key (v1, v2)
119
		self.edges[key].label = label
120
 
121
 
376 ira 122
################################################################################
123
###                      Tests are below this point                          ###
124
################################################################################
125
 
126
 
127
def run_test (graph, vertex, should_be, suite, test_num):
128
	"""Run a test, check the result. Print the status."""
129
	c = graph.get_children (vertex)
130
	c.sort ()
131
 
132
	if (c != should_be):
133
		print 'Failed test #%d in suite: %s' % (test_num, suite)
134
 
135
def run_tests_1 ():
136
	"""Run the first set of tests."""
137
	SUITE = 'Tests 1'
138
 
139
	vertices = range (11)
140
	edges = ( [0, 1], [0, 9], [0, 8], [8, 10], [8, 7], [9, 6], [9, 5],
141
			[6, 7], [1, 4], [1, 3], [1, 2], [2, 0] )
142
 
143
	g = Graph (vertices, edges)
144
 
145
	run_test (g, 0, [1, 2, 8, 9], SUITE, 0)
146
	run_test (g, 1, [0, 2, 3, 4], SUITE, 1)
147
	run_test (g, 2, [0, 1], SUITE, 2)
148
	run_test (g, 3, [1], SUITE, 3)
149
	run_test (g, 4, [1], SUITE, 4)
150
	run_test (g, 5, [9], SUITE ,5)
151
	run_test (g, 6, [7, 9], SUITE, 6)
152
	run_test (g, 7, [6, 8], SUITE, 7)
153
	run_test (g, 8, [0, 7, 10], SUITE, 8)
154
	run_test (g, 9, [0, 5, 6], SUITE, 9)
155
	run_test (g, 10, [8], SUITE, 10)
156
 
157
def run_tests_2 ():
158
	"""Run the second set of tests."""
159
	SUITE = 'Tests 2'
160
 
161
	vertices = ['a', 'b', 'c', 'd', 'e']
162
	edges = ( ['a', 'b'], ['a', 'c'], ['a', 'd'], ['b', 'a'], ['b', 'c'],
163
			['b', 'e'], ['e', 'b'], ['e', 'c'], ['e', 'd'],
164
			['d', 'a'], ['d', 'c'], ['d', 'e'], ['c', 'a'],
165
			['c', 'b'], ['c', 'd'], ['c', 'e'] )
166
 
167
	g = Graph (vertices, edges)
168
 
169
	run_test (g, 'a', ['b', 'c', 'd'], SUITE, 0)
170
	run_test (g, 'b', ['a', 'c', 'e'], SUITE, 1)
171
	run_test (g, 'c', ['a', 'b', 'd', 'e'], SUITE, 2)
172
	run_test (g, 'd', ['a', 'c', 'e'], SUITE, 3)
173
	run_test (g, 'e', ['b', 'c', 'd'], SUITE, 4)
174
 
175
def main ():
176
	"""Main function."""
177
 
178
	print 'Running self tests. Any failures will be reported below'
179
 
180
	run_tests_1 ()
181
	run_tests_2 ()
182
 
183
 
184
if __name__ == '__main__':
185
	main ()
186