logo
 
Logic Programming
CptS 355 - Programming Language Design
Washington State University
Home
Notices
Calendar
Homework
Syllabus
Resources
People

Logic Programming

In the 1970s a programming language called Prolog was developed. The semantics of Prolog were derived from logic. The goal of this lecture is to become familiar with Prolog to write simple programs. There is much more to Prolog than we will cover.

Terminology

constant

A constant is an attribute value. By convention all constants start with lower-case letters. Some example constants are: joe, cp2001, sue, cp2003, etc.

variable

A variable is like a variable in a mathematical equation, it represents some constant that has yet to be determined. For example in the mathematical equation.
  X = Y + 3
The variable X is some unknown value, however, we know it is exactly 3 greater than the variable Y, which is also an unknown value. If we later determine that
  Y = 10
we then know that
  X = 13
Variables in Datalog are just like variables in mathematics. By convention variables always start with an upper case letter, e.g., Name, Code, Phone, X, Y, Z, etc.

fact

A fact is the same thing as a tuple in a relation. It is a true assertion about the enterprise being modelled. A ground fact has the following general form.
  predicate name(list of constants).
where predicate name is the name of a predicate. The fact is ground because no variables appear in the fact. Ground facts and predicates are like tuples in relations. The name of the predicate is effectively just the name of a relation, and the list of constants comprise the values of a tuple within that relation.

rules

A rule is a way to derive new facts, that is, a rule is (part of) a query. All rules have the following general form.
 head :- body
where the head is a single predicate and the body is a list of predicates. Each predicate is of the form.
  functor(list of constants or variables)
A rule has the following meaning in logic: the ':-' is an implication symbol (logical IF), and the ',' corresponds to logical AND. So let's assume we have the rule.
   Q :- P
This rules means IF P THEN Q, or in other words, if P is true then we can conclude that Q is true, or in other words
  P => Q
Modus Ponens is a proof rule in logic that let's us prove new facts. It is the only such proof rule in Datalog. Modus Ponens has the following general form. Given that
  • 'P => Q' is a true statement and
  • 'P' is true
  • then we know that 'Q' is true.
Or in other words, in Prolog, if we have some facts that support the body of a rule, we can conclude that the head is true.

Unification

Unification is the process of making one predicate the same as another. The end result of unification is that either the two predicates fail to unify, or they unify with perhaps some binding of constants to variables, or variables to variables. Two predicates are said to unify if
  • they have the same name,
  • they have the same number of attributes, and
  • each of their attributes unifies, left to right, using the following reasoning.
    • If both attributes are constants, they must be the same constant.
    • If one attribute is a constant, and the other a variable, then the variable is bound to the constant.
    • If both attributes are variables, they are bound to each other.
Let's try to unify some predicates. Do the following two predicates unify?
  1. sameSubject(joe, sue, Code)
  2. enrolledIn(joe, cp2001)
No they have different names, and a differing number of attributes. How about these?
  1. enrolledIn(joe, cp2001)
  2. enrolledIn(sue, cp2001)
No the first attributes in each are different constants. How about these?
  1. enrolledIn(joe, cp2001)
  2. enrolledIn(joe, cp2003)
No the second attributes in each are different constants. How about these?
  1. enrolledIn(Name, cp2001)
  2. enrolledIn(sue, cp2001)
Yes, with the caveat that the variable Name = sue (Name is bound to sue). How about these?
  1. enrolledIn(Name, cp2001)
  2. enrolledIn(sue, Code)
Yes, with the caveat that Name = sue and Code = cp2001. How about these?
  1. enrolledIn(sue, Code1)
  2. enrolledIn(sue, Code2)
Yes, with the caveat that Code1 = Code2. How about these?
  1. enrolledIn(X, X)
  2. enrolledIn(sue, Y)
Yes, with the caveat that sue = X = Y.

Queries

Prolog queries are evaluated in a top-down manner (from rule heads to rule bodies). This technique is called backward chaining. In backward chaining the head is unified, and then we try to prove each term in the body. An example will make the process clearer. Assume that we have the following set of facts.
    student(sue, 335-0904).
    student(joe, 335-4621).
    enrolledIn(joe, cpts355).
    enrolledIn(sue, cpts452).
    enrolledIn(joe, cpts460).
Further assume that we have one rule.
    full(Name, Code, Phone) :- student(Name, Phone), enrolledIn(Name, Code).
Finally, suppose our query is to find out the phone number(s) and names of those enrolled in cpts355.
    ? - full(X, cpts355, Y)
To evaluate this query, we will try first try to unify it with the head of some rule. Well, we have only one rule, so it is pretty easy.
    full(Name, Code, Phone)
                ^  
                |     
      full(X, cpts355, Y)
It produces the bindings X = Name, joe = Code, and Y = Phone. Now let's try to prove the first term in the rule.
    student(sue, 355-0904)
unifies with
    student(X, Y)
producing the bindings X = sue, Y = 355-0904. We now try to prove enrolledIn(sue, cpts355). Nothing unifies with that since sue is not enrolled in cpts355. So our attempt to prove the body of the rule fails. We try again with the next student fact.
    student(joe, 355-4621)
unifies with
    student(X, Y)
producing the bindings X = joe, Y = 355-4621. We next try to prove enrolledIn(joe, cpts355). It unifies with the first enrollment fact, so we have proved full(X, cpts355, Y) with the bindings X = joe and Y = 355-4621. In a very real sense, the body of a rule can be viewed as a pattern. A combination of facts `matches' or `unifies' with the pattern only under certain assignments of values to the variables. These assignments are made as new fact are derived.
    full(Name, Code, Phone) :- student(Name, Phone), enrolledIn(Name, Code).
         |      |     |                 ^     ^                  ^     ^
        \|/    \|/   \|/                |     |                  |     |
     full(X, cpts355, Y)      student(joe, 355-4621), enrolledIn(joe, cpts355).

Source of Information

These lecture notes are based on Chapter 16 in "Programming Languages, 6ed" by Robert Sebesta.
                                                                                                                                                                                                                                                                                                                                             
  (c) 2003 Curtis Dyreson, (c) 2004 Carl H. Hauser           E-mail questions or comments to Prof. Carl Hauser