packages feed

GenZ-0.1.0.0: lib/FormP.hs

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

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

-- | Propositional Formulas
data FormP = BotP | AtP Atom | ConP FormP FormP | DisP FormP FormP | ImpP FormP FormP
  deriving (Eq,Ord,Generic)

instance PropLog FormP where
  neg f = ImpP f BotP
  dis :: FormP -> FormP -> FormP
  dis = DisP
  con = ConP
  top = neg BotP
  iff f g = ConP (ImpP f g) (ImpP g f)
  -- Axiom: Γ, p ⇒ ∆, p
  isAtom (AtP _) = True
  isAtom _ = False
  isAxiom _ fs _ = [ ("ax", [])
                  | any (\f -> swap f `Set.member` fs) fs ]
  leftBot _ fs _ = [ ("⊥L", []) | Left BotP `Set.member` fs ]
  size BotP         = 1
  size (AtP _)      = 1
  size (ConP f g)   = 1 + size f + size g
  size (DisP f g)   = 1 + size f + size g
  size (ImpP f g)   = 1 + size f + size g
  subFormulas BotP         = [BotP]
  subFormulas (AtP a)      = [AtP a]
  subFormulas (ConP f g)   = ConP f g : (subFormulas f ++ subFormulas g)
  subFormulas (DisP f g)   = DisP f g : (subFormulas f ++ subFormulas g)
  subFormulas (ImpP f g)   = ImpP f g : (subFormulas f ++ subFormulas g)

instance Show FormP where
  show BotP       = "⊥"
  show (AtP a)    = a
  show (ConP f g) = "(" ++ show f ++ " ∧ " ++ show g ++ ")"
  show (DisP f g) = "(" ++ show f ++ " v " ++ show g ++ ")"
  show (ImpP f g) = "(" ++ show f ++ " → " ++ show g ++ ")"

instance TeX FormP where
  tex BotP       = "\\bot"
  tex (AtP ('p':s)) = "p_{" ++ s ++ "}"
  tex (AtP a)    = a
  tex (ConP f g) = "(" ++ tex f ++ " \\land " ++ tex g ++ ")"
  tex (DisP f g) = "(" ++ tex f ++ " \\lor " ++ tex g ++ ")"
  tex (ImpP f g) = "(" ++ tex f ++ " \\to " ++ tex g ++ ")"

instance Arbitrary FormP where
  arbitrary = sized genForm where
    factor = 2
    genForm 0 = oneof [ pure BotP, AtP <$> elements (map return "pqrst") ]
    genForm 1 = AtP <$> elements (map return "pqrst")
    genForm n = oneof
      [ pure BotP
      , AtP <$> elements (map return "pqrst")
      , ImpP <$> genForm (n `div` factor) <*> genForm (n `div` factor)
      , ConP <$> genForm (n `div` factor) <*> genForm (n `div` factor)
      , DisP <$> genForm (n `div` factor) <*> genForm (n `div` factor)
      ]
  shrink = nub . genericShrink

o,p,q,r :: FormP
[o,p,q,r] = map (AtP . return) "opqr"

-- | Contradiction
contradiction :: FormP
contradiction = ConP p (neg p)

-- | Excluded middle
excludedMiddle :: FormP
excludedMiddle = DisP p (neg p)

-- | Double negation
doubleNegation :: FormP
doubleNegation = iff (neg (neg p)) p

-- | Right Double negation
doubleNegationR :: FormP
doubleNegationR = ImpP p (neg (neg p))

-- | Peirce's Law
peirce :: FormP
peirce = ImpP (ImpP (ImpP p q) p) p

-- | Double negation of excluded middle
dnEM :: FormP
dnEM = neg $ neg excludedMiddle

-- | List of tests
t1,t2,t3,t4,t5,t6:: FormP
[t1,t2,t3,t4,t5,t6] = [ ImpP p p
                , ImpP (ImpP p (ImpP p q)) (ImpP p q)
                , ImpP (ImpP peirce q) q
                , ConP r excludedMiddle
                , neg $ neg $ ImpP p (ImpP q r)
                , neg $ neg $ DisP p $ neg q
                ]

-- True in IPL
phi :: FormP
phi = ImpP (ConP p (ImpP p q)) (ImpP (ImpP p q) q)

