Logic programs

In a logic program terms are used to denote the entities that constitute the world that the program is about.

Terms

\semindex{terms} Terms denote individuals. Terms are either constants or functional expressions. Constants are used as names for particular individuals. Numbers or names of persons are examples of constants. We will use the letter c, possibly subscripted, for indicating constants. To be able to refer to unspecified items we use logical variables, that we will write as capital X, Y, Z. We may also use compound terms to denote individuals. We use the letters f and g as function-symbols and write such functional expressions as f(t1,...,t_n) where each t_i , for 0 <= i <= n , is a term. In other words, if we define terms t by [] t ::= c | X | f(t1,...,t_n) : n >= 0 then a term can be either a constant, a logical variable or a compound term consisting of a function-symbol and zero or more argument-terms. As an example from mathematical logic, we have the constant 0 and the compound terms s(0), s(s(0)),..., wich are commonly used to denote the natural numbers. As a hint, just count the number of function-symbols! To illustrate the use of a variable consider the term s(X). This term may be regarded as denoting any number greater than zero, since whatever value X takes there is always at least one function-symbol.

Literals

\semindex{literals} Having defined terms we may introduce atoms and literals. We use the letters p and q for predicate-symbols and write p(t1,...,t_n) or q(t1,...,t_n) for atoms. Atoms with zero arguments may be regarded as atomic propositions. A literal is either an atom or the negation of an atom. We will use the letters A and B, possibly subscripted to write literals. We will call literals with a negation sign negative literals, and literals without a negation sign positive literals.

Program clauses

\semindex{clauses} \semindex{program clauses} The constituents of a logic program are clauses. In general, clauses have the form \semindex{\programclause} [] A <- B1,...,B_n where A is commonly called the head of the clause and the literals B1,...,B_n the body. Informally such a clause may be read as stating that A holds if each of the literals B1,...,B_n holds. In other words, the arrow pointing to the left may be read as an implication symbol relating the antecedent B1,...,B_n to the consequent A. The antecedent B1,...,B_n stands for the conjunction of the literals B1,...,B_n. In case the number of literals in the body is zero as in the clause \semindex{\factclause} [] A <- the literal A may be regarded as unconditionally true. The latter clause states a fact, whereas the former expresses an implication-like rule. These two kinds of clauses are called program clauses. A logic program is simply a collection of program clauses. We use the letter P to denote a logic program.

Goal clauses

\semindex{goal clauses} Apart from the program clauses, two additional kinds of clauses exist: goal clauses and the empty clause. Goal clauses are of the form \semindex{\goalclause} [] <- G where G is a conjunction of literals B1,...,B_n, just as the body of a program clause. In contrast with a program clause, a goal clause has an empty head. A goal clause such as the one above can be regarded as a request to prove the conjunction of the literals B1,...,B_n. When also the right-hand side of a goal clause is empty we speak of the empty clause, which is usually written as []. \semindex{\emptyclause} For such a goal clause there is nothing left to be proven. As an example, consider the clauses \oprog{number}{
    number(0) <- 
    number(s(X)) <- number(X)
  
} that define the natural numbers, including zero. As a goal clause we may then state <- number(s(s(0)) asking whether s(s(0)) is a natural number, which is obviously the case.