0

I am using parallel colt wherein I need to find the rank of a matrix. The API documentation says the following about the following about DoubleAlgebra#rank:

rank(DoubleMatrix2D A)

Returns the effective numerical rank of matrix A, obtained from Singular Value Decomposition.

But when I use it in my code, I get an IllegalArgumentException at runtime:

Exception in thread "main" java.lang.IllegalArgumentException: Matrix must be dense
    at cern.colt.matrix.tdouble.algo.DoubleProperty.checkDense(Unknown Source)
    at cern.colt.matrix.tdouble.algo.decomposition.DenseDoubleSingularValueDecomposition.<init>(Unknown Source)
    at cern.colt.matrix.tdouble.algo.DenseDoubleAlgebra.svd(Unknown Source)
    at cern.colt.matrix.tdouble.algo.DenseDoubleAlgebra.rank(Unknown Source)

The API doesn't mention that a matrix needs to be dense. In my IDE (I use Intellij IDEA), when I ctrl+click the method name in my code, it goes to the source, which shows

public int rank(cern.colt.matrix.tdouble.DoubleMatrix2D doubleMatrix2D) { /* compiled code */ }

Bottomline, everywhere I see the requirement for a DoubleMatrix2D object, not a DenseDoubleMatrix2D object. Any idea why the runtime exception happens?

Community
  • 1
  • 1
Chthonic Project
  • 8,216
  • 1
  • 43
  • 92
  • Can you show us something about the matrix you're trying to calculate the rank of? What does it look like? What class instance is it? – ashes999 Jan 27 '14 at 19:38
  • How would you perform [Singular Value Decomposition](http://en.wikipedia.org/wiki/Singular_value_decomposition) with a sparse matrix? – Elliott Frisch Jan 27 '14 at 19:38

1 Answers1

0

It seems like, as the message says, it really does need a DenseDoubleMatrix2D instance.

Here's what the source traces through (simplified with A kept the same name throughout):

DoubleAlgebra.rank(DoubleMatrix2D A): return svd(A).rank();
  > svd(DoubleMatrix2D A): return new DenseDoubleSingularValueDecomposition(A, true, true);
    > DenseDoubleSingularValueDecomposition(): checkDense(A);

For checkDense itself:

 public void checkDense(DoubleMatrix2D A) {
     if (!(A instanceof DenseDoubleMatrix2D) && !(A instanceof DenseColumnDoubleMatrix2D))
         throw new IllegalArgumentException("Matrix must be dense");
 }

You can see the actual exception code here.

What you probably want to do is just use an instance of DenseDoubleMatrix2D instead of whatever you're currently sending in.

ashes999
  • 9,925
  • 16
  • 73
  • 124
  • Yes, that's how I managed to get my code working. In fact, I had ended up at the same grepcode page that you have linked. But, since the API only requires a DoubleMatrix2D argument, shouldn't the source code have `checkDense` return boolean, and the `rank` method have something like `if (checkDense(A) == false) A = new DenseDoubleMatrix2D(A.toArray())` ? I guess I am irked more by the undocumented difference between the API and the actual code behavior than anything else. – Chthonic Project Jan 27 '14 at 20:25
  • It's hard to document every requirement. If my answer helped, I would appreciate the upvote/accept. Your question seemed odd though, something like "why is this documentation wrong?" which is impossible to say, unless you're the author :) – ashes999 Jan 27 '14 at 21:13