.c	Saturday  April 16,1983  19:31  NM+4D.10H.19M.33S.  -*- Bolio -*-


.chapter "Peripheral Utilities"

This chapter will accumulate documentation on various minor utilities
which are distributed with lan{nil}, but which are not necessarily
part of lan{nil} proper.

.section "The Predicate Simplifier"

lan{Nil} offers a predicate simplifier, which simplifies
lan{lisp}-format predicates into disjunctive normal form.  This
program was originally written by Deepak Kapur with the help of Ramesh
Patil for the lan{protosystem} automatic programming project
directed by William Martin at MIT in the mid 1970s.  Since then, it
has been converted to use lan{lsb} ref{LSBman}, brought up in both
lan{zetalisp} and lan{nil}, and improved at a low level.  The code
for this is not loaded by default in lan{nil};  it exists as
7nil$disk:[nil.utilities]simp*, and to load it, the package
definition file 7nil$disk:[nil.utilities]simp.pkg* should be
loaded first.  This may be performed automatically by use of
.lisp
(require 'simp)
.end_lisp
See 3require*, (require-fun).

This simplifier only really works on simple predicates and
connectives.  It performs some trivial canonicalizations of arithmetic
operations and inequalities (3equal*, 3greaterp*, and
3lessp*), but it does not truly recognize identities or other
relations among them.  There is also a read-time (compile-time)
conditionalization for whether it attempts to deal with existential
quantification, as represented by forms of the form
.lisp
(for-some (2k1* 2k2* ... 2kn*) 2pred*)
.end_lisp
This feature is normally turned off, which simplifies the internal
datastructures used and improves the efficiency in the other cases.
Again, simplification of forms containing existential quantification
does not always reduce as well as it should.  To get this one would
have to recompile 3simp* with that feature turned on.

.defun simp pred-form
Simplifies 2pred-form*.  For example,
.lisp
(simp '(and c d (or a b)))  =>  (or (and a c d) (and b c d))
.end_lisp
.end_defun

.defun simpor p1 p2
.defun1 simpand p1 p2
Approximately equivalent to
.lisp
(simp (list 3and-2or*-or* 2p1* 2p2*))
.end_lisp
.end_defun

.defun simpnot pred
Simplifies the 2not* of 2pred*.
.end_defun

.defun simporlist pred-list
.defun1 simpandlist pred-list
Simplifies the 3or* or 3and* of 2pred-list*.
.end_defun

.defun *simpor p1 p2
.defun1 *simpand p1 p2
2p1* and 2p2* must already be in disjunctive normal form,
i.e., already simplified (as returned by some simplification call).
This is faster than using 3simpor* or 3simpand*.
.end_defun

.defun *simporlist pred-list
.defun1 *simpandlist pred-list
Simplifies the 3or* or 3and* of the predicates in
2pred-list*, which must be already simplified.
.end_defun

.defun *simpnot pred
Simplifies the 3not* of 2pred*, which must be already
simplified.
.end_defun

There is also a hack for doing both uniquizing of predicates returned,
and also "atomizing", associating an atomic symbol with a predicate
(which will be expanded out in subsequent simplification).  The former
was important in the lan{pdp-10 maclisp} version when large
databases associating predicates with probabilities were in use.  See
the source code if either of these are desired.


.section "A Mini-MYCIN"

This is a small production rule system upon which class projects
in the MIT course 6.871 were implemented. Some students in the course
taught this term by Prof. Peter Szolovits and Dr. Ramesh Patil used
this code in lan{nil}. The directory 7NIL$DISK:[MYCIN]* has what
the students got to start with. This is more of an example lisp
program than it is a utility. Here is part of a script of a run of
the test example:

.lisp
(load "nil$disk:[mycin]loader")
(load-mycin)
Indeterminate context: RULE4 flushed.
Type (return t)
;bkpt ERROR
1>break>(return t)
Indeterminate context: RULE5 flushed.
Type (return t)
;bkpt ERROR
1>break>(return t)
(run)
Creating new context node: PERSON-2
.end_lisp

The files 7GOBBLE.LSP* and 7MYCINF.LSP* are the basic system, upon which
students built sets of rules to do something useful or interesting.
The example above, from 7MYCINT.LSP* is not interesting, just (barely)
illustratory. 7TAXAID.LSP* has a completed project a student did in
1980. 

.section "Maclisp Compatibility for Macsyma"

The directory 7NIL$DISK:[MACSYMA]* has some code in that is used for
compiling and running lan{macsyma} in lan{nil} and that will be useful
to anyone porting a lan{maclisp} program.

The file 7ALOAD.LSP* has an autoloading handler that works by handling the
3:undefined-function* error condition. This might be a generally
useful thing to have around.

The file 7PKGMC.LSP* illustrates the use of 3pkg-create-package*
and 3intern-local* in order to build a namespace that shadows
conflicting or incompatibly defined functions and variables.

The file 7NILCOM.LSP* gives definitions of the functions 3map*,
3subst*, 3member*, and 3assoc*, which are compatible
with lan{maclisp}.

.section "Graphics Utilities"

Streams supporting elementary 2d and 3d graphics operations and
device-dependant interface streams are provided in the directory
7NIL$DISK:[GRAPHICS]*. To call these functions
load the file 7NIL$DISK:[GRAPHICS]LOADER*. The functionality
provided here is simple and powerful
and has been used to support
a number of scientific programming applications, including a data
acquisition system in the lan{Maclisp} incarnation of the code.
The names and choice of operations follow commonly used conventions.

The way it works is to compose at runtime streams which implement
higher level operations in terms of lower level ones. For example, to
get a stream which supports 3-d operations to a Tektronics compatible
terminal we evaluate:
.lisp
(MAKE-ZCLIP-STREAM
 (MAKE-ORTHAGONAL-3D-STREAM
  (MAKE-GRAPHICS-STREAM
   (MAKE-TEK-STREAM
    TERMINAL-IO))))
.end_lisp
In order to send the same output to a file and a terminal at the same time we
might use this construct:
.lisp
(MAKE-ZCLIP-STREAM
 (MAKE-ORTHAGONAL-3D-STREAM
  (MAKE-GRAPHICS-STREAM
   (MAKE-TEK-STREAM
    (MAKE-BROADCAST-STREAM TERMINAL-IO (OPEN "PLOT.DAT" :OUT))))))
.end_lisp
To have two simultaneous but differently configured window/viewport
streams to the same terminal we might say:
.lisp
(LET ((S (MAKE-TEK-STREAM TERMINAL-IO)))
  (SET-VIEWPORT (setq *window-1 (MAKE-GRAPHICS-STREAM S))
		10 10 700 300))
  (SET-VIEWPORT (SETQ *WINDOW-2 (MAKE-GRAPHICS-STREAM S))
		10 310 700 700)))
