PCjs Machines

Home of the original IBM PC emulator for browsers.


PC-SIG Diskette Library (Disk #417)

[PCjs Machine "ibm5170"]

Waiting for machine "ibm5170" to load....

Information about “A.D.A. PROLOG”

The PROLOG -- "Programming in Logic" -- language on this disk is
the educational/public domain version from Automata Design
Associates (A.D.A.).  PROLOG is considered one of the major fifth
generation languages and is not for the faint-hearted.
Considered the leading edge of most expert systems and artifical
intelligence program developments, PROLOG is remarkably good for
writing "question answering" systems.  It excells at writing
programs that perform complicated strategies for computing the
best or worst way to accomplish a task, or to avoid an
undesirable result.

Besides PROLOG, there are many companion programs here: PROLOGED.COM
is a simple screen editor for use within PROLOG; ATN.ARC contains Lou
Schumacher's natural language parser; EXPERT.ARC contains expert
systems for such fields as medical, rockblasting, fault diagnosis,
etc.  GAMES.ARC has some simple board games and adventure games, while
PUZZLES.ARC demonstrates techniques of translating word problems into
unambiguous logic.

PIE.ARC contains Simon Blackwell's "PIE" Truth Maintenance System
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.

System Requirements: 256K, one disk drive and monochrome display.

How to Start: As all programs and documentation are archived, consult
the READ.ME for detailed information about the files on this disk and
on how to unsqueeze all the archived files.  First one to get is

Suggested Registration:  $10.00

File Descriptions:

READ     ME   Detail about the files on this disk and how to unsqueeze
PROLOG   ARC  Squeezed Documention for the PROLOG programs
GO       BAT  Batch file for basic directions
FILES417 TXT  Description of files contents
ARCDOC   ARC  Archived directions on using the ARC.EXE utility
ARC      EXE  Utility to "Unsqueeze" the files on this disk
README        Notes on archiving programs



                              File Archive Utility
                                   Version 5.0

     (C) COPYRIGHT 1985, 1986 by System Enhancement Associates;

     This document describes the ARC file utility, version 5.0, which was
     created by System Enhancement Associates in January of 1986.

                                Table of Contents
                                Table of Contents

     Introduction  ....................................................   1
     Using ARC  .......................................................   3
     ARC commands  ....................................................   4
         Adding files  ................................................   4
         Extracting files  ............................................   6
         Deleting files  ..............................................   6
         Listing archive entries  .....................................   7
         Printing files  ..............................................   9
         Running files  ...............................................   9
         Testing an archive  ..........................................  10
         Converting an archive  .......................................  10
     ARC options  .....................................................  11
         Suppressing compression  .....................................  11
         Backup retention  ............................................  12
         Message suppression  .........................................  13
         Encryption/decryption  .......................................  14
     RAMdisk support  .................................................  15
     MARC  ............................................................  16
     XARC  ............................................................  17
     Version numbers  .................................................  18
     Program update service  ..........................................  19
     Common questions and answers  ....................................  20
     Revision history  ................................................  22
         Changes in version 3  ........................................  22
         Changes in version 4  ........................................  22
         Changes in version 4.1  ......................................  23
         Changes in version 4.3  ......................................  23
         Changes in version 4.4  ......................................  24
         Changes in version 4.5  ......................................  24
         Changes in version 5.0  ......................................  25
     Program history and credits  .....................................  27
     Site license  ....................................................  28
     Order form  ......................................................  30


     ARC is the copyrighted property of System Enhancement Associates.  You
     are granted a limited license to use ARC, and to copy it and
     distribute it, provided that the following conditions are met:

     1) No fee may be charged for such copying and distribution.

     2) ARC may ONLY be distributed in its original, unmodified state.

     Any voluntary contributions for the use of this program will be
     appreciated, and should be sent to:

                          System Enhancement Associates
                                  21 New Street
                                Wayne, NJ   07470

     You may not use this product in a commercial environment or a
     governmental organization without paying a license fee of $35.  Site
     licenses and commercial distribution licenses are available.  A
     program disk and printed documentation are available for $50.  See the
     order form in the back of this manual for more details.

     A word about user supported software:

     The user supported software concept (usually referred to as freeware)
     is an attempt to provide software at low cost.  The cost of offering a
     new product by conventional means is staggering, and hence dissuades
     many independent authors and small companies from developing and
     promoting their ideas.  User supported software is an attempt to
     develop a new marketing channel, where products can be introduced at
     low cost.

     If user supported software works, then everyone will benefit.  The
     user will benefit by receiving quality products at low cost, and by
     being able to "test drive" software thoroughly before purchasing it.
     The author benefits by being able to enter the commercial software
     arena without first needing large sources of venture capital.

     But it can only work with your support.  We're not just talking about
     ARC here, but about all user supported software.  If you find that you
     are still using a program after a couple of weeks, then pretty
     obviously it is worth something to you, and you should send in a

     ARC                                                           Page   1
     And now, back to ARC:

     ARC is used to create and maintain file archives.  An archive is a
     group of files collected together into one file in such a way that the
     individual files may be recovered intact.

     ARC is different from other archive and library utilities in that it
     automatically compresses the files being archived, so that the
     resulting archive takes up a minimum amount of space.

     When ARC is used to add a file to an archive it analyzes the file to
     determine which of four storage methods will result in the greatest
     savings.  These four methods are:

     1) No compression; the file is stored as is.

     2) Repeated-character compression; repeated sequences of the same byte
        value are collapsed into a three-byte code sequence.

     3) Huffman squeezing; the file is compressed into variable length bit
        strings, similar to the method used by the SQ programs.

     4) Dynamic Lempel-Zev compression;  the file is stored as a series of
        variable size bit codes which represent character strings, and
        which are created "on the fly".

     Note that since one of the four methods involves no compression at
     all, the resulting archive entry will never be larger than the
     original file.

     An interesting note:  It has been brought to our attention that BASIC
     programs compress to a smaller size when they are not tokenized.  If
     you are more concerned with space than speed, you may wish to convert
     your BASIC programs to ASCII form before adding them to an archive.
     Your BASIC manual should give instructions on how to do this.

     ARC                                                           Page   2
                                    USING ARC
                                    USING ARC

     ARC is invoked with a command of the following format:

         ARC <x> <arcname> [<template> . . .]


         <x> is an ARC command letter (see below), in either upper or lower

         <arcname> is the name of the archive to act on, with or without an
         extension.  If no extension is supplied, then ".ARC" is assumed.
         The archive name may include path and drive specifiers.

         <template> is one or more file name templates.  The "wildcard"
         characters "*" and "?" may be used.  A file name template may
         include a path or drive specifier, though it isn't always

     If ARC is invoked with no arguments (by typing "ARC", and pressing
     "enter"), then a brief command summary is displayed.

     Following is a brief summary of the available ARC commands:

         a   = add files to archive
         m   = move files to archive
         u   = update files in archive
         f   = freshen files in archive
         d   = delete files from archive
         x,e = extract files from archive
         r   = run files from archive
         p   = copy files from archive to standard output
         l   = list files in archive
         v   = verbose listing of files in archive
         t   = test archive integrity
         c   = convert entry to new packing method

     Following is a brief summary of the available ARC options, which may
     alter how a command works:

         b   = retain backup copy of archive
         s   = suppress compression (store only)
         w   = suppress warning messages
         n   = suppress notes and comments
         g   = encode or decode archive entry

     ARC                                                           Page   3
                                  ARC COMMANDS
                                  ARC COMMANDS

     This section describes each of the commands.  ARC will accept any one
     command at a time.  If no commands are given, then a brief command
     list is displayed.


     Files are added to an archive using the "A" (Add), "M" (Move), "U"
     (Update), or "F" (Freshen) commands.  Add always adds the file.  Move
     differs from Add in that the source file is deleted once it has been
     added to the archive.

     Update differs from Add in that the file is only added if it is not
     already in the archive, or if it is newer that the corresponding entry
     in the archive.

     Freshen is similar to Update, except that new files are not added to
     the archive; only files already in the archive are updated.

     For example, if you wish to add a file named "TEST.DAT" to an archive
     named "MY.ARC", you would use a command of the form:

         ARC a my test.dat

     If you wanted to add all files with a ".C" extension, and all files
     named "STUFF" to an archive named "JUNK.ARC", you could type:

         ARC a junk *.c stuff.*

     If you wanted to move all files in your current directory into an
     archive named "SUM.ARC", you could use a command of the form:

         ARC m sum *.*

     If you have an archive named "TEXT.ARC", and you wanted to add to it
     all of your files with an extension of ".TXT" which have been created
     or changed since they were last archived, then you would type:

         ARC u text *.txt

     If you have a bunch of files in your current directory, with backup
     copies being stored in an archive named "SAFE.ARC", then if you wanted
     to make sure that every file in the archive is the latest version of
     that file, you would type:

         ARC f safe

     ARC                                                           Page   4
     A word about Update and Freshen:  These are similar in that they look
     at the date and time of last change on the file, and only add it if
     the file has been changed since it was last archived.  They differ in
     that Update will add new files, while Freshen will not.

     In other words, Update looks for the files on disk, and adds them if
     they are new or have changed, while Freshen looks in the archive, and
     tries to update the files which are already there.

     Archive entries are always maintained in alphabetic order.  Archive
     entries may not have duplicate names.  If you add a file to an archive
     that already contains a file by that name, then the existing entry in
     the archive is replaced.  Also, the archive itself and its backup will
     not be added.

     You may also add a file which is in a directory other than your
     current directory.  For example, it is perfectly legal to type:

         ARC a junk c:\dustbin\stuff.txt

     You cannot add two files with the same name.  In other words, if you
     have a file named "C:\DUSTBIN\STUFF.TXT" and another file named
     "C:\BUCKET\STUFF.TXT", then typing:

         arc a junk c:\dustbin\*.* c:\bucket\*.*

     will not work.

     ARC does not save the path name.  In other words, if you specify a
     drive and/or path when adding a file, only the actual file name is
     stored in the archive.

     ARC will never add an archive to itself, nor will it add the temporary
     copy or a backup copy of the archive.

     ARC                                                           Page   5

     Archive entries are extracted with the "E" (Extract) and "X" (eXtract)
     commands.  For example, if you had an archive named "JUNK.ARC", and
     you wanted all files in it with an extension of ".TXT" or ".DOC" to be
     recreated on your disk, you could type:

         ARC x junk *.txt *.doc

     If you wanted to extract all of the files in an archive named
     "JUNK.ARC", you could simply type:

         ARC x junk

     Whatever method of file compression was used in storing the files is
     reversed, and uncompressed copies are created in the current

     You can also specify a path name, in which case the decompressed copy
     is placed in the specified directory.  For example, if you had an
     archive named "JUNK.ARC", and you wanted all files in it with an
     extension of ".TXT" to be placed in the directory "C:\WASTE\LAND",
     then you could type:

         ARC x junk c:\waste\land\*.txt

     If you wanted to put the file "TRASH.TXT" on your A: drive, and the
     file "LITTER.TXT" on your B: drive, you could type:

         ARC x junk a:trash.txt b:litter.txt

     If you give more than one path for a file, then only the first one is
     used.  For example, if you typed:

         ARC x junk a:trash.txt b:trash.txt

     then TRASH.TXT will be placed on your A: drive.


     Archive entries are deleted with the "D" (Delete) command.  For
     example, if you had an archive named "JUNK.ARC", and you wished to
     delete all entries in it with a filename extension of ".C", you could

         ARC d junk *.c

     ARC                                                           Page   6

     You can obtain a list of the contents of an archive by using the "L"
     (List) command or the "V" (Verbose list) command.  For example, to see
     what is in an archive named "JUNK.ARC", you could type:

         ARC l junk

     If you are only interested in files with an extension of ".DOC", then
     you could type:

         ARC l junk *.doc

     ARC prints a short listing of an archive's contents like this:

         Name          Length    Date
         ============  ========  =========
         ALPHA.TXT         6784  16 May 85
         BRAVO.TXT         2432  16 May 85
         COCO.TXT           256  16 May 85
                 ====  ========
         Total      3      9472

     "Name" is simply the name of the file.

     "Length" is the unpacked file length.  In other words, it is the
     number of bytes of disk space which the file would take up if it were

     "Date" is the date on which the file had last been modified, as of the
     time when it was added to the archive.

     "Total" is pretty obvious, I think.

     ARC prints a verbose listing of an archive's contents like this:

     Name          Length    Stowage    SF   Size now  Date       Time    CRC
     ============  ========  ========  ====  ========  =========  ======  ====
     ALPHA.TXT         6784  Squeezed   35%      4413  16 May 85  11:53a  8708
     BRAVO.TXT         2432  Squeezed   41%      1438  16 May 85  11:53a  5BD6
     COCO.TXT           256   Packed     5%       244  16 May 85  11:53a  3AFB
             ====  ========            ====  ========
     Total      3      9472             27%      6095

     "Name", "Length", and "Date" are the same as for a short listing.

     "Stowage" is the compression method used.  The following compression
     methods are currently employed:

            --          No compression.
          Packed        Runs of repeated byte values are collapsed.
         Squeezed       Huffman squeeze technique employed.
         Crunched       Lempel-Zev compression technique employed.

     ARC                                                           Page   7
     "SF" is the stowage factor.  In other words, it is the percentage of
     the file length which was saved by compression.  The total stowage
     factor is the stowage factor for the archive as a whole, not counting
     archive overhead.

     "Size now" is the number of bytes the file is occupying while in the

     "Time" is the time of last modification, and is associated with the
     date of last modification.

     "CRC" is the CRC check value which has been stored with the file.
     Another CRC value will be calculated when the file is extracted or
     tested to ensure data integrity.  There is no especially good reason
     for displaying this value.

     ARC                                                           Page   8

     Archive entries may be examined with the "P" (Print) command.  This
     works the same as the Extract command, except that the files are not
     created on disk.  Instead, the contents of the files are written to
     standard output.  For example, if you wanted to see the contents of
     every ".TXT" file in an archive named "JUNK.ARC", but didn't want them
     saved on disk, you could type:

         ARC p junk *.txt

     If you wanted them to be printed on your printer instead of on your
     screen, you could type:

         ARC p junk *.txt >prn


     Archive entries may be run without being extracted by use of the "R"
     (Run) command.  For example, if you had an archive named "JUNK.ARC"
     which contained a file named "LEMON.COM", which you wished to run, you
     could type:

         ARC r junk lemon

     You can run any file from an archive which has an extension of ".COM",
     ".EXE", ".BAT", or ".BAS".  You do not have to specify the extension,
     but all matching files are run if you do not.  In other words, if you
     had an archive named "JUNK.ARC" which contained the files "LEMON.COM",
     "LEMON.EXE", and "LEMON.BAS", and you typed:

         ARC r junk lemon

     Then all three programs will be run.  You can avoid this by specifying
     an extension in this case.

     You cannot give arguments to a program you are running from an
     archive.  Also, you will need a fair amount of memory to run a program
     from an archive.  It probably cannot be done with less than 256k.

     In practice, the file to be run is extracted, run, and then deleted.

     ARC                                                           Page   9

     The integrity of an archive may be tested by use of the "T" (Test)
     command.  This checks to make sure that all of the file headers are
     properly placed, and that all of the files are in good shape.

     This can be very useful for critical archives, where data integrity
     must be assured.  When an archive is tested, all of the entries in the
     archive are unpacked (without saving them anywhere) so that a CRC
     check value may be calculated and compared with the recorded CRC

     For example, if you just received an archive named "JUNK.ARC" over a
     phone line, and you want to make sure that you received it properly,
     you could type:

         ARC t junk

     It defeats the purpose of the T command to combine it with N or W.


     The "C" (Convert) command is used to convert an archive entry to take
     advantage of newer compression techniques.  This is occasionally
     desirable when a new version of ARC is released.  Please refer to the
     revision history section for details on when new compression methods
     were implemented.

     For example, if you had an archive named "JUNK.ARC", and you wanted to
     make sure that all files with an extension of ".DOC" were encoded
     using the very latest methods, you could type:

         ARC c junk *.doc

     Or if you wanted to convert every file in the archive, you could type:

         ARC c junk

     ARC                                                           Page  10
                                   ARC OPTIONS
                                   ARC OPTIONS

     This section describes the options which are available to modify how
     ARC works.  Any of these options can be combined with any of the
     commands, though the result may not always be something you'd want to


     The "S" (Suppress compression) option can be combined with any command
     that updates archive entries.  These include Add, Move, Update,
     Freshen, and Convert.  The effect of the S option is to prevent any
     compression techniques from being employed.  This is intended to allow
     you to add a few files at a time to an archive quickly, and then later
     convert the archive to compress everything at once.

     For example, over the course of a day you might give each of the
     following commands:

         ARC as junk *.txt
         ARC as junk *.mac
         ARC as junk *.doc

     At the end of the day, when you have finished adding things to the
     archive, you could have all of the archive entries compressed at once
     by typing:

         ARC c junk

     You could also decompress the archive by typing:

         ARC cs junk

     though I can't imagine why you'd want to.

     ARC                                                           Page  11

     When ARC changes an archive (during an Add, Move, Update, Freshen,
     Delete, or Convert) it creates a new archive with the same name, but
     with an extension of ".$$$".  For example, if you add a file to an
     archive named STUFF.ARC, then ARC will create a new archive named
     STUFF.$$$.  ARC will read from your existing archive and write out the
     new archive with any changes to the ".$$$" copy.

     Normally when ARC is finished it deletes the original and renames the
     new archive to the original name (ie. STUFF.ARC goes away, and
     STUFF.$$$ becomes the new STUFF.ARC).  Among other things, this means
     that if anything goes wrong and ARC is unable to finish, then your
     original archive will still be intact.

     In some circumstances you may wish to retain the original version of
     the archive as a backup copy.  You can do this easily by using the
     Backup option.  Add the letter "B" to your command, and ARC will
     rename your original archive to have an extension of ".BAK" instead of
     deleting it.

     In other words, if you wanted to add "WASTE.TXT" to an archive named
     "JUNK.ARC", but wanted to keep a backup copy, then you would type:

         ARC ab junk waste.txt

     Your original archive would become "JUNK.BAK", while "JUNK.ARC" would
     contain the new "WASTE.TXT" file.

     If you keep a backup of an archive which already has a backup, then
     the older backup copy is deleted.

     ARC                                                           Page  12

     ARC prints three types of messages: warnings, comments, and errors.

     Warnings are messages about suspected error conditions, such as when a
     file to be extracted already exists, or when an extracted file fails
     the CRC error check.  Warnings may be suppressed by use of the "W"
     (Warn) command.  You should use this command sparingly.  In fact, you
     should probably not use this command at all.

     Comments (or notes) are informative messages, such as naming each file
     as it is added to the archive.  Comments and notes may be suppressed
     by use of the "N" (Note) command.

     Errors are actual system problems, such as running out of disk space.
     You cannot suppress errors.

     For example, suppose you extracted all files with an extension of
     ".BAS" from an archive named "JUNK.ARC"  Then, after making some
     changes which you decide not to keep, you decide that you want to
     extract them all again, but you don't want to be asked to confirm
     every one.  In this case, you could type:

         ARC xw junk *.bas

     Or, if you are going to add a hundred files with an extension of
     ".MSG" to an archive named "TRASH.ARC", and you don't want ARC to list
     them as it adds them, you could type:

         ARC an trash *.msg

     Or, if you want to extract the entire contents of an archive named
     "JUNK.ARC", and you don't want to hear anything, then type:

         ARC xnw junk

     ARC                                                           Page  13

     Archive entries may be encrypted and decrypted by using the "G"
     (Garble) option.  The Garble option takes the remainder of the command
     string as the password to use, so it must be the last option.

     For example, if you wanted to add a file named "WASTE.TXT" to an
     archive named "JUNK.ARC", and you wanted to encrypt it using the
     password "DEBRIS", then you would type:

         ARC agdebris junk waste.txt

     Later on, when you want to extract it again, you would type:

         ARC xgdebris junk waste.txt

     The password you supply is used to encrypt (or decrypt) the archive
     entry by performing an exclusive OR between each byte of the packed
     data and each byte of the password.  The password can be any length,
     and each of its bytes is used in rotation.  The password is converted
     to uppercase before it is used, so it is not case sensitive.  Since
     the encryption is performed on the packed data, it has no effect on
     stowage factors.

     This is not a particularly sophisticated means of encryption, and it
     is theoretically possible to crack.  Still, since it is performed on
     the packed data, the result should be quite sufficient for casual use.

     You can, if you wish, use different passwords for different files in
     an archive, but we advise against it.  If you are going to encrypt an
     archive, we suggest you use the same password for every file, and give
     the password whenever you do anything at all with the archive.  It is
     possible to list the entries in an encrypted archive using the "L" and
     "V" commands without giving the password, but nothing else will work

     We advise that you use this option sparingly, if at all.  If you
     should forget or mistype your password, it is highly unlikely that you
     will ever recover your data.

     ARC                                                           Page  14
                                 RAMDISK SUPPORT
                                 RAMDISK SUPPORT

     If you have a RAMdisk, or other high-speed storage, then you can speed
     up ARC somewhat by telling it to put its temporary files on the
     RAMdisk.  You do this by setting the ARCTEMP environment string with
     the MS-DOS SET command.  For example, if drive B: is your RAMdisk,
     then you would type:

         set ARCTEMP=B:

     Refer to the MS-DOS manual for more details about the SET command.
     You need only set the ARCTEMP string once, and ARC will use it from
     then on until you change its value or reboot your system.

     If ARC does not find an environment string named ARCTEMP, then it
     looks for one named TEMP to use instead.  Several packages already use
     the TEMP string for exactly this purpose.  If you have need of an
     environment string named TEMP for something else, then you should be
     sure to define ARCTEMP.

     There are a limited number of temporary files created by ARC.  The one
     most often used is "$ARCTEMP.CRN", which is created (if possible) when
     adding a file to an archive.  The Convert command uses a file named
     "$ARCTEMP.CVT" to hold each file as it is being converted.  The Run
     command also creates a temporary file, which has the name "$ARCTEMP",
     and whose extension matches that of the file being run.

     ARC                                                           Page  15

     MARC is a separate program which is used to merge archives created by
     ARC.  MARC moves files from one archive to another without unpacking

     MARC is used as follows:

         MARC <target> <source> [<template> . . .]


         <target> is the name of the archive to add files to.

         <source> is the name of the archive to read files from.

         <template> is one or more file name templates.  The wildcard
         characters "*" and "?" may be used.  If no template is supplied,
         then all of the files in <source> are added to <target>.

     It is not necessary for the target to exist.  If it does not exist,
     then it is created.  Thus, MARC can be used as an "extractor" as well
     as a "merger".

     For example, if you wanted to create an archive named "JUNK.ARC",
     which is to contain all of the files with an extension of ".TXT" which
     are currently contained in another archive named "WASTE.ARC", then you
     could type:

         MARC junk waste *.txt

     If you wanted to create an archive named "JUNK.ARC", which is to
     contain all of the files currently in the archives "WASTE.ARC" and
     "TRASH.ARC", you could type:

         MARC junk waste
         MARC junk trash

     Though it would probably be faster to type:

         COPY waste.arc junk.arc
         MARC junk trash

     If MARC is invoked with no arguments, then it gives brief directions
     in its use.

     ARC                                                           Page  16

     XARC is a separate program which is used to extract all files from one
     or more archives.  It doesn't do anything that ARC doesn't do, and it
     isn't any faster, but it may be preferred in certain cases, as it is
     much smaller than ARC.

     XARC is used as follows:

         XARC <arcname> . . .

     Where <arcname> is the name of one or more archives.  The wildcard
     characters "*" and "?" may be used.  All files are extracted from the
     named archives.

     For example, if you wanted to extract everything from two archives
     named "WASTE.ARC" and "JUNK.ARC", you could type:

         XARC waste junk

     If you wanted to extract every file from every archive in a
     subdirectory named "TRASH", you could type:

         XARC trash\*.arc

     If XARC is invoked with no arguments, then it gives brief directions
     in its use.

     ARC                                                           Page  17
                                 VERSION NUMBERS
                                 VERSION NUMBERS

     There seems to be some confusion about our version numbering scheme.
     All of our version numbers are given as a number with two decimal

     The units indicate a major revision, such as adding a new packing

     The first decimal place (tenths) indicates a minor revision that is
     not essential, but which may be desired.

     The second decimal place (hundredths) indicates a trivial revision
     that will probably only be desired by specific individuals or by die-
     hard "latest version" fanatics.

     ARC also displays its date and time of last edit.  A change of the
     date and time without a corresponding change in version number
     indicates a truly trivial change, such as fixing a spelling error.

     To sum up: If the units change, then you should get the newer version
     as soon as you can.  If the tenths change, then you may want to get
     the newer version, but there's no hurry.  If anything else changes,
     then you probably shouldn't bother.  This is reflected by our own
     habit of referring to "version 4.5" instead of "version 4.52".

     ARC                                                           Page  18
                             PROGRAM UPDATE SERVICE
                             PROGRAM UPDATE SERVICE

     A license to ARC entitles you to use all future versions of ARC.  New
     versions are generally available through normal freeware distribution
     channels, and we prefer that you obtain them that way.  However, many
     users of ARC have written to ask us about an update service.

     A program disk containing the latest version is returned on every
     order of $50 or more.  If you wish to purchase a single-user license
     and want an update disk, please enclose a check or money order for $50
     instead of $35.

     For a fee of $50 per year you can subscribe to our program update
     service.  Subscribers get up to five program updates per year mailed
     to them as new versions come out.  This does not include trivial

     ARC                                                           Page  19
                          COMMON QUESTIONS AND ANSWERS
                          COMMON QUESTIONS AND ANSWERS

     Here are some of the more common questions we've received about ARC,
     along with their answers:

     Q: Why do you bother with squeezing when crunching is so much faster?

     A: Because crunching isn't really as fast as it looks.  Crunching is a
        one pass operation, while squeezing requires two passes.  ARC
        actually does the crunching during the analysis pass, and puts the
        crunched output in a file named "$ARCTEMP.CRN".  If crunching turns
        out to be the best method, then this temporary file is copied into
        the new archive.  In other words, when ARC says "crunching" it
        isn't really crunching, it's just copying a file.

        Also, there are a lot of files out there that squeeze much better
        than they crunch.

     Q: Why does ARC run out of room if I make an archive bigger than about

     A: Because you are working on a floppy disk.  ARC creates a copy of
        your archive, incorporating any new files as it goes.  When it is
        done, it deletes the original and renames the new one.  There are a
        number of reasons for doing it this way, one being that your
        original archive is still intact if anything happens while ARC is
        running.  ARC also needs room for the temporary file used in

        You can save some space by using the ARCTEMP environment string to
        put the temporary file on another disk, as well as using drive
        specifiers and having the archive and the files to add on separate
        disks, but you still won't be able to make an archive larger than
        about 180k.  If you need to make a larger archive, and if you have
        a fixed disk, then you can create the archive on the fixed disk and
        then copy it to the floppy.

     Q: I've seen an ARC.COM and an ARC.EXE.  Which one is the right one?

     A: ARC.EXE.  One or more people have been running ARC through a
        utility that converts an ".EXE" file to a ".COM" file.  But this
        utility is designed to save space, not speed.  On ARC it saves
        about 250 bytes, and makes no measurable difference in program
        speed.  We've decided that the savings are not worth the extra step
        in development in this case.

     ARC                                                           Page  20
     Q: Can I use ARC to distribute my public domain or freeware program?

     A: Yes, of course.

     Q: Can I use ARC to distribute my commercial software package?

     A: Yes.  Please contact us for a commercial distribution license.

     Q: I'm a commercial user.  Why should I pay for freeware that others
        get for free?

     A: Because you cannot credibly plead poverty.  Freeware, all freeware,
        is an attempt to develop a new marketing channel to the benefit of
        everyone.  You can still "test drive" freeware for a short period,
        but if you decide to use it in your business, then you should pay
        for it.

     Q: Why not allow me to select which method of compression I want ARC
        to use?

     A: It would needlessly complicate ARC, both internally and in use.
        The exact nature of the compression methods used are complex, and
        quite different.  The only sure way to tell which will be best in
        any given case is to analyze the data, as ARC does.  The method
        chosen may not always be what you expect.

     Q: How can I get the latest version of ARC?

     A: ARC updates are distributed through normal freeware channels, and
        by FidoNet.  We also ship a program update disk on every order of
        $50 or more.  In addition, we also offer an update subscription
        service.  See the previous section for more details.

     ARC                                                           Page  21
                                REVISION HISTORY
                                REVISION HISTORY


     The function used to calculate the CRC check value in previous
     versions has been found to be in error.  It has been replaced with the
     proper function.  ARC will still read archives created with earlier
     versions of ARC, but it will report a warning that the CRC value is in
     error.  All archives created prior to version 3.0 should be unpacked
     and repacked with the latest version of ARC.

     Transmitting a file with XMODEM protocol rounds the size up to the
     next multiple of 128 bytes, adding garbage to the end of the file.
     This used to confuse ARC, causing it to think that the end of the
     archive was invalidly formatted.  This has been corrected in
     version 3.01.  Older archives may still be read, but ARC may report
     them to be improperly formatted.  All files can be extracted, and no
     data is lost.  In addition, ARC will automatically correct the problem
     when it is encountered.


     ARC is adding another data compression technique in this version.  We
     have been looking for some technique that could improve on Huffman
     squeezing in at least a few cases.  So far, Lempel-Zev compression
     seems to be fulfilling our fondest hopes, often achieving compression
     rates as much as 20% better than squeezing, and sometimes even better.
     Huffman squeezing depends on some bytes being more "popular" than
     others, taking the file as a whole.  Lempel-Zev compression is instead
     looking for strings of bytes which are repeated at various points
     (such as an end of line followed by spaces for indentation).  Lempel-
     Zev compression is therefore looking for repetition at a more "macro"
     level, often achieving impressive packing rates.

     In the typical case a file is added to an archive once and then
     extracted many times, so the increased time for an update should more
     than pay for itself in increased disk space and reduced file
     transmission time.

     As usual, ARC version 4.0 is completely upward compatible.  That is,
     it can deal properly with any archive created by any earlier version
     of ARC.  It is NOT reverse compatible.  Archives created by ARC 4.0
     will generally not be usable by earlier versions of ARC.

     ARC                                                           Page  22

     Lempel-Zev coding has been improved somewhat by performing non-repeat
     compression on the data before it is coded (as was already done with
     Huffman squeezing).  This has the two fold advantage of (a) reducing
     to some extent the amount of data to be encoded, and (b) increasing
     the time it takes for the string table to fill up.  Performance gains
     are small, but noticeable.

     The primary changes are in internal organization.  ARC is now much
     "cleaner" inside.  In addition to the aesthetic benefits to the
     author, this should make life easier for the hackers out there.  There
     is also a slight, but not noticeable, improvement in overall speed
     when doing an update.

     Version 4.1 is still fully upward compatible.  But regretfully, it is
     again not downward compatible.  Version 4.1 can handle any existing
     archive, but creates archives which older versions (including 4.0)
     cannot unpack.


     Version 4.3 adds the much-demanded feature of using pathnames when
     adding files to an archive.  For obscure technical reasons, files
     being extracted still go in the current directory on the current
     drive.  Pathnames are also not supported for any of the other
     commands, because it would make no sense.

     Version 4.3 is also using a slightly different approach when adding a
     file to an archive.  The end result is twofold:

     1) Slightly more disk space is required on the drive containing the
        archive.  This should only be noticeable to those creating very
        large archives on a floppy based system.

     2) A 30% reduction in packing time has been achieved in most cases.
        This should be noticeable to everyone.

     As always, version 4.3 is still fully upwards compatible, and is
     backwards compatible as far as version 4.1.

     ARC                                                           Page  23

     The temporary file introduced in version 4.3 occasionally caused
     problems for people who had not added a FILES= statement to their
     CONFIG.SYS file.  This has now been corrected.  Also, support of the
     ARCTEMP environment string was added to allow placing of the temporary
     file on a RAMdisk.

     A bug was reported in the Run command, which has been fixed.  From the
     nature of the bug, and the extreme time required before the bug was
     reported, it is deduced that the Run command is probably the least
     used feature of ARC.

     The Update command was changed.  It is no longer a straight synonym
     for Add.  Instead, Update now only adds a file if it is newer than the
     version already in the archive, as shown by the MS-DOS date/time


     The Convert command was not making use of RAMdisk support.  Now it is.

     The Freshen command was added.  Our first choice for a name was
     Refresh, but we already had a Run command.  Assuming that you have an
     archive which already contains everything you want in it (for software
     distribution, perhaps), then Freshen would be used to update the
     archive.  It was pointed out to us that ARC already knows what is in
     the archive, so it should be able to look on disk for newer versions.
     Now it can.

     The Suppress compression option was added by popular demand.  It
     allows files to be added quickly to an archive, since the files are
     not analyzed or compressed, but merely stored straight.  The intent is
     to allow users to build an archive "in pieces", and then compress all
     of the entries at once with the Convert command.  The conversion is
     much faster if you take advantage of RAMdisk support.

     A minor bug was detected in our handling of date/time stamps which
     occasionally resulted in stamping an archive with the wrong date and
     time.  This has been corrected.

     ARC                                                           Page  24

     Several users of ARC have written us to suggest that we should put an
     order form in the documentation.  It seems that several types of
     organizations require something like that or they cannot pay no matter
     how much they'd like to.  While doing that, we also went over the
     documentation from top to bottom and "slicked it up".  It's now a bit
     more of an actual manual.  We think you'll appreciate the table of
     contents as well; we sure do!

     The Move command used to delete the files as it went.  It now waits
     until it is finished updating the archive, and deletes them all at
     once.  (You did know that Move is just an Add where the file gets
     deleted, didn't you?)  This, along with the changes made in version
     4.5, means that it is now much safer to interrupt ARC while it is

     The Print command no longer prints the name of each file.  Instead, it
     prints a formfeed after each file.

     The Run command now supports BASICA programs.  Also, the filename
     extension is no longer required on the Run command.

     The Garble option was added.  It provides a convenient means of low
     level data security for the casual user.  Use it sparingly, if at all.

     ARC no longer tests for the presence of $ARCTEMP.CRN before creating a
     new one.  If you interrupt ARC a lot, you'll find this much more
     convenient.  If you happen to have a file named $ARCTEMP.CRN which you
     want to keep, too bad.

     Improved error recovery was added when reading an archive.  ARC now
     has a good chance of recovering the data from a corrupted archive (the
     corrupted entry is still lost, of course).

     Path support has been added for all commands, though it doesn't do
     anything on most of them.  For example, there isn't much we can do
     with a path in the List command.  But many users will be glad to know
     that a path can be used when extracting a file, and specifies where
     the file is to be placed.

     Support for the TEMP environment string was added.  If ARC doesn't
     find an environment string named ARCTEMP, then it looks for one named
     TEMP to use instead.  Several packages already use the TEMP string for
     exactly this purpose.  With any luck, maybe we can get a standard

     ARC                                                           Page  25
     ARC is now using a different variation of Lempel-Zev coding, courtesy
     of Kent Williams, who found it on USENET and adapted it to the IBM PC.
     The new method differs from the old in several respects.  The most
     significant differences are:

     1) Where our previous implementation used a fixed code size of twelve
        bits, the new one starts with a code size of nine bits and
        increases it as it needs to.

     2) The earlier method tended to "choke" on large files when its string
        table filled up.  The new method has a rather ingenious scheme its
                     adaptive reset
        authors call adaptive reset.  When it notices that its string table
        has filled, and its compression ratio is starting to suffer, it
        clears the table and starts defining new strings.

     Our benchmarks show an improvement in compression on the order of 10%
     when crunching is used.  Additionally, ARC 5.0 is on the order of 23%
     faster at adding a file when crunching is used, or 13% faster when
     squeezing is used.  Extracting a file crunched with the new method is
     27% faster than it is with the old method.  Extraction of any other
     type of file (including those crunched with the older method) is no
     faster than before.  These figures are based on our own benchmark
     tests; your results may vary.

     The previous implementation of Lempel-Zev coding is no longer used to
     pack files.  The "V" (Verbose listing) command distinguishes between
     the two by referring to the older method as "crunched" (with a lower-
     case "c"), and the newer method as "Crunched" (with a capital "C").

     ARC 5.0 can still read archives created by earlier versions of ARC,
     but once again it creates archives which older versions cannot read.

     ARC                                                           Page  26
                           PROGRAM HISTORY AND CREDITS
                           PROGRAM HISTORY AND CREDITS

     In its short life thus far, ARC has astounded us with its popularity.
     We first wrote it in March of 1985 because we wanted an archive
     utility that used a distributive directory approach, since this has
     certain advantages over the more popular central directory approach.
     We added automatic squeezing in version 2 at the prompting of a
     friend.  In version 2.1 we added the code to test for the best
     compression method.  Now (in October of 1985) we find that our humble
     little program has spread across the country, and seems to have become
     a new institution.

     We are thankful for the support and appreciation we have received.  We
     hope that you find this program of use.

     If we have achieved greatness, it is because we have stood upon the
     shoulders of giants.  Nothing is created as a thing unto itself, and
     ARC is no exception.  Therefore, we would like to give credit to the
     following people, without whose efforts ARC could not exist:

     Brian W. Kernighan and P. J. Plauger, whose book "Software Tools"
     provided many of the ideas behind the distributive directory approach
     used by ARC.

     Dick Greenlaw, who wrote the public domain SQ and USQ programs, in
     which the Huffman squeezing algorithm was first developed.

     Robert J. Beilstein, who adapted SQ and USQ to Computer Innovations
     C86 (the language we use), thus providing us with important parts of
     our squeezing logic.

     Kent Williams, who graciously allowed us to use his LZWCOM and LZWUNC
     programs as a basis for our Lempel-Zev compression logic, and who
     continues to make valuable contributions.

     David Schwaderer, whose article in the April 1985 issue of PC Tech
     Journal provided us with the logic for calculating the CRC 16 bit

     Terry A. Welch, whose article "A Technique for High Performance Data
     Compression", IEEE Computer Vol 17 No 6 (June 1984) seems to have
     started all the research on Lempel-Zev coding.

     Spencer W. Thomas, Jim McKie, Steve Davies, Ken Turkowski, James A.
     Woods, and Joe Orost, who are the authors of the UNIX compress

     And many, many others whom we could not identify.

     ARC                                                           Page  27
                                  SITE LICENSE
                                  SITE LICENSE

     Corporate users may wish to obtain a site license for the use of ARC.
     Please use the order form in this manual to order a site license.
     Site licenses are granted as of when we receive your payment.  License
     fees vary depending on the number of computers on which ARC will be
     used, as follows:

          1 to  9 copies  $35 each
         10 to 24 copies  $25 each
         25 to 49 copies  $20 each
         50 to 99 copies  $15 each
         over  99 copies  $1500 one time fee

     The following page is a site license agreement, which should be signed
     and sent with your payment when ordering a commercial site license.

     ARC                                                           Page  28
     The use of ARC in a commercial environment or government organization
     is granted under the following terms:

     1.  Payment of the license fee must be made to System Enhancement
         Associates.  The fee is based on the number of computers which
         will be used to run ARC, as follows:

               1 to  9 copies  $35 each
              10 to 24 copies  $25 each
              25 to 49 copies  $20 each
              50 to 99 copies  $15 each
              over  99 copies  $1500 one time fee

     2.  You may use ARC on the number of computers included in the license
         fee.  If you have paid the fee for over 99 copies, then you may
         use ARC on any number of computers within your organization.

     3.  You may make copies of the program, in its original,  unmodified
         form,  without restriction.  You may distribute these copies of
         the program without restriction.

     4.  If these copies are distributed outside of your organization,  you
         have no obligation to control the use of those copies which are
         outside of your organization.

     5.  You may make copies of the program documentation, in both its
         printed form and machine readable form, without restriction.

     6.  You may use future versions of ARC under this license.  The latest
         version is available from System Enhancement Associates for a
         small service charge.

     7.  You may NOT modify the program or charge a fee for copying or
         distributing the program.

     8.  It is your responsibility to make the necessary copies and to
         deliver them to the computers which they will be used on.

         I agree to abide by the terms and conditions of this license.

         _____________________________         __________________________
         Signature                             Date

         Name (please print or type)



     ARC                                                           Page  29
                                   ORDER FORM
                                   ORDER FORM

     Check which items you wish to purchase:

         (_) Noncommercial license for the use of ARC.

         (_) Commercial license for the use of ARC on ___ computers (see
             price schedule and terms on preceding page).

         (_) Program disk and documentation (only on orders of $50 or

         (_) Program update subscription service (not more than five
             updates, does not include trivial changes), $50/year.

         (_) Payment of $_____ is enclosed (check or money order).

         (_) Please charge $_____ to my (_) Visa or (_) MasterCard:

             Card number: ______________________________

             Expiration date: __________________________




         ______________________   ________  ____________
         City                     State     Zip

         FidoNet address

     Send this completed form to:

                          System Enhancement Associates
                                  21 New Street
                                Wayne, NJ   07470

     For program disk orders outside the U.S., please add an additional $5,
     and enclose an international money order payable in U.S. currency.

     For commercial site license orders, please enclose a signed copy of
     the site license agreement.

     ARC                                                           Page  30


DISK NO 417   A.D.A. PROLOG  VERSION 1.91P                           v4
Prolog is popular in artificial intellegence circles.  The prolog on this
disk is the public domain version from automata design associates.  They
have other versions which they charge for.
PROLOG   ARC  Executable program after it is unsqueezed
ARCDOC   ARC  Squeezed Documention for the PDPROLOG program
READ     ME   Detail about the files on this disk and how to unsqueeze
ARC      EXE  Utility to "Unsqueeze" the files on this disk
GO       BAT  Start up instructions
1030D E Duane Avenue
Sunnyvale Ca. 94086
(408) 730-9291
(c) Copyright 1987 PC-SIG



                  A Prolog Augmented Transition Network Parser

                               Table of Contents

1.  General                                                         1

2.  ATN Form                                                        1

        Figure 1.  ATN Network                                      1
        Figure 2.  Phrase Network                                   2

3.  Approach                                                        2
        Phase I                                                     2
        Phase II                                                    2
        Phase III                                                   2

4.  Phase I                                                         2

5.  Phase II                                                        3

6.  Phase III                                                       5
        ATNBLD                                                      6
        ATNNEW                                                      8

7.  Conclusions                                                     9


1.  ATN.PRO                                                         

        Program Listing                                             1-1
        Phase I - Example I                                         1-5
        Phase I - Example II                                        1-6

2.  ATNREV.PRO                                                      

        Program Listing                                             2-1
        Phase II - Example I                                        2-4
        Phase II - Example II                                       2-4

3.  ATNBLD.PRO                                                      

        Program Listing                                             3-1
        Example ATN Definition                                      3-3

4.  ATNNEW1.PRO                                                     

        Program Listing                                             4-1
        Phase III - Example I                                       4-4
        Phase III - Example II (Subject Predicate Agreement)        4-5

                                  submitted by

                              Ludwig J. Schumacher

                               November 26, 1985

1.  General.  This report documents the development of an Augmented Transition
Network (ATN) sentence parser in the PROLOG language and is submitted in partial
fulfillment of the requirements for CS 680, Natural Language Processing, George
Mason University, Fall 1985.  It is assumed that the reader is familiar with
natural language processing and PROLOG so associated terms will be used without
explanation.  The author had no prior experience with logic programming and does
not presume to evaluate the PROLOG language, only that small subset of commands
he was able to master in attempting to apply the language to this specific
project.  The examples contained herein are executed under A.D.A. PROLOG,
ver 1.6c, (c) Automata Design Associates 1985.

2.  ATN Form.  The form of the ATN which is used in this paper is shown in
Figure 1.  This form has been chosen not as comprehensive coverage of English
sentence structure but to provide a simple form which does incorporate the major
features of ATNs.  Figure 2 is the noun and prepositional phrase network.

              -  Transition from node to node based upon specified conditions.

              -  Optional conditions, such as the determiner and adjective in
                 the noun phrase.
              -  Augmentation with sub-networks such as the noun and
                 prepositional phrases.

              -  Recursiveness such as the adjective in the noun phrase and the
                 noun phrase at node 2.

                                        np              pp
                                      *   *           *   *
                            verb     \/  *      pp   \/ * 
      np  **** >  q1 ************** > q2/ ********** > q3/
      *              *                /\
q0 *                    *    aux      * verb
      *                     *         *
      aux **** >  q4 ************* >  q5

                             Figure 1.  ATN Network
       det      *   *
      ******    \/  *     noun                         prep
qnp *       * >  qnp1 ********** > qnp2/        qpp ****** > qnp

                           Figure 2.  Phrase Network

3.  Approach.  The project was conducted in three phases.

    a.  Phase I.  Phase I was experimentation with PROLOG to develop some
working application. An ATN parser was programmed but only by forcing PROLOG
into a procedural mold.  This phase culminated in a briefing presented in class
on 24 October.

    b.  Phase II.  Phase II was the translation of the procedures developed in
Phase I into facts and rules appropriate for a logic program, which would more
fully exploit the capabilities of PROLOG.

    c.  Phase III.  Phase III was additional experimentation to make the programs
more dynamic and to exploit the power of an ATN to pass differing information
depending upon the particular transition.  These experiments included procedures
to automatically update the vocabulary, allow for user defined networks,
refinement of the database search procedures, and incorporation of subject and
predicate agreement verification.

4.  Phase I

    a.  The program developed during Phase I (Attachment 1) is not a logic
program, but a set of procedures executed with the PROLOG language.  Procedures
are defined as a set of 'q' rules which are passed the current node number and
the unparsed and parsed parts of the sentence.  Each set of procedures defined
the actions to be taken at that node. For example, q(0,_) are the procedures for
node 0, q(1,_,_) are the procedures for node 1, etc.

    b.  There are a number of limitations to this approach.

              -  The addition of a node requires a new set of procedures and
modification of the code for each node from which a transition can be made.

              -  It would be difficult to modify the code dynamically, since
procedures must be executed in sequence, and changes would have to be inserted at
specific points.

              -  Elimination of a node requires not only the elimination of the
procedure for that node, but the removal of all calls to that node from other

5.  Phase II.  Phase II was the development of a logic program to accomplish the
same functions as that developed during Phase I.  The approach was to translate
the statement, "There is a transition from node X to node Y on condition Z", to
the PROLOG equivalent "arc(X,Y,Z)".  The complete program is at Attachment 2 and
appropriate sections are reproduced below.

    a.  The first step was to redefine the facts.  The transitions are in the
form of arc(from node,to node,condition).


    b. The terminal nodes are identified by term(at node,empty list), where the
remainder of the sentence is the second variable.


    c.  Since phrase transitions are based upon a series of words rather than a
single condition, they are treated as separate networks.  The empty list as the
transition condition is used to effect a jump.


    d.  With these 'facts' established, one can now use the recursive and
backtracking nature of PROLOG to find a path from the initial point to a
terminal node.

              1)  A sentence is input as a PROLOG list enclosed in brackets and
