1

I have a moderately large Ax = b problem that I want to solve. Matrix A is 600x600.

My code solves the problem, but takes unusually long time to do so. So, I tried to check (with System.currentTimeMillis()) to see where my code slows down.

It turns out, that during the calculations of A, I execute the command A = L1 * A0 * L1.transpose(). The process consumes almost 100% of its total time in this line.

A weird thing is, L1 is a 600x600 unit matrix (that is, A[i,j] = 1, if i == j and 0, otherwise). So, this line should not really take that long to execute. It should also be easy to bypass in this problem

An even weirder thing though, happens if I try to bypass that line by commenting it out and replacing it with A = A0. Then the code takes way too long (after 10x the original time I killed it) to execute. Also, the CPU usage reaches 100%.

I checked, and it turns out that A and L1 * A0 * L1.transpose() are identical.

To sum up, using a part of my Java code (I use library ojalgo for handling matrices):

// PrimitiveMatrix A0, L1, b are already calculated.

long startTime = System.currentTimeMillis();
System.out.println((System.currentTimeMillis() - startTime0) / 1000.0); // this prints about 2 seconds, concerning calculations of A0, L1, b.

PrimitiveMatrix A = L1.multiply(A0).multiply((L1).transpose());
System.out.println((System.currentTimeMillis() - startTime0) / 1000.0);  // this prints about 67 seconds    

// PrimitiveMatrix A = A0; // if this is NOT a comment, then the code has not run after (10+)x my "normal" time 

final PrimitiveMatrix x = (A.invert()).multiply(b);

System.out.println((System.currentTimeMillis() - startTime0) / 1000.0);  // this prints about 69 seconds  

// I checked that
// A0.equals(L1.multiply(A0).multiply((L1).transpose())
// returns true

This whole process takes about 69 seconds, and 65 of them are consumed in a trivial calculation, that I have failed to bypass. The same procedure has run successfully in the past for smaller matrices (60x60).

I am not really sure how to proceed with my debugging attempts. Any help would be greatly appreciated.

It seems the problem runs a little deeper than I had originally estimated. I tried to print those matrices in order to upload them, but then another problem appeared. I found out that my code crashes the very first time I run System.out.println(A0.get(aRow,aColumn));. A0 was created by adding numbers of type double to every position of a zero matrix with dimensions 600x600. In addition, the following messages appear:

       Exception in thread "main" java.lang.StackOverflowError
    at org.ojalgo.matrix.store.SuperimposedStore.get(SuperimposedStore.java:84)
    at org.ojalgo.matrix.store.SuperimposedStore.get(SuperimposedStore.java:84)
    at org.ojalgo.matrix.store.SuperimposedStore.get(SuperimposedStore.java:84)
...

Again, I want to emphasize that the same process runs normally when those matrices are 60x60.

apete
  • 1,250
  • 1
  • 10
  • 16
Nick Simos
  • 67
  • 4
  • 2
    Since you don't define/initialize L1, I think we have 0% chance of determining why this code runs slowly. Please post a [minimal, runnable example.](http://stackoverflow.com/help/mcve) – markspace Sep 19 '16 at 16:48
  • You have not provided enough information for anyone to help. How are the various matrices created? The internals of a PrimitiveMatrix is determined by how it was created. What version of ojAlgo are you using? – apete Sep 19 '16 at 20:30
  • @markspace as I mentioned above, L1 is a `600x600` unit matrix (that is, L1[i,j] = 1, if i == j and 0, otherwise). – Nick Simos Sep 20 '16 at 08:37
  • @apete please read again the updated version of my question. It seems that the problem occurs when trying to get a number from those matrices. Also, I use ojAlgo 38.1. – Nick Simos Sep 20 '16 at 08:42

1 Answers1

2

I assume you're using BasicMatrix#add(int,int,Number)

Did you call that method 600x600 times to build your matrix? You should NOT do that!

In newer versions of ojAlgo that method has been removed because it was often misunderstood/misused.

You should read this: https://github.com/optimatika/ojAlgo/wiki/Getting-Started

apete
  • 1,250
  • 1
  • 10
  • 16
  • Your assumption was dead right! However, the matrix is of type PrimitiveMatrix (I'm not sure about the difference). Also, I read your link, but I'm not sure what I should do instead. I want to fill a `600x600` PrimitiveMatrix with values of smaller matrices. That's why I created a zero `600x600` matrix and added those values in it. What is the most appropriate way to do this? P.S Sorry, but I am new to Java and ojAlgo. – Nick Simos Sep 20 '16 at 13:21
  • Read this again. https://github.com/optimatika/ojAlgo/wiki/Getting-Started Specifically the "Creating matrices by explicitly setting all elements" section of the example code. – apete Sep 20 '16 at 15:26
  • You are right about this but in ojAlgo 38.1 I can't import `org.ojalgo.matrix.BasicMatrix.Builder`. Is there any way to use PrimitiveDenseStore and then turn it into PrimitiveMatrix? The rest of the matrices are of type PrimitiveMatrix, so I need this matrix also in this form. – Nick Simos Sep 20 '16 at 15:36
  • I updated my version of ojAlgo and followed your instructions, so now problem seems to have been solved! Thank you very much! – Nick Simos Sep 20 '16 at 18:56