<html><head></head><body bgcolor="#FFFFFF"><div>Anton, I think the mapM inside searchBy is incorrect. You're threading state between exploration of different branches, which you I think shouldn't be doing.<br><br><div><br></div></div><div><br>30.10.2011, в 19:44, Anton Kholomiov &lt;<a href="mailto:anton.kholomiov@gmail.com">anton.kholomiov@gmail.com</a>&gt; написал(а):<br><br></div><div></div><blockquote type="cite"><div>I'm misunderstanding astar. I've thought that 'whole route'-heuristic&nbsp;<div>will prevent algorithm from going in circles. The more you circle around</div><div>the more the whole route distance is. Thank you for showing this.&nbsp;</div>
<div>Here is an updated version. searchBy function contains a state.</div><div>State value accumulates visited nodes:</div><div><br></div><div>-- | Heuristic search. Nodes are visited from smaller to greater.</div><div><div>
searchBy :: Ord b =&gt; (a -&gt; b) -&gt; (a -&gt; a -&gt; Ordering) -&gt; Tree a -&gt; [a]</div><div>searchBy f heur t = evalState (searchBy' f heur t) S.empty</div><div><br></div><div>searchBy' :: Ord b&nbsp;</div><div>
&nbsp;&nbsp; &nbsp;=&gt; (a -&gt; b) -&gt; (a -&gt; a -&gt; Ordering) -&gt; Tree a -&gt; State (S.Set b) [a]</div><div>searchBy' f heur (Node v ts) = get &gt;&gt;= phi</div><div>&nbsp;&nbsp; &nbsp;where phi visited</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| S.member (f v) visited = return []</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| otherwise &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;=&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;put (S.insert (f v) visited) &gt;&gt;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(v :) . foldr (mergeBy heur) [] &lt;$&gt;&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mapM (searchBy' f heur) ts</div>
<div><br></div><div>I need to add function&nbsp;Ord b =&gt; (a -&gt; b). It</div><div>converts tree nodes into visited nodes. I'm using it&nbsp;</div><div>for saving distance-values alongside with nodes</div><div>in astar algorithm.</div>
<div><br></div><div>In attachment you can find algorithm with&nbsp;your example.&nbsp;</div><div><br></div><div class="gmail_quote">2011/10/27 Ryan Ingram <span dir="ltr">&lt;<a href="mailto:ryani.spam@gmail.com">ryani.spam@gmail.com</a>&gt;</span><br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">Also, this wasn't clear in my message, but the edges in the graph only go one way; towards the top/right; otherwise the best path is ABCDEHIJ :)<div>
<div></div><div class="h5"><br><br><div class="gmail_quote">On Thu, Oct 27, 2011 at 10:48 AM, Ryan Ingram <span dir="ltr">&lt;<a href="mailto:ryani.spam@gmail.com" target="_blank">ryani.spam@gmail.com</a>&gt;</span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">You're missing one of the key insights from A-star (and simple djikstra, for that matter): once you visit a node, you don't have to visit it again.<br>

<br>Consider a 5x2 2d graph with these edge costs:<br><br><span style="font-family:courier new,monospace">B 1 C 1 D 1 E 9 J<br>
1&nbsp;&nbsp; 1&nbsp;&nbsp; 1&nbsp;&nbsp; 1&nbsp;&nbsp; 1<br>A 2 F 2 G 2 H 2 I<br><br></span>with the start node being A, the target node being J, and the heuristic being manhattan distance.&nbsp; Your search will always try to take the top route, on every node along the bottom path, even though you visit every node along the top route in your first try at reaching the goal.&nbsp; You need a way to mark that a node is visited and remove it from future consideration, or else you're wasting work.<br>


<br>A-star will visit the nodes in the order ABCDE FGHIJ; your algorithm visits the nodes in the order ABCDE FCDE GDE HE IJ.<br><font color="#888888"><br>&nbsp; -- ryan<br><br></font><div class="gmail_quote"><div><div></div><div>

On Sat, Oct 22, 2011 at 5:28 AM, Anton Kholomiov <span dir="ltr">&lt;<a href="mailto:anton.kholomiov@gmail.com" target="_blank">anton.kholomiov@gmail.com</a>&gt;</span> wrote:<br>
</div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div></div><div>Recently I was looking for an A-star search algorithm.&nbsp;I've found a package&nbsp;<div>

