0 | module Data.Graph.Indexed.Util
3 | import Data.Array.Mutable
4 | import Data.AssocList.Indexed
5 | import Data.Linear.Traverse1
6 | import Data.Graph.Indexed.Types
7 | import Data.SortedMap
8 | import Data.SortedSet
20 | allFinsFast : (n : Nat) -> List (Fin n)
22 | allFinsFast (S n) = go [] last
24 | go : List (Fin $
S n) -> Fin (S n) -> List (Fin $
S n)
26 | go xs (FS x) = go (FS x :: xs) (assert_smaller (FS x) $
weaken x)
34 | lupdNodes : {k : _} -> MArray s k (Adj k e n) -> (n -> n) -> F1' s
35 | lupdNodes r f = mupdate {label $= f} r
37 | parameters (r : MArray s k (Adj k e n))
41 | lupdNode : (n1 : Fin k) -> (n -> n) -> F1' s
42 | lupdNode n1 f = modify r n1 {label $= f}
46 | lsetNode : (n1 : Fin k) -> n -> F1' s
47 | lsetNode n1 v = modify r n1 {label := v}
51 | linsEdge : Edge k e ->F1' s
52 | linsEdge (E n1 n2 el) t =
53 | let _ # t := modify r n1 {neighbours $= insert n2 el} t
54 | in modify r n2 {neighbours $= insert n1 el} t
58 | ldelEdge : (n1, n2 : Fin k) -> F1' s
60 | let _ # t := modify r n1 {neighbours $= delete n2} t
61 | in modify r n2 {neighbours $= delete n1} t
65 | linsEdges : List (Edge k e) -> F1' s
66 | linsEdges = traverse1_ linsEdge
70 | ldelEdges : List (Fin k, Fin k) -> F1' s
71 | ldelEdges = traverse1_ (\(x,y) => ldelEdge x y)
75 | ctxtEdges : Fin k -> Adj k e n -> SnocList (Edge k e)
76 | ctxtEdges x (A _ ns) = foldlKV acc [<] ns
79 | acc : Fin k -> SnocList (Edge k e) -> e -> SnocList (Edge k e)
80 | acc y sp v with (compare x y) proof eq
81 | _ | LT = sp :< E x y v
90 | contexts : {k : _} -> IGraph k e n -> List (Context k e n)
91 | contexts = foldrKV (\x,(A l ns),cs => C x l ns :: cs) [] . graph
95 | nodes : {k : _} -> (0 _ : IGraph k e n) -> List (Fin k)
96 | nodes _ = allFinsFast k
100 | labNodes : {k : _} -> IGraph k e n -> List (Fin k, n)
101 | labNodes = foldrKV (\x,(A l _),cs => (x,l) :: cs) [] . graph
105 | labels : {k : _} -> IGraph k e n -> List n
106 | labels = foldr (\(A l _) => (l ::)) [] . graph
111 | adj : IGraph k e n -> Fin k -> Adj k e n
112 | adj (IG g) k = at g k
116 | lab : IGraph k e n -> Fin k -> n
117 | lab g = label . adj g
122 | neighboursAsAL : IGraph k e n -> Fin k -> AssocList k e
123 | neighboursAsAL g = neighbours . adj g
128 | neighboursAsPairs : IGraph k e n -> Fin k -> List (Fin k, e)
129 | neighboursAsPairs g = pairs . neighboursAsAL g
133 | neighbours : IGraph k e n -> Fin k -> List (Fin k)
134 | neighbours g = keys . neighboursAsAL g
138 | edgesTo : IGraph k e n -> Fin k -> List (Edge k e)
140 | let A _ ns := adj g k
141 | in mapMaybe (\(n,l) => mkEdge k n l) $
pairs ns
146 | lneighbours : IGraph k e n -> Fin k -> List (Fin k, n)
147 | lneighbours g = map (\x => (x, lab g x)) . neighbours g
152 | lneighboursAsAL : IGraph k e n -> Fin k -> AssocList k (e, n)
153 | lneighboursAsAL g = mapKV (\x => (, lab g x)) . neighboursAsAL g
157 | neighbourLabels : IGraph k e n -> Fin k -> List n
158 | neighbourLabels g = map (lab g) . neighbours g
162 | edgeLabels : IGraph k e n -> Fin k -> List e
163 | edgeLabels g = values . neighbours . adj g
167 | elab : IGraph k e n -> Fin k -> Fin k -> Maybe e
168 | elab (IG g) x y = lookup y . neighbours $
at g x
172 | edge : IGraph k e n -> Fin k -> Fin k -> Maybe (Edge k e)
173 | edge g x y = elab g x y >>= mkEdge x y
177 | adjacent : IGraph k e n -> Fin k -> Fin k -> Bool
178 | adjacent g x y = isJust $
elab g x y
182 | edges : {k : _} -> IGraph k e n -> List (Edge k e)
183 | edges (IG g) = foldrKV (\x,adj,es => ctxtEdges x adj <>> es) [] g
187 | size : {k : _} -> IGraph k e n -> Nat
188 | size = length . edges
192 | deg : IGraph k e n -> Fin k -> Nat
193 | deg g = length . neighbours g
197 | hasNeighbour : IGraph k e n -> Fin k -> Fin k -> Bool
198 | hasNeighbour g k = isJust . elab g k
206 | empty : IGraph 0 e n
209 | 0 mapLen : (f : a -> b) -> (as : List a) -> length (map f as) === length as
211 | mapLen f (x :: xs) = cong S $
mapLen f xs
215 | mkGraphL : (ns : List n) -> List (Edge (length ns) e) -> IGraph (length ns) e n
217 | IG $
allocListWith ns (`A` empty) $
\r,t =>
218 | let _ # t := linsEdges r es t
219 | in unsafeFreeze r t
223 | mkGraph : {k : _} -> (ns : Vect k n) -> List (Edge k e) -> IGraph k e n
225 | IG $
allocVect (map (`A` empty) ns) $
\r,t =>
226 | let _ # t := linsEdges r es t
227 | in unsafeFreeze r t
235 | mkGraphRev : {k : _} -> (ns : Vect k n) -> List (Edge k e) -> IGraph k e n
237 | IG $
allocVectRev (map (`A` empty) ns) $
\r,t =>
238 | let _ # t := linsEdges r es t
239 | in unsafeFreeze r t
242 | generate : (k : Nat) -> (Fin k -> Adj k e n) -> IGraph k e n
243 | generate k f = IG $
generate k f
253 | -> (Fin k -> Adj k e n -> Adj k e1 n1)
256 | mapCtxt fun (IG g) = IG $
mapWithIndex fun g
262 | -> (Fin k -> Adj k e n -> n1)
265 | mapWithCtxt fun = mapCtxt (\x,adj => adj $> fun x adj)
269 | mapAdj : {k : _} -> (Adj k e n -> Adj k f m) -> IGraph k e n -> IGraph k f m
270 | mapAdj fun (IG g) = IG $
map fun g
274 | mapWithAdj : {k : _} -> (Adj k e n -> m) -> IGraph k e n -> IGraph k e m
275 | mapWithAdj fun = mapAdj (\adj => adj $> fun adj)
280 | -> {auto app : Applicative f}
281 | -> (Fin k -> Adj k e n -> f (Adj k e1 n1))
283 | -> f (IGraph k e1 n1)
284 | traverseCtxt fun (IG g) = IG <$> traverseWithIndex fun g
289 | -> {auto app : Applicative f}
290 | -> (Fin k -> Adj k e n -> f n1)
292 | -> f (IGraph k e n1)
293 | traverseWithCtxt fun = traverseCtxt (\x,a => (`A` a.neighbours) <$> fun x a)
303 | updateNodes : {k : _} -> Fin k -> (f,g : m -> n) -> IGraph k e m -> IGraph k e n
304 | updateNodes x f g = mapWithCtxt (\y,a => if x == y then f a.label else g a.label)
308 | updateNode : {k : _} -> Fin k -> (n -> n) -> IGraph k e n -> IGraph k e n
309 | updateNode x f = updateNodes x f id
313 | setNode : {k : _} -> Fin k -> n -> IGraph k e n -> IGraph k e n
314 | setNode x = updateNode x . const
327 | updateEdges x y f g =
328 | mapCtxt $
\k,(A l a) =>
330 | if k == x then mapKV (\m,l => if m == y then f l else g l) a
331 | else if k == y then mapKV (\m,l => if m == x then f l else g l) a
342 | updateEdge x y f = updateEdges x y f id
346 | insEdges : {k : _} -> List (Edge k e) -> IGraph k e n -> IGraph k e n
348 | IG $
allocGen k (adj g) $
\r,t =>
349 | let _ # t := linsEdges r es t
350 | in unsafeFreeze r t
354 | insEdge : {k : _} -> Edge k e -> IGraph k e n -> IGraph k e n
355 | insEdge = insEdges . pure
359 | delEdges : {k : _} -> List (Fin k, Fin k) -> IGraph k e n -> IGraph k e n
360 | delEdges ps g = IG $
allocGen k (adj g) $
\r,t =>
361 | let _ # t := ldelEdges r ps t
362 | in unsafeFreeze r t
366 | delEdge : {k : _} -> (x,y : Fin k) -> IGraph k e n -> IGraph k e n
367 | delEdge x y = delEdges [(x,y)]
371 | insNodes : {k,m : _} -> IGraph k e n -> (ns : Vect m n) -> IGraph (k + m) e n
372 | insNodes (IG g) ns =
373 | let g' := map (weakenAdjN m) g
374 | in IG $
append g' (map fromLabel (array ns))
382 | -> (es : List (Edge (k + m) e))
383 | -> IGraph (k + m) e n
384 | insNodesAndEdges g ns es = insEdges es $
insNodes g ns
390 | insNode : {k : _} -> IGraph k e n -> n -> IGraph (S k) e n
391 | insNode g v = rewrite plusCommutative 1 k in insNodes g [v]
394 | adjEdges : SortedMap (Fin x) (Fin y) -> Adj x e n -> Adj y e n
395 | adjEdges m (A l ns) =
396 | let ps := mapMaybe (\(n,v) => (,v) <$> lookup n m) $
pairs ns
397 | in A l $
fromList ps
399 | zipTR : SnocList (a,b) -> List a -> List b -> List (a,b)
400 | zipTR sx [] _ = sx <>> []
401 | zipTR sx _ [] = sx <>> []
402 | zipTR sx (x :: xs) (y :: ys) = zipTR (sx:<(x,y)) xs ys
405 | delNodes : {k : _} -> List (Fin k) -> IGraph k e n -> Graph e n
406 | delNodes {k = 0} _ _ = G _ empty
407 | delNodes {k = S x} ks (IG g) =
408 | let set := SortedSet.fromList ks
410 | filterWithKey (\x,_ => not (contains x set)) g | A 0 _ => G _ empty
411 | finX := filter (\x => not (contains x set)) $
allFinsFast (S x)
412 | finY := allFinsFast (S y)
413 | proMap := SortedMap.fromList $
zipTR [<] finX finY
414 | in G (S y) (IG $
map (adjEdges proMap) h)
418 | delNode : {k : _} -> Fin k -> IGraph k e n -> Graph e n
419 | delNode = delNodes . pure
424 | mergeGraphsWithEdges :
426 | -> (g1 : IGraph k e n)
427 | -> (g2 : IGraph m e n)
428 | -> List (Fin k, Fin m, e)
429 | -> IGraph (k + m) e n
430 | mergeGraphsWithEdges {k} g t es =
431 | let vNodes := label <$> toVect t.graph
432 | cEdges := map (\(x,y,l) => compositeEdge x y l) es
433 | lEdges := incEdge k <$> edges t
434 | in insNodesAndEdges g vNodes (cEdges ++ lEdges)
440 | -> (g1 : IGraph k e n)
441 | -> (g2 : IGraph m e n)
442 | -> IGraph (k + m) e n
443 | mergeGraphs {k} g t =
444 | let vNodes := label <$> toVect t.graph
445 | lEdges := incEdge k <$> edges t
446 | in insNodesAndEdges g vNodes lEdges
453 | {k : _} -> Show e => Show n => Show (IGraph k e n) where
454 | showPrec p g = showCon p "mkGraph" $
showArg (labels g) ++ showArg (edges g)
457 | Show e => Show n => Show (Graph e n) where
458 | showPrec p (G o g) = showCon p "G" $
showArg o ++ showArg g
460 | pl : Nat -> Fin k -> String
461 | pl n = padLeft n ' ' . show . finToNat
464 | pretty : {k : _} -> (e -> String) -> (n -> String) -> IGraph k e n -> String
466 | let ns := labNodes g
468 | maxLen := length $
show k
470 | "Nodes:" :: map (dispNode maxLen) ns ++
471 | "\nEdges:" :: map (dispEdge maxLen) es
474 | dispNode : Nat -> (Fin k, n) -> String
475 | dispNode k (n1,l) =
476 | " \{pl k n1} :> \{dn l}"
478 | dispEdge : Nat -> Edge k e -> String
479 | dispEdge k (E n1 n2 l) =
480 | "E \{pl k n1} \{pl k n2} \{de l}"