-- * For benchmarks
-- False
conBotR :: Int -> FormP
conBotR k = foldr ConP BotP (replicate k BotP )
-- False
conBotL :: Int -> FormP
conBotL k = foldl ConP BotP (replicate k BotP )
-- False
disBotR :: Int -> FormP
disBotR k = foldr DisP BotP (replicate k BotP )
-- False
disBotL :: Int -> FormP
disBotL k = foldl DisP BotP (replicate k BotP )
-- True
conTopR :: Int -> FormP
conTopR k = foldr ConP top (replicate k top )
-- True
conTopL :: Int -> FormP
conTopL k = foldl ConP top (replicate k top )
-- True
disTopR :: Int -> FormP
disTopR k = foldr DisP top (replicate k top )
-- True
disTopL :: Int -> FormP
disTopL k = foldl DisP top (replicate k top )
-- True in CPL, false in IPL
conPeiR :: Int -> FormP
conPeiR k = foldr ConP peirce (replicate (2*k) peirce )
-- True in CPL, false in IPL
conPeiL :: Int -> FormP
conPeiL k = foldl ConP peirce (replicate (2*k) peirce )
-- True in CPL, false in IPL
disPeiR :: Int -> FormP
disPeiR k = foldr DisP peirce (replicate (2*k) peirce )
-- True in CPL, false in IPL
disPeiL :: Int -> FormP
disPeiL k = foldl DisP peirce (replicate (2*k) peirce )
-- True in CPL, IPL
disPhiPeiR :: Int -> FormP
disPhiPeiR k = foldr DisP phi (replicate (2*k) peirce )
-- True in CPL, IPL
disPhiPeiL :: Int -> FormP
disPhiPeiL k = foldl DisP phi (replicate (2*k) peirce )
-- True in CPL, false in IPL
phiImpPei :: Int -> FormP
phiImpPei 0 = peirce
phiImpPei n = ImpP phi $ phiImpPei (n-1)

allFormulasP :: [(String, Int -> FormP)]
allFormulasP =
  [ ("disPhiPei-R", disPhiPeiR)
  , ("disPhiPei-L", disPhiPeiL)
  , ("disPei-R", disPeiR)
  , ("disPei-L", disPeiL)
  , ("conPei-R", conPeiR)
  , ("conPei-L", conPeiL)
  , ("conBot-R", conBotR)
  , ("conBot-L", conBotL)
  , ("disBot-R", disBotR)
  , ("disBot-L", disBotL)
  , ("conTop-R", conTopR)
  , ("conTop-L", conTopL)
  , ("disTop-R", disTopR)
  , ("disTop-L", disTopL)
  ]

-- | Only go until 20 or you will run out of memory.
hardFormulasP :: [(String, Int -> FormP)]
hardFormulasP =
   [ ("phiImpPei", phiImpPei) ]

-- * Test formulas
-- | Positive classical propositional logic tests
posCPropTests :: [(String, FormP)]
posCPropTests =
      [ ( "Top"                                              , top )
      , ( "Double negation: " ++ show doubleNegation         , doubleNegation )
      , ( "Double negation right: " ++ show doubleNegationR  , doubleNegationR )
      , ( "Excluded middle: " ++ show excludedMiddle         , excludedMiddle )
      , ( "Peirce's law: " ++ show peirce                    , peirce )
      , ( "Double negation of excluded middle " ++ show dnEM , dnEM )
      , ( show phi                                           , phi )
      , ( show t1                                            , t1 )
      , ( show t2                                            , t2 )
      , ( show t3                                            , t3 )
      , ( "conTopR 10"                                       , conTopR 10 )
      , ( "conTopL 10"                                       , conTopL 10 )
      , ( "disTopR 10"                                       , disTopR 10 )
      , ( "disTopL 10"                                       , disTopL 10 )
      , ( "conPeiR 10"                                       , conPeiR 10 )
      , ( "conPeiL 10"                                       , conPeiL 10 )
      , ( "disPeiR 10"                                       , disPeiR 10 )
      , ( "disPeiL 10"                                       , disPeiL 10 )
      , ( "disPhiPeiR 10"                                    , disPhiPeiR 10 )
      , ( "disPhiPeiL 10"                                    , disPhiPeiL 10 )
      , ( "phiImpPei 10"                                     , phiImpPei 10 )
      ]

-- Negative classical propositional logic tests
negCPropTests :: [(String, FormP)]
negCPropTests =
      [ ( "Bot"                , BotP)
      , ( show contradiction   , contradiction)
      , ( show t4              , t4)
      , ( show t5              , t5)
      , ( show t6              , t6)
      , ( "conBotR 10"         , conBotR 10)
      , ( "conBotL 10"         , conBotL 10)
      , ( "disBotR 10"         , disBotR 10)
      , ( "disBotL 10"         , disBotL 10)
      ]