toysolver-0.7.0: src/ToySolver/Graph/Base.hs
{-# LANGUAGE FlexibleContexts #-}
-----------------------------------------------------------------------------
-- |
-- Module : ToySolver.Graph.Base
-- Copyright : (c) Masahiro Sakai 2020
-- License : BSD-style
--
-- Maintainer : masahiro.sakai@gmail.com
-- Stability : provisional
-- Portability : non-portable
--
-----------------------------------------------------------------------------
module ToySolver.Graph.Base
( EdgeLabeledGraph
, Graph
, graphToUnorderedEdges
, graphFromUnorderedEdges
, graphFromUnorderedEdgesWith
, isIndependentSet
) where
import Control.Monad
import Data.Array.IArray
import Data.Array.ST
import qualified Data.IntMap.Lazy as IntMap
import Data.IntMap.Lazy (IntMap)
import qualified Data.IntSet as IntSet
import Data.IntSet (IntSet)
type EdgeLabeledGraph a = Array Int (IntMap a)
type Graph = EdgeLabeledGraph ()
graphToUnorderedEdges :: EdgeLabeledGraph a -> [(Int, Int, a)]
graphToUnorderedEdges g = do
(node1, nodes) <- assocs g
(node2, a) <- IntMap.toList $ snd $ IntMap.split node1 nodes
return (node1, node2, a)
graphFromUnorderedEdges :: Int -> [(Int, Int, a)] -> EdgeLabeledGraph a
graphFromUnorderedEdges = graphFromUnorderedEdgesWith const
graphFromUnorderedEdgesWith :: (a -> a -> a) -> Int -> [(Int, Int, a)] -> EdgeLabeledGraph a
graphFromUnorderedEdgesWith f n es = runSTArray $ do
a <- newArray (0, n-1) IntMap.empty
let ins i x l = do
m <- readArray a i
writeArray a i $! IntMap.insertWith f x l m
forM_ es $ \(node1, node2, a) -> do
ins node1 node2 a
ins node2 node1 a
return a
isIndependentSet :: EdgeLabeledGraph a -> IntSet -> Bool
isIndependentSet g s = null $ do
(node1, node2, _) <- graphToUnorderedEdges g
guard $ node1 `IntSet.member` s
guard $ node2 `IntSet.member` s
return ()