Conditions

Conditions

Precondition

Preconditions control the activation of a frame. For a frame to become active the preconditions defined for the frame have to be satisfied. Preconditions are satisfied by either matching beliefs of an agent (if the frames are defined for an agent or the frames are thoughtframes) or by matching facts in the world (if the frames are defined for an object). Preconditions can include variables as part of their matching of specific beliefs/facts.

Syntax

precondition::={ [ known | unknown ] } ( novalcomparison ) |
{ [ knownval | not ] } ( evalcomparison )
novalcomparison::=BEL.obj-attr |
BEL.obj-attr REL.relation-name |
BEL.tuple-object-ref REL.relation-name
evalcomparison::=eval-val-comp | rel-comp
eval-val-comp::=expression BEL.evaluation-operator expression |
BEL.obj-attr BEL.equality-operator ID.literal-symbol |
BEL.obj-attr BEL.equality-operator ID.literal-string |
BEL.obj-attr BEL.equality-operator BEL.sgl-object-ref |
BEL.sgl-object-ref BEL.equality-operator BEL.sgl-object-ref
rel-comp::=BEL.obj-attr REL.relation-name BEL.obj-attr { is ID.truth-value } | BEL.obj-attr REL.relation-name BEL.sgl-object-ref { is ID.truth-value } | BEL.tuple-object-ref REL.relation-name BEL.sgl-object-ref { is ID.truth-value } |
expression::=term | expression | [ +|-] term
term::=factor | term | [ * | / | div | mod ] factor
factor::=primary | factor ^ primary
primary::=- primary | element
element::=ID.number | BEL.obj-attr | VAR.variable-name | unknown

Semantics

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 <agent2>

where <agent1> and <agent2> are either agents or objects.

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 therefore 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 therefore 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 therefore a post-assigned variable. <mycar> is not specified in any OA, OR, ORO condition element and is therefore 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

  1. 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.
  2. 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.
  3. Expressions must evaluate to a value of type int, long or double.
  4. 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.
  5. Only one unbound post-assigned variable can be used in a precondition.
  6. No unbound post-assigned variables can be used in a precondition using one of the relational operators '<', '>' or '!='.
  7. 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.

Consequence

A consequences is a logical statement for concluding/asserting new beliefs for an agent or object and/or facts in the world.

Syntax

consequence::=conclude ( ( resultcomparison )
{ , fact-certainty }
{ , belief-certainty } ) ;
resultcomparison::=result-val-comp | PRE.rel-comp
result-val-comp::=BEL.obj-attr BEL.equality-operator PRE.expression |
BEL.obj-attr BEL.equality-operator ID.literal-symbol |
BEL.obj-attr BEL.equality-operator ID.literal-string |
BEL.obj-attr BEL.equality-operator BEL.sgl-object-ref |
BEL.tuple-object-ref BEL.equality-operator BEL.sgl-object-ref
fact-certainty::=fc : ID.unsigned
belief-certainty::=bc : ID.unsigned

Semantics

Fact certainty

The fact certainty is a number ranging from 0 to 100 and represents the percentage of chance that a fact will be created based on the consequence. A fact certainty of 0% means that no fact will be created, 100% means that a fact will be created at all times.

Belief certainty

The belief certainty is a number ranging from 0 to 100 and represents the percentage of chance that a belief will be created based on the consequence. A belief certainty of 0% means that no belief will be created, 100% means that a belief will be created at all times.

Example

  conclude((current.receivedCash = false), bc:100, fc:100)
  conclude(heartRate{bpm, timestamp},{bc:100, fc:0});

Defaults

  • fc = 100
  • bc = 100

Constraints

  1. In the comparison 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. If the left hand side attribute is of a collection type and an index is specified any value type can be assigned. If no index is specified then only the value unknown or a value resolving to a collection type can be defined on the right hand side. If the right hand side is of a collection type and an index is specified then the compiler will assume that the type it resolves to is compatible with the left hand side type, the virtual machine will at run-time ensure type compatibility. If the right hand side resolves to a type that is incompatible with the left hand side type then an error is reported in the log and the consequence will fail.
  2. In the comparison 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.
  3. The values of fact-certainty and belief-certainty range from 0 to 100 and represent a percentage.
  4. A consequence defined in the body of a thoughtframe can only conclude beliefs. The fact certainty argument will be ignored, a warning will be generated in case the belief-certainty is set to 0.

Detectable

A detectable is a declarative statement defining first which state changes an agent or object can detect and second what action results from detecting the state change.

Detecting facts is a two-phase process. In the first phase the agent or object detects the fact and the fact becomes a belief for the agent or object. No matter what the right hand side is in the form OA=V and OA=O the fact will become a belief for the agent or object. To make this behavior clearer, the detection condition may be stated without the equality and right hand side (OA) or the right hand side may be given as a wildcard character (OA=?). In the case of an ORO, the right hand side and truth value are also ignored in determining the matching facts and they also may be omitted from the condition (OR) or given as the wildcard character (OR?) to indicate that any fact with the specified relation and matching the left hand side should match the condition no matter what it has for a right hand side object or truth value.

