Subversion Repositories programming

Rev

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
 
88
			for node in M:
89
				if (node not in OPEN) and (node not in CLOSED):
90
					OPEN.append (node)
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)
102
 
103
			counter += 1
104
 
105
		return 'FAILURE'
106
 
107
def add_bfs (M, OPEN, CLOSED):
108
	for node in M:
109
		if (node not in OPEN) and (node not in CLOSED):
110
			OPEN.append (node)
111
 
112
def add_dfs (M, OPEN, CLOSED):
113
	for node in M:
114
		if (node not in OPEN) and (node not in CLOSED):
115
			OPEN.insert (0, node) # insert node at beginning
116
 
117
 
118
from Graph import Graph
119
from DrawGraph import DrawGraph
120
 
121
def main ():
122
	#vertices = [0, 1, 2, 3, 'goal']
123
	#edges = ( [0,1], [1,2], [2,3], [3,'goal'] )
124
 
125
	#vertices = [0, 1, 2, 3, 'goal']
126
	#edges = ( [0,1], [0,2], [2,3], [2,'goal'] )
127
 
128
	vertices = [0, 1, 2, 3, 5, 6, 7, 8, 'g1', 'g2']
129
	edges = ( [0,1], [0,2], [0,8], [2,3], [2,'g2'], [1,5], [1,6], [6,7], [7,'g1'] )
130
 
131
	g = Graph (vertices, edges)
132
	s = GraphSearch (g, 0, ['g1', 'g2'])
133
	result = s.search ()
134
 
135
	if result != 'FAILURE':
136
		DrawGraph ('result', result).render_graph ('res.svg') #result.vertices, result.edges.keys ()).render_graph ('res.svg')
137
 
138
 
139
if __name__ == '__main__':
140
	main ()