diff options
Diffstat (limited to 'src/main/java/org/apache/commons/math3/linear/PreconditionedIterativeLinearSolver.java')
-rw-r--r-- | src/main/java/org/apache/commons/math3/linear/PreconditionedIterativeLinearSolver.java | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/src/main/java/org/apache/commons/math3/linear/PreconditionedIterativeLinearSolver.java b/src/main/java/org/apache/commons/math3/linear/PreconditionedIterativeLinearSolver.java new file mode 100644 index 0000000..6808d46 --- /dev/null +++ b/src/main/java/org/apache/commons/math3/linear/PreconditionedIterativeLinearSolver.java @@ -0,0 +1,205 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math3.linear; + +import org.apache.commons.math3.exception.DimensionMismatchException; +import org.apache.commons.math3.exception.MaxCountExceededException; +import org.apache.commons.math3.exception.NullArgumentException; +import org.apache.commons.math3.util.IterationManager; +import org.apache.commons.math3.util.MathUtils; + +/** + * This abstract class defines preconditioned iterative solvers. When A is ill-conditioned, instead + * of solving system A · x = b directly, it is preferable to solve either <center> (M + * · A) · x = M · b </center> (left preconditioning), or <center> (A · + * M) · y = b, followed by M · y = x </center> (right + * preconditioning), where M approximates in some way A<sup>-1</sup>, while matrix-vector products + * of the type M · y remain comparatively easy to compute. In this library, M (not + * M<sup>-1</sup>!) is called the <em>preconditionner</em>. + * + * <p>Concrete implementations of this abstract class must be provided with the preconditioner M, as + * a {@link RealLinearOperator}. + * + * @since 3.0 + */ +public abstract class PreconditionedIterativeLinearSolver extends IterativeLinearSolver { + + /** + * Creates a new instance of this class, with default iteration manager. + * + * @param maxIterations the maximum number of iterations + */ + public PreconditionedIterativeLinearSolver(final int maxIterations) { + super(maxIterations); + } + + /** + * Creates a new instance of this class, with custom iteration manager. + * + * @param manager the custom iteration manager + * @throws NullArgumentException if {@code manager} is {@code null} + */ + public PreconditionedIterativeLinearSolver(final IterationManager manager) + throws NullArgumentException { + super(manager); + } + + /** + * Returns an estimate of the solution to the linear system A · x = b. + * + * @param a the linear operator A of the system + * @param m the preconditioner, M (can be {@code null}) + * @param b the right-hand side vector + * @param x0 the initial guess of the solution + * @return a new vector containing the solution + * @throws NullArgumentException if one of the parameters is {@code null} + * @throws NonSquareOperatorException if {@code a} or {@code m} is not square + * @throws DimensionMismatchException if {@code m}, {@code b} or {@code x0} have dimensions + * inconsistent with {@code a} + * @throws MaxCountExceededException at exhaustion of the iteration count, unless a custom + * {@link org.apache.commons.math3.util.Incrementor.MaxCountExceededCallback callback} has + * been set at construction of the {@link IterationManager} + */ + public RealVector solve( + final RealLinearOperator a, + final RealLinearOperator m, + final RealVector b, + final RealVector x0) + throws NullArgumentException, + NonSquareOperatorException, + DimensionMismatchException, + MaxCountExceededException { + MathUtils.checkNotNull(x0); + return solveInPlace(a, m, b, x0.copy()); + } + + /** {@inheritDoc} */ + @Override + public RealVector solve(final RealLinearOperator a, final RealVector b) + throws NullArgumentException, + NonSquareOperatorException, + DimensionMismatchException, + MaxCountExceededException { + MathUtils.checkNotNull(a); + final RealVector x = new ArrayRealVector(a.getColumnDimension()); + x.set(0.); + return solveInPlace(a, null, b, x); + } + + /** {@inheritDoc} */ + @Override + public RealVector solve(final RealLinearOperator a, final RealVector b, final RealVector x0) + throws NullArgumentException, + NonSquareOperatorException, + DimensionMismatchException, + MaxCountExceededException { + MathUtils.checkNotNull(x0); + return solveInPlace(a, null, b, x0.copy()); + } + + /** + * Performs all dimension checks on the parameters of {@link #solve(RealLinearOperator, + * RealLinearOperator, RealVector, RealVector) solve} and {@link + * #solveInPlace(RealLinearOperator, RealLinearOperator, RealVector, RealVector) solveInPlace}, + * and throws an exception if one of the checks fails. + * + * @param a the linear operator A of the system + * @param m the preconditioner, M (can be {@code null}) + * @param b the right-hand side vector + * @param x0 the initial guess of the solution + * @throws NullArgumentException if one of the parameters is {@code null} + * @throws NonSquareOperatorException if {@code a} or {@code m} is not square + * @throws DimensionMismatchException if {@code m}, {@code b} or {@code x0} have dimensions + * inconsistent with {@code a} + */ + protected static void checkParameters( + final RealLinearOperator a, + final RealLinearOperator m, + final RealVector b, + final RealVector x0) + throws NullArgumentException, NonSquareOperatorException, DimensionMismatchException { + checkParameters(a, b, x0); + if (m != null) { + if (m.getColumnDimension() != m.getRowDimension()) { + throw new NonSquareOperatorException(m.getColumnDimension(), m.getRowDimension()); + } + if (m.getRowDimension() != a.getRowDimension()) { + throw new DimensionMismatchException(m.getRowDimension(), a.getRowDimension()); + } + } + } + + /** + * Returns an estimate of the solution to the linear system A · x = b. + * + * @param a the linear operator A of the system + * @param m the preconditioner, M (can be {@code null}) + * @param b the right-hand side vector + * @return a new vector containing the solution + * @throws NullArgumentException if one of the parameters is {@code null} + * @throws NonSquareOperatorException if {@code a} or {@code m} is not square + * @throws DimensionMismatchException if {@code m} or {@code b} have dimensions inconsistent + * with {@code a} + * @throws MaxCountExceededException at exhaustion of the iteration count, unless a custom + * {@link org.apache.commons.math3.util.Incrementor.MaxCountExceededCallback callback} has + * been set at construction of the {@link IterationManager} + */ + public RealVector solve(RealLinearOperator a, RealLinearOperator m, RealVector b) + throws NullArgumentException, + NonSquareOperatorException, + DimensionMismatchException, + MaxCountExceededException { + MathUtils.checkNotNull(a); + final RealVector x = new ArrayRealVector(a.getColumnDimension()); + return solveInPlace(a, m, b, x); + } + + /** + * Returns an estimate of the solution to the linear system A · x = b. The solution is + * computed in-place (initial guess is modified). + * + * @param a the linear operator A of the system + * @param m the preconditioner, M (can be {@code null}) + * @param b the right-hand side vector + * @param x0 the initial guess of the solution + * @return a reference to {@code x0} (shallow copy) updated with the solution + * @throws NullArgumentException if one of the parameters is {@code null} + * @throws NonSquareOperatorException if {@code a} or {@code m} is not square + * @throws DimensionMismatchException if {@code m}, {@code b} or {@code x0} have dimensions + * inconsistent with {@code a} + * @throws MaxCountExceededException at exhaustion of the iteration count, unless a custom + * {@link org.apache.commons.math3.util.Incrementor.MaxCountExceededCallback callback} has + * been set at construction of the {@link IterationManager} + */ + public abstract RealVector solveInPlace( + RealLinearOperator a, RealLinearOperator m, RealVector b, RealVector x0) + throws NullArgumentException, + NonSquareOperatorException, + DimensionMismatchException, + MaxCountExceededException; + + /** {@inheritDoc} */ + @Override + public RealVector solveInPlace( + final RealLinearOperator a, final RealVector b, final RealVector x0) + throws NullArgumentException, + NonSquareOperatorException, + DimensionMismatchException, + MaxCountExceededException { + return solveInPlace(a, null, b, x0); + } +} |