Subversion Repositories programming

Rev

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