with each word separated by a comma.  There is no punctuation at the end of the
sentence.  All words must be in lower case.

              2)  Once the sentence, S, has been input, control is passed to the
rule trans (transition).  The variables are: current node, next node, parsed
sentence, sentence remaining to be parsed, and sentence remaining to be parsed
after transition.


              3)  If the current node (Lq) is a terminal node and the remainder
of the sentence (S1) is null, then the sentence has been parsed.

trans(Lq,_,Parse,S1,_) :- term(Lq,S1),nl,
                          print('Completed ',Lq),

              4)  If the next word (S0) is the type (Type) to effect a
transition, then trans is called recursively.  (Note: Nbr is a variable designed
to provide information on the singularity or plurality of the word.  It is not
used in this example.)

trans(Lq,Nq,Parse,[S0|S1],S1) :- word(S0,Type,Nbr),
                            print('Transition ',Lq,' ',Nq,' ',S0, ' ',Type),

              5)  If the next word in the sentence does not establish the
criteria for a transition, check to determine if a phrase does. If so, the rest
of the sentence is checked for the proper phrase, either np or pp. This requires
the separate network check, ptrans, which allows parsing as the network is
transitioned, but will return unchanged if it fails.

trans(Lq,Nq,Parse,S0,S1) :-  arc(Lq,Nq,np),

