Subversion Repositories programming

Rev

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