PreconditionedIterativeLinearSolver.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.math4.legacy.linear;

  18. import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
  19. import org.apache.commons.math4.legacy.exception.MaxCountExceededException;
  20. import org.apache.commons.math4.legacy.exception.NullArgumentException;

  21. /**
  22.  * <p>
  23.  * This abstract class defines preconditioned iterative solvers. When A is
  24.  * ill-conditioned, instead of solving system A &middot; x = b directly, it is
  25.  * preferable to solve either
  26.  * <pre>
  27.  * (M &middot; A) &middot; x = M &middot; b
  28.  * </pre>
  29.  * (left preconditioning), or
  30.  * <pre>
  31.  * (A &middot; M) &middot; y = b, &nbsp;&nbsp;&nbsp;&nbsp;followed by
  32.  * M &middot; y = x
  33.  * </pre>
  34.  * (right preconditioning), where M approximates in some way A<sup>-1</sup>,
  35.  * while matrix-vector products of the type M &middot; y remain comparatively
  36.  * easy to compute. In this library, M (not M<sup>-1</sup>!) is called the
  37.  * <em>preconditionner</em>.
  38.  *
  39.  * <p>
  40.  * Concrete implementations of this abstract class must be provided with the
  41.  * preconditioner M, as a {@link RealLinearOperator}.
  42.  * </p>
  43.  *
  44.  * @since 3.0
  45.  */
  46. public abstract class PreconditionedIterativeLinearSolver
  47.     extends IterativeLinearSolver {

  48.     /**
  49.      * Creates a new instance of this class, with default iteration manager.
  50.      *
  51.      * @param maxIterations the maximum number of iterations
  52.      */
  53.     public PreconditionedIterativeLinearSolver(final int maxIterations) {
  54.         super(maxIterations);
  55.     }

  56.     /**
  57.      * Creates a new instance of this class, with custom iteration manager.
  58.      *
  59.      * @param manager the custom iteration manager
  60.      * @throws NullArgumentException if {@code manager} is {@code null}
  61.      */
  62.     public PreconditionedIterativeLinearSolver(final IterationManager manager)
  63.         throws NullArgumentException {
  64.         super(manager);
  65.     }

  66.     /**
  67.      * Returns an estimate of the solution to the linear system A &middot; x =
  68.      * b.
  69.      *
  70.      * @param a the linear operator A of the system
  71.      * @param m the preconditioner, M (can be {@code null})
  72.      * @param b the right-hand side vector
  73.      * @param x0 the initial guess of the solution
  74.      * @return a new vector containing the solution
  75.      * @throws NullArgumentException if one of the parameters is {@code null}
  76.      * @throws NonSquareOperatorException if {@code a} or {@code m} is not
  77.      * square
  78.      * @throws DimensionMismatchException if {@code m}, {@code b} or
  79.      * {@code x0} have dimensions inconsistent with {@code a}
  80.      * @throws MaxCountExceededException at exhaustion of the iteration count,
  81.      * unless a custom
  82.      * {@link org.apache.commons.math4.legacy.core.IntegerSequence.Incrementor.MaxCountExceededCallback callback}
  83.      * has been set at construction of the {@link IterationManager}
  84.      */
  85.     public RealVector solve(final RealLinearOperator a,
  86.         final RealLinearOperator m, final RealVector b, final RealVector x0)
  87.         throws NullArgumentException, NonSquareOperatorException,
  88.         DimensionMismatchException, MaxCountExceededException {
  89.         NullArgumentException.check(x0);
  90.         return solveInPlace(a, m, b, x0.copy());
  91.     }

  92.     /** {@inheritDoc} */
  93.     @Override
  94.     public RealVector solve(final RealLinearOperator a, final RealVector b)
  95.         throws NullArgumentException, NonSquareOperatorException,
  96.         DimensionMismatchException, MaxCountExceededException {
  97.         NullArgumentException.check(a);
  98.         final RealVector x = new ArrayRealVector(a.getColumnDimension());
  99.         x.set(0.);
  100.         return solveInPlace(a, null, b, x);
  101.     }

  102.     /** {@inheritDoc} */
  103.     @Override
  104.     public RealVector solve(final RealLinearOperator a, final RealVector b,
  105.                             final RealVector x0)
  106.         throws NullArgumentException, NonSquareOperatorException,
  107.         DimensionMismatchException, MaxCountExceededException {
  108.         NullArgumentException.check(x0);
  109.         return solveInPlace(a, null, b, x0.copy());
  110.     }

  111.     /**
  112.      * Performs all dimension checks on the parameters of
  113.      * {@link #solve(RealLinearOperator, RealLinearOperator, RealVector, RealVector) solve}
  114.      * and
  115.      * {@link #solveInPlace(RealLinearOperator, RealLinearOperator, RealVector, RealVector) solveInPlace},
  116.      * and throws an exception if one of the checks fails.
  117.      *
  118.      * @param a the linear operator A of the system
  119.      * @param m the preconditioner, M (can be {@code null})
  120.      * @param b the right-hand side vector
  121.      * @param x0 the initial guess of the solution
  122.      * @throws NullArgumentException if one of the parameters is {@code null}
  123.      * @throws NonSquareOperatorException if {@code a} or {@code m} is not
  124.      * square
  125.      * @throws DimensionMismatchException if {@code m}, {@code b} or
  126.      * {@code x0} have dimensions inconsistent with {@code a}
  127.      */
  128.     protected static void checkParameters(final RealLinearOperator a,
  129.         final RealLinearOperator m, final RealVector b, final RealVector x0)
  130.         throws NullArgumentException, NonSquareOperatorException,
  131.         DimensionMismatchException {
  132.         checkParameters(a, b, x0);
  133.         if (m != null) {
  134.             if (m.getColumnDimension() != m.getRowDimension()) {
  135.                 throw new NonSquareOperatorException(m.getColumnDimension(),
  136.                                                      m.getRowDimension());
  137.             }
  138.             if (m.getRowDimension() != a.getRowDimension()) {
  139.                 throw new DimensionMismatchException(m.getRowDimension(),
  140.                                                      a.getRowDimension());
  141.             }
  142.         }
  143.     }

  144.     /**
  145.      * Returns an estimate of the solution to the linear system A &middot; x =
  146.      * b.
  147.      *
  148.      * @param a the linear operator A of the system
  149.      * @param m the preconditioner, M (can be {@code null})
  150.      * @param b the right-hand side vector
  151.      * @return a new vector containing the solution
  152.      * @throws NullArgumentException if one of the parameters is {@code null}
  153.      * @throws NonSquareOperatorException if {@code a} or {@code m} is not
  154.      * square
  155.      * @throws DimensionMismatchException if {@code m} or {@code b} have
  156.      * dimensions inconsistent with {@code a}
  157.      * @throws MaxCountExceededException at exhaustion of the iteration count,
  158.      * unless a custom
  159.      * {@link org.apache.commons.math4.legacy.core.IntegerSequence.Incrementor.MaxCountExceededCallback callback}
  160.      * has been set at construction of the {@link IterationManager}
  161.      */
  162.     public RealVector solve(RealLinearOperator a, RealLinearOperator m,
  163.         RealVector b) throws NullArgumentException, NonSquareOperatorException,
  164.         DimensionMismatchException, MaxCountExceededException {
  165.         NullArgumentException.check(a);
  166.         final RealVector x = new ArrayRealVector(a.getColumnDimension());
  167.         return solveInPlace(a, m, b, x);
  168.     }

  169.     /**
  170.      * Returns an estimate of the solution to the linear system A &middot; x =
  171.      * b. The solution is computed in-place (initial guess is modified).
  172.      *
  173.      * @param a the linear operator A of the system
  174.      * @param m the preconditioner, M (can be {@code null})
  175.      * @param b the right-hand side vector
  176.      * @param x0 the initial guess of the solution
  177.      * @return a reference to {@code x0} (shallow copy) updated with the
  178.      * solution
  179.      * @throws NullArgumentException if one of the parameters is {@code null}
  180.      * @throws NonSquareOperatorException if {@code a} or {@code m} is not
  181.      * square
  182.      * @throws DimensionMismatchException if {@code m}, {@code b} or
  183.      * {@code x0} have dimensions inconsistent with {@code a}
  184.      * @throws MaxCountExceededException at exhaustion of the iteration count,
  185.      * unless a custom
  186.      * {@link org.apache.commons.math4.legacy.core.IntegerSequence.Incrementor.MaxCountExceededCallback callback}
  187.      * has been set at construction of the {@link IterationManager}
  188.      */
  189.     public abstract RealVector solveInPlace(RealLinearOperator a,
  190.         RealLinearOperator m, RealVector b, RealVector x0) throws
  191.         NullArgumentException, NonSquareOperatorException,
  192.         DimensionMismatchException, MaxCountExceededException;

  193.     /** {@inheritDoc} */
  194.     @Override
  195.     public RealVector solveInPlace(final RealLinearOperator a,
  196.         final RealVector b, final RealVector x0) throws
  197.         NullArgumentException, NonSquareOperatorException,
  198.         DimensionMismatchException, MaxCountExceededException {
  199.         return solveInPlace(a, null, b, x0);
  200.     }
  201. }