smcdel-1.2.0: src/SMCDEL/Symbolic/K.hs
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, ScopedTypeVariables #-}
module SMCDEL.Symbolic.K where
import Data.Tagged
import Control.Arrow ((&&&),first)
import Data.Dynamic (fromDynamic)
import Data.HasCacBDD hiding (Top,Bot)
import Data.List (delete,intercalate,sort,intersect,nub,(\\))
import qualified Data.Map.Strict as M
import Data.Map.Strict ((!))
import Test.QuickCheck
import SMCDEL.Explicit.K
import SMCDEL.Internal.Help (apply,lfp,powerset)
import SMCDEL.Internal.TexDisplay
import SMCDEL.Language
import SMCDEL.Other.BDD2Form
import SMCDEL.Symbolic.S5 (State,texBDD,boolBddOf,texBddWith,bddEval,relabelWith)
import SMCDEL.Translations.S5 (booloutof)
mvP, cpP :: Prp -> Prp
mvP (P n) = P (2*n) -- represent p in the double vocabulary
cpP (P n) = P ((2*n) + 1) -- represent p' in the double vocabulary
-- | Map p or p' in double vocabulary to p in single vocabulary.
unmvcpP :: Prp -> Prp
unmvcpP (P m) | even m = P $ m `div` 2
| otherwise = P $ (m-1) `div` 2
mv, cp :: [Prp] -> [Prp]
mv = map mvP
cp = map cpP
unmv, uncp :: [Prp] -> [Prp]
-- | Go from p in double vocabulary to p in single vocabulary.
unmv = map f where
f (P m) | odd m = error "unmv failed: Number is odd!"
| otherwise = P $ m `div` 2
-- | Go from p' in double vocabulary to p in single vocabulary.
uncp = map f where
f (P m) | even m = error "uncp failed: Number is even!"
| otherwise = P $ (m-1) `div` 2
data Dubbel
type RelBDD = Tagged Dubbel Bdd
totalRelBdd, emptyRelBdd :: RelBDD
totalRelBdd = pure $ boolBddOf Top
emptyRelBdd = pure $ boolBddOf Bot
allsamebdd :: [Prp] -> RelBDD
allsamebdd ps = pure $ conSet [boolBddOf $ PrpF p `Equi` PrpF p' | (p,p') <- zip (mv ps) (cp ps)]
class TagBdd a where
tagBddEval :: [Prp] -> Tagged a Bdd -> Bool
tagBddEval truths querybdd = evaluateFun (untag querybdd) (\n -> P n `elem` truths)
instance TagBdd Dubbel
cpBdd :: Bdd -> RelBDD
cpBdd b = Tagged $ relabelFun (\n -> (2*n) + 1) b
mvBdd :: Bdd -> RelBDD
mvBdd b = Tagged $ relabelFun (2 *) b
unmvBdd :: RelBDD -> Bdd
unmvBdd (Tagged b) =
relabelFun (\n -> if even n then n `div` 2 else error ("Not even: " ++ show n ++ "in the RelBDD " ++ show b)) b
propRel2bdd :: [Prp] -> M.Map State [State] -> RelBDD
propRel2bdd props relation = pure $ disSet (M.elems $ M.mapWithKey linkbdd relation) where
linkbdd here theres =
con (booloutof (mv here) (mv props))
(disSet [ booloutof (cp there) (cp props) | there <- theres ] )
samplerel :: M.Map State [State]
samplerel = M.fromList [
( [] , [ [],[P 1],[P 2],[P 1, P 2] ] ),
( [P 1] , [ [P 1], [P 1, P 2] ] ),
( [P 2] , [ [P 2], [P 1, P 2] ] ),
( [P 1, P 2], [ [P 1, P 2] ] ) ]
relBddOfIn :: Agent -> KripkeModel -> RelBDD
relBddOfIn i (KrM m)
| not (distinctVal (KrM m)) = error "m does not have distinct valuations."
| otherwise = pure $ disSet (M.elems $ M.map linkbdd m) where
linkbdd (mapPropBool,mapAgentReach) =
con
(booloutof (mv here) (mv props))
(disSet [ booloutof (cp there) (cp props) | there<-theres ] )
where
props = M.keys mapPropBool
here = M.keys (M.filter id mapPropBool)
theres = map (truthsInAt (KrM m)) (mapAgentReach ! i)
data BelStruct = BlS [Prp] -- vocabulary
Bdd -- state law
(M.Map Agent RelBDD) -- observation laws
deriving (Eq,Show)
instance Pointed BelStruct State
type BelScene = (BelStruct,State)
instance Pointed BelStruct Bdd
type MultipointedBelScene = (BelStruct,Bdd)
instance HasVocab BelStruct where
vocabOf (BlS voc _ _) = voc
instance HasAgents BelStruct where
agentsOf (BlS _ _ obdds) = M.keys obdds
bddOf :: BelStruct -> Form -> Bdd
bddOf _ Top = top
bddOf _ Bot = bot
bddOf _ (PrpF (P n)) = var n
bddOf bls (Neg form) = neg $ bddOf bls form
bddOf bls (Conj forms) = conSet $ map (bddOf bls) forms
bddOf bls (Disj forms) = disSet $ map (bddOf bls) forms
bddOf bls (Xor forms) = xorSet $ map (bddOf bls) forms
bddOf bls (Impl f g) = imp (bddOf bls f) (bddOf bls g)
bddOf bls (Equi f g) = equ (bddOf bls f) (bddOf bls g)
bddOf bls (Forall ps f) = forallSet (map fromEnum ps) (bddOf bls f)
bddOf bls (Exists ps f) = existsSet (map fromEnum ps) (bddOf bls f)
bddOf bls@(BlS allprops lawbdd obdds) (K i form) = unmvBdd result where
result = forallSet ps' <$> (imp <$> cpBdd lawbdd <*> (imp <$> omegai <*> cpBdd (bddOf bls form)))
ps' = map fromEnum $ cp allprops
omegai = obdds ! i
bddOf bls@(BlS allprops lawbdd obdds) (Kw i form) = unmvBdd result where
result = dis <$> part form <*> part (Neg form)
part f = forallSet ps' <$> (imp <$> cpBdd lawbdd <*> (imp <$> omegai <*> cpBdd (bddOf bls f)))
ps' = map fromEnum $ cp allprops
omegai = obdds ! i
bddOf bls@(BlS voc lawbdd obdds) (Ck ags form) = lfp lambda top where
ps' = map fromEnum $ cp voc
lambda :: Bdd -> Bdd
lambda z = unmvBdd $
forallSet ps' <$>
(imp <$> cpBdd lawbdd <*>
(imp <$> (disSet <$> sequence [obdds ! i | i <- ags]) <*>
cpBdd (con (bddOf bls form) z)))
bddOf bls (Ckw ags form) = dis (bddOf bls (Ck ags form)) (bddOf bls (Ck ags (Neg form)))
bddOf bls (PubAnnounce f g) =
imp (bddOf bls f) (bddOf (bls `update` f) g)
bddOf bls (PubAnnounceW f g) =
ifthenelse (bddOf bls f)
(bddOf (bls `update` f) g)
(bddOf (bls `update` Neg f) g)
bddOf bls@(BlS props _ _) (Announce ags f g) =
imp (bddOf bls f) (restrict bdd2 (k,True)) where
bdd2 = bddOf (announce bls ags f) g
(P k) = freshp props
bddOf bls@(BlS props _ _) (AnnounceW ags f g) =
ifthenelse (bddOf bls f) bdd2a bdd2b where
bdd2a = restrict (bddOf (announce bls ags f ) g) (k,True)
bdd2b = restrict (bddOf (announce bls ags (Neg f)) g) (k,True)
(P k) = freshp props
bddOf bls (Dia (Dyn dynLabel d) f) =
con (bddOf bls preCon) -- 5. Prefix with "precon AND ..." (diamond!)
. relabelWith copyrelInverse -- 4. Copy back changeProps V_-^o to V_-
. simulateActualEvents -- 3. Simulate actual event(s) [see below]
. substitSimul [ (k, changeLaw ! p) -- 2. Replace changeProps V_- with postcons
| p@(P k) <- changeProps] -- (no "relabelWith copyrel", undone in 4)
. bddOf (bls `update` trf) -- 1. boolean equivalent wrt new struct
$ f
where
changeProps = M.keys changeLaw
copychangeProps = [(freshp $ vocabOf bls ++ addProps)..]
copyrelInverse = zip copychangeProps changeProps
(trf@(Trf addProps addLaw changeLaw _), shiftrel) = shiftPrepare bls trfUnshifted
(preCon,trfUnshifted,simulateActualEvents) =
case fromDynamic d of
-- 3. For a single pointed event, simulate actual event x outof V+
Just ((t,x) :: Event) -> ( preOf (t,x), t, (`restrictSet` actualAss) )
where actualAss = [(newK, P k `elem` x) | (P k, P newK) <- shiftrel]
Nothing -> case fromDynamic d of
-- 3. For a multipointed event, simulate a set of actual events by ...
Just ((t,xsBdd) :: MultipointedEvent) ->
( preOf (t,xsBdd), t
, existsSet (map fromEnum addProps) -- ... replacing addProps with assigments
. con actualsBdd -- ... that satisfy actualsBdd
. con (bddOf bls addLaw) -- ... and a precondition.
) where actualsBdd = relabelWith shiftrel xsBdd
Nothing -> error $ "cannot update belief structure with '" ++ dynLabel ++ "':\n " ++ show d
validViaBdd :: BelStruct -> Form -> Bool
validViaBdd bls@(BlS _ lawbdd _) f = top == imp lawbdd (bddOf bls f)
evalViaBdd :: BelScene -> Form -> Bool
evalViaBdd (bls@(BlS allprops _ _),s) f = let
bdd = bddOf bls f
b = restrictSet bdd list
list = [ (n, P n `elem` s) | (P n) <- allprops ]
in
case (b==top,b==bot) of
(True,_) -> True
(_,True) -> False
_ -> error $ "evalViaBdd failed: Composite BDD leftover!\n"
++ " bls: " ++ show bls ++ "\n"
++ " s: " ++ show s ++ "\n"
++ " form: " ++ show f ++ "\n"
++ " bdd: " ++ show bdd ++ "\n"
++ " list: " ++ show list ++ "\n"
++ " b: " ++ show b ++ "\n"
instance Semantics BelStruct where
isTrue = validViaBdd
instance Semantics BelScene where
isTrue = evalViaBdd
instance Semantics MultipointedBelScene where
isTrue (kns@(BlS _ lawBdd _),statesBdd) f =
let a = lawBdd `imp` (statesBdd `imp` bddOf kns f)
in a == top
instance Update BelStruct Form where
checks = [ ] -- unpointed structures can be updated with anything
unsafeUpdate bls@(BlS props lawbdd obs) psi =
BlS props (lawbdd `con` bddOf bls psi) obs
instance Update BelScene Form where
unsafeUpdate (kns,s) psi = (unsafeUpdate kns psi,s)
announce :: BelStruct -> [Agent] -> Form -> BelStruct
announce bls@(BlS props lawbdd obdds) ags psi = BlS newprops newlawbdd newobdds where
(P k) = freshp props
newprops = sort $ P k : props
newlawbdd = con lawbdd (imp (var k) (bddOf bls psi))
newobdds = M.mapWithKey newOfor obdds
newOfor i oi | i `elem` ags = con <$> oi <*> (equ <$> mvBdd (var k) <*> cpBdd (var k))
| otherwise = con <$> oi <*> (neg <$> cpBdd (var k)) -- p_psi'
statesOf :: BelStruct -> [State]
statesOf (BlS allprops lawbdd _) = map (sort.getTrues) prpsats where
bddvars = map fromEnum allprops
bddsats = allSatsWith bddvars lawbdd
prpsats = map (map (first toEnum)) bddsats
getTrues = map fst . filter snd
texRelBDD :: RelBDD -> String
texRelBDD (Tagged b) = texBddWith texRelProp b where
texRelProp n
| even n = show (n `div` 2)
| otherwise = show ((n - 1) `div` 2) ++ "'"
bddprefix, bddsuffix :: String
bddprefix = "\\begin{array}{l} \\scalebox{0.3}{"
bddsuffix = "} \\end{array} \n"
instance TexAble BelStruct where
tex (BlS props lawbdd obdds) = concat
[ " \\left( \n"
, tex props, ", "
, bddprefix, texBDD lawbdd, bddsuffix
, ", "
, intercalate ", " obddstrings
, " \\right) \n"
] where
obddstrings = map (bddstring . (fst &&& (texRelBDD . snd))) (M.toList obdds)
bddstring (i,os) = "\\Omega_{\\text{" ++ i ++ "}} = " ++ bddprefix ++ os ++ bddsuffix
instance TexAble BelScene where
tex (bls, state) = concat
[ " \\left( \n", tex bls, ", ", tex state, " \\right) \n" ]
instance TexAble MultipointedBelScene where
tex (bls, statesBdd) = concat
[ " \\left( \n"
, tex bls ++ ", "
, " \\begin{array}{l} \\scalebox{0.4}{"
, texBDD statesBdd
, "} \\end{array}\n "
, " \\right)" ]
cleanupObsLaw :: BelScene -> BelScene
cleanupObsLaw (BlS vocab law obs, s) = (BlS vocab law (M.map clean obs), s) where
clean relbdd = restrictLaw <$> relbdd <*> (con <$> cpBdd law <*> mvBdd law)
determinedVocabOf :: BelStruct -> [Prp]
determinedVocabOf strct = filter (\p -> validViaBdd strct (PrpF p) || validViaBdd strct (Neg $ PrpF p)) (vocabOf strct)
nonobsVocabOf :: BelStruct -> [Prp]
nonobsVocabOf (BlS vocab _law obs) = filter (`notElem` usedVars) vocab where
usedVars =
map unmvcpP
$ sort
$ nub
$ concatMap (map P . Data.HasCacBDD.allVarsOf . untag)
$ M.elems obs
withoutProps :: [Prp] -> BelStruct -> BelStruct
withoutProps propsToDel (BlS oldProps oldLawBdd oldObs) =
BlS
(oldProps \\ propsToDel)
(existsSet (map fromEnum propsToDel) oldLawBdd)
(M.map (fmap $ existsSet (map fromEnum propsToDel)) oldObs)
equivExtraVocabOf :: [Prp] -> BelStruct -> [(Prp,Prp)]
equivExtraVocabOf mainVocab bls =
[ (p,q) | p <- vocabOf bls \\ mainVocab, q <- vocabOf bls, p > q, validViaBdd bls (PrpF p `Equi` PrpF q) ]
replaceWithIn :: (Prp,Prp) -> BelStruct -> BelStruct
replaceWithIn (p,q) (BlS oldProps oldLaw oldObs) =
BlS (delete p oldProps) (changeBdd oldLaw) (fmap (fmap changeRelBdd) oldObs) where
changeBdd = Data.HasCacBDD.relabel [ (fromEnum p, fromEnum q) ]
changeRelBdd = Data.HasCacBDD.relabel $ sort [ (fromEnum $ mvP p, fromEnum $ mvP q)
, (fromEnum $ cpP p, fromEnum $ cpP q) ]
replaceEquivExtra :: [Prp] -> BelStruct -> (BelStruct,[(Prp,Prp)])
replaceEquivExtra mainVocab startBls = lfp step (startBls,[]) where
step (bls,replRel) = case equivExtraVocabOf mainVocab bls of
[] -> (bls,replRel)
((p,q):_) -> (replaceWithIn (p,q) bls, (p,q):replRel)
instance Optimizable BelStruct where
optimize myVocab bls = fst $ replaceEquivExtra myVocab $
withoutProps ((determinedVocabOf bls `intersect` nonobsVocabOf bls) \\ myVocab) bls
instance Optimizable MultipointedBelScene where
optimize myVocab (oldBls,oldStatesBdd) = (newKns,newStatesBdd) where
intermediateBls = withoutProps ((determinedVocabOf oldBls `intersect` nonobsVocabOf oldBls) \\ myVocab) oldBls
removedProps = vocabOf oldBls \\ vocabOf intermediateBls
intermediateStatesBdd = existsSet (map fromEnum removedProps) oldStatesBdd
(newKns,replRel) = replaceEquivExtra myVocab intermediateBls
newStatesBdd = Data.HasCacBDD.relabel [ (fromEnum p, fromEnum q) | (p,q) <-replRel ] intermediateStatesBdd
instance Arbitrary BelStruct where
arbitrary = do
numExtraVars <- choose (0,2)
let myVocabulary = defaultVocabulary ++ take numExtraVars [freshp defaultVocabulary ..]
(BF statelaw) <- sized (randomboolformWith myVocabulary) `suchThat` (\(BF bf) -> boolBddOf bf /= bot)
obs <- mapM (\i -> do
BF obsLaw <- sized $ randomboolformWith (sort $ mv myVocabulary ++ cp myVocabulary) -- FIXME should rather be a random BDD?
return (i,pure $ boolBddOf obsLaw)
) defaultAgents
return $ BlS myVocabulary (boolBddOf statelaw) (M.fromList obs)
shrink bls = [ withoutProps [p] bls | length (vocabOf bls) > 1, p <- vocabOf bls \\ defaultVocabulary ]
data Transformer = Trf
[Prp] -- addprops
Form -- event law
(M.Map Prp Bdd) -- changelaw
(M.Map Agent RelBDD) -- eventObs
deriving (Eq,Show)
instance HasAgents Transformer where
agentsOf (Trf _ _ _ obdds) = M.keys obdds
instance HasPrecondition Transformer where
preOf _ = Top
instance Pointed Transformer State
type Event = (Transformer,State)
instance HasPrecondition Event where
preOf (Trf addprops addlaw _ _, x) = simplify $ substitOutOf x addprops addlaw
instance Pointed Transformer Bdd
type MultipointedEvent = (Transformer,Bdd)
instance HasPrecondition MultipointedEvent where
preOf (Trf addprops addlaw _ _, xsBdd) =
simplify $ Exists addprops (Conj [ formOf xsBdd, addlaw ])
instance TexAble Transformer where
tex (Trf addprops addlaw changelaw eventObs) = concat
[ " \\left( \n"
, tex addprops, ", "
, tex addlaw, ", "
, tex changeprops, ", "
, intercalate ", " $ map snd . M.toList $ M.mapWithKey texChange changelaw, ", "
, intercalate ", " eobddstrings
, " \\right) \n"
] where
changeprops = M.keys changelaw
texChange prop changebdd = tex prop ++ " := " ++ tex (formOf changebdd)
eobddstrings = map (bddstring . (fst &&& (texRelBDD . snd))) (M.toList eventObs)
bddstring (i,os) = "\\Omega^+_{\\text{" ++ i ++ "}} = " ++ bddprefix ++ os ++ bddsuffix
instance TexAble Event where
tex (trf, eventFacts) = concat
[ " \\left( \n", tex trf, ", ", tex eventFacts, " \\right) \n" ]
instance TexAble MultipointedEvent where
tex (trf, eventStates) = concat
[ " \\left( \n"
, tex trf ++ ", \\ "
, " \\begin{array}{l} \\scalebox{0.4}{"
, texBDD eventStates
, "} \\end{array}\n "
, " \\right)" ]
-- | shift addprops to ensure that props and newprops are disjoint:
shiftPrepare :: BelStruct -> Transformer -> (Transformer, [(Prp,Prp)])
shiftPrepare (BlS props _ _) (Trf addprops addlaw changelaw eventObs) =
(Trf shiftaddprops addlawShifted changelawShifted eventObsShifted, shiftrel) where
shiftrel = sort $ zip addprops [(freshp props)..]
shiftaddprops = map snd shiftrel
-- apply the shifting to addlaw, changelaw and eventObs:
addlawShifted = replPsInF shiftrel addlaw
changelawShifted = M.map (relabelWith shiftrel) changelaw
-- to shift addObs we need shiftrel in the double vocabulary:
shiftrelMVCP = sort $ zip (mv addprops) (mv shiftaddprops)
++ zip (cp addprops) (cp shiftaddprops)
eventObsShifted = M.map (fmap $ relabelWith shiftrelMVCP) eventObs
instance Update BelScene Event where
unsafeUpdate (bls@(BlS props law obdds),s) (trf, eventFactsUnshifted) = (BlS newprops newlaw newobs, news) where
-- PART 1: SHIFTING addprops to ensure props and newprops are disjoint
(Trf addprops addlaw changelaw addObs, shiftrel) = shiftPrepare bls trf
-- the actual event:
eventFacts = map (apply shiftrel) eventFactsUnshifted
-- PART 2: COPYING the modified propositions
changeprops = M.keys changelaw
copyrel = zip changeprops [(freshp $ props ++ addprops)..]
copychangeprops = map snd copyrel
copyrelMVCP = sort $ zip (mv changeprops) (mv copychangeprops)
++ zip (cp changeprops) (cp copychangeprops)
-- PART 3: actual transformation
newprops = sort $ props ++ addprops ++ copychangeprops
newlaw = conSet $ relabelWith copyrel (con law (bddOf bls addlaw))
: [var (fromEnum q) `equ` relabelWith copyrel (changelaw ! q) | q <- changeprops]
newobs = M.mapWithKey (\i oldobs -> con <$> (relabelWith copyrelMVCP <$> oldobs) <*> (addObs ! i)) obdds
news = sort $ concat
[ s \\ changeprops
, map (apply copyrel) $ s `intersect` changeprops
, eventFacts
, filter (\ p -> bddEval (s ++ eventFacts) (changelaw ! p)) changeprops ]
instance Update BelStruct Transformer where
checks = [haveSameAgents]
unsafeUpdate bls ctrf = BlS newprops newlaw newobs where
(BlS newprops newlaw newobs, _) = unsafeUpdate (bls,undefined::State) (ctrf,undefined::State) -- using laziness!
instance Update BelScene MultipointedEvent where
unsafeUpdate (bls,s) (trfUnshifted, eventFactsBddUnshifted) =
update (bls,s) (trf,selectedEventState) where
(trf@(Trf addprops addlaw _ _), shiftRel) = shiftPrepare bls trfUnshifted
eventFactsBdd = relabelWith shiftRel eventFactsBddUnshifted
selectedEventState :: State
selectedEventState = map (P . fst) $ filter snd selectedEvent
selectedEvent = case
allSatsWith
(map fromEnum addprops)
(eventFactsBdd `con` restrictSet (bddOf bls addlaw) [ (k, P k `elem` s) | P k <- vocabOf bls ])
of
[] -> error "no selected event"
[this] -> this
more -> error $ "too many selected events: " ++ show more
-- TODO: test this!
instance Update MultipointedBelScene MultipointedEvent where
checks = [haveSameAgents] -- no need to check precondition, we allow an empty set of actual states
unsafeUpdate (bls@(BlS props _ _),statesBdd) (trfUnshifted, eventsBddUnshifted) =
(newBls, newStatesBdd) where
-- shiftPrepare first to ensure that eventsBdd is also shifted
(trf@(Trf addprops _ changelaw _), shiftRel) = shiftPrepare bls trfUnshifted
eventsBdd = relabelWith shiftRel eventsBddUnshifted
(newBls, _) = unsafeUpdate (bls,undefined::State) (trf,undefined::State) -- using laziness!
-- the actual event:
changeprops = M.keys changelaw
copyrel = zip changeprops [(freshp $ props ++ addprops)..]
newStatesBdd = conSet [ relabelWith copyrel statesBdd, eventsBdd ]
trfPost :: Event -> Prp -> Bdd
trfPost (Trf addprops _ changelaw _, x) p
| p `elem` M.keys changelaw = restrictLaw (changelaw ! p) (booloutof x addprops)
| otherwise = boolBddOf $ PrpF p
reduce :: Event -> Form -> Maybe Form
reduce _ Top = Just Top
reduce e Bot = Just $ Neg $ preOf e
reduce e (PrpF p) = Impl (preOf e) <$> Just (formOf $ trfPost e p)
reduce e (Neg f) = Impl (preOf e) <$> (Neg <$> reduce e f)
reduce e (Conj fs) = Conj <$> mapM (reduce e) fs
reduce e (Disj fs) = Disj <$> mapM (reduce e) fs
reduce e (Xor fs) = Impl (preOf e) <$> (Xor <$> mapM (reduce e) fs)
reduce e (Impl f1 f2) = Impl <$> reduce e f1 <*> reduce e f2
reduce e (Equi f1 f2) = Equi <$> reduce e f1 <*> reduce e f2
reduce _ (Forall _ _) = Nothing
reduce _ (Exists _ _) = Nothing
reduce e@(t@(Trf addprops _ _ eventObs), x) (K a f) =
Impl (preOf e) <$> (Conj <$> sequence
[ K a <$> reduce (t,y) f | y <- powerset addprops -- FIXME is this a bit much?
, tagBddEval (mv x ++ cp y) (eventObs ! a)
])
reduce e (Kw a f) = reduce e (Disj [K a f, K a (Neg f)])
reduce _ Ck {} = Nothing
reduce _ Ckw {} = Nothing
reduce _ PubAnnounce {} = Nothing
reduce _ PubAnnounceW {} = Nothing
reduce _ Announce {} = Nothing
reduce _ AnnounceW {} = Nothing
reduce _ Dia {} = Nothing
bddReduce :: BelScene -> Event -> Form -> Bdd
bddReduce scn@(oldBls,_) event@(Trf addprops _ changelaw _, eventFacts) f =
let
changeprops = M.keys changelaw
-- same as in 'transform', to ensure props and addprops are disjoint
shiftaddprops = [(freshp $ vocabOf scn)..]
shiftrel = sort $ zip addprops shiftaddprops
-- apply the shifting to addlaw and changelaw:
changelawShifted = M.map (relabelWith shiftrel) changelaw
(newBlS,_) = update scn event
-- the actual event, shifted
actualAss = [ (shifted, P orig `elem` eventFacts) | (P orig, P shifted) <- shiftrel ]
postconrel = [ (n, changelawShifted ! P n) | (P n) <- changeprops ]
-- reversing V^o to V
copychangeprops = [(freshp $ vocabOf scn ++ map snd shiftrel)..]
copyrelInverse = zip copychangeprops changeprops
in
imp (bddOf oldBls (preOf event)) $ -- 0. check if precondition holds
relabelWith copyrelInverse $ -- 4. changepropscopies -> original changeprops
(`restrictSet` actualAss) $ -- 3. restrict to actual event x outof V+
substitSimul postconrel $ -- 2. replace changeprops with postconditions
bddOf newBlS f -- 1. boolean equivalent wrt new structure
evalViaBddReduce :: BelScene -> Event -> Form -> Bool
evalViaBddReduce (bls,s) event f = evaluateFun (bddReduce (bls,s) event f) (\n -> P n `elem` s)