|
Logic Programming
CptS 355 - Programming Language Design Washington State University |
|
Logic ProgrammingHistory of logic programmingLogic programming is based on rules of logical inference going back to Aristotle. In 1965 the resolution algorithm was discovered that provided a convenient implementation of logical inference letting computers construct proofs in the sense of Aristotle, Euclid, Frege, and Russell and Whitehead. The resolution idea quickly led to the creation of the Prolog language for logic programming.The goal of this lecture is to become familiar with Prolog in order to write simple programs. There is much more to Prolog than we will cover. TerminologyconstantA constant is an attribute value. By convention all constants start with lower-case letters. Some example constants are: joe, cp2001, sue, cp2003, etc.variableA 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 + 3The 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 = 10we then know that X = 13Variables in Prolog are more like variables in mathematics than are normal programming variables in other languages. By convention variables always start with an upper case letter, e.g., Name, Code, Phone, X, Y, Z, etc. factA 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.predicatename(list of constants).where predicatename is the name of a predicate. The fact is called 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. rulesA 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 :- bodywhere the head is a single predicate and the body is a comma-separated list of predicates. A general predicate is of the form. predicatename(list of constants, variables, or predicates)and ground predicates are a special case. 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, RThis rules means IF P AND R THEN Q, or in other words, if
P is true then we
can conclude that Q is true, or in other words
P => QModus Ponens is a proof rule in logic that let's us prove new facts. It is the only such proof rule in Prolog. Modus Ponens has the following general form. Given that
UnificationUnification 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
QueriesProlog 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).
Factorial exampleLook at factorial function in C:
/* assume x is non-negative */
int factorial (int x) {
return ( x ? x*factorial(x-1) : 1 )
}
The C factorial program will compute factorial(x) given x. But remember that
mathematicaly a function may be represented by its graph, and for factorial
this would be
factorial = {(0,1), (1,1), (2,2), (3,6), (4,24)...}
How could the function be represented in logic programming?
factorial(0,1). factorial(X,Y) :- X>0, Y=Z*X, W=X-1, factorial(W,Z).With this definition of factorial, we can make a query like
factorial(X,73572) to attempt to find X such that X! = 73572.
(Note that there obviously is no such X).
While this is
convenient to program, it may take a long time to execute!
ResourcesWikipedia has decent (not great) articles on both unification and Prolog. The Prolog article has links to many implementations that you could experiment with.gprolog seems good enough for elementary use. One thing that stumped
me for awhile was how to interactively enter facts and rules since the
interpreter prompts for a query -- ?-. Enter the query [user].
After that you can enter facts and rules. When finished, enter an end-of-file (ctrl-D or ctrl-Z). That will take you back to the query prompt.
|
|