Task control
The control activity is transferred from task to task
during the
search for a solution of the problem. This transfer can be either
simple (sequential - task 1 always follows task 2) or more
complex
when the exact form of the activity transfer depends on the
current state of the solution (e.g. on the result of some
test).
Control transfer is performed in the ''background''. When
a task
becomes active, it is active till it returns this activity back
to
the task control mechanism (in the current state of the solution
there is no need for the task to remain active - this stage is
detected by the active task). Then the task control passes the
activity to the next appropriate task.
Each task consists of a set of rules. While some task is active,
only rules of this task and rules dedicated to the activity
transfer to the next task can be fired. The rules of the task
have
higher priority than the activity transfer rules. This enables
first
to fire all relevant rules of the active task. The rules for the
task control (the choice of the next task and the passing the
activity to this task) can be fired only when there is no rule
of
the active task which is relevant in the current situation.
Which fact is currently active is specified by a control
token.
This
token is the fact of the following form
- (job <name of the active task>)
which can be found in the database. To divide all rules into
groups
according to the tasks they belong to, every rule contains the
test for the activity of its task at the beginning of its
condition
part. Thus a general form of rules belonging to a particular task
is as follows
-
(defrule <rule name>
-
(job <name of a task the rule belongs to>)
...
=>
-
...
)
The transfer of the activity from one task to another can be
implemented in two steps:
- remove the old control token from the database
- assert the new control token with the name of the next task
into the database
An example of a simple sequential activity transfer is the
transfer
of the control token from the task initialize to the task
evaluate:
-
(defrule end-initialize-1
-
(declare (salience -50))
?a <- (job initialize)
=>
-
(retract ?a)
(assert (job evaluate))
)
Similar schema is used to activate the task test for solution
existence. The only difference is that this task is always
activated
as the first one. The rule belonging to this task has a very simple form
-
(defrule start-1
-
(declare (salience -50))
=>
-
(assert (job test-exist))
)
More complex activity transfer, based on the result of the
previous
task, consists of several rules. For instance to choose the next
task after the task evaluate returns the control:
-
(defrule end-evaluate-1
-
(declare (salience -50))
?a <- (job evaluate)
=>
-
(retract ?a)
(assert (job test1))
)
-
(defrule end-test1-1
-
(declare (salience -50))
?a <- (job test1)
(not (object (is-a constraint)
(cons-violation yes)))
=>
-
(retract ?a)
(assert (job optimize))
)
-
(defrule end-test1-2
-
(declare (salience -50))
?a <- (job test1)
(object (is-a constraint)
(cons-violation yes))
=>
-
(retract ?a)
(assert (job change))
)
where first the simple transfer to the appropriate test is
performed. The test always consists of several rules (the number
of rules corresponds to the number of different output values of
the test). These rules have to contain the appropriate form of
the
test in their condition parts (in the example above the presence
of
constraint violations is tested).
The test can be performed as the test of the current state of the
solution. Another possibility is to test the result of the
activity
of the previous task. The previous task could assert its result
into the database represented by one of the facts
(result
success)
or (result failure). The next task should retract this
information
from the database. This is true for the control after the tasks
test for solution existence, change, and relax.
As an example, the
part of the task control after the task change is finished
-
(defrule end-test2-2
-
(declare (salience -50))
?a <- (job test2)
?b <- (result failure)
=>
-
(retract ?a)
(retract ?b)
(assert (job relaxation))
)
Tasks success and failure are implemented as
special tasks which
are able to display the message about the success of the search
of the solution and to provide the current state of this
solution.