PCjs Machines

Home of the original IBM PC emulator for browsers.

Logo

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
PROLOG.DOC!

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

ARC.DOC





















                                       ARC

                              File Archive Utility
                                   Version 5.0

















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





     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























                                  INTRODUCTION
                                  INTRODUCTION



     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:

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









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

     Where:

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

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

     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.



     ____________
     ADDING FILES

     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
     ________________
     EXTRACTING FILES

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

     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.



     ______________
     DELETING FILES

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

         ARC d junk *.c











     ARC                                                           Page   6
     _______________________
     LISTING ARCHIVE ENTRIES

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

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

     "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
     ______________
     PRINTING FILES

     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



     _____________
     RUNNING FILES

     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
     __________________
     TESTING AN ARCHIVE

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

     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.


     _____________________
     CONVERTING AN ARCHIVE

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



     _______________________
     SUPPRESSING COMPRESSION

     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
     ________________
     BACKUP RETENTION

     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
     ___________________
     MESSAGE SUPPRESSION

     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
     _____________________
     ENCRYPTION/DECRYPTION

     Archive entries may be encrypted and decrypted by using the "G"
     (Garble) option.  The Garble option takes the remainder of the command
                                                      last
     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
                                              not
     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
     properly.


     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
                                      MARC



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


     MARC is used as follows:

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

     Where:

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



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

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

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








































     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.

                                                              much
        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
        180k?

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

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

                                                              all
     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



     ____________________
     CHANGES IN VERSION 3

     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.



     ____________________
     CHANGES IN VERSION 4

     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
     ______________________
     CHANGES IN VERSION 4.1

     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.



     ______________________
     CHANGES IN VERSION 4.3

     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
     ______________________
     CHANGES IN VERSION 4.4

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



     ______________________
     CHANGES IN VERSION 4.5

     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
     ______________________
     CHANGES IN VERSION 5.0

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

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













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

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


     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)

         _____________________________
         Title

         _____________________________
         Company




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

         (_) 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: __________________________

         _______________________________________________
         Name

         _______________________________________________


         _______________________________________________
         Address

         ______________________   ________  ____________
         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


FILES417.TXT

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

PC-SIG
1030D E Duane Avenue
Sunnyvale Ca. 94086
(408) 730-9291
(c) Copyright 1987 PC-SIG

ATNRPT.TXT

..head01rCS680
..foot59ci

                  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

Attachements:                                                       

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
..head01rCS680
..foot59c##
                  A PROLOG AUGMENTED TRANSITION NETWORK PARSER

                                  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
                          np




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

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

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

            arc(q0,q1,np).
            arc(q1,q2,verb).
            arc(q2,q2,np).
            arc(q2,q3,pp).
            arc(q0,q4,aux).
            arc(q4,q5,np).
            arc(q1,q5,aux).
            arc(q5,q2,verb).


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

            term(q2,[]).
            term(q3,[]).

    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.

            arc(qnp,qnp1,det).
            arc(qnp,qnp1,[]).
            arc(qnp1,qnp1,adj).
            arc(qnp1,qnp2,noun).
            arc(qpp,qnp,prep).


    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.

         trans(q0,Nq,Parse,S,S1)

..page
              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),
                          nl,print(Parse).


              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),
                                 arc(Lq,Nq,Type),
                                 nl,
                            print('Transition ',Lq,' ',Nq,' ',S0, ' ',Type),
                                 append(Parse,[[Type],S0],P1),
                                 !,
                                 trans(Nq,Z,P1,S1,S2).


              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),
                             ptrans(qnp,Nq,Lq,S0,[np],Parse).


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


              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),
                                     arc(Bq,Zq,Type),
                                     append(Pr,[[Type],S0],P1),
                                     !,
                                     ptrans(Zq,Nq,Lq,S1,P1,Parse).

ptrans(qnp2,Nq,Lq,S0,Pr,Parse) :- nl,
                                  print('Transition ',Lq,' ',Nq),
                                  nl,
                                  print(Pr),
                                  append(Parse,Pr,P1),
                                  !,
                                  trans(Nq,Rq,P1,S0,S1).


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

              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),
         asserta(qend(Q0)),termnode,flow(Q0).


termnode :- print('Enter the next terminal node or the word done: '),
            read(QT),
            not(QT=done),
            termck(QT),
            assertfa(node,term(QT,[])),
            asserta(qend(QT)),
            termnode.

termnode  :-  !,true.


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

..page
                        (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),arcck(Q0,Qnext,Con),
             assertfz(node,arc(Q0,Qnext,Con)),
             qendck(Q0,Qnext).

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

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

condition(verb).
condition(noun).
condition(aux).
condition(prep).
condition(aux).
condition(pp).
condition(np).


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


                        (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 ? '),
            read(Ns),
            not(Ns=done),
            ((checkstart(Ns),
            flow(Ns));nextnode).

..page
nextnode :-  pthck,
             !,retract(term([],[])),
             nl,print('Network completed'),
             listing(arc),listing(term),
             nl,print('Enter name of new ATN file '),read(S),
             update(node,S),forget(node).


nextnode :-  nextnode.


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

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
                                       arc(Bq,Zq,Type),
        ( ( not(Type=noun); subj(_) ); asserta(subj(Nbr)) ),               -2
                                       append(Pr,[[Type],S0],P1),
                                       ptrans(Zq,Nq,Lq,S1,P1,Parse).

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


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
                                        append(Pr,[and],P1),
                                        ptrans(qnp,Nq,Lq,S1,P1,Parse).


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




ptrans(qnp2,Nq,Lq,S0,Pr,Parse) :-  nl,
                                   print('Transition ',Lq,' ',Nq),
                                   nl,
                                   print(Pr),
                                   append(Parse,Pr,P1),
                                   trans(Nq,Rq,P1,S0,S1).



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



..pgno1
..foot59c1-##
/*                 Augmented Transition Network Program

                                  ATN.PRO

                                 10/22/85
*/


/*  Standard routines for append & membership checking       */


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

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

member(X,[X|_]).
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),!,
         nl,nl,print('TRANSFERS'),nl,nl,print('---------'),nl,nl,q(0,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(H,Z),wordck(T).

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


/*  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,[[]]), !,
                   qend(2,E).

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,[]), !,
             qend(3,E).

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]), !,
                           append(G,['det(',H,')'],G1),
                           np1([S|T],Nq,E,Lq,G1).


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



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


np1([H|T],Nq,E,Lq,G)  :- trans(H,[noun]),!,nl,
                         append(G,['noun(',H,')'],G1),
                         append(E,G1,F),
                         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]),
                           append(['prep(',H,')'],G,G1),
                           np(S,T,Nq,E,Lq,G1).


/*   Word defines the vocabulary set                  */


word(the,[det]).
word(boy,[noun]).
word(runs,[verb]).
word(happy,[adj]).
word(john,[noun]).
word(can,[aux]).
word(run,[verb]).
word(a,[det]).
word(big,[adj]).
word(small,[adj]).
word(girl,[noun]).
word(dog,[noun]).
word(on,[prep]).
word(pretty,[adj]).
word(fast,[adj]).
word(barks,[verb]).
word(to,[prep]).
word([],[]).
word(giant, [noun]).
word(is, [verb]).
word(giant, [noun]).
word(is, [verb]).
word(sleeps, [verb]).
word(mary, [noun]).
word(likes, [verb]).

..pgno1
..foot59c2-##
/*                 Augmented Transition Network Program

                                ATNREV.PRO

                                 11/24/85
*/


/*  Standard routines for append & membership checking       */


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

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

member(X,[X|_]).
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),!,
         nl,nl,print('TRANSFERS'),nl,nl,print('---------'),nl,nl,
         Parse=[],
         trans(q0,Nq,Parse,S,S1).


/*  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(H,Z),wordck(T).

wordnew(W,Z) :- assertz(word(W,Z,s)),open('word.tem',ar),
                nlf('word.tem'),
                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).  */


arc(q0,q1,np).
arc(q1,q2,verb).
arc(q2,q2,np).
arc(q2,q3,pp).
arc(q0,q4,aux).
arc(q4,q5,np).
arc(q1,q5,aux).
arc(q5,q2,verb).

term(q2,[]).
term(q3,[]).


word(boy,noun,s).
word(boys,noun,pl).
word(run,verb,pl).
word(runs,verb,s).
word(the,det,s).

arc(qnp,qnp1,det).
arc(qnp,qnp1,_).
arc(qnp1,qnp1,adj).
arc(qnp1,qnp2,noun).
arc(qpp,qnp,prep).


