Closed jefft0 closed 1 year ago
Nice catch! I'm just pinging @arashsheikhlar because I think he should have a look at this. He could do a similar check with his created composite states and requirement models to see whether there is a variable mismatch between his newly created requirement model and the causal model that it instantiates.
Background: When CTPX builds a model where the LHS is a command, it has all the information needed for forward chaining to assign values to the variables in the RHS. However, CTPX can also build a model where the LHS is an imdl, called a "reuse" model. An example from hand-grab-sphere-learn is the following model which says that if a hand H is holding object X and moves, then X moves too (simplified with meaningful variable names):
Here, we are concerned with forward chaining as follows.
cst_same_position
is instantiated with handH
holding objectX
at positionP0
. This matches the LHS of the requirement modelmdl_move_reuse_req
which uses the RHS to create the requirement formdl_move_reuse
. (Note that the requirement hasX
, discussed below.) Later in the same frame, the move command fires to move handH
fromP0
toP1
, and creates the imdl(imdl mdl_move [P0: (ti T0: T1:)] [H: DeltaP: P1: T2B: T2B:])
. This matches the LHS of modelmdl_move_reuse
whose RHS predicts the new position of the object(mk.val X: position P1:)
.How does AERA assign the variables for
X
andP1
(during forward chaining)? The new positionP1
comes directly from the LHS imdl which containsP1
. The value forX
comes from the requirement created by the RHS ofmdl_move_reuse_req
. This has a value because it came from the icst on the requirement model's LHS.In summary, all of the variables on the RHS of
mdl_move_reuse
are mentioned in other places where they can be bound with a value. However if a variable is not mentioned in other places, it is called a "free variable". If the RHS has a free variable then the prediction made from the RHS will have an unbound variable, which we don't want. Consider the following reuse model created by CTPX:This is very similar except that
mdl_displace
does not predict the new position of the hand. It only predicts that hand will not be at positionP0
after a displacement. (mdl_displace
has an anti-fact on the RHS which doesn't haveP1
. SIDENOTE: Instead of this pull request, a solution could be for CTPX to handle models that have an anti-fact on the RHS in a special way, for example in this case to predict that the objectX
will not be atP0
.) Therefore, when the model fires it produces the imdl(imdl mdl_displace [P0: (ti T0: T1:)] [H: DeltaP: T2B: T2B:])
. This is similar to the imdl above formdl_move
except that there is noP1
. The RHS of the reuse model is(mk.val X: position P1:)
but in this caseP1
is a free variable. A prediction made from the RHS of this reuse model would have an unbound variable, which we don't want. When CTPX creates a model like this, we need to detect it and discard the model.When CTPX builds the models, it first builds a causal model
m0
, then calls the methodCTPX::build_requirement
to build the related requirement modelm1
. This pull request updates this method as follows to check if the RHS ofm0
has a free variable.m0
. In the example above these areX
andP1
. (We ignore the timing variables likeT2
andT3
).m0
. In the example above, this is the reused imdl such as(imdl mdl_displace [P0: (ti T0: T1:)] [H: DeltaP: T2B: T2B:])
. If it is mentioned then it is not a free variable, so proceed to keep the model.m0
, most notably in the assignment guards. (This is not the case in the examples above.) If it is mentioned then it is not a free variable, so proceed to keep the model.m1
, then check if this variable is mentioned in the LHS ofm1
. Inmdl_displace_reuse_req
above, the exposed variables are[H: DeltaP: T2B: T2B: X:]
. Note thatX
is also mentioned in the icst on the LHS, butP1
is not in the exposed variables (nor mentioned in the LHS). If the variable is mentioned in the exposed args and also in the LHS ofm1
then it is not a free variable, so proceed to keep the model.false
which discards the model.If you are still following, there is one more point to clarify. In the examples above we use meaningful variable names like
X
. But CTPX uses variables likev8
andv9
. Furthermore, suppose we are checking variablev9
fromm0
. The corresponding variable in the exposed variables ofm1
may be different, such asv8
. Therefore we use the utility functionget_ihlp_exposed_args_position
which performs this mapping.