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.

Alphabet

SoleLogics.AbstractAlphabetType
abstract type AbstractAlphabet{V} end

Abstract 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 ...
true

Interface

  • atoms(a::AbstractAlphabet)::AbstractVector
  • Base.isfinite(::Type{<:AbstractAlphabet})::Bool
  • randatom(rng::Union{Random.AbstractRNG, Integer}, a::AbstractAlphabet, args...; kwargs...)::AbstractAtom

Utility functions

  • natoms(a::AbstractAlphabet)::Bool
  • Base.in(p::AbstractAtom, a::AbstractAlphabet)::Bool
  • Base.eltype(a::AbstractAlphabet)
  • randatom(a::AbstractAlphabet, args...; kwargs...)::AbstractAtom
  • atomstype(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)::Bool

in 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.

source

Grammar

SoleLogics.AbstractGrammarType
abstract type AbstractGrammar{V<:AbstractAlphabet,O<:Operator} end

Abstract 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)::AbstractAlphabet
  • Base.in(::SyntaxTree, g::AbstractGrammar)::Bool
  • formulas(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.

source
SoleLogics.formulasMethod
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 nformulas argument can be used to limit the size of the returned Vector;
  • a maxdepth argument can be used to limit the syntactic component, represented as a syntax tree,

to a given maximum depth;

See also AbstractGrammar, AbstractSyntaxBranch.

source
SoleLogics.CompleteFlatGrammarType
struct CompleteFlatGrammar{V<:AbstractAlphabet,O<:Operator} <: AbstractGrammar{V,O}
    alphabet::V
    operators::Vector{<:O}
end

V 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.

source
SoleLogics.formulasMethod
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.

source

Algebra

SoleLogics.AbstractAlgebraType
abstract type AbstractAlgebra{T<:Truth} end

Abstract 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.

source
SoleLogics.truthtypeMethod
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.

source
SoleLogics.iscrispMethod
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.

source

Logic

SoleLogics.AbstractLogicType
abstract type AbstractLogic{G<:AbstractGrammar,A<:AbstractAlgebra} end

Abstract type of a logic, which comprehends a context-free grammar (syntax) and an algebra (semantics).

Interface

  • grammar(l::AbstractLogic)::AbstractGrammar
  • algebra(l::AbstractLogic)::AbstractAlgebra

Utility functions

Implementation

When implementing a new logic type, the methods grammar and algebra should be implemented.

See also AbstractAlgebra, AbstractGrammar.

source

More on Connectives

SoleLogics.collatetruthMethod
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.

source
SoleLogics.simplifyMethod
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.

source

Propositional boolean logic

Boolean logic Connectives are regrouped in a single collection.

SoleLogics.BooleanTruthType
struct BooleanTruth <: Truth
    flag::Bool
end

Structure for representing the Boolean truth values ⊤ and ⊥. It wraps a flag which takes value true for ⊤ (TOP), and false for ⊥ (BOT)

See also BooleanAlgebra.

source
SoleLogics.BooleanAlgebraType
struct BooleanAlgebra <: AbstractAlgebra{Bool} end

A 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.

source

A method is provided to simply access a propositional logic.

SoleLogics.propositionallogicMethod
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.

source

Interpretations

Interpretations are nothing but dictionaries working with Truth values, or other types that can be ultimately converted to Truth.

SoleLogics.TruthDictType
struct TruthDict{D<:AbstractDict{A where A<:Atom,T where T<:Truth}} <: AbstractAssignment
    truth::D
end

A 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
Note

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, AbstractInterpretation, DefaultedTruthDict, BooleanTruth.

source
SoleLogics.DefaultedTruthDictType
struct DefaultedTruthDict{
    D<:AbstractDict{A where A<:Atom,T where T<:Truth},
    T<:Truth
} <: AbstractAssignment
    truth::D
    default_truth::T
end

A 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, AbstractInterpretation, interpret, Atom, TruthDict, DefaultedTruthDict.

source

To associate interpretations with their assignment, we can simply build a truth table.

AbstractInterpretationSet

LogicalInstance{S<:AbstractInterpretationSet}

check(φ::Formula, s::AbstractInterpretationSet, i_instance::Integer, args...; kwargs...)
check(φ::Formula, s::AbstractInterpretationSet, args...; kwargs...)

InterpretationVector{M<:AbstractInterpretation}