Mon, 03/28/2011 - 19:20

Imagine I want to create the following model:

I try creating this model fragment using the following R code:

lVars <- c('a', 'b') freeParams <- c('p1', 'p2', 'p3') model <- mxModel('model', type = 'RAM', latentVars = lVars, mxPath(from = lVars, to = lVars, arrows = 2, all = TRUE, labels = freeParams))

But this code generates the model:

What happened here? The explanation: When the mxPath() function is called with all = TRUE, it will generate n x m paths, where n is the length of 'from' argument and 'm' is the length of the 'to' argument. Keep in mind that when a path is created, it will clobber any existing path that has the same 'from', 'to', and number of arrows. In the case of symmetric paths, the 'from' and 'to' arguments can be switched with impunity. So the following paths are created:

From | To | Label |
---|---|---|

a | a | p1 |

a | b | p2 |

b | a | p3 |

b | b | p1 |

This is a bug, right? The expected behavior when all = TRUE and arrows = 2 is not to clobber 1/2 of the generated paths. Does anyone have an example where the behavior shown here is the desired behavior?

Attachment | Size |
---|---|

correct.jpg | 69.54 KB |

incorrect.jpg | 69.4 KB |

Update: the following code snippet now works in the source code repository, as of revision 1738. This functionality will be available in OpenMx 1.2.

I advocate that the behavior is a bug. If 'arrows' is '1' and 'all' is 'TRUE', then the number of paths should be |to| x |from| for all cases.

If 'arrows' is '2' and 'all' is 'TRUE', then the number of paths should be |to| x |from| if and only if 'to' and 'from' contain non-overlapping elements. If 'to' and 'from' contain overlapping elements, then the mxPath() function should not generate duplicate paths that overwrite old paths.

I think the guiding rule should be that the function never stomps on something that this call to it created.

That would mean

1. accumulating a list of from-to paths

2. removing duplicates (including mirror images)

3. then creating them, using the provided labels.

Only if the final list doesn't match the label length should a warning be thrown.

This way from and too lists can overlap partly or completely and you always get one connection from everthing on the left to everything on the right, which is a nice intention-oriented interpretation of "ALL" as "all unique combinations".

We need to think about consistency with other functions, too.

`paste()`

doesn't have an`all=TRUE`

flag, but we're in the process of implementing`mxPaste()`

that does. We will want the behavior of`mxPaste()`

to be consistent with`mxPath()`

for any value of 'arrows'.That is, we want to be able to do

`mxPath(from=latents, to=latents, arrows=x, all=TRUE, labels=mxPaste(latentNames, latentNames, all=TRUE))`

to work regardless of whether x is 1 or 2.There's also the complexity argument--at least with the current setup, the behavior is always the same. In this set up, what happens if from and to are overlapping but not identical? What if there are duplicates in from= or to=? We at least need a simple guiding rule.

The prospect of creating a path then immediately klobbering it doesn't seem right either--if we can come up with an easy guiding rule, I think I can get behind the change in semantics. What is the easy way to automatically generate labels for

`mxPath(from=vars, arrows=2, all=TRUE)`

?What about

`mxPath(from=vars1, to=vars2, arrows=2, all=TRUE)`

if vars1 and vars2 are overlapping but not identical? (When I ran this by Mike Spiegel, he validly asked "when would anyone do that?" I don't have an answer, so if anybody does, please let me know.)Either way, I tend to agree with Ryne--it makes sense to at least throw a warning if people provide a the number of elements being labeled that isn't a clean multiple of the number of labels. Yes, people will probably ignore it. But at least we tried. This warning-throwing behavior for mismatched numbers of values is pretty common in R.

So this should be smarter, but we run the risk of having different functionality for 1 and 2 headed arrows. One way to restate what you're pointing out is that when arrows=2, mxPath populates a symmetric matrix, so our usual tricks for populating symmetric matrices should work. The difference between mxPath and mxMatrix is that mxMatrix requires that the vector of labels be a multiple of the number of elements in the matrix, whereas mxPath allows you to supply 3 labels for four paths.

This is a bigger discussion, and one I would have thought we'd have had before. I think at least a warning is warranted, depending on whether we're telling people that they gave 3 labels for 4 paths or telling them that they assigned the same parameter two different labels.

Just as a reminder, this is what we do if someone tried to pull Mike's dual assignment of the a b covariance in a matrix:

"all" is is every-possible, so I think this is doing the requested behaviour, but no-one would desire it :-)

So I think you are requesting and getting

from a to a

from a to b

from b to a

from b to b

When the third path is not wanted, and shifts your labels.

I accomplish this using

Should look like this:

not this