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.
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.
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 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...)) which: - 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:NO-CONTINUATION
, the macroWITH-NO-CONTINUATIONS
is available to suppress continuations in all clauses of a rule.
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.
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 (animals (Dogs Rover) (Cats Sam)))) asserts: (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.
(: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.
(:STOP) will halt execution and return to the user level. It is useful when searching for just one solution or when errors are detected.
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.
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++.
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: (: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.
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. Example: (: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.
The function ALGY-STATS
will retrieve
and optionally print the number of frames and
relations in the KB.
algy-save
functionThe function(ALGY-SAVE frames filename)
will save the specified frames to the file. The information on the file consists of AlgernonTELL
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.
This page was created by
Micheal Hewett