|
Precondition modifiers
A precondition is defined with one of four
modifiers: known, knownval, unknown, or
not. The modifier for a precondition may be omitted; in this
case, the modifier defaults to ‘known’ for a novalcomparison (no right-hand-side
value) and to ‘knownval’ for an evalcomparison (a right-hand-side value is
present). The modifiers have the following meaning.
known:
The modifier known represents
the possibility for an agent/object to have a belief/fact,
but be unspecific as to whether the agent/objects knows the
actual value.
For example, to evaluate the following
precondition:
known (car1.color)
The simulation engine
would simply check with the belief set of an agent to see whether the agent
has a belief of the form:
car1.color = ?
If the engine finds a belief of this form,
as it would when the following belief is present:
car1.color = red
then the engine would evaluate the
precondition as true. A simple relational precondition like:
known (John
is-the-son-of)
will evaluate to true when the engine finds
the beliefs (the right hand side and
truth-value are completely ignored):
John is-the-son-of Bill
is true
John is-the-son-of Bill
is false
John is-the-son-of Jack is true
John is-the-son-of Jack is false
A more complex precondition like:
known (Cimap-order1.service-tech
is-the-son-of)
will evaluate to true if the following
beliefs are present:
Cimap-order1.service-tech = <agent1>
<agent1> is-the-son-of
where <agent1> is either an agent or object.
knownval:
The modifier knownval (known
value) means that the simulation engine must find a precise
match for the precondition. The precondition is only true if
matching beliefs/facts can be found for both the left hand
side and the right hand side and if the relation between them
is found as well. For example for a complex precondition such
as:
knownval(Cimap-order1.service-tech
is-the-son-of Cimap-order2.service-tech)
the following beliefs must be present:
Cimap-order1.service-tech = <agent1>
Cimap-order2.service-tech = <agent2>
<agent1>
is-the-son-of <agent2>
When using variables, the engine will find
as many matches as there are valid instantiations for the
variables.
unknown (a.k.a. no-knowledge-of):
When the modifier unknown is
used, the simulation engine looks at the beliefs of the agent
or facts in the world for objects for possible matches of the
precondition. If there are any matches, the precondition
evaluates to false, if no matches are found the precondition
evaluates to true. The unknown modifier can be
interpreted as The agent/object has no beliefs/facts
for <precondition>. However, there are
intricacies that need to be explained further.
When matching a
precondition of the form: O1A1, the simulation engine
looks for a belief of the form O1A1= ?. When a belief
of the form O1A1= ? is found, the simulation engine
interprets this to mean that the agent ‘knows’ about this object and
attribute and thus the precondition is false.
When the precondition
is of the form O1 rel however, no matter what the right hand side
or the truth of the relation is, the simulation engine will simply look up
whether the agent/object possesses the belief/fact O1 rel ?, and
if so will evaluate the precondition to be false.
All other
preconditions, require at least two steps for the simulation engine to
determine the truth or falsehood of the precondition.
The form O1A1
rel requires the simulation engine to evaluate first the O1A1
then the result of the O1A1 (say O2) with
the relation. When a belief/fact for either the OA or for O2 rel
is not found, the precondition will be evaluated to true, if both are found
the precondition will evaluate to false. For example given the following
beliefs:
John.car = car1
car1 is-drive-by Jack
and the precondition:
unknown (John.car
is-driven-by)
The simulation engine will evaluate the
precondition to false, because it finds beliefs for
"John.car = ?" with the value car1 and it finds a belief for "car1
is-drive-by ?". If either of the beliefs were not available the
precondition would evaluate to true.
not (a.k.a. no-matching-beliefs):
Not works similar to
unknown in that when there is no belief for the precondition specified with
the not modifier the precondition will evaluate to true. If a belief does
exist for the condition in the precondition then the not modifier works
similar to the modifier knownval, but negates the resulting truth-value. The
simulation engine will first try the knownval for the precondition. If the
precondition with the knownval modifier evaluates to true then the
precondition with the not modifier evaluates to false and vice versa.
Precondition Evaluation Order
When variables are used in one or more precondition(s)
the order in which the preconditions are specified is important. Depending
on the order different outcomes are possible. The reason that precondition
order is important is that the simulation engine is not a standard pattern
matcher, but actually evaluates the preconditions causing potential
assignments of values to variables. For example:
knownval(John.car
= <car>)
The simulation engine tries to find a belief of the form
‘John.car=’. If it finds one stating ‘John.car=car1’ then it will
assign the value car1 to the variable <car>.
If you were to write the following two preconditions in
the following order the outcome might be unexpexted:
not(John.car =
<car>)
knownval(<car> belongs-to <company>)
Suppose we have the following beliefs:
John.car = car1
car2 belongs-to nynex
The simulation engine will evaluate the first
precondition first and first treat the precondition as a knownval therefor
assigning the value ‘car1’ to the variable <car> because it
matches the precondition with the belief ‘John.car = car1’. Since this
precondition is a not this precondition will always evaluate to false. The
simulation engine would not continue but if it would then the simulation
engine would verify the second precondition. It found a binding for the
<car> variable and will substitute its value. It will then try to find
a belief of the form ‘car1 belongs-to <company>. It cannot find such
a belief and therefor will fail the evaluation causing the frame not to be
made available. However if you turn the preconditions around the outcome is
different.
knownval(<car> belongs-to <company>)
not(John.car = <car>)
In this case <car> will be bound to car2, the first
precondition evaluates to true. The second precondition will be evaluated
and the simulation engine tries to find the belief ‘John.car=car2’, it
cannot find such a belief but due to the ‘not’ modifier the precondition
will evaluate to true causing the frame to be made available.
The precondition ordering will also be important when
taking into account the use of variables. The next section discusses the
distinction made by the simulation engine in the types variables and how
that can affect the importance of the precondition order.
Pre-, Post- and Unassigned Variables
The simulation engine makes a distinction in how
variables are bound in a frame. The three types of value assignments are
pre-assigned, post-assigned and unassigned.
Unassigned variables are variables not used in any
preconditions but that get their binding in an activity.
Pre-assigned variables are variables that get their
values assigned in preconditions and get a pre-binding before the
preconditions are evaluated. Pre-assigned variables are variables used in an
object/attribute tuple (OA) or that are used in an object/relation tuple
(OR) or object/relation/object triplet (ORO) where the object is a variable.
In case of the ORO it could be one of the objects that is a variable or
both. The simulation engine makes sure that for each OA, OR (with an (un)known
modifier) and ORO there is at least one matching belief/fact before fully
evaluating the preconditions. The variables used in these condition elements
will get a pre-binding by matching the variables with the object values in
the beliefs/facts. A final binding will be determined when the preconditions
are evaluated.
Post-assigned variables are variables that get their
values assigned in preconditions as well, but they will get a binding during
the evaluation of the preconditions. These variables have no pre-binding
like pre-assigned variables do. Post-assigned variables are the variables
not used in any OA, OR, ORO condition elements but are usually ‘assignment’
variables specified on the left hand side or right hand side of a value
condition, for example:
<myagent>.car = <mycar>
<myagent> is part of an OA pair and is therefor a
post-assigned variable. <mycar> is not specified in any OA, OR, ORO
condition element and is therefor a post-assigned variable. The simulation
engine will have found potential matched for the OA and will have pre-bound
the <myagent> variable. During the evaluation of the precondition the
simulation engine will then for each value of <myagent> get the
belief/fact that caused that value binding for <myagent> and retrieve
its right hand side. Assume that the belief was:
John.car = car1
<myagent> is John and the right hand side is ‘car1’.
The simulation engine will now assigne the value ‘car1’ to the variable
<mycar> during the evaluation of the precondition.
Due to the distinction between pre- and post-assigned
variables ordering of preconditions is also important if no conflicts are to
occur with the constraints listed below. Assume a frame with the following
preconditions:
knownval(<totalOrders> = <numVMOrders>+Builder.numOrders)
knownval(VM.numOrders = <numVMOrders>)
In this case the first precondition has two post-assigned
variables <totalOrders> and <numVMOrders>. The simulation engine
can resolve Builder.numOrders to a value but cannot resolve the values for
the post-assigned variables. This would be an endless list of possible
values. The simulation engine would report an error and fail the evaluation
of the precondition. If the preconditions would now be reversed
knownval(VM.numOrders = <numVMOrders>)
knownval(<totalOrders>
= <numVMOrders>+Builder.numOrders)
then the simulation engine resolves the <numVMOrders> post-assigned
variable first, it will bind a value to it by finding a belief of the form
VM.numOrders = ? and assigning the right hand side value to the variable. Then
during the evaluation of the second precondition the <numVMOrders>
variable will have a value bound to it that can be used together with the right
hand side value of the belief Builder.numOrders = ? to assign a value to <totalOrders>.
The evaluation of all preconditions will succeed and the frame can be made
available.
Constraints
-
The left hand side attribute type and the right
hand side value-type or right hand side attribute type of a
value-expression must be the same, except in the case of an attribute
being of a collection type and an index having been specific for the
attribute, in that case any value can be assigned, if no index is
specified however only unknown is valid or an expression resulting in
the same collection type. If an object-attribute-index is used on the
left or right hand side to resolve to a value then the type
compatibility constraint is relaxed, the compiler will assume that a
value of the correct type is returned to compare to the left or right
hand side. The virtual machine will at run-time ensure that type
compatibility holds, if not it will evaluate the precondition to false
and generate a warning message in the log.
-
The left hand side and right hand side types in a
relational expression must match the types as defined for the relation
used in the relational expression. Only the right hand side can be
defined to use an object-attribute-index. The compiler will allow this
without type checking, the compiler will assume that a value of the
correct type is returned for the relation. The virtual machine will at
run-time ensure that type compatibility holds, if not it will evaluate
the precondition to false and generate a warning message in the log. The
use of object-attribute-index on the left hand side would resolve to an
unknown type not allowing the compiler to verify whether the relation is
declared for that type and is therefore not permitted.
-
Expressions must evaluate to a value of type int,
long
or double.
-
No nested expressions
are allowed. The first release of the virtual machine will not support
them yet. As soon as the virtual machine is able to support nested
expressions, this constraint will be lifted.
-
Only one unbound
post-assigned variable can be used in a precondition.
-
No unbound
post-assigned variables can be used in a precondition using one of the
relational operators ‘<’, ‘>’ or ‘!=’.
-
No unbound
post-assigned variables can be used in an expression.
Note that constraints
5 to 7 cannot be detected by the compiler but only by the simulation
engine. The simulation engine will report errors in the error log and will
fail the evaluation of the precondition in which these constraints are
violated.
|