Horn clauses
A Horn clause is a disjunction with at most one positive literal, where all variables are implicitly universally quantified over the whole formula. For example,
¬father(X,Y) ∨ ¬father(Y,Z) ∨ grandfather(X,Z)
is a Horn clause. Since ¬α ∨ ¬β is equivalent to ¬(α ∧ β), and ¬α ∨ β is equivalent to α → β, that Horn clause can be written as:
¬father(X,Y) ∨ ¬father(Y,Z) ∨ grandfather(X,Z)
≡ ¬(father(X,Y) ∧ father(Y,Z)) ∨ grandfather(X,Z)
≡ father(X,Y) ∧ father(Y,Z) → grandfather(X,Z)
Or, equivalently, as:
grandfather(X,Z) ← father(X,Y) ∧ father(Y,Z)
A Horn clause composed by a single positive literal is called a fact. For example, father(adam,cain) ∨ ⊥
, which can be written as father(adam,cain) ← ⊤
, is a fact.
A Horn clause without positive literal is called a goal (a.k.a. query). For example, ⊥ ∨ ¬father(adam,cain)
, which can be written as ⊥ ← father(adam,cain)
, is a goal.
A Horn clause of the form ⊥ ← ⊤ is called a contradiction. For example, the resolution of the goal ⊥ ← father(adam,cain)
with the fact father(adam,cain) ← ⊤
produces the resolvent ⊥ ← ⊤
. The literal at the LHS of ← is positive, and a literal at the RHS is negative. Therefore, two unifiable literals in opposite sides of ← can be cancelled by resolution.
A Horn clause that is not a goal clause is called a definite clause.
A set of definite clauses is called a logic program.
In logic programming, the constant literals ⊥ and ⊤ are often omitted. Usually, a fact is written as α ←, a goal is written as ← α, and a contradiction is written as ←.
Horn clauses express a subset of FOL with very useful properties (e.g., unique minimal models and relatively low computational complexity). In fact, Logic programming and Prolog are built on top of Horn clauses.
Proof by contradiction
Consider the following logic program (with numbered clauses):
(1) father(adam,abel) ←
(2) father(adam,cain) ←
(3) father(adam,seth) ←
(4) father(seth,enos) ←
(5) grandfather(X,Z) ← father(X,Y) ∧ father(Y,Z)
The question Who is Enos' grandfather? (that is, there is someone who is Enos' grandfather and we want to know who this person is) can be expressed by the formula ∃W.grandfather(W,enos)
. Clearly, that formula is not a Horn clause. However, in order to proof that formula by contradiction, we must consider its negation:
¬∃W.grandfather(W,enos)
≡ ∀W.¬grandfather(W,enos)
≡ ∀W.[⊥ ∨ ¬grandfather(W,enos)]
≡ ⊥ ← grandfather(W,enos)
≡ ← grandfather(W,enos)
which is, indeed, a Horn clause (or, more precisely, a goal clause).
So, if the logic program (1)-(5) is consistent and ∃W.grandfather(W,enos)
is true w.r.t. that program, then the goal ← grandfather(W,enos)
must lead to a contradiction (and the constant bound to the universal variable W
must be the desired answer for the question):
← grandfather(W,enos) (5) grandfather(X,Z) ← father(X,Y) ∧ father(Y,Z)
| |
+-------------------------+ {X=W, Z=enos}
|
← father(W,Y) ∧ father(Y,enos) (3) father(adam,seth) ←
| |
+----------------------------------+ {W=adam, Y=seth}
|
← father(seth,enos) (4) father(seth,enos) ←
| |
+-----------------------+ {}
|
← [contradiction]
Horn clauses are useful in various applications due to their very nice
properties: the resolvent of two Horn clauses is a new Horn clause, and the
resolvent of a goal clause and a definite clause is a new goal clause.
Horn clauses and Prolog
In Prolog, the connective ∧
is replaced by ,
and the connective ←
is replaced by :-
(except in facts, where that connective is omitted, and in goals, where the top-level prompt ?-
implicitly stands for ←
).
"In logic, this is achieved by writing the statement as a rule with
an empty conclusion, i.e. a rule for which the truth of its premises would lead to falsity"
A clause with an empty conclusion is nothing more than a goal of the form ← α, which is equivalent to ⊥ ← α. So, if the premise α is true:
⊥ ← α
≡ ⊥ ← ⊤
≡ ⊥ ∨ ¬⊤
≡ ⊥ [falsity]
Thus, the symbols "?-" and ":-" are in fact equivalent. A
contradiction is found if resolution leads to the empty rule, of which
the premises are always true (since there are none), but the
conclusion is always false.
Since both symbols ?-
and :-
are used in place of ←
, clearly, they are equivalent. Particularly, the symbol ?-
is only implicitly used (when a query is typed in the top-level prompt). In some implementations of Prolog, a goal clause in the program source-code is automatically executed when that program is loaded. For example, when the following program is loaded in SWI-Prolog, the text Hi Alfred!
is written to the current output:
user('Alfred'). % user('Alfred') ←
:- user(Name), format('Hi ~w!~n', [Name]). % ← user(Name), format('Hi ~w!~n', [Name]).
Empty rule is just another name for contradiction (i.e., ⊥ ← ⊤
, often written simply as ←
). Of course, the premise of an empty rule is always true (⊤) and its conclusion is always false (⊥).