@@ -25,14 +25,16 @@ module Constrained.Graph (
2525
2626import Control.Monad
2727import Data.Foldable
28- import Data.List (sortOn , nub )
28+ import Data.List (nub )
2929import Data.Map (Map )
3030import Data.Map qualified as Map
3131import Data.Maybe
3232import Data.Set (Set )
3333import Data.Set qualified as Set
3434import Prettyprinter
3535import Test.QuickCheck
36+ -- TODO: consider using more of this
37+ import Data.Graph qualified as G
3638
3739-- | A graph with unlabeled edges for keeping track of dependencies
3840data Graph node = Graph
@@ -166,21 +168,22 @@ topsort gr@(Graph e _) = go [] e
166168 removeNode n ds = Set. difference ds noDeps <$ guard (not $ n `Set.member` noDeps)
167169 if not $ null noDeps
168170 then go (Set. toList noDeps ++ order) (Map. mapMaybeWithKey removeNode g)
169- else Left . concat . take 1 . sortOn length . filter ( not . null ) . map ( findCycle gr) $ Map. keys e
171+ else Left $ findCycle gr
170172
171173-- | Simple DFS cycle finding
172- findCycle :: Ord node => Graph node -> node -> [node ]
173- findCycle g@ (Graph e _) node = concat . take 1 $ filter loopy $ go mempty node
174+ findCycle :: Ord node => Graph node -> [node ]
175+ findCycle g@ (Graph e _) = mkCycle . concat . take 1 . filter isCyclic . map ( map tr) . concatMap cycles . G. scc $ gr
174176 where
175- loopy [] = False
176- loopy c@ (x: _) = dependsOn (last c) x g
177- go seen n
178- | n `Set.member` seen = [[] ]
179- | otherwise = do
180- n' <- neighbours
181- (n : ) <$> go (Set. insert n seen) n'
182- where
183- neighbours = maybe [] Set. toList $ Map. lookup n e
177+ edgeList = [ (n, n, Set. toList es) | (n, es) <- Map. toList e ]
178+ (gr, tr0, _) = G. graphFromEdges edgeList
179+ tr x = let (n, _, _) = tr0 x in n
180+ cycles (G. Node a [] ) = [[a]]
181+ cycles (G. Node a as) = (a: ) <$> concatMap cycles as
182+ isCyclic [] = False
183+ isCyclic [a] = dependsOn a a g
184+ isCyclic _ = True
185+ -- Removes a non-dependent stem from the start of the dependencies
186+ mkCycle ns = let l = last ns in dropWhile (\ n -> not $ dependsOn l n g) ns
184187
185188-- | Get the dependencies of a node in the graph, `mempty` if the node is not
186189-- in the graph
0 commit comments