3203. Introduction to Artificial Intelligence

Prolog (4)


1. Program as data

A special feature of Prolog is that there is no strict distinction between "program" and "data". There are built-in predicates that process both of them similarly.

To make program modification safe, some Prolog interpreters and compilers ask a predicate dynamic P/N to be used to declares a predicate name P with N arguments as a "dynamic" predicate, so its definition in the database (as facts and rules) can be changed at run time. By default the built-in predicates and predicates defined in files are static, that is, cannot be modified at run time.

To call it to accomplish the declaration when a file of Prolog program is loading:

:- dynamic factorial/2.
Other goals can be similarly achieved using ':-', such as
:- write('Welcome to my program!'), nl.
The actual changes of a database is carried out by the following predicates, where the clause C must be sufficiently instantiated to determine the predicate key, that is, the first predicate encountered when the clause is read from left to right. If a new predicate name is introduced by asserting, it is dynamic by default.

The goal listing(P) will display the current definition of the predicate P in the database.

Example: different from the previously introduced factorial programs, the following program will add facts into the database:

:- dynamic factorial/2.
factorial(0, 1). 
factorial(N, A) :- N > 0, N1 is N - 1, factorial(N1, A1), A is N*A1, 
                   asserta(factorial(N, A)), write(' * '). 
When it runs, new results will be remembered to avoid repeated calculation.
1 ?- factorial(3, X).
 *  *  * 
X = 6 .

2 ?- factorial(3, X).
X = 6 .

3 ?- listing(factorial).
:- dynamic factorial/2.

factorial(3, 6).
factorial(2, 2).
factorial(1, 1).
factorial(0, 1).
factorial(A, C) :-
        B is A+ -1,
        factorial(B, D),
        C is A*D,
        asserta(factorial(A, C)),
        write(' * ').

Operator "univ", written as "=..", converts between a term and a list, such as p(X, Y) =.. [p, X, Y]. It is useful for modifying dynamic predicates. An example to form a fact:
?- X =.. [bird, tweety], assert(X).
X = bird(tweety).

?- bird(Y).
Y = tweety.

Predicate clause(H,B) retrieves rules in memory whose head matches H and body matches B. H must be sufficiently instantiated to determine the main predicate of the head.

After a goal P has been built, it can be invoked by call(P). The goal succeed if P does, else fail. Example:

?- X =.. [append, [a], [b], Y], call(X).
X = append([a], [b], [a, b])
Y = [a, b].
In this way, a program can be built in run time, then executed.

The predicate call is also used in other places, such as to define not for negation.

By taking programs as data, the execution process of Prolog can be specified within Prolog itself, as a meta-interpreter of the language itself.


2. Prolog summary

Logic programming is declarative because it separates the "logic" part and the "control" part of a solution. Roughly speaking, user programs provide the former (as facts and rules), while the Prolog interpreter/compiler provides the latter (as a kind of depth-first search through the knowledge space), though the user can change it using control predicates.

The major differences between the two types of languages:
Prolog Java/C++
  • Declarative language, where a program consists of a set of facts and rules.
  • The execution of program corresponds to a goal-directed inference process.
  • A program can be used for different purposes.
  • A program can modify itself.
  • High flexibility.
  • Procedural language, where a program specifies an algorithm.
  • The execution of program corresponds to a sequence of operations on data.
  • A program is only used for a single purpose.
  • A program cannot modify itself.
  • High efficiency.

Suitable situations:
Prolog Java/C++
  • Where the solutions can be obtained by reasoning from available knowledge.
  • Where flexibility is more important than efficiency.
  • Where the solutions can be obtained by executing available algorithms.
  • Where efficiency is more important than flexibility.


3. Other declarative programming languages

The programming language Datalog can be considered as a subset of Prolog. It is often used as a query language for deductive databases.

Constraint Logic Programming extends Logic Programming technique to solve constraint satisfaction problems. In such a program, constraints on a problem are represented by propositions, including equations and inequalities. For example:

?- X + 2 = 7.
X = 5
Lisp is another popular programming language in AI. It is a functional programming language. See LISP Primer for a comprehensive description of the language. For example, a Lisp program for the function factorial:
(defun factorial (n)
   (if (= n 0) 1
       (* n (factorial (- n 1)))))
Similar to Prolog, List provides support for the manipulations of symbolic structures, and allows programs to be handled as data.