In the second phase the beliefs of the agents or objects are matched with the detectable definition and if there is a positive match, the detectable action is executed. In contrast to the fact detection phase, the right hand side of a condition of the form OA=V, OA=O, or ORO is not ignored when matching beliefs. But if the right hand side of the condition is omitted or given as the wildcard '?' any right hand side value or object is allowed in matching beliefs.

Note that these two phases are independent for agents and objects, i.e. regardless of whether the fact is present in the world, the second phase is performed. This means that if the agent or object has received a matching belief through a communication, the belief will trigger the action of the detectable.

Syntax

detectable::=detectable detectable-name {
{ when ( [ whenever | ID.unsigned ] )}
detect ( ( resultcomparison ) { , detect-certainty } )
{ then detectable-action } ;
}
detectable-name::=ID.name
resultcomparison::=[ detect-val-comp | detect-rel-comp ]
detect-val-comp::=obj-attr |
obj-attr BEL.evaluation-operator PRE.expression |
obj-attr BEL.evaluation-operator obj-attr |
obj-attr BEL.equality-operator ID.literal-symbol |
obj-attr BEL.equality-operator ID.literal-string |
obj-attr BEL.equality-operator sgl-object-ref
detect-rel-comp::=detectable-object REL.relation-name |
detectable-object REL.relation-name sgl-object-ref
{ is ID.truth-value }
obj-attr::=detectable-tuple { ( BEL.collection-index ) }
detectable-tuple::=detectable-object . ATT.attribute-name
detectable-object::=BEL.tuple-object-ref | < ID.name >
sgl-object-ref::=BEL.sgl-object-ref | < ID.name > | ?
detect-certainty::=dc : ID.unsigned
detectable-action::=continue | impasse | abort | complete | end_activity

Semantics

When

For each detectable needs to be specified when the agent or object can detect a certain fact. There are two options:

whenever:

This means that the detectable is checked every time a new fact is asserted in the world and for an agent also every time a new belief is asserted.

at a specified time:

For the detectable needs to be specified exactly when the detectable needs to be checked by specifying a percentage varying from 0 to 100% specifying at what percentage of the workframe completion the detectable needs to check the fact set and belief set. These kind of detectables are only checked once.

< Class Variable >

Agents and objects do not always have the ability to know in advance about what concepts they can detect facts. To allow these agents and objects to detect facts about unknown concepts it is possible to define the class of concepts for which facts need to be detected. On the left hand side of the detectable condition instead of specifying the name of a variable, parameter or concept instance (agent, object, conceptual object, or area) the class of concept is specified in between the brackets < and > such as <BaseGroup>. This will have the agent or object detect all facts of which the left hand side concept instance is an instance of the specified class or an instance of any of its sub classes. The matches can be restricted by specifying a more specific class in the detectable condition. The agent or object will in that case only detect those instances that are instances of that class or any of its subclasses, but not any of its superclasses, even if the superclass defines that attribute and facts for concept instances of that super class exist. A bracketed class name may also be used on the right hand side of a detectable condition to indicate that, in the belief matching step, beliefs may have any right hand side concept that is an instance of that class or any of its subclasses.

Wildcard

A wildcard character, '?', may be used on the right-hand side of a detectable condition to indicate that the right-hand side value or object of a matching fact (in step one) or a matching belief (in step 2) is ignored. Normally, this may be stated more directly by simply omitting the operator and right-hand side of a value comparison or by omitting the right-hand side object of a relation comparison. However, the wildcard may occasionally be useful in a relation comparison together with 'is false' or 'is unknown' to match beliefs with truth values other than 'true'.

Detect-certainty

The detect-certainty is a number ranging from 0 to 100 and represents the percentage of chance that a fact will be detected based on the detectable. A detect-certainty of 0% means that the fact will never be detected and basically means that the detectable is switched off. A detect-certainty of 100% means that a fact will always be detected based on the detectable.

Detectable action

There are 5 different detectable actions possible:

continue:

Has no effect, only used for having agents or object detect facts and turn them into beliefs.

impasse:

Impasses the workframe on which the agent or object is working until the impasse is resolved.

abort:

Terminates the workframe on which the agent or object is working immediately.

complete:

Terminates the workframe on which the agent or object is working immediately, but still executes all remaining consequences defined in the workframe. All remaining activities are skipped.

end_activity:

This action type is only meaning full when used with composite activities. Causes the composite activity on which the agent or object is working to be ended.

Example

  detectable colorOfCar {
    detect((<Car>.color = ?));
  }
  detectable openingFridge {
    detect((fridge.doorState = "open")) then continue;
  }
  detectable leaveKitchen {
    detect((current.location != Kitchen)) then end_activity;
  }

Defaults

  • when = whenever
  • dc = 100
  • action = continue

