packages feed

astar 0.2.1 → 0.3.0.0

raw patch · 4 files changed

+170/−154 lines, 4 filesdep +hashabledep +psqueuesdep +unordered-containersdep −PSQueuedep −containersdep ~basenew-uploaderPVP ok

version bump matches the API change (PVP)

Dependencies added: hashable, psqueues, unordered-containers

Dependencies removed: PSQueue, containers

Dependency ranges changed: base

API changes (from Hackage documentation)

- Data.Graph.AStar: instance (Ord a, Ord c, Show a, Show c) => Show (AStar a c)
+ Data.Graph.AStar: instance (GHC.Show.Show c, GHC.Show.Show a) => GHC.Show.Show (Data.Graph.AStar.AStar a c)
- Data.Graph.AStar: aStar :: (Ord a, Ord c, Num c) => (a -> Set a) -> (a -> a -> c) -> (a -> c) -> (a -> Bool) -> a -> Maybe [a]
+ Data.Graph.AStar: aStar :: (Hashable a, Ord a, Ord c, Num c) => (a -> HashSet a) -> (a -> a -> c) -> (a -> c) -> (a -> Bool) -> a -> Maybe [a]
- Data.Graph.AStar: aStarM :: (Monad m, Ord a, Ord c, Num c) => (a -> m (Set a)) -> (a -> a -> m c) -> (a -> m c) -> (a -> m Bool) -> m a -> m (Maybe [a])
+ Data.Graph.AStar: aStarM :: (Monad m, Hashable a, Ord a, Ord c, Num c) => (a -> m (HashSet a)) -> (a -> a -> m c) -> (a -> m c) -> (a -> m Bool) -> m a -> m (Maybe [a])

Files

