packages feed

GenZ-0.1.0.0: lib/Logic/Modal/K45.hs

module Logic.Modal.K45 where

import qualified Data.Set as Set
import General
import Logic.Modal.K
import Logic.Modal.K4
import FormM

kfourfive :: Logic FormM
kfourfive = Log { name = "K45"
                , safeRules   = [leftBot, isAxiom, replaceRule safeML]
                , unsafeRules = [boxK45rule]
                }

{-
CPL(safe) + ☐k45 rule(unsafe + global loopcheck):
          □Γ1, Γ2 ⇒ □∆, φ
☐k45  Γ', □Γ1, □Γ2⇒ □∆, □φ, ∆'
-}

boxK45rule :: Rule FormM
boxK45rule hs fs (Right (Box f)) =
  concatMap (globalLoopCheckMap "☐k45" (fs:hs)) premises
 where
  -- { □Γ1 ∪ □Γ2 }
  lBoxes = Set.filter isLeftBox fs
  -- { □Δ }
  rBoxesRemove = Set.delete (Right (Box f)) (Set.filter isRightBox fs)
  -- all possible □Δ
  deltaS :: [Set.Set (Either FormM FormM)]
  deltaS = Set.toList (Set.powerSet rBoxesRemove)
  -- [(□Γ1, □Γ2)]
  boxGammaPartitions :: [(Set.Set (Either FormM FormM), Set.Set (Either FormM FormM))]
  boxGammaPartitions = partitionDrop lBoxes
  -- □Γ1, Γ2 ⇒ □Δ, φ
  premises :: [Set.Set (Either FormM FormM)]
  premises =
    [ Set.unions
        [ boxGamma1
        , Set.map fromBox boxGamma2
        , delta
        , Set.singleton (Right f)
        ]
    | delta <- deltaS
    , (boxGamma1, boxGamma2) <- boxGammaPartitions
    ]
boxK45rule _ _ _ = []

-- Generate all ordered partitions of a set. O(n·2^n)
partitionDrop :: Ord a => Set.Set a -> [(Set.Set a, Set.Set a)]
partitionDrop s =
  [ (Set.fromDistinctAscList ls, Set.fromDistinctAscList rs)
  | (ls, rs) <- go (Set.toAscList s)
  ]
  where
    -- go produces (leftElemsAsc, rightElemsAsc)
    go []     = [([], [])]
    go (x:xs) =
      let rest = go xs
      in  [(l, r) | (l, r) <- rest]   -- drop x
       ++ [(l, x:r) | (l, r) <- rest] -- x ∈ Γ1
       ++ [(x:l, r) | (l, r) <- rest] -- x ∈ Γ2

isRightBox :: Either FormM FormM -> Bool
isRightBox (Right (Box _)) = True
isRightBox _              = False