tamarin-prover-0.8.0.0: src/Theory/Tools/InjectiveFactInstances.hs
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-- |
-- Copyright : (c) 2012 Simon Meier
-- License : GPL v3 (see LICENSE)
--
-- Maintainer : Simon Meier <iridcode@gmail.com>
-- Portability : portable
--
-- Computate an under-approximation to the set of all facts with unique
-- instances, i.e., fact whose instances never occur more than once in a
-- state. We use this information to reason about protocols that exploit
-- exclusivity of linear facts.
module Theory.Tools.InjectiveFactInstances (
-- * Computing injective fact instances.
simpleInjectiveFactInstances
) where
import Extension.Prelude (sortednub)
import Control.Applicative
import Control.Monad.Fresh
import Data.Label
import qualified Data.Set as S
import Safe (headMay)
import Theory.Model
-- | Compute a simple under-approximation to the set of facts with injective
-- instances. A fact-tag is has injective instances, if there is no state of
-- the protocol with more than one instance with the same term as a first
-- argument of the fact-tag.
--
-- We compute the under-approximation by checking that
-- (1) the fact-tag is linear,
-- (2) every introduction of such a fact-tag is protected by a Fr-fact of the
-- first term, and
-- (3) every rule has at most one copy of this fact-tag in the conlcusion and
-- the first term arguments agree.
--
-- We exclude facts that are not copied in a rule, as they are already handled
-- properly by the naive backwards reasoning.
simpleInjectiveFactInstances :: [ProtoRuleE] -> S.Set FactTag
simpleInjectiveFactInstances rules = S.fromList $ do
tag <- candidates
guard (all (guardedSingletonCopy tag) rules)
return tag
where
candidates = sortednub $ do
ru <- rules
tag <- factTag <$> get rConcs ru
guard $ (factTagMultiplicity tag == Linear)
&& (tag `elem` (factTag <$> get rPrems ru))
return tag
guardedSingletonCopy tag ru =
length copies <= 1 && all guardedCopy copies
where
prems = get rPrems ru
copies = filter ((tag ==) . factTag) (get rConcs ru)
firstTerm = headMay . factTerms
-- True if there is a first term and a premise guarding it
guardedCopy faConc = case firstTerm faConc of
Nothing -> False
Just tConc -> freshFact tConc `elem` prems || guardedInPrems tConc
-- True if there is a premise with the same tag and first term
guardedInPrems tConc = (`any` prems) $ \faPrem ->
factTag faPrem == tag && maybe False (tConc ==) (firstTerm faPrem)