.end_lisp
Or two different devices
.lisp
(MAKE-GRAPHICS-STREAM
 (MAKE-GRAPHIC-DEVICE-BROADCAST-STREAM
  (MAKE-TEK-STREAM TERMINAL-IO)
  (MAKE-GIGI-STREAM (OPEN "TTA2:" :OUT))))
.END_LISP
However, that would not work, boundaries message incompatibility is
detected. Must split using MAKE-GRAPHICS-BROADCAST-STREAM on two
instances of the GRAPHICS-STREAM type.

Obviously useless combinations are detected, but we do not attempt
to put forth a complete theory of these objects and deal with all
manner of protocal between the streams.

**BLA Say something about: using steve and graphics and echo-area-stream
in combination.

.subsection "Device Dependant"
.defun make-tek-stream substream
sends :write-char :write-raw-char to substream.
.end_defun
.defun make-gigi-stream substream
.end_defun

.subsection "2 dimension"
.defun make-graphics-stream substream
Makes a stream that does floating-point scaling and clipping, using
a window and a viewport.
.end_defun

.subsection "generic"
.defun draw-line stream x1 y1 x2 y2
Sends the :DRAW-LINE message to the stream. If X1 is a sequence (a
list or a vector) then it maps over them elements sending the :DRAW-LINE
message.
.end_defun

.subsection "3d operations"
.defun make-zclip-stream
.end_defun
.defun make-3d-orthogonal
.end_defun

.subsection "related issues"

.defun make-echo-area-stream &key :row :lines
.end_defun

May then do
.lisp
(defparameter *echo-area* (make-echo-area :row 10 :lines 3))
(read-with-prompt ">")
.end_lisp
.defmac plot
extremely simple.
.end_defmac

*BLA. Example with two plot windows, an echo area, reading commands
in macsyma-like syntax using PARSE.VAS

