Differences between Algernon v3 and previous versions

This document summarizes changes in Algernon v3.

No tty-level interface

  Algernon v3 has no "(algy)" interface function through which the
  user can access the KB.  Instead, the user should use the Amaze
  graphical interface (by running "(amaze)"), or display information
  as shown below:

    display an object:   (tell '((:show object-name)))

    trace:  (algy-trace), (algy-trace-rule), (algy-untrace-rule)

  One of the few remaining commands is (acom-reset), which will
  reinitialize the knowledge base.

New trace commands

  In Algernon v3, one can trace at different levels of detail
  or trace only certain rules.

  (algy-trace level)   - Sets the trace level.  Default is 1.

                           0: no tracing
			   1: normal operation success/failure
			   2: extended trace - shows rules being activated and executed
			 3-4: for Algernon internal development use
			  -1: timing information for Algernon development use

  (silently body)        A macro to set trace level to 0 while the forms in the body
                        are executing.

  (find-rule rule-key)   Displays the name of the rule with the given key.
                       The key is the first clause of the antecedent for
                       if-added rules, and the first clause of the consequent
                       for if-needed rules.

  (algy-trace-rule rule-name)    Sets trace level 2 while the rule is executing.
  (algy-untrace-rule rule-name)  Removes any special tracing for a rule.

  (algy-untrace)  Removes all rule tracing and sets the trace level to 1.

Binding environment of variables

  When processing paths containing :A, :THE and :FORC variables,
  only the primary variable of the form is visible outside of
  the clause.  For example:

   ((near Me ?you)
    (:A  ?thing 
         (near   ?you ?thing)         ;; nested environment, so ?you is visible
         (beside ?you ?something)     ;; ?something is only visible in :A form
    (around ?you ?thing)              ;; legal
    (around ?you ?something)          ;; Illegal

:A syntax changed

  :A no longer accepts multiple assignment variables as in
     (:A  (?var1 ?var2) (...))

  Instead, it accepts only one variable, and the variable may
  optionally be specified as a member of a set.

     (:A  ?var  (...))   or   (:A  (?var set)  (...))

  For example,

     (:A ?rover (name ?rover "Rover") (isa ?rover Dogs) (...other forms...))

  is now more concisely

     (:A (?rover Dogs) (name ?rover "Rover") (...other forms...))

     - creates a new frame with the name "Rover"
     - binds the ?rover variable to the new frame
     - asserts a member link from Dogs to the new frame
     - processes the other forms in the :A clause


  :NO-CONTINUATION has been added as a synonym for :NO-COMPLETION.

  What were formerly called rule completions are now
  called rule continuations, so the commands to
  suppress continuations have also changed.  In addition to
  is available to suppress continuations in all clauses of a rule.

Compiling multiple versions of if-needed rules

  When compiling an if-needed rule such as:
     ((rel ?x ?y ?z) <- (...) (...))

  it is unknown at compile time which of the variables ?x, ?y and ?z
  will be bound at rule activation time.  The compiled code generated
  for a specific instruction often depends on whether a variable is 
  known to be bound.  To handle this, the compiler generates several
  versions of the compiled form of the rule for various sets of bound
  variables.  If, at runtime, it runs into a bound/unbound variable
  configuration that it did not anticipate, it will compile yet another
  version of the rule (compilation is nearly instantaneous).

  Since the user may never intend for certain configurations
  of unbound variables to occur, the compiler may generate 
  "path restriction" warnings during compilation of these
  alternate rule forms.  These messages are sometimes spurious, but
  may also be genuine, so the programmer is encouraged to read the
  warning messages closely.

  The warning messages list the rule and the variable configuration
  under which the rule was compiled.  For example:

  * Algernon Compilation Warning 
  * :PATH-RESTRICTION warning in clause (R2 ?W Widget) of rule RULE26-?X-?Y-?Z
  * the rule being compiled may be incorrect.

  This message states that RULE26 was being compiled in the mode where
  the three variables {?x, ?y, ?z} were bound.  Note that the warning is 
  about variable ?W, which is not listed in the set of bound variables.  
  If the given configuration of bound variables never occurs during a
  program run, the warning can be ignored.

Disjoint taxonomic subsets

  Sibling subsets of a taxonomy are now declared disjoint, and 
  assigning an instance to one of the subsets now causes it to
  be declared as "not an instance" of the other subsets.

  For example, (deftaxonomy  (physical-objects
                                  (Dogs  Rover)
                                  (Cats  Sam))))


     (isa Rover Dogs)
     (not (isa Rover Cats))
     (isa Sam Cats)
     (not (isa Sam Dogs))

  You may set the variable *use-disjoint-rule* to NIL to turn this off.
  Turning it off causes KBs to load a lot faster.

New :FIRE command

(:FIRE <clause>) will fire if-added rules as if the clause
had been asserted.  This is dangerous, since the system doesn't
verify that the clause is actually in the system.  An inconsistent
knowledge base could result.

New :STOP command

(:STOP) will halt execution and return to the user level.

 It is useful when searching for just one solution or when errors are detected.

Constrained rule activation

Given a query:  (rel ?x ?y ?y)   and rules of the form:

  ((rel ?a ?b ?c) <- ...))

there is a question of whether the rule should be constrained
at activation time so that ?b and ?c have the same value. 
In Algernon v1 and v2, the rule executes unconstrained and the
returned values are filtered ex post facto.  

In Algernon v3, the rule is constrained at activation time
and will execute as though its consequent is (rel ?a ?b ?b).

This is implemented by substituting dummy variables into
the executing rule.  The user may encounter these dummy
variables if they fall into the debugger.

Compile-time slot type checking

Algernon checks every slot reference for correct argument types.
Algernons v1 and v2 do this at runtime.  Algernon v3 does it 
when compiling each rule or path.  This provides for faster
runtime and earlier detection of errors.

However, this means that the KB components should be defined
in the following order:

  1) taxonomy
  2) slots
  3) rules

