{"id":24746837,"url":"https://github.com/nilqed/lisa-rules","last_synced_at":"2026-01-05T21:02:48.923Z","repository":{"id":269826003,"uuid":"908577363","full_name":"nilqed/lisa-rules","owner":"nilqed","description":"Lisa is a production rule system for Common Lisp, whose purpose is to provide a foundation for the development of \"intelligent\" applications. Lisa employs a modern CLOS implementation of Rete and is based on CLIPS and Jess.","archived":false,"fork":false,"pushed_at":"2024-12-26T12:48:45.000Z","size":281,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-23T01:28:40.505Z","etag":null,"topics":["clips-rules","common-lisp","forward-chaining","production-system","rete-algorithm"],"latest_commit_sha":null,"homepage":"","language":"Common Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-2.1","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nilqed.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-12-26T12:14:16.000Z","updated_at":"2024-12-26T13:04:43.000Z","dependencies_parsed_at":"2025-01-21T15:15:13.611Z","dependency_job_id":null,"html_url":"https://github.com/nilqed/lisa-rules","commit_stats":null,"previous_names":["nilqed/lisa-rules"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/nilqed/lisa-rules","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nilqed%2Flisa-rules","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nilqed%2Flisa-rules/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nilqed%2Flisa-rules/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nilqed%2Flisa-rules/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nilqed","download_url":"https://codeload.github.com/nilqed/lisa-rules/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nilqed%2Flisa-rules/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28218585,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2026-01-05T02:00:06.358Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clips-rules","common-lisp","forward-chaining","production-system","rete-algorithm"],"created_at":"2025-01-28T04:35:07.029Z","updated_at":"2026-01-05T21:02:48.889Z","avatar_url":"https://github.com/nilqed.png","language":"Common Lisp","funding_links":[],"categories":[],"sub_categories":[],"readme":"This is a *fork* of the LISA system by David E. Young from https://lisa.sourceforge.net/.\n\nSome comments at the end of this README ..\n\nThe LISA Reference Guide\n------------------------\n\nThis guide describes in detail the programming interface to LISA. It is\n*not* a treatise on production-rule technology; readers are assumed to\nhave a working knowledge of rule-based systems and their development.\nThis document also avoids any detailed description of LISA's\nimplementation of the Rete algorithm; perhaps at some future date I'll\nmake an attempt.\n\nAbbreviated Table of Contents\n-----------------------------\n\n| `The Programming Language \u003c#The%20Programming%20Language\u003e`__\n| `The Environment \u003c#The%20Environment\u003e`__\n| `Contexts \u003c#Contexts\u003e`__\n| `Dynamic Rule Definition \u003c#Dynamic%20Rule%20Definition\u003e`__\n| `Queries \u003c#Queries\u003e`__\n| `Conflict Resolution \u003c#Conflict%20Resolution\u003e`__\\ `\n  The LISA Debugger\n   \u003c#The%20LISA%20Debugger\u003e`__\\ `Auto Notification \u003cauto-notify.html\u003e`__\n| `Getting Started \u003c#Getting%20Started\u003e`__\n| `Things Yet to Do \u003c#Things%20Yet%20to%20Do\u003e`__\n| `Supported Platforms \u003c#Supported%20Platforms\u003e`__\n|  \n\nI. The Programming Language\n~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThis section describes the publicly-available operators in the LISA\nlanguage, separated into various categories:\n\n   `Fact-Related Operators \u003c#Fact-Related%20Operators\u003e`__\n\n      Language elements dealing with facts.\n\n   `Rule-Related Operators \u003c#Rule-Related%20Operators\u003e`__\n\n      Language elements dealing with rules.\n\n   `CLOS-Related Operators \u003c#CLOS-Related%20Operators\u003e`__\n\n      Language elements dealing with CLOS instances.\n\n   `Engine-Related Operators \u003c#Engine-Related%20Operators\u003e`__\n\n      Language elements dealing with operations on an inference engine.\n\n   `Environment-Related Operators \u003c#Environment-Related%20Operators\u003e`__\n\n      Language elements dealing with the LISA environment.\n\n   `Debugging-Related Operators \u003c#Debugging-Related%20Operators\u003e`__\n\n      Language elements useful during system development.\n\nFact-Related Operators\n^^^^^^^^^^^^^^^^^^^^^^\n\n \n\n======================================= =====\n(deftemplate *name* () (*slot-name\\**)) Macro\n======================================= =====\n\n..\n\n   Creates an internal LISA class identified by *name* that can be\n   instantiated as a fact within the knowledge base. The *slot-name*\\ s\n   are analogous to class slots, but without any of the keyword\n   arguments. Templates are a convenient way of specifying concepts that\n   don't need the full support of CLOS, but frankly they're really only\n   in place to ease the transition from CLIPS and Jess. \n\n======================== =====\n(defimport *class-name*) Macro\n======================== =====\n\n..\n\n   A convenience macro that imports the symbols associated with a class\n   into whatever LISA-related package the developer wishes. The symbols\n   imported reflect the name of the class name and all of its immediate\n   slots. If taxonomic reasoning is enabled, then the class's ancestors\n   are imported as well.\n\n===================================================== =====\n(deffacts *deffact-name* (*key*\\ \\*) *fact-list*\\ \\*) Macro\n===================================================== =====\n\n..\n\n   Registers a list of facts that will be automatically inserted into\n   the knowledge base upon each RESET. The *deffact-name* is the\n   symbolic name that will be attached to this group of facts;\n   *fact-list* is a list of fact specifiers. The format of each fact\n   specifier is identical to that found in an ASSERT form, minus the\n   *assert* keyword. There are currently no supported keywords for this\n   macro.\n\n=========================== =====\n(assert (*fact-specifier*)) Macro\n=========================== =====\n\n..\n\n   Inserts a fact identified by *fact-specifier* into the knowledge\n   base. There are two forms of ASSERT; the first operates on\n   template-based facts, the other on CLOS instances. For templates,\n   ASSERT takes a symbol representing the name of the template, followed\n   by a list of (*slot-name value*) pairs:\n\n   (assert (frodo (name frodo) (age 100))\n\n   If the template associated with a fact has not been declared prior to\n   its assertion, LISA will signal a continuable error.\n\n   For instances of user-defined classes, ASSERT takes a form that must\n   evaluate to a CLOS instance:\n\n   (assert ((make-instance 'frodo :name 'frodo :age 100)))\n\n   or:\n\n   (let ((?instance (make-instance 'frodo :name 'frodo)))\n\n       (assert (?instance)))\n\n   or:\n\n   | (defun add-my-instance (frodo-object)\n   |   (assert (#?frodo-object)))\n\n   This last example makes use of the #? reader macro, which LISA offers\n   as a user-customisable feature. It's simply a short-hand notation for\n   *(identity frodo-object)*.\n\n============================ ========\n(retract *fact-or-instance*) Function\n============================ ========\n\n..\n\n   Removes a fact or instance from the knowledge base. In the case of a\n   template-based fact, *fact-or-instance* may be either a symbol\n   representing the name of the fact, or an integer mapping to the fact\n   identifier; for CLOS objects *fact-or-instance* must be an instance\n   of STANDARD-OBJECT.\n\n============================ ========\n(assert-instance *instance*) Function\n============================ ========\n\n..\n\n   Inserts a CLOS instance into the knowledge base.\n\n============================= ========\n(retract-instance *instance*) Function\n============================= ========\n\n..\n\n   Removes a CLOS instance from the knowledge base.\n\n===================================== =====\n(modify *fact* (*slot-name value*)\\*) Macro\n===================================== =====\n\n..\n\n   Makes changes to the fact instance identified by *fact*. Affected\n   slots and their new values are specified by (*slot-name value*). Note\n   that *value* can be an arbitrary Lisp expression that will be\n   evaluated at execution time.\n\nRule-Related Operators\n^^^^^^^^^^^^^^^^^^^^^^\n\n \n\n================================================ =====\n(defrule *name (key\\*) pattern\\** =\u003e *action\\**) Macro\n================================================ =====\n\n..\n\n   Creates a rule identified by *name* and compiles it into the Rete\n   network. *Name* is any Lisp form that evaluates to a symbol. The\n   keyword arguments modify the rule as follows:\n\n   ::\n\n      :salience integer\n\n   ..\n\n      Assigns a priority to the rule that will affect the firing order.\n      The salience value is a small integer in the range (-250, 250). By\n      default, all rules have salience 0.\n\n   ::\n\n      :context name\n\n   ..\n\n      Binds the rule to a context identified by the symbol *name*. The\n      context must have been previously defined, or LISA will signal an\n      error.\n\n   ::\n\n      :auto-focus t\n\n   ..\n\n      Identifies the rule as requiring \"auto focus\" behavior. This means\n      that whenever the rule is activated, its context will be made the\n      active context after the rule firing completes.\n\n   If the rule identified by *name* already exists in the Rete network\n   it is replaced by the new definition.\n\n   .. rubric:: Patterns\n      :name: patterns\n\n   Each rule consists of zero or more *pattern*\\ s, or Conditional\n   Elements (CEs). Collectively these patterns are known as the rule's\n   Left Hand Side (LHS), and are the entities that participate in the\n   pattern-matching process. LISA currently defines three pattern types:\n\n   ::\n\n      generic pattern\n\n   ..\n\n      This pattern type matches against facts in the knowledge base. The\n      head of the pattern matches equivalently-named facts; the pattern\n      body is optionally composed of slot-names, values, variables and\n      predicates. The best way to understand these things is to look at\n      some examples:\n\n      ::\n\n         (simple-pattern)\n\n      ..\n\n         The simplest type of pattern. This example will match any fact\n         of class *simple-pattern*.\n\n      ::\n\n         (goal-is-to (action unlock))\n\n      ..\n\n         This pattern matches facts of class *goal-is-to*. In addition,\n         it specifies that the slot named *action* must have as its\n         value the symbol *unlock*.\n\n      ::\n\n         (thing (name ?chest) (on-top-of (not floor)))\n\n      ..\n\n         A bit more interesting. Matches facts of class *thing*;\n         assuming this is the first appearance of the variable *?chest*,\n         binds it to the value of the slot *name*; specifies that the\n         slot *on-top-of* should not have as its value the symbol\n         *floor*.\n\n      ::\n\n         (?monkey (monkey (holding ?chest)))\n\n      ..\n\n         Assuming the variable *?chest* was bound in a previous pattern,\n         matches facts of class *monkey* whose slot *holding* has the\n         same value as *?chest*. Additionally, if the pattern is\n         successfully matched, binds the fact object to the variable\n         *?monkey*. The variable *?monkey* is called a *pattern\n         binding*.\n\n      ::\n\n         (pump (flow-rate ?flow-rate (\u003c ?flow-rate 25)))\n\n      ..\n\n         More interesting still. This pattern matches facts of class\n         *pump*, and binds the value of the slot *flow-rate* to the\n         variable *?flow-rate*. In addition, there is a constraint on\n         this slot declaring that the value of *?flow-rate* must be less\n         than 25. In general, constraints can be arbitrary Lisp\n         expressions that serve as predicates.\n\n      ::\n\n         (fact-with-list (list '(1 2 three)))\n\n      ..\n\n         Patterns can perform matching on lists as well as simpler data\n         types. Here, the slot *list* must have the value *'(1 2\n         three)*. More complicated list analysis can be done using\n         user-defined predicates.\n\n   ::\n\n      negated pattern\n\n   ..\n\n      This pattern type is the complement of most variations of the\n      generic pattern. Negated patterns have the symbol *not* as their\n      head, and match if a fact satisfying the pattern is *not* found.\n      For example:\n\n      ::\n\n         (not (tank-level-warning (tank ?tank) (type low)))\n\n      Note that negated patterns are not allowed to have pattern\n      bindings.\n\n   ::\n\n      test pattern\n\n   ..\n\n      The *test* conditional element allows one to evaluate arbitrary\n      Lisp code on the rule LHS; these Lisp forms serve as a predicate\n      that determines whether or not the pattern will match. For\n      example, the pattern\n\n      ::\n\n         (test (and (high-p ?tank) (intact-p ?tank)))\n\n      will succeed if the AND form returns non-*nil*; i.e. the functions\n      HIGH-P and INTACT-P both return non-*nil* values.\n\n   ::\n\n      or pattern\n\n   ..\n\n      The *or* conditional element collects any number of patterns into\n      a logical group, and matches if any of the patterns inside the\n      *or* match. If more than one of the sub-patterns matches, the *or*\n      group matches more than once. LISA implements a rule containing an\n      *or* CE as a collection of related rules, with each rule\n      representing exactly one branch. For example, given the following\n      DEFRULE form:\n\n      (defrule frodo () \n\n          (frodo) \n\n          (or (bilbo) \n\n               (gandalf)) \n\n          (samwise)\n\n      =\u003e)\n\n      LISA will generate two rules into the rete network, a primary rule\n      and a single sub-rule:\n\n         ::\n\n            frodo: (frodo), (bilbo), (samwise)\n\n         ::\n\n            frodo~1: (frodo), (gandalf), (samwise)\n\n      Notice that LISA separates the example DEFRULE into the primary\n      rule *frodo*, and a single sub-rule, *frodo~1*. LISA maintains the\n      relationship between a primary rule and its sub-rules; if a\n      primary rule is removed, every related sub-rule is also\n      eliminated.\n\n   ::\n\n      logical pattern\n\n   ..\n\n      The *logical* conditional element implements LISA's notion of\n      truth maintenance. Patterns appearing within a LOGICAL form in a\n      rule are conditionally bound to facts asserted from that rule's\n      RHS. If during inferencing one or more logical facts are retracted\n      (or asserted in the case of negated patterns), all facts bound to\n      those logical facts are retracted. Here's an example:\n\n      (defrule frodo ()\n\n          (logical \n\n            (bilbo) \n\n            (not (gandalf)))\n\n                    (frodo)\n\n      =\u003e\n\n      (assert (pippin)))\n\n      When rule FRODO fires, it asserts a PIPPIN fact that is dependent\n      on the existence of BILBO and the absence of GANDALF. If either\n      BILBO is retracted or GANDALF asserted, PIPPIN will be removed as\n      a consequence.\n\n      A LOGICAL conditional element must be the first pattern in a rule.\n      Multiple LOGICAL forms within the same rule are allowed, but they\n      must be contiguous.\n\n      **NB**: A rule beginning with the LOGICAL conditional element\n      implicitly matches the INITIAL-FACT; thus, in order for rules\n      employing truth maintenance to function correctly, a RESET must be\n      always be performed prior to any operation affecting working\n      memory. LISA's behavior is undefined otherwise.\n\n   ::\n\n      exists pattern\n\n   ..\n\n      The EXISTS conditional element performs an existential test on a\n      pattern. The pattern will match exactly once, even if there are\n      many facts that might satisfy it. For example, this rule:\n\n      | (defrule frodo ()\n      |     (exists (frodo (has-ring t)))\n      |     =\u003e)\n\n      will activate just once if there is at least one FRODO fact whose\n      HAS-RING slot has the value T.\n\n   ::\n\n      The initial fact\n\n   If a rule provides no conditional elements, then it is said to match\n   the *initial-fact*, which is asserted as the result of a call to\n   *reset*. Thus, the following rule will always activate after each\n   reset:\n\n   (defrule always-fires ()\n\n      =\u003e\n\n      (format t \"always-fires fired!~%\"))\n\n   ::\n\n      CLOS instances\n\n   Every fact asserted into working memory is backed by a corresponding\n   CLOS instance. In the case of DEFTEMPLATEs, LISA creates an internal\n   class mirroring the template; user-defined class instances are simply\n   bound to a fact during assertions. Instances associated with facts\n   are accessible on rule LHSs via the :OBJECT special slot:\n\n   (tank (name ?name) (:object  ?tank-object))\n\n   Once bound, method and function calls can be made on this object from\n   the rule's LHS and RHS.\n\n   | When reasoning over CLOS objects, LISA is capable of considering an\n     instance's object hierarchy during pattern matching. In other\n     words, it is possible to write rules that apply to many facts that\n     share a common ancestry. The following code fragment provides an\n     example:\n   |  \n\n   (defclass fundamental () ())\n\n   (defclass rocky (fundamental) ())\n\n   (defclass boris (fundamental) ())\n\n    \n\n    \n\n   (defrule cleanup (:salience -100)\n\n       (?fact (fundamental))\n\n        =\u003e\n\n       (retract ?fact))\n\n    \n\n   The rule *cleanup* will fire for every instance of *rocky* and\n   *boris* in the knowledge base, retracting each in turn. Note that\n   taxonomic reasoning is disabled by default. To use the feature,\n   evaluate (setf (lisa:consider-taxonomy) t).\n\n   .. rubric:: Actions\n      :name: actions\n\n   Following any conditional elements are the rule's actions, if any.\n   Collectively known as the Right Hand Side (RHS), actions consist of\n   arbitrary Lisp forms. All variables declared on the LHS are\n   available, along with the special operator *engine*, which evaluates\n   to the rule's inference engine object. Currently, each rule's RHS is\n   given to the Lisp compiler during rule compilation, and executes\n   within a special lexical environment established by LISA for each\n   firing.\n\n======================= =====\n(undefrule *rule-name*) Macro\n======================= =====\n\n..\n\n   Undefines, or removes, a rule from the Rete network. *Rule-name* is a\n   symbol representing the name of the rule. If *rule-name* is not\n   qualified with a context name (e.g. *context.rulename*), then the\n   Initial Context is assumed.\n\nCLOS-Related Operators\n^^^^^^^^^^^^^^^^^^^^^^\n\n| There are a few special features that LISA provides for keeping CLOS\n  instances synchronised with their corresponding facts in working\n  memory. If an instance is altered outside of LISA's control, then LISA\n  must somehow be informed of the change to maintain working memory\n  consistency. The basic mechanism is manual notification, in which an\n  application explicitly invokes a special function to initiate\n  synchronisation. Users of the two commercial Lisps supported by LISA\n  also have the option of employing `Auto\n  Notification \u003cauto-notify.html\u003e`__, an experimental feature that\n  removes the burden of synchronisation from the application.\n|  \n\n====================================================== ========\n(mark-instance-as-changed *instance* \u0026key *slot-name*) Function\n====================================================== ========\n\n..\n\n   Notifies LISA that a change has been made to *instance* outside of\n   the knowledge-base (i.e. not via the *modify* operator), and\n   synchronizes the instance with its associated fact. *Slot-name* is\n   either the symbolic name of a slot belonging to *instance* that has\n   changed value, or NIL (the default), in which case all slots are\n   synchronized. An application *must* call this method whenever a slot\n   change occurs outside of LISA's control.\n\nEngine-Related Operators\n^^^^^^^^^^^^^^^^^^^^^^^^\n\n| These operators provide an interface to instances of the inference\n  engine itself.\n\n================== ========\n(inference-engine) Function\n================== ========\n\n..\n\n   Evaluates to the currently active instance of the inference engine.\n\n======= ========\n(reset) Function\n======= ========\n\n..\n\n   Re-initializes the knowledge base, removing facts, clearing all\n   context agendas, and asserting the *initial-fact*.\n\n======= ========\n(clear) Function\n======= ========\n\n..\n\n   Re-initializes the LISA environment, mostly by creating a new\n   instance of the default inference engine.\n\n============================ ========\n(run \u0026optional *focus-list)* Function\n============================ ========\n\n..\n\n   Runs the inference engine, optionally pushing the context names on\n   *focus-list* onto the focus stack before doing so. Execution will\n   continue until either all agendas are exhausted or a rule calls\n   (halt).\n\n======================= ========\n(walk \u0026optional *step*) Function\n======================= ========\n\n..\n\n   Runs the engine in *step* increments, single-stepping by default.\n   Here, \"single-stepping\" means \"one rule at a time\".\n\n====== ========\n(halt) Function\n====== ========\n\n..\n\n   Halts the inference engine, even if the agendas still have\n   activations. Typically used only on rule RHSs.\n\nEnvironment-Related Operators\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n   These operators are used to manipulate and inspect the LISA\n   environment.\n\n============================================== =====\n(with-inference-engine (*engine*) *forms*\\ \\*) Macro\n============================================== =====\n\n..\n\n   Evaluates *forms* within the context of the inference engine\n   *engine*. Under most circumstances, use this macro in a\n   multi-processing environment to safely load a knowledge base into\n   *engine*.\n\n======================= ========\n(make-inference-engine) Function\n======================= ========\n\n..\n\n   Creates an instance of LISA's default inference engine.\n\n====== ========\n(rule) Function\n====== ========\n\n..\n\n   Within the context of an executing rule, returns the CLOS object\n   representing that rule.\n\n=================== ========\n(consider-taxonomy) Function\n=================== ========\n\n..\n\n   Returns the current setting for taxonomic reasoning. Use (setf\n   (consider-taxonomy) *value*) to change the setting. The default (NIL)\n   means LISA ignores class taxonomy during pattern matching.\n\n======================= ========\n(allow-duplicate-facts) Function\n======================= ========\n\n..\n\n   Returns the current setting for duplicate fact checking. Use (setf\n   (allow-duplicate-facts) *value*) to change the setting. By default,\n   LISA allows duplicate facts to be asserted. If checking is enabled\n   and an application attempts to assert a duplicate fact, LISA signals\n   a DUPLICATE-FACT error.\n\n================== ========\n(use-fancy-assert) Function\n================== ========\n\n..\n\n   Returns the current setting for fancy assertions. If enabled (the\n   default), the #? reader macro is installed in the global readtable.\n\nDebugging-Related Operators\n^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n| These operators are typically used interactively to inspect the state\n  of an inference engine. Some of these operators are only loosly\n  defined and need further work.\n|  \n\n======= ========\n(facts) Function\n======= ========\n\n..\n\n   Prints on *trace output* the contents of the active inference\n   engine's fact base.\n\n================================ ========\n(rules \u0026optional *context-name*) Function\n================================ ========\n\n..\n\n   Prints on *trace output* the contents of the active inference\n   engine's rule base. By default, all rules and all contexts will be\n   printed. If *context-name* is provided, then only those rules in that\n   context are printed.\n\n================================= ========\n(agenda \u0026optional *context-name*) Function\n================================= ========\n\n..\n\n   Prints on *trace output* the contents of the active inference\n   engine's agenda. By default, the agendas for all contexts will be\n   printed, unless *context-name* is supplied.\n\n=============== ========\n(watch *event*) Function\n=============== ========\n\n..\n\n   Asks LISA to report the occurrence of *event* to *trace output*.\n\n   Currently, LISA allows monitoring of these events:\n\n   ::\n\n      :facts\n\n   ..\n\n      Triggers an event each time a fact is asserted or retracted.\n\n   ::\n\n      :activations\n\n   ..\n\n      Triggers an event each time a rule is added to or removed from the\n      agenda.\n\n   ::\n\n      :rules\n\n   ..\n\n      Triggers an event each time a rule is fired.\n\n   ::\n\n      :all\n\n   ..\n\n      Watch all allowable events.\n\n================= ========\n(unwatch *event*) Function\n================= ========\n\n..\n\n   Disables the monitoring of *event*. See the documentation for *watch*\n   to see the allowable event types.\n\n========== ========\n(watching) Function\n========== ========\n\n..\n\n   Displays the list of events currently being monitored.\n\nII. The Environment\n~~~~~~~~~~~~~~~~~~~\n\nFor application developers, LISA makes available two different types of\nenvironments. Package LISA-USER contains all of LISA's exported symbols,\nplus those of COMMON-LISP. User-level work can safely be done in this\npackage. Alternatively, package LISA-LISP can be used with DEFPACKAGE\nforms to import a LISA environment into user-defined packages:\n\n   | (defpackage \"FRODO\"\n   |   (:use \"LISA-LISP\"))\n\nAs with LISA-USER, LISA-LISP exports all external symbols in the LISA\nand COMMON-LISP packages. See the various examples provided in\n\"lisa:misc;\".\n\nThere are a few aspects of LISA that may be customised prior to\nbuilding. The file \"lisa:src;config;config.lisp\" contains a set of\ndefault behaviors; feel free to edit this file to your liking.\n\nIII. Contexts\n~~~~~~~~~~~~~\n\nLISA contexts are a way of partitioning a knowledge base into distinct\ngroups of rules. The mechanism is similar to modules in CLIPS and recent\nversions of Jess, in that individual rule groups can be invoked\n\"procedurally\" without resorting to the use of control facts to\nmanipulate firing order. Contexts can also serve as an organizational\nconstruct when working with larger knowledge bases. Each context has its\nown agenda and conflict resolution strategy.\n\nEach inference engine instance created in LISA contains a default\ncontext, named \"The Initial Context\" (or INITIAL-CONTEXT). Unless\narrangements are made otherwise, all rules will reside in this context. \nThe DEFCONTEXT macro creates a new context; rules may then be loaded\ninto the new context by supplying the :CONTEXT keyword to DEFRULE.\nContexts serve as a form of namespace for rules; thus, it is legal for\nidentically named rules to reside in different contexts. Rules are\ndistinctly identified by qualifying the rule name with the context name;\nfor example, rule *wizards.gandalf* is a rule named *gandalf* that\nresides within the *wizards* context.\n\nActivations in the Initial Context are always available for firing.\nOtherwise, activations in other contexts will only fire if those\ncontexts are explicitly given control, via the FOCUS operator. Each\ninference engine maintains its own focus stack; before a new context is\ngiven control, the active context is pushed onto the focus stack. The\nREFOCUS operator may be used on a rule's RHS (or, perhaps,\ninteractively) to leave the active context and return control to the\nprevious context on the stack. Control automatically returns to the\nprevious context if the active context runs out of activations. When all\ncontexts have exhausted their activations, the inference engine halts.\n\nA rule can be tagged with the *auto-focus* attribute by supplying the\nAUTO-FOCUS keyword to DEFRULE. If an auto-focus rule activates, that\nrule's context is automatically pushed onto the focus stack and given\ncontrol when the rule completes its firing.\n\nNote carefully that while the *rules* in a knowledge base may be\npartitioned, there remains a *single working memory* per inference\nengine. At any given time, all facts in a knowledge base are visible to\nall rules in that knowledge base, regardless of context.\n\n=========================================== =====\n(defcontext *context-name* \u0026key *strategy*) Macro\n=========================================== =====\n\n..\n\n   Creates a new context identified by *context-name*, which must be a\n   string designator. If *strategy* is non-NIL then it must be an object\n   implementing a suitable conflict resolution strategy.\n\n============================= =====\n(undefcontext *context-name*) Macro\n============================= =====\n\n..\n\n   Destroys the context identified by *context-name*, which must be a\n   string designator. All rules bound to the context are removed from\n   the Rete network, along with their activations, if any.\n\n============================= =====\n(focus \u0026rest *context-names*) Macro\n============================= =====\n\n..\n\n   If *context-names* is non-NIL, it should be a collection of context\n   names that will be added to the focus stack. Contexts are pushed onto\n   the focus stack in right-to-left order. If no names are specified,\n   then FOCUS returns the active context object.\n\n========= =====\n(refocus) Macro\n========= =====\n\n..\n\n   Activates the next available context.\n\n============= =====\n(focus-stack) Macro\n============= =====\n\n..\n\n   Returns the inference engine's focus stack.\n\n========== =====\n(contexts) Macro\n========== =====\n\n..\n\n   Returns a list of all the inference engine's defined contexts.\n\n====================================== =====\n(with-context (*context* \u0026body *body*) Macro\n====================================== =====\n\n..\n\n   Evaluates the forms contained in *body* within the context *context*.\n\nIV. Dynamic Rule Definition\n~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n| In addition to statically declared rules, LISA supports the definition\n  of rules at runtime. That is, it is possible to create new rules from\n  the RHSs of existing rules as they fire. These *dynamically defined*\n  rules become immediately available to the inference engine for\n  potential activation. As a simple example, consider the following\n  rule:\n\n   (defrule rocky ()\n     (rocky (name ?name))\n     =\u003e\n     (defrule boris ()\n       (boris (name ?name))\n       =\u003e\n       (format t \"Dynamic rule BORIS fired; NAME is ~S~%\" ?name)))\n\nWhen rule ROCKY fires, its RHS creates a dynamically defined rule named\nBORIS. This new rule is inserted into the inference engine and\nimmediately becomes part of the Rete network. Variables bound on the LHS\nof ROCKY behave as expected within the context of BORIS; this means that\n?NAME in BORIS is bound to the same object as that found in\nROCKY\\ :sup:`\\*`.\n\nHere's a more complicated example:\n\n   (defrule rocky ()\n     (rocky (name ?name))\n     =\u003e\n     (let ((dynamic-rule\n                (defrule (gensym) ()\n                  (boris (name ?name))\n                  =\u003e\n                  (format t \"Dynamic rule ~A fired; name is ~S~%\"\n   (get-name (rule)) ?name))))\n       (format t \"Rule ROCKY added dynamic rule ~A~%\" (get-name\n   dynamic-rule))))\n\nAs before, rule ROCKY creates a dynamic rule when fired. However, this\ntime the new rule is given a unique name by evaluating the form\n(GENSYM); either the name or the instance can then be remembered for use\nlater. These two rules also introduce functions in the LISA API for\nretrieving both the currently executing rule and its name (RULE and\nGET-NAME, respectively).\n\n:sup:`\\*` Actually, this isn't precisely true. Whenever LISA encounters\na dynamic rule during parsing it looks at all the rule's variables and\nsubstitutes any bound values. Thus, in rule BORIS the variable ?NAME\nwould be replaced by the value of ?NAME as bound in rule ROCKY.\n\nV. Queries\n~~~~~~~~~~\n\nAs of LISA version 1.2, a simple query language is supported that allows\nretrieval of facts from a knowledge base, either interactively via a\nLisp listener or programmatically. The query engine leverages the\ninferencing component by transforming query expressions into rules and\ninserting them, at runtime, into the Rete network. Each query is\nassigned a unique identifier and cached upon first appearance;\nsubsequent queries with semantically equivalent bodies will find the\ncached instance and execute with substantially improved performance,\nespecially for larger knowledge bases. As an example, consider the\nfollowing two query forms:\n\n|   (retrieve (?x ?y)\n|     (?x (hobbit (name ?name)))\n|     (?y (ring-bearer (name ?name))))\n\n|   (retrieve (?h1 ?h2)\n|     (?h1 (hobbit (name ?hobbit-name)))\n|     (?h2 (ring-bearer (name ?hobbit-name))))\n\nThe variables appearing in the first argument to RETRIEVE (e.g. '(?x\n?y)) are used to establish bindings for each firing of the query; each\nvariable must also appear in the query body as an appropriate pattern\nbinding. Other than this requirement, query bodies are structurally\nidentical to rule bodies; anything that is legal in a rule LHS is legal\nin a query body. Note that these two examples are semantically\nequivalent; although the variable names are different, the patterns\nappear in the same order and the relationships among variables are\nidentical. Thus, firing either query will yield the same set of fact\nbindings. LISA is able to recognize such similarities in queries and\nimplements a caching scheme that minimizes unnecessary dynamic rule\ncreation.\n\nRETRIEVE returns two values; a list of bindings for each query firing,\nand the symbolic name assigned by LISA to the query instance. The second\nvalue is probably only useful while developing/testing queries; using\nthis symbol one can ask LISA to forget about a query by removing it from\nthe cache and the Rete network. The binding list is the principal value\nof interest. Since a query is really a rule, it can fire an arbitrary\nnumber of times for each invocation. Each firing is represented as a\nlist of CONS cells. The CAR of each cell is one of the variables\nspecified in the query's binding list; its CDR is a fact bound to that\nvariable that satisfies the variable's associated pattern. For example,\nassuming that the first of the above query examples fires twice during a\ncertain invocation, RETRIEVE would return something like:\n\n|   (((?X . \u003cHOBBIT INSTANCE 1\u003e) (?Y . \u003cRING-BEARER INSTANCE 1\u003e))\n|     ((?X . \u003cHOBBIT INSTANCE 2\u003e) (?Y . \u003cRING-BEARER INSTANCE 2)))\n|   #:G7777\n\nAs explained previously, the second value is the symbolic name LISA\nassigned to the query when its rule instance was initially created. Most\nof the time it will be ignored.\n\nAs of release 1.3, LISA incorporates a unified view of template- and\nCLOS-based facts; as a result queries now function for both types of\nfacts. In the former case, LISA creates a class modeled around the\ntemplate. Class and slot names are taken directly from the DEFTEMPLATE\nform; each slot is given a reader method named according to DEFSTRUCT\nconventions (i.e. *class name-slot name*). For example, \n\n   | (deftemplate frodo ()\n   |   (slot companion (default merry)))\n\nWill yield the following class specification:\n\n   | (defclass frodo (inference-engine-object)\n   |   ((companion :initform 'merry :initarg :companion :reader\n     frodo-companion)))\n\n| These functions and macros comprise the current interface to the query\n  engine:\n|  \n\n=========================================== =====\n(retrieve (*variables*\\ \\*) *patterns*\\ \\*) Macro\n=========================================== =====\n\n..\n\n   Initiates a query against the knowledge base. Variable bindings for\n   the query are found in *variables; patterns* consists of matching\n   forms that comprise the body of the query rule. RETRIEVE returns two\n   values: a list of CONS cells for each firing and the symbolic name\n   LISA assigned to the query when it was initially constructed. The CAR\n   of each CONS cell is one of the binding variables; the CDR is the\n   CLOS instance bound to that variable.\n\n===================== ========\n(forget-query *name*) Function\n===================== ========\n\n..\n\n   Instructs LISA to forget about the query identified by the symbol\n   *name*. Doing so removes the query's rule instance from the Rete\n   network and the query itself from the cache. Useful only during query\n   development, probably.\n\n============================================================= =====\n(with-simple-query ((*var value*) *query-form* \u0026body *body*)) Macro\n============================================================= =====\n\n..\n\n   Evaluates *query-form*. Then, iterates over the resulting list\n   structure, binding each variable and fact to *var* and *value*,\n   respectively, and evaluating *body*. This macro is useful if one is\n   interested in just the individual variable/fact pairs and doesn't\n   care much about the binding context that occurred during query\n   firing.\n\nVI. Conflict Resolution\n~~~~~~~~~~~~~~~~~~~~~~~\n\n| Conflict Resolution (CR) is the mechanism LISA employs to determine\n  the order in which multiple activations will fire. Currently, LISA\n  offers two \"built-in\" strategies; *breadth-first* and *depth-first*.\n  It is possible to implement new CR algorithms by creating a class\n  derived from *lisa:strategy* and implementing a few generic functions;\n  instances of this new strategy can then be given to\n  *make-inference-engine*.\n|  \n\n======================================== ================\n(add-activation *strategy* *activation*) Generic Function\n======================================== ================\n\n..\n\n   Makes a new *activation* eligible for firing.\n\n=========================================== ================\n(find-activation *strategy* *rule* *token*) Generic Function\n=========================================== ================\n\n..\n\n   Locates an activation associated with *rule* and *token*.\n\n============================ ================\n(next-activation *strategy*) Generic Function\n============================ ================\n\n..\n\n   Returns the next eligible activation.\n\n============================= ================\n(list-activations *strategy*) Generic Function\n============================= ================\n\n..\n\n   Returns a list of eligible activations.\n\nDocumentation for the CR interface is still fairly light. Look for\nimprovements in upcoming releases.\n\nVII. The LISA Debugger\n~~~~~~~~~~~~~~~~~~~~~~\n\nNew as of 2.0 alpha 4, the LISA debugger is a simple monitoring and\ninspection utility that may be used to \"debug\" production rules.\nAlthough one cannot step through a rule pattern by pattern, breakpoints\nmay be set to trigger just before a rule fires. When a breakpoint is\nreached, one can then interactively examine the token stack, display all\npattern bindings and their values, single-step into the next activation,\netc.\n\nBy default, LISA builds without the debugger loaded to avoid a slight\nperformance drag on rule firings. To use the debugger, in the CL-USER\npackage evaluate the form (require 'lisa-debugger (lisa-debugger)). If\nyou're running Allegro Common Lisp, LISA understands how to hook into\nthe module search list; thus you may instead evaluate (require\n'lisa-debugger).\n\nThe functionality available via the LISA debugger may increase as user\nneeds dictate; here is the command set as of this writing:\n\n======================= ========\n(set-break *rule-name*) Function\n======================= ========\n\n..\n\n   Sets a breakpoint in the rule identified by the symbol *rule-name.*\n\n========================= ========\n(clear-break *rule-name*) Function\n========================= ========\n\n..\n\n   Clears the breakpoint previously set on the rule identified by the\n   symbol *rule-name*.\n\n============== ========\n(clear-breaks) Function\n============== ========\n\n..\n\n   Removes all breakpoints.\n\n===================== ================\n\\*break-on-subrules\\* Special variable\n===================== ================\n\n..\n\n   Setting this variable to a non-NIL value will cause the debugger to\n   manage breakpoints for a primary rule and all of its subrules (see\n   the section on the *or* conditional element for an explanation of\n   primary rules).\n\n====== ========\n(next) Function\n====== ========\n\n..\n\n   Fires the currently suspended rule, then single-steps into the next\n   activation, if there is one. If there isn't one, the debugger exits.\n\n======== ========\n(resume) Function\n======== ========\n\n..\n\n   Resumes normal execution, until the next breakpoint is reached.\n\n============================= ========\n(tokens \u0026key (*verbose nil*)) Function\n============================= ========\n\n..\n\n    Displays the token stack, which contains the facts that activated\n   this particular rule. If *verbose* is non-nil, then the fact\n   instances themselves are printed; otherwise, a shorthand notation is\n   used.\n\n========== ========\n(bindings) Function\n========== ========\n\n..\n\n   Displays the bindings (pattern variables) found on the rule's LHS,\n   along with their values.\n\n================ ========\n(fact *fact-id*) Function\n================ ========\n\n..\n\n   Returns the fact instance associated with *fact-id*, a small integer\n   assigned to each fact by the inference engine.\n\n============= ========\n(breakpoints) Function\n============= ========\n\n..\n\n   Displays all breakpoints.\n\n====== ========\n(rule) Function\n====== ========\n\n..\n\n   Returns the rule instance representing the suspended activation.\n\nVIII. Getting Started\n~~~~~~~~~~~~~~~~~~~~~\n\nLISA requires the Portable Defsystem as maintained by the CLOCC project;\nfor your convenience, a copy is included in the distribution. Building\nLISA should be straight-forward. First, either load \"lisa:lisa.system\"\nor change your working directory to the LISA root directory; then,\nevaluate (mk:compile-system :lisa). Note that LISA uses logical\npathnames in its defsystem, and translations that are suitable for a\nLinux (or Cygwin/Windows) environment are established there. They might\nwork for you; perhaps not. Until I figure out how to correctly place\ndefault translations you might have to do some hand editing. Sorry.\n\nTo build a knowledge base, write your production rules using the various\nsource examples (and this document) as your guide and load the file(s)\ninto Lisp. You can then change to the LISA-USER package and experiment.\nLook for the examples in \"lisa:misc;\".\n\nA note to CLISP users. LISA requires that CLISP be run with full ANSI\nsupport enabled. Also, the baseline version with which LISA has been\ntested is 2.25.1. Earlier releases might work as well, but no\nguarantees.\n\nIX. Things Yet to Do.\n~~~~~~~~~~~~~~~~~~~~~\n\nThis section is a list (albeit incomplete) of features that would\nimprove LISA significantly.\n\n#. *Backward chaining*: Perhaps an implementation of Prolog's\n   backchaining algorithm that has concurrent access to working memory\n   (i.e. along with Rete).\n\nX. Supported Platforms.\n~~~~~~~~~~~~~~~~~~~~~~~\n\nLISA has been tested, and is known to run, on the following Common Lisp\nimplementations:\n\n-  Allegro Common Lisp, versions 5.0.1 and 6.x, Linux and Windows 2000.\n-  Xanalys LispWorks, versions 4.1.20 and 4.2, Linux and Windows 2000.\n-  CLISP, version 2.27 and newer, Linux and Windows 2000.\n-  CMUCL, version 18c, Linux.\n\n\n___\n\nTested with SBCL 2.2.9.debian with the folder ``lisa`` copied\ninto ``~/quicklisp/local-projects``. Unfortunately there is a *package-lock*\nthat inhibits smooth loading. That is why the package ``cl-package-locks`` is helpful ::\n\n\n    (ql::quickload :cl-package-locks)\n    (cl-package-locks::unlock-package :common-lisp)\n    (ql::quickload :lisa)  ;;; unlock 2\n    (cl-package-locks::lock-package :common-lisp)\n\n    ;;; (cl-package-locks::all-locked-packages)\n    ;;; (cl-package-locks::all-unlocked-packages)\n\n\n    (in-package \"LISA-USER\")\n\n    (deftemplate expr () (slot str))\n\n    (defrule r1 () (expr (str ?s)) =\u003e (print ?S))\n\n    (assert (expr (str \"A + B + 2 * C - D\")))\n    (assert (expr (str '(\"A + B + 2 * C - D\" \"X + Y\" \"2 * Z + X\"))))\n\n    (facts)\n    (agenda)\n    (run)\n\n    --\u003e should yield:\n\n    #\u003cEXPR ; id 0 {100443A323}\u003e\n    #\u003cEXPR ; id 1 {10017A10E3}\u003e\n    For a total of 2 facts.\n    #\u003cACTIVATION (INITIAL-CONTEXT.R1 (F-0) ; salience = 0) {1001740173}\u003e\n    #\u003cACTIVATION (INITIAL-CONTEXT.R1 (F-0) ; salience = 0) {1001740173}\u003e\n    For a total of 2 activations.\n\n    \"A + B + 2 * C - D\" \n    (\"A + B + 2 * C - D\" \"X + Y\" \"2 * Z + X\") \n    * \n\n\nThis README was converted by using ``pandoc`` applied to ``ref-guide.html`` (in the doc folder).\n\n___\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnilqed%2Flisa-rules","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnilqed%2Flisa-rules","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnilqed%2Flisa-rules/lists"}