AUTOMATA DESIGN ASSOCIATES
A.D.A PROLOG Documentation Version 1.95C
for the Educational and Public
Domain Versions
June 21, 1987
Copyright Robert Morein and
Automata Design Associates
1570 Arran Way
Dresher, Pa.
19025
(215)-646-4894
News
A.D.A.
offers the first Prolog with a
Cyclic Structure Unifier
for the IBM PC.
If
you have CGA graphics
capability, be sure to run "The
Knight's Tour", by Tim Elliot, to be found in GAMES.ARC. It's a
graphic
representation of a classic
puzzle: how to
make the
"knight" piece
of chess, which has a rather
peculiar movement
rule, visit all the squares of a chess
board.
Javier Salazar
has contributed a wang
algorithm, which
determines the correctness of predicate
calculus formulae, and a
logic tutor.
Jim Adams
of Bendix Aerospace
has contributed a
skolemizer program
(look for the file "LOGIC.ARC". This
nifty
thing takes statements written in the
formalism of the predicate
calculus
and converts them to prolog Horn
clauses. You should
refer to chapter 10 of Clocksin and
Mellish for explanation.
Take a look at the chess endgame
program in "games."
Simon Blackwell's
"PIE" Truth Maintenance
System is
presented in revised, debugged, and
enlarged form. This system is
found
in the directory
"expert" and augments
the strictly
deductive capabilities
of raw Prolog with additional
forms of
reasoning. PIE
has a syntax that resembles colloquial
English.
Wait till you see the backwards quote
marks!
The predicates "batch"
and "nobatch" are introduced to allow
execution of batch files without confusing messages
and prompts
appearing on the screen. I've put one
in Simon's "KOPS" file.
1
Copyright
Notice
The public domain PD PROLOG system has been
contributed to
the
public domain for unrestricted use with one exception:
the
object
code may not be disassembled
or modified. Electronic
bulletin boards
and SIG groups are urged to aid in giving this
software the widest possible
distribution.
This documentation may be
reproduced freely, but it may not
be
included in any other documentation without the permission of
the author.
2
Introduction
We
hope that you'll get some fun out
of this PROLOG. It
will
afford
you exposure to THE fifth generation language at the cost
only
of some intellectual
effort. The motive
is perfectly
explicable: We
want you to think of Automata Design
Associates
for
fifth generation software.
It also gives us a nice warm
feeling.
The
minimum memory requirement is 200 k of transient
program
area,
plus whatever space is needed to execute programs
from
within PROLOG. DOS or MSDOS 2.0 are required. The program
does
not
require IBM PC compatibility to
run, although the
screen
access routines do require
compatibility.
3
Products by Automata
Design Associates
Automata Design
Associates specializes in
software for
artificial intelligence
and robotic applications. A
PROLOG
language system is available in various
configurations. A LISP
interpreter will be introduced in March
of 1985.
1. LISP systems
PD LISP
PD
LISP is a public domain Common LISP subset. It comes with
a
150 page instruction manual on disk,
and is available from us for
$10.00.
.UNX LISP
UNX LISP, written by Dave Morein, is a
Common LISP subset. It has
nifty
things like SAVE/RESTORE, which
let you stop a job in the
middle,
save it, and start it up again, and
tree structured
lexical scoping. It is available from
us for $69.95.
4
I.PROLOG Systems
There are
six versions of PROLOG available
from Automata
Design Associates. The systems run under the MSDOS or PCDOS. All
of them access all available memory up
to 1 megabyte.
.Public Domain PROLOG
This
serves to further the general awareness of the public about
PROLOG.
It also is an excellent adjunct
to anyone learning the
language. Most
of the core PROLOG described by
Clocksin and
Mellish
in the book Programming In PROLOG
is implemented. A
complete IBM PC video screen support library is
included in this
and all
other A.D.A. prologs. Trace predicates are not.
This
version is available from us for $10.00
postage paid.
.Educational PROLOG
At
extremely modest cost this affords an educational institution
or
individual a PROLOG
system which provides
the maximum
available programming
area available within
the 8086 small
programming model. Tracing,
a debugging aid, allows
monitoring
a program as it runs. User settable spy points selectively allow
this.
Exhaustive tracing is also
available. I/O redirection
gives some file ability.
An
"exec" function allows
the execution of a program
or
editor
from within PROLOG,
thus encouraging an
interactive
environment.
An
"interrupt" menu is
added, permitting the control of
tracing, toggling the printer, and
screen printing.
Definite clause grammar support is
now included.
The cost of Educational PROLOG is
$29.95.
.FS PROLOG
A
small increment in price adds full random access
file
capability. Character and structure I/O
are allowed.
The
"asserta and "assertz" predicates are expanded and work
with a clause indexing ability. One can assert clauses anywhere
in the database under precise pattern
matching control.
A tree structured lexical scoping
system and floating point
arithmetic are other enhancements.
The cost of FSM PROLOG is $49.95
5
.VMI PROLOG -- Virtual Memory (Replaces
type VMS)
At reasonable cost the addition of
virtual memory gives an
expansion of capabilities of an order
of magnitude.
The database on disk is treated
transparently. No special
provisions need
be made by the
user. Virtual and
resident
databases may be mixed.
A unique updating algorithim
preserves
the format of the database as typed by
the user while making only
those changes necessary to make it
equivalent to the database in
central memory.
The cost of VMI PROLOG is $99.95
6
.VML PROLOG Large model Virtual Memory
System
A.D.A. PROLOG is a remarkable fifth generation
developement
tool
for the implementation of
intelligent strategies and
optimized control.
It is both the kernel for applications
of
virtually unlimited scope and a sophisticated
developement tool
that multiplies the productivity of the
programmer many times.
Conventional Prolog
is based on the first order
predicate
calculus. VML
emulates the second
order calculus, with
unconstrained manipulation of
cyclic, self referential
structures. The
cyclic unifier is selectable by a mode
switch,
with no loss of compatibility.
Perhaps
only one other Prolog system, written
by Alain
Colmareur, permits manipulation of cyclic
structures. Permitted
by the second order predicate calculus,
but not the first, cyclic
structures are self referential, or
recursively defined.
A conventional Prolog system
typically crashes when a cyclic
structure is
found, because such a structure appears
to be
infinite. But with our Cyclic Unifier,
available in types VML and
VMA Prolog, cyclic structures can be
handled with impunity.
Many structures in nature are cyclic, and we suggest that
many applications will appear to the
user. For example, consider
the
benzene ring, which chemists
refer to as a cyclic aromatic
hydrocarbon:
H H
\ /
C ===== C
/ \
/ \
H --- C C --- H
\\ //
\\ //
C -----
C
/ \
H H
This
might be represented in Prolog by
a cyclic
structure as
follows:
X = [ [[c,h]],[c,h],[[c,h]],[c,h],[[c,h]],[c,h]|X]
It
would appear that groups and
topological properties can be
succinctly described as cyclic
structures. A simple group can be
expressed as follows:
X = [a,b,c|X].
7
Then
the cyclic nature of the group can be observed with
the goal "member( M, X )",
which gives:
a,b,c,a,b,c,a,b,c,....(ad
infinitum)
With a cost/performance ratio exceeding that of
any other
product
and a compatibility
insured by compliance
to the
Edinburgh syntax, performance is
enhanced by numerous extensions,
many of them invisible to the user.
A quick overview of some of the
features discloses:
1)
This system now incorporates a
cyclic structure
unifier. The
only other Prolog system capable
of
unifying cyclic structures is PrologII, written
by
the inventor of Prolog, Alain
Colmerauer.
2)
Invisible compilation to a semantic
network
preserves the flexibility of the
interpreted mode and
the speed of a compiler.
The programmer can compile and recompile any
portion
of a module at any time. The edit/compile/test cycle
is short and free of strain. An
interface is provided
to an editor of choice.
3) Floating point arithmetic with
a full complement
of
input and output
methods, transcendental and
conversion functions.
4)
Virtual memory. Module
size and number
are
unrestricted, with
a total capacity
of several
hundred megabytes. Resident and virtual modules may
be co-resident. Compilation is
incremental. The cache
algorithim is
sophisticated. Changes made in the
database can be updated to disk by
a single command.
5) A powerful exec function and
acceptance of stream
input make integration into applications practical.
6)
Global polymorphic variables
retain information
that would
otherwise require the
"assertion" of
facts.
7)
A quoted variable class, borrowed
from LISP,
permits referencing variables as objects as well as
by value.
8
8) Multidimensional arrays, dynamically created and
destroyed, efficiently
store numeric and nonnumeric
structures. Arrays are ideal for
representing spatial
and ordinal relationships.
9)
Debugging facilities let you see your program run
without any additional generation
steps.
10)
Totally invisible and
incremental garbage
collection. There
is NEVER any
wait for this
function.
11) A
tree structured, dynamically
configurable
lexical scoping system. The work
of many programmers
can be coupled together in the form of libraries
and
nested domains.
Each lexically scoped domain is a
hidden space which
communicates with the parent domain via exports and
imports. Domains can be linked
together under program
control to achieve any desired
configuration.
12) The Grammar Rule Notation is
an integral feature.
13) Keyword redefinition makes
porting code easy.
The
cost of this system is $200 for
the MSDOS version.
.VMA PROLOG Large model Virtual Memory
System
This
system has additional forms of virtual
memory. It was
intended for
deep reasoning problems.
Contact us for
more
information.
9
Prolog Runtime
Systems
The A.D.A. Runtime Systems permit distribution of debugged
code in source form without
royalties. A Runtime System provides
all
of the facilities of the
corresponding Development System
except for:
1) Tracing.
2)
The console command loop.
A
Runtime System is invoked from
the DOS command line with an
argument specifying a stream file that
replaces the console. The
stream file is a UNIX* innovation that
allows applications to be
connected by "pipes", in a
convenient, high level manner.
All the
other development facilities
remain available,
including multiple modules and virtual memory. Since update
to
disk
is included, the ability of the system to learn
is not
impaired in any way. Compare this to our competitors, whose hard
compiled code results in fixed goals and inability to
change the
distribution on a dynamic basis.
Four versions are available. Each is priced the same as the
corresponding development system, and can be distributed without
royalty by the license holder with his
applications:
FS
Runtime - $50.00
VMI Runtime - $100.00
VML Runtime - $200.00
VMA Runtime - $250.00
The above systems are in stock for
immediate delivery.
* trademark AT&T
10
Upgrade Policy
Half the cost of any A.D.A. PROLOG
system may be credited to
the purchase of a higher level
version. The full cost of VMS
prolog
may be applied to the purchase of VMI or
VML PROLOG.
Updates to a particular level product
vary from $15.00 to $35.00.
Technical Information
Technical information
may be obtained at (215) - 646-
4894. This is available provided that
you have read the entire
documentation supplied with this disk, and at least
the first
third of Programming In Prolog. We will
politely inquiries from
people who just want to see the sample
programs run.
Perhaps we can answer the
following questions in advance:
There is no support for: APPLE II, Atari, Commodore, or
CPM 80 . Other machines from these manufactures may be
supported
in the future.
The MSDOS
products are available on "5"
IBM compatible
diskettes.
To Place Your Order:
You may place your order at the
following number:
(215)-646-4894 - day and night.
Returns
The software may be returned within 30 days of
purchase for
a full refund. This applies whether or not the software has
been
used.
We do ask that manuals, disks and packaging be returned in
excellent condition.
11
Installation
You will need an IBM PC compatible
machine with a minimum of
256
kbytes of memory.
ED PROLOG benefits from all available
memory up to the 1 megabyte INTEL limit.
To
determine the amount of TPA your machine
has, run the
"chkdsk" program which is
supplied with DOS. The last line reads:
XXXXXX bytes
free
where XXXXXX is a six digit number.
If
this number is greater than 200000, ED
PROLOG will have
reduced workspace. If it's over 245000, the amount of memory is
optimal. If this is not the case, there
are two possibilities:
1) The machine doesn't have enough
memory.
2)
Something else is removing memory
from TPA, such as a co-
resident program,
a ramdisk, a large dos driver, or a
large
number of file or disk buffers.
If
you're short of memory, make sure that no other
programs,
ramdisks, or drivers besides DOS are running in the
machine. You
may find it helps to eliminate (by
renaming) the config.sys file
when you intend to run ED PROLOG.
How to run the
Demonstration Programs
without Knowing What
You're Doing
We strongly advise that you
purchase the book Programming in
PROLOG by Clocksin and Mellish, publisher Springer Verlag, 1981.
For
the impatient we give some
advice. Type the demonstration
program you wish to run. There must be at least one entry point
within
the program.
Note:
Please understand that these are
demonstrations programs.
Regarding user
interface, they are poorly written.
You will
probably have to read Clocksin and
Mellish to appreciate that the
following examples of input are not
equivalent: "yes." , "yes" .
The program fragment
"console" shows how you may improve the
console input routines of any of these
programs.
The Hematology Diagnosis Program -
"hemat"
Although the logical
structure is not as sophisticated as
that of "animals", it is
interesting for several reasons:
1)
The program evaluates numerical data to arrive
at a
diagnosis.
2) Although inaccurate, it demonstrates
that useful question
12
answering systems are not difficult to
write in PROLOG.
3)
There are some mistakes in the
program, which only
slightly impede its usefulness.
This program
uses structure input.
Terminate all your
answers with a period, as in
"y.<CR>", or "no.<CR>".
The starting point is
"signs.<CR>". PROLOG
will prompt you
for
signs of anemia.
The program attempts to
diagnose two
varieties of a hemolytic anemia.
The program could use a good
working over by a hematologist
and we would be delighted to
collaborate.
Prime Number Generator -
"sieve"
This program demonstrates that anything can be
programed in
PROLOG if one tries hard enough. Asking the
question
"primes( 50, L
).<CR>" causes a list of prime numbers less than
50
to be printed out.
"Sieve" is heavily recursive and quickly
exhausts the stack space of the small
model interpreters.
Grrules
This is
an example of the use
of the definite
clause
grammer
notation. PD PROLOG does
not have this
translation
facility, but ED PROLOG and all of our other versions do. It is
possible to
perform the translations
by hand if
you have
thoroughly read
C & M. Then you would have
the pleasure of
asking:
?-sentence( X,
[every,man,loves,a,woman], [] ).
and
having the meaning elucidated as a statment in the predicate
calculus.
13
Special
Offer # 1
For some
inexplicable reason,
demonstration programs are
hard to come by. We are too busy
writing PROLOG fill this gap. We
will reward the contribution of
"cute" sample programs. Here
are
the guidlines as of 9/3/86:
1) We've got enough games, puzzles and
geneology programs.
2) We need:
a)
Alternate forms of reasoning,
such as probabalistic
(Bayesian, fuzzy logic) forward
chaining, cover sets.
b)
Programs which use the graphics.
c)
3) Expert systems.
You
must be certain that your contribution does not infringe on
anyone's copyright.
The reward is the following: A copy of
VMI virtual memory PROLOG.
There will be a charge of $20.00 to
cover our costs. That way, we
won't go broke rewarding sample
programs.
The
sample program will be published as an intact file together
with whatever comments or advertisments
the author may see fit to
include, on our distribution disks.
Exceptional contributions
may merit a copy of type VML
large
model virtual memory PROLOG which now
incorporates a UNIX1 style
tree structured domain system.
Special Offer #
2
If
you are a hardware manufacturer and would like a PROLOG
language for your system, the solution is simple. Just send us
one
of your machines! Provided your system implements
a "C"
compiler, it will be ported in no time
flat.
______
1. Trademark of AT & T.
14
Writing Programs For
ED PROLOG
You do not type in programs at the
"?-" prompt. There is no
built-in editor.
The command "consult( user )" is accepted but
does not cause PROLOG to enter an
editing mode. We feel that the
most universally acceptable editing
method is for the user to use
a text editor of choice, which can be invoked from within PROLOG
by the "exec" predicate.
Use Wordstar
or your customary editor to write a
program.
Then
run PD PROLOG and use the consult function to
load the
program.
In
all cases except PD PROLOG, you can
run your editor
without leaving PROLOG by use of the
"exec" predicate.
15
Running the
Interpreter
COMMANDS: Give commands in lower case.
TO RUN:
Invoke PROLOG.EXE. After the "?-" prompt appears, you
may
give Prolog goals to be
executed, followed by a period, and
a carriage return.
TO ENTER A FACT:
Don't do it except with the
"assert" predicates. This is the
most frequently misunderstood aspect of
A.D.A. Prolog. If
you want to enter a bunch of
facts, put them in a file and
"consult" them using the
"consult" predicate.
TO ASK A QUESTION:
At the prompt, type
"<expression>.<CR>", where
<expression> is
a question as described by Clocksin
and
Mellish. Be sure to terminate the
question with a period.
The question may be up to 500
characters long.
TO INPUT A STRUCTURE AT THE KEYBOARD:
The structure may be up to 500
characters in length. Be sure
to terminate with a period.
TO ASK FOR ANOTHER SOLUTION:
If a solution has been provided,
the PROLOG interpreter will
ask "More?
(Y/N):". Only if a
"y" is typed
will the
interpreter perform a search.
TO ABORT A SEARCH:
Simply type
the escape key.
The interpreter will
respond with
"Interrrupted.", and
return to the command
prompt.
TO LOAD DATABASE:
Type
"consult(<filename>).<CR>" The file name must have
the
extension ".PRO". It
is not necessary
to include the
extension in the argument of
consult. The file name as given
must not be the same as a
predicate name in the file or any
file which will be loaded.
TO TRACE:
When the system displays the
prompt "?-", type "trace.<CR>".
The display will likely move too
rapidly for you to read. To
stop the display, type Control S. To restart the display,
type Control S.
To turn the trace
display off, type
"notrace<CR>" at
the prompt "?-". The
interrupt menu
contains additional
options, such as sending
all trace
output to a file, as well as
display at the console.
16
TO INTERRUPT A PROGRAM:
See the
section entitled "The
Interrupt Menu" for a
description of the flexible options. Basically,
one types
ESC to terminate a program, while Control V or Control
I
interrupt a program.
TO RECONSULT A FILE:
The predicate
"recon" is identical
to the Edinburgh
predicate "reconsult."
TO REMOVE A DATABASE:
Type
"forget(<filename>).<CR>"
TO REMOVE ALL ASSERTIONS MADE BY
PROGRAMS OR YOU:
Type "forget( user
).<CR>"
TO EXIT TO THE OPERATING SYSTEM:
Type
"exitsys.<CR>"
The system is totally interactive;
any commands the operator
gives
are and must be valid program statements. Statements must
terminate with a period. All commands which take a file name
also
accept a path name. Any name
which is not a valid PROLOG
atom (refer to C & M) must be
enclosed in single quotes. Thus one
could say
consult( expert )
but one would need single quotes with
consult(
'b:\samples\subtype\expert' ).
To exit the system, type
"exitsys.<CR>"
Atoms
may contain MSDOS pathnames if they are enclosed by single
quotes, ie., '\b:\samples\animal' .
You may consult more than one file at a
time. However, all names
are public and name conflicts must be
avoided. The order in which
modules are loaded may, in cases of poor program design, affect
the behavior.
Command Line
Arguments
ED and PD PROLOG accept one
command line argument, which is
the name of a "stream" which
replaces the console for input. The
"stream" in
MSDOS is a pipe or file which supplies input until
end-of-file is reached. Control then
reverts back to the console.
To avoid noisy parser error messages
when end-of-file is reached,
the
last command in the file should be "see( user )." See Simon
Blackwell's PIE program for an example
of this.
17
A Reference of Note
With minor
exceptions, the syntax is a
superset of that
described by
Clocksin and Mellish in the
book Programming in
Prolog by W.F. Clocksin and C.S. Mellish, published by Springer
Verlag in Berlin, Heidelberg, New York,
and Tokyo. We shall refer
to this book as "C & M".
A book
review section is included at the end
of this
documentation.
There are
very few syntactical
differences, mostly
unrecognized and/or minor.
When an operator is declared using the
"op" statement, the
operator must be enclosed in single
quotes in the "op" statement
itself,
if it would not otherwise be a
legal Edinburgh functor.
Subsequently, however,
the parser will recognize it for what it
is,
except in the "unop" statement, where it
must again be
enclosed in single quotes.
Variable numbers of functor
paramaters are supported.
A
goal may be represented by a variable,
which is less
restrictive than
the C &
M requirement that all
goals be
functors. The
variable must be instantiated to a
functor when
that goal is pursued.
Rules which appear inside other
expressions must be enclosed
in
parenthesis if the "," operator is to be recognized
as a
logical connective.
All infix
operators described by C & M,
and user defined
infix,
prefix, and postfix operators with variable associativity
and precedence are supported exactly as
in C & M.
18
Memory Size
Configuration
Type ED
can access the full memory
of the
machine, but
previously required configuation by
A.D.A. The supplied program
"prconf.exe" allows
the user to configure the amount of
memory
used
by the PROLOG system. The reason
why this is important is
that
it is the vacant memory above the system which is used
by
the
"exec" function to load and execute other
programs. The
amount of memory used is configured
into the PROLOG.EXE file and
cannot be changed when PROLOG is
actually running.
The configuration
is carried out
with PRCONF.EXE and
PROLOG.EXE on the same disk. The user runs
PRCONF and answers the
sole question
Enter the amount of workspace
required in decimal Kbytes:
PRCONF
then modifies the PROLOG.EXE file and writes the changes
out
to disk. This may be done as many times as
required and
experimentation is
beneficial. There are
several factors
competing for memory and they must be
balanced:
1) The
amount of workspace must be sufficient to run the
prolog programs. The total amount of memory used by PROLOG
given by the following formula:
size of PROLOG.EXE
+size of workspace selected
+size of space needed to
"exec" other programs, if used
+size of
"COMMAND.COM" if "exec" is used
----------------------------------------
= Total used by Prolog system.
"Total" must be less than the available
transient memory.
To get this, run the "chkdsk" program, supplied with DOS,
and read the last line of the
printout.
2) There must be sufficient memory to
"exec" the desired
programs.
3) Drivers
and auxiliary programs installed by
the user
such as
"sidekick" or "superkey" take
memory in a
preemptive fashion.
You may have
some difficulty in
determining how much free memory there really
is. After
PRCONF has
been run, load
PROLOG and note
that the
copyright notice displays the highest memory location
used
by PROLOG.
If the selected amount of workspace is
greater than the memory of
the
machine allows, PROLOG simply
acquires all available memory
for
its own use.
This has only one bad effect - the
"exec"
function won't function.
19
The Built In Predicate
Library
Available Operators in
PD and ED PROLOG
Column 1 gives the function symbol.
Column 2 gives the precedence. The
range of precedence is 1 to 255.
A zero in the precedence column
indicates the symbol is parsed as
a functor, and precedence is
meaningless in this case.
Column 3 gives the associativity.
A zero in the associativity column
indicates the symbol is parsed
as a functor, and associativity is
meaningless in this case.
Column 4 indicates which version the
function is available in.
Unless otherwise noted, the function is
available in all versions.
Nonstandard predicates are indicated by
"NS".
op/pred precedence associativity availability
"!" 0 0
"|" 0 0
"=" 40, XFX
"==" 40, XFX
"\\=" 40, XFX
"\\==" 40, XFX
"/" 21, YFX
"@=" 40, XFX
">=" 40, XFX
"=<" 40, XFX
">" 40, XFX
"<" 40, XFX
"-" 31, YFX
"*" 21, YFX
"+" 31, YFX
"=.." 40, XFX
"-->" 255, YFY (not
in PD PROLOG)
"?-" 255, FY
"arg" 0, 0,
"asserta" 0, 0,
"assertz" 0,
0,
"atom" 0, 0,
"atomic" 0, 0,
"batch" 0, 0
"clause" 0, 0,
"clearops" 0, 0,
"cls" 0, 0, NS
"concat" 0, 0,
"consult" 8, FX,
"crtgmode" 0, 0, NS
20
"crtset" 0, 0, NS
"curset" 0, 0, NS
"curwh" 0, 0, NS
"debugging 0, 0,
"dir" 0, 0,
"display" 0, 0,
"dotcolor" 0, 0, NS
"drawchar" 0, 0, NS
"drawdot" 0, 0, NS
"drawline" 0,
0, NS
"exec" 0, 0,
"exitsys" 0, 0, NS
"forget" 0, 0, NS
"functor" 0, 0,
"get0" 8, FX,
"integer" 0, 0,
"is" 40, XFX,
"listing" 0, 0,
"memleft" 0, 0, NS
"mod" 11, XFX,
"name" 0, 0,
"nl" 0, 0,
"nodebug" 0, 0, (not in PD PROLOG)
"nonvar" 0, 0,
"nospy" 50, FX, (not in PD PROLOG)
"not" 60 FX
"notrace" 0, 0, (not in PD PROLOG)
"op" 0, 0,
"popoff" 0, 0, NS
"popoffd" 0, 0, NS
"popon" 0, 0, NS
"popond" 0,
0, NS
"print" 0, 0,
"prtscr" 0, 0, NS
"put" 0, 0,
"ratom" 0,
0,
"read" 0, 0,
"recon" 0, 0, (Note: this is
"reconsult")
"repeat" 0, 0,
"retract" 0, 0
"rnum" 0, 0,
"see" 0, 0,
"seeing" 0, 0,
"seen" 0, 0,
"skip" 0, 0, (not in PD PROLOG)
"spy" 50, FX,
"tab" 0, 0,
"tell" 0, 0,
"telling" 0, 0,
"told" 0, 0,
"trace" 0, 0, (not in PD PROLOG)
"true" 0, 0,
"unop" 0, 0,
"var" 0, 0,
"write" 0, 0,
21
Description of the
Modifications
I/O Redirection
I/O
redirection is a feature described by Clocksin and Mellish.
The predicates "see", "seeing", "seen", "tell", "telling", and
"told" are used to select the
streams used for input and output.
The predicates
"seen" and "told" require as arguments the
name of the stream that is to be
closed. This enables the system
to
remember the indices of several streams and switch back
and
forth between them.
The predicate "batch", when inserted at the beginning of a
stream file, has the following
properties:
1)
The normal prompt,
"?-", and advisory
messages do not
appear at the screen.
2)
It is self cancelling if the input stream is reassigned
to the console.
3) It may also be cancelled by the
predicate "batch".
call( <goal> )
The predicate as defined in C & M is
obsolete. The purpose
was
to permit a goal search where the goal name was a
variable
instantiated to
some functor name. A.D.A. permits writing of
goals with such names, so the mediation of the "call"
clause is
no longer necessary.
The "call" predicate
may be trivially
implemented for
compatibility with the PROLOG
definition
call( X ) :-
X.
clause
The function
clause( X, Y ) has the
new optional form
clause(
X, Y, I
). If the third variable is
written, it is
instantiated to the current address of a clause in memory.
The
only
use of the result is with succeeding assertfa and assertfz
statements.
22
debugging
"Debugging" prints a list of the current spypoints.
After
each name a sequence of numbers may
appear, indicating the number
of
arguments that is a condition of the trace. The
word "all"
appears
if the number of arguments is not a condition of the
trace.
op( <prec>, <assoc>,
<functor> )
Defines the
user definable grammar
of a functor.
The
definition conforms to that in C &
M. We mention here a minor but
important point. If <functor> is not a valid PROLOG atom
it must
be
enclosed in single
quotes when declared
in the "op"
declaration. It
is not necessary or legal to do
this when the
functor is actually being used as an
operator. In version 1.6, a
declared or built-in operator can be used either as
an operator
or as a functor. For example,
+(2,3) = 2 +
3.
is a true statement.
Declared operators
are annotated in the directory
display
with their precedence and
associativity.
23
Output predicates
display
write
print
put
These functions
have been modified
to accept multiple
arguments in the form:
print( <arg1>,
<arg2>, <arg3>,... )
Thus, "put( a, b, c )" would
result in the display of "abc".
The names
of some PROLOG atoms that may occur
are not
accepted by
the PROLOG scanner unless
surrounded by single
quotes.
This only applies when such an atom is read in, not when
it is internally generated.
Nevertheless, this presents us with a
problem: We
would like to be capable of
writing valid PROLOG
terms to a file. In some cases, it is
necessary to add the single
quotes.
In other cases, such as human
oriented output, they are
an irritant. The modified definitions
of the following predicates
are an attempt at a solution:
display
Operator precedence
is ignored, all functors are printed
prefix and single quotes are
printed if needed or they were
supplied if and when the atom was
originally input.
write
Operator
precedence is taken into account and operators are
printed according to
precedence. Single quotes are printed
under the same conditions as for
"display."
print
Operator precedence is taken into account and
operators are
printed according to precedence. Single quotes
are never
displayed. This
is a human oriented form of output
and
should never
be used for writing of terms for the
PROLOG
scanner.
24
get0
read
The functions
"get0" and
"read" have been
extended to
support input from a stream other than
the one currently selected
by "see". To direct output to
a file or other stream, an optional
argument is used.
For example, "get0(
char, <file name> )" or
"get0( char, user )" would cause input to come from
<file name>
or the console. If the file has not already been opened, "get0"
will fail.
Atoms enclosed by single quotest,
eg. '\nthis is a new line'
can contain the escape sequences
'\n', '\r', '\t' and '\''.
If these atoms are printed by
"display" or "write" they
are
printed
just as they are. If they are printed by the
"print"
clause they are translated as follows:
'\n'
results in the printing of a carriage return and a line
feed.
'\r' results in the printing of a
carriage return only.
'\t' results in the printing of a tab
character.
'\'' allows the printing of a single
quote within a quoted atom.
The "portray" feature is
not presently implemented.
25
Description of the New
Predicates
batch, nobatch
This
predicate now makes it possible to avoid the appearance of
messages and prompts on the screen when
input has been redirected
to come from a file.
The
predicate formerly had a
different effect which no longer
exists.
When
placed at the head of a stream file which is "seen" the
system
prompt is not repetetively
displayed as the stream
is
executed. Advisory messages are not displayed
either.
The
command "batch" is self cancelling if control reverts to the
console
at any time. It may also be
cancelled by invoking the
predicate "nobatch."
A related change is that when the
Prolog system is invoked with a
command
line argument for a stream, the system prompt is not
initially displayed. So if the first command in the stream file
is
"batch.", it is
possible to use i/o redirection without
the
appearance of any system messages except aor
the signon message.
clearops
Nullify the
operator status of
every operator in the
database.
concat( (<variable> |
<functor>), <List> )
A
list of functors or operators is
concatenated into one
string,
which becomes the name of a new atom to which <variable>
or <functor> must match or be
instantiated.
dir( option )
Provide an alphabetized
listing to the console of atoms,
constants, or
open files. Without
options, simply type
"dir.<CR>". Options
are:
dir( p ) - list clause names only.
dir( c ) - list consulted files only.
Consulted files are prefixed by
"S:".
26
exec( arg1, arg2, ... argn )
Execute the program named as arg1, provided that there is
sufficient memory.
arg2 through argn must be functors which are
supplied as the command line argument, separated by
one space
from
neighbors. The PCDOS or MSDOS operating
system program
"COMMAND.COM" must be reachable by the DOS search
path, because
using "exec" invokes
"COMMAND.COM", which is the DOS shell.
You can temporarily leave PROLOG and execute the
DOS shell
with
the invocation "exec(
command )." The DOS prompt
should
appear,
and you can run programs bearing
in mind that PROLOG is
still
resident and occupying the bulk of memory. To
return to
PROLOG, type "exit" at the
DOS prompt.
This function
is restricted in the case of the type PD
to
executing a
program named "prologed",
which may be an editor
supplied by you.
This function
will not work properly unless the system
is
configured for memory.
exitsys
Exit to the operating system.
forget( <file name> )
Make a database unavailable for use and reclaim
the storage
it occupied.
ratom( <arg>, <stream> )
Read an atom from the input
stream, to which <arg> matches
or
is instantiated. <stream> is optional. If <stream> is not
given, the input stream defaults to the
standar input.
Input is terminated by a CR or LF,
which are not included in
the stream.
27
Arithmetic
Capabilities
Integer arithmetic is supported. Numbers are 32 bit signed
quantities. The following arithmetic
operators are supported:
"+",
"-", "*", "/", <, <=, >, >=, mod.
Arithmetic operators must never be used
as goals, although they
may be part of structures. It is legal
to write:
X = a + b
which
results in the instantiation of X to the struture (a + b).
But the following is not legal:
alpha( X, Y )
:- X + Y, beta( Y ).
Evaluation of an arithemtic expression is mediated by
the "is"
and inequality predicates. For instance,
the following would be
correct:
alpha( X, Y, Z ) :- Z
is X + Y.
beta( X, Y ) :- X + 2
< Y + 3.
28
Memory Metric
Predicate
The purpose of this predicate is
to give the prolog system
a
sense of how much memory remains so that
expensive search
strategies can
be controlled. It is not possible to
exactly
quantify how much memory remains. At the lowest level, there are
two
types of memory - the stack and the heap. The stack expands
down
from high memory,
while the heap tends
to expand at
unpredictable intervals upwards. If the stack and heap meet, the
prolog
system must abort the search and
return to the prompt.
Judicious use
of the memory
metric predicates reduces
the
probability of this happening.
The stack is easy to quantify because it
expands downwards
in
a predictable way with recursion. The symbol
space is a
"heap". For
those interested, the structure of the
heap is
determined by the
C compiler under which Prolog was compiled.
There
is a function internal to Prolog
known as the allocator
searches the
heap for enough contiguous memory to create a new
symbol.
The heap resembles a piece of
Swiss cheese; the holes
represent symbols and already allocated
memory while the remained
is
searched by the allocator for a
piece of contiguous memory
large enough to satisfy a request. If one cannot be found,
the
uppermost bound of the heap is expanded upwards, and that bound
is
the number which we measure for an estimate
of remaining
memory.
The sqace between the top of the heap, and
the top of the
stack,
which we call "gap",
serves as a rough guide to how much
memory
remains. The demands
of the system are not
entirely
predictable, however.
For example, the creation of a new symbol
larger
than "gap" would cause an abort. The user must
use the
numbers
supplied by these
functions as a
heuristic guide,
tempered by
experience, to minimize
the possibility of an
unexpected abort.
"Gap" is measured in 256 byte
pages.
memleft( X )
If
the argument is an integer, this
is satisfied if the size of
"gap" is greater than
"X".
If the argument is a variable, it is instantiated to the amount
of "gap" remaining.
29
IBM PC Video Display Predicates
A high level method is provided for
drawing and displaying on the
screen of IBM PC and compatible
computers.
cls
Clear
the screen and position the cursor at the upper left hand
corner.
crtgmode( X )
Matches
the argument to the mode byte of
the display which is
defined as follows:
mode meaning
0 40 x 25 BW
(default)
1 40 x 25
COLOR
2 80 x 25 BW
3 80 x 25
COLOR
4 320 x 200 COLOR
5 320 x 200 BW
6 640 x 200 BW
7 80 x 25
monochrome display card
crtset( X )
This
sets the mode of the display. The
argument must be one of
the modes given above.
curset <row>, <column>,
<page> )
Sets the cursor to the given row,
column, and page. The arguments
must be integers.
curwh
<row>, <column> )
Reports the current position of the
cursor. The argument must be
an integer or variable. The format is:
1) page zero is assumed.
2) The row is in the range 0 to
79, left to right.
3) The column is in the range 0 to
24, bottom to top.
30
dotcolor( <row>, <column>,
<color> )
The
argument <color> is matched
to the color of the specified
dot. The monitor must be in graphics
mode.
drawchar( <character>,
<attribute> )
Put a character at the current cursor
position with the specified
attribute. The
arguments <character> and
<attribute> must be
integers. Consult
the IBM technical reference manual
regarding
attributes.
drawdot( <row>, <column>,
<color> )
Put
a dot at the specified position.
The monitor must be in the
graphics mode.
The arguments must be
integer. The argument
<color> is mapped to integers by
default in the following manner:
drawline( <X1>, <Y1>,
<X2>, <Y2>, <color> )
Draw a line on the between the
coordinate pairs. The monitor must
be in the graphics mode and the
arguments are integer.
prtscr
Print
the screen as it currently appears. Be
sure that the
printer
is on line and ready before invoking this
predicate,
since otherwise, the system may lock up
or abort.
The
integer argument <color> referred to in the above predicates
is represented as follows:
COLOR PALETTE 0 PALETTE 1
0 background background
1 green cyan
2 red magenta
3 brown white
To change the palette and the
background, see the IBM Technical
Reference Bios listings for more
information.
31
The Interrupt
Menu
(type ED only)
This menu
has been modified. It was
formerly called the
ESCAPE
menu, but the
meaning of the ESCAPE
key has been
redefined. It
is no longer necessary to display the menu
to
perform
one of the menu functions. This
reduces the amount of
display which is lost by scrolling off
the screen.
Version 1.9 offers the ability to attempt a goal from
the
interrupt menu, while not disturbing
the ongoing computation.
At any time while searching,
printing, or accepting keyboard
input,
you can break to this menu. It is
generally not possible
to
do this during disk access, since control
passes to the
operating system
at this time. Two keys cause this
break to
occur:
^V:
The menu is displayed and a command is accepted at the
prompt "INTERRUPT>". After
a command, the menu
is
redisplayed until
the user selects a command
which
causes an exit.
^I: The menu is not displayed. Command is accepted at the
prompt "INTERRUPT>" until the user
selects a command
which causes an exit.
ESC: Typing this key causes a
termination of the PROLOG
search and
control returns to the user command
level
with a prompt of
"?-". Notice that previously,
the ESC
key invoked this menu.
32
As the resulting menu indicates,
the following functions are
possible:
A: Abort the search and return to
the prompt.
O
Open a trace file. The user is prompted for the
file
name. The file receives all trace output. If a file is
already opened it is closed
with all output preserved.
C
Close the trace file if one is open.
Otherwise there is
no effect.
^C: Immediately exit PROLOG without closing files. This is
not advised.
^P: Typing <Control>P toggles
the printer. If the printer is
on, all
input and output will also
be routed to the
printer.
S: If the machine in use is an IBM PC
compatible machine,
the currently displayed screen will be
printed. If the
machine is not
an IBM PC compatible, do not use
this
function.
T: If trace
is in use, most of the trace
output can be
temporarily turned off by use
of this function, which is
a toggle.
G: Satisfy a goal. The system prompt will appear. Do not be
confused into
thinking that the system has reverted
to
the prompt.
After the user has entered the goal in
the
usual
manner, satisfaction of the goal is immediately
attempted. This need not affect the running computation
in any way,
although it is certainly possible to do so.
After the
goal is attempted, control returns
to the
INTERRUPT menu.
The purpose is to facilitate detailed
analysis of a running system.
R:
Entering another ESC causes a return to the current
activity (keyboard
input or search) with no
residual
effect from the interruption.
33
Conserving memory
space
Success popping is controlled by
the predicates "popond",
"popoffd", "popon", and
"popoff". Success
popping is means of
reclaiming storage which is used on backtracking to reconstruct
how a particular goal was
satisfied. If it is obvious that there
is no alternative solution to a goal
this PROLOG system is smart
enough to reclaim that storage.
In
this system, succees popping is
an expensive operation.
Therefore, there
is a tradeoff of memory versus
time. On the
other hand, discrete use of success
popping can actually speed up
a program by recreating structures in a
more accessible form.
The definitions of the control predicates is
given in this
manual
and their use is totally optional.
The modulation of
success popping has no effect on
program logic (read solution.)
The "cut" can
save substantial time
and computational
overhead as well as storage. Although the execution of the cut
costs
time, you can design your program
to use cuts in critical
places
to avoid unnecessary
backtracking. Thus the
execution
speed of the program can actually
increase.
Anyone who
has read Clocksin and Mellish
is aware, of
course, that the "cut" has a
powerful logical impact which is not
always desirable.
popoff
See the below definition.
popon
The
inference engine does complete success popping for
goals
which appear after
"popon". Consider this
example:
goal :- a, popon, b, c, popoff, d.
If no alternative solutions exist for b, then
success popping
will
reclaim storage by removing unnecessary records describing
how
"b" was satisfied.
If the Prolog system cannot
rule out
possible additional solutions, success popping will never occur,
regardless of your use of
"popon".
Since goal "d" occurs
after "popoff", success
popping will
never occur.
34
popoffd
If
no "popon" or
"popoff" declarations occur in a
clause, the
default
action is determined by
"popoffd" and "popond". If
"popoffd" has been
invoked, the default is that
success popping
will not occur.
popond
The inverse of "popoffd".
Turns on default success popping.
printf( <stream>,
<term1>,<term2>,... )
35
Prolog
Tutorial
Introduction
Probably you
have heard of the language PROLOG within
the
last year or so. You probably wondered
the following things:
1) What does the name stand for? Names
of computer languages are
almost always acronyms.
2) What is it good for?
3) Why now?
4) Can I get a copy to play with?
Congratulations! You obviously
know the answer to the fourth
question. We now respond to the other
three.
1)
The name stands for "programming in logic."
This we
shall
elaborate on in depth later on.
2) PROLOG is good for writing question
answering systems. It is
also
good for writing
programs that perform
complicated
strategies that
compute the best or worst way to
accomplish a
task, or avoid an undesirable result.
3) PROLOG was virtually unknown in this
country until researchers
in
Japan announced that it was to be the core language of
that
country's fifth generation computer
project. This is the project
with
which Japan hopes to achieve a
domainant position in the
world information industry of the
1990's.
PROLOG is one
of the most unusual computer languages
ever
invented. It
cannot be compared to
FORTRAN, PASCAL, "C", or
BASIC.
The facilities complement, rather
than replace those of
conventional languages.
Although it has great
potential for
database work,
it has nothing in
common with the
database
languages used on microcomputers.
Perhaps the
best point to make is that while
conventional
languages are prescriptive, PROLOG is
descriptive. A statement in
a conventional language might read:
if( car_wheels = TRUE ) then
begin
(some sort of procedure)
X = X + 1;
end
36
A statment in PROLOG could just be a
statment of fact about cars
and wheels. There are many
relationships that hold. For instance,
has( car, wheels ).
has( car, quant(wheels, four) ).
round( wheels ).
Each
of these statments is an
independent fact relating cars,
wheels,
and the characteristics of wheels. Because
they are
independent, they can be put into a
PROLOG program by programmers
working separately. The man who is a
specialist on car bodies can
say
his thing, the wheel specialist
can have his say, and the
participants can work with relative
independence. And this brings
to light a major advantage of PROLOG:
PARALLEL
PROGRAMMING!!!
With
conventional programming
languages projects can still be
"chunked", or
divided between programmers. But
efficiency on a
team
project drops drastically below that of
the individual
programmer wrapped
up in his own trance. As
the number of
participants grows
the need for
communication grows
geometrically. The time spent
communicating can exceed that spent
programming!
Although PROLOG
does not eliminate
the need for
task
coordination, the problem is
considerably simplified. It
also provides the ability to answer
questions in a "ready to eat
form."
Consider your favorite BASIC interpreter. Based upon the
statements about cars and wheels
previously given, could you ask
it the following question?
has( car, X ), round( X ).
Does a
car have anything which is
round? The question
instructs the PROLOG interpreter to
consider all the objects that
it
knows are possessed by a car and find those which are round.
Perhaps
you are beginning to guess that PROLOG has the abilities
of a smart database searcher. It can not only find the facts but
selectively find them and interpret
them.
37
Consider the problem of a fault
tree, as exemplified by this
abbreviated one:
{Car won't start}
|
|
[Engine
turns over](No) --> [Battery
voltage](no)-\
(Yes) v
| {Check
battery}
|
[Smell gasoline](yes) --> {Try full
throttle cranking}
| (failure)
/--------/ |
(details omitted)
The fault tree is easily
programmed in BASIC. Later we shall
show
that PROLOG supplies a superior
replacement for the fault
tree.
Though the tree is capable of diagnosing only the problem
for
which it was designed, PROLOG dynamically constructs
the
appropriate tree from facts and rules you have
provided. PROLOG
is not limited to answering one
specific question. Given enough
information, it
will attempt to find all deductive solutions to
any problem.
38
PROLOG PRIMER
I. Rules and Facts
This is
where you should start if you know
nothing about
PROLOG. Let us consider a simple
statment in PROLOG, such as:
1)
has( car, wheels ).
This
statement is a "fact. The word "has" in this statment is
known
either as a functor or
predicate. It is a name for
the
relationship within the parenthesis. It implies that a car has
wheels.
But the order
of the words inside
the bracket is
arbitrary and established by you. You
could just as easily say:
2)
has( wheels, car ).
and if you wrote this way
consistently, all would be well.
The
words
has, wheels, and car are all PROLOG atoms. "Wheels" and
"car" are constants.
A
database of facts
can illustrate the
data retrieval
capabilities of PROLOG. For instance:
3)
has( car, wheels ).
has( car, frame ).
has( car, windshield ).
has( car, engine ).
You could then ask PROLOG the question:
4)
has( car, Part ).
The
capital "P" of Part
means that Part is a variable. PROLOG
will make Part equal to whatever
constant is required to make the
question match one of the facts in the
database. Thus PROLOG will
respond:
Part = wheels.
More?(Y/N):
If you type "y" the next
answer will appear:
Part = frame.
More?(Y/N):
If you continue, PROLOG will produce
the answers Part = windshield
and Part = engine. Finally, you will
see:
More?(Y/N):y
39
No.
indicating that PROLOG has exhausted
the database. Incidentally,
when
a variable is set equal to a
constant or other variable,
it is said to be instantiated to that
object.
Notice that
PROLOG searches the database forwards
and in
this case, from the beginning. The forward search path is built
into PROLOG and cannot be changed. An
author of a program written
in
a prescriptive language is quite
conscious of the order of
execution of his
program, while in PROLOG it is not
directly
under his control.
The other major element is the
rule which is a fact which is
conditionally true. In logic this is
called a Horn clause:
5)
has( X, wheels ) :- iscar( X ).
The
fact iscar( car ) and the above rule are equivalent to
6)
has( car, wheels).
The
symbol :- is the "rule sign." The expression on the left of
:-is the "head" and on the
right is the body. The variable X has
scope
of the rule, which means that it
has meaning only within
the rule. For instance,
we could have two rules in the database
using identically named variables.
7)
has( X, transportation ) :-
has( X, car ), has( license, X ).
8)
has( X, elephant ) :- istrainer( X ), hasjob( X ).
The
variables X in the two
expressions are completely distinct
and have nothing to do with each other.
The comma between has( X, car ) and has(
license, X ) means "and"
or logical conjuction. The rule will not be true unless both the
clauses has(X, car) and has( license, X
) are true.
On the other hand if there is a
rule
9)
has( license, X ) :- passedexam( X ).
consider what PROLOG will do in
response to the question:
10)
has( harry, transportation ).
(Notice
that harry has not been
capitalized because we do not
want
it taken as a variable. We could,
however, say 'Harry'
enclosed in single quotes.)
40
It
will scan the database and use (7),
in which X will be
instantiated to harry. The rule
generates two new questions:
11)
has( harry, car ).
12)
has( license, harry ).
Assuming that
harry has a car,
the first clause of (7) is
satisfied and the database is scanned
for a match to (12). PROLOG
picks
up rule (9) in which X is
instantiated to harry and the
question is now posed:
13)
passedexam( harry ).
If there is a fact:
passedexam( harry ).
in
the database then all is well and harry
has transportation.
If there is not, then PROLOG will
succinctly tell you:
No.
But
suppose Harry has money and can hire a chauffer as any good
programmer can.
That could be made part of the
program in the
following way.
The rule which PROLOG tried to use
was:
14)
has( X, transportation ) :-
has( X, car ), has( license, X ).
At any point following it there could
be included another rule:
15)
has( X, transportation ) :- has( X, money ).
or simply the bald fact:
16)
has( harry, transportation ).
These additional
rules or facts would
be used in two
circumstances. If at any point a rule does not yield a
solution,
PROLOG
will scan forward
from that rule
to find another
applicable one.
This process is known as "backtracking search"
and can be quite time consuming.
If
in response to the "More?" prompt you answer "y"
PROLOG will
search
for an additional distinct solution.
It will attempt to
find an alternate rule or fact for the
last rule or fact used. If
that
fails, it will back up to the antecedent rule and
try to
find
an alternate antecedent. And it
will continue to back up
until
it arrives at the question you
asked, at which point it
will say:
41
No.
"Antecedent" to a rule means that it gave rise to its'
use. For
example, (7)
is the antecedent of (9) in
the context of the
question (16).
II.
Grammar
It is a boring subject, but it
must be discussed. All PROLOG
statements are composed of valid terms,
possibly a rule sign (":-
"), commas representing conjunction
("and"), and a period at the
very end.
A term is a structure, constant,
variable, or number.
What is a structure? It is a kind
of grouping:
1) Structures consist of a
functor, and a set of objects or
structures in parenthesis.
2)
Objects are constants,
variables, numbers, or
lists,
which we have not discussed
yet.
3)
A constant or functor must be a
string of letters and
numbers, beginning with a lower case
letter, unless
you choose
to enclose it in single
quotes ( 'howdy
pardner' ),
in which case you are
freed from these
restrictions.
4) A variable
must be a string of letters and
numbers
beginning with a capital
letter.
5) A functor
may optionally have
arguments enclosed in
parenthesis , as in: hascar( X
) or hascar.
An example: "has( X, transportation )." is a
structure.
42
III. Input / Output
You now
know enough to
write simple databases
and
interrogate them
profitably. But before
we examine more
sophisticated examples,
it will be necessary to add
input and
output to the language. There are built
in functions which appear
as rules which are satisfied once. Thus
the statment:
write( 'Hello world.' ).
can be included on the right side of a
rule:
greetings( X ) :- ishuman( X ), write( 'Hello world.' ). You
can
also write "write( X )" where X is some variable. Note that
'Hello
world.' is not enclosed in double quotes. Single quotes,
which denote a constant, are required.
Double quotes would denote
a list, which is another thing
entirely.
Provided that a
match to "ishuman" can be
found, the builtin
function "write" is
executed and the message
printed to the
screen.
The builtin
read( X ) reads a "structure" that you
input
from the keyboard. More formally, we
have
read( <variable> or
<constant> )
write( <variable> or
<constant> )
If you write read( Input ), then the variable "keyboard" will
be
assigned to whatever is typed at the
keyboard, provided that the
input
is a valid PROLOG structure. The
builtin "read" will fail
if instead of Keyboard we wrote read(
baloney ), where "baloney"
is a constant, and the user at the keyboard did not type
exactly
"baloney."
When you input a structure in response
to a "read" statement, be
sure to end it with a period and an
<ENTER>.
There is a
convenient way of putting the cursor on a new
line. This is the builtin
"nl". For example:
showme :- write( 'line 1' ), nl,
write( 'line 2' ).
would result in:
line 1
line 2
There is
also a primitive form of input/output for single
characters. It will be discussed later.
43
IV. A Fault Tree Example
Consider the "won't
start" fault tree for an automobile:
{Car won't start}
|
|
[Engine
turns over](No) --> [Battery
voltage](no)-\
(Yes) v
| {Check battery}
|
[Smell gasoline](yes) --> {Try full
throttle cranking}
| (failure)
/--------/ |
| /------------------------/
|
|
| |
|
[Check for fuel line leaks](yes)-->{Replace fuel line}
| (no)
| |
| |
|
[Check for defective carburator](yes)--\
| (no) v
| {Repair
carburator}
\----\
|
|
[Is spark present](no)-->[Do points
open and close](no)-\
| (yes) v
/----/ | {Adjust points}
| /------------------------/
| |
|
[Pull distributor wire, observe spark](blue)--\
|
(orange) v
| | {Check plug wires
& cap}
| |
|
[Measure voltage on coil primary](not 12V)--\
| (12V) v
| | {Check wiring, ballast resistor}
| |
|
[Check condenser with ohmmeter](conducts)--\
|
(no conduction)
v
| | {Replace condenser}
| |
|
[Open and close points](voltage not 0 - 12)--\
|
(voltage swings 0 - 12) v
| | {Fix primary circuit}
| |
|
{Consider hidden fault, swap components]
|
|
\-------{Call a tow truck!!}
44
A PROLOG program to implement this is simple. Each statment
represents a
decision point fragment of the
tree. The PROLOG
interpreter dynamically
assembles the tree as it
attempts a
solution.
'car wont start' :- write( 'Is the
battery voltage low?' ),
affirm, nl,
write( 'Check
battery' ).
'car wont start' :- write( 'Smell
gasoline?' ),
affirm, nl,
'fuel system'.
'fuel system' :-
write( 'Try full throttle cranking' ).
'fuel system' :- write( 'Are there fuel line leaks?' ),
affirm, nl,
write( 'Replace
fuel line.' ).
'fuel system' :- write( 'Check carburator' ).
'car wont start' :- write( 'Is spark
present?' ),
not( affirm ), nl,
'no spark'.
'no spark' :- write( 'Do points open and close?' ),
not( affirm ), nl,
write( 'Adjust or
replace points.' ).
'no spark' :- write( 'Is the spark off the coil
good?' ),
affirm,
write( 'Check plug
wires and cap.' ).
'no spark' :- write( 'What is the voltage on the
primary
of the coil: ' ),
read( Volts ),
Volts < 10,
nl,
write('Check wiring
and ballast resistor.').
'no spark' :- write( 'Does the capacitor leak?' ),
affirm,
write( 'Replace the
capacitor.' ).
'no spark' :- not( 'primary circuit' ).
'primary circuit'
:- write( 'Open
the points. Voltage
across
coil?:'), nl,
read( Openvolts ),
Openvolts < 1,
write( 'Close the points. Voltage
across
coil?:'),
read( Closevolts ),
Closevolts > 10, nl,
write( 'Primary
circuit is OK.' ).
45
'no spark' :- write( 'Consider a hidden fault. Swap
cap,
rotor,points,capacitor.' ).
'Car wont start' :- write( 'Get a tow
truck!!' ).
--End
program--
The above
is a simple example of an
expert system. A
sophisticated system would tell you exactly the method
by which
it
has reached a conclusion. It would
communicate by a "shell"
program
written in PROLOG which would
accept a wider range of
input
than the "valid
structure" required by
the PROLOG
interpreter directly.
46
V. Lists
Consider a
shopping list given you by your wife.
It is a
piece of paper with items written on it
in an order that probably
symbolizes their
importance. At the top it may
say EGGS!!!,
followed by carrots, hamburger, and
finally a flea collar for the
dog, if you can find one. In PROLOG
such a list would be written:
1)
[eggs, carrots, hamburger, fleacollar]
The
order of a list is important so that eggs and carrots cannot
be reversed and PROLOG be uncaring.
Let us put the list in a structure:
shopping( [eggs, carrots,
hamburger, fleacollar] ).
Then
if you wished to isolate the head of the list you could ask
the question:
shopping( [ Mostimportant | Rest ]
).
and PROLOG would respond:
Mostimportant =
eggs,
Rest =
[carrots, hamburger,
fleacollar].
The vertical bar "|" is
crucial here. It is the string extraction
operator, which
performs a combination
of the CDR and
CAR
functions of LISP.
When it appears in the context [X|Y] it
can
separate the head of the list from the
rest, or tail.
You may have gained the impression that PROLOG is
a rather
static language capable of answering simple
questions, but it is
far
more powerful than that. The
string extraction operator is
the
key. It permits PROLOG to whittle
a complex expression down
to the bare remainder. If the rules you have given it permit it
to
whittle the remainder
down to nothing, then
success is
achieved. An example of this is the
definition of "append."
Let us suppose you have not yet done
yesterday's shopping,
let alone today's. You pull it out of
your wallet and sootch tape
it to the list your wife just gave you.
Yesterday's list was:
[tomatoes, onions, ketchup]
Combined with [eggs, carrots,
hamburger, fleacollar] we obtain
[eggs,carrots,hamburger,fleacollar,tomatoes,onions,garlic].
To
take one list and to attach it to the tail of another list is
to
"append" the first to
the second. The PROLOG definition of
append is:
47
Rule1: append( [], L, L ).
Rule2: append( [X|List1], List2, [X|List3] ) :-
append( List1, List2,
List3 ].
The
general scheme is this:
The definition consists of one rule and
one fact. The rule will
be used over and over again until what
little is left matches the
fact.
The [] stands for empty list,
which is like a bag without
anything in it. This is an example of a
recursive definition.
Suppose we ask:
append( [a,b,c], [d,e,f],
Whatgives ).
1. Rule 2 is invoked with arguments (
[a,b,c], [d,e,f], Whatgives ).
2. Rule 2 is invoked again with
arguments:
( [b,c], [d,e,f], List3 ).
3. Rule 2 is invoked again with
arguments:
( [b], [d,e,f], List3 ).
4.
The arguments are now ([],
[d,e,f], List3 ). Rule 1
now
matches. End.
How does this cause a list to be
constructed? The key is to watch
the
third argument. Supplied
by the user,
it is named
"Whatgives". The inference
engine matches it to [X|List3] in rule
2. Now lets trace this as rule two is
successivly invoked:
Whatgives
|
|
|
v
Rule2:
[X|List3] (List1 = [b,c])
| \
| \
| \
v \
Rule2:
a [X'|List3'] (List1' =
[c])
| \
| \
| \
v \
Rule2: b
[X''|List3''] (List1'' = [], ie., empty set.)
| \
| \
| \
Rule1: c L
( in Rule1 = [d,e,f] )
End.
48
L in rule 1 is [d,e,f] for the
following reason: Notice that rule
2 never alters List2. It supplies it to
whatever rule it invokes.
So L in rule 1 is the original List2,
or [a,b,c].
This example would not have worked
if the order of rules one
and
two were reversed.
The PROLOG inference
engine always
attempts to use the the first rule
encountered. You could imagine
it as always reading your program from
the top down in attempting
to
find an appropriate rule. Since
rule 2 would always satisfy,
an
unpleasant thing would
have happened if the
order were
reversed. The program would loop
forever.
A Reading List
I
hope that this tiny introduction to PROLOG whets
your
appetite. But if you want to go on,
there is no one book which I
could recommend as a complete
reference. This is a reflection on
the depth of the subject.
If
you don't consider yourself very technical,
or you're a
manager wishing to learn about Prolog,
or you simply want as much
assistance as possible, a good book is:
Introduction to Prolog
Bharath, Ramachandran
TAB books, 1985
I
don't recommend it to those seriously interested, or
as a
precursor to the more advanced texts.
The "standard text", which throws piles of source code fragments
at you is:
Programming In Prolog
W.F. Clocksin and C.S. Mellish
Springer - Verlag
Berlin,Heidelberg,New York.
1981,1984
It can be purchased directly from
Springer Verlag in New York.
The
authors apparently believe
in the Montessori method
of
instruction. The importance of this book cannot be
underrated,
however, when you consider that it established a
standard, core
Prolog
dialect simply by virtue of its
publication. The first
several
chapters are eminently readable.
When you
get bogged
down, however, it might be time to
switch.
If
you think that what you want is
detailed explanation, we
recommend:
Prolog for Programmers
Kluzniak, Feliks and Szpakowicz,
Stanislaw
APIC Studies in Data Processing
No. 24
Academic Press, 1985
49
This is a detailed text which rewards
careful study. Most likely,
you'll
decide you didn't want detailed explanation afterall. It
has
the theoretical foundation for a
university course in the
subject.
Slightly less
theoretical and very comprehensive is:
The Art of
Prolog
Sterling and Shapiro
MIT Press, 1986
One
book presents interesting "AI" applications such as
game
playing, strategy, and shell systems in considerable
detail.
You may be interested in seeing
"AI" applications such as game
playing, strategy, and shell programs in
considerable detail.
The
following book has
alot of code
that with minor
modification can
be made to
work (watch the
range of
precedences for operators, which is 0
to 255 in C & M Prolog).
Prolog Programming for
Artificial Intelligence
Ivan Bratko
Addison-Wesley, 1986
Bratko's book can take one from the
very fundamentals to rather
advanced data structures. However, as an introduction,
it may
be too fast paced, requiring
supplementation.
If
one purchased all of the
books, one would undoubtedly
find
reward in switching from one to
the other, as
the need
arose.
The
state of the art is well characterized by
the following
texts:
Logic Programming
Edited by K.L. Clark and S.-A.
Tarnlund
Academic Press, 1982
Academic papers describing
shortfalls and extensions to the
language. A potpourri.
Logic Programming and Its
Applications
Edited by Michel Van Caneghem and
David H. D. Warren
Ablex, 1986
Inspirational short-takes of state
of the art applications.
Implementations of Prolog
Edited by J.A. Campbell
Ellis Horwood, 1984
Chronicles all the mistakes and
successes of those trying to
50
produce a
nice implementation. Leaves
out the Warren
machine, which is a pity, however,
since it is the father of
all other compilation techniques.
The above three texts are difficult,
but ideal if you want to get
into research.
A
purely mathematical treatise, I
recommend this text for the
pure mathematician:
Foundations of Logic Programming
J.W. Lloyd
Springer - Verlag 1984
It
is a proof-theoretic derivation of the
automatic theorem
prover used by PROLOG.
51