-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGraph.hs
79 lines (67 loc) · 2.53 KB
/
Graph.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
{-# LANGUAGE OverloadedLists #-}
module Main (main) where
import Data.Functor ((<&>))
import Data.Map (Map)
import Data.Map qualified as Map
import Data.Maybe (listToMaybe, mapMaybe)
import Data.Sequence (Seq ((:<|)))
import Data.Sequence qualified as Seq
import GHC.IsList (IsList (fromList, toList))
type EdgeList = Map Int [Int]
newtype Node = Node (Int, [Node])
edgeListToGraph :: EdgeList -> Maybe Node
edgeListToGraph edgeList = do
(nodeId, _) <- listToMaybe $ toList edgeList
edgeListToGraphFrom edgeList nodeId
where
edgeListToGraphFrom edgeList' nodeId' = do
neighbours <- Map.lookup nodeId' edgeList'
return (Node (nodeId', mapMaybe (edgeListToGraphFrom edgeList') neighbours))
graphToEdgeListBf :: Node -> EdgeList
graphToEdgeListBf graph =
bf [graph] Map.empty
where
bf :: Seq Node -> EdgeList -> EdgeList
bf Seq.Empty edgeList = edgeList
bf ((Node (nodeId, neighbours)) :<| remainingToVisit) edgeList =
if nodeId `Map.member` edgeList
then bf remainingToVisit edgeList
else
bf
(remainingToVisit <> fromList neighbours)
(Map.insert nodeId (map (\(Node (neighbourNodeId, _)) -> neighbourNodeId) neighbours) edgeList)
graphToEdgeListDf :: Node -> EdgeList
graphToEdgeListDf graph =
df [graph] Map.empty
where
df :: Seq Node -> EdgeList -> EdgeList
df Seq.Empty edgeList = edgeList
df ((Node (nodeId, neighbours)) :<| remainingToVisit) edgeList =
if nodeId `Map.member` edgeList
then df remainingToVisit edgeList
else
df
(fromList neighbours <> remainingToVisit)
(Map.insert nodeId (map (\(Node (neighbourNodeId, _)) -> neighbourNodeId) neighbours) edgeList)
main :: IO ()
main = do
putStrLn "Input Edge List:"
print $ Just input
putStrLn "Round Trip BF:"
let oneRoundTripBf = roundTripBf $ Just input
print oneRoundTripBf
putStrLn "Round Trip DF:"
let oneRoundTripDf = roundTripDf $ Just input
print oneRoundTripDf
putStrLn "Round Trips BF + DF:"
let twoRoundTripsBfDf = roundTripBf $ roundTripDf $ Just input
print twoRoundTripsBfDf
putStrLn "Isomorphic:"
print $ oneRoundTripBf == oneRoundTripDf && oneRoundTripBf == twoRoundTripsBfDf
where
roundTripBf maybeEdgeList = maybeEdgeList >>= edgeListToGraph <&> graphToEdgeListBf
roundTripDf maybeEdgeList = maybeEdgeList >>= edgeListToGraph <&> graphToEdgeListDf
input :: EdgeList =
fromList $ map createEdges [1 .. 10_000]
where
createEdges i = (i, [j | j <- [i .. i + 50], j /= i && j <= 10_000])