Exemplo n.º 1
0
  /**
   * Solves for "X" in the equation this * X = B, where X is a DenseMatrix, "this" and "B" will be
   * converted to a DenseMatrix (if not already)
   *
   * @param B AbstractMTJMatrix, will be converted to a DenseMatrix
   * @return DenseMatrix of "X" in this * X = B
   */
  public final Matrix solve(AbstractMTJMatrix B) {
    DenseMatrix X = new DenseMatrix(this.getNumColumns(), B.getNumColumns());

    DenseMatrix Bdense;
    if (B instanceof DenseMatrix) {
      Bdense = (DenseMatrix) B;
    } else {
      Bdense = new DenseMatrix(B);
    }

    DenseMatrix Adense;
    if (this instanceof DenseMatrix) {
      Adense = (DenseMatrix) this;
    } else {
      Adense = new DenseMatrix(this);
    }

    boolean usePseudoInverse = false;
    try {
      Adense.solveInto(Bdense, X);
      usePseudoInverse = false;
    } catch (MatrixSingularException e) {
      Logger.getLogger(AbstractMTJMatrix.class.getName())
          .log(Level.WARNING, "AbstractMTJMatrix.solve(): Matrix is singular.");
      usePseudoInverse = true;
    }

    // Sometimes LAPACK will return NaNs or infs as the solutions, but MTJ
    // won't throw the exception, so we need to check for this.
    // If we detect this, then we'll use a pseudoinverse
    if (!usePseudoInverse) {
      for (int i = 0; i < X.getNumRows(); i++) {
        for (int j = 0; j < X.getNumColumns(); j++) {
          double v = X.getElement(i, j);
          if (Double.isNaN(v) || Double.isInfinite(v)) {
            Logger.getLogger(AbstractMTJMatrix.class.getName())
                .log(Level.WARNING, "AbstractMTJMatrix.solve(): Solver produced invalid results.");
            usePseudoInverse = true;
            break;
          }
        }
        if (usePseudoInverse) {
          break;
        }
      }
    }

    if (usePseudoInverse) {
      // The original LU solver produced a sucky answer, so let's use
      // the absurdly expensive SVD least-squares solution
      return Adense.pseudoInverse().times(Bdense);
    }

    return X;
  }