/*  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),
                          nl,print(Parse).


trans(Lq,Nq,Parse,[S0|S1],S1) :-  word(S0,Type,Nbr),
                                  arc(Lq,Nq,Type),
                                  nl,
                                  print('Transition ',Lq,' ',Nq,' ',S0,
                                            ' ',Type),
                                  append(Parse,[[Type],S0],P1),
                                  !,
                                  trans(Nq,Z,P1,S1,S2).


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.  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),
                                arc(Bq,Zq,Type),
                                append(Pr,[[Type],S0],P1),
                                !,
                                ptrans(Zq,Nq,Lq,S1,P1,Parse).

ptrans(qnp2,Nq,Lq,S0,Pr,Parse) :-  nl,
                                   print('Transition ',Lq,' ',Nq),
                                   nl,
                                   print(Pr),
                                   append(Parse,Pr,P1),
                                   !,
                                   trans(Nq,Rq,P1,S0,S1).

..page
..pgno1
..foot59c3-##
/*        PROGRAM TO BUILD PRIMARY AUGMENTED TRANSITION NETWORK

                                ATNBLD.PRO

                                 11/24/85

*/


/*  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),
         asserta(qend(Q0)),termnode,flow(Q0).


termnode :-  print('Enter the next terminal node or the word done: '),
             read(QT),
             not(QT=done),
             termck(QT),
             assertfa(node,term(QT,[])),
             asserta(qend(QT)),
             termnode.

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),arcck(Q0,Qnext,Con),
             assertfz(node,arc(Q0,Qnext,Con)),
             qendck(Q0,Qnext).

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

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

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 ? '),
             read(Ns),
             not(Ns=done),
             ((checkstart(Ns),
             flow(Ns));nextnode).

nextnode :-  pthck,
             !,retract(term([],[])),
             nl,print('Network completed'),
             listing(arc),listing(term),
             nl,print('Enter name of new ATN file '),read(S),
             update(node,S).

nextnode :-  nextnode.

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

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

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

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

condition(verb).
condition(noun).
condition(aux).
condition(prep).
condition(aux).
condition(pp).
condition(np).
..pgno1
..foot59c4-##
/*              FINAL AUGMENTED TRANSITION NETWORK PROGRAM

                                ATNNEW1.PRO

                                 11/24/85
*/


