packages feed

hgraph-1.2.0.0: src/HGraph/Undirected/Solvers/IndependentSet.hs

module HGraph.Undirected.Solvers.IndependentSet
        ( maximize
        , atLeast
        , reduce
        )
where

import Data.Maybe
import HGraph.Undirected
import HGraph.Utils

-- | Find a maximum independet set in `g`
maximize g = last [fromJust x | k <- [1..numVertices g], let x = atLeast g k, isJust x]

-- | Search for an independent set of size at least `k` in `g`
atLeast g k
  | k <= 0 = Just []
  | numVertices g == 0 = Nothing
  | otherwise = 
    let (g', xs, k') = reduce g k
    in
    if k' >= k then
      Just xs
    else
      fmap (xs ++) $ 
        mhead [ u : fromJust ys
              | u <- vertices g'
              , let ys = atLeast (foldr (flip removeVertex) g' $ u : neighbors g' u) (k - 1 - k')
              , isJust ys]

reduce g k
  | k <= 0 = (g, [], 0)
  | k > (numVertices g) || (k == (numVertices g) && numEdges g > 0) = (empty g, [], 0)
  | otherwise = 
    let xs0 = filter (\v -> degree g v == 0) $ vertices g
        xsn = filter (\v -> degree g v >= (numVertices g) - k + 1) $ vertices g
        g' = foldr (flip removeVertex) g (xsn ++ xs0)
        x1  = take 1 $ filter (\v -> degree g' v == 1) $ vertices g'
    in case x1 of
        [v] ->
          let k0 = length xs0
              g'' = foldr (flip removeVertex) g' $ v : neighbors g' v
              (g''', xs', k') = reduce g'' (k - k0 - 1)
          in (g''', v:xs0 ++ xs', 1 + k0 + k')
        [] -> (g', xs0, length xs0)