Skip to content

Commit 4cf6c28

Browse files
committed
Add docstrings.
This documents all exported functions, and important exported types.
1 parent 3c49e1b commit 4cf6c28

11 files changed

+148
-10
lines changed

src/conjunctive_normal_form.jl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
export get_conjunctive_normal_form
22

33
"""
4-
Get equivalent formula in the conjunctive normal form for a given formula.
4+
get_conjunctive_normal_form(formula)
5+
6+
Return `formula` in the conjunctive normal form, expressed as clauses.
7+
8+
`formula` must not contain quantifiers. The returned formula is logically
9+
equivalent to `formula`.
510
"""
611
function get_conjunctive_normal_form(formula)
712
# Ideally, we would use a single @match clause to handle both
813
# negations and junctions. The negation case is tricky to implement
914
# in such a unified approach, however, so we generate the CNF in two
1015
# steps.
11-
"""
12-
Get equivalent formula with no negation in non-literal formulas.
13-
"""
1416
function collapse_negations(formula)
1517
@match formula begin
1618
f::Negation => begin

src/helpers.jl

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
export @debug
1+
export @debug,
2+
powerset,
3+
getnextfreesymbol,
4+
resetfreesymbols
25

36
function bracketsplit(str)
47
parts = []
@@ -46,6 +49,11 @@ function strip_and_remove_surrounding_brackets(str)
4649
str
4750
end
4851

