|
module Systems where
|
|
|
|
import qualified Data.Map.Strict as Map
|
|
import qualified Data.Set as Set
|
|
import Data.Map.Strict (Map)
|
|
import Data.Set (Set)
|
|
import Data.List
|
|
|
|
import Presyntax
|
|
|
|
newtype Face = Face { getFace :: Map String Bool }
|
|
deriving (Eq, Show, Ord)
|
|
|
|
evalFormula :: Formula -> Face -> Bool
|
|
evalFormula (Is0 x) f =
|
|
case Map.lookup x (getFace f) of
|
|
Just x -> not x
|
|
Nothing -> error $ "dimension not bound in formula: " ++ show x
|
|
|
|
evalFormula (Is1 x) f =
|
|
case Map.lookup x (getFace f) of
|
|
Just x -> x
|
|
Nothing -> error $ "dimension not bound in formula: " ++ show x
|
|
|
|
evalFormula (And a b) f = evalFormula a f && evalFormula b f
|
|
evalFormula (Or a b) f = evalFormula a f || evalFormula b f
|
|
|
|
evalFormula Top _ = True
|
|
evalFormula Bot _ = False
|
|
|
|
freeVarsFormula :: Formula -> Set String
|
|
freeVarsFormula (Is0 x) = Set.singleton x
|
|
freeVarsFormula (Is1 x) = Set.singleton x
|
|
freeVarsFormula (And a b) = Set.union (freeVarsFormula a) (freeVarsFormula b)
|
|
freeVarsFormula (Or a b) = Set.union (freeVarsFormula a) (freeVarsFormula b)
|
|
freeVarsFormula Top = mempty
|
|
freeVarsFormula Bot = mempty
|
|
|
|
faces :: Formula -> ([Face], [Face])
|
|
faces formula = partition (evalFormula formula) allPossible where
|
|
truths [] = [mempty]
|
|
truths (x:xs) = uncurry Map.insert <$> [(x, True), (x, False)] <*> truths xs
|
|
|
|
allPossible = Face <$> truths (Set.toList (freeVarsFormula formula))
|
|
|
|
impossible, possible, tautological :: Formula -> Bool
|
|
impossible = null . fst . faces
|
|
possible = not . null . fst . faces
|
|
tautological = not . null . snd . faces
|
|
|
|
toDNF :: Formula -> Formula
|
|
toDNF = orFormula . map formulaOfFace . fst . faces
|
|
|
|
formulaOfFace :: Face -> Formula
|
|
formulaOfFace = andFormula . map (\(x, i) -> if i then Is1 x else Is0 x) . Map.toDescList . getFace
|
|
|
|
andFormula :: [Formula] -> Formula
|
|
andFormula = foldr and Top where
|
|
and x y =
|
|
case x of
|
|
Top -> case y of
|
|
Bot -> Bot
|
|
_ -> y
|
|
Bot -> Bot
|
|
_ -> case y of
|
|
Top -> x
|
|
_ -> And x y
|
|
|
|
orFormula :: [Formula] -> Formula
|
|
orFormula [] = Bot
|
|
orFormula (x:xs) = or x (orFormula xs) where
|
|
or x y =
|
|
case x of
|
|
Top -> Top
|
|
Bot -> case y of
|
|
Top -> Top
|
|
_ -> y
|
|
_ -> case y of
|
|
Bot -> x
|
|
_ -> Or x y
|
|
|
|
notFormula :: Formula -> Formula
|
|
notFormula Top = Bot
|
|
notFormula Bot = Top
|
|
notFormula (Is0 x) = Is1 x
|
|
notFormula (Is1 x) = Is0 x
|
|
notFormula (And x y) = Or (notFormula x) (notFormula y)
|
|
notFormula (Or x y) = And (notFormula x) (notFormula y)
|
|
|
|
newtype System a = FMap { getSystem :: Map Formula a }
|
|
deriving (Eq, Show, Ord)
|
|
|
|
emptySystem :: System a
|
|
emptySystem = FMap mempty
|
|
|
|
mapSystem :: System a -> (a -> b) -> System b
|
|
mapSystem (FMap x) f = FMap (Map.filterWithKey (\f _ -> f /= Bot) (fmap f x))
|