packages feed

logic-classes-1.7: Data/Logic/Instances/PropLogic.hs

{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes, ScopedTypeVariables, TypeFamilies, UndecidableInstances #-}
{-# OPTIONS -fno-warn-orphans #-}
module Data.Logic.Instances.PropLogic
    ( flatten
    , plSat
    ) where

import Data.Logic.ATP.Formulas (IsFormula(asBool), IsAtom, IsFormula(..))
import Data.Logic.ATP.Lit (convertLiteral, IsLiteral(..), IsLiteral(..), LFormula)
import Data.Logic.ATP.Pretty (HasFixity(precedence, associativity), Pretty(pPrintPrec), Side(Top))
import Data.Logic.ATP.Prop (BinOp(..), associativityPropositional, IsPropositional(..), JustPropositional,
                            precedencePropositional, prettyPropositional, simpcnf)
import Data.Set.Extra as Set (toList)
import PropLogic hiding (at)

instance IsAtom atom => JustPropositional (PropForm atom)

instance IsAtom atom => IsLiteral (PropForm atom) where
    naiveNegate = N
    foldNegation normal inverted (N x) = foldNegation inverted normal x
    foldNegation normal _ x = normal x
    foldLiteral' ho ne tf at fm =
        case fm of
          N x -> ne x
          T -> tf True
          F -> tf False
          A x -> at x
          _ -> ho fm


instance IsAtom atom => IsFormula (PropForm atom) where
    type AtomOf (PropForm atom) = atom
    atomic = A
    overatoms = error "FIXME: overatoms PropForm"
    onatoms = error "FIXME: onatoms PropForm"
    true = T
    false = F
    asBool T = Just True
    asBool F = Just False
    asBool _ = Nothing

instance IsAtom atom => IsPropositional (PropForm atom) where
    foldCombination = error "FIXME: PropForm foldCombination"
    x .<=>. y = EJ [x, y]
    x .=>.  y = SJ [x, y]
    x .|.   y = DJ [x, y]
    x .&.   y = CJ [x, y]
    foldPropositional' ho co ne tf at formula =
        case formula of
          -- EJ [x,y,z,...] -> CJ [EJ [x,y], EJ[y,z], ...]
          EJ [] -> error "Empty equijunct"
          EJ [x] -> foldPropositional' ho co ne tf at x
          EJ [x0, x1] -> co x0 (:<=>:) x1
          EJ xs -> foldPropositional' ho co ne tf at (CJ (map (\ (x0, x1) -> EJ [x0, x1]) (pairs xs)))
          SJ [] -> error "Empty subjunct"
          SJ [x] -> foldPropositional' ho co ne tf at x
          SJ [x0, x1] -> co x0 (:=>:) x1
          SJ xs -> foldPropositional' ho co ne tf at (CJ (map (\ (x0, x1) -> SJ [x0, x1]) (pairs xs)))
          DJ [] -> tf False
          DJ [x] -> foldPropositional' ho co ne tf at x
          DJ (x0:xs) -> co x0 (:|:) (DJ xs)
          CJ [] -> tf True
          CJ [x] -> foldPropositional' ho co ne tf at x
          CJ (x0:xs) -> co x0 (:&:) (CJ xs)
          N x -> ne x
          T -> tf True
          F -> tf False
          A x -> at x

instance (IsPropositional (PropForm atom), IsAtom atom) => Pretty (PropForm atom) where
    pPrintPrec = prettyPropositional Top

instance (IsPropositional (PropForm atom), IsAtom atom) => HasFixity (PropForm atom) where
    precedence = precedencePropositional
    associativity = associativityPropositional

pairs :: [a] -> [(a, a)]
pairs (x:y:zs) = (x,y) : pairs (y:zs)
pairs _ = []

flatten :: PropForm a -> PropForm a
flatten (CJ xs) =
    CJ (concatMap f (map flatten xs))
    where
      f (CJ ys) = ys
      f x = [x]
flatten (DJ xs) =
    DJ (concatMap f (map flatten xs))
    where
      f (DJ ys) = ys
      f x = [x]
flatten (EJ xs) = EJ (map flatten xs)
flatten (SJ xs) = SJ (map flatten xs)
flatten (N x) = N (flatten x)
flatten x = x

{-
plSat0 :: (PropAlg a (PropForm atom), IsPropositional (PropForm atom) atom, Ord atom, Pretty atom, HasFixity atom) => PropForm atom -> Bool
plSat0 f = satisfiable . (\ (x :: PropForm atom) -> x) . clauses0 $ f

clauses0 :: (IsPropositional (PropForm atom) atom, Ord atom, Pretty atom, HasFixity atom) => PropForm atom -> PropForm atom
clauses0 = CJ . map (DJ . map unmarkLiteral . Set.toList) . Set.toList . simpcnf id
-}

plSat :: (IsPropositional (PropForm atom), IsAtom atom) => PropForm atom -> Bool
plSat = satisfiable . clauses

clauses :: forall atom. IsPropositional (PropForm atom) => PropForm atom -> PropForm atom
clauses = CJ . map (DJ . map (convertLiteral id :: LFormula atom -> PropForm atom) . Set.toList) . Set.toList . simpcnf id