packages feed

lambdabot-4.1: scripts/FT/FreeTheorems/Specialization.hs

-- Copyright 2006, Sascha Boehme.




-- | This module defines function which are used in specializing relations to
--   functions.

module FreeTheorems.Specialization (
    extractRelationVariables,
    replaceRelationVariable
) where



import FreeTheorems.Simplification
import FreeTheorems.TheoremData
import FreeTheorems.Types
import FreeTheorems.Unfolding
import Control.Monad (liftM)



-- | Returns all relation variables of a theorem which can be specialized to a
--   function.
--   Relation variables being quantified on the left-hand side of an implication
--   can not be specialized. However, relation variables being quantified like
--
-- >   ((forall R. theorem) ==> theorem1) ==> theorem2
--
--   can be specialized. Thus, the position relative to implications decides
--   whether a relation variable is returned by this function.

extractRelationVariables :: Theorem -> [RelationVariable]
extractRelationVariables theorem = extractRelVars True theorem



-- | Returns all relation variables of a theorem which can be specialized to a
--   function. This is a helper function for 'extractRelationVariables' and uses
--   its first argument to decide if a relation variable can be specialized to a
--   function.

extractRelVars :: Bool -> Theorem -> [RelationVariable]
extractRelVars takeRVs theorem =
  case theorem of
    IsElementOf _ _         -> []
    ForallPairs _ _ t       -> extractRelVars takeRVs t
    ForallRelations rv _ t  -> if takeRVs
                                 then rv : (extractRelVars takeRVs t)
                                 else extractRelVars takeRVs t
    ForallFunctions _ _ _ t -> extractRelVars takeRVs t
    ForallElements _ _ t    -> extractRelVars takeRVs t
    Conjunction t1 t2       -> extractRelVars takeRVs t1
                               ++ extractRelVars takeRVs t2
    Implication t1 t2       -> extractRelVars (not takeRVs) t1
                               ++ extractRelVars takeRVs t2



--------------------------------------------------------------------------------



-- | Replaces a relation variable found by 'extractRelationVariables' in the
--   given theorem. A new function symbol is created to replace the relation
--   variable. The returned theorem is simplified by 'simplifyTheorem'.

replaceRelationVariable :: Theorem -> RelationVariable -> TheoremState Theorem
replaceRelationVariable theorem rv = do
  f <- newRelationAsFunctionVariable
  return $ simplifyTheorem (replaceRelVar rv f theorem)



-- | Replaces every occurrence of a relation variable by the given term
--   variable. This is a helper function for 'replaceRelationVariable'.

replaceRelVar :: RelationVariable -> TermVariable -> Theorem -> Theorem
replaceRelVar rv f theorem =
  case theorem of
    IsElementOf p r       -> IsElementOf p (replaceInRel rv f [] r)

    ForallPairs p r t     -> let r' = replaceInRel rv f [] r
                                 t' = replaceRelVar rv f t
                             in  adjustForallPairs p r' t'

    ForallRelations rv' res t -> let t'   = replaceRelVar rv f t
                                     res' = map (updateRestriction f) res
                                     R _ _ types = rv
                                 in  if rv == rv'
                                       then ForallFunctions f types res' t'
                                       else ForallRelations rv'     res  t'

    ForallFunctions f' types res t -> ForallFunctions f' types res
                                                      (replaceRelVar rv f t)

    ForallElements x ty t -> ForallElements x ty (replaceRelVar rv f t)

    Conjunction t1 t2     -> Conjunction (replaceRelVar rv f t1)
                                         (replaceRelVar rv f t2)

    Implication t1 t2     -> Implication (replaceRelVar rv f t1)
                                         (replaceRelVar rv f t2)



-- | Takes a restriction for a relation variable and transforms it into a
--   restriction for the given term variable.

updateRestriction :: TermVariable -> Restriction -> Restriction
updateRestriction f res =
  case res of
    IsStrictAndContinuous _ -> IsStrict f
    otherwise               -> res



-- | Replaces every occurrence of the given relation variable by the given term
--   variable in a relation.
--   The third argument gives a list of relation variables bound in the current
--   environment.

replaceInRel :: RelationVariable
                -> TermVariable
                -> [RelationVariable]
                -> Relation
                -> Relation

replaceInRel rv f rvs rel =
  case rel of
    RelTerm _ _          -> rel
    RelVar rv'           -> if (rv' `elem` rvs) || (rv' /= rv)
                              then RelVar rv'
                              else let R _ _ (ttv1, ttv2) = rv
                                       types = ( TypeTermVar ttv1
                                               , TypeTermVar ttv2)
                                   in  RelTerm (TermVar f) types
    RelLift m c rels     -> RelLift m c (map (replaceInRel rv f rvs) rels)
    RelLiftList m rel'   -> adjustLiftList m (replaceInRel rv f rvs rel')
    RelLiftTuple m rels  -> RelLiftTuple m (map (replaceInRel rv f rvs) rels)
    RelFun m rel1 rel2   -> RelFun m (replaceInRel rv f rvs rel1)
                                     (replaceInRel rv f rvs rel2)
    RelForall m rv' rel' -> RelForall m rv' (replaceInRel rv f (rv':rvs) rel')



-- | Creates a proper notation of a lifted list relation. If the argument
--   relation is a function, the list relation is replaced by @map@.

adjustLiftList :: LanguageModel -> Relation -> Relation
adjustLiftList model rel =
  case rel of
    RelTerm t (ty1, ty2) -> let tmap  = TermVar (PV "map")
                                tmap' = (TermIns (TermIns tmap ty1) ty2)
                            in  RelTerm (TermApp tmap' t)
                                        (TypeList ty1, TypeList ty2)
    otherwise            -> RelLiftList model rel



-- | Creates a proper notation for abstractions over term variables. If the
--   corresponding relation is a function, then the term variables abstraction
--   uses a different notation.

adjustForallPairs :: (TermVariable, TermVariable)
                     -> Relation
                     -> Theorem
                     -> Theorem

adjustForallPairs (tv1, tv2) rel theorem =
  case rel of
    RelTerm _ _ -> let (ty1, ty2)  = getTypesOf rel
                   in  ForallElements tv1 ty1
                       $ ForallElements tv2 ty2
                       $ Implication
                           (IsElementOf (TermVar tv1, TermVar tv2) rel)
                           theorem
    otherwise   -> ForallPairs (tv1, tv2) rel theorem