An inferencing state represents all the state needed to run the forward chaining interpreter, including the object base, the current cycle number and the set of unfired instantiations. It does not include rule or context definitions or any backward chaining state information.
Inferencing states are first-class objects that can be created and destroyed as required. Each inferencing state must have a unique name (as compared with eql
) and initially there is a single inferencing state named :default
.
The function make-inferencing-state makes a new empty inferencing state. Inferencing states must be destroyed with destroy-inferencing-state when no longer needed, to release the memory that they use.
Inferencing states can be found using the function find-inferencing-state and the function list-all-inferencing-states can be used to make a list of all known inferencing states.
The value of the variable *inferencing-state* is known as the current inferencing state. Its value can be changed before calling KnowledgeWorks functions, but should not be changed within the body of a rule.
Some operations, such as object creation, slot modification, reset and infer only affect the current inferencing state. Backward chaining operations that match the object base only find objects from the current inferencing state.
Operations that change rules or contexts, such as defrule and clear-all, affect all inferencing states.
In many cases, a single inferencing state is sufficient and the initial inferencing state named :default
can be used without any special effort.
To allow several independent inferencing operations to be performed simultaneously, multiple inferencing states must be managed explicitly. Some typical situations are described below.
By binding *inferencing-state* around all KnowledgeWorks operations in a thread's main function as in the example below, its value can be unique to each thread.
(defun test-1-counter (name)
(let* ((*inferencing-state* nil)
(step (1+ (random 10)))
(limit (* step (+ 2000 (random 100)))))
(unwind-protect
(progn
(setq *inferencing-state*
(make-inferencing-state name))
(make-instance 'counter
:value limit
:step step)
(infer))
(destroy-inferencing-state *inferencing-state*))))
(mp:process-run-function (format nil "Test ~D" index)
'()
'test-1-counter
(gensym)
By binding *inferencing-state* around specific KnowledgeWorks operations in a function as in the example below, multiple inferencing states can be maintained within a single thread.
(defun test-stepping-single-context ()
(let ((state1 (make-inferencing-state 'state1))
(state2 (make-inferencing-state 'state2)))
(unwind-protect
(progn
(let ((*inferencing-state* state1))
(make-instance 'step-controller
:kb-name 'stepper-one-a))
(let ((*inferencing-state* state2))
(make-instance 'step-controller
:kb-name 'stepper-one-b))
(loop repeat 10
do
(let ((*inferencing-state* state1))
(infer))
(let ((*inferencing-state* state2))
(infer))))
(destroy-inferencing-state state1)
(destroy-inferencing-state state2))))
KnowledgeWorks and Prolog User Guide (Macintosh version) - 26 Feb 2015