trans(Lq,Nq,Parse,S0,S1) :-  arc(Lq,Nq,pp),

              6)  If no word or phrase has been found to effect a
transition, the sentence will not parse.

trans(Lq,Nq,Parse,S0,S1) :- !,nl,
                            print('The sentence failed at ',Lq),
                            nl,print('Parsed ',Parse),
                            nl,print('Left ',S0).

              7)  The phrase transition network code is almost identical to the
primary code, except that it continues to call itself until such time as it
reaches qnp2, which is the terminal node, or fails at a node other than qnp2.
In the first case it will effect a transition to the next node (Nq) and call
trans with the new data.  In the second case, ptrans will fail and conditions
remain unchanged.
ptrans(Bq,Nq,Lq,[S0|S1],Pr,Parse) :- word(S0,Type,Nbr),

ptrans(qnp2,Nq,Lq,S0,Pr,Parse) :- nl,
                                  print('Transition ',Lq,' ',Nq),

6.  Phase III

    a.  These programs demonstrate that PROLOG can be used to develop an ATN
parser but still do not exploit the power of PROLOG to operate in a dynamic
environment.  Specific capabilities which should be included are:

              1)  The ATN should be able to provide additional information
beyond whether or not the sentence parsed.

              2)  The program should assist the user in construction of the ATN

              3)  The program should verify the words are in the vocabulary set
