Thu, 08/06/2009 - 18:22

Shouldn't matrices of type "Symm" only take one triangle of data? Otherwise you can do this: run runs fine, but sees asymmetrical values in the matrix

s <- mxMatrix(type="Symm", 3, 3,

c(FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE),

c(1, .9, .8, .8, 1, .8, .8, .8, 1),

c(NA, "free1", "free2", "free1", NA, "free3", "free2", "free3", NA))

s

Greetings all,

I am not sure this is the best place to post this but I have encountered a rather odd quirk with the mxMatrix command.

There is a shortcut in Chapter 3 of the documentation that uses 'T' & 'F' instead of the full 'TRUE' and 'FALSE' for the specification of the free parameters in the matrix. However this shortcut only works if the matrix is not of type 'Symm'. Otherwise it throws and error:

Error: Illegal number of elements (###) for free matrix in SymmMatrix constructor.

Changing the free parameter values to 'TRUE' & 'FALSE' fixes it, but this is allowed for matrices of type 'Full'.

Both ways work the same.

Type "T" and "F" into R to see what they are set too... I'm guessing not to TRUE and FALSE

The 1-char codes are a very handy short-cut, but rely on the user not changing them to other values.

Caught me once (there's a post here to prove it). good practice from time to time to say:

if(T==TRUE & F==FALSE){

"OK"

} else {

"oops"

}

Hmmm, so it does.

I wonder where I was encountering that error then? I was getting this on the 4th of this month, and I haven't updated any of the packages... strange.

Good to see it is working :)

Disregard my previous post.

-Joel

an MxMatrix doesn't have a slot for its row or column count.

If we want to get the size of an mxMatrix, we should get the size of its values then get the dim of that?

dim(matrix@values)

--> [3,3]

Thanks Michael!

cLabels = c(

+ "v1c1", NA, NA,

+ "v2c1", "v2c2", NA,

+ "v3c1", "v3c2", "v3c3"

+ )

>

> cMatrix = mxMatrix("Lower", nrow=3, ncol=3, free=TRUE, values=.5, labels=cLabels, name="c") #

Error: Upper triangle of labels matrix in lower matrix 'c' is not all NAs!

The error message seems wrong or misleading. the upper triangle was all NAs.

byrow=TRUE?

hmm.. yes setting byrow=TRUE fixes that error... but sending just the lower triangle in row order works without altering byrow:

cLabels = c(

"v1c1",

"v2c1", "v2c2",

"v3c1", "v3c2", "v3c3"

)

cMatrix = mxMatrix("Lower", nrow=nVar, ncol=nVar, free=TRUE, values=.5, labels=cLabels, name="c")

So the default direction changes depending on whether you give a lower or a full set of values: if full, byrow=FALSE is the default, but if only a lower is given, then that fills as if byrow=TRUE?

Umm, I tried the example you just gave and the lower triangle of labels was populated by columns, just as you told it to be populated.

Ouch. I see that now. Missed that bad bottom left entry.

Sorry for the false alarm.

I guess, then, I would like the default setting for by row to be TRUE.

I've thought some about that. And it is tempting. But nothing else in R has byrow=TRUE as a default. This is likely due to the dependence on CBLAS. But for whatever reason, R has byrow=FALSE defaults even when they don't make sense. (try using the defaults on write() on a data file and the read it back in with read.table() if you want some confusion)

Anyway, if people want to override defaults in R, they can do so. They can use the same methods to do so for OpenMx. But I think it would cause more confusion rather than less if we do things opposite of R's defaults.

Based on the discussion of today's developer meeting, a global option in R will be added to select the default behavior of the byrow argument. The standard value for this option will be FALSE. Any documentation on the website should assume the standard value of FALSE.

As of revision 773, use options('mxByrow' = TRUE) to change the default behavior of the byrow argument in the mxMatrix() function.

I think in R you can find a counter-example for any consistency :-)

In general, my argument (and yours too I think from what you say?) would be that our defaults should reflect the common settings that users want, not the common setting programmers chose.

Anyhow: I'll leave it to the hive mind, having made my buzz :-)

Off too add byrow=TRUE to everything...

Yep, byrow=TRUE produces the correct result in either the NAs case or the lower triangular input case. No switching involved. If you want to input a vector into your matrices in this form:

always use byrow=TRUE.

Q: Convert "Full" to "Lower"?

Is there a way in OpenMx to convert a matrix from Full to Lower?

I would like to be able to say mxMatrix(, "Lower", fullMatrixIPreparedEarlier)

But of course if you input the values matrix of a Full, it barfs on the non NA values in the upper triangle...

At the moment, error checking happens when you run the model. So in your example above, mxRun(mxModel(s)) will throw an error. If the user inputs only one triangle of data, then the lower triangle and upper triangle are populated with those values.

This example points out that there are two classes of errors.

A. Some errors result in problems that are encapsulated within a single mxFoo function call.

B. Other errors are only evident when the entire model is evaluated together.

Tim Bates example is a Class A error. Catching Class A errors at their source is a service to the user since it localizes (both in space and time) their debugging.

I've added error checking to the mxMatrix() function. I can see the possibility of the user wanting to create an incomplete and invalid matrix to use as a template. But the verification call is exactly one line, so its easy to reverse this decision.

Thanks mike!

In the same vein:

'Diag'

error if nrow != ncol. : "Symmetrical matrices must be square: You provided %i rows and %i columns!"

error if any values off the diagonal are free : "Error in matrix %name: No off-diagonal cells in an Diagonal matrix can be free"

error if any values off the diagonal are != 0 : "Error in matrix %name: All values off the diagonal of an Diagonal matrix must be 0"

'Iden'

error if nrow != ncol. : "Symmetrical matrices must be square: you provided %i rows and %i columns!"

error if any values are free : "Error in matrix %name: No cells in an Identity matrix can be free"

error if any values on the diagonal are != 1 : "Error in matrix %name: All values on the diagonal of an Identity matrix must be 1"

error if any values off the diagonal are != 0 : "Error in matrix %name: All values off the diagonal of an Identity matrix must be 0"

'Symm'

error if (nrow != ncol) : "Symmetrical matrices must be square: you provided %i rows and %i columns!"

done

error if any values are not mirrored in the upper and lower triangles

'Unit'

error if any values are free : "Error in matrix %name: No cells in a Unit matrix can be free"

error if any value != 1 : "Error in matrix %name: All values in a Unit matrix must be 1"

'Zero'

error if any values are free : "Error in matrix %name: No cells in a Zero matrix can be free"

error if any values != 0 : "Error in matrix %name: All values in a Zero matrix must be 0"

Thanks for the fix. I think it's the right thing to do. In my opinion, the number of people helped by proximal error checking in this case will exceed the number of people frustrated. And the person who is frustrated will just say, "oh, I guess I couldn't fool the program that way." and maybe figure out that procedural model definition will help him/her get the same job done faster/easier anyway.

Indeed: Much nicer to catch things when they occur - and much easier to give meaningful feedback

"You provided asymmetrical input to symmetrical matrix 'A' "

rather than

"Model parser got unexpected value, expected matrix" or similar.

Would it be desirable to throw an error on getting value array of length other than sigma(n) where n=1 to nrow?

Or is that just making life unnecessarily hard? It would make it impossible to commit the asymmetrical symm-matrix error.