USING: help.markup help.syntax ;
IN: path-finding
+{ <astar> <bfs> } related-words
+
HELP: astar
{ $description "This tuple must be subclassed and its method " { $link cost } ", "
{ $link heuristic } ", and " { $link neighbours } " must be implemented. "
"may not be as efficient as subclassing the " { $link astar } " tuple."
} ;
+HELP: <bfs>
+{ $values
+ { "neighbours" "an assoc" }
+ { "astar" "a astar tuple" }
+}
+{ $description "Build an astar object from the " { $snippet "neighbours" } " assoc. "
+ "When used with " { $link find-path } ", this astar tuple will use the breadth-first search (BFS) "
+ "path finding algorithm which is a particular case of the general A* algorithm."
+} ;
+
HELP: find-path
{ $values
{ "start" "a node" }
"which have been examined during the A* exploration."
} ;
-ARTICLE: "astar" "A* algorithm"
-"The " { $vocab-link "path-finding" } " vocabulary implements a graph search algorithm for finding the least-cost path from one node to another." $nl
-"The " { $link astar } " tuple may be derived from and its " { $link cost } ", " { $link heuristic } ", and " { $link neighbours } " methods overwritten, or the " { $link <astar> } " word can be used to build such an object from quotations." $nl
+ARTICLE: "path-finding" "Path finding using the A* algorithm"
+"The " { $vocab-link "path-finding" } " vocabulary implements a graph search algorithm for finding the least-cost path from one node to another using the A* algorithm." $nl
+"The " { $link astar } " tuple may be derived from and its " { $link cost } ", " { $link heuristic } ", and " { $link neighbours } " methods overwritten, or the " { $link <astar> } " or " { $link <bfs> } " words can be used to build a new tuple." $nl
"Make an A* object:"
-{ $subsections <astar> }
+{ $subsections <astar> <bfs> }
"Find a path between nodes:"
{ $subsections find-path } ;
-ABOUT: "astar"
+ABOUT: "path-finding"
! Copyright (C) 2010 Samuel Tardieu.
! See http://factorcode.org/license.txt for BSD license.
USING: arrays assocs combinators hashtables kernel literals math math.functions
-math.vectors path-finding sequences sorting splitting strings tools.test ;
+math.vectors memoize path-finding sequences sorting splitting strings tools.test ;
IN: path-finding.tests
! Use a 10x9 maze (see below) to try to go from s to e, f or g.
! In this version, we will use the quotations-aware version through <astar>.
+MEMO: routes ( -- hash ) $[ { "ABD" "BC" "C" "DCE" "ECF" } [ unclip swap 2array ] map >hashtable ] ;
+
: n ( pos -- neighbours )
- $[ { "ABD" "BC" "C" "DCE" "ECF" } [ unclip swap 2array ] map >hashtable ] at ;
+ routes at ;
: c ( from to -- cost )
"" 2sequence H{ { "AB" 1 } { "AD" 2 } { "BC" 5 } { "DC" 2 } { "DE" 1 } { "EC" 2 } { "EF" 1 } } at ;
! No path from D to B -- all nodes reachable from D must have been examined
[ f "CDEF" ] [ "DB" test2 ] unit-test
+
+! Find a path using BFS. There are no path from F to A, and the path from D to
+! C does not include any other node.
+
+[ f ] [ "FA" first2 routes <bfs> find-path ] unit-test
+[ "DC" ] [ "DC" first2 routes <bfs> find-path >string ] unit-test
M: astar-simple heuristic heuristic>> call( n1 n2 -- c ) ;
M: astar-simple neighbours neighbours>> call( n -- neighbours ) ;
+TUPLE: bfs < astar neighbours ;
+M: bfs cost 3drop 1 ;
+M: bfs heuristic 3drop 0 ;
+M: bfs neighbours neighbours>> at ;
+
PRIVATE>
: find-path ( start target astar -- path/f )
: considered ( astar -- considered )
in-closed-set>> members ;
+
+: <bfs> ( neighbours -- astar )
+ [ bfs new ] dip >>neighbours ;