Subversion Repositories programming

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
380 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
 
7
# 1) Put the start node N0 on OPEN. Create G with just this node
8
# 2) Create the list CLOSED which is empty
9
#
10
# LOOP:
11
#
12
# 3) If OPEN is empty, exit with FAILURE
13
# 4) Select the first node from OPEN, put it on CLOSED. Call this N
14
# 5) If N is a goal node, exit successfully with the solution in G
15
# 6) Generate M from the children of N
16
# 7) Add anything not in M not in (CLOSED union OPEN) to OPEN
17
# 8) Reorder OPEN appropriately
18
# 9) goto LOOP
19
 
20
from Graph import Graph
21
import yapgvb
22
 
23
class GraphSearch (object):
24
	"""Implements a graph search"""
25
 
26
	def __init__ (self, full_graph, start_node, goal_nodes):
27
		"""Constructor.
28
		full_graph: a Graph representing all the knowledge
29
		start_node: the node to start at (must be in full_graph)
30
		goal_nodes: a list of nodes to end at"""
31
 
32
		self.__kb = full_graph
33
		self.__start_node = start_node
34
		self.__goal_nodes = goal_nodes
35
		self.__ordering_func = list.sort
36
 
37
	def set_ordering_func (self, func):
38
		"""Set the ordering function to use."""
39
		self.__ordering_func = func
40
 
41
	def __find_nearest_child (self, children, already_visited):
42
		"""Find the child that we came from. This necessitates that
43
		the list already_visited be sorted in the order of nodes visited"""
44
		for n in reversed(already_visited):
45
			if n in children:
46
				return n
47
 
48
		# This should never happen
49
		raise ValueError
50
 
51
	def search (self):
52
 
53
		# Create the result graph
54
		result = Graph ()
55
		#result.add_vertex (self.__start_node)
56
		firsttime = True
57
		counter = 0
58
 
59
		OPEN = [self.__start_node]
60
		CLOSED = []
61
 
62
		while OPEN:
63
			N = OPEN.pop(0)
64
			CLOSED.append (N)
65
 
66
			# Find all possible next paths
67
			M = self.__kb.get_children (N)
68
 
69
			# Add the current place to the result graph
70
			result.add_vertex (N)
71
			if not firsttime:
72
				v1 = N
73
				v2 = self.__find_nearest_child (M, CLOSED)
74
 
75
				result.add_edge (v1, v2)
76
				result.set_edge_color (v1, v2, yapgvb.colors.red)
77
				result.set_edge_label (v1, v2, str(counter))
78
 
79
				self.__kb.set_edge_color (v1, v2, 'red')
80
				self.__kb.set_edge_label (v1, v2, str(counter))
81
			else:
82
				firsttime = False
83
 
84
			# Check if we've reached the goal
85
			if N in self.__goal_nodes:
86
				return self.__kb #result
87
 
382 ira 88
			#for node in M:
89
			#	if (node not in OPEN) and (node not in CLOSED):
90
			#		OPEN.append (node)
380 ira 91
 
92
			# Sort OPEN appropriately
93
			# NOTE: no sort algorithm is BFS
94
			#self.__ordering_func (OPEN)
95
 
96
			# FIXME: maybe take the "for node in M" loop and
97
			# FIXME: combine it with the ordering function into
98
			# FIXME: it's own function that chooses how to add
99
			# FIXME: the nodes from M into OPEN
100
			#
101
			# FIXME: prototype might be: func (M, OPEN, CLOSED)
382 ira 102
			#add_dfs (M, OPEN, CLOSED)
103
			OPEN = add_bfs (M, OPEN, CLOSED)
380 ira 104
 
105
			counter += 1
106
 
107
		return 'FAILURE'
108
 
109
def add_bfs (M, OPEN, CLOSED):
110
	for node in M:
111
		if (node not in OPEN) and (node not in CLOSED):
112
			OPEN.append (node)
113
 
382 ira 114
	return OPEN
115
 
380 ira 116
def add_dfs (M, OPEN, CLOSED):
117
	for node in M:
118
		if (node not in OPEN) and (node not in CLOSED):
119
			OPEN.insert (0, node) # insert node at beginning
120
 
382 ira 121
	return OPEN
380 ira 122
 
382 ira 123
 
380 ira 124
from Graph import Graph
125
from DrawGraph import DrawGraph
126
 
127
def main ():
128
	#vertices = [0, 1, 2, 3, 'goal']
129
	#edges = ( [0,1], [1,2], [2,3], [3,'goal'] )
130
 
131
	#vertices = [0, 1, 2, 3, 'goal']
132
	#edges = ( [0,1], [0,2], [2,3], [2,'goal'] )
133
 
134
	vertices = [0, 1, 2, 3, 5, 6, 7, 8, 'g1', 'g2']
135
	edges = ( [0,1], [0,2], [0,8], [2,3], [2,'g2'], [1,5], [1,6], [6,7], [7,'g1'] )
136
 
137
	g = Graph (vertices, edges)
138
	s = GraphSearch (g, 0, ['g1', 'g2'])
139
	result = s.search ()
140
 
141
	if result != 'FAILURE':
142
		DrawGraph ('result', result).render_graph ('res.svg') #result.vertices, result.edges.keys ()).render_graph ('res.svg')
143
 
144
 
145
if __name__ == '__main__':
146
	main ()