before attempting to parse, and if not, allow them to be added.

              4)  The database search should be efficient. Especially in the
case of a large vocabulary set, the initial form of word(Name,[type]) is
unacceptable in that PROLOG must conduct a linear search of the entire set of
words to identify success or failure.

                        (a)  Dr. Berghel, University of Nebraska, suggested in
his presentation at George Mason that the vocabulary be stored as individual
letters and the search space would be reduced to words of a particular length.
For example, the word 'the' would be in the database as "word(t,h,e)".  In order
to identify if "the" is in the vocabulary set, it is partitioned into the
individual letters and only those words with arity 3 would need to be searched.

                        (b)  An alternative to the use of arity would be to
construct each word as a separate fact.  Thus "the" would be represented as
"the(word)".  It is assumed that PROLOG is more efficient searching a database
of unique facts rather than one of fewer facts differentiated by arity.  There
may, however, be some impact on memory requirements.  It must also be noted that
this would not serve the spelling correction procedure outlined by Dr. Berghel.

                        (c)  A concept which could be integrated with either of
the two approaches outlined above would be to allow the facts which are used
more often to migrate to the front of the list. Specifically, exploit PROLOG's
capability to alter the program by deleting facts when used and adding them to
the front of the list.
    b.  The two programs at Attachments 3 and 4 incorporate some of these
