Dijkstra(1対全・最短路)
コンテンツ
Dijkstra まだ一度も走らせていない。
たぶんバグあり。
module Dijkstra where import Data.List import Data.Graph import Data.Array.IArray import Debug.Trace import qualified Data.Set as Set type Weight = Array Edge Int -- g=graph, w=weight, d=distance, p=path, q=queue dijkstra :: Graph -> Weight -> Set.Set (Int,Vertex) -> Array Vertex (Int,Vertex) -> Set.Set Vertex -> Array Vertex (Int,Vertex) dijkstra g w d p q | Set.null q = p | otherwise = let ((_,u),d') = Set.deleteFindMin d (d'',p',q') = update g w d' p q u in dijkstra g w d'' p' q' update g w d p q u | Set.member u q = (d',p',q') | otherwise = (d,p,q) where q' = Set.delete u q vs = intersect (Set.toList q') $reachable g u du = fst.(p!)$u updates = [(du+w!(u,v),v)|v<-vs,du + w!(u,v) < (fst.(p!))v] d' = foldl (flip Set.insert) d updates p' = p//[(v,(d,u))|(d,v)<-updates] shortestPath ::Graph -> Weight -> Vertex -> Array Vertex (Int,Vertex) shortestPath g w s = dijkstra g w d p q where maxW = sum.elems$w d = Set.fromList$(0,s):[(maxW,v)|v<-vertices g,v/=s] p = array (bounds g)$(s,(0,s)):[(v,(maxW,s))|v<-vertices g,v/=s] q = Set.fromList.vertices$g
それにしても、あまり美しくない。しかもヒープを使っていないという罠。
だって、ヒープのパッケージ入ってないし。
もしかしたらqは不要?
qは不要でした。
module Dijkstra where import Data.List import Data.Graph import Data.Array.Diff import Control.Arrow import qualified Data.Set as S type Weight = Array Edge Int -- g=graph, w=weight, d=distance, p=path dijkstra :: Graph -> Weight -> (S.Set (Int,Vertex) ,Table (Int,Vertex)) -> Table (Int,Vertex) dijkstra g w = snd.until (S.null.fst) (update g w) update g w (d,p) | du > (fst.(p!))u = (d',p) | otherwise = (d'',p') where ((du,u),d') = S.deleteFindMin d updates = [(du+w!(u,v),v)|v<-g!u,du + w!(u,v) < (fst.(p!))v] d'' = foldl (flip S.insert) d' updates p' = p//[(v,(dv,u))|(dv,v)<-updates] shortestPaths ::Graph -> Weight -> Vertex -> Table (Int,Vertex) shortestPaths g w s = dijkstra g w (d,p) where maxW = (1+).sum.map (w!).edges$g d = S.fromList$(0,s):[(maxW,v)|v<-vertices g,v/=s] p = array (bounds g)$(s,(0,s)):[(v,(maxW,s))|v<-vertices g,v/=s] shortestPath ::Graph -> Weight -> Vertex ->Vertex-> (Int,[Vertex]) shortestPath g w s = (fst.(p!)&&&(s:).reverse.unfoldr f) where p = shortestPaths g w s f v | s==v = Nothing | v/=s = Just (v,snd.(p!)$v)
だけどまだ、ヒープを使ってなし、プライオリティキューも使ってない。
しかし、log N は定数という説があるから、まあ良い?
実はライブラリがあった罠。
http://haskell.cs.yale.edu/ghc/dist/stable/old-docs/libraries/fgl/Data-Graph-Inductive-Query-SP.html
作成者 Toru Mano
最終更新時刻 2023-01-01 (c70d5a1)