This project has moved and is read-only. For the latest updates, please go here.

Matrix type compatibility

Dec 10, 2010 at 12:27 AM

Hi David,

First of all, thank you for sharing the code. I appreciate the simplicity of being able to do matrix math in a similar way to MATLAB. I am however having an issue. I have a fairly complex matrix expression containing both square and rectangular matrices which the compiler doesn't seem to like.

I have 3 matrices: a 6x6 SquareMatrix S, a 6x7 Matrix H, and a 7x7 SquareMatrix E. I want to compute:

S = H * E * H.Transpose(); 

but it says >>> Cannot implicitly convert type 'Meta.Numerics.Matrices.Matrix' to 'Meta.Numerics.Matrices.SquareMatrix' <<< However, I need S.Inverse() later so I need it to be a SquareMatrix. I'm sure there is an easy solution that will allow me to convert a regular Matrix to a SquareMatrix but I can't figure it out.

Any help would be appreciated.


Dec 10, 2010 at 4:00 PM

And while I'm at it, is there a nice way to negate a matrix? The "-" operator doesn't seem to be supported. i.e M1 = -M2 * M3?

Dec 12, 2010 at 9:32 AM
Edited Dec 12, 2010 at 9:15 PM

Hi! While what you want to do makes perfect sense mathematically, it's hard to get a type-safe object-oriented langauge to do it. That's because the compiler demands that the types of your expressions be known to it at compile-time, based only on the types that they are composed from. Since you could multiply a rectangular matrix by a square matrix by a rectangular matrix and not get a square matrix (e.g. 2X3 * 3X3 * 3X4), the compiler can't be sure that the result is square. In order to recoginze that it's square in this case, it would need to look at the dimensions of these particular instances, which there is no way to get it to do.

I have considered several times collapsing square and rectangular matrices into a single type, which would just throw an InvalidOperationException if you tried to invert a non-square matrix or do some other operation that doesn't make sense. That would eliminate this particular problem. But it would cause others (e.g. shifting an invalid inversion from a compile-time to a run-time error), and the problem would still exist for other specialized matrix types like symmetric and tri-diagonal.

At the moment the best suggestion I can offer is to copy your result into a SquareMatrix and then invert it. That is inefficient, but not worringly so when you consider that such a copy operation is O(N^2) and the inversion you want to do on it is O(N^3).

For 2.0, I will look at providing an explicit cast so you could write (SquareMatrix) H * E * H.Tranpose() when you know that you should get a square matrix. (The cast would throw and InvalidOperationException if you were wrong.) I will also add a matrix negation operator. (For the moment, you should be able to get the same effect by multiplying by -1.0, e.g. M1 = -1.0 * M2 * M3.)

I am very interested to learn what you find hard and what you find easy about Meta.Numerics' object model. For example, one of the things you can do with MATLAB but not with Meta.Numerics is operate on sub-matrices (using MATLAB's : notation). Is that something you miss or is it not that important? Are there any other gotchas or missing features that are important for you?

Dec 16, 2010 at 4:52 PM

Thanks for the reply.

The copying thing should work for my purposes. I don't think that it will cause my any grief efficiency wise. I'm probably doing something a lot worse elsewhere in my code :P

And of course the multiplying by -1.0 * M2 is exactly what I want to do. I'm a little embarrassed actually that I didn't just put that together on my own. I guess I'm a little too MATLAB reliant these days and I mentally shut-down when the same syntax didn't work.

Thanks so much for the library. As for additional features, I can suggest a few but they're not overly complex. Someone could pretty easily add them as methods in their own code but they would be nice to have prepackaged:

   1. A fill method or equivalent - i.e. something that will put a value for every entry in the matrix.

   2. A diagonal fill - same as above but only for diagonal entries

   3. a normalize method (for vectors) - just to scale the entries down so the 2-norm of the vector is unity, i.e. the MATLAB equivalent of vector = vector  ./ norm(vector)

That's all I've got off the top of my head. And forgive me if some of these are already included; I haven't had a great deal of time to explore what's already there just yet.

Thanks again for a great library.