Introduction
At the end of this chapter, you are going to understand how Atoms and Truth values are arranged into alphabets and grammars.
You will also get an in-depth view of how boolean Truth values and boolean Connective's are defined from both a syntax and a syntactical standpoint of view.
Finally, you will get a clearer idea about how to represent and manipulate interpretations and their outcomes.
Recalling the type hierarchy presented in man-core, it is here enriched with the following new types and structures.
TruthConnectiveAbstractAlphabetAbstractGrammarAbstractAlgebraAbstractLogicInterpretationTruthTableLogicalInstance
Alphabet
SoleLogics.AbstractAlphabet — Type
abstract type AbstractAlphabet{V} endAbstract type for representing an alphabet of atoms with values of type V. An alphabet (or propositional alphabet) is a set of atoms (assumed to be countable).
Examples
julia> Atom(1) in ExplicitAlphabet(Atom.(1:10))
true
julia> Atom(1) in ExplicitAlphabet(1:10)
true
julia> Atom(1) in AlphabetOfAny{String}()
false
julia> Atom("mystring") in AlphabetOfAny{String}()
true
julia> "mystring" in AlphabetOfAny{String}()
┌ Warning: Please, use Base.in(Atom(mystring), alphabet::AlphabetOfAny{String}) instead of Base.in(mystring, alphabet::AlphabetOfAny{String})
└ @ SoleLogics ...
trueInterface
atoms(a::AbstractAlphabet)::AbstractVectorBase.isfinite(::Type{<:AbstractAlphabet})::Boolrandatom(rng::Union{Random.AbstractRNG, Integer}, a::AbstractAlphabet, args...; kwargs...)::AbstractAtom
Utility functions
natoms(a::AbstractAlphabet)::BoolBase.in(p::AbstractAtom, a::AbstractAlphabet)::BoolBase.eltype(a::AbstractAlphabet)randatom(a::AbstractAlphabet, args...; kwargs...)::AbstractAtomatomstype(a::AbstractAlphabet)valuetype(a::AbstractAlphabet)
Implementation
When implementing a new alphabet type MyAlphabet, you should provide a method for establishing whether an atom belongs to it or not; while, in general, this method should be:
function Base.in(p::AbstractAtom, a::MyAlphabet)::Boolin the case of finite alphabets, it suffices to define a method:
function atoms(a::AbstractAlphabet)::AbstractVector{atomstype(a)}By default, an alphabet is considered finite:
Base.isfinite(::Type{<:AbstractAlphabet}) = true
Base.isfinite(a::AbstractAlphabet) = Base.isfinite(typeof(a))
Base.in(p::AbstractAtom, a::AbstractAlphabet) = Base.isfinite(a) ? Base.in(p, atoms(a)) : error(...)See also AbstractGrammar, AlphabetOfAny, AbstractAtom, ExplicitAlphabet.
Base.isfinite — Method
Base.isfinite(a::AbstractAlphabet)Return true if the alphabet is finite, false otherwise.
See AbstractAlphabet.
SoleLogics.atoms — Method
atoms(a::AbstractAlphabet)::AbstractVector{atomstype(a)}List the atoms of a finite alphabet.
See also AbstractAlphabet.
SoleLogics.natoms — Method
natoms(a::AbstractAlphabet)::IntegerReturn the number of atoms of a finite alphabet.
See also randatom, AbstractAlphabet.
Base.in — Method
Base.in(p::AbstractAtom, a::AbstractAlphabet)::BoolReturn whether an atom belongs to an alphabet.
See also AbstractAlphabet, AbstractAtom.
SoleLogics.ExplicitAlphabet — Type
struct ExplicitAlphabet{V} <: AbstractAlphabet{V}
atoms::Vector{Atom{V}}
endAn alphabet wrapping atoms in a (finite) Vector.
See also AbstractAlphabet, atoms.
SoleLogics.AlphabetOfAny — Type
struct AlphabetOfAny{V} <: AbstractAlphabet{V} endAn implicit, infinite alphabet that includes all atoms with values of a subtype of V.
See also AbstractAlphabet.
Grammar
SoleLogics.AbstractGrammar — Type
abstract type AbstractGrammar{V<:AbstractAlphabet,O<:Operator} endAbstract type for representing a context-free grammar based on a single alphabet of type V, and a set of operators that consists of all the (singleton) child types of O. V context-free grammar is a simple structure for defining formulas inductively.
Interface
alphabet(g::AbstractGrammar)::AbstractAlphabetBase.in(::SyntaxTree, g::AbstractGrammar)::Boolformulas(g::AbstractGrammar; kwargs...)::Vector{<:SyntaxTree}
Utility functions
Base.in(a::AbstractAtom, g::AbstractGrammar)atomstype(g::AbstractGrammar)tokenstype(g::AbstractGrammar)operatorstype(g::AbstractGrammar)alphabettype(g::AbstractGrammar)
See also alphabet, AbstractAlphabet, Operator.
SoleLogics.alphabet — Method
alphabet(g::AbstractGrammar{V} where {V})::VReturn the propositional alphabet of a grammar.
See also AbstractAlphabet, AbstractGrammar.
Base.in — Method
Base.in(φ::SyntaxTree, g::AbstractGrammar)::BoolReturn whether a SyntaxTree, belongs to a grammar.
See also AbstractGrammar, SyntaxTree.
SoleLogics.formulas — Method
formulas(
g::AbstractGrammar;
maxdepth::Integer,
nformulas::Union{Nothing,Integer} = nothing,
args...
)::Vector{<:SyntaxTree}Enumerate the formulas produced by a given grammar with a finite and iterable alphabet.
Implementation
Additional args can be used to model the function's behavior. At least these two arguments should be covered:
- a
nformulasargument can be used to limit the size of the returnedVector; - a
maxdepthargument can be used to limit the syntactic component, represented as a syntax tree,
to a given maximum depth;
See also AbstractGrammar, AbstractSyntaxBranch.
SoleLogics.CompleteFlatGrammar — Type
struct CompleteFlatGrammar{V<:AbstractAlphabet,O<:Operator} <: AbstractGrammar{V,O}
alphabet::V
operators::Vector{<:O}
endV grammar of all well-formed formulas obtained by the arity-complying composition of atoms of an alphabet of type V, and all operators in operators. With n operators, this grammar has exactly n+1 production rules. For example, with operators = [∧,∨], the grammar (in Backus-Naur form) is:
φ ::= p | φ ∧ φ | φ ∨ φwith p ∈ alphabet. Note: it is flat in the sense that all rules substitute the same (unique and starting) non-terminal symbol φ.
See also AbstractGrammar, Operator, alphabet, formulas, connectives, operators, leaves.
SoleLogics.connectives — Method
connectives(g::AbstractGrammar)List all connectives appearing in a grammar.
See also Connective, nconnectives.
SoleLogics.leaves — Method
leaves(g::AbstractGrammar)List all leaves appearing in a grammar.
See also SyntaxLeaf, nleaves.
SoleLogics.formulas — Method
formulas(
g::CompleteFlatGrammar{V,O} where {V,O};
maxdepth::Integer,
nformulas::Union{Nothing,Integer} = nothing
)::Vector{SyntaxBranch}Generate all formulas whose SyntaxBranchs that are not taller than a given maxdepth.
See also AbstractGrammar, SyntaxBranch.
Algebra
SoleLogics.AbstractAlgebra — Type
abstract type AbstractAlgebra{T<:Truth} endAbstract type for representing algebras. Algebras are used for grounding the truth of atoms and the semantics of operators. They typically encode a lattice structure where two elements(or nodes) ⊤ and ⊥ are referred to as TOP (or maximum) and bot (or minimum). Each node in the lattice represents a truth value that an atom or a formula can have on an interpretation, and the semantics of operators is given in terms of operations between truth values.
Interface
truthtype(a::AbstractAlgebra)domain(a::AbstractAlgebra)top(a::AbstractAlgebra)bot(a::AbstractAlgebra)
Utility functions
iscrisp(a::AbstractAlgebra)
Implementation
When implementing a new algebra type, the methods domain, TOP, and bot should be implemented.
See also bot, BooleanAlgebra, Operator, TOP, collatetruth, domain, iscrisp, truthtype.
SoleLogics.truthtype — Method
truthtype(::Type{<:AbstractAlgebra{T}}) where {T<:Truth} = T
truthtype(a::AbstractAlgebra) = truthtype(typeof(a))The Julia type for representing truth values of the algebra.
See also AbstractAlgebra.
SoleLogics.domain — Method
domain(a::AbstractAlgebra)Return an iterator to the values in the domain of a given algebra.
See also AbstractAlgebra.
SoleLogics.top — Method
SoleLogics.bot — Method
SoleLogics.iscrisp — Method
iscrisp(a::AbstractAlgebra) = iscrisp(typeof(a))An algebra is crisp (or boolean) when its domain only has two values, namely, the top and the bottom. The antonym of crisp is fuzzy.
See also AbstractAlgebra.
Logic
SoleLogics.AbstractLogic — Type
abstract type AbstractLogic{G<:AbstractGrammar,A<:AbstractAlgebra} endAbstract type of a logic, which comprehends a context-free grammar (syntax) and an algebra (semantics).
Interface
grammar(l::AbstractLogic)::AbstractGrammaralgebra(l::AbstractLogic)::AbstractAlgebra
Utility functions
- See also
AbstractGrammar - See also
AbstractAlgebra
Implementation
When implementing a new logic type, the methods grammar and algebra should be implemented.
See also AbstractAlgebra, AbstractGrammar.
SoleLogics.grammar — Method
grammar(l::AbstractLogic{G})::G where {G<:AbstractGrammar}Return the grammar of a given logic.
See also AbstractGrammar, AbstractLogic, algebra, alphabet, formulas, grammar, operators, truthtype.
SoleLogics.algebra — Method
algebra(l::AbstractLogic{G,V})::V where {G,V}Return the algebra of a given logic.
See also AbstractAlgebra, AbstractLogic.
More on Connectives
SoleLogics.NamedConnective — Type
struct NamedConnective{Symbol} <: Connective endA singleton type for representing connectives defined by a name or a symbol.
Examples
The AND connective (i.e., the logical conjunction) is defined as the subtype:
const CONJUNCTION = NamedConnective{:∧}()
const ∧ = CONJUNCTION
arity(::typeof(∧)) = 2See also NEGATION, CONJUNCTION, DISJUNCTION, IMPLICATION, Connective.
SoleLogics.collatetruth — Method
collatetruth(c::Connective, ts::NTuple{N,T where T<:Truth}, args...)::Truth where {N}Return the truth value for a composed formula c(t1, ..., tN), given the N with t1, ..., tN being Truth values.
See also simplify, Connective, Truth.
SoleLogics.simplify — Method
simplify(c::Connective, ts::NTuple{N,F where F<:Formula} args...)::Truth where {N}Return a formula with the same semantics of a composed formula c(φ1, ..., φN), given the N immediate sub-formulas.
See also collatetruth, Connective, Formula.
Propositional boolean logic
SoleLogics.NEGATION — Constant
const NEGATION = NamedConnective{:¬}()
const ¬ = NEGATION
arity(::typeof(¬)) = 1Logical negation (also referred to as complement). It can be typed by \neg<tab>.
See also NamedConnective, Connective.
SoleLogics.CONJUNCTION — Constant
const CONJUNCTION = NamedConnective{:∧}()
const ∧ = CONJUNCTION
arity(::typeof(∧)) = 2Logical conjunction. It can be typed by \wedge<tab>.
See also NamedConnective, Connective.
SoleLogics.DISJUNCTION — Constant
const DISJUNCTION = NamedConnective{:∨}()
const ∨ = DISJUNCTION
arity(::typeof(∨)) = 2Logical disjunction. It can be typed by \vee<tab>.
See also NamedConnective, Connective.
SoleLogics.IMPLICATION — Constant
const IMPLICATION = NamedConnective{:→}()
const → = IMPLICATION
arity(::typeof(→)) = 2Logical implication. It can be typed by \to<tab>.
See also NamedConnective, Connective.
Boolean logic Connectives are regrouped in a single collection.
SoleLogics.BASE_CONNECTIVES — Constant
const BASE_CONNECTIVES = [¬, ∧, ∨, →]Basic logical operators.
See also NEGATION, CONJUNCTION, DISJUNCTION, IMPLICATION, Connective.
SoleLogics.BooleanTruth — Type
struct BooleanTruth <: Truth
flag::Bool
endStructure for representing the Boolean truth values ⊤ and ⊥. It wraps a flag which takes value true for ⊤ (TOP), and false for ⊥ (BOT)
See also BooleanAlgebra.
SoleLogics.BooleanAlgebra — Type
struct BooleanAlgebra <: AbstractAlgebra{Bool} endA Boolean algebra, defined on the values TOP (representing truth) and BOT (for bottom, representing falsehood). For this algebra, the basic operators negation, conjunction and disjunction (stylized as ¬, ∧, ∨) can be defined as the complement, minimum and maximum, of the integer cast of true and false, respectively.
See also Truth.
SoleLogics.BaseLogic — Type
struct BaseLogic{G<:AbstractGrammar,A<:AbstractAlgebra} <: AbstractLogic{G,A}
grammar::G
algebra::A
endA basic logic based on a grammar and an algebra, where both the grammar and the algebra are instantiated.
See also grammar, algebra, AbstractGrammar, AbstractAlgebra, AbstractLogic.
A method is provided to simply access a propositional logic.
SoleLogics.propositionallogic — Method
propositionallogic(;
alphabet = AlphabetOfAny{String}(),
operators = NamedConnective[¬, ∧, ∨, →],
grammar = CompleteFlatGrammar(AlphabetOfAny{String}(), NamedConnective[¬, ∧, ∨, →]),
algebra = BooleanAlgebra()
)Instantiate a propositional logic given a grammar and an algebra. Alternatively, an alphabet and a set of operators can be specified instead of the grammar.
Examples
julia> (¬) isa operatorstype(propositionallogic())
true
julia> (¬) isa operatorstype(propositionallogic(; operators = [∨]))
false
julia> propositionallogic(; alphabet = ["p", "q"]);
julia> propositionallogic(; alphabet = ExplicitAlphabet([Atom("p"), Atom("q")]));
See also modallogic, AbstractAlphabet, AbstractAlgebra, AlphabetOfAny, [CompleteFlatGrammar], BooleanAlgebra, BASE_PROPOSITIONAL_CONNECTIVES.
Interpretations
Interpretations are nothing but dictionaries working with Truth values, or other types that can be ultimately converted to Truth.
SoleLogics.AbstractAssignment — Type
abstract type AbstractAssignment <: Interpretation endAbstract type for assigments, that is, interpretations of propositional logic, encoding mappings from AbstractAtoms to Truth values.
Interface
Base.haskey(i::AbstractAssignment, ::AbstractAtom)::Boolinlinedisplay(i::AbstractAssignment)::Stringinterpret(a::AbstractAtom, i::AbstractAssignment, args...; kwargs...)::SyntaxLeaf
See also AbstractAssignment, AbstractAtom, Interpretation.
Base.haskey — Method
Base.haskey(i::AbstractAssignment, ::AbstractAtom)::BoolReturn whether an AbstractAssignment has a truth value for a given Atom. If any object is passed, it is wrapped in an Atom and then checked.
Examples
julia> haskey(TruthDict(["a" => true, "b" => false, "c" => true]), Atom("a"))
true
julia> haskey(TruthDict(1:4, false), Atom(3))
trueSee also AbstractAssignment, Interpretation, AbstractAtom, TruthDict, Atom.
SoleLogics.TruthDict — Type
struct TruthDict{D<:AbstractDict{A where A<:Atom,T where T<:Truth}} <: AbstractAssignment
truth::D
endA logical interpretation instantiated as a dictionary, explicitly assigning truth values to a finite set of atoms.
Examples
julia> TruthDict(1:4)
TruthDict with values:
┌────────┬────────┬────────┬────────┐
│ 4 │ 2 │ 3 │ 1 │
│ Int64 │ Int64 │ Int64 │ Int64 │
├────────┼────────┼────────┼────────┤
│ ⊤ │ ⊤ │ ⊤ │ ⊤ │
└────────┴────────┴────────┴────────┘
julia> t1 = TruthDict(1:4, false); t1[5] = true; t1
TruthDict with values:
┌───────┬───────┬───────┬───────┬───────┐
│ 5 │ 4 │ 2 │ 3 │ 1 │
│ Int64 │ Int64 │ Int64 │ Int64 │ Int64 │
├───────┼───────┼───────┼───────┼───────┤
│ ⊤ │ ⊥ │ ⊥ │ ⊥ │ ⊥ │
└───────┴───────┴───────┴───────┴───────┘
julia> t2 = TruthDict(["a" => true, "b" => false, "c" => true])
TruthDict with values:
┌────────┬────────┬────────┐
│ c │ b │ a │
│ String │ String │ String │
├────────┼────────┼────────┤
│ ⊤ │ ⊥ │ ⊤ │
└────────┴────────┴────────┘
julia> check(parseformula("a ∨ b"), t2)
true
If prompted for the value of an unknown atom, this throws an error. If boolean, integer, or float values are specified, they are converted to Truth values. If the structure is initialized as empty, BooleanTruth values are assumed.
See also AbstractAssignment, Interpretation, DefaultedTruthDict, BooleanTruth.
SoleLogics.DefaultedTruthDict — Type
struct DefaultedTruthDict{
D<:AbstractDict{A where A<:Atom,T where T<:Truth},
T<:Truth
} <: AbstractAssignment
truth::D
default_truth::T
endA truth table instantiated as a dictionary, plus a default value. This structure assigns truth values to a set of atoms and, when prompted for the value of an atom that is not in the dictionary, it returns default_truth.
Implementation
If you use interpret function and you pass a DefaultedTruthDict as AbstractAssignment and the Atom is not present in the dictionary, then the default dictionary value will be returned and not the Atom itself.
Here is an example of this.
julia> interpret(Atom(5), DefaultedTruthDict(string.(1:4), false))
⊥Examples
julia> t1 = DefaultedTruthDict(string.(1:4), false); t1["5"] = false; t1
DefaultedTruthDict with default truth `⊥` and values:
┌────────┬────────┬────────┬────────┬────────┐
│ 4 │ 1 │ 5 │ 2 │ 3 │
│ String │ String │ String │ String │ String │
├────────┼────────┼────────┼────────┼────────┤
│ ⊤ │ ⊤ │ ⊥ │ ⊤ │ ⊤ │
└────────┴────────┴────────┴────────┴────────┘
julia> check(parseformula("1 ∨ 2"), t1)
true
julia> check(parseformula("1 ∧ 5"), t1)
false
See also AbstractAssignment, Interpretation, interpret, Atom, TruthDict, DefaultedTruthDict.
To associate interpretations with their assignment, we can simply build a truth table.
SoleLogics.TruthTable — Type
struct TruthTable{A,T<:Truth}Dictionary which associates an AbstractAssignments to the truth value of the assignment itself on a SyntaxStructure.
See also AbstractAssignment, SyntaxStructure, Truth.
InterpretationSet
LogicalInstance{S<:InterpretationSet}
check(φ::Formula, s::InterpretationSet, i_instance::Integer, args...; kwargs...)
check(φ::Formula, s::InterpretationSet, args...; kwargs...)
InterpretationVector{M<:Interpretation}