module Data.BellmanFord where
import Data.Maybe
import Control.Monad
import Control.CUtils.DataParallel
import Control.CUtils.Conc
import Data.List.Extras.Argmax
import Data.List
import Data.Array
keys :: [(a, b)] -> [a]
keys = map fst
mapWithKey :: (t -> u -> v) -> Array Int (t, u) -> Array Int (t, v)
mapWithKey f ar = let
?seq = True
?pool = BoxedThreadPool NoPool in
arr_concF(\(_, i)->let (a, b) = ar!i in ((,) $! a) $! f a b) ((), snd(bounds ar)+1)
relaxEdge nodeWeights edgeWeights x (k, weight) = argmin snd ((k, weight) : map (\y -> (y, maybe (1/0) (\z -> snd (fromJust (lookup y nodeWeightsLs)) + z) (lookup (y, x) edgeWeights))) (keys nodeWeightsLs)) where
nodeWeightsLs = elems nodeWeights
bellmanFord :: (Eq a) => [((a, a), Double)] -> a -> [(a, (a, Double))]
bellmanFord gr x = elems$foldl' (\weights _ -> mapWithKey (relaxEdge weights gr) weights) weights [1..length gr+1] where
ks = nub (map fst (keys gr) ++ map snd (keys gr))
weights = newArray$(x, (x, 0)) : map (\x -> (x, (x, 1/0))) (delete x ks)
retrievePath :: (Eq a) => [(a, (a, Double))] -> a -> a -> [a]
retrievePath mp a a2 | a == a2 = [a]
retrievePath mp a a2 = retrievePath mp a (fst (fromJust (lookup a2 mp))) ++ [a2]
cycles :: (Eq a) => [((a, a), ())] -> a -> Maybe a
cycles gr x = do
(y, z) <- lookup x weights
guard (round z < 0)
return y where
gr' = mapWithKey (\_ _ -> 1)$newArray gr
weights = bellmanFord(elems gr') x