Constraints

  1. In the comparison 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. Object-attribute-index is considered type compatible with any type and is permitted on both the left and right hand side. For detectables the right hand side is ignored and therefore no errors or warnings will ever be generated even if the right hand side resolves to a value that is type incompatible with the left hand side. However for the trigger the right hand side is relevant and if the value resulting from evaluating the right hand side is type incompatible with the left hand side a warning is generated in the log and the detectable action is not executed.
  2. In the comparison 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.
  3. ID.name when used as the left hand side concept must be the name of a concept class, i.e. a group, class, conceptual class or area definition.
  4. The value of the detect-certainty ranges from 0 to 100 and represents a percentage.
  5. The end-activity action type can only be used when a detectable is defined in a composite activity.

Transfer Definition

A transfer-definition describes what belief(s) are to be communicated between two actors. The transfer-definition also describes whether the belief has to be sent to the actor with whom is communicated or whether the belief has to be received from the actor with whom is communicated. The transfer definition can specify the exact belief(s) that are to be communicated or can specify a CommunicativeAct defining the message that is to be communicated. A CommunicativeAct is a much more formal representation of a message based on the CommunicativeAct specification defined by the Foundation for Intelligent Physical Agents (FIPA). When a CommunicativeAct is specified the transfer will consist of all the beliefs in that CommunicativeAct's belief set. An actor can only send a CommunicativeAct to another actor and never receive a CommunicativeAct from another actor (the initiating actor can not force another actor to communicate). The receive action is therefore only valid to read all the beliefs of a CommunicativeAct.

Syntax

transfer-definition::=

transfer-action ( communicative-act | DET.resultcomparison)

transfer-action

::=

send | receive

communicative-act

::=OBJ.object-name | PAC.param-name

Semantics

Transfer-action

The transfer action defines the direction of the communication. The 'send' action states that belief(s) of the initiating agent or object matching the transfer definition are transferred from the initiating agent or object to the non-initiating agent or object. The 'receive' action states that belief(s) of the non-initiating agent or object matching the transfer definition are transferred from the non-initiating agent or object to the initiating agent or object. Note that if the transfer definition specifies a condition as an object/attribute tuple (OA=V) the right hand side value is ignored in the matching process. To make this behavior clearer, the condition may be stated without the equality and right hand side (OA) or the right hand side may be given as a wildcard character (OA=?). In the case of an ORO, the right hand side is not ignored in the matching process but it may be omitted from the condition (OR) or given as the wildcard character (OR?) to indicate that any right hand side object should match the condition.

< Class Variable >

To provide more flexibility in determining the beliefs to be transferred in a communication a transfer definition condition may use bracketed class variables. A transfer definition condition, instead of specifying the name of a variable, parameter or concept instance (agent, object, conceptual object, or area), may specify the class of concept in between the brackets < and > such as <BaseGroup>. A class variable may be used anywhere a concept reference may appear in the condition. It may be used either on the left-hand or right-hand sides of the condition and may appear as a standalone object reference or paired with an attribute name. This will have the transfer condition match all beliefs that have a concept instance in a position corresponding to the class variable that is an instance of the specified class or an instance of any of its subclasses. The matches can be restricted by specifying a more specific class in the transfer definition condition. The agent or object will in that case only send beliefs involving those instances that are instances of that class or any of its subclasses, but not any of its superclasses, even if the superclass defines the attribute or relation and beliefs for concept instances of that super class exist.

Wildcard

A wildcard character, '?', may be used on the right-hand side of a transfer definition condition to indicate that the right-hand side value or object of a matching belief is ignored. Normally, this may be stated more directly by simply omitting the operator and right-hand side of a value comparison or by omitting the right-hand side object of a relation comparison. However, the wildcard may occasionally be useful in a relation comparison together with 'is false' or 'is unknown' to transfer beliefs with truth values other than 'true'.

Example

communicate colorOfMyCar(FriendGroup friend, Car car) {
    max_duration: 5;
    with: friend;
    about: send(current.car = ?),
      send(car.color = ?);
  }

Constraints

  1. In the comparison 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. Object-attribute-index is considered type compatible with any type and is permitted on both the left and right hand side. Since the right hand side of the condition is ignored, no errors or warnings will ever be generated even if the value resulting from the right hand side is type incompatible.
  2. In the comparison 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.
  3. An ID.name when used in a class variable must be the name of a concept class, i.e. a group, class, conceptual class or area definition.
  4. If a communicative-act is specified and the action is send then the object-name or value passed to the parameter identified by param-name must be an object instance that is an instance of brahms.communication.CommunicativeAct.
  5. If a communicative-act is specified and the action is receive then the object-name or value passed to the parameter identified by param-name must be an object instance that is an instance of brahms.communication.CommunicativeAct and the value for the communication activities 'with' property must be identical to the communicative-act specified in the transfer definition to indicate the reading of the communicative-act's beliefs.