nilfor each slot
(def-kb-struct <class-spec> <slot-spec>*)
where the arguments are the same as for
defstruct except that in
<class-spec> only the options
:print-function are allowed. A structure may only be included in a KnowledgeWorks structure if it too is a KnowledgeWorks structure defined by
def-kb-struct. All the functions normally provided by
defstruct (accessors, a predicate etc.) are generated. An instance of the structure class may be created by the generic function
<slot-specifier> is the keyword version of the slot name, as with any structures, and
<value> is the value the slot is to take, otherwise defaulting to the value specified in the
def-kb-struct form. If created from Lisp by any means other than
make-instance (for example, by the automatically defined
make-<structure-name> constructor), the inference engine will not know about the structure.
Forward chaining rules are more efficient if the more restrictive preconditions (that is, the ones which will have fewer matches) are written first. Computationally cheap Lisp tests should be used wherever possible as they reduce the search space of the rule interpreter. The Lisp tests should where possible be broken into sufficiently small pieces that they can be applied as early on as possible.
because in the first example the Lisp tests can be applied directly to the trains and signals respectively before looking at combinations of trains and signals, whereas in the second case all the combinations must be produced before the Lisp test can be applied. Simply separating the tests is enough for the rule compiler to apply them to the right object base matches -- the precise order of the tests is unimportant.
The single most significant way to improve conflict resolution time is to divide the rulebase up into contexts. The time taken by conflict resolution is dependent on the total number of instantiations of all the rules in the context so the fewer rules in each context, the more efficient conflict resolution will be.
KnowledgeWorks is best able to optimize rule-defined tactics and least able to optimize dynamic tactics. The optimizations for a particular type of tactic can only be applied if it is preceded only by tactics which can be optimized to the same degree (or better). For example, in the strategy
(recency priority), the tactic
priority would only be optimized as a static tactic. In the strategy
(priority mea recency),
priority can be optimized as a rule-defined tactic but
recency will be treated as a dynamic tactic.
The KnowledgeWorks Backward Chainer indexes clauses for a backward rule based on the first argument. If the first arguments to backward rule clauses are distinct non-variables, the backward chainer can pre-select possible matching clauses for a call.
The KnowledgeWorks Backward Chainer supports the transformation of "tail-recursive" calls into jumps. Thus, stack overflow can be avoided without resorting to "repeat, fail" loops in most cases. For example, given the definition:
(run-forever) will run forever without generating a stack overflow. Note that this optimization is not limited to recursive calls to the same rule. The last call of any rule will be compiled as a jump, drastically reducing stack usage.
The use of "cut" is a well known performance enhancement for Prolog-style rules. In KnowledgeWorks it does more than reduce the time spent in search. When a "cut" is invoked, all the stack space between the initial call to the containing rule and the current stack location is reclaimed immediately, and can have a significant impact on the total space requirements of a program.
KnowledgeWorks and Prolog User Guide (Macintosh version) - 24 Mar 2017