@@ -20,16 +20,16 @@ import qualified Data.Set as Set
2020import qualified Data.List as List
2121
2222
23- -- | @bfs next solved prunes initial@ performs a breadth-first search over a set
23+ -- | @bfs next prunes found initial@ performs a breadth-first search over a set
2424-- of states, starting with @initial@, generating neighboring states with
2525-- @next@, and pruning out any state for which a function in @prunes@ returns
26- -- 'True'. It returns a path to a state for which @solved @ returns 'True'.
26+ -- 'True'. It returns a path to a state for which @found @ returns 'True'.
2727-- Returns 'Nothing' if no path is possible.
2828--
2929-- === Example: Making change problem
3030--
3131-- >>> :{
32- -- countChange target = bfs add_one_coin (== target) [(> target)] 0
32+ -- countChange target = bfs add_one_coin [(> target)] (== target) 0
3333-- where
3434-- add_one_coin amt = map (+ amt) coins
3535-- coins = [25, 10, 5, 1]
@@ -40,12 +40,12 @@ import qualified Data.List as List
4040bfs :: Ord state =>
4141 (state -> [state ])
4242 -- ^ Function to generate "next" states given a current state
43- -> (state -> Bool )
44- -- ^ Predicate to determine if solution found. 'bfs' returns a path to the
45- -- first state for which this predicate returns 'True'.
4643 -> [state -> Bool ]
4744 -- ^ List of ways to prune search. These are predicates which, if 'True', are
4845 -- considered to indicate a "dead end".
46+ -> (state -> Bool )
47+ -- ^ Predicate to determine if solution found. 'bfs' returns a path to the
48+ -- first state for which this predicate returns 'True'.
4949 -> state
5050 -- ^ Initial state
5151 -> Maybe [state ]
@@ -57,10 +57,10 @@ bfs =
5757 generalizedSearch Seq. empty id (\ _ _ -> False )
5858
5959
60- -- | @dfs next solved prunes initial@ performs a depth-first search over a set
60+ -- | @dfs next prunes found initial@ performs a depth-first search over a set
6161-- of states, starting with @initial@, generating neighboring states with
6262-- @next@, and pruning out any state for which a function in @prunes@ returns
63- -- 'True'. It returns a depth-first path to a state for which @solved @
63+ -- 'True'. It returns a depth-first path to a state for which @found @
6464-- returns 'True'. Returns 'Nothing' if no path is possible.
6565--
6666-- === Example: Simple directed graph search
@@ -69,17 +69,17 @@ bfs =
6969--
7070-- >>> graph = Map.fromList [(1, [2, 3]), (2, [4]), (3, [4]), (4, [])]
7171--
72- -- >>> dfs (graph Map.!) (== 4) [] 1
72+ -- >>> dfs (graph Map.!) [] (== 4) 1
7373-- Just [3,4]
7474dfs :: Ord state =>
7575 (state -> [state ])
7676 -- ^ Function to generate "next" states given a current state
77- -> (state -> Bool )
78- -- ^ Predicate to determine if solution found. 'dfs' returns a path to the
79- -- first state for which this predicate returns 'True'.
8077 -> [state -> Bool ]
8178 -- ^ List of ways to prune search. These are predicates which, if 'True', are
8279 -- considered to indicate a "dead end".
80+ -> (state -> Bool )
81+ -- ^ Predicate to determine if solution found. 'dfs' returns a path to the
82+ -- first state for which this predicate returns 'True'.
8383 -> state
8484 -- ^ Initial state
8585 -> Maybe [state ]
@@ -91,20 +91,20 @@ dfs =
9191 generalizedSearch [] id (\ _ _ -> True )
9292
9393
94- -- | @dijkstra next solved prunes initial@ performs a shortest-path search over
94+ -- | @dijkstra next prunes found initial@ performs a shortest-path search over
9595-- a set of states using Dijkstra's algorithm, starting with @initial@,
9696-- generating neighboring states and their incremental costs with @next@, and
9797-- pruning out any state for which a function in @prunes@ returns 'True'.
9898-- This will find the least-costly path from an initial state to a state for
99- -- which @solved @ returns 'True'. Returns 'Nothing' if no path to a solved state
99+ -- which @found @ returns 'True'. Returns 'Nothing' if no path to a solved state
100100-- is possible.
101101--
102102-- === Example: Making change problem, with a twist
103103--
104104-- >>> :{
105105-- -- Twist: dimes have a face value of 10 cents, but are actually rare
106106-- -- misprints which are worth 10 dollars
107- -- countChange target = dijkstra add_one_coin (== target) [(> target)] 0
107+ -- countChange target = dijkstra add_one_coin [(> target)] (== target) 0
108108-- where
109109-- add_one_coin amt =
110110-- map (\(true_val, face_val) -> (true_val, face_val + amt)) coin_values
@@ -117,27 +117,27 @@ dijkstra :: (Num cost, Ord cost, Ord state) =>
117117 (state -> [(cost , state )])
118118 -- ^ Function to generate list of incremental cost and neighboring states
119119 -- given the current state
120- -> (state -> Bool )
121- -- ^ Predicate to determine if solution found. 'dijkstra' returns the shortest
122- -- path to the first state for which this predicate returns 'True'.
123120 -> [state -> Bool ]
124121 -- ^ List of ways to prune search. These are predicates which, if 'True', are
125122 -- considered to indicate a "dead end".
123+ -> (state -> Bool )
124+ -- ^ Predicate to determine if solution found. 'dijkstra' returns the shortest
125+ -- path to the first state for which this predicate returns 'True'.
126126 -> state
127127 -- ^ Initial state
128128 -> Maybe (cost , [(cost , state )])
129129 -- (Total cost, [(incremental cost, step)]) for the first path found which
130130 -- satisfies the given predicate
131- dijkstra next solved prunes initial =
131+ dijkstra next prunes found initial =
132132 -- Dijkstra's algorithm can be viewed as a generalized search, with the search
133133 -- container being a heap, with the states being compared without regard to
134134 -- cost, with the shorter paths taking precedence over longer ones, and with
135135 -- the stored state being (cost so far, state).
136136 -- This implementation makes that transformation, then transforms that result
137137 -- back into the desired result from @dijkstra@
138138 unpack <$>
139- generalizedSearch emptyLIFOHeap snd better next' (solved . snd )
140- (map ( . snd ) prunes ) (0 , initial)
139+ generalizedSearch emptyLIFOHeap snd better next' (map ( . snd ) prunes )
140+ (found . snd ) (0 , initial)
141141 where
142142 next' (cost, st) = map (\ (incr, new_st) -> (incr + cost, new_st)) (next st)
143143 unpack packed_states =
@@ -154,14 +154,14 @@ dijkstra next solved prunes initial =
154154 -- a new zero-length path to a point
155155
156156
157- -- | @aStar next solved prunes initial@ performs a best-first search using
157+ -- | @aStar next prunes found initial@ performs a best-first search using
158158-- the A* search algorithm, starting with the state @initial@, generating
159159-- neighboring states, their cost, and an estimate of the remaining cost with
160160-- @next@, and pruning out any state for which a function in @prunes@ returns
161- -- 'True'. This returns a path to a state for which @solved @ returns 'True'.
161+ -- 'True'. This returns a path to a state for which @found @ returns 'True'.
162162-- If the estimate is strictly a lower bound on the remaining cost to reach a
163- -- @ solved@ state, then the returned path is the shortest path. Returns
164- -- 'Nothing' if no path to a @ solved@ state is possible.
163+ -- solved state, then the returned path is the shortest path. Returns
164+ -- 'Nothing' if no path to a solved state is possible.
165165--
166166-- === Example: Path finding in taxicab geometry
167167--
@@ -171,32 +171,32 @@ dijkstra next solved prunes initial =
171171-- nextTowards dest pos = map (\p -> (1, dist p dest, p)) (neighbors pos)
172172-- :}
173173--
174- -- >>> aStar (nextTowards (0, 2)) (== (0, 2)) [ (== (0, 1))] (0, 0)
174+ -- >>> aStar (nextTowards (0, 2)) [ (== (0, 1))] (== (0, 2)) (0, 0)
175175-- Just (4,[(1,(1,0)),(1,(1,1)),(1,(1,2)),(1,(0,2))])
176176aStar :: (Num cost , Ord cost , Ord state ) =>
177177 (state -> [(cost , cost , state )])
178178 -- ^ Function which, when given the current state, produces a list whose
179179 -- elements are (incremental cost to reach neighboring state,
180180 -- estimate on remaining cost from said state, said state).
181- -> (state -> Bool )
182- -- ^ Predicate to determine if solution found. 'aStar' returns the shortest
183- -- path to the first state for which this predicate returns 'True'.
184181 -> [state -> Bool ]
185182 -- ^ List of ways to prune search. These are predicates which, if 'True', are
186183 -- considered to indicate a "dead end".
184+ -> (state -> Bool )
185+ -- ^ Predicate to determine if solution found. 'aStar' returns the shortest
186+ -- path to the first state for which this predicate returns 'True'.
187187 -> state
188188 -- ^ Initial state
189189 -> Maybe (cost , [(cost , state )])
190190 -- (Total cost, [(incremental cost, step)]) for the first path found which
191191 -- satisfies the given predicate
192- aStar next found prunes initial =
192+ aStar next prunes found initial =
193193 -- The idea of this implementation is that we can use the same machinery as
194194 -- Dijkstra's algorithm, by changing Dijsktra's cost function to be
195195 -- (incremental cost + lower bound remaining cost). We'd still like to be able
196196 -- to return the list of incremental costs, so we modify the internal state to
197197 -- be (incremental cost to state, state). Then at the end we undo this
198198 -- transformation
199- unpack <$> dijkstra next' (found . snd ) ( map ( . snd ) prunes ) (0 , initial)
199+ unpack <$> dijkstra next' (map ( . snd ) prunes) (found . snd ) (0 , initial)
200200 where
201201 next' (_, st) = map pack (next st)
202202 pack (incr, est, new_st) = (incr + est, (incr, new_st))
@@ -274,21 +274,21 @@ generalizedSearch :: (SearchContainer container state, Ord stateKey) =>
274274 -- old and should thus be inserted
275275 -> (state -> [state ])
276276 -- ^ Function to generate "next" states given a current state
277- -> (state -> Bool )
278- -- ^ Predicate to determine if solution found. 'search' returns a path to the
279- -- first state for which this predicate returns 'True'.
280277 -> [state -> Bool ]
281278 -- ^ List of ways to prune search. These are predicates which, if 'True', are
282279 -- considered to indicate a "dead end".
280+ -> (state -> Bool )
281+ -- ^ Predicate to determine if solution found. 'search' returns a path to the
282+ -- first state for which this predicate returns 'True'.
283283 -> state
284284 -- ^ Initial state
285285 -> Maybe [state ]
286286 -- ^ First path found to a state matching the predicate, or 'Nothing' if no
287287 -- such path exists.
288- generalizedSearch empty mk_key better next solved prunes initial =
288+ generalizedSearch empty mk_key better next prunes found initial =
289289 let get_steps search_st = paths search_st Map. ! mk_key (current search_st)
290290 in fmap (reverse . get_steps)
291- . findIterate (solved . current) ( nextSearchState better mk_key next prunes)
291+ . findIterate (nextSearchState better mk_key next prunes) (found . current )
292292 $ SearchState initial empty (Set. singleton $ mk_key initial)
293293 (Map. singleton (mk_key initial) [] )
294294
@@ -330,7 +330,7 @@ instance Ord k => SearchContainer (LIFOHeap k a) (k, a) where
330330
331331-- | @findIterate found next initial@ takes an initial seed value and applies
332332-- @next@ to it until either @found@ returns True or @next@ returns @Nothing@
333- findIterate :: (a -> Bool ) -> (a -> Maybe a ) -> a -> Maybe a
334- findIterate found next initial
333+ findIterate :: (a -> Maybe a ) -> (a -> Bool ) -> a -> Maybe a
334+ findIterate next found initial
335335 | found initial = Just initial
336- | otherwise = next initial >>= findIterate found next
336+ | otherwise = next initial >>= findIterate next found
0 commit comments