下面列出了怎么用org.apache.commons.math3.linear.SingularMatrixException的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
@Test(expected=SingularMatrixException.class)
public void testNonInvertible() {
/*
* Overrides the method from parent class, since the default singularity
* threshold (1e-14) does not trigger the expected exception.
*/
LinearProblem problem = new LinearProblem(new double[][] {
{ 1, 2, -3 },
{ 2, 1, 3 },
{ -3, 0, -9 }
}, new double[] { 1, 1, 1 });
AbstractLeastSquaresOptimizer optimizer = createOptimizer();
PointVectorValuePair optimum = optimizer.optimize(100, problem, problem.target, new double[] { 1, 1, 1 }, new double[] { 0, 0, 0 });
Assert.assertTrue(FastMath.sqrt(problem.target.length) * optimizer.getRMS() > 0.6);
optimizer.computeCovariances(optimum.getPoint(), 1.5e-14);
}
@Override
@Test(expected=SingularMatrixException.class)
public void testNonInvertible() {
/*
* Overrides the method from parent class, since the default singularity
* threshold (1e-14) does not trigger the expected exception.
*/
LinearProblem problem = new LinearProblem(new double[][] {
{ 1, 2, -3 },
{ 2, 1, 3 },
{ -3, 0, -9 }
}, new double[] { 1, 1, 1 });
AbstractLeastSquaresOptimizer optimizer = createOptimizer();
PointVectorValuePair optimum
= optimizer.optimize(new MaxEval(100),
problem.getModelFunction(),
problem.getModelFunctionJacobian(),
problem.getTarget(),
new Weight(new double[] { 1, 1, 1 }),
new InitialGuess(new double[] { 0, 0, 0 }));
Assert.assertTrue(FastMath.sqrt(optimizer.getTargetSize()) * optimizer.getRMS() > 0.6);
optimizer.computeCovariances(optimum.getPoint(), 1.5e-14);
}
@Override
@Test(expected=SingularMatrixException.class)
public void testNonInvertible() {
/*
* Overrides the method from parent class, since the default singularity
* threshold (1e-14) does not trigger the expected exception.
*/
LinearProblem problem = new LinearProblem(new double[][] {
{ 1, 2, -3 },
{ 2, 1, 3 },
{ -3, 0, -9 }
}, new double[] { 1, 1, 1 });
AbstractLeastSquaresOptimizer optimizer = createOptimizer();
optimizer.optimize(100, problem, problem.target, new double[] { 1, 1, 1 }, new double[] { 0, 0, 0 });
Assert.assertTrue(FastMath.sqrt(problem.target.length) * optimizer.getRMS() > 0.6);
optimizer.getCovariances(1.5e-14);
}
@Override
@Test(expected=SingularMatrixException.class)
public void testNonInvertible() {
/*
* Overrides the method from parent class, since the default singularity
* threshold (1e-14) does not trigger the expected exception.
*/
LinearProblem problem = new LinearProblem(new double[][] {
{ 1, 2, -3 },
{ 2, 1, 3 },
{ -3, 0, -9 }
}, new double[] { 1, 1, 1 });
AbstractLeastSquaresOptimizer optimizer = createOptimizer();
optimizer.optimize(100, problem, problem.target, new double[] { 1, 1, 1 }, new double[] { 0, 0, 0 });
Assert.assertTrue(FastMath.sqrt(problem.target.length) * optimizer.getRMS() > 0.6);
double[][] cov = optimizer.getCovariances(1.5e-14);
}
@Override
@Test(expected=SingularMatrixException.class)
public void testNonInvertible() {
/*
* Overrides the method from parent class, since the default singularity
* threshold (1e-14) does not trigger the expected exception.
*/
LinearProblem problem = new LinearProblem(new double[][] {
{ 1, 2, -3 },
{ 2, 1, 3 },
{ -3, 0, -9 }
}, new double[] { 1, 1, 1 });
AbstractLeastSquaresOptimizer optimizer = createOptimizer();
PointVectorValuePair optimum = optimizer.optimize(100, problem, problem.target, new double[] { 1, 1, 1 }, new double[] { 0, 0, 0 });
Assert.assertTrue(FastMath.sqrt(problem.target.length) * optimizer.getRMS() > 0.6);
optimizer.computeCovariances(optimum.getPoint(), 1.5e-14);
}
@Override
@Test(expected=SingularMatrixException.class)
public void testNonInvertible() {
/*
* Overrides the method from parent class, since the default singularity
* threshold (1e-14) does not trigger the expected exception.
*/
LinearProblem problem = new LinearProblem(new double[][] {
{ 1, 2, -3 },
{ 2, 1, 3 },
{ -3, 0, -9 }
}, new double[] { 1, 1, 1 });
AbstractLeastSquaresOptimizer optimizer = createOptimizer();
PointVectorValuePair optimum
= optimizer.optimize(new MaxEval(100),
problem.getModelFunction(),
problem.getModelFunctionJacobian(),
problem.getTarget(),
new Weight(new double[] { 1, 1, 1 }),
new InitialGuess(new double[] { 0, 0, 0 }));
Assert.assertTrue(FastMath.sqrt(optimizer.getTargetSize()) * optimizer.getRMS() > 0.6);
optimizer.computeCovariances(optimum.getPoint(), 1.5e-14);
}
@Override
@Test(expected=SingularMatrixException.class)
public void testNonInvertible() {
/*
* Overrides the method from parent class, since the default singularity
* threshold (1e-14) does not trigger the expected exception.
*/
LinearProblem problem = new LinearProblem(new double[][] {
{ 1, 2, -3 },
{ 2, 1, 3 },
{ -3, 0, -9 }
}, new double[] { 1, 1, 1 });
AbstractLeastSquaresOptimizer optimizer = createOptimizer();
optimizer.optimize(100, problem, problem.target, new double[] { 1, 1, 1 }, new double[] { 0, 0, 0 });
Assert.assertTrue(FastMath.sqrt(problem.target.length) * optimizer.getRMS() > 0.6);
double[][] cov = optimizer.getCovariances(1.5e-14);
}
private void outputResult() {
output = new StringBuilder();
printDoubleArray("expectedPosition: ", expectedPosition);
printDoubleArray("linear calculatedPosition: ", linearCalculatedPosition.toArray());
printDoubleArray("non-linear calculatedPosition: ", nonLinearOptimum.getPoint().toArray());
output.append("numberOfIterations: ").append(nonLinearOptimum.getIterations()).append("\n");
output.append("numberOfEvaluations: ").append(nonLinearOptimum.getEvaluations()).append("\n");
try {
RealVector standardDeviation = nonLinearOptimum.getSigma(0);
printDoubleArray("standardDeviation: ", standardDeviation.toArray());
output.append("Norm of deviation: ").append(standardDeviation.getNorm()).append("\n");
RealMatrix covarianceMatrix = nonLinearOptimum.getCovariances(0);
output.append("covarianceMatrix: ").append(covarianceMatrix).append("\n");
} catch (SingularMatrixException e) {
System.err.println(e.getMessage());
}
System.out.println(output.toString());
}
@Override
@Test(expected=SingularMatrixException.class)
public void testNonInvertible() {
/*
* Overrides the method from parent class, since the default singularity
* threshold (1e-14) does not trigger the expected exception.
*/
LinearProblem problem = new LinearProblem(new double[][] {
{ 1, 2, -3 },
{ 2, 1, 3 },
{ -3, 0, -9 }
}, new double[] { 1, 1, 1 });
AbstractLeastSquaresOptimizer optimizer = createOptimizer();
PointVectorValuePair optimum
= optimizer.optimize(new MaxEval(100),
problem.getModelFunction(),
problem.getModelFunctionJacobian(),
problem.getTarget(),
new Weight(new double[] { 1, 1, 1 }),
new InitialGuess(new double[] { 0, 0, 0 }));
Assert.assertTrue(FastMath.sqrt(optimizer.getTargetSize()) * optimizer.getRMS() > 0.6);
optimizer.computeCovariances(optimum.getPoint(), 1.5e-14);
}
@Override
@Test(expected=SingularMatrixException.class)
public void testNonInvertible() {
/*
* Overrides the method from parent class, since the default singularity
* threshold (1e-14) does not trigger the expected exception.
*/
LinearProblem problem = new LinearProblem(new double[][] {
{ 1, 2, -3 },
{ 2, 1, 3 },
{ -3, 0, -9 }
}, new double[] { 1, 1, 1 });
AbstractLeastSquaresOptimizer optimizer = createOptimizer();
PointVectorValuePair optimum = optimizer.optimize(100, problem, problem.target, new double[] { 1, 1, 1 }, new double[] { 0, 0, 0 });
Assert.assertTrue(FastMath.sqrt(problem.target.length) * optimizer.getRMS() > 0.6);
optimizer.computeCovariances(optimum.getPoint(), 1.5e-14);
}
@Override
@Test(expected=SingularMatrixException.class)
public void testNonInvertible() {
/*
* Overrides the method from parent class, since the default singularity
* threshold (1e-14) does not trigger the expected exception.
*/
LinearProblem problem = new LinearProblem(new double[][] {
{ 1, 2, -3 },
{ 2, 1, 3 },
{ -3, 0, -9 }
}, new double[] { 1, 1, 1 });
AbstractLeastSquaresOptimizer optimizer = createOptimizer();
PointVectorValuePair optimum
= optimizer.optimize(new MaxEval(100),
problem.getModelFunction(),
problem.getModelFunctionJacobian(),
problem.getTarget(),
new Weight(new double[] { 1, 1, 1 }),
new InitialGuess(new double[] { 0, 0, 0 }));
Assert.assertTrue(FastMath.sqrt(optimizer.getTargetSize()) * optimizer.getRMS() > 0.6);
optimizer.computeCovariances(optimum.getPoint(), 1.5e-14);
}
@Override
@Test(expected=SingularMatrixException.class)
public void testNonInvertible() {
/*
* Overrides the method from parent class, since the default singularity
* threshold (1e-14) does not trigger the expected exception.
*/
LinearProblem problem = new LinearProblem(new double[][] {
{ 1, 2, -3 },
{ 2, 1, 3 },
{ -3, 0, -9 }
}, new double[] { 1, 1, 1 });
AbstractLeastSquaresOptimizer optimizer = createOptimizer();
PointVectorValuePair optimum = optimizer.optimize(100, problem, problem.target, new double[] { 1, 1, 1 }, new double[] { 0, 0, 0 });
Assert.assertTrue(FastMath.sqrt(problem.target.length) * optimizer.getRMS() > 0.6);
optimizer.computeCovariances(optimum.getPoint(), 1.5e-14);
}
@Override
@Test(expected=SingularMatrixException.class)
public void testNonInvertible() {
/*
* Overrides the method from parent class, since the default singularity
* threshold (1e-14) does not trigger the expected exception.
*/
LinearProblem problem = new LinearProblem(new double[][] {
{ 1, 2, -3 },
{ 2, 1, 3 },
{ -3, 0, -9 }
}, new double[] { 1, 1, 1 });
AbstractLeastSquaresOptimizer optimizer = createOptimizer();
PointVectorValuePair optimum
= optimizer.optimize(new MaxEval(100),
problem.getModelFunction(),
problem.getModelFunctionJacobian(),
problem.getTarget(),
new Weight(new double[] { 1, 1, 1 }),
new InitialGuess(new double[] { 0, 0, 0 }));
Assert.assertTrue(FastMath.sqrt(optimizer.getTargetSize()) * optimizer.getRMS() > 0.6);
optimizer.computeCovariances(optimum.getPoint(), 1.5e-14);
}
@Nonnull
public static RealMatrix inverse(@Nonnull final RealMatrix m, final boolean exact)
throws SingularMatrixException {
LUDecomposition LU = new LUDecomposition(m);
DecompositionSolver solver = LU.getSolver();
final RealMatrix inv;
if (exact || solver.isNonSingular()) {
inv = solver.getInverse();
} else {
SingularValueDecomposition SVD = new SingularValueDecomposition(m);
inv = SVD.getSolver().getInverse();
}
return inv;
}
/**
* L = A x R
*
* @return a matrix A that minimizes A x R - L
*/
@Nonnull
public static RealMatrix solve(@Nonnull final RealMatrix L, @Nonnull final RealMatrix R,
final boolean exact) throws SingularMatrixException {
LUDecomposition LU = new LUDecomposition(R);
DecompositionSolver solver = LU.getSolver();
final RealMatrix A;
if (exact || solver.isNonSingular()) {
A = LU.getSolver().solve(L);
} else {
SingularValueDecomposition SVD = new SingularValueDecomposition(R);
A = SVD.getSolver().solve(L);
}
return A;
}
/** <p>Produces a Gaussian mixture model based on the difference between targets and segment means.</p>
* <p>Filters targets to populations where more than the minProportion lie in a single segment.</p>
* <p>Returns null if no pass filtering. Please note that in these cases,
* in the rest of this class, we use this to assume that a GMM is not a good model.</p>
*
* @param segments -- segments with segment mean in log2 copy ratio space
* @param targets -- targets with a log2 copy ratio estimate
* @param minProportion -- minimum proportion of all targets that a given segment must have in order to be used
* in the evaluation
* @param numComponents -- number of components to use in the GMM. Usually, this is 2.
* @return never {@code null}. Fitting result with indications whether it converged or was even attempted.
*/
private MixtureMultivariateNormalFitResult retrieveGaussianMixtureModelForFilteredTargets(final List<ModeledSegment> segments,
final TargetCollection<ReadCountRecord.SingleSampleRecord> targets, double minProportion, int numComponents){
// For each target in a segment that contains enough targets, normalize the difference against the segment mean
// and collapse the filtered targets into the copy ratio estimates.
final List<Double> filteredTargetsSegDiff = getNumProbeFilteredTargetList(segments, targets, minProportion);
if (filteredTargetsSegDiff.size() < numComponents) {
return new MixtureMultivariateNormalFitResult(null, false, false);
}
// Assume that Apache Commons wants data points in the first dimension.
// Note that second dimension of length 2 (instead of 1) is to wrok around funny Apache commons API.
final double[][] filteredTargetsSegDiff2d = new double[filteredTargetsSegDiff.size()][2];
// Convert the filtered targets into 2d array (even if second dimension is length 1). The second dimension is
// uncorrelated Gaussian. This is only to get around funny API in Apache Commons, which will throw an
// exception if the length of the second dimension is < 2
final RandomGenerator rng = RandomGeneratorFactory.createRandomGenerator(new Random(RANDOM_SEED));
final NormalDistribution nd = new NormalDistribution(rng, 0, .1);
for (int i = 0; i < filteredTargetsSegDiff.size(); i++) {
filteredTargetsSegDiff2d[i][0] = filteredTargetsSegDiff.get(i);
filteredTargetsSegDiff2d[i][1] = nd.sample();
}
final MixtureMultivariateNormalDistribution estimateEM0 = MultivariateNormalMixtureExpectationMaximization.estimate(filteredTargetsSegDiff2d, numComponents);
final MultivariateNormalMixtureExpectationMaximization multivariateNormalMixtureExpectationMaximization = new MultivariateNormalMixtureExpectationMaximization(filteredTargetsSegDiff2d);
try {
multivariateNormalMixtureExpectationMaximization.fit(estimateEM0);
} catch (final MaxCountExceededException | ConvergenceException | SingularMatrixException e) {
// We are done, we cannot make a fitting. We should return a result that we attempted a fitting, but it
// did not converge. Include the model as it was when the exception was thrown.
return new MixtureMultivariateNormalFitResult(multivariateNormalMixtureExpectationMaximization.getFittedModel(), false, true);
}
return new MixtureMultivariateNormalFitResult(multivariateNormalMixtureExpectationMaximization.getFittedModel(), true, true);
}
private void updateInverseCovariance() {
try {
inverseCov = new LUDecomposition(cov).getSolver().getInverse();
} catch (SingularMatrixException e) {
singularCovariances.inc();
inverseCov = new SingularValueDecomposition(cov).getSolver().getInverse();
}
}
@Override
public Map<String, Double> getScores() {
if (coefficients == null) {
return null;
} else {
Map<String, Double> scores = new HashMap<>();
try {
scores.put("rSquared", olsModel.calculateRSquared());
scores.put("totalSumOfSquares", olsModel.calculateTotalSumOfSquares());
} catch (SingularMatrixException sme) {
LOG.debug("The OLSMultipleLinearRegression model's matrix has no inverse (i.e. it is singular) so no scores can be calculated at this time.");
}
return scores;
}
}
@Test
public void testConstantPrediction(){
Double timestamp = 1565444720000.0;
Double inputCount = 1000.0;
Double outputCount = 1000.0;
Double queueCount = 50.0;
Double[] feature0 = {timestamp - 1000,outputCount/inputCount};
Double[] feature1 = {timestamp,outputCount/inputCount};
Double[] feature2 = {timestamp + 1000,outputCount/inputCount};
Double[] feature3 = {timestamp + 2000,outputCount/inputCount};
Double[][] features = {feature0, feature1,feature2,feature3};
Double[] labels = {queueCount,queueCount,queueCount, queueCount};
OrdinaryLeastSquares model = new OrdinaryLeastSquares();
boolean exOccurred = false;
try {
model.learn(Stream.of(features), Stream.of(labels));
} catch (SingularMatrixException sme){
exOccurred = true;
}
// SingularMatrixException should not be thrown, it will instead be logged
assertFalse(exOccurred);
}
@Override
public void learn(Stream<Double[]> features, Stream<Double> labels) {
double[] labelArray = ArrayUtils.toPrimitive(labels.toArray(Double[]::new));
double[][] featuresMatrix = features.map(ArrayUtils::toPrimitive).toArray(double[][]::new);
this.olsModel.newSampleData(labelArray, featuresMatrix);
try {
this.coefficients = olsModel.estimateRegressionParameters();
} catch (SingularMatrixException sme) {
LOG.debug("The OLSMultipleLinearRegression model's matrix has no inverse (i.e. it is singular) so regression parameters can not be estimated at this time.");
}
}
@Override
@Test
public void testNonInvertible() {
try{
/*
* Overrides the method from parent class, since the default singularity
* threshold (1e-14) does not trigger the expected exception.
*/
LinearProblem problem = new LinearProblem(new double[][] {
{ 1, 2, -3 },
{ 2, 1, 3 },
{ -3, 0, -9 }
}, new double[] { 1, 1, 1 });
final Optimum optimum = optimizer.optimize(
problem.getBuilder().maxIterations(20).build());
//TODO check that it is a bad fit? Why the extra conditions?
Assert.assertTrue(FastMath.sqrt(problem.getTarget().length) * optimum.getRMS() > 0.6);
optimum.getCovariances(1.5e-14);
fail(optimizer);
}catch (SingularMatrixException e){
//expected
}
}
@Test(expected=SingularMatrixException.class)
public void testQRSingular() {
final RealMatrix a = MatrixUtils.createRealMatrix(new double[][] {
{ 1, 6, 4 }, { 2, 4, -1 }, { -1, 2, 5 }
});
final RealVector b = new ArrayRealVector(new double[]{ 5, 6, 1 });
new QRDecomposition(a, 1.0e-15).getSolver().solve(b);
}
/**
* Correct the current state estimate with an actual measurement.
*
* @param z
* the measurement vector
* @throws NullArgumentException
* if the measurement vector is {@code null}
* @throws DimensionMismatchException
* if the dimension of the measurement vector does not fit
* @throws SingularMatrixException
* if the covariance matrix could not be inverted
*/
public void correct(final RealVector z)
throws NullArgumentException, DimensionMismatchException, SingularMatrixException {
// sanity checks
MathUtils.checkNotNull(z);
if (z.getDimension() != measurementMatrix.getRowDimension()) {
throw new DimensionMismatchException(z.getDimension(),
measurementMatrix.getRowDimension());
}
// S = H * P(k) - * H' + R
RealMatrix s = measurementMatrix.multiply(errorCovariance)
.multiply(measurementMatrixT)
.add(measurementModel.getMeasurementNoise());
// invert S
// as the error covariance matrix is a symmetric positive
// semi-definite matrix, we can use the cholesky decomposition
DecompositionSolver solver = new CholeskyDecomposition(s).getSolver();
RealMatrix invertedS = solver.getInverse();
// Inn = z(k) - H * xHat(k)-
RealVector innovation = z.subtract(measurementMatrix.operate(stateEstimation));
// calculate gain matrix
// K(k) = P(k)- * H' * (H * P(k)- * H' + R)^-1
// K(k) = P(k)- * H' * S^-1
RealMatrix kalmanGain = errorCovariance.multiply(measurementMatrixT).multiply(invertedS);
// update estimate with measurement z(k)
// xHat(k) = xHat(k)- + K * Inn
stateEstimation = stateEstimation.add(kalmanGain.operate(innovation));
// update covariance of prediction error
// P(k) = (I - K * H) * P(k)-
RealMatrix identity = MatrixUtils.createRealIdentityMatrix(kalmanGain.getRowDimension());
errorCovariance = identity.subtract(kalmanGain.multiply(measurementMatrix)).multiply(errorCovariance);
}
@Test(expected=SingularMatrixException.class)
public void testNonInvertible() {
QRDecomposition qr =
new QRDecomposition(MatrixUtils.createRealMatrix(testData3x3Singular));
final RealMatrix inv = qr.getSolver().getInverse();
}
@Test(expected=SingularMatrixException.class)
public void testNonInvertible() {
QRDecomposition qr =
new QRDecomposition(MatrixUtils.createRealMatrix(testData3x3Singular));
final RealMatrix inv = qr.getSolver().getInverse();
}
/**
* Correct the current state estimate with an actual measurement.
*
* @param z
* the measurement vector
* @throws NullArgumentException
* if the measurement vector is {@code null}
* @throws DimensionMismatchException
* if the dimension of the measurement vector does not fit
* @throws SingularMatrixException
* if the covariance matrix could not be inverted
*/
public void correct(final RealVector z)
throws NullArgumentException, DimensionMismatchException, SingularMatrixException {
// sanity checks
MathUtils.checkNotNull(z);
if (z.getDimension() != measurementMatrix.getRowDimension()) {
throw new DimensionMismatchException(z.getDimension(),
measurementMatrix.getRowDimension());
}
// S = H * P(k) - * H' + R
RealMatrix s = measurementMatrix.multiply(errorCovariance)
.multiply(measurementMatrixT)
.add(measurementModel.getMeasurementNoise());
// invert S
// as the error covariance matrix is a symmetric positive
// semi-definite matrix, we can use the cholesky decomposition
DecompositionSolver solver = new CholeskyDecomposition(s).getSolver();
RealMatrix invertedS = solver.getInverse();
// Inn = z(k) - H * xHat(k)-
RealVector innovation = z.subtract(measurementMatrix.operate(stateEstimation));
// calculate gain matrix
// K(k) = P(k)- * H' * (H * P(k)- * H' + R)^-1
// K(k) = P(k)- * H' * S^-1
RealMatrix kalmanGain = errorCovariance.multiply(measurementMatrixT).multiply(invertedS);
// update estimate with measurement z(k)
// xHat(k) = xHat(k)- + K * Inn
stateEstimation = stateEstimation.add(kalmanGain.operate(innovation));
// update covariance of prediction error
// P(k) = (I - K * H) * P(k)-
RealMatrix identity = MatrixUtils.createRealIdentityMatrix(kalmanGain.getRowDimension());
errorCovariance = identity.subtract(kalmanGain.multiply(measurementMatrix)).multiply(errorCovariance);
}
@Override
@Test(expected=SingularMatrixException.class)
public void testNonInvertible() {
/*
* Overrides the method from parent class, since the default singularity
* threshold (1e-14) does not trigger the expected exception.
*/
LinearProblem problem = new LinearProblem(new double[][] {
{ 1, 2, -3 },
{ 2, 1, 3 },
{ -3, 0, -9 }
}, new double[] { 1, 1, 1 });
final LevenbergMarquardtOptimizer optimizer = createOptimizer()
.withMaxEvaluations(100)
.withMaxIterations(20)
.withModelAndJacobian(problem.getModelFunction(),
problem.getModelFunctionJacobian())
.withTarget(problem.getTarget())
.withWeight(new DiagonalMatrix(new double[] { 1, 1, 1 }))
.withStartPoint(new double[] { 0, 0, 0 });
final double[] optimum = optimizer.optimize().getPoint();
Assert.assertTrue(FastMath.sqrt(optimizer.getTarget().length) * optimizer.computeRMS(optimum) > 0.6);
optimizer.computeCovariances(optimum, 1.5e-14);
}
@Test(expected=SingularMatrixException.class)
public void testNonInvertible() {
QRDecomposition qr =
new QRDecomposition(MatrixUtils.createRealMatrix(testData3x3Singular));
final RealMatrix inv = qr.getSolver().getInverse();
}
/**
* Compute the right pseudo inverse. Input matrix must have full row rank.
*
* See also: <a href="https://en.wikipedia.org/wiki/Moore%E2%80%93Penrose_inverse#Definition">Moore–Penrose inverse</a>
*
* @param arr Input matrix
* @param inPlace Whether to store the result in {@code arr}
* @return Right pseudo inverse of {@code arr}
* @exception IllegalArgumentException Input matrix {@code arr} did not have full row rank.
*/
public static INDArray pRightInvert(INDArray arr, boolean inPlace) {
try{
final INDArray inv = arr.transpose().mmul(invert(arr.mmul(arr.transpose()), inPlace));
if (inPlace) arr.assign(inv);
return inv;
} catch (SingularMatrixException e){
throw new IllegalArgumentException(
"Full row rank condition for right pseudo inverse was not met.");
}
}
/**
* Correct the current state estimate with an actual measurement.
*
* @param z
* the measurement vector
* @throws NullArgumentException
* if the measurement vector is {@code null}
* @throws DimensionMismatchException
* if the dimension of the measurement vector does not fit
* @throws SingularMatrixException
* if the covariance matrix could not be inverted
*/
public void correct(final RealVector z)
throws NullArgumentException, DimensionMismatchException, SingularMatrixException {
// sanity checks
MathUtils.checkNotNull(z);
if (z.getDimension() != measurementMatrix.getRowDimension()) {
throw new DimensionMismatchException(z.getDimension(),
measurementMatrix.getRowDimension());
}
// S = H * P(k) - * H' + R
RealMatrix s = measurementMatrix.multiply(errorCovariance)
.multiply(measurementMatrixT)
.add(measurementModel.getMeasurementNoise());
// invert S
// as the error covariance matrix is a symmetric positive
// semi-definite matrix, we can use the cholesky decomposition
DecompositionSolver solver = new CholeskyDecomposition(s).getSolver();
RealMatrix invertedS = solver.getInverse();
// Inn = z(k) - H * xHat(k)-
RealVector innovation = z.subtract(measurementMatrix.operate(stateEstimation));
// calculate gain matrix
// K(k) = P(k)- * H' * (H * P(k)- * H' + R)^-1
// K(k) = P(k)- * H' * S^-1
RealMatrix kalmanGain = errorCovariance.multiply(measurementMatrixT).multiply(invertedS);
// update estimate with measurement z(k)
// xHat(k) = xHat(k)- + K * Inn
stateEstimation = stateEstimation.add(kalmanGain.operate(innovation));
// update covariance of prediction error
// P(k) = (I - K * H) * P(k)-
RealMatrix identity = MatrixUtils.createRealIdentityMatrix(kalmanGain.getRowDimension());
errorCovariance = identity.subtract(kalmanGain.multiply(measurementMatrix)).multiply(errorCovariance);
}