The compiler propagates types by inferring a variable's type at its first
reference, and then assuming that type for all subsequent references.
The first reference in a rule may be the first clause of the consequent 
(for if-needed rules) or the first clause of the antecedent (for
if-added rules).  

Subclasses are supported.  For example, if the first reference of
a variable gives it the type 'DOGS', then a subsequent reference
that requires a type of 'MAMMALS' would be allowed (assuming the
taxonomy defines a subclass relationship between DOGS and MAMMALS).
However, the reverse would not be allowed.  This is equivalent to 
the type propagation allowed in O-O languages like C++.

Does not assert types of slot values

In earlier versions of Algernon, asserting a value into a slot 
would also automatically assert an ISA relationship between the 
value and the type of that slot position.  For example, the

   (:slot  pet  (Humans Animals))

and the assertion:

   (pet Fred Rover)

would automatically assert:

   (isa Fred  Humans)
   (isa Rover Animals)

Over the course of a long run, these assertions were performed
repeatedly, and were wasteful in terms of the computation they
required.  Algernon v3 no longer makes these automatic assertions.

Algernon performs compile-time type checking on the arguments of 
slots to ensure that they are consistent within the body of each rule,
but the programmer must ensure run-time consistency of the KB.

Automatic type restriction at compile time

Occasionally an Algernon user will write a rule
in which a frame is retrieved using a slot with
a general type (such as THINGS), but used later
in the rule in a slot with a more specific type
(such as DOGS).  Algernon does not normally allow
this, because the more specific type can not
be guaranteed by the compiler.  So at compile-time
the compiler would generate spurious and annoying
warning messages when compiling such a rule.

In AAM v4.6, the user can now specify (both at
compile-time and run-time) that a variable
is of a more restricted type.  This is done by
including an ISA or MEMBER clause before using
a slot with the more restricted type.


  (:slot part-of Things (Things))
  (:slot paint-parts-of-car Cars         (Colors))
  (:slot paint-engine-part  Engine-Parts (Colors))

  ;; rule specifically for car engine parts
  ((paint-engine-parts ?car ?color)
   (part-of ?car ?engine-part)
      ;; type(?engine-part) == Things
   (isa ?engine-part Engine-Parts)
      ;; Now type(?engine-part) == Engine-Parts
   (paint-engine-part ?engine-part ?color)

The new type must be a sub-type of the old type.  

KB statistics

The function ALGY-STATS will retrieve
and optionally print the number of frames and
relations in the KB.

New algy-save function

The function (ALGY-SAVE frames filename) will 
save the specified frames to the file.  The information on
the file consists of Algernon TELL commands that
will recreate the frames in the state they existed at the
time of the save.  It will save the slot-values of frames, slots, 
and rules.  It saves only the VALUE and NOT-VALUE facets of slots.

At this time, it does not save all the necessary information about rules (because it is not available). If you save rules to the file, you will need to hand-edit the file before loading it again. Search for '???' in the file.

ALGY-SAVE is new in version 3.0.1.

[Algernon v3 home]

This page was created by

Micheal Hewett