packages feed

tpdb-2.7.1: src/TPDB/DP/Usable.hs

module TPDB.DP.Usable where

import TPDB.Data
import TPDB.Pretty

import TPDB.DP.Unify
import TPDB.DP.TCap

import qualified Data.IntSet as S
import qualified Data.IntMap.Strict as M

-- | restrict one SCC to its usable rules.
-- DANGER: this ignores the CE condition
restrict :: (Eq c, Ord v, TermC v c) => RS c (Term v c) -> RS c (Term v c)
restrict dp = 
    dp { rules = filter strict (rules dp)
               ++ usable dp
       }

-- | computes the least closed set of usable rules, cf. Def 4.5
-- http://cl-informatik.uibk.ac.at/users/griff/publications/Sternagel-Thiemann-RTA10.pdf

usable :: (Eq c, Ord v, TermC v c)
       => TRS v c -> [Rule (Term v c)]
usable dp =
  let dpi = M.fromList $ zip [0..] $ rules dp
      fp = fixpoint
        ( \ s -> S.union s $ required dpi $ S.toList s)
        (required dpi $ map fst $ filter (strict . snd) $ M.toList dpi)
  in  map (dpi M.!) $ S.toList fp

fixpoint f x = 
    let y = f x in if x == y then x else fixpoint f y

-- | indices of rules that can be used
-- to rewrite rhs of rules with indices @is@
required :: (Eq c, Ord v, TermC v c)
       => M.IntMap ( Rule (Term v c) )
         -> [ Int ]
         -> S.IntSet
required dpi is =  S.fromList
  $ concatMap (needed dpi)
  $ map (rhs . (dpi M.!)) is

-- | indices of rules that can be used
-- to rewrite the given term @t@ (including subterms)
needed :: (Eq c, Ord v, TermC v c)
       => M.IntMap (Rule (Term v c))
       -> Term v c
       -> [ Int ]
needed dpi t = case t of
    Node f args -> (map fst
         $ filter ( \ (j,u) -> unifies ( vmap Left $ lhs u ) ( vmap Right $ tcap (M.elems dpi) t ) )
         $ filter ( not . strict . snd)
         $ M.toList dpi)
        ++ ( args >>= needed dpi )
    Var v -> []