/*  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),
         consult(Fn),nl,
         asserta(file(Fn)),
         consult(words),nl,
         batch,nl,print('INPUT'),nl,print('-----'),nl,
         nl,print('Input sentence: '),read(S),nl,
         print('The working set is ',S),wordck(S),
         nl,nl,print('TRANSFERS'),nl,nl,print('---------'),nl,nl,
         Parse=[],
         trans(q0,Nq,Parse,S,S1).


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(H,Z,Z1),wordck(T).

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


arc(qnp,qnp1,det).
arc(qnp,qnp1,[]).
arc(qnp1,qnp1,adj).
arc(qnp1,qnp2,noun).
arc(qpp,qnp,prep).


/*  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),
                          nl,print(Parse),
                       (  ( subj(Nbr),pred(Nbr) );
                      (nl,print('The subject and predicate do not agree.')
                          ) ),
                          update(words),
                          exec('erase words.pro'),
                          exec('ren words.$$$ words.pro'),
                          forget(words),
                          file(Fn),
                          forget(Fn),
                          endclr.

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


trans(Lq,Nq,Parse,[S0|S1],S1) :-  S0(Type,Nbr),
                                  arc(Lq,Nq,Type),
                                 ((Type=verb,asserta(pred(Nbr)));
                                     not(type=verb)),
                                  nl,
                                  print('Transition ',Lq,' ',Nq,' ',S0,
                                            ' ',Type),
                                  append(Parse,[[Type],S0],P1),
                                  trans(Nq,Z,P1,S1,S2).


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),
                            endclr.
/*  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),
                                arc(Bq,Zq,Type),
                          (
                             (
                                 not(Type=noun);

                                 subj(_)
                                          );
                                 asserta(subj(Nbr))
                                                  ),
                                append(Pr,[[Type],S0],P1),
                                ptrans(Zq,Nq,Lq,S1,P1,Parse).

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


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


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




ptrans(qnp2,Nq,Lq,S0,Pr,Parse) :-  nl,
                                   print('Transition ',Lq,' ',Nq),
                                   nl,
                                   print(Pr),
                                   append(Parse,Pr,P1),
                                   trans(Nq,Rq,P1,S0,S1).

SKOLEM.DOC

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



PROLOG.DOC

















                           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

                                 (215)-646-4894



























                                      News

        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.

































                                        1








                                Copyright Notice

             The  public domain PD PROLOG system has been contributed  to
        the  public domain for unrestricted use with one  exception:  the
        object  code  may not be  disassembled  or  modified.  Electronic
        bulletin  boards  and SIG groups are urged to aid in giving  this
        software the widest possible distribution.

             This documentation may be reproduced freely,  but it may not
        be  included in any other documentation without the permission of
        the author.














































                                        2








                                  Introduction

        We  hope  that you'll get some fun out of this  PROLOG.  It  will
        afford  you exposure to THE fifth generation language at the cost
        only  of  some  intellectual  effort.  The  motive  is  perfectly
        explicable:  We  want you to think of Automata Design  Associates
        for  fifth  generation  software.  It also gives us a  nice  warm
        feeling.

        The  minimum  memory  requirement is 200 k of  transient  program
        area,  plus  whatever  space is needed to execute  programs  from
        within PROLOG.  DOS or MSDOS 2.0 are required.  The program  does
        not  require  IBM PC compatibility to run,  although  the  screen
        access routines do require compatibility.











































                                        3








                     Products by Automata Design Associates

             Automata  Design  Associates  specializes  in  software  for
        artificial  intelligence  and  robotic  applications.   A  PROLOG
        language  system is available in various configurations.  A  LISP
        interpreter will be introduced in March of 1985.



        1. LISP systems

             PD LISP

        PD  LISP is a public domain Common LISP subset.  It comes with  a
        150 page instruction manual on disk, and is available from us for
        $10.00.

             .UNX LISP

        UNX LISP, written by Dave Morein, is a Common LISP subset. It has
        nifty  things like SAVE/RESTORE,  which let you stop a job in the
        middle,  save  it,  and start it up again,  and  tree  structured
        lexical scoping. It is available from us for $69.95.


































                                        4








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

             An  "interrupt"   menu is added,  permitting the control  of
        tracing, toggling the printer, and screen printing.

             Definite clause grammar support is now included.

             The cost of Educational PROLOG is $29.95.



        .FS PROLOG

             A  small  increment  in price adds full random  access  file
        capability. Character and structure I/O are allowed.

             The  "asserta and "assertz" predicates are expanded and work
        with a clause indexing ability.  One can assert clauses  anywhere
        in the database under precise pattern matching control.

             A tree structured lexical scoping system and floating  point
        arithmetic are other enhancements.

             The cost of FSM PROLOG is $49.95




                                        5









        .VMI PROLOG -- Virtual Memory (Replaces type VMS)


             At reasonable cost the addition of virtual memory gives  an
        expansion of capabilities of an order of magnitude.

             The  database on disk is treated transparently.  No  special
        provisions  need  be  made  by the  user.  Virtual  and  resident
        databases  may be mixed.  A unique updating algorithim  preserves
        the format of the database as typed by the user while making only
        those changes necessary to make it equivalent to the database  in
        central memory.

             The cost of VMI PROLOG is $99.95










































                                        6








        .VML PROLOG Large model Virtual Memory System

             A.D.A.  PROLOG is a remarkable fifth generation developement
        tool  for  the  implementation  of  intelligent  strategies   and
        optimized  control.  It  is both the kernel for  applications  of
        virtually  unlimited scope and a sophisticated developement  tool
        that multiplies the productivity of the programmer many times.

             Conventional  Prolog  is based on the first order  predicate
        calculus.   VML   emulates  the  second  order   calculus,   with
        unconstrained   manipulation   of   cyclic,    self   referential
        structures.  The  cyclic unifier is selectable by a mode  switch,
        with no loss of compatibility.

             Perhaps  only  one  other Prolog system,  written  by  Alain
        Colmareur,  permits manipulation of cyclic structures.  Permitted
        by the second order predicate calculus, but not the first, cyclic
        structures are self referential, or recursively defined.

             A conventional Prolog system typically crashes when a cyclic
        structure  is  found,  because  such a structure  appears  to  be
        infinite. But with our Cyclic Unifier, available in types VML and
        VMA Prolog, cyclic structures can be handled with impunity.

             Many  structures in nature are cyclic,  and we suggest  that
        many applications will appear to the user.  For example, consider
        the  benzene ring,  which chemists refer to as a cyclic  aromatic
        hydrocarbon:


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


        This  might  be represented in Prolog by a  cyclic  structure  as
        follows:


               X = [ [[c,h]],[c,h],[[c,h]],[c,h],[[c,h]],[c,h]|X]

        It  would  appear that groups and topological properties  can  be
        succinctly described as cyclic structures.  A simple group can be
        expressed as follows:

                                 X = [a,b,c|X].



                                        7








        Then  the cyclic nature of the group can be observed  with
        the goal "member( M, X )", which gives:

                      a,b,c,a,b,c,a,b,c,....(ad infinitum)

             With  a  cost/performance ratio exceeding that of any  other
        product  and  a  compatibility  insured  by  compliance  to   the
        Edinburgh syntax, performance is enhanced by numerous extensions,
        many of them invisible to the user.

             A quick overview of some of the features discloses:

             1)  This  system now incorporates a cyclic  structure
             unifier.  The  only  other Prolog system  capable  of
             unifying  cyclic structures is PrologII,  written  by
             the inventor of Prolog, Alain Colmerauer.

             2)  Invisible  compilation  to  a  semantic  network
             preserves the flexibility of the interpreted mode and
             the speed of a compiler.

             The  programmer can compile and recompile any portion
             of a module at any time.  The edit/compile/test cycle
             is short and free of strain. An interface is provided
             to an editor of choice.


             3) Floating point arithmetic with a full  complement
             of  input  and  output  methods,  transcendental  and
             conversion functions.


             4)  Virtual  memory.  Module  size  and  number  are
             unrestricted,   with  a  total  capacity  of  several
             hundred megabytes.  Resident and virtual modules  may
             be co-resident. Compilation is incremental. The cache
             algorithim  is  sophisticated.  Changes made  in  the
             database can be updated to disk by a single command.


             5) A powerful exec function and acceptance of  stream
             input make  integration into  applications practical.


             6)  Global polymorphic variables  retain  information
             that  would  otherwise  require  the  "assertion"  of
             facts.


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





                                        8








             8) Multidimensional arrays,  dynamically created  and
             destroyed,  efficiently  store numeric and nonnumeric
             structures. Arrays are ideal for representing spatial
             and ordinal relationships.

             9)  Debugging facilities let you see your program run
             without any additional generation steps.


             10)  Totally   invisible  and   incremental   garbage
             collection.   There   is  NEVER  any  wait  for  this
             function.


             11)  A  tree  structured,   dynamically  configurable
             lexical scoping system. The work of many  programmers
             can  be coupled together in the form of libraries and
             nested domains.

             Each lexically scoped domain is a hidden space  which
             communicates  with the parent domain via exports  and
             imports. Domains can be linked together under program
             control to achieve any desired configuration.


             12) The Grammar Rule Notation is an integral feature.


             13) Keyword redefinition makes porting code easy.


        The  cost  of this system is $200 for the MSDOS version.



        .VMA PROLOG Large model Virtual Memory System

        This  system  has  additional forms of  virtual  memory.  It  was
        intended  for  deep  reasoning  problems.  Contact  us  for  more
        information.

















                                        9








                             Prolog Runtime Systems


             The A.D.A.  Runtime Systems permit distribution of  debugged
        code in source form without royalties.  A Runtime System provides
        all  of  the facilities of the corresponding  Development  System
        except for:

             1) Tracing.

             2)  The  console  command loop.

        A  Runtime  System is invoked from the DOS command line  with  an
        argument specifying a stream file that replaces the console.  The
        stream file is a UNIX* innovation that allows applications to  be
        connected by "pipes", in a convenient, high level manner.

             All  the  other  development  facilities  remain  available,
        including  multiple modules and virtual memory.  Since update  to
        disk  is  included,  the ability of the system to  learn  is  not
        impaired in any way.  Compare this to our competitors, whose hard
        compiled  code results in fixed goals and inability to change the
        distribution on a dynamic basis.

             Four versions are available.  Each is priced the same as the
        corresponding development system,  and can be distributed without
        royalty by the license holder with his applications:


                  FS  Runtime - $50.00

                  VMI Runtime - $100.00

                  VML Runtime - $200.00

                  VMA Runtime - $250.00

             The above systems are in stock for immediate delivery.


             * trademark AT&T
















                                       10








                                 Upgrade Policy

             Half the cost of any A.D.A. PROLOG system may be credited to
        the purchase of a higher level version.      The full cost of VMS
        prolog  may  be  applied to the purchase of VMI  or  VML  PROLOG.
        Updates to a particular level product vary from $15.00 to $35.00.


                                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.



                                     Returns

             The  software may be returned within 30 days of purchase for
        a full refund.  This applies whether or not the software has been
        used.  We do ask that manuals, disks and packaging be returned in
        excellent condition.













                                       11








                                  Installation

             You will need an IBM PC compatible machine with a minimum of
        256  kbytes  of  memory.  ED PROLOG benefits from  all  available
        memory up to the 1 megabyte INTEL limit.

             To  determine the amount of TPA your machine  has,  run  the
        "chkdsk" program which is supplied with DOS. The last line reads:

                                XXXXXX bytes free

        where XXXXXX is a six digit number.

        If  this  number  is greater than 200000,  ED  PROLOG  will  have
        reduced workspace.  If it's over 245000,  the amount of memory is
        optimal. If this is not the case, there are two possibilities:

        1) The machine doesn't have enough memory.

        2)  Something  else is removing memory from TPA,  such as  a  co-
        resident  program,  a  ramdisk,  a large dos driver,  or a  large
        number of file or disk buffers.

        If  you're  short of memory,  make sure that no  other  programs,
        ramdisks,  or drivers besides DOS are running in the machine. You
        may find it helps to eliminate (by renaming) the config.sys  file
        when you intend to run ED PROLOG.


                      How to run the Demonstration Programs
                        without Knowing What You're Doing

             We strongly advise that you purchase the book Programming in
        PROLOG by Clocksin and Mellish,  publisher Springer Verlag, 1981.
        For  the  impatient we give some advice.  Type the  demonstration
        program you wish to run.  There must be at least one entry  point
        within  the  program.

        Note:  Please  understand that these are demonstrations programs.
        Regarding  user  interface,  they are poorly  written.  You  will
        probably have to read Clocksin and Mellish to appreciate that the
        following examples of input are not equivalent: "yes." , "yes" .

             The program fragment "console" shows how you may improve the
        console input routines of any of these programs.


        The Hematology Diagnosis Program - "hemat"

             Although  the  logical structure is not as sophisticated  as
        that of "animals", it is interesting for several reasons:

             1)  The  program  evaluates numerical data to  arrive  at  a
        diagnosis.



                                       12








             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.


        Grrules

             This  is  an  example  of the use  of  the  definite  clause
        grammer  notation.  PD  PROLOG  does not  have  this  translation
        facility,  but ED PROLOG and  all of our other versions do. It is
        possible  to  perform  the  translations  by  hand  if  you  have
        thoroughly  read  C  & M.  Then you would have  the  pleasure  of
        asking:

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

        and  having the meaning elucidated as a statment in the predicate
        calculus.




















                                       13








                               Special Offer  # 1

             For  some  inexplicable reason,  demonstration programs  are
        hard to come by. We are too busy writing PROLOG fill this gap. We
        will reward the contribution of "cute" sample programs.  Here are
        the guidlines as of 9/3/86:

        1) We've got enough games, puzzles and geneology programs.
        2) We need:
             a)  Alternate  forms  of reasoning,  such  as  probabalistic
        (Bayesian, fuzzy logic) forward chaining, cover sets.

             b)  Programs which use the graphics.

             c)
        3) Expert systems.

        You  must be certain that your contribution does not infringe  on
        anyone's copyright.

        The reward is the following: A copy of VMI virtual memory PROLOG.
        There will be a charge of $20.00 to cover our costs. That way, we
        won't go broke rewarding sample programs.

        The  sample program will be published as an intact file  together
        with whatever comments or advertisments the author may see fit to
        include, on our distribution disks.

        Exceptional  contributions  may  merit a copy of type  VML  large
        model virtual memory PROLOG which now incorporates a UNIX1  style
        tree structured domain system.



                                Special Offer # 2


             If  you are a hardware manufacturer and would like a  PROLOG
        language  for your system,  the solution is simple.  Just send us
        one  of  your machines!  Provided your system  implements  a  "C"
        compiler, it will be ported in no time flat.


        ______
             1. Trademark of AT & T.












                                       14








                         Writing Programs For ED PROLOG

             You do not type in programs at the "?-" prompt.  There is no
        built-in  editor.  The command "consult( user )" is accepted  but
        does not cause PROLOG to enter an editing mode.  We feel that the
        most universally acceptable editing method is for the user to use
        a text editor of choice,  which can be invoked from within PROLOG
        by the "exec" predicate.

             Use  Wordstar  or your customary editor to write a  program.
        Then  run  PD  PROLOG and use the consult function  to  load  the
        program.

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










































                                       15








                             Running the Interpreter

        COMMANDS: Give commands in lower case.

        TO RUN:
             Invoke PROLOG.EXE.  After the "?-" prompt appears,  you  may
             give Prolog goals to be executed,  followed by a period, and
             a carriage return.

        TO ENTER A FACT:
             Don't do it except with the "assert" predicates. This is the
             most  frequently misunderstood aspect of A.D.A.  Prolog.  If
             you want to enter a bunch of facts,  put them in a file  and
             "consult" them using the "consult" predicate.

        TO ASK A QUESTION:
             At the prompt, type "<expression>.<CR>", where
             <expression>  is  a  question as described by  Clocksin  and
             Mellish. Be sure to terminate the question with a period.
             The question may be up to 500 characters long.

        TO INPUT A STRUCTURE AT THE KEYBOARD:
             The structure may be up to 500 characters in length. Be sure
             to terminate with a period.

        TO ASK FOR ANOTHER SOLUTION:
             If a solution has been provided, the PROLOG interpreter will
             ask  "More?  (Y/N):".  Only  if  a "y"  is  typed  will  the
             interpreter perform a search.

        TO ABORT A SEARCH:
             Simply   type   the  escape  key.   The   interpreter   will
             respond  with  "Interrrupted.",  and return to  the  command
             prompt.

        TO LOAD DATABASE:
             Type  "consult(<filename>).<CR>" The file name must have the
             extension  ".PRO".  It  is  not  necessary  to  include  the
             extension in the argument of consult. The file name as given
             must not be the same as a predicate name in the file or  any
             file which will be loaded.

        TO TRACE:
             When the system displays the prompt "?-", type "trace.<CR>".
             The display will likely move too rapidly for you to read. To
             stop the display,  type Control S.  To restart the  display,
             type  Control S.  To turn the trace      display  off,  type
             "notrace<CR>"  at  the  prompt  "?-".   The  interrupt  menu
             contains  additional  options,  such  as sending  all  trace
             output to a file, as well as display at the console.







                                       16








        TO INTERRUPT A PROGRAM:
             See  the  section  entitled  "The  Interrupt  Menu"  for   a
             description  of the flexible options.  Basically,  one types
             ESC  to terminate a program,  while Control V or  Control  I
             interrupt a program.

        TO RECONSULT A FILE:
             The   predicate  "recon"  is  identical  to  the   Edinburgh
             predicate "reconsult."

        TO REMOVE A DATABASE:
             Type "forget(<filename>).<CR>"

        TO EXIT TO THE OPERATING SYSTEM:
             Type "exitsys.<CR>"

             The system is totally interactive; any commands the operator
        gives  are and must be valid program statements.  Statements must
        terminate with a period.      All commands which take a file name
        also  accept a path name.  Any name which is not a  valid  PROLOG
        atom (refer to C & M) must be enclosed in single quotes. Thus one
        could say

             consult( expert )

        but one would need single quotes with

             consult( 'b:\samples\subtype\expert' ).


        To exit the system, type "exitsys.<CR>"

        Atoms  may contain MSDOS pathnames if they are enclosed by single
        quotes, ie.,  '\b:\samples\animal' .

        You may consult more than one file at a time.  However, all names
        are public and name conflicts must be avoided. The order in which
        modules are loaded may,  in cases of poor program design,  affect
        the behavior.



                             Command Line Arguments

             ED and PD PROLOG accept one command line argument,  which is
        the name of a "stream" which replaces the console for input.  The
        "stream"  in  MSDOS is a pipe or file which supplies input  until
        end-of-file is reached. Control then reverts back to the console.
        To avoid noisy parser error messages when end-of-file is reached,
        the  last command in the file should be "see( user )." See  Simon
        Blackwell's PIE program for an example of this.






                                       17








                               A Reference of Note


             With  minor  exceptions,  the syntax is a superset  of  that
        described  by  Clocksin and Mellish in the  book  Programming  in
        Prolog by W.F.  Clocksin and C.S.  Mellish, published by Springer
        Verlag in Berlin, Heidelberg, New York, and Tokyo. We shall refer
        to this book as "C & M".


             There   are  very  few   syntactical   differences,   mostly
        unrecognized and/or minor.
             When  an operator is declared using the "op" statement,  the
        operator must be enclosed in single quotes in the "op"  statement
        itself,  if  it would not otherwise be a legal Edinburgh functor.
        Subsequently,  however,  the parser will recognize it for what it
        is,  except  in  the "unop" statement,  where it  must  again  be
        enclosed in single quotes.

             Variable numbers of functor paramaters are supported.

             A  goal  may be represented by a  variable,  which  is  less
        restrictive  than  the  C  &  M requirement  that  all  goals  be
        functors.  The  variable must be instantiated to a  functor  when
        that goal is pursued.

             Rules which appear inside other expressions must be enclosed
        in  parenthesis  if  the "," operator is to be  recognized  as  a
        logical connective.

             All  infix  operators described by C & M,  and user  defined
        infix,  prefix, and postfix operators with variable associativity
        and precedence are supported exactly as in C & M.
























                                       18








                            Memory Size Configuration

             Type  ED  can  access the full memory of  the  machine,  but
        previously required configuation by A.D.A.  The supplied  program
        "prconf.exe"  allows  the user to configure the amount of  memory
        used  by the PROLOG system.  The reason why this is important  is
        that  it is the vacant memory above the system which is  used  by
        the  "exec"  function  to load and execute  other  programs.  The
        amount of memory used is configured into the PROLOG.EXE file  and
        cannot be changed when PROLOG is actually running.

             The  configuration  is  carried  out  with  PRCONF.EXE   and
        PROLOG.EXE on the same disk. The user runs PRCONF and answers the
        sole question

            Enter the amount of workspace required in decimal Kbytes:

        PRCONF  then modifies the PROLOG.EXE file and writes the  changes
        out  to  disk.  This may be done as many times  as  required  and
        experimentation   is  beneficial.   There  are  several   factors
        competing for memory and they must be balanced:

              1)  The  amount of workspace must be sufficient to run  the
              prolog programs.  The total amount of memory used by PROLOG
              given by the following formula:

                  size of PROLOG.EXE
                 +size of workspace selected
                 +size of space needed to "exec" other programs, if used
                 +size of "COMMAND.COM" if "exec" is used
                ----------------------------------------
                 = Total used by Prolog system.

              "Total"  must be less than the available transient  memory.
              To get this,  run the "chkdsk" program,  supplied with DOS,
              and read the last line of the printout.


              2)  There must be sufficient memory to "exec"  the  desired
              programs.

              3)  Drivers  and auxiliary programs installed by  the  user
              such   as  "sidekick"  or  "superkey"  take  memory  in   a
              preemptive  fashion.   You  may  have  some  difficulty  in
              determining  how much free memory there  really  is.  After
              PRCONF  has  been  run,  load  PROLOG  and  note  that  the
              copyright  notice displays the highest memory location used
              by PROLOG.

        If the selected amount of workspace is greater than the memory of
        the  machine allows,  PROLOG simply acquires all available memory
        for  its  own  use.  This has only one bad  effect  - the  "exec"
        function won't function.




                                       19








                         The Built In Predicate Library

                        Available Operators in PD and ED PROLOG


        Column 1 gives the function symbol.

        Column 2 gives the precedence. The range of precedence is 1 to 255.
        A zero in the precedence column indicates the symbol is parsed as
        a functor, and precedence is meaningless in this case.

        Column 3 gives the associativity.
        A zero in the associativity column indicates the symbol is parsed
        as a functor, and associativity is meaningless in this case.

        Column 4 indicates which version the function is available in.
        Unless otherwise noted, the function is available in all versions.
        Nonstandard predicates are indicated by "NS".


        op/pred      precedence    associativity         availability

        "!"             0             0
        "|"             0             0
        "="             40,           XFX
        "=="            40,           XFX
        "\\="           40,           XFX
        "\\=="          40,           XFX
        "/"             21,           YFX
        "@="            40,           XFX
        ">="            40,           XFX
        "=<"            40,           XFX
        ">"             40,           XFX
        "<"             40,           XFX
        "-"             31,           YFX
        "*"             21,           YFX
        "+"             31,           YFX
        "=.."           40,           XFX
        "-->"           255,          YFY       (not  in  PD PROLOG)
        "?-"            255,          FY



        "arg"           0,            0,
        "asserta"       0,            0,
        "assertz"       0,            0,
        "atom"          0,            0,
        "atomic"        0,            0,
        "batch"         0,            0
        "clause"        0,            0,
        "clearops"      0,            0,
        "cls"           0,            0,       NS
        "concat"        0,            0,
        "consult"       8,            FX,
        "crtgmode"      0,            0,       NS


                                       20








        "crtset"        0,            0,       NS
        "curset"        0,            0,       NS
        "curwh"         0,            0,       NS
        "debugging      0,            0,
        "dir"           0,            0,
        "display"       0,            0,
        "dotcolor"      0,            0,       NS
        "drawchar"      0,            0,       NS
        "drawdot"       0,            0,       NS
        "drawline"      0,            0,       NS
        "exec"          0,            0,
        "exitsys"       0,            0,       NS
        "forget"        0,            0,       NS
        "functor"       0,            0,
        "get0"          8,            FX,
        "integer"       0,            0,
        "is"            40,           XFX,
        "listing"       0,            0,
        "memleft"       0,            0,      NS
        "mod"           11,           XFX,
        "name"          0,            0,
        "nl"            0,            0,
        "nodebug"       0,            0,       (not in PD PROLOG)
        "nonvar"        0,            0,
        "nospy"         50,           FX,      (not in PD PROLOG)
        "not"           60            FX
        "notrace"       0,            0,       (not in PD PROLOG)
        "op"            0,            0,
        "popoff"        0,            0,       NS
        "popoffd"       0,            0,       NS
        "popon"         0,            0,       NS
        "popond"        0,            0,       NS
        "print"         0,            0,
        "prtscr"        0,            0,       NS
        "put"           0,            0,
        "ratom"         0,            0,
        "read"          0,            0,
        "recon"         0,            0, (Note: this is "reconsult")
        "repeat"        0,            0,
        "retract"       0,            0
        "rnum"          0,            0,
        "see"           0,            0,
        "seeing"        0,            0,
        "seen"          0,            0,
        "skip"          0,            0,       (not in PD PROLOG)
        "spy"           50,           FX,
        "tab"           0,            0,
        "tell"          0,            0,
        "telling"       0,            0,
        "told"          0,            0,
        "trace"         0,            0,       (not in PD PROLOG)
        "true"          0,            0,
        "unop"          0,            0,
        "var"           0,            0,
        "write"         0,            0,


                                       21








                        Description of the Modifications.


        I/O Redirection

        I/O  redirection is a feature described by Clocksin and  Mellish.
        The predicates "see",  "seeing",  "seen",  "tell", "telling", and
        "told" are used to select the streams used for input and output.

             The  predicates  "seen" and "told" require as arguments  the
        name of the stream that is to be closed.  This enables the system
        to  remember the indices of several streams and switch  back  and
        forth between them.

             The  predicate "batch",  when inserted at the beginning of a
        stream file, has the following properties:

             1)  The normal prompt,  "?-",  and advisory messages do  not
             appear at the screen.

             2)  It is self cancelling if the input stream is  reassigned
             to the console.

             3) It may also be cancelled by the predicate "batch".



        call( <goal> )

             The  predicate as defined in C & M is obsolete.  The purpose
        was  to permit a goal search where the goal name was  a  variable
        instantiated  to  some functor name.  A.D.A.  permits writing  of
        goals with such names,  so the mediation of the "call" clause  is
        no longer necessary.

             The  "call"  predicate  may  be  trivially  implemented  for
        compatibility with the PROLOG definition

                                 call( X ) :- X.



        clause

             The  function  clause(  X,  Y ) has the  new  optional  form
        clause(  X,  Y,  I  ).  If the third variable is written,  it  is
        instantiated  to the current address of a clause in  memory.  The
        only  use of the result is with succeeding assertfa and  assertfz
        statements.








                                       22








        debugging

             "Debugging"  prints a list of the current  spypoints.  After
        each name a sequence of numbers may appear, indicating the number
        of  arguments that is a condition of the trace.  The  word  "all"
        appears  if  the  number of arguments is not a condition  of  the
        trace.




        op( <prec>, <assoc>, <functor> )

             Defines  the  user  definable  grammar  of  a  functor.  The
        definition conforms to that in C & M. We mention here a minor but
        important point.  If <functor> is not a valid PROLOG atom it must
        be   enclosed  in  single  quotes  when  declared  in  the   "op"
        declaration.  It  is  not necessary or legal to do this when  the
        functor is actually being used as an operator.  In version 1.6, a
        declared  or built-in operator can be used either as an  operator
        or as a functor. For example,

                                 +(2,3) = 2 + 3.

        is a true statement.

             Declared  operators  are annotated in the directory  display
        with their precedence and associativity.





























                                       23








        Output predicates

           display
           write
           print
           put

             These  functions  have  been  modified  to  accept  multiple
        arguments in the form:

                       print( <arg1>, <arg2>, <arg3>,... )

        Thus, "put( a, b, c )" would result in the display of "abc".
             The  names  of  some  PROLOG atoms that may  occur  are  not
        accepted  by  the  PROLOG scanner  unless  surrounded  by  single
        quotes.  This only applies when such an atom is read in, not when
        it is internally generated. Nevertheless, this presents us with a
        problem:  We  would  like to be capable of writing  valid  PROLOG
        terms to a file. In some cases, it is necessary to add the single
        quotes.  In other cases,  such as human oriented output, they are
        an irritant. The modified definitions of the following predicates
        are an attempt at a solution:

             display
             Operator  precedence  is ignored,  all functors are  printed
             prefix and single quotes are printed if needed or they  were
             supplied if and when the atom was originally input.

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

             print
             Operator  precedence is taken into account and operators are
             printed  according to precedence.  Single quotes  are  never
             displayed.  This  is  a  human oriented form of  output  and
             should  never  be used for writing of terms for  the  PROLOG
             scanner.


















                                       24








        get0
        read

             The  functions  "get0"  and "read"  have  been  extended  to
        support input from a stream other than the one currently selected
        by "see". To direct output to a file or other stream, an optional
        argument  is used.  For example,  "get0( char,  <file name> )" or
        "get0( char,  user )" would cause input to come from <file  name>
        or the console.  If the file has not already been opened,  "get0"
        will fail.



             Atoms enclosed by single quotest, eg. '\nthis is a new line'
        can contain the escape sequences

             '\n', '\r', '\t' and '\''.

             If these atoms are printed by "display" or "write" they  are
        printed  just  as they are.  If they are printed by  the  "print"
        clause they are translated as follows:

        '\n'  results  in  the printing of a carriage return and  a  line
        feed.
        '\r' results in the printing of a carriage return only.
        '\t' results in the printing of a tab character.
        '\'' allows the printing of a single quote within a quoted atom.

             The "portray" feature is not presently implemented.




























                                       25








                        Description of the New Predicates


        batch, nobatch

        This  predicate now makes it possible to avoid the appearance  of
        messages and prompts on the screen when input has been redirected
        to come from a file.

        The  predicate  formerly had a different effect which  no  longer
        exists.

        When  placed  at  the head of a stream file which is  "seen"  the
        system  prompt  is not repetetively displayed as  the  stream  is
        executed. Advisory messages are not displayed either.

        The  command "batch" is self cancelling if control reverts to the
        console  at any time.  It may also be cancelled by  invoking  the
        predicate "nobatch."

        A related change is that when the Prolog system is invoked with a
        command  line  argument for a stream,  the system prompt  is  not
        initially displayed.  So if the first command in the stream  file
        is  "batch.",  it is possible to use i/o redirection without  the
        appearance of any system messages except aor the signon message.



        clearops-

             Nullify  the  operator  status  of  every  operator  in  the
             database.

        concat( (<variable> | <functor>), <List> )

             A  list  of functors or operators is concatenated  into  one
        string,  which becomes the name of a new atom to which <variable>
        or <functor> must match or be instantiated.


        dir( option )

             Provide  an  alphabetized listing to the console  of  atoms,
        constants,   or   open  files.   Without  options,   simply  type
        "dir.<CR>". Options are:

             dir( p ) - list clause names only.
             dir( c ) - list consulted files only.

        Consulted files are prefixed by "S:".







                                       26








        exec( arg1, arg2, ... argn )

             Execute  the program named as arg1,  provided that there  is
        sufficient  memory.  arg2 through argn must be functors which are
        supplied  as the command line argument,  separated by  one  space
        from  neighbors.  The  PCDOS or MSDOS  operating  system  program
        "COMMAND.COM"  must be reachable by the DOS search path,  because
        using "exec" invokes "COMMAND.COM", which is the DOS shell.

             You  can temporarily leave PROLOG and execute the DOS  shell
        with  the  invocation "exec( command )." The  DOS  prompt  should
        appear,  and  you can run programs bearing in mind that PROLOG is
        still  resident and occupying the bulk of memory.  To  return  to
        PROLOG, type "exit" at the DOS prompt.

             This  function  is restricted in the case of the type PD  to
        executing  a  program named "prologed",  which may be  an  editor
        supplied by you.

             This  function  will not work properly unless the system  is
        configured for memory.


        exitsys

             Exit to the operating system.



        forget( <file name> )
             Make  a database unavailable for use and reclaim the storage
        it occupied.



        ratom( <arg>, <stream> )-
             Read an atom from the input stream,  to which <arg>  matches
        or  is  instantiated.  <stream> is optional.  If <stream> is  not
        given, the input stream defaults to the standar input.
             Input is terminated by a CR or LF, which are not included in
        the stream.
















                                       27








                             Arithmetic Capabilities

             Integer  arithmetic is supported.  Numbers are 32 bit signed
        quantities. The following arithmetic operators are supported:

                      "+", "-", "*", "/", <, <=, >, >=, mod.

        Arithmetic operators must never be used as goals,  although  they
        may be part of structures. It is legal to write:

                                    X = a + b

        which  results in the instantiation of X to the struture (a + b).
        But the following is not legal:

                       alpha( X, Y ) :- X + Y, beta( Y ).


        Evaluation  of  an arithemtic expression is mediated by the  "is"
        and inequality predicates.  For instance,  the following would be
        correct:

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

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
































                                       28








                            Memory Metric Predicate

             The purpose of this predicate is to give the prolog system
        a  sense  of  how much memory remains so  that  expensive  search
        strategies  can  be  controlled.  It is not possible  to  exactly
        quantify how much memory remains.  At the lowest level, there are
        two  types of memory - the stack and the heap.  The stack expands
        down  from  high  memory,  while  the heap  tends  to  expand  at
        unpredictable intervals upwards.  If the stack and heap meet, the
        prolog  system  must abort the search and return to  the  prompt.
        Judicious  use  of  the  memory  metric  predicates  reduces  the
        probability of this happening.

             The  stack is easy to quantify because it expands  downwards
        in  a  predictable  way with recursion.  The symbol  space  is  a
        "heap".  For  those  interested,  the structure of  the  heap  is
        determined  by  the C compiler under which Prolog  was  compiled.
        There  is  a function internal to Prolog known as  the  allocator
        searches  the  heap for enough contiguous memory to create a  new
        symbol.  The  heap resembles a piece of Swiss cheese;  the  holes
        represent symbols and already allocated memory while the remained
        is  searched  by the allocator for a piece of  contiguous  memory
        large enough to satisfy a request.  If one cannot be  found,  the
        uppermost  bound of the heap is expanded upwards,  and that bound
        is  the  number  which we measure for an  estimate  of  remaining
        memory.

             The  sqace between the top of the heap,  and  the top of the
        stack,  which we call "gap",  serves as a rough guide to how much
        memory  remains.  The  demands  of the system  are  not  entirely
        predictable,  however.  For example, the creation of a new symbol
        larger  than "gap" would cause an abort.  The user must  use  the
        numbers  supplied  by  these  functions  as  a  heuristic  guide,
        tempered  by  experience,  to  minimize  the  possibility  of  an
        unexpected abort.

        "Gap" is measured in 256 byte pages.

        memleft( X )

        If  the argument is an integer,  this is satisfied if the size of
        "gap" is greater than "X".

        If the argument is a variable,  it is instantiated to the  amount
        of "gap" remaining.












                                       29








                         IBM PC Video Display Predicates


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



        cls

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



        crtgmode( X )

        Matches  the  argument to the mode byte of the display  which  is
        defined as follows:

                  mode           meaning

                   0             40 x  25  BW (default)
                   1             40 x  25  COLOR
                   2             80 x  25  BW
                   3             80 x  25  COLOR
                   4            320 x 200  COLOR
                   5            320 x 200  BW
                   6            640 x 200  BW
                   7             80 x  25  monochrome  display card



        crtset( X )

        This  sets the mode of the display.  The argument must be one  of
        the modes given above.



        curset( <row>, <column>, <page> )

        Sets the cursor to the given row, column, and page. The arguments
        must be integers.



        curwh(  <row>, <column> )

        Reports the current position of the cursor.  The argument must be
        an integer or variable. The format is:

             1) page zero is assumed.
             2) The row is in the range 0 to 79, left to right.
             3) The column is in the range 0 to 24, bottom to top.


                                       30








        dotcolor( <row>, <column>, <color> )

        The  argument  <color> is matched to the color of  the  specified
        dot. The monitor must be in graphics mode.



        drawchar( <character>, <attribute> )

        Put a character at the current cursor position with the specified
        attribute.  The  arguments  <character> and <attribute>  must  be
        integers.  Consult  the IBM technical reference manual  regarding
        attributes.



        drawdot( <row>, <column>, <color> )

        Put  a dot at the specified position.  The monitor must be in the
        graphics  mode.  The  arguments  must be  integer.  The  argument
        <color> is mapped to integers by default in the following manner:



        drawline( <X1>, <Y1>, <X2>, <Y2>, <color> )

        Draw a line on the between the coordinate pairs. The monitor must
        be in the graphics mode and the arguments are integer.



        prtscr

        Print  the  screen  as it currently appears.  Be  sure  that  the
        printer  is  on  line and ready before invoking  this  predicate,
        since otherwise, the system may lock up or abort.



        The  integer argument <color> referred to in the above predicates
        is represented as follows:

             COLOR          PALETTE 0           PALETTE 1

               0            background          background
               1            green               cyan
               2            red                 magenta
               3            brown               white

        To change the palette and the background,  see the IBM  Technical
        Reference Bios listings for more information.






                                       31








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

             ^V:  The menu is displayed and a command is accepted at the
                  prompt  "INTERRUPT>".  After  a command,  the  menu  is
                  redisplayed  until  the user selects  a  command  which
                  causes an exit.

             ^I:  The menu is not displayed.  Command is accepted at the
                  prompt  "INTERRUPT>" until the user selects  a  command
                  which causes an exit.

             ESC: Typing this key  causes a  termination of  the  PROLOG
                  search  and  control returns to the user command  level
                  with a prompt of "?-".  Notice that previously, the ESC
                  key invoked this menu.
















                                       32








             As the resulting menu indicates, the following functions are
        possible:

             A: Abort the search and return to the prompt.

             O  Open  a trace file.  The user is prompted for  the  file
                name.  The file receives all trace output.  If a file is
                already opened it is closed with all output preserved.

             C  Close the trace file if one is open.  Otherwise there is
                no effect.

            ^C: Immediately  exit PROLOG without closing files.  This is
                not advised.

            ^P: Typing <Control>P toggles the printer. If the printer is
                on,  all  input  and output will also be  routed  to  the
                printer.

             S: If  the machine in use is an IBM PC compatible  machine,
                the  currently displayed screen will be printed.  If  the
                machine  is  not an IBM PC compatible,  do not  use  this
                function.

             T: If  trace  is in use,  most of the trace output  can  be
                temporarily turned off by use of this function,  which is
                a toggle.

             G: Satisfy a goal.  The system prompt will appear. Do not be
                confused  into  thinking that the system has reverted  to
                the  prompt.  After the user has entered the goal in  the
                usual  manner,  satisfaction  of the goal is  immediately
                attempted.  This need not affect the running  computation
                in  any way,  although it is certainly possible to do so.
                After  the  goal is attempted,  control  returns  to  the
                INTERRUPT  menu.  The  purpose is to facilitate  detailed
                analysis of a running system.

             R:  Entering  another  ESC causes a return to the  current
                activity  (keyboard  input or search)  with  no  residual
                effect from the interruption.
















                                       33









                             Conserving memory space


               Success popping is controlled by the predicates "popond",
        "popoffd",  "popon",  and  "popoff".  Success popping is means of
        reclaiming  storage which is used on backtracking to  reconstruct
        how a particular goal was satisfied.  If it is obvious that there
        is no alternative solution to a goal this PROLOG system is  smart
        enough to reclaim that storage.

             In  this system,  succees popping is an expensive operation.
        Therefore,  there  is a tradeoff of memory versus  time.  On  the
        other hand, discrete use of success popping can actually speed up
        a program by recreating structures in a more accessible form.

             The  definitions of the control predicates is given in  this
        manual  and  their use is totally  optional.  The  modulation  of
        success popping has no effect on program logic (read solution.)

             The  "cut"  can  save  substantial  time  and  computational
        overhead  as well as storage.  Although the execution of the  cut
        costs  time,  you can design your program to use cuts in critical
        places  to  avoid unnecessary backtracking.  Thus  the  execution
        speed of the program can actually increase.

             Anyone  who  has  read Clocksin and  Mellish  is  aware,  of
        course, that the "cut" has a powerful logical impact which is not
        always desirable.


        popoff

        See the below definition.



        popon

        The  inference  engine  does complete success popping  for  goals
        which appear after "popon".  Consider this example:

          goal :-  a, popon, b, c, popoff, d.

        If  no alternative solutions exist for b,  then  success  popping
        will  reclaim storage by removing unnecessary records  describing
        how  "b"  was  satisfied.  If the Prolog system cannot  rule  out
        possible additional solutions,  success popping will never occur,
        regardless of your use of "popon".
             Since goal "d" occurs after "popoff",  success popping  will
        never occur.






                                       34








        popoffd

        If  no  "popon" or "popoff" declarations occur in a  clause,  the
        default  action  is  determined by  "popoffd"  and  "popond".  If
        "popoffd" has been invoked,  the default is that success  popping
        will not occur.



        popond

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












































                                       35








                                 Prolog Tutorial


                                  Introduction




             Probably  you  have heard of the language PROLOG within  the
        last year or so. You probably wondered the following things:

        1) What does the name stand for? Names of computer languages are
        almost always acronyms.

        2) What is it good for?

        3) Why now?

        4) Can I get a copy to play with?

             Congratulations! You obviously know the answer to the fourth
        question. We now respond to the other three.

        1)  The  name  stands for "programming in logic." This  we  shall
        elaborate on in depth later on.

        2) PROLOG is good for writing question answering systems.  It  is
        also   good   for  writing  programs  that  perform   complicated
        strategies  that  compute the best or worst way to  accomplish  a
        task, or avoid an undesirable result.

        3) PROLOG was virtually unknown in this country until researchers
        in  Japan announced that it was to be the core language  of  that
        country's fifth generation computer project.  This is the project
        with  which  Japan hopes to achieve a domainant position  in  the
        world information industry of the 1990's.

             PROLOG  is  one of the most unusual computer languages  ever
        invented.  It  cannot be compared to  FORTRAN,  PASCAL,  "C",  or
        BASIC.  The facilities complement,  rather than replace those  of
        conventional  languages.  Although  it  has great  potential  for
        database  work,  it  has  nothing in  common  with  the  database
        languages used on microcomputers.

             Perhaps  the  best point to make is that while  conventional
        languages are prescriptive, PROLOG is descriptive. A statement in
        a conventional language might read:

             if( car_wheels = TRUE ) then
               begin
                 (some sort of procedure)
                 X = X + 1;
               end




                                       36








        A statment in PROLOG could just be a statment of fact about  cars
        and wheels. There are many relationships that hold. For instance,

             has( car, wheels ).

             has( car, quant(wheels, four) ).

             round( wheels ).

        Each  of  these statments is an independent fact  relating  cars,
        wheels,  and  the  characteristics of wheels.  Because  they  are
        independent, they can be put into a PROLOG program by programmers
        working separately. The man who is a specialist on car bodies can
        say  his thing,  the wheel specialist can have his say,  and  the
        participants can work with relative independence. And this brings
        to light a major advantage of PROLOG:


                             PARALLEL PROGRAMMING!!!


        With  conventional  programming languages projects can  still  be
        "chunked",  or  divided between programmers.  But efficiency on a
        team  project  drops  drastically below that  of  the  individual
        programmer  wrapped  up  in  his own trance.  As  the  number  of
        participants    grows   the   need   for   communication    grows
        geometrically. The time spent communicating can exceed that spent
        programming!
             Although   PROLOG   does   not  eliminate   the   need   for
        task  coordination,  the problem is considerably  simplified.  It
        also provides the ability to answer questions in a "ready to  eat
        form."  Consider your favorite BASIC interpreter.  Based upon the
        statements about cars and wheels previously given,  could you ask
        it the following question?


              has( car, X ), round( X ).

             Does  a  car  have anything which  is  round?  The  question
        instructs the PROLOG interpreter to consider all the objects that
        it  knows are possessed by a car and find those which are  round.
        Perhaps  you are beginning to guess that PROLOG has the abilities
        of a smart database searcher.  It can not only find the facts but
        selectively find them and interpret them.













                                       37








             Consider the problem of a fault tree, as exemplified by this
        abbreviated one:



        {Car won't start}
             |
             |
        [Engine  turns  over](No) --> [Battery voltage](no)-\
                (Yes)                                       v
                 |                                  {Check battery}
                 |
        [Smell gasoline](yes) --> {Try full throttle cranking}
                 |                       (failure)
        /--------/                           |

                            (details omitted)



             The fault tree is easily programmed in BASIC. Later we shall
        show  that  PROLOG supplies a superior replacement for the  fault
        tree.  Though the tree is capable of diagnosing only the  problem
        for  which  it was designed,  PROLOG dynamically  constructs  the
        appropriate  tree from facts and rules you have provided.  PROLOG
        is not limited to answering one specific question.  Given  enough
        information,  it  will attempt to find all deductive solutions to
        any problem.





























                                       38









                                  PROLOG PRIMER

        I.                       Rules and Facts



             This  is  where you should start if you know  nothing  about
        PROLOG. Let us consider a simple statment in PROLOG, such as:

        1)   has( car, wheels ).

        This  statement  is a "fact.  The word "has" in this statment  is
        known  either  as a functor or predicate.  It is a name  for  the
        relationship  within the parenthesis.  It implies that a car  has
        wheels.  But  the  order  of  the words  inside  the  bracket  is
        arbitrary and established by you. You could just as easily say:

        2)   has( wheels, car ).

        and if you wrote this way consistently,  all would be  well.  The
        words  has,  wheels,  and car are all PROLOG atoms.  "Wheels" and
        "car" are constants.

        A   database   of  facts  can  illustrate  the   data   retrieval
        capabilities of PROLOG. For instance:

        3)   has( car, wheels ).
             has( car, frame ).
             has( car, windshield ).
             has( car, engine ).

        You could then ask PROLOG the question:

        4)   has( car, Part ).

        The  capital  "P" of Part means that Part is a  variable.  PROLOG
        will make Part equal to whatever constant is required to make the
        question match one of the facts in the database. Thus PROLOG will
        respond:

             Part = wheels.

             More?(Y/N):

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

             Part = frame.

             More?(Y/N):

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

             More?(Y/N):y


                                       39









             No.

        indicating that PROLOG has exhausted the database.  Incidentally,
        when  a  variable is set equal to a constant or  other  variable,
        it is said to be instantiated to that object.

             Notice  that  PROLOG searches the database forwards  and  in
        this case,  from the beginning.  The forward search path is built
        into PROLOG and cannot be changed. An author of a program written
        in  a  prescriptive language is quite conscious of the  order  of
        execution  of  his program,  while in PROLOG it is  not  directly
        under his control.

             The other major element is the rule which is a fact which is
        conditionally true. In logic this is called a Horn clause:


        5)   has( X, wheels ) :- iscar( X ).

        The  fact iscar( car ) and the above rule are equivalent to

        6)   has( car, wheels).

        The  symbol :- is the "rule sign." The expression on the left  of
        :-is the "head" and on the right is the body.  The variable X has
        scope  of the rule,  which means that it has meaning only  within
        the rule.  For instance,  we could have two rules in the database
        using identically named variables.


        7)   has( X,  transportation ) :-
                           has( X,  car ), has( license, X ).

        8)   has( X, elephant ) :- istrainer( X ), hasjob( X ).

        The  variables  X in the two expressions are completely  distinct
        and have nothing to do with each other.

        The comma between has( X, car ) and has( license, X ) means "and"
        or logical conjuction.  The rule will not be true unless both the
        clauses has(X, car) and has( license, X ) are true.


             On the other hand if there is a rule

        9)   has( license, X ) :- passedexam( X ).

        consider what PROLOG will do in response to the question:

        10)  has( harry, transportation ).

        (Notice  that  harry has not been capitalized because we  do  not
        want  it  taken as a variable.  We could,  however,  say  'Harry'
        enclosed in single quotes.)


                                       40









             It  will scan the database and use (7),  in which X will  be
        instantiated to harry. The rule generates two new questions:

        11)  has( harry, car ).

        12)  has( license, harry ).

        Assuming  that  harry  has  a car,  the first clause  of  (7)  is
        satisfied and the database is scanned for a match to (12). PROLOG
        picks  up  rule (9) in which X is instantiated to harry  and  the
        question is now posed:

        13)  passedexam( harry ).

             If there is a fact:

             passedexam( harry ).

        in  the database then all is well and harry  has  transportation.
        If there is not, then PROLOG will succinctly tell you:

             No.

        But  suppose Harry has money and can hire a chauffer as any  good
        programmer  can.  That  could be made part of the program in  the
        following way.

             The rule which PROLOG tried to use was:

        14)  has( X,  transportation ) :-
                           has( X,  car ), has( license, X ).

        At any point following it there could be included another rule:

        15)  has( X, transportation ) :- has( X, money ).

        or simply the bald fact:

        16)  has( harry, transportation ).

             These  additional  rules  or  facts would  be  used  in  two
        circumstances.  If at any point a rule does not yield a solution,
        PROLOG   will  scan  forward  from  that  rule  to  find  another
        applicable  one.  This process is known as "backtracking  search"
        and can be quite time consuming.


        If  in response to the "More?" prompt you answer "y" PROLOG  will
        search  for an additional distinct solution.  It will attempt  to
        find an alternate rule or fact for the last rule or fact used. If
        that  fails,  it  will back up to the antecedent rule and try  to
        find  an alternate antecedent.  And it will continue to  back  up
        until  it  arrives at the question you asked,  at which point  it
        will say:


                                       41









             No.

        "Antecedent"  to a rule means that it gave rise to its' use.  For
        example,  (7)  is  the antecedent of (9) in the  context  of  the
        question (16).




        II.                          Grammar

             It is a boring subject, but it must be discussed. All PROLOG
        statements are composed of valid terms, possibly a rule sign (":-
        "),  commas representing conjunction ("and"), and a period at the
        very end.
             A term is a structure, constant, variable, or number.

             What is a structure? It is a kind of grouping:

             1) Structures consist of a functor, and a set of objects or
                structures in parenthesis.

             2)  Objects are constants,  variables,  numbers,  or  lists,
                which we have not discussed yet.

             3)  A  constant or functor must be a string of  letters  and
                numbers, beginning with a lower case letter, unless
                you  choose  to  enclose  it in single  quotes  (  'howdy
                pardner'  ),  in  which  case you are  freed  from  these
                restrictions.
             4) A  variable  must be a string of  letters  and  numbers
                beginning with a capital letter.

             5) A  functor  may optionally have  arguments  enclosed  in
                parenthesis , as in: hascar( X ) or hascar.

        An example:  "has( X, transportation )." is a structure.



















                                       42








        III.                     Input / Output

             You   now   know  enough  to  write  simple  databases   and
        interrogate   them  profitably.   But  before  we  examine   more
        sophisticated  examples,  it  will be necessary to add input  and
        output to the language. There are built in functions which appear
        as rules which are satisfied once. Thus the statment:

             write( 'Hello world.' ).

        can be included on the right side of a rule:


        greetings(  X ) :- ishuman( X ),  write( 'Hello world.' ).  You
        can  also write "write( X )" where X is some variable.  Note that
        'Hello  world.' is not enclosed in double quotes.  Single quotes,
        which denote a constant, are required. Double quotes would denote
        a list, which is another thing entirely.

        Provided  that  a match to "ishuman" can be  found,  the  builtin
        function  "write"  is  executed and the message  printed  to  the
        screen.
             The  builtin  read( X ) reads a "structure" that  you  input
        from the keyboard. More formally, we have

             read( <variable> or <constant> )
             write( <variable> or <constant> )

        If you write read( Input ),  then the variable "keyboard" will be
        assigned to whatever is typed at the keyboard,  provided that the
        input  is a valid PROLOG structure.  The builtin "read" will fail
        if instead of Keyboard we wrote read( baloney ),  where "baloney"
        is a constant,  and the user at the keyboard did not type exactly
        "baloney."

        When you input a structure in response to a "read" statement,  be
        sure to end it with a period and an <ENTER>.

             There  is  a convenient way of putting the cursor on  a  new
        line. This is the builtin "nl". For example:

             showme :- write( 'line 1' ), nl, write( 'line 2' ).

        would result in:

             line 1
             line 2

             There  is  also a primitive form of input/output for  single
        characters. It will be discussed later.







                                       43








        IV.                   A Fault Tree Example

             Consider the "won't start" fault tree for an automobile:

        {Car won't start}
             |
             |
        [Engine  turns  over](No) --> [Battery voltage](no)-\
                (Yes)                                       v
                 |                                  {Check battery}
                 |
        [Smell gasoline](yes) --> {Try full throttle cranking}
                 |                       (failure)
        /--------/                           |
        |           /------------------------/
        |           |
        |           |
        |  [Check for fuel line leaks](yes)-->{Replace fuel line}
        |          (no)
        |           |
        |           |
        |  [Check for defective carburator](yes)--\
        |          (no)                           v
        |                                {Repair carburator}
        \----\
             |
             |
        [Is spark present](no)-->[Do points open and close](no)-\
             |                             (yes)                v
        /----/                               |          {Adjust points}
        |           /------------------------/
        |           |
        |  [Pull distributor wire, observe spark](blue)--\
        |        (orange)                                v
        |           |                           {Check plug wires & cap}
        |           |
        |  [Measure voltage on coil primary](not 12V)--\
        |         (12V)                                v
        |           |              {Check wiring, ballast resistor}
        |           |
        |  [Check condenser with ohmmeter](conducts)--\
        |    (no conduction)                          v
        |           |                         {Replace condenser}
        |           |
        |  [Open and close points](voltage not 0 - 12)--\
        |   (voltage swings 0 - 12)                     v
        |           |                         {Fix primary circuit}
        |           |
        |  {Consider hidden fault, swap components]
        |
        |
        \-------{Call a tow truck!!}





                                       44








             A PROLOG program to  implement this is simple. Each statment
        represents  a  decision point fragment of the  tree.  The  PROLOG
        interpreter  dynamically  assembles  the tree as  it  attempts  a
        solution.

        'car wont start' :- write( 'Is the battery voltage low?' ),
                            affirm, nl,
                            write( 'Check battery' ).

        'car wont start' :- write( 'Smell gasoline?' ),
                            affirm, nl,
                            'fuel system'.

        'fuel system'    :- write( 'Try full throttle cranking' ).

        'fuel system'    :- write( 'Are there fuel line leaks?' ),
                            affirm, nl,
                            write( 'Replace fuel line.' ).

        'fuel system'    :- write( 'Check carburator' ).

        'car wont start' :- write( 'Is spark present?' ),
                            not( affirm ), nl,
                            'no spark'.

        'no spark'       :- write( 'Do points open and close?' ),
                            not( affirm ), nl,
                            write( 'Adjust or replace points.' ).

        'no spark'       :- write( 'Is the spark off the coil good?' ),
                            affirm,
                            write( 'Check plug wires and cap.' ).

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

        'no spark'       :- write( 'Does the capacitor leak?' ),
                            affirm,
                            write( 'Replace the capacitor.' ).

        'no spark'       :- not( 'primary circuit' ).

        'primary circuit'
                         :- write( 'Open the  points.  Voltage  across
                              coil?:'), nl,
                            read( Openvolts ), Openvolts < 1,
                            write(  'Close the points.  Voltage  across
                              coil?:'),
                            read( Closevolts ), Closevolts > 10, nl,
                            write( 'Primary circuit is OK.' ).



                                       45








        'no spark'       :- write( 'Consider a hidden fault. Swap
                              cap, rotor,points,capacitor.' ).


        'Car wont start' :- write( 'Get a tow truck!!' ).


                                 --End program--


             The  above  is  a  simple example of  an  expert  system.  A
        sophisticated  system would tell you exactly the method by  which
        it  has reached a conclusion.  It would communicate by a  "shell"
        program  written  in PROLOG which would accept a wider  range  of
        input   than  the  "valid  structure"  required  by  the   PROLOG
        interpreter directly.









































                                       46








        V.                            Lists

             Consider  a  shopping list given you by your wife.  It is  a
        piece of paper with items written on it in an order that probably
        symbolizes  their  importance.  At the top it  may  say  EGGS!!!,
        followed by carrots, hamburger, and finally a flea collar for the
        dog, if you can find one. In PROLOG such a list would be written:

        1)   [eggs, carrots, hamburger, fleacollar]

        The  order of a list is important so that eggs and carrots cannot
        be reversed and PROLOG be uncaring.

        Let us put the list in a structure:

             shopping( [eggs, carrots, hamburger, fleacollar] ).

        Then  if you wished to isolate the head of the list you could ask
        the question:

             shopping( [ Mostimportant | Rest ] ).

        and PROLOG would respond:

             Mostimportant   =  eggs,
             Rest   =   [carrots,   hamburger, fleacollar].

        The vertical bar "|" is crucial here. It is the string extraction
        operator,  which  performs  a  combination  of the  CDR  and  CAR
        functions  of LISP.  When it appears in the context [X|Y] it  can
        separate the head of the list from the rest, or tail.


             You  may have gained the impression that PROLOG is a  rather
        static language capable of answering simple questions,  but it is
        far  more powerful than that.  The string extraction operator  is
        the  key.  It permits PROLOG to whittle a complex expression down
        to the bare remainder.  If the rules you have given it permit  it
        to  whittle  the  remainder  down to  nothing,  then  success  is
        achieved. An example of this is the definition of "append."

             Let  us suppose you have not yet done yesterday's  shopping,
        let alone today's. You pull it out of your wallet and sootch tape
        it to the list your wife just gave you. Yesterday's list was:

             [tomatoes, onions, ketchup]

        Combined with [eggs, carrots, hamburger, fleacollar] we obtain

             [eggs,carrots,hamburger,fleacollar,tomatoes,onions,garlic].

        To  take one list and to attach it to the tail of another list is
        to  "append"  the first to the second.  The PROLOG definition  of
        append is:



                                       47










        Rule1:     append( [], L, L ).

        Rule2:     append( [X|List1], List2, [X|List3] ) :-
                      append( List1, List2, List3 ].

        The  general  scheme is this:

        The definition consists of one rule and one fact.  The rule  will
        be used over and over again until what little is left matches the
        fact.  The [] stands for empty list,  which is like a bag without
        anything in it. This is an example of a recursive definition.
             Suppose we ask:

             append( [a,b,c], [d,e,f], Whatgives ).

        1. Rule 2 is invoked with arguments ( [a,b,c], [d,e,f], Whatgives ).
        2. Rule 2 is invoked again with arguments:
             ( [b,c], [d,e,f], List3 ).
        3. Rule 2 is invoked again with arguments:
             ( [b], [d,e,f], List3 ).
        4.  The  arguments  are now ([],  [d,e,f],  List3 ).  Rule 1  now
            matches. End.

        How does this cause a list to be constructed? The key is to watch
        the   third  argument.   Supplied  by  the  user,   it  is  named
        "Whatgives". The inference engine matches it to [X|List3] in rule
        2. Now lets trace this as rule two is successivly invoked:


                Whatgives
                   |
                   |
                   |
                   v
        Rule2:  [X|List3] (List1 = [b,c])
                 |  \
                 |   \
                 |    \
                 v     \
        Rule2:   a   [X'|List3'] (List1' = [c])
                      |    \
                      |     \
                      |      \
                      v       \
        Rule2:        b     [X''|List3''] (List1'' = [], ie., empty set.)
                              |    \
                              |     \
                              |      \
        Rule1:                c       L  ( in Rule1 = [d,e,f] )

        End.




                                       48








        L in rule 1 is [d,e,f] for the following reason: Notice that rule
        2 never alters List2. It supplies it to whatever rule it invokes.
        So L in rule 1 is the original List2, or [a,b,c].

             This example would not have worked if the order of rules one
        and  two  were  reversed.  The  PROLOG  inference  engine  always
        attempts to use the the first rule encountered. You could imagine
        it as always reading your program from the top down in attempting
        to  find an appropriate rule.  Since rule 2 would always satisfy,
        an  unpleasant  thing  would  have happened  if  the  order  were
        reversed. The program would loop forever.



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

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

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

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


                                       49










        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













































                                       50







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