concepts.  Attachment 3 is a listing and example use of the program 'ATNBLD'
which can be used to build the primary transition network.  Attachment 4,
'ATNNEW', uses the network developed by ATNBLD, stores each word as a separate,
unique fact, and identifies sentences in which the subject and predicate are not
in number agreement.

              1) ATNBLD  ATNBLD requests the names of the nodes and the
conditions for transition and establishes a separate database for the network
defined by the user.  The initial node must be entered and all terminal nodes
identified.  Then the user defines paths to each terminal node.

                        (a)  BUILD.  Build is the entry point into the program.
It requests the start node (Q0), the terminal nodes, termnode, then transfers to
flow.  The predicate 'ret', defined in a standard routine, is used to retract
predicates.  It is used here to retract any predicates which would interfere
with the construction of the network.  The predicates generated within the
program are:
                        - term: defines that a node is a
                                terminal node

                        - qend: identifies nodes that have a
                                path to a terminal node

                        - arc:  identifies the transitions from
                                node to node

build :- batch,ret(qend),nl,ret(arc),nl,ret(term),asserta(term([],[])),
         consult(node),nl,print('Enter the start node: '),read(Q0),

termnode :- print('Enter the next terminal node or the word done: '),

termnode  :-  !,true.

termck(Qt)  :-  not(term(Qt,[]));
                nl,print('Terminal node ',Qt,' already entered'),nl.

                        (b)  FLOW.  Flow is the primary control structure.  It
