Copyright | (c) Artem Mavrin 2021 |
---|---|
License | BSD3 |
Maintainer | artemvmavrin@gmail.com |
Stability | experimental |
Portability | POSIX |
Safe Haskell | Safe |
Language | Haskell2010 |
Intuitionistic 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
- 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
- prove :: Ord a => Judgement a -> Maybe (Proof a)
- proveTautology :: Ord a => Formula a -> Maybe (Proof a)
- proveStatman :: Ord a => Judgement a -> Maybe (Proof a)
- proveImp :: Ord a => Judgement a -> Maybe (Proof a)
- isProvable :: Ord a => Judgement a -> Bool
- isTautology :: Ord a => Formula a -> Bool
- findCut :: Proof a -> Maybe (Proof a)
- hasCut :: Proof a -> Bool
- correct :: Ord a => Judgement a -> Proof a -> Bool
- valid :: Ord a => Proof a -> Bool
- debug :: Ord a => Proof a -> Either (Proof a) ()
- 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'))
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 |
Proof search for judgements and formulas
prove :: Ord a => Judgement a -> Maybe (Proof a) Source #
Find an intuitionistic proof of a judgement, if a proof exists.
proveTautology :: Ord a => Formula a -> Maybe (Proof a) Source #
Find an intuitionistic proof of a formula, if a proof exists.
Specific proof search algorithms
proveStatman :: Ord a => Judgement a -> Maybe (Proof a) Source #
Find an intuitionistic proof of a judgement, if one exists, using Statman's algorithm.
- Richard Statman (1979) "Intuitionistic propositional logic is polynomial-space complete." Theoretical Computer Science, Volume 9, Issue 1, pp. 67–72. DOI.
The judgement to be proved is converted to an implicational judgement as
described in toImp
and proved (if possible) using proveImp
. The resulting
proof is then converted into a proof of the original judgement.
proveImp :: Ord a => Judgement a -> Maybe (Proof a) Source #
(
finds an intuitionistic proof
of a judgement \(g \vdash a\) in the implicational fragment of propositional
logic, if such a proof exists.proveImp
(g |-
a))
The algorithm is adapted from section 2.4 of
- Samuel Mimram (2020) PROGRAM = PROOF.
Examples
>>>
proveImp $ [Var 'a', Imp (Var 'a') (Var 'b')] |- Var 'b'
Just (ImpElim ([Var 'a',Imp (Var 'a') (Var 'b')] |- Var 'b') (Axiom ([Var 'a',Imp (Var 'a') (Var 'b')] |- Imp (Var 'a') (Var 'b'))) (Axiom ([Var 'a',Imp (Var 'a') (Var 'b')] |- Var 'a')))
>>>
proveImp $ [Imp (Var 'a') (Var 'b'), Imp (Var 'b') (Var 'a')] |- Var 'a'
Nothing
Provability checking
isProvable :: Ord a => Judgement a -> Bool Source #
Determine whether a judgement is intuitionistically valid.
Examples
>>>
isProvable $ [Var "a", Var "b"] |- And (Var "a") (Var "b")
True
>>>
isProvable $ [] |- Or (Var "a") (Not (Var "a"))
False
isTautology :: Ord a => Formula a -> Bool Source #
Determine whether a formula is an intuitionistic tautology.
Examples
>>>
isTautology $ Imp (And (Var 'a') (Var 'b')) (Var 'a')
True
>>>
isTautology $ Or (Var 'a') (Not (Var 'a'))
False
>>>
isTautology $ Not (Not (Or (Var 'a') (Not (Var 'a'))))
True
Cuts
findCut :: Proof a -> Maybe (Proof a) Source #
Find the cut nearest the root of a proof, if any. This functions assumes the proof is valid.
Proof correctness
correct :: Ord a => Judgement a -> Proof a -> Bool Source #
Check whether a proof is a correct proof of a given judgement
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.