hgraph-1.2.0.0: src/HGraph/Undirected/Solvers/VertexCover.hs
module HGraph.Undirected.Solvers.VertexCover
( minimumVertexCover
, vertexCoverAtMost
)
where
import HGraph.Undirected
import Control.Monad
import Data.Maybe
import qualified Data.Map as M
import qualified Data.Set as S
minimumVertexCover :: (Mutable t, UndirectedGraph t, Adjacency t) => t a -> [a]
minimumVertexCover g = map (itol M.!) $ fromJust $ foldr mplus Nothing $ map (vertexCoverAtMost' gi) [1..]
where
(gi, assocs) = linearizeVertices g
itol = M.fromList assocs
vertexCoverAtMost :: (Mutable t, UndirectedGraph t, Adjacency t) => t a -> Int -> Maybe [a]
vertexCoverAtMost g k = fmap (map (itol M.!)) $ vertexCoverAtMost' gi k
where
(gi, assocs) = linearizeVertices g
itol = M.fromList assocs
vertexCoverAtMost' :: (Mutable t, UndirectedGraph t, Adjacency t) => t Int -> Int -> Maybe [Int]
vertexCoverAtMost' g k
| k < 0 = Nothing
| k' < 0 = Nothing
| numEdges g' == 0 = Just sol'
| numEdges g' > k * k = Nothing
| otherwise =
(fmap (v:) $ vertexCoverAtMost' (removeVertex g' v) (k'-1)) `mplus`
(fmap (nv++) $ vertexCoverAtMost' (foldr (flip removeVertex) g' (v:nv)) (k' - (degree g' v)))
where
(g', sol', k') = reduce g k
e' = edges g'
(v,_) = head e'
nv = neighbors g' v
reduce g k = reduce' g k [] (vertices g) S.empty
reduce' g k sol [] _ = (g,sol,k)
reduce' g k sol (v:vs) visited
| v `S.member` visited = reduce' g k sol vs visited
| d == 1 = reduce' (removeVertex (removeVertex g v) u) (k-1) (u:sol) (un ++ vs)
( (S.insert v $ S.insert u visited) `S.difference`
(S.delete v $ S.fromList un))
| d == 0 = reduce' (removeVertex g v) k sol vs (S.insert v visited)
| d > k = reduce' (removeVertex g v) (k - 1) (v:sol) (vn ++ vs)
((S.insert v visited) `S.difference` (S.fromList vn))
| otherwise = reduce' g k sol vs (S.insert v visited)
where
d = degree g v
u = head $ neighbors g v
un = neighbors g u
vn = neighbors g v