but I couldn't understand the code.&nbsp;Then I saw some blogposts but they</div>
<div>&nbsp;were difficult to&nbsp;understand too. I thought about some easier solution that</div>
<div>relies on laziness. And I've come to this:</div><div><br></div><div>Heuristic search is like depth-first search but solutions in sub-trees&nbsp;</div><div>are concatenated with <font color="#000099">mergeBy</font> function, that concatenates two&nbsp;</div>



<div>list by specific order:</div><div><br></div><div><div>module Search where</div><div><br></div><div>import Control.Applicative</div><div>import Data.Function(on)</div><div>import Control.Arrow(second)</div><div>import Data.Tree</div>



</div><div><br></div><div><div>-- | Heuristic search. Nodes are visited from smaller to greater.</div><div>searchBy :: (a -&gt; a -&gt; Ordering) -&gt; Tree a -&gt; [a]</div><div>searchBy &nbsp;heur (Node v ts) =&nbsp;</div><div>&nbsp;&nbsp; &nbsp;v : foldr (mergeBy heur) [] (searchBy heur &lt;$&gt; ts)</div>



<div><br></div><div>-- | Merge two lists. Elements concatenated in specified order.</div><div>mergeBy :: (a -&gt; a -&gt; Ordering) -&gt; [a] -&gt; [a] -&gt; [a]</div><div>mergeBy _ a &nbsp; &nbsp; &nbsp; &nbsp; [] &nbsp; &nbsp; &nbsp;= a</div><div>mergeBy _ [] &nbsp; &nbsp; &nbsp; &nbsp;b &nbsp; &nbsp; &nbsp; = b</div>



<div>mergeBy p (a:as) &nbsp; &nbsp;(b:bs) &nbsp;</div><div>&nbsp;&nbsp; &nbsp;| a `p` b == LT &nbsp; &nbsp;= a : mergeBy p as (b:bs)</div><div>&nbsp;&nbsp; &nbsp;| otherwise &nbsp; &nbsp; &nbsp; &nbsp; = b : mergeBy p bs (a:as)</div></div><div><br></div><div><br></div><div>Now we can define specific heuristic search in terms of <font color="#000099">searchBy</font>:</div>



<div><br></div><div><div>-- | Heuristic is distance to goal.</div><div>bestFirst :: Ord h =&gt; (a -&gt; h) -&gt; (a -&gt; [a]) -&gt; a -&gt; [a]</div><div>bestFirst dist alts =&nbsp;</div><div>&nbsp;&nbsp; &nbsp;searchBy (compare `on` dist) . unfoldTree (\a -&gt; (a, alts a))</div>



<div><br></div><div>-- | A-star search.</div><div>-- Heuristic is estimated length of whole path.&nbsp;</div><div>astar :: (Ord h, Num h) =&gt; (a -&gt; h) -&gt; (a -&gt; [(a, h)]) -&gt; a -&gt; [a]</div><div>astar dist alts s0 = fmap fst $&nbsp;</div>



<div>&nbsp;&nbsp; &nbsp;searchBy (compare `on` astarDist) $ unfoldTree gen (s0, 0)</div><div>&nbsp;&nbsp; &nbsp;where astarDist (a, d) = dist a + d</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;gen (a, d) &nbsp;= d `seq` ((a, d), second (+d) &lt;$&gt; alts a)</div></div><div><br></div>



<div>I'm wondering is it effective enough?</div><div><br></div><font color="#888888"><div><br></div><div>Anton</div>
</font><br></div></div><div>_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org" target="_blank">Haskell-Cafe@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
<br></div></blockquote></div><br>
</blockquote></div><br>
</div></div></blockquote></div><br></div>
</div></blockquote><blockquote type="cite"><div>&lt;Search.hs&gt;</div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>Haskell-Cafe mailing list</span><br><span><a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a></span><br><span><a href="http://www.haskell.org/mailman/listinfo/haskell-cafe">http://www.haskell.org/mailman/listinfo/haskell-cafe</a></span><br></div></blockquote></body></html>