0

Solution of SVD difference is very high between commons-math3 and ojalgo libraries. Is there any way to reduce the difference based on any input params.

        double[][] olsColumns = { { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 },
                { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 },
                { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 },
                { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 },
                { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 },
                { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 },
                { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 },
                { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 },
                { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 },
                { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 },
                { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 },
                { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 },
                { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 },
                { 1.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 1.0 } };
        double[] observationVector = { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };

//Ojalgo
final PrimitiveDenseStore tmpOriginal = PrimitiveDenseStore.FACTORY.rows(olsColumns);
        SingularValue<Double> tmpSVD = SingularValue.make(tmpOriginal);
        tmpSVD.decompose(tmpOriginal);
        double[] singularValues = tmpSVD.getSingularValues().toRawCopy1D();
        double[][] V = tmpSVD.getQ2().toRawCopy2D();
        System.out.println("V" + Arrays.deepToString(V));
        System.out.println("Singular values" + Arrays.toString(singularValues));
        try {

            // MatrixStore<Double> doubleMat = tmpSVD.solve(tmpOriginal,
            // PrimitiveDenseStore.FACTORY.column(Utils.prepareObservationVector()));
            MatrixStore<Double> solution = tmpSVD.getSolution(PrimitiveDenseStore.FACTORY.column(observationVector),
                    tmpSVD.preallocate(tmpOriginal));
            System.out.println("Solution " + Arrays.toString(solution.toRawCopy1D()));
        } catch (Exception e) {
            e.printStackTrace();
        }

//Commons-Math3

        RealMatrix newPredM = new Array2DRowRealMatrix(olsColumns);
        SingularValueDecomposition svd = new SingularValueDecomposition(newPredM);
        // RealMatrix covariance = svd.getCovariance(0);
        // System.out.println("covariance"+Arrays.deepToString(covariance.getData()));
        System.out.println("V" + Arrays.deepToString(svd.getV().getData()));
        System.out.println("Singular values" + Arrays.toString(svd.getSingularValues()));
        double[] solution = svd.getSolver().solve(new ArrayRealVector(observationVector)).toArray();
        System.out.println("Solution" + Arrays.toString(solution));

Commons Math3 Solution: [0.01612903225806451, 0.016129032258064502]

OjAlgo Solution Solution: [7.614155324982286E13, -7.614155324982295E13]

Guillaume
  • 14,306
  • 3
  • 43
  • 40
Sudheer
  • 5
  • 2

1 Answers1

0

Which version of ojAlgo are you using?

When I try that code I get an exception because the "preallocated" matrix you supply to the tmpSVD.getSolution(...) method is the wrong size/shape. If you simply remove that second argument the allocation is done for you and the code works. I get this result:

V[[0.707106781186548, -0.707106781186547], [0.707106781186547, 0.707106781186548]]
Singular values[13.638181696985853, 9.035878689445474E-15]
Solution [0.016129032258064484, 0.01612903225806446]
apete
  • 1,250
  • 1
  • 10
  • 16
  • the version I have used is Manifest-Version: 1.0 Implementation-Title: ojAlgo Implementation-Version: 47.1.2 – Sudheer Jun 25 '19 at 11:52
  • I get below error when I remove the second argument of tmpSVD.getSolution(...) java.lang.ArithmeticException: / by zero at org.ojalgo.matrix.store.operation.MultiplyBoth.lambda$static$12(MultiplyBoth.java:556) at org.ojalgo.matrix.store.PrimitiveDenseStore.fillByMultiplying(PrimitiveDenseStore.java:768) at org.ojalgo.matrix.decomposition.RawSingularValue.doGetInverse(RawSingularValue.java:541) at org.ojalgo.matrix.decomposition.RawSingularValue.getSolution(RawSingularValue.java:178) at org.ojalgo.matrix.decomposition.RawSingularValue.getSolution(RawSingularValue.java:173) – Sudheer Jun 25 '19 at 11:56
  • The latest release is v47.2.0. There has been work on related parts of ojAlgo lately. Maybe this has been fixed then. Try using what's in the development branch: https://github.com/optimatika/ojAlgo/compare/master...develop – apete Jun 25 '19 at 12:06
  • I have tried with v47.2.0 the output is same but I had to remove second argument of tmpSVD.getSolution(...) . I cloned the dev branch shared and build the artifacts and with those artifacts, I got the same output mentioned in your answer. I have 2 more questions 1. When will the v47.3.0 available on maven repository, any timeline 2. Is second argument no more needed for getSolution method. – Sudheer Jun 25 '19 at 13:50
  • The second argument is, and always has been, optional. It's there to allow for efficient memory usage.Open an issue at GiHub regarding the bug. – apete Jun 25 '19 at 17:49