smcdel-1.0.0: src/SMCDEL/Examples/GossipS5.hs
module SMCDEL.Examples.GossipS5 where
import SMCDEL.Language
import SMCDEL.Symbolic.S5 hiding (Event)
import SMCDEL.Symbolic.S5.Change
import Data.Map.Strict (fromList,keys)
import Data.List ((\\))
gossipers :: Int -> [Int]
gossipers n = [0..(n-1)]
hasSof :: Int -> Int -> Int -> Prp
hasSof n a b | a == b = error "Let's not even talk about that."
| otherwise = toEnum (n * a + b)
has :: Int -> Int -> Int -> Form
has n a b = PrpF (hasSof n a b)
expert :: Int -> Int -> Form
expert n a = Conj [ PrpF (hasSof n a b) | b <- gossipers n, a /= b ]
allExperts :: Int -> Form
allExperts n = Conj [ expert n a | a <- gossipers n ]
gossipInit :: Int -> KnowScene
gossipInit n = (KnS vocab law obs, actual) where
vocab = [ hasSof n i j | i <- gossipers n, j <- gossipers n, i /= j ]
law = boolBddOf $ Conj [ Neg $ PrpF $ hasSof n i j
| i <- gossipers n, j <- gossipers n, i /= j]
obs = [ (show i, []) | i <- gossipers n ]
actual = [ ]
thisCallProp :: (Int,Int) -> Prp
thisCallProp (i,j) | i < j = P (100 + 10*i + j)
| otherwise = error $ "wrong call: " ++ show (i,j)
call :: Int -> (Int,Int) -> Event
call n (a,b) = (callTrf n, [thisCallProp (a,b)])
callTrf :: Int -> KnowChange
callTrf n = CTrf eventprops eventlaw changeprops changelaws eventobs where
thisCallHappens (i,j) = PrpF $ thisCallProp (i,j)
isInCallForm k = Disj $ [ thisCallHappens (i,k) | i <- gossipers n \\ [k], i < k ]
++ [ thisCallHappens (k,j) | j <- gossipers n \\ [k], k < j ]
allCalls = [ (i,j) | i <- gossipers n, j <- gossipers n, i < j ]
eventprops = map thisCallProp allCalls
eventlaw = simplify $
Conj [ Disj (map thisCallHappens allCalls)
-- some call must happen, but never two at the same time:
, Neg $ Disj [ Conj [thisCallHappens c1, thisCallHappens c2]
| c1 <- allCalls, c2 <- allCalls \\ [c1] ] ]
callPropsWith k = [ thisCallProp (i,k) | i <- gossipers n, i < k ]
++ [ thisCallProp (k,j) | j <- gossipers n, k < j ]
eventobs = fromList [(show k, callPropsWith k) | k <- gossipers n]
changeprops = keys changelaws
changelaws = fromList
[(hasSof n i j, boolBddOf $ -- after a call, i has the secret of j iff
Disj [ has n i j -- i already knew j, or
, Conj (map isInCallForm [i,j]) -- i and j are both in the call or
, Conj [ isInCallForm i -- i is in the call and there is some k in
, Disj [ Conj [ isInCallForm k, has n k j ] -- the call who knew j
| k <- gossipers n \\ [j] ] ]
])
| i <- gossipers n, j <- gossipers n, i /= j ]
doCall :: KnowScene -> (Int,Int) -> KnowScene
doCall start (a,b) = knowChange start (call (length $ agentsOf start) (a,b)) -- TODO optimize here!
after :: Int -> [(Int,Int)] -> KnowScene
after n = foldl doCall (gossipInit n)
isSuccess :: Int -> [(Int,Int)] -> Bool
isSuccess n cs = evalViaBdd (after n cs) (allExperts n)
whoKnowsMeta :: KnowScene -> [(Int,[(Int,String)])]
whoKnowsMeta scn = [ (k, map (meta k) [0..maxid] ) | k <- [0..maxid] ] where
n = length (agentsOf scn)
maxid = n - 1
meta x y = (y, map (knowsAbout x y) [0..maxid])
knowsAbout x y i
| y == i = 'X'
| evalViaBdd scn ( K (show x) $ PrpF (hasSof n y i)) = 'Y'
| evalViaBdd scn (Neg $ K (show x) $ Neg $ PrpF (hasSof n y i)) = '?'
| evalViaBdd scn ( K (show x) $ Neg $ PrpF (hasSof n y i)) = '_'
| otherwise = 'E'
allSequs :: Int -> Int -> [ [(Int,Int)] ]
allSequs _ 0 = [ [] ]
allSequs n l = [ (i,j):rest | rest <- allSequs n (l-1), i <- gossipers n, j <- gossipers n, i < j ]