52+
"""
53+
powerset(x)
54+
55+
Returns the powerset of x (a set of all subsets of x).
56+
"""
4957
function powerset(x)
5058
result = [Set()]
5159
for element in collect(x), idx = 1:length(result)
@@ -83,6 +91,11 @@ function dispatch_applyrecursively(functionexpr, objectexpr,
8391
end
8492
end
8593

94+
"""
95+
@debug variable
96+
97+
Print the symbol `variable`, followed by its value, followed by an empty line.
98+
"""
8699
macro debug(variable)
87100
Expr(:call,
88101
:println,
@@ -95,6 +108,27 @@ macro debug(variable)
95108
)
96109
end
97110

111+
112+
"""
113+
getnextfreesymbol()
114+
115+
Returns a new, unique string that can be used
116+
for naming objects.
117+
118+
This does not check if a user-entered formula
119+
already contains the returned string.
120+
"""
121+
function getnextfreesymbol end
122+
123+
"""
124+
resetfreesymbols()
125+
126+
Resets the free symbol state.
127+
128+
Newly generated symbols will "start over".
129+
"""
130+
function resetfreesymbols end
131+
98132
let nextfreesymbol = 0
99133
global getnextfreesymbol
100134
global resetfreesymbols

src/parser.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
export Formula
2+
13
Term(str::AbstractString) = begin
24
function get_term(str)
35
function_match = match(r"(\w*)\((.*)\)$", str)
@@ -38,6 +40,11 @@ AFormula(str::AbstractString) = begin
3840
AFormula(Variable(name), Formula(formula))
3941
end
4042

43+
"""
44+
Formula(str::AbstractString)
45+
46+
Parse `str` to a Formula object and return that object.
47+
"""
4148
Formula(str::AbstractString) = begin
4249
formula = strip_and_remove_surrounding_brackets(str)
4350
parts = strip.(bracketsplit(formula))

src/prenex_normal_form.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ function handle_junction(formula1, formula2, junction)
2525
end
2626
end
2727

28+
"""
29+
get_prenex_normal_form(formula)
30+
31+
Return the prenex normal form of `formula`.
32+
33+
The returned formula is logically equivalent to `formula`.
34+
"""
2835
function get_prenex_normal_form(formula)
2936
prepared_formula = get_renamed_quantifiers_form(formula)
3037
@match prepared_formula begin

src/quantified_variables_form.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
export get_quantified_variables_form,
22
get_unbound_variables
33

4+
"""
5+
get_quantified_variables_form(formula)
6+
7+
Return `formula` with all unbound variables bound to existential quantifiers.
8+
9+
The returned formula is equisatisfiable with `formula`.
10+
"""
411
function get_quantified_variables_form(formula)
512
variables = get_unbound_variables(formula)
613
quantified_variables_form = formula

src/removed_quantifier_form.jl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
export get_removed_quantifier_form
22

3-
# In "Logik für Informatiker", the removed quantifier form
4-
# is called the "Matrix" of a formula. This has nothing to
5-
# do with the general notion of matrices in mathematics.
3+
"""
4+
get_removed_quantifier_form(formula::Union{Formula, Term})
5+
6+
Return `formula` without any quantifiers.
7+
"""
68
function get_removed_quantifier_form(formula::Union{Formula, Term})
79
@match formula begin
810
f::AFormula || f::EFormula => get_removed_quantifier_form(f.formula)

src/renamed_quantifiers_form.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
export get_renamed_quantifiers_form
22

3+
"""
4+
get_renamed_quantifiers_form(formula, replacements=Dict{Variable, Variable}())
5+
6+
Return `formula` with new, unique variable symbols assigned to each quantified variable.
7+
8+
The returned formula is logically equivalent to `formula`.
9+
"""
310
function get_renamed_quantifiers_form(formula, replacements=Dict{Variable, Variable}())
411
@match formula begin
512
f::Negation => Negation(

src/resolution.jl

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
export is_satisfiable
22

3+
"""
4+
get_most_general_unifier(unifiables::Set{<:Unifiable})
5+
6+
Returns the most general unifier of `unifiable1` and `unifiable2`.
7+
8+
This is a naive implementation of a unification algorithm. It is supposed to be comprehensible.
9+
"""
310
function get_most_general_unifier(unifiables::Set{<:Unifiable})
411
unifier = Substitution()
512
unified = first(unifiables)
@@ -10,6 +17,13 @@ function get_most_general_unifier(unifiables::Set{<:Unifiable})
1017
unifier
1118
end
1219

20+
"""
21+
most_general_unifier!(unifier!::Substitution, unifiable1::Unifiable, unifiable2::Unifiable)
22+
23+
Computes the most general unifier of `unifiable1` and `unifiable2` and stores it in `unifier!`.
24+
25+
This is a naive implementation of a unification algorithm. It is supposed to be comprehensible.
26+
"""
1327
function most_general_unifier!(unifier!::Substitution, unifiable1::Unifiable, unifiable2::Unifiable)
1428
substituted_unifiable1 = substitute(unifiable1, unifier!)
1529
substituted_unifiable2 = substitute(unifiable2, unifier!)
@@ -65,7 +79,16 @@ function most_general_unifier!(unifier!::Substitution, unifiable1::Unifiable, un
6579
end
6680
end
6781

68-
# Apply substitution in order.
82+
"""
83+
substitute(formula::Union{Term, Formula, Literal, Clause}, substitution::Substitution)
84+
85+
Return `formula` with all entries in `substitution` applied in order.
86+
87+
A `substitution` entry consists of a variable and a term. An entry is applied by replacing all
88+
occurrences of the variable with the term.
89+
"""
90+
function substitute end
91+
6992
function substitute(formula::Union{Term, Formula, Literal, Clause}, substitution::Substitution)
7093
substituted_formula = formula
7194
for (substitutee, substituter) in substitution
@@ -103,6 +126,14 @@ function substitute(formula::Union{Term, Formula, Literal, Clause}, substitutee,
103126
end
104127
end
105128

129+
"""
130+
rename_all_variables(formula, replacements=Dict{Variable, Variable}())
131+
132+
Return `formula` with all variables replace by new, unique names. The returned
133+
formula is logically equivalent to `formula`.
134+
135+
The `replacements` dictionary is for internal use only.
136+
"""
106137
function rename_all_variables(formula, replacements=Dict{Variable, Variable}())
107138
@match formula begin
108139
f::Clause => @applyrecursively rename_all_variables(:_, replacements) f Clause
@@ -134,6 +165,16 @@ function rename_all_variables(formula, replacements=Dict{Variable, Variable}())
134165
end
135166
end
136167

168+
"""
169+
get_maybe_unifiable_literals(clause1::Clause, clause2::Clause)
170+
171+
Return a set of clauses that might be unifiable.
172+
173+
Each returned clause consists of literals in `clause1` and literals in
174+
`clause2`. To be considered unifiable, the selected literals in `clause1`
175+
must have the opposite negation of the literals in `clause2`. This function
176+
is used to reduce the search space for literals for the unification algorithm.
177+
"""
137178
function get_maybe_unifiable_literals(clause1::Clause, clause2::Clause)
138179
maybe_unifiable_literals = Set{Set{Literal}}()
139180
all_literals = union(clause1, clause2)
@@ -159,6 +200,21 @@ function get_maybe_unifiable_literals(clause1::Clause, clause2::Clause)
159200
maybe_unifiable_literals
160201
end
161202

203+
"""
204+
is_satisfiable(formula; maxsearchdepth)
205+
206+
Check if `formula` is satisfiable.
207+
208+
If `formula` is unsatisfiable, this function will return `false` in finite time.
209+
If `formula` is satisfiable, this function may run forever. This behavior stems
210+
from the fundamental limit that the satisfiability problem for first-order logic
211+
is semidecidable. The `maxsearchdepth` parameter allows you to work around this
212+
limitation by specifying the maximum expansion depth of the resolution algorithm
213+
search tree. If the algorithm exceeds that limit, it throws an OverMaxSearchDepthError
214+
exception.
215+
"""
216+
function is_satisfiable end
217+
162218
function is_satisfiable(clauses::CNF; maxsearchdepth=Inf)
163219
if maxsearchdepth == 0
164220
throw(OverMaxSearchDepthError())

src/skolem_normal_form.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
export get_skolem_normal_form
2+
"""
3+
get_skolem_normal_form(formula, replacements=Dict{Variable, Function}(), all_quantifiers=Vector{Variable}())
24
5+
Returns the [skolem normal form](https://en.wikipedia.org/wiki/Skolem_normal_form) of `formula`.
6+
7+
`replacements` and `all_quantifiers` are optional arguments that are only used internally.
8+
The returned formula is equisatisfiable with `formula`.
9+
"""
310
function get_skolem_normal_form(formula, replacements=Dict{Variable, Function}(), all_quantifiers=Vector{Variable}())
411
@match formula begin
512
f::AFormula => begin

src/testing_helpers.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,22 @@ using Base.Test
33
export @customtest,
44
@customtest_throws
55

6+
#=
7+
customtest and customtest_throws are wrappers around the normal
8+
@test and @test_throws macros. They ensure that the test execution
9+
is independent of the test order by resetting the interal package state.
10+
Currently, the internal package state consists only of the next free
11+
symbol.
12+
=#
13+
614
macro customtest(test)
715
quote
816
resetfreesymbols()
917
@test $(esc(test))
1018
resetfreesymbols()
1119
end
1220
end
21+
1322
macro customtest_throws(exception, test)
1423
quote
1524
resetfreesymbols()

0 commit comments

Comments
 (0)