I implemented the square bracket operator for MxAlgebra expressions. In an algebra it is now possible to write A[x, y] or A[,y] or A[x,] or A[,]. x and y must be either numeric literal values, or they can also be an arbitrary 1 x 1 matrices if you want to get fancy. A lion's share of the credit should be attributed to Tim Brick. The matrix operator and function interface that we designed made it fairly easy to implement this operator. It seemed like the square-bracket operator might be useful. See models/passing/AlgebraComputePassing.R for some examples.

For developers: in R the expression A[x,] is parsed as a function with three arguments. The three arguments are A, x, and "". The OpenMx library will now translate any "" it sees inside an algebra expression into a 0 x 0 constant matrix. This is legitimate because we have forbidden the use of "" as either a free/fixed parameter label or the name of an entity. I don't know if this trick will be recycled for other uses, but feel free to use it.

One comment on the current changes: I decided that A[x,] should return a row matrix and A[,y] should return a column matrix. This is different from the behavior in R. R will return a vector in either case (not a matrix). It would appear that when vector and matrix are used in R in an operation, the vector is converted to the "correct" dimensions to make the operation succeed. Thoughts on my implementation? Should both cases return a row matrix? Should both cases return a column matrix? Currently conformability testing will succeed on some error conditions because R is flexible with vectors and matrices. I believe I can convert the A[x,] expressions into the correct as.matrix() expressions inside the mxEval(compute=TRUE) call. Any problems with this approach?

Nifty!

I intuit that this is the correct behavior; it is what I would expect.

Do you think that doing things at variance with what R does will be problematic? My feeling is that it's better to have matrices of everything, so that we can continue algebraic operations with them. Otherwise formulae would end up full of as.matrix() functions, I suspect.

Yeah, I'm going to implement tonight the change in mxEval() that inserts as.matrix() or t(as.matrix()) around expressions of the form A[x,] or A[,y] so that mxEval() will always return a matrix just like the back-end. Otherwise we can't match the native behavior in R, because we don't want to support vectors in the back-end.

I committed the changes such that conformability checking is in effect. So if A and B are 3 x 3 matrices, then mxEval(A[1,] + B[2,], compute=TRUE) will succeed but mxEval(A[1,] + B[,2], compute=TRUE) will throw an error. This is good stuff because the conformability checking in OpenMx uses mxEval(...,compute=TRUE) to check the dimensions of algebra expressions.

> I decided that A[x,] should return a row matrix

> and A[,y] should return a column matrix.

That will be helpful for users: More so than getting a row or column when asking for the other.

I also agree with this logic. I don't expect it would surprise anyone.

As requested in the last developers meeting, when using the square bracket operator A[x,y] then x or y can be either a string or a global variable that stores a string. The string should be a row or column name of the matrix/algebra A, or an error is thrown. This has been implemented in revision 981. Note that if you attempt to use a string inside an MxAlgebra expression in any other context, then you will get an error message.

As discussed at the last developer's meeting, the square-bracket operator can now be used in MxMatrix labels just as it can be used in MxAlgebra expressions. Previously the square-bracket operator was restricted to constant values for row and column argument when the operator was used in a MxMatrix label. You can see an example of the new notation here: http://openmx.psyc.virginia.edu/repoview/1/trunk/models/failing/MultilevelLongFormatFailing.R.

There was some trickery in autoboxing the MxMatrix label into an MxAlgebra expression. The hard part was not the translation itself, but rather hiding any effects of the translation from the user. I say this only because I have tested a number of error conditions. But some error condition will probably surface that I have not imagined. So have fun.