packages feed

GenZ-0.1.0.0: lib/FormM.hs

{-# LANGUAGE DeriveGeneric, FlexibleInstances #-}
{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
module FormM where

import qualified Data.Set as Set
import GHC.Generics
import Test.QuickCheck
import Data.List as List
import General
import FormP

-- * The Modal Language

data FormM = BotM | AtM Atom | ConM FormM FormM | DisM FormM FormM | ImpM FormM FormM | Box FormM
  deriving (Eq,Ord,Generic)

instance PropLog FormM where
  neg f = ImpM f BotM
  dis = DisM
  con = ConM
  top = neg BotM
  iff f g = ConM (ImpM f g) (ImpM g f)
  -- Axiom: Γ, p ⇒ ∆, p
  isAtom (AtM _) = True
  isAtom _ = False
  isAxiom _ fs _ = [ ("ax", [])
                  | any (\f -> swap f `Set.member` fs) fs ]
  leftBot _ fs _ = [ ("⊥L", []) | Left BotM `Set.member` fs ]
  size BotM         = 1
  size (AtM _)      = 1
  size (ConM f g)   = 1 + size f + size g
  size (DisM f g)   = 1 + size f + size g
  size (ImpM f g)   = 1 + size f + size g
  size (Box f)      = 1 + size f
  subFormulas BotM         = [BotM]
  subFormulas (AtM a)      = [AtM a]
  subFormulas (ConM f g)   = ConM f g : (subFormulas f ++ subFormulas g)
  subFormulas (DisM f g)   = DisM f g : (subFormulas f ++ subFormulas g)
  subFormulas (ImpM f g)   = ImpM f g : (subFormulas f ++ subFormulas g)
  subFormulas (Box f)      = Box f : subFormulas f

dia :: FormM -> FormM
dia f = neg $ Box $ neg f

instance Show FormM where
  show BotM       = "⊥"
  show (AtM a)    = a
  show (ConM f g) = "(" ++ show f ++ " ∧ " ++ show g ++ ")"
  show (DisM f g) = "(" ++ show f ++ " v " ++ show g ++ ")"
  show (ImpM f g) = "(" ++ show f ++ " → " ++ show g ++ ")"
  show (Box f)    = "☐" ++ show f

instance TeX FormM where
  tex BotM       = "\\bot"
  tex (AtM ('p':s)) = "p_{" ++ s ++ "}"
  tex (AtM a)    = a
  tex (ConM f g) = "(" ++ tex f ++ " \\land " ++ tex g ++ ")"
  tex (DisM f g) = "(" ++ tex f ++ " \\lor " ++ tex g ++ ")"
  tex (ImpM f g) = "(" ++ tex f ++ " \\to " ++ tex g ++ ")"
  tex (Box f)    = " \\Box " ++ tex f

instance Arbitrary FormM where
  arbitrary = sized genForm where
    factor = 2
    genForm 0 = oneof [ pure BotM, AtM <$> elements (map return "pqrst")]
    genForm 1 = AtM <$> elements (map return "pqrst")
    genForm n = oneof
      [ pure BotM
      , AtM <$> elements (map return "pqrst")
      , ImpM <$> genForm (n `div` factor) <*> genForm (n `div` factor)
      , ConM <$> genForm (n `div` factor) <*> genForm (n `div` factor)
      , DisM <$> genForm (n `div` factor) <*> genForm (n `div` factor)
      , Box <$> genForm (n `div` factor)
      ]
  shrink = nub . genericShrink

a1,b1,c1,d1,e1 :: FormM
[a1,b1,c1,d1,e1] = map (AtM . return) "12345"

-- * Axioms

-- □(φ → ψ) → (□φ → □ψ) | Holds in all modal logics
kAxiom :: FormM
kAxiom = ImpM (Box (ImpM a1 b1)) (ImpM (Box a1) (Box b1))

-- □φ → □□φ | Holds in D4, K4, K45, D45, S4, GL
fourAxiom :: FormM
fourAxiom = ImpM (Box a1) (Box (Box a1))

-- □φ → φ | Holds in T, S4
tAxiom :: FormM
tAxiom = ImpM (Box a1) a1

-- φ → □♢φ | Holds in B
bAxiom :: FormM
bAxiom = ImpM a1 (Box (dia a1))

-- □(□φ → φ) → □φ | Holds in GL
lobAxiom :: FormM
lobAxiom = ImpM (Box (ImpM (Box a1) a1)) (Box a1)

-- ¬□⊥ | Holds in D, D4, D45, T, S4, S5
consistency :: FormM
consistency = neg . Box $ BotM

-- □□φ → □φ | Holds in T, S4, D45
density :: FormM
density = ImpM (Box (Box a1)) (Box a1)

-- □φ → ♢φ | Holds in D, D4, D45, T, S4 | Also known as seriality
dAxiom :: FormM
dAxiom = ImpM (Box a1) (dia a1)

-- ♢φ → □♢φ | Holds in K45, D45, S5
fiveAxiom :: FormM
fiveAxiom = ImpM (dia a1) (Box (dia a1))

-- Holds in all modal logics
f1 :: FormM
f1 = ImpM (ConM (Box a1) (Box (ImpM a1 b1))) (Box b1)

-- Never holds.
f2 :: FormM
f2 = ImpM (Box (ImpM a1 b1)) (ImpM (Box a1) (ImpM (Box b1) (Box c1)))

-- * For benchmarks
-- □...□φ
boxes :: Int -> FormM -> FormM
boxes 0 f = f
boxes n f = Box (boxes (n-1) f)
-- □...□⊤
boxesTop :: Int -> FormM
boxesTop n = boxes n top
-- □...□⊥
boxesBot :: Int -> FormM
boxesBot n = boxes n BotM
-- □...□φ → □...□□φ | Holds in D4, K4, K45, S4, GL (in logics that have 4)
boxToMoreBox :: Int -> FormM
boxToMoreBox n = ImpM (boxes n a1) (boxes (n + 1) a1)
-- □...□□φ → □...□φ | Holds in T, S4, D45
boxToFewerBox :: Int -> FormM
boxToFewerBox n = ImpM (boxes (n + 1) a1) (boxes n a1)
-- □(□φ → φ) → □...□φ | Holds only in GL
lobBoxes:: Int -> FormM
lobBoxes n = ImpM (Box (ImpM (Box a1) a1)) (boxes n a1)

-- | ◇...◇φ
diamonds :: Int -> FormM -> FormM
diamonds 0 f = f
diamonds n f = Box (boxes (n-1) f)

-- | ◇...◇φ → □...□φ | Holds in D
boxesToDiamonds :: Int -> FormM
boxesToDiamonds n = ImpM (boxes n a1) (diamonds n a1)

-- | Generate a list of n variables
listOfAt :: Int -> [FormM]
listOfAt n = map (AtM . show) $ take n [(3::Integer)..]

-- | Multi-version of the K Axiom
multiVerK :: Int -> FormM
multiVerK n = ImpM (Box (List.foldr ImpM (AtM "1") (listOfAt n)))
                $ foldr (ImpM . Box) (Box (AtM "1")) (listOfAt n)

-- | Similar to multiVerK, but with an extra atom in the premise. Not provable
extraAtK :: Int -> FormM
extraAtK n = ImpM (Box (List.foldr ImpM (AtM "1") (listOfAt n ++ [AtM "2"])))
                $ foldr (ImpM . Box) (Box (AtM "1")) (listOfAt n)

-- | Bench formula for S4. Not provable
negBoxes :: Int -> FormM
negBoxes n = neg $ Box $ neg $ boxes n a1

-- * Embedding Propositional language into Modal language
pTom :: FormP -> FormM
pTom BotP = BotM
pTom (AtP x) = AtM x
pTom (ConP x y) = ConM (pTom x) (pTom y)
pTom (DisP x y) = DisM (pTom x) (pTom y)
pTom (ImpP x y) = ImpM (pTom x) (pTom y)

-- The Gödel–McKinsey–Tarski Translation
translation :: FormP -> FormM
translation BotP = BotM
translation (AtP x) = Box $ AtM x
translation (ConP x y) = ConM (translation x) (translation y)
translation (DisP x y) = DisM (translation x) (translation y)
translation (ImpP x y) = Box $ ImpM (translation x) (translation y)

propFormulasM :: [(String, Int -> FormM)]
propFormulasM =  map (fmap (pTom .)) allFormulasP

boxesFormulasM :: [(String, Int -> FormM)]
boxesFormulasM =
  [ ("boxesTop", boxesTop) -- T used to be faster than Z
  , ("boxesBot", boxesBot)
  ]

kFormulasM :: [(String, Int -> FormM)]
kFormulasM =
  [ ("multiVerK", multiVerK) -- T
  , ("boxToMoreBox", boxToMoreBox) -- F
  , ("extraAtK", extraAtK) -- F
  ]

k4FormulasM :: [(String, Int -> FormM)]
k4FormulasM =
  [ ("boxToMoreBox", boxToMoreBox) -- T
  , ("boxToFewerBox", boxToFewerBox) -- F
  ]

glFormulasM :: [(String, Int -> FormM)]
glFormulasM =
  [ ("lobBoxes", lobBoxes) -- T
  , ("boxToFewerBox", boxToFewerBox) -- F
  ]

s4FormulasM :: [(String, Int -> FormM)]
s4FormulasM =
  [ ("negBoxes", negBoxes) -- F
  ]

-- Only go until 20 or you will run out of memory.
hards4FormulasM :: [(String, Int -> FormM)]
hards4FormulasM =
  [ ("boxToFewerBox", boxToFewerBox) -- T
  , ("lobBoxes", lobBoxes) -- F
  ]

-- | Positive modal logic tests
posModalTests :: [(String, FormM)]
posModalTests =
      [ ("k Axiom"          , kAxiom)
      , (show f1            , f1)
      , ("boxesTop 10"      , boxesTop 10)
      , ("multiVerK 5"     , multiVerK 5)
      ]

-- | Negative modal logic tests
negModalTests :: [(String, FormM)]
negModalTests =
      [ (show f2            , f2)
      , ("negBoxes 10"      , negBoxes 10)
      , ("boxesBot 10"      , boxesBot 10)
      , ("extraAtK 3"       , extraAtK 3)]