There has been some discussion of changing the behavior of mxPath() when arrows='2', all=TRUE, and paths from (a,b) and (b,a) are specified. See here [6] for that discussion. I have become convinced that our current implementation of mxPath()
needs some improvement. These improvements are orthogonal to the discussion of 'all=TRUE' for symmetric paths. I will describe the current state of the implementation, and then suggest several improvements.
Current System
A path specification is stored by OpenMx as an S4 objects. It contains the slots '@from', '@to', '@arrows', '@values', '@excludeself', etc. When the all=TRUE argument is used in the mxPath()
function, then each element of the 'from' argument is replicated N times, where N is the length of the 'to' argument. The vector of replicated arguments is stored in the '@from' slot of the S4 object. See here [7] for an example. I don't remember if this implementation was selected as a matter or convenience or performance (see below for performance considerations).
As a consequence of this implementation, the '@excludeself' slot stores a boolean value indicating whether or not to exclude (x,x) paths. It is not possible with the current implementation to drop the '@exludeself' argument from the S4 object and manually weed out (x,x) paths from the '@from' and '@to' vectors, and still maintain consistency with the '@values', '@labels', '@free', etc. vectors. You can try it for yourself, using the link above as an example.
Problems with Current System
- We are breaking the OpenMx philosophy of WYSIWYS (what-you-say-is-what-you-see). The 'all=TRUE' argument is expanded just enough so that R can internally generate all pairs, but notice that all pairs are not explicitly shown.
- We need to carry around the @excludeself state because of the 'all=TRUE' implementation decision.
- If we decided to explicitly expand all the paths in the S4 object, there may be some performance considerations in the OpenMx front-end. The performance consideration would be the extra garbage collection if we need to store a collection of hundreds of paths in a non-compact representation.
Proposal #1
Eliminate the '@excludeself' slot from the S4 MxPath object. Explicitly store all the path information in the S4 object. This proposal has the benefit of simplicity. When the user generates a path object, they see exactly what paths they have generated. It has the drawback of a runtime performance penalty. Another downside is that it is too verbose a representation. For example, if I have generated 50 paths that all have free parameters, then I would see 50 TRUE
values in the '@free' slot when I try to print the MxPath object.
Proposal #2
Keep the '@excludeself' slot and add an '@all' slot to the S4 MxPath object. Then the user will see exactly what they typed into the mxPath()
function when they inspect the MxPath object. We can add a function omxExpandPaths()
that uses the '@excludeself' and '@all' slots to generates an expanded form of the MxPath object. omxExpandPaths() returns a MxPath object with '@exludeself' and '@all' set to FALSE
, but the same paths are stored in the return value as represented in the input value.
Proposal #2 maintains the current performance of the runtime and restores the WYSIWYS property to the MxPath interface.