− Data/Graph/AStar.hs
@@ -1,147 +0,0 @@-module Data.Graph.AStar (aStar,aStarM) where--import qualified Data.Set as Set-import Data.Set (Set, (\\))-import qualified Data.Map as Map-import Data.Map (Map, (!))-import qualified Data.PSQueue as PSQ-import Data.PSQueue (PSQ, Binding(..), minView)-import Data.List (foldl')-import Control.Monad (foldM)--data AStar a c = AStar { visited  :: !(Set a),-                         waiting  :: !(PSQ a c),-                         score    :: !(Map a c),-                         memoHeur :: !(Map a c),-                         cameFrom :: !(Map a a),-                         end      :: !(Maybe a) }-    deriving Show-    -aStarInit start = AStar { visited  = Set.empty,-                          waiting  = PSQ.singleton start 0,-                          score    = Map.singleton start 0,-                          memoHeur = Map.empty,-                          cameFrom = Map.empty,-                          end      = Nothing }--runAStar :: (Ord a, Ord c, Num c) =>-         (a -> Set a)     -- adjacencies in graph-         -> (a -> a -> c) -- distance function-         -> (a -> c)      -- heuristic distance to goal-         -> (a -> Bool)   -- goal-         -> a             -- starting vertex-         -> AStar a c     -- final state--runAStar graph dist heur goal start = aStar' (aStarInit start)-  where aStar' s-          = case minView (waiting s) of-              Nothing            -> s-              Just (x :-> _, w') ->-                if goal x-                  then s { end = Just x }-                  else aStar' $ foldl' (expand x)-                                       (s { waiting = w',-                                            visited = Set.insert x (visited s)})-                                       (Set.toList (graph x \\ visited s))-        expand x s y-          = let v = score s ! x + dist x y-            in case PSQ.lookup y (waiting s) of-                 Nothing -> link x y v-                              (s { memoHeur-                                     = Map.insert y (heur y) (memoHeur s) })-                 Just _  -> if v < score s ! y-                              then link x y v s-                              else s-        link x y v s-           = s { cameFrom = Map.insert y x (cameFrom s),-                 score    = Map.insert y v (score s),-                 waiting  = PSQ.insert y (v + memoHeur s ! y) (waiting s) }---- | This function computes an optimal (minimal distance) path through a graph in a best-first fashion,--- starting from a given starting point.-aStar :: (Ord a, Ord c, Num c) =>-         (a -> Set a)     -- ^ The graph we are searching through, given as a function from vertices-                          -- to their neighbours.-         -> (a -> a -> c) -- ^ Distance function between neighbouring vertices of the graph. This will-                          -- never be applied to vertices that are not neighbours, so may be undefined-                          -- on pairs that are not neighbours in the graph.-         -> (a -> c)      -- ^ Heuristic distance to the (nearest) goal. This should never overestimate the-                          -- distance, or else the path found may not be minimal.-         -> (a -> Bool)   -- ^ The goal, specified as a boolean predicate on vertices.-         -> a             -- ^ The vertex to start searching from.-         -> Maybe [a]     -- ^ An optimal path, if any path exists. This excludes the starting vertex.-aStar graph dist heur goal start-    = let s = runAStar graph dist heur goal start-      in case end s of-            Nothing -> Nothing-            Just e  -> Just (reverse . takeWhile (not . (== start)) . iterate (cameFrom s !) $ e)--runAStarM :: (Monad m, Ord a, Ord c, Num c) =>-          (a -> m (Set a))   -- adjacencies in graph-          -> (a -> a -> m c) -- distance function-          -> (a -> m c)      -- heuristic distance to goal-          -> (a -> m Bool)   -- goal-          -> a               -- starting vertex-          -> m (AStar a c)   -- final state--runAStarM graph dist heur goal start = aStar' (aStarInit start)-  where aStar' s-          = case minView (waiting s) of-              Nothing            -> return s-              Just (x :-> _, w') ->-                do g <- goal x-                   if g then return (s { end = Just x })-                        else do ns <- graph x-                                u <- foldM (expand x)-                                           (s { waiting = w',-                                                visited = Set.insert x (visited s)})-                                           (Set.toList (ns \\ visited s))-                                aStar' u-        expand x s y-          = do d <- dist x y-               let v = score s ! x + d-               case PSQ.lookup y (waiting s) of-                 Nothing -> do h <- heur y-                               return (link x y v (s { memoHeur = Map.insert y h (memoHeur s) }))-                 Just _  -> return $ if v < score s ! y-                                        then link x y v s-                                        else s-        link x y v s-           = s { cameFrom = Map.insert y x (cameFrom s),-                 score    = Map.insert y v (score s),-                 waiting  = PSQ.insert y (v + memoHeur s ! y) (waiting s) }---- | This function computes an optimal (minimal distance) path through a graph in a best-first fashion,--- starting from a given starting point.-aStarM :: (Monad m, Ord a, Ord c, Num c) =>-         (a -> m (Set a))   -- ^ The graph we are searching through, given as a function from vertices-                            -- to their neighbours.-         -> (a -> a -> m c) -- ^ Distance function between neighbouring vertices of the graph. This will-                            -- never be applied to vertices that are not neighbours, so may be undefined-                            -- on pairs that are not neighbours in the graph.-         -> (a -> m c)      -- ^ Heuristic distance to the (nearest) goal. This should never overestimate the-                            -- distance, or else the path found may not be minimal.-         -> (a -> m Bool)   -- ^ The goal, specified as a boolean predicate on vertices.-         -> m a             -- ^ The vertex to start searching from.-         -> m (Maybe [a])   -- ^ An optimal path, if any path exists. This excludes the starting vertex.-aStarM graph dist heur goal start-    = do sv <- start-         s <- runAStarM graph dist heur goal sv-         return $ case end s of-                    Nothing -> Nothing-                    Just e  -> Just (reverse . takeWhile (not . (== sv)) . iterate (cameFrom s !) $ e)-----plane :: (Integer, Integer) -> Set (Integer, Integer)-plane (x,y) = Set.fromList [(x-1,y),(x+1,y),(x,y-1),(x,y+1)]--planeHole :: (Integer, Integer) -> Set (Integer, Integer)-planeHole (x,y) = Set.filter (\(u,v) -> planeDist (u,v) (0,0) > 10) (plane (x,y))--planeDist :: (Integer, Integer) -> (Integer, Integer) -> Double-planeDist (x1,y1) (x2,y2) = sqrt ((x1'-x2')^2 + (y1'-y2')^2)-    where [x1',y1',x2',y2'] = map fromInteger [x1,y1,x2,y2]--
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2008, Cale Gibbard+Copyright (c) 2008, Cale Gibbard; 2016, Johannes Weiss All rights reserved.  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
astar.cabal view
@@ -1,13 +1,28 @@ name:                astar-version:             0.2.1+version:             0.3.0.0 synopsis:            General A* search algorithm. description:         This is a data-structure independent implementation of A* search. category:            Data license:             BSD3 license-file:        LICENSE-author:              Cale Gibbard-maintainer:          cgibbard@gmail.com-build-Depends:       base,containers,PSQueue+author:              Cale Gibbard, Johannes Weiss+maintainer:          public@tux4u.de build-type:          Simple-exposed-modules:     Data.Graph.AStar-ghc-options:         -O2+Homepage:            https://github.com/weissi/astar+bug-reports:         https://github.com/weissi/astar/issues+copyright:           2008 Cale Gibbard+                     2016 Johannes Weiss+tested-with:         GHC==7.10.1+cabal-version:       >= 1.6++library+  hs-source-dirs:    src+  exposed-modules:   Data.Graph.AStar+  build-depends:     base >= 4 && < 5,+                     unordered-containers >= 0.2,+                     psqueues >= 0.2,+                     hashable >= 1.2++source-repository head+  type:     git+  location: https://github.com/weissi/astar.git
+ src/Data/Graph/AStar.hs view
@@ -0,0 +1,148 @@+module Data.Graph.AStar (aStar,aStarM) where++import qualified Data.HashSet as Set+import Data.HashSet (HashSet)+import Data.Hashable (Hashable(..))+import qualified Data.HashMap.Strict as Map+import Data.HashMap.Strict (HashMap, (!))+import qualified Data.OrdPSQ as PSQ+import Data.OrdPSQ (OrdPSQ, minView)+import Data.List (foldl')+import Control.Monad (foldM)++data AStar a c = AStar { visited  :: !(HashSet a),+                         waiting  :: !(OrdPSQ a c ()),+                         score    :: !(HashMap a c),+                         memoHeur :: !(HashMap a c),+                         cameFrom :: !(HashMap a a),+                         end      :: !(Maybe a) }+    deriving Show++aStarInit start = AStar { visited  = Set.empty,+                          waiting  = PSQ.singleton start 0 (),+                          score    = Map.singleton start 0,+                          memoHeur = Map.empty,+                          cameFrom = Map.empty,+                          end      = Nothing }++runAStar :: (Hashable a, Ord a, Ord c, Num c)+         => (a -> HashSet a)     -- adjacencies in graph+         -> (a -> a -> c) -- distance function+         -> (a -> c)      -- heuristic distance to goal+         -> (a -> Bool)   -- goal+         -> a             -- starting vertex+         -> AStar a c     -- final state++runAStar graph dist heur goal start = aStar' (aStarInit start)+  where aStar' s+          = case minView (waiting s) of+              Nothing            -> s+              Just (x, _,  _, w') ->+                if goal x+                  then s { end = Just x }+                  else aStar' $ foldl' (expand x)+                                       (s { waiting = w',+                                            visited = Set.insert x (visited s)})+                                       (Set.toList (graph x `Set.difference` visited s))+        expand x s y+          = let v = score s ! x + dist x y+            in case PSQ.lookup y (waiting s) of+                 Nothing -> link x y v+                              (s { memoHeur+                                     = Map.insert y (heur y) (memoHeur s) })+                 Just _  -> if v < score s ! y+                              then link x y v s+                              else s+        link x y v s+           = s { cameFrom = Map.insert y x (cameFrom s),+                 score    = Map.insert y v (score s),+                 waiting  = PSQ.insert y (v + memoHeur s ! y) () (waiting s) }++-- | This function computes an optimal (minimal distance) path through a graph in a best-first fashion,+-- starting from a given starting point.+aStar :: (Hashable a, Ord a, Ord c, Num c) =>+         (a -> HashSet a)     -- ^ The graph we are searching through, given as a function from vertices+                          -- to their neighbours.+         -> (a -> a -> c) -- ^ Distance function between neighbouring vertices of the graph. This will+                          -- never be applied to vertices that are not neighbours, so may be undefined+                          -- on pairs that are not neighbours in the graph.+         -> (a -> c)      -- ^ Heuristic distance to the (nearest) goal. This should never overestimate the+                          -- distance, or else the path found may not be minimal.+         -> (a -> Bool)   -- ^ The goal, specified as a boolean predicate on vertices.+         -> a             -- ^ The vertex to start searching from.+         -> Maybe [a]     -- ^ An optimal path, if any path exists. This excludes the starting vertex.+aStar graph dist heur goal start+    = let s = runAStar graph dist heur goal start+      in case end s of+            Nothing -> Nothing+            Just e  -> Just (reverse . takeWhile (not . (== start)) . iterate (cameFrom s !) $ e)++runAStarM :: (Monad m, Hashable a, Ord a, Ord c, Num c) =>+          (a -> m (HashSet a))   -- adjacencies in graph+          -> (a -> a -> m c) -- distance function+          -> (a -> m c)      -- heuristic distance to goal+          -> (a -> m Bool)   -- goal+          -> a               -- starting vertex+          -> m (AStar a c)   -- final state++runAStarM graph dist heur goal start = aStar' (aStarInit start)+  where aStar' s+          = case minView (waiting s) of+              Nothing            -> return s+              Just (x, _,  _, w') ->+                do g <- goal x+                   if g then return (s { end = Just x })+                        else do ns <- graph x+                                u <- foldM (expand x)+                                           (s { waiting = w',+                                                visited = Set.insert x (visited s)})+                                           (Set.toList (ns `Set.difference` visited s))+                                aStar' u+        expand x s y+          = do d <- dist x y+               let v = score s ! x + d+               case PSQ.lookup y (waiting s) of+                 Nothing -> do h <- heur y+                               return (link x y v (s { memoHeur = Map.insert y h (memoHeur s) }))+                 Just _  -> return $ if v < score s ! y+                                        then link x y v s+                                        else s+        link x y v s+           = s { cameFrom = Map.insert y x (cameFrom s),+                 score    = Map.insert y v (score s),+                 waiting  = PSQ.insert y (v + memoHeur s ! y) () (waiting s) }++-- | This function computes an optimal (minimal distance) path through a graph in a best-first fashion,+-- starting from a given starting point.+aStarM :: (Monad m, Hashable a, Ord a, Ord c, Num c) =>+         (a -> m (HashSet a))   -- ^ The graph we are searching through, given as a function from vertices+                            -- to their neighbours.+         -> (a -> a -> m c) -- ^ Distance function between neighbouring vertices of the graph. This will+                            -- never be applied to vertices that are not neighbours, so may be undefined+                            -- on pairs that are not neighbours in the graph.+         -> (a -> m c)      -- ^ Heuristic distance to the (nearest) goal. This should never overestimate the+                            -- distance, or else the path found may not be minimal.+         -> (a -> m Bool)   -- ^ The goal, specified as a boolean predicate on vertices.+         -> m a             -- ^ The vertex to start searching from.+         -> m (Maybe [a])   -- ^ An optimal path, if any path exists. This excludes the starting vertex.+aStarM graph dist heur goal start+    = do sv <- start+         s <- runAStarM graph dist heur goal sv+         return $ case end s of+                    Nothing -> Nothing+                    Just e  -> Just (reverse . takeWhile (not . (== sv)) . iterate (cameFrom s !) $ e)+++++plane :: (Integer, Integer) -> HashSet (Integer, Integer)+plane (x,y) = Set.fromList [(x-1,y),(x+1,y),(x,y-1),(x,y+1)]++planeHole :: (Integer, Integer) -> HashSet (Integer, Integer)+planeHole (x,y) = Set.filter (\(u,v) -> planeDist (u,v) (0,0) > 10) (plane (x,y))++planeDist :: (Integer, Integer) -> (Integer, Integer) -> Double+planeDist (x1,y1) (x2,y2) = sqrt ((x1'-x2')^2 + (y1'-y2')^2)+    where [x1',y1',x2',y2'] = map fromInteger [x1,y1,x2,y2]++