/** * @param data dense matrix represented in row-major form * @return solver for the system Ax = b */ static Solver getSolver(double[][] data) { if (data == null) { return null; } RealMatrix M = new Array2DRowRealMatrix(data, false); double infNorm = M.getNorm(); double singularityThreshold = infNorm * SINGULARITY_THRESHOLD_RATIO; RRQRDecomposition decomposition = new RRQRDecomposition(M, singularityThreshold); DecompositionSolver solver = decomposition.getSolver(); if (solver.isNonSingular()) { return new Solver(solver); } // Otherwise try to report apparent rank int apparentRank = decomposition.getRank(0.01); // Better value? log.warn("{} x {} matrix is near-singular (threshold {}). Add more data or decrease the " + "number of features, to <= about {}", M.getRowDimension(), M.getColumnDimension(), singularityThreshold, apparentRank); throw new SingularMatrixSolverException(apparentRank, "Apparent rank: " + apparentRank); }
@Override public Solver getSolver(RealMatrix M) { if (M == null) { return null; } RRQRDecomposition decomposition = new RRQRDecomposition(M, SINGULARITY_THRESHOLD); DecompositionSolver solver = decomposition.getSolver(); if (solver.isNonSingular()) { return new CommonsMathSolver(solver); } // Otherwise try to report apparent rank int apparentRank = decomposition.getRank(0.01); // Better value? log.warn("{} x {} matrix is near-singular (threshold {}). Add more data or decrease the value of model.features, " + "to <= about {}", M.getRowDimension(), M.getColumnDimension(), SINGULARITY_THRESHOLD, apparentRank); throw new SingularMatrixSolverException(apparentRank, "Apparent rank: " + apparentRank); }
/** * Calculates the parameters of a bivariate quadratic equation. * * @param elevationValues the window of points to use. * @return the parameters of the bivariate quadratic equation as [a, b, c, d, e, f] */ private static double[] calculateParameters( final double[][] elevationValues ) { int rows = elevationValues.length; int cols = elevationValues[0].length; int pointsNum = rows * cols; final double[][] xyMatrix = new double[pointsNum][6]; final double[] valueArray = new double[pointsNum]; // TODO check on resolution int index = 0; for( int y = 0; y < rows; y++ ) { for( int x = 0; x < cols; x++ ) { xyMatrix[index][0] = x * x; // x^2 xyMatrix[index][1] = y * y; // y^2 xyMatrix[index][2] = x * y; // xy xyMatrix[index][3] = x; // x xyMatrix[index][4] = y; // y xyMatrix[index][5] = 1; valueArray[index] = elevationValues[y][x]; index++; } } RealMatrix A = MatrixUtils.createRealMatrix(xyMatrix); RealVector z = MatrixUtils.createRealVector(valueArray); DecompositionSolver solver = new RRQRDecomposition(A).getSolver(); RealVector solution = solver.solve(z); // start values for a, b, c, d, e, f, all set to 0.0 final double[] parameters = solution.toArray(); return parameters; }
@Override public boolean isNonSingular(RealMatrix M) { QRDecomposition decomposition = new RRQRDecomposition(M, SINGULARITY_THRESHOLD); DecompositionSolver solver = decomposition.getSolver(); return solver.isNonSingular(); }