liquid-fixpoint-0.5.0.0: src/Language/Fixpoint/Solver/Eliminate.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE BangPatterns #-}
module Language.Fixpoint.Solver.Eliminate (eliminate) where
import qualified Data.HashSet as S
import qualified Data.HashMap.Strict as M
import Language.Fixpoint.Types
import Language.Fixpoint.Types.Visitor (kvars, isConcC)
import Language.Fixpoint.Partition (depCuts, depNonCuts, deps)
import Language.Fixpoint.Misc (safeLookup, group, errorstar)
--------------------------------------------------------------------------------
eliminate :: SInfo a -> (Solution, SInfo a)
--------------------------------------------------------------------------------
eliminate si = ( sHyp, si' )
where
sHyp = solFromList [] kHyps
si' = cutSInfo kI cKs si
kHyps = nonCutHyps kI nKs si
kI = kIndex si
(cKs,nKs) = kutVars si
kutVars :: SInfo a -> (S.HashSet KVar, S.HashSet KVar)
kutVars si = (depCuts ds, depNonCuts ds)
where
ds = deps si
--------------------------------------------------------------------------------
-- | Map each `KVar` to the list of constraints on which it appears on RHS
--------------------------------------------------------------------------------
type KIndex = M.HashMap KVar [Integer]
--------------------------------------------------------------------------------
kIndex :: SInfo a -> KIndex
--------------------------------------------------------------------------------
kIndex si = group [(k, i) | (i, c) <- iCs, k <- rkvars c]
where
iCs = M.toList (cm si)
rkvars = kvars . crhs
cutSInfo :: KIndex -> S.HashSet KVar -> SInfo a -> SInfo a
cutSInfo kI cKs si = si { ws = ws', cm = cm' }
where
ws' = M.filterWithKey (\k _ -> S.member k cKs) (ws si)
cm' = M.filterWithKey (\i c -> S.member i cs || isConcC c) (cm si)
cs = S.fromList (concatMap kCs cKs)
kCs k = M.lookupDefault [] k kI
nonCutHyps :: KIndex -> S.HashSet KVar -> SInfo a -> [(KVar, Hyp)]
nonCutHyps kI nKs si = [ (k, nonCutHyp kI si k) | k <- S.toList nKs ]
nonCutHyp :: KIndex -> SInfo a -> KVar -> Hyp
nonCutHyp kI si k = nonCutCube <$> cs
where
cs = getSubC si <$> M.lookupDefault [] k kI
nonCutCube :: SimpC a -> Cube
nonCutCube c = Cube (senv c) (rhsSubst c)
rhsSubst :: SimpC a -> Subst
rhsSubst = rsu . crhs
where
rsu (PKVar _ su) = su
rsu _ = errorstar "Eliminate.rhsSubst called on bad input"
getSubC :: SInfo a -> Integer -> SimpC a
getSubC si i = safeLookup msg i (cm si)
where
msg = "getSubC: " ++ show i
--------------------------------------------------------------------------------
{-
eliminateAll :: SInfo a -> (Solution, SInfo a)
eliminateAll !si = foldl' eliminate (mempty, si) nonCuts
where
nonCuts = depNonCuts $ deps si
eliminate :: (Solution, SInfo a) -> KVar -> (Solution, SInfo a)
eliminate (!s, !si) k = (solInsert k (mkJVar orPred) s, si')
where
si' = si { cm = nokCs , ws = M.delete k $ ws si }
kCs = M.filter ( elem k . kvars . crhs) (cm si) -- with k in RHS (SLOW!)
nokCs = M.filter (notElem k . kvars . crhs) (cm si) -- without k in RHS (SLOW!)
kW = (ws si) M.! k
kDom = domain (bs si) kW
orPred = POr $!! extractPred kDom (bs si) <$> M.elems kCs
extractPred :: [Symbol] -> BindEnv -> SimpC a -> Expr
extractPred kDom be sc = renameQuantified (subcId sc) kSol
where
kSol = PExist xts $ PAnd (lhsPreds ++ suPreds)
xts = filter (nonFunction be . fst) yts
yts = second sr_sort <$> env
env = clhs be sc
lhsPreds = bindPred <$> env
suPreds = substPreds kDom $ crhs sc
-- x:{v:int|v=10} -> (x=10)
bindPred :: (Symbol, SortedReft) -> Expr
bindPred (x, sr) = p `subst1`(v, eVar x)
where
v = reftBind r
r = sr_reft sr
p = reftPred r
-- k0[v:=e1][x:=e2] -> [v = e1, x = e2]
substPreds :: [Symbol] -> Expr -> [Expr]
substPreds dom (PKVar _ (Su subs)) = [PAtom Eq (eVar x) e | (x, e) <- M.toList subs , x `elem` dom]
substPreds _ _ = errorstar "Eliminate.substPreds called on bad input"
-- SLOW!
nonFunction :: BindEnv -> Symbol -> Bool
nonFunction be sym = sym `notElem` funcs
where
funcs = [x | (_, x, sr) <- bindEnvToList be
, isFunctionSortedReft sr]
renameQuantified :: Integer -> Expr -> Expr
renameQuantified i (PExist bs p) = PExist bs' p'
where
su = substFromQBinds i bs
bs' = first (subst su) <$> bs
p' = subst su p
renameQuantified _ _ = errorstar "Eliminate.renameQuantified called on bad input"
substFromQBinds :: Integer -> [(Symbol, Sort)] -> Subst
substFromQBinds i bs = Su $ M.fromList [(s, EVar $ existSymbol s i) | s <- fst <$> bs]
-}