requests the next node and the condition for transition.  It verifies that the
condition is valid, that the arc has not been previously defined, and adds it to
the database. The predicate 'qendck' verifies a path has been completed.

flow(Q0)  :- nl,print('Transition from ',Q0,' to ? '),read(Qnext),
             print(' on condition ? '),read(Con),

con(Q0,Con) :- condition(Con).

con(Q0,Con) :- nl,print(Con,' is an invalid condition. '),


arcck(Q0,Qn,Z)  :-  not(arc(Q0,Qn,Z));
                    nl,print('Arc from ',Q0,' to ',Qn,' on ',Z,'

                        (c) The predicate 'qendck' verifies that there is a path
from the end node of the arc just entered to a terminal node.  If not, control
is passed to 'flow', otherwise 'nextnode' allows a new path to be initiated or
the program terminated. Pthck is used to verify that there is a path to each of
the terminal nodes before the program is terminated. Checkstart prevents
isolated nodes from being inserted into the network.

qendck(Q0,Qnext)  :- qend(Qnext),(qend(Q0);asserta(qend(Q0))),nextnode.

qendck(Q0,Qnext)  :-  (qend(Q0);asserta(qend(Q0))),flow(Qnext).

nextnode :- nl,print('Enter next start node or the word done ? '),

nextnode :-  pthck,
             nl,print('Network completed'),
             nl,print('Enter name of new ATN file '),read(S),

nextnode :-  nextnode.

pthck   :-    term(Q,[]),not(Q=[]),not(arc(_,Q,_)),
              nl,print('No path to terminal node ',Q),

pthck    :-  term([],[]).

checkstart(Ns) :-  qend(Ns);
                   nl,print(Ns,' is an invalid node '),fail.

              2) ATNNEW  One of the features of an ATN vis-a-vis other parsers
is that the path of transversal can be used to provide information. ATNNEW is an
example which demonstrates that this can be accomplished in PROLOG. This
program, which is limited to the ATN in Figure 1, identifies the subject of the
sentence as the noun (or nouns) in the noun phrase used to transition between
nodes q0 and q1, or q4 and q5.  It also uses the 'p' or 's' associated with each
noun or verb and checks the subject and predicate for agreement in number.  The
code for the predicate ptrans, below, is annotated along the right-hand column
with numbers to correspond to the notes below.

 ptrans(Bq,Nq,Lq,[S0|S1],Pr,Parse) :-  S0(Type,Nbr),                       -1
        ( ( not(Type=noun); subj(_) ); asserta(subj(Nbr)) ),               -2

ptrans(Bq,Nq,Lq,S,Pr,Parse)   :-  arc(Bq,Zq,[]),

ptrans(qnp2,Nq,Lq,[S0|S1],Pr,Parse) :-  S0=and,(Lq=q4;Lq=q0),              -3
                       ( ( subj(_),retract(subj(_)) ); not(subj(_)) ),     -4
                                        asserta(subj(p)),                  -5

ptrans(qnp2,Nq,Lq,[S0|S1],Pr,Parse) :-  S0=and,                            -6

ptrans(qnp2,Nq,Lq,S0,Pr,Parse) :-  nl,
                                   print('Transition ',Lq,' ',Nq),

              -1.  S0 is the next word in the sentence.  Each word is defined as
a unique fact with a type and number (p or s or x).

              -2.  This line establishes the number of the subject as that of
the noun unless one has already been established.  The subject for all sentences
covered by the ATN in Figure 1 will be located in noun phrases parsed before
reaching node q2, hence nouns in noun phrases at node q2 or q3 will be ignored.

              -3.  This predicate is a special provision for the use of 'and' if
the next word is 'and', and we are attempting to transition from node q4 or q0.

              -4.  Retract the predicate subj which contains the number for the
subject.  The not(subj(_)) is actually not required, since the subj has had to
been asserted if the program gets to this point but is included for balance.

              -5.  This part of the clause establishes the number associated with
the subject as plural based on the use of and.

              -6.  This clause accounts for the case of an and in a noun phrase
not at node q0 or q4.

6.  Conclusions.  The programs developed for this project demonstrate that
PROLOG is a powerful language that offers unique capabilities and interesting
potential but little user interface. It is surprising that the power of the
language has not been exploited to enhance the utility.

    a.  Any useful application will require some form of procedure.
Construction of these procedures, such as in the Phase III example, is awkward
in the current language.

    b.  Although all variables are local to a predicate, the dynamic nature of
PROLOG enables the programmer to establish global variables through program
modification.  It is this feature which appears to offer great potential.

    c.  There are some alternative search techniques, beyond the scope of this
paper, which should be evaluated.

    d.  Given that these examples only employ the most rudimentary PROLOG
commands, the language appears to offer a rich environment, limited primarily by
the lack of user interface.

/*                 Augmented Transition Network Program



/*  Standard routines for append & membership checking       */

append([Z|L1],L2,[Z|L3]) :- append(L1,L2,L3).

printstring([H|T]) :- put(H), printstring(T).

member(X,[_|Y]) :- member(X,Y).

/*  The start module accepts a set of words, enclosed in brackets and
separated by commas.  It calls wordck to verify that each of the words is
in the vocabulary set.   */

start :- batch,nl,print('INPUT'),nl,print('-----'),nl,
         nl,print('Input sentence: '),read(S),nl,
         print('The working set is ',S),wordck(S),!,

/*  Wordck checks for the end of the set, [], then if the word is in the
vocabulary.  If not, it asks for the category, and adds it to the file
WORD.TEM which is joined with the program after it has run.*/

wordck([])   :-   !,true.

wordck([H|T]) :- word(H,Y),wordck(T).

wordck([H|T]) :-  nl,print(H,' is not a recognized word '),
                  nl,print(' enter verb,aux, .. '),read(Z),

wordnew(W,Z) :- assertz(word(W,Z)),open('word.tem',ar),
                printf('word.tem', 'word(', W, ',', Z, ').'),

/*  Trans checks the category of the current word (H) versus the category
required to make a transition (Z).  */

trans(H,Z)   :-  word(H,X), member(X,[Z]).

qfail(Nq,S,E)  :-  !, nl,nl,print('The sentence failed at ',Nq),nl,
                 print('The sentence form to this node is ',E),nl,
                 print('The rest of the sentence is ',S),qend1.

qend(Z,E)  :-  nl,nl,print('OUTPUT'),nl,print('------'),nl,nl,
               print('The sentence is:'),nl,nl,print(E),nl,nl,
               print('The sentence is completed at node ',Z),qend1.

