packages feed

hgraph-1.10.0.0: src/HGraph/Undirected/AdjacencyMap.hs

{-# LANGUAGE GADTs #-}

module HGraph.Undirected.AdjacencyMap
       ( Graph
       , emptyGraph
       , module HGraph.Undirected
       )
where

import HGraph.Undirected
import qualified Data.Map as M
import qualified Data.Set as S

data Graph a where
  Graph :: Ord a => M.Map a (S.Set a) -> Int -> Graph a

emptyGraph :: Ord a => Graph a
emptyGraph = Graph M.empty 0

instance UndirectedGraph Graph where
  empty (Graph _ _) = Graph M.empty 0
  vertices (Graph adj _) = M.keys adj
  numVertices (Graph adj _) = fromIntegral $ M.size adj
  edges (Graph adj _) = [(v,u) | (v, nv) <- M.assocs adj, u <- S.toList nv, u >= v]
  numEdges (Graph _ numE) = fromIntegral $ numE
  linearizeVertices g@(Graph adj _) = (g', assocs)
    where
      assocs = zip [0..] (M.keys adj)
      ltoi = M.fromList $ zip (M.keys adj) [0..]
      g' = foldr addEdge (foldr addVertex emptyGraph (map fst assocs)) $
            [ (ltoi M.! u, ltoi M.! v) | (u,v) <- edges g ]


instance Adjacency Graph where
  neighbors (Graph adj _) v = S.toList $ adj M.! v
  degree (Graph adj _) v = fromIntegral $ S.size $ adj M.! v
  edgeExists (Graph adj _) (v,u) = u `S.member` (adj M.! v)
  inducedSubgraph (Graph adj numE) vs = Graph adj' $ (M.foldl' (\s n -> s + S.size n) 0 adj') `div` 2
    where
      adj' = M.map (\n -> S.intersection n svs) $ M.restrictKeys adj svs
      svs = S.fromList vs

instance Mutable Graph where
  addVertex v (Graph adj nE) = Graph (M.insert v S.empty adj) nE
  removeVertex v g@(Graph adj nE) = 
    Graph (M.delete v $ foldr (M.adjust (S.delete v)) adj nv) (nE - (degree g v))
    where
      nv = neighbors g v
  addEdge (v,u) g@(Graph adj nE)
    | edgeExists g (v,u) = g
    | otherwise = Graph adj' (nE + 1)
      where
        adj' = M.insertWith S.union v (S.singleton u) $ M.insertWith S.union u (S.singleton v) adj
  removeEdge (v,u) g@(Graph adj nE)
    | not $ edgeExists g (v,u) = g
    | otherwise = Graph adj' (nE - 1)
      where
        adj' = M.adjust (S.delete u) v $ M.adjust (S.delete v) u adj