Copyright | (c) Artem Mavrin 2021 |
---|---|
License | BSD3 |
Maintainer | artemvmavrin@gmail.com |
Stability | experimental |
Portability | POSIX |
Safe Haskell | Safe |
Language | Haskell2010 |
Classical propositional logic library.
Synopsis
- data Formula a where
- subformulas :: Ord a => Formula a -> Set (Formula a)
- substitute :: Eq a => Formula a -> a -> Formula a -> Formula a
- canonicalCNF :: Ord a => Formula a -> Formula a
- getAnyVariable :: Formula a -> Maybe a
- type Context a = Set (Formula a)
- data Judgement a = Judgement {
- antecedents :: Context a
- succedent :: Formula a
- (|-) :: (Ord a, Foldable f) => f (Formula a) -> Formula a -> Judgement a
- weakenJudgement :: Ord a => Judgement a -> Formula a -> Judgement a
- data Proof a where
- pattern Axiom :: Judgement a -> Proof a
- pattern FalseElim :: Judgement a -> Proof a -> Proof a
- pattern TrueIntr :: Judgement a -> Proof a
- pattern NotElim :: Judgement a -> Proof a -> Proof a -> Proof a
- pattern NotIntr :: Judgement a -> Proof a -> Proof a
- pattern ImpElim :: Judgement a -> Proof a -> Proof a -> Proof a
- pattern ImpIntr :: Judgement a -> Proof a -> Proof a
- pattern OrElim :: Judgement a -> Proof a -> Proof a -> Proof a -> Proof a
- pattern OrIntrL :: Judgement a -> Proof a -> Proof a
- pattern OrIntrR :: Judgement a -> Proof a -> Proof a
- pattern AndElimL :: Judgement a -> Proof a -> Proof a
- pattern AndElimR :: Judgement a -> Proof a -> Proof a
- pattern AndIntr :: Judgement a -> Proof a -> Proof a -> Proof a
- pattern IffElimL :: Judgement a -> Proof a -> Proof a
- pattern IffElimR :: Judgement a -> Proof a -> Proof a
- pattern IffIntr :: Judgement a -> Proof a -> Proof a -> Proof a
- isProvable :: Ord a => Judgement a -> Bool
- isTautology :: Ord a => Formula a -> Bool
- class TruthAssignment t a where
- evalVar :: t -> a -> Bool
- evalFormula :: t -> Formula a -> Bool
- (|=) :: TruthAssignment t a => t -> Formula a -> Bool
- satSimple :: Eq a => Formula a -> Bool
- satDPLL :: Ord a => Formula a -> Bool
- satAssignmentSimple :: Ord a => Formula a -> Maybe (Map a Bool)
- satAssignmentDPLL :: Ord a => Formula a -> Maybe (Map a Bool)
- class AST t where
- subtrees :: (AST t, Ord t) => t -> Set t
- properSubtrees :: (AST t, Ord t) => t -> Set t
- parseFormula :: String -> Maybe (Formula String)
- parseJudgement :: String -> Maybe (Judgement String)
- pretty :: PrettyPrintable a => a -> String
- prettyFormula :: PrettyPrintable a => Formula a -> String
- prettyJudgement :: PrettyPrintable a => Judgement a -> String
- prettyProof :: PrettyPrintable a => Proof a -> String
Formulas
Formulas of propositional logic are built inductively from atomic propositions
- truth \(\top\),
- falsity \(\bot\), and
- propositional variables \(a, b, c, \ldots\)
using the unary connective
- negation \(\lnot\)
and the binary connectives
- implication \(\rightarrow\),
- disjunction \(\lor\),
- conjunction \(\land\), and
- equivalence \(\leftrightarrow\).
pattern Lit :: Bool -> Formula a | Propositional literal/constant. |
pattern Var :: a -> Formula a | Propositional variable. |
pattern Not :: Formula a -> Formula a | Negation. |
pattern Imp :: Formula a -> Formula a -> Formula a | Implication. |
pattern Or :: Formula a -> Formula a -> Formula a | Disjunction. |
pattern And :: Formula a -> Formula a -> Formula a | Conjunction. |
pattern Iff :: Formula a -> Formula a -> Formula a | Equivalence. |
Instances
Eq a => Eq (Formula a) Source # | Syntactic equality. |
Ord a => Ord (Formula a) Source # | First compare heights, then compare sizes, then resolve using the
convention |
Defined in AutoProof.Internal.Formula.Types | |
Read a => Read (Formula a) Source # | |
Show a => Show (Formula a) Source # | |
AST (Formula a) Source # | |
PrettyPrintable a => PrettyPrintable (Formula a) Source # | |
type Root (Formula a) Source # | |
Defined in AutoProof.Internal.Formula.Types |
Operations on formulas
subformulas :: Ord a => Formula a -> Set (Formula a) Source #
Get the set of subformulas of a propositional formula.
Examples
>>>
subformulas $ Or (Var 'x') (And (Var 'y') (Var 'z'))
fromList [Var 'x',Var 'y',Var 'z',And (Var 'y') (Var 'z'),Or (Var 'x') (And (Var 'y') (Var 'z'))]
substitute :: Eq a => Formula a -> a -> Formula a -> Formula a Source #
(
represents \(a[p/x]\), the substitution of each
occurence of the variable \(x\) in the formula \(a\) by the formula \(p\).substitute
a x p)
Examples
>>>
substitute (Imp (Var 'e') (Var 'e')) 'e' (And (Var 'a') (Var 'a'))
Imp (And (Var 'a') (Var 'a')) (And (Var 'a') (Var 'a'))
canonicalCNF :: Ord a => Formula a -> Formula a Source #
Convert a formula into a canonical conjunctive normal form.
Examples
>>>
import AutoProof.Internal.Formula
>>>
canonicalCNF $ Or (Not (Imp (Var "a") (Var "b"))) (Var "c")
And (Or (Var "c") (Not (Var "b"))) (Or (Var "c") (Var "a"))
getAnyVariable :: Formula a -> Maybe a Source #
Obtain a propositional variable from a formula, if there is one.
Examples
>>>
getAnyVariable (Or (Var "a") (Var "b"))
Just "a"
>>>
getAnyVariable (Lit False :: Formula String)
Nothing
Judgements
type Context a = Set (Formula a) Source #
A set of propositional formulas, used as antecedents of a judgement.
(Judgement c a)
represents the judgement or sequent \(c \vdash a\).
>>>
Judgement Set.empty (Imp (And (Var 'a') (Var 'b')) (Var 'a'))
[] |- Imp (And (Var 'a') (Var 'b')) (Var 'a')
Judgement | |
|
Instances
Eq a => Eq (Judgement a) Source # | |
Ord a => Ord (Judgement a) Source # | |
Defined in AutoProof.Internal.Judgement | |
(Ord a, Read a) => Read (Judgement a) Source # | |
Show a => Show (Judgement a) Source # | |
PrettyPrintable a => PrettyPrintable (Judgement a) Source # | |
Judgement constructor
(|-) :: (Ord a, Foldable f) => f (Formula a) -> Formula a -> Judgement a infix 5 Source #
Infix judgement constructor. (c
represents the judgement
\(c \vdash a\).|-
a)
>>>
[Var 'a', Imp (Var 'a') (Var 'b')] |- Var 'b'
[Var 'a',Imp (Var 'a') (Var 'b')] |- Var 'b'
Note: If c
is already a Set
, then it is recommended to use
(Judgement c a)
in favor of (c
, since the latter will create a
new set and fill it with the values in |-
a)c
.
Operations on judgements
weakenJudgement :: Ord a => Judgement a -> Formula a -> Judgement a Source #
Weaken a judgement by inserting a formula into its hypotheses.
>>>
weakenJudgement ([Var 'a', Imp (Var 'a') (Var 'b')] |- Var 'b') (Var 'c')
[Var 'a',Var 'c',Imp (Var 'a') (Var 'b')] |- Var 'b'
Proofs
A proof tree for propositional logic.
pattern Axiom :: Judgement a -> Proof a | An axiom \[ \frac{}{ g \vdash a } \, (\text{Axiom}) \] |
pattern FalseElim :: Judgement a -> Proof a -> Proof a | Falsity elimination (principle of explosion).
\[ \frac{ \displaystyle\frac{ p }{ g \vdash \bot } }{ g \vdash a } \, ({\bot}\text{E}) \] |
pattern TrueIntr :: Judgement a -> Proof a | Truth introduction.
\[ \frac{}{ g \vdash \top } \, (\top\text{I}) \] |
pattern NotElim :: Judgement a -> Proof a -> Proof a -> Proof a | Negation elimination.
\[ \frac{ \displaystyle\frac{ p }{ g_1 \vdash \lnot a } \qquad \displaystyle\frac{ q }{ g_2 \vdash a } }{ g \vdash \bot } \, ({\lnot}\text{E}) \] |
pattern NotIntr :: Judgement a -> Proof a -> Proof a | Negation introduction.
\[ \frac{ \displaystyle\frac{ p }{ g, a \vdash \bot } }{ g \vdash \lnot a } \, ({\lnot}\text{I}) \] |
pattern ImpElim :: Judgement a -> Proof a -> Proof a -> Proof a | Implication elimination (modus ponens).
\[ \frac{ \displaystyle\frac{ p }{ g_1 \vdash a \rightarrow b } \qquad \displaystyle\frac{ q }{ g_2 \vdash a } }{ g \vdash b } \, ({\rightarrow}\text{E}) \] |
pattern ImpIntr :: Judgement a -> Proof a -> Proof a | Implication introduction.
\[ \frac{ \displaystyle\frac{ p }{ g, a \vdash b } }{ g \vdash a \rightarrow b } \, ({\rightarrow}\text{I}) \] |
pattern OrElim :: Judgement a -> Proof a -> Proof a -> Proof a -> Proof a | Disjunction elimination.
\[ \frac{ \displaystyle\frac{ p }{ g_1 \vdash a \lor b } \qquad \displaystyle\frac{ q }{ g_2, a \vdash c } \qquad \displaystyle\frac{ r }{ g_3, b \vdash c } }{ g \vdash c } \, ({\lor}\text{E}) \] |
pattern OrIntrL :: Judgement a -> Proof a -> Proof a | Left disjunction introduction.
\[ \frac{ \displaystyle\frac{ p }{ g \vdash a } }{ g \vdash a \lor b } \, ({\lor}\text{IL}) \] |
pattern OrIntrR :: Judgement a -> Proof a -> Proof a | Right disjunction introduction.
\[ \frac{ \displaystyle\frac{ p }{ g \vdash b } }{ g \vdash a \lor b } \, ({\lor}\text{IR}) \] |
pattern AndElimL :: Judgement a -> Proof a -> Proof a | Left conjunction elimination.
\[ \frac{ \displaystyle\frac{ p }{ g \vdash a \land b } }{ g \vdash a } \, ({\land}\text{EL}) \] |
pattern AndElimR :: Judgement a -> Proof a -> Proof a | Right conjunction elimination.
\[ \frac{ \displaystyle\frac{ p }{ g \vdash a \land b } }{ g \vdash b } \, ({\land}\text{ER}) \] |
pattern AndIntr :: Judgement a -> Proof a -> Proof a -> Proof a | Conjunction introduction.
\[ \frac{ \displaystyle\frac{ p }{ g_1 \vdash a } \qquad \displaystyle\frac{ q }{ g_2 \vdash b } }{ g \vdash a \land b } \, ({\land}\text{I}) \] |
pattern IffElimL :: Judgement a -> Proof a -> Proof a | Left equivalence elimination.
\[ \frac{ \displaystyle\frac{ p }{ g \vdash a \leftrightarrow b } }{ g \vdash a \rightarrow b } \, ({\leftrightarrow}\text{EL}) \] |
pattern IffElimR :: Judgement a -> Proof a -> Proof a | Right equivalence elimination.
\[ \frac{ \displaystyle\frac{ p }{ g \vdash a \leftrightarrow b } }{ g \vdash b \rightarrow a } \, ({\leftrightarrow}\text{ER}) \] |
pattern IffIntr :: Judgement a -> Proof a -> Proof a -> Proof a | Equivalence introduction.
\[ \frac{ \displaystyle\frac{ p }{ g_1 \vdash a \rightarrow b } \qquad \displaystyle\frac{ q }{ g_2 \vdash b \rightarrow a } }{ g \vdash a \leftrightarrow b } \, ({\leftrightarrow}\text{I}) \] |
Instances
Eq a => Eq (Proof a) Source # | |
Ord a => Ord (Proof a) Source # | |
Defined in AutoProof.Internal.Proof.Types | |
(Ord a, Read a) => Read (Proof a) Source # | |
Show a => Show (Proof a) Source # | |
AST (Proof a) Source # | |
PrettyPrintable a => PrettyPrintable (Proof a) Source # | |
type Root (Proof a) Source # | |
Defined in AutoProof.Internal.Proof.Types |
Provability checking
isProvable :: Ord a => Judgement a -> Bool Source #
Determine whether a judgement is classically valid.
Examples
>>>
isProvable $ [Not (Not (Var 'a'))] |- Var 'a'
True
>>>
isProvable $ [Var 'a'] |- Var 'b'
False
isTautology :: Ord a => Formula a -> Bool Source #
Determine whether a formula is a classically tautology.
Examples
>>>
isTautology $ Or (Var 'a') (Not (Var 'a'))
True>>>
isTautology $ Var 'a'
False
Satisfiability
Truth assignments
class TruthAssignment t a where Source #
Class representing truth assignments for evalutating propositional logic formulas.
evalVar :: t -> a -> Bool Source #
Evaluate the truth value of a variable under a given truth assignment.
evalFormula :: t -> Formula a -> Bool Source #
Evaluate the truth value of a formula under a given truth assignment.
Instances
TruthAssignment () a Source # | Assigns all propositional variables the truth value Examples
|
Ord a => TruthAssignment (Map a Bool) a Source # | Truth assignments where a missing key in the map is interpreted as Examples
|
(|=) :: TruthAssignment t a => t -> Formula a -> Bool infix 5 Source #
Semantic entailment relation. This is an infix alias of evalFormula
.
Examples
>>>
t = Map.fromList $ [("a", True), ("b", False)]
>>>
t |= And (Var "a") (Not (Var "b"))
True
Check satisfiability
satSimple :: Eq a => Formula a -> Bool Source #
A simple baseline satisfiability algorithm.
This algorithm is based on the observation that if \(a\) is a propositional formula and \(x\) is a propositional variable, then \(a\) is satisfiable if and only if either \(a[\top/x]\) is satisfiable or \(a[\bot/x]\) is satisfiable.
Examples
>>>
satSimple $ Var "a"
True
>>>
satSimple $ And (Var "a") (Not (Var "a"))
False
satDPLL :: Ord a => Formula a -> Bool Source #
DPLL satisfiability algorithm.
Examples
>>>
import AutoProof.Internal.Formula
>>>
satDPLL $ Var "a"
True
>>>
satDPLL $ And (Var "a") (Not (Var "a"))
False
Satisfying assignment search
satAssignmentSimple :: Ord a => Formula a -> Maybe (Map a Bool) Source #
A simple baseline satisfiability algorithm, returning a satisfying truth assignment if there is one.
This algorithm is based on the observation that if \(a\) is a propositional formula and \(x\) is a propositional variable, then \(a\) is satisfiable if and only if either \(a[\top/x]\) is satisfiable or \(a[\bot/x]\) is satisfiable.
Examples
>>>
a = And (Not (Var "a")) (Or (Var "b") (Var "c")) -- satisfiable
>>>
Just t = satAssignmentSimple a
>>>
t
fromList [("a",False),("b",True),("c",True)]>>>
t |= a
True
>>>
satAssignmentSimple $ And (Var "a") (Not (Var "a")) -- unsatisfiable
Nothing
satAssignmentDPLL :: Ord a => Formula a -> Maybe (Map a Bool) Source #
DPLL satisfiability algorithm, returning a satisfying truth assihnment, if there is one.
Examples
>>>
a = And (Not (Var "a")) (Or (Var "b") (Var "c")) -- satisfiable
>>>
Just t = satAssignmentDPLL a
>>>
t
fromList [("a",False),("c",True)]>>>
t |= a
True
Note: The variable "b"
is missing in the map above, which means that it's
implictly assigned the value False
.
>>>
satAssignmentDPLL $ And (Var "a") (Not (Var "a")) -- unsatisfiable
Nothing
Abstract syntax trees
Abstract syntax tree class.
The value at the AST's root node.
The AST's child ASTs.
Number of edges on the longest path from the root of the AST to a leaf.
Number of nodes in the AST.
subtrees :: (AST t, Ord t) => t -> Set t Source #
(
is the set of all subtrees of an AST subtrees
t)t
(including t
itself).
properSubtrees :: (AST t, Ord t) => t -> Set t Source #
(
is the the set of all proper subtrees of an AST
properSubtrees
t)t
(i.e., not including t
itself).
Parsing
parseFormula :: String -> Maybe (Formula String) Source #
(
parses a string parseFormula
s)s
as a propositional formula,
returning a
on success, where Just
aa
is the parsed formula.
For a version of parseFormula
that does not return a wrapped formula but
also throws an error when it cannot parse, see unsafeParseFormula
.
Conventions
Supported connective symbols:
- Negation:
"~"
,"¬"
. - Implication:
"->"
,"=>"
,"→"
,"⇾"
,"⇒"
"⊃"
. - Disjunction:
"|"
,"\/"
,"∨"
,"+"
- Conjunction:
"&"
,"/\"
,"∧"
,"^"
,"*"
- Equivalence:
"<->"
,"↔"
,"⇿"
,"⇔"
- Negation:
- Implication is right-associative and has lower precedence than the other connectives.
- Equivalence is left-associative and has higher precedence than implication but lower precedence than conjunction and disjunction.
- Disjunction is left-associative and has higher precedence than equivalence but lower precedence than conjunction.
- Conjunction is left-associative and has highest precedence out of the binary connectives.
- Negation binds most tightly, and must immediately precede its argument (i.e., there should not be a space between a negation symbol and the proposition that follows).
- Valid variable names begin with a letter (uppercase or lowercase) or an
underscore, and may be followed by a letter, underscore, digit, or single
quote (a "prime" symbol). The exceptions are the strings
"false"
and"true"
, which are parsed as the propositional literals \(\bot\) and \(\top\), respectively.
Examples
>>>
parseFormula "a -> b -> c"
Just (Imp (Var "a") (Imp (Var "b") (Var "c")))
>>>
parseFormula "~a | b -> c"
Just (Imp (Or (Not (Var "a")) (Var "b")) (Var "c"))
>>>
parseFormula "(a -> b) & ~c"
Just (And (Imp (Var "a") (Var "b")) (Not (Var "c")))
parseJudgement :: String -> Maybe (Judgement String) Source #
(parseJudgement s)
parses a string s
as a propositional judgement.
A valid judgement is made up of an antecedent, a turnstile symbol, and a
consequent (in that order). The antecedents are a (potentially empty)
comma-separated list of formulas, the turnstile symbol is either "|-"
or
"⊢"
, and the consequent is another formula.
See parseFormula
for the specification of valid formulas.
Examples
>>>
parseJudgement "a, a -> b |- b"
Just ([Var "a",Imp (Var "a") (Var "b")] |- Var "b")
>>>
parseJudgement "a |- a | b"
Just ([Var "a"] |- Or (Var "a") (Var "b"))
Pretty-printing
pretty :: PrettyPrintable a => a -> String Source #
Pretty-print a value.
prettyFormula :: PrettyPrintable a => Formula a -> String Source #
Get a pretty-printed representation of a propositional formula.
Examples
>>>
prettyFormula $ Imp (Var "a") (Or (Var "b") (Lit False))
"a → (b ∨ ⊥)"
prettyJudgement :: PrettyPrintable a => Judgement a -> String Source #
Get a pretty-printed representation of a judgement.
Examples
>>>
prettyJudgement $ [Var "a", Imp (Var "a") (Var "b")] |- Var "b"
"a, a → b ⊢ b"
prettyProof :: PrettyPrintable a => Proof a -> String Source #
Get a pretty-printed representation of a proof.