packages feed

liquid-fixpoint-8.10.7: src/Language/Fixpoint/Congruence/Closure.hs

module Language.Fixpoint.Congruence.Closure where 

-- import           Data.Hashable
import           Data.Interned
import           Control.Monad
-- import           Control.Monad.Except      -- (MonadError(..))
import           Control.Monad.State.Strict
import qualified Data.HashMap.Strict        as M
import           Language.Fixpoint.Congruence.Types 
import           Language.Fixpoint.Misc       (ifM)

sat :: CongQuery -> Bool 
sat = undefined

type UF = State UFState

data UFState = U 
  { ufPar   :: M.HashMap Id Term          -- ^ i :-> t      IF term 'i' has union-find parent 't'
  , ufPreds :: M.HashMap Id [(Int, Term)] -- ^ i :-> (j, t) IF term 'i' is 'j'-th arg in application 't'
  }

parent :: Term -> UF (Maybe Term)
parent u = M.lookup (identity u) <$> gets ufPar

find :: Term -> UF Id
find u = do 
  mbU' <- parent u 
  case mbU' of
    Nothing -> return (identity u) 
    Just u' -> find u'  

union :: Term -> Term -> UF () 
union _u _v = undefined -- _TODO 

preds :: Id -> UF [(Int, Term)]
preds = undefined -- _TODO 

isCong :: Term -> Term -> UF Bool 
isCong = undefined -- _TODO 

isEq :: Term -> Term -> UF Bool 
isEq u v = do 
  ui <- find u 
  vi <- find v 
  return (ui == vi)

congMerge :: (Int, Term) -> (Int, Term) -> UF ()
congMerge (i, u) (j, v) 
  | i == j = ifM (isEq u v) 
              (return ())
              (ifM (isCong u v) 
                (merge u v)
                (return ()))
  | otherwise = return ()  

merge :: Term -> Term -> UF ()
merge u v = do 
  ui <- find u
  vi <- find v 
  unless (ui == vi) $ do 
    uPs <- preds ui 
    vPs <- preds vi 
    union u v
    forM_ uPs $ \u' ->
      forM_ vPs $ \v' -> 
        congMerge u' v'