qend1 :- open('word.tem',ar),nlf('word.tem'),
         close('word.tem'),exec('ren atn.pro atn.sav'),
         exec('copy atn.sav+word.tem atn.pro'),
         exec('erase atn.sav'),exec('erase word.tem').

/*    Print transfer from node to node */

qout(A,B,C,D,E,F) :- append(E,[C,'(',A,')'],F),
                     nl, print('Transfer from node ',B,' to node ',D,
                     ' by word ',A,' evaluated as a ',C).

/*   Main program to check the conditions for transfer from node to node.
     The first number is the number of the node, i.e. q(0.. is node 0.
     The module either checks for a word type and transfers control
     directly, or passes to np / pp the next node.                    */

/*  Node 0 - aux to 4 / np to 1 / or fail          */

q(0,[H|T])  :-  trans(H,[aux]),!,qout(H,0,[aux],4,E,F), q(4,T,F).

q(0,[H|T])  :-  np(H,T,1,[],0,[np]).

q(0,S)      :-  qfail(0,S,[]).

/*  Node 1 - verb to 2 / aux to 5 / or fail    */

q(1,[H|T],E)  :-  trans(H,[verb]),!,qout(H,1,[verb],2,E,F), q(2,T,F).

q(1,[H|T],E)  :-  trans(H,[aux]),!, qout(H,1,[aux],5,E,F), q(5,T,F).

q(1,S,E)      :-  qfail(1,S,E).

/*  Node 2 -  null to end / np to 2 / pp to 3 / or fail     */

q(2,H,E)      :- member(H,[[]]), !,

q(2,[H|T],E)  :-  np(H,T,2,E,2,[np]).

q(2,[H|T],E)  :-  pp(H,T,3,E,2,[pp]).

q(2,S,E)      :-  qfail(2,S,E).

/*  Node 3 - null to end / or fail         */

q(3,H,E)  :- trans(H,[]), !,

q(3,S,E)      :-  qfail(3,S,E).

/*  Node 4 - np to 5 / or fail           */

q(4,[H|T],E)  :-  np(H,T,5,E,4,[np]).

q(4,S,E)      :-  qfail(4,S,E).

/*  Node 5 - verb to 2 / or fail         */

q(5,[H|T],E)  :-  trans(H,[verb]),!, qout(H,5,[verb],2,E,F), q(2,T,F).

q(5,S,E)      :-  qfail(5,S,E).

/*  Noun phrase -  (det) (adj) (adj) .. noun        */

/*  The np1 clause is required to allow recursive calls for adj   */

np(H,[S|T],Nq,E,Lq,G)  :-  trans(H,[det]), !,

np(H,Z,Nq,E,Lq,G)      :-  np1([H|Z],Nq,E,Lq,G).

np1([H|T],Nq,E,Lq,G)  :-  trans(H,[adj]),

np1([H|T],Nq,E,Lq,G)  :- trans(H,[noun]),!,nl,
                         print('Transfer from node ',Lq,' to ',Nq),
                         print(' by ',G1),q(Nq,T,F).

/*  Prep phrase requires a prep followed by a np   */

pp(H,[S|T],Nq,E,Lq,G)  :-  trans(H,[prep]),

/*   Word defines the vocabulary set                  */

word(giant, [noun]).
word(is, [verb]).
word(giant, [noun]).
word(is, [verb]).
word(sleeps, [verb]).
word(mary, [noun]).
word(likes, [verb]).

/*                 Augmented Transition Network Program



/*  Standard routines for append & membership checking       */

append([Z|L1],L2,[Z|L3]) :- append(L1,L2,L3).

printstring([H|T]) :- put(H), printstring(T).

member(X,[_|Y]) :- member(X,Y).

/*  The start module accepts a set of words, enclosed in brackets and
separated by commas.  It calls wordck to verify that each of the words is
in the vocabulary set.   */

start :- batch,nl,print('INPUT'),nl,print('-----'),nl,
         nl,print('Input sentence: '),read(S),nl,
         print('The working set is ',S),wordck(S),!,

/*  Wordck checks for the end of the set, [], then if the word is in the
vocabulary.  If not, it asks for the category, and adds it to the file
WORD.TEM which is joined with the program after it has run.*/

wordck([])   :-   !,true.

wordck([H|T]) :- word(H,_,_),wordck(T).

wordck([H|T]) :-  nl,print(H,' is not a recognized word '),
                  nl,print(' enter verb,aux, .. '),read(Z),

wordnew(W,Z) :- assertz(word(W,Z,s)),open('word.tem',ar),
                printf('word.tem', 'word(', W, ',', Z, ').'),

/*  The arcs are defined in terms of from node, to node, condition.
Terminal nodes are identified with the empty list.  Words are defined by
type word name, type, and a character to be used in later examples with the
number (plural or singular).  */





/*  Trans recursively checks the conditions for transition from the last
node (Lq) to the next node (Nq).  Phrases are specifically treated as pp or
np in order to allow the type of phrase to be identified in the parsed
sentence.  */

trans(Lq,_,Parse,S1,_) :- term(Lq,S1),nl,
                          print('Completed ',Lq),

trans(Lq,Nq,Parse,[S0|S1],S1) :-  word(S0,Type,Nbr),
                                  print('Transition ',Lq,' ',Nq,' ',S0,
                                            ' ',Type),

trans(Lq,Nq,Parse,S0,S1) :-  arc(Lq,Nq,np),

trans(Lq,Nq,Parse,S0,S1) :-  arc(Lq,Nq,pp),

trans(Lq,Nq,Parse,S0,S1) :- !,nl,
                            print('The sentence failed at ',Lq),
                            nl,print('Parsed ',Parse),
                            nl,print('Left ',S0).

/*  Ptrans checks the transition of the phrase network.  The first clause
calls itself recursively until node qnp2 has been reached, which concludes
the transition.  Success results in trans being called  with the new node.
Failure returns the trans with conditions unchanged.  */

ptrans(Bq,Nq,Lq,[S0|S1],Pr,Parse) :-  word(S0,Type,Nbr),

ptrans(qnp2,Nq,Lq,S0,Pr,Parse) :-  nl,
                                   print('Transition ',Lq,' ',Nq),





/*  Build is the entry point into the program.  It requires that the
program with standard routines and the program node, which is empty, have
already been consulted.  */

/*  The program requests the start and terminal nodes, the paths and
transition conditions, then establishes a node program with a name
specified by the user.  */

/*  Ret removes any data from memory which might interfere with network
construction.  Term([],[]) is required to prevent failure when checkint
terminal conditions.  Qend identifies all nodes for which there is a path
to a terminal node.  The start node is identified initially since the
program will require this path be completed before any other can be
constructed.  Termnode accepts the terminal nodes.  Flow accepts the
transition arcs and conditions.  */

build :- batch,ret(qend),nl,ret(arc),nl,ret(term),asserta(term([],[])),
         nl,print('Enter the start node: '),read(Q0),

termnode :-  print('Enter the next terminal node or the word done: '),

termnode  :-  !,true.

/*  Flow requests transitions from node to node and adds each arc and new
node to the database.  Qendck will continue to call flow until such time as
a terminal node has been reached then allow a new path to be initiated.  */

flow(Q0)  :- nl,print('Transition from ',Q0,' to ? '),read(Qnext),
             print(' on condition ? '),read(Con),

con(Q0,Con) :- condition(Con).

con(Q0,Con) :- nl,print(Con,' is an invalid condition. '),

termck(Qt)  :-  not(term(Qt,[]));
                nl,print('Terminal node ',Qt,' already entered'),nl.

arcck(Q0,Qn,Z)  :-  not(arc(Q0,Qn,Z));
                    nl,print('Arc from ',Q0,' to ',Qn,' on ',Z,' exits.').

qendck(Q0,Qnext)  :-  qend(Qnext),(qend(Q0);asserta(qend(Q0))),nextnode.

qendck(Q0,Qnext)  :-  (qend(Q0);asserta(qend(Q0))),flow(Qnext).

/*  Nextnode allows a new path to be initiated or the program to be
terminated.  Before termination it calls pthck to insure there is a path to
each terminal node.  Checkstart prevents an isolated node from being
entered.  */

nextnode :-  nl,print('Enter next start node or the word done ? '),

nextnode :-  pthck,
             nl,print('Network completed'),
             nl,print('Enter name of new ATN file '),read(S),

nextnode :-  nextnode.

pthck   :-    term(Q,[]),not(Q=[]),not(arc(_,Q,_)),
              nl,print('No path to terminal node ',Q),

pthck    :-  term([],[]).

checkstart(Ns) :-  qend(Ns);
                   nl,print(Ns,' is an invalid node '),fail.

/*  Condition lists the acceptable conditions for a transition.   */




/*  Start is the entry into the program.  It requires that a set of
standard routines has already been consulted (append in particular).  It
allows the user to specify the network program, which can be build using
ATNBLD.  Words is a file with the vocabulary set.  The sentences is a list
of words separated by commas and enclosed in brackets.  Wordck verifies
that the words are in the vocabulary set, and if not requests required
data. Parse is the sentence as it is parsed.  Trans controls the flow from
node to node.  */

start :- nl,print('ATN network file? '),read(Fn),
         nl,print('Input sentence: '),read(S),nl,
         print('The working set is ',S),wordck(S),

wordck([])   :-   true.

wordck([H|T]) :- H(_,_),wordck(T).

wordck([H|T]) :-  nl,print(H,' is not a recognized word '),
                  nl,print(' enter verb,aux, .. '),read(Z),
                  nl,print(' enter p or s or x  '),read(Z1),

wordnew(W,Z,Z1) :- assertfz(words,W(Z,Z1)).

/*  Since the phrase transition network includes more specific procedures
than the primary network, it is included in this program rather than in the
network file consulted by start.  It could be more dynamic, but that was
considered beyond the scope of this project.  */


/*  Trans controls the flow along the network.  If a terminal node has been
reached and the entire sentence has been parsed, the agreement in number
(plural or singular) between the subject and predicate is checked.  If they
do not agree, this fact is displayed.  Update words creates a file
WORDS.$$$ which contains the new vocabulary.

If a conditions for termination has not been met, trans checks for a
transition word or a transition phrase.  If none of these conditions are
met, the sentence will not parse.

When a verb is encountered the number (singular or plural) is 'filed'.
This procedure is unique for a specific network in which only one verb can
be encountered.  */

trans(Lq,_,Parse,S1,_) :- term(Lq,S1),nl,
                          print('Completed ',Lq),
                       (  ( subj(Nbr),pred(Nbr) );
                      (nl,print('The subject and predicate do not agree.')
                          ) ),
                          exec('erase words.pro'),
                          exec('ren words.$$$ words.pro'),

endclr :-  (not(file(_));ret(file)),(not(subj(_));ret(subj)),

trans(Lq,Nq,Parse,[S0|S1],S1) :-  S0(Type,Nbr),
                                  print('Transition ',Lq,' ',Nq,' ',S0,
                                            ' ',Type),

trans(Lq,Nq,Parse,S0,S1) :-  arc(Lq,Nq,np),
                             ptrans(qnp,Nq,Lq,S0,[' '+np],Parse).

trans(Lq,Nq,Parse,S0,S1) :-  arc(Lq,Nq,pp),
                             ptrans(qpp,Nq,Lq,S0,[' '+pp],Parse).

trans(Lq,Nq,Parse,S0,S1) :- nl,
                            print('The sentence failed at ',Lq),
                            nl,print('Parsed ',Parse),
                            nl,print('Left ',S0),
/*  Ptrans checks the transition of the phrase network.  It calls itself
recursively until node qnp2 is reached.  Provisions are included to
establish the number (plural or singular) of the subject, which is designed
for a specific network in which the noun phrase in which the subject is
located will be encountered before any other noun phrase.

The upon reaching qnp2 a check is made for the word 'and'.  If encountered,
the number of the subject is changed to plural and a check for another noun
phrase is initiated.

The spacing of the parenthesis is to facilitate reading of the code.  */

ptrans(Bq,Nq,Lq,[S0|S1],Pr,Parse) :-  S0(Type,Nbr),


ptrans(Bq,Nq,Lq,S,Pr,Parse)   :-  arc(Bq,Zq,[]),

ptrans(qnp2,Nq,Lq,[S0|S1],Pr,Parse) :-  S0=and,(Lq=q4;Lq=q0),
                                       ( ( subj(_),retract(subj(_)) );
                                         not(subj(_)) ),

ptrans(qnp2,Nq,Lq,[S0|S1],Pr,Parse) :-  S0=and,

ptrans(qnp2,Nq,Lq,S0,Pr,Parse) :-  nl,
                                   print('Transition ',Lq,' ',Nq),


Contributed by Jim Adams of Bendix Aerospace.

The files "SKOLEM.OPS" and "SKOLEM.PRO" implement the translate 
program described in C&M Appendix B and discussed in Chapter 10.  
This is the program that translates predicate calculus statements 
into Prolog statements.  The program is named SKOLEM.PRO and is 
started on the command line with "pdprolog SKOLEM.OPS".  To 
translate a predicate calculus statement you type, e.g. Three 
sample predicate calculus statements are included in "SKOLEM.OPS" 
and may be commented out.

     ?- translate(all(X,s(X)<->exists(Y,e(X,Y)))).
The answer should be something like:
     s(X_1) :- e(X_1,Y_10).
     e(X_1,f1(X_1) :- s(X_1).
(The particular example comes from "x is a set iff there is a y
such that x is an element of y", the first axiom of set theory.)
The op codes are found in trans.ops and follow C&M:
             <->   if and only if
              ->   implies
              &    and
              #    or
              ~    not


                           AUTOMATA DESIGN ASSOCIATES

                     A.D.A PROLOG Documentation Version 1.91P
                  for the Educational and Public Domain Versions

                                December 26, 1986

              Copyright Robert Morein and Automata Design Associates

                                 1570 Arran Way
                               Dresher, Pa. 19025



        A.D.A.  offers  the first Prolog with a Cyclic Structure  Unifier 
        for the IBM PC.

             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.


                                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.



        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 

        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.


                     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 

             .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.


        II. 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 

             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


        .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


        .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 

                                 H             H        
                                  \          /          
                                    C ===== C           
                                  /           \         
                                 /             \        
                          H --- C                C --- H
                                 \\            //       
                                  \\          //        
                                    C ----- C           
                                  /           \         
                                 H             H        

        This  might  be represented in Prolog by a  cyclic  structure  as 
               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]. 


        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 

             7)  A  quoted  variable class,  borrowed  from  LISP, 
             permits  referencing variables as objects as well  as 
             by value.


             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 

             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 


                             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


                                 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.

                                Run-time Packages

             Software  developers wishing to integrate an A.D.A.  product 
        into  their  system  should inquire  about  specialized  run-time 
        packages available at reasonable cost.

                              Technical Information

             Technical information may be obtained at (215) - 646- 4894

             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" and 8" diskettes.

                              To Place Your Order:

             You may place your order at the following number:

                        (215)-646-4894   - day and night.


             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.



             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 


             2) Although inaccurate, it demonstrates that useful question 
        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.


             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 

                 ?-sentence( X, [every,man,loves,a,woman], [] ).

        and  having the meaning elucidated as a statment in the predicate 


                               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.

        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.


                         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 

             In  all  cases except PD PROLOG,  you can  run  your  editor 
        without leaving PROLOG by use of the "exec" predicate.


                             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.

             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.

             The structure may be up to 500 characters in length. Be sure 
             to terminate with a period.

             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.

             Simply   type   the  escape  key.   The   interpreter   will      
             respond  with  "Interrrupted.",  and return to  the  command      

             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.


             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. 

             The   predicate  "recon"  is  identical  to  the   Edinburgh 
             predicate "reconsult."

             Type "forget(<filename>).<CR>"

             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.


                               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".

             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.


                            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 

              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.


                         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


        "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,                                   


                        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.


             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 



             "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 

        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.


        Output predicates


             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:

             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.

             Operator  precedence is taken into account and operators are 
             printed according to precedence.  Single quotes are  printed 
             under the same conditions as for "display."

             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 



             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 
        '\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.


                        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 

        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.


             Nullify  the  operator  status  of  every  operator  in  the 

        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:".


        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.


             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.


                             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 

                         alpha( X, Y, Z ) :- Z is X + Y.

                         beta( X, Y ) :- X + 2 < Y + 3.


                            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 

             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.


                         IBM PC Video Display Predicates

        A high level method is provided for drawing and displaying on the 
        screen of IBM PC and compatible computers. 


        Clear  the screen and position the cursor at the upper left  hand 

        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.


        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 

        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.


        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.


                                   Trace Files

                                 (type ED only)

             You  can  now dump your trace to disk,  instead  of  (groan) 
        wasting  reams of printer paper.  This option is described in the 
        next section.

                               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 

             ^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. 


             As the resulting menu indicates, the following functions are 

             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 

             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 

             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.


                             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.


        See the below definition.


        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.



        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.


        The inverse of "popoffd". Turns on default success popping.
        printf( <stream>, <term1>,<term2>,... )


                                 Prolog Tutorial          


             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
                 (some sort of procedure)
                 X = X + 1;


        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 
             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.


             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.


                                  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 

             Part = wheels.

        If you type "y" the next answer will appear:

             Part = frame.


        If you continue, PROLOG will produce the answers Part = windshield 
        and Part = engine. Finally, you will see:



        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.)


             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:


        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:



        "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 
             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.


        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 
             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 

        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.


        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!!}


             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 

        '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?' ),
                            write( 'Check plug wires and cap.' ).

        'no spark'       :- write( 'What is the voltage on the primary
                             of the coil: ' ), 
                            read( Volts ), 
                            Volts < 10,
                            write('Check wiring and ballast resistor.').

        'no spark'       :- write( 'Does the capacitor leak?' ),
                            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 
                            read( Closevolts ), Closevolts > 10, nl,
                            write( 'Primary circuit is OK.' ). 


        '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.


        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


        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:


        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: 

        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] )              


        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.

             I  hope  that  this tiny introduction to PROLOG  whets  your 
        appetite. Here's a suggested book list:

        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 starter book is:

             Introduction to Prolog
             Bharath, Ramachandran
             TAB books, 1985

        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

        This  book  can be ordered from B.  Dalton's.  The one in  Willow 
        Grove, Pa (215)-657-8383, attempts to keep it in stock. Would you 
        please mention PD PROLOG?  We're trying to get Dalton's to  carry 
        our products in their software section.

        The  authors  apparently  believe  in the  Montessori  method  of 

        If  you  think that what you want  is  detailed  explanation,  we 

             Prolog for Programmers
             Kluzniak, Feliks and Szpakowicz, Stanislaw
             APIC Studies in Data Processing No. 24
             Academic Press, 1985

        This is a detailed text which rewards careful study. Most likely, 
        you'll decide you didn't want detailed explanation afterall.

             If  one  purchased all of the books,  one would  undoubtedly 
        find  reward  in switching from one to the  other,  as  the  need 


        We also recomend, for the mathematically inclined

             Foundations of Logic Programming
             J.W. Lloyd
             Springer - Verlag 1984

             Logic Programming
             Edited by K.L. Clark and S.-A. Tarnlund
             Academic Press, 1982


Directory of PC-SIG Library Disk #0417

 Volume in drive A has no label
 Directory of A:\

ARC      EXE     32181   3-05-86  11:33a
ARCDOC   ARC     24123   3-05-86  11:34a
FILES417 TXT       803   1-31-87   3:08p
GO       BAT       584  11-21-86   9:02a
PROLOG   ARC    274923  12-26-86  11:13a
READ     ME       3870  11-07-86   1:48a
README            3200  11-18-85  12:00p
        7 file(s)     339684 bytes
                       19456 bytes free