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.  *      https://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. /*
  18.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */
  21. package org.hipparchus.linear;

  22. import org.hipparchus.exception.LocalizedCoreFormats;
  23. import org.hipparchus.exception.MathIllegalArgumentException;
  24. import org.hipparchus.exception.MathIllegalStateException;
  25. import org.hipparchus.exception.NullArgumentException;
  26. import org.hipparchus.util.IterationManager;
  27. import org.hipparchus.util.MathUtils;

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

  55.     /**
  56.      * Creates a new instance of this class, with default iteration manager.
  57.      *
  58.      * @param maxIterations the maximum number of iterations
  59.      */
  60.     protected PreconditionedIterativeLinearSolver(final int maxIterations) {
  61.         super(maxIterations);
  62.     }

  63.     /**
  64.      * Creates a new instance of this class, with custom iteration manager.
  65.      *
  66.      * @param manager the custom iteration manager
  67.      * @throws NullArgumentException if {@code manager} is {@code null}
  68.      */
  69.     public PreconditionedIterativeLinearSolver(final IterationManager manager)
  70.         throws NullArgumentException {
  71.         super(manager);
  72.     }

  73.     /**
  74.      * Returns an estimate of the solution to the linear system A &middot; x =
  75.      * b.
  76.      *
  77.      * @param a the linear operator A of the system
  78.      * @param m the preconditioner, M (can be {@code null})
  79.      * @param b the right-hand side vector
  80.      * @param x0 the initial guess of the solution
  81.      * @return a new vector containing the solution
  82.      * @throws NullArgumentException if one of the parameters is {@code null}
  83.      * @throws MathIllegalArgumentException if {@code a} or {@code m} is not
  84.      * square
  85.      * @throws MathIllegalArgumentException if {@code m}, {@code b} or
  86.      * {@code x0} have dimensions inconsistent with {@code a}
  87.      * @throws MathIllegalStateException at exhaustion of the iteration count,
  88.      * unless a custom
  89.      * {@link org.hipparchus.util.Incrementor.MaxCountExceededCallback callback}
  90.      * has been set at construction of the {@link IterationManager}
  91.      */
  92.     public RealVector solve(final RealLinearOperator a,
  93.         final RealLinearOperator m, final RealVector b, final RealVector x0)
  94.         throws MathIllegalArgumentException, NullArgumentException, MathIllegalStateException {
  95.         MathUtils.checkNotNull(x0);
  96.         return solveInPlace(a, m, b, x0.copy());
  97.     }

  98.     /** {@inheritDoc} */
  99.     @Override
  100.     public RealVector solve(final RealLinearOperator a, final RealVector b)
  101.         throws MathIllegalArgumentException, NullArgumentException, MathIllegalStateException {
  102.         MathUtils.checkNotNull(a);
  103.         final RealVector x = new ArrayRealVector(a.getColumnDimension());
  104.         x.set(0.);
  105.         return solveInPlace(a, null, b, x);
  106.     }

  107.     /** {@inheritDoc} */
  108.     @Override
  109.     public RealVector solve(final RealLinearOperator a, final RealVector b,
  110.                             final RealVector x0)
  111.         throws MathIllegalArgumentException, NullArgumentException, MathIllegalStateException {
  112.         MathUtils.checkNotNull(x0);
  113.         return solveInPlace(a, null, b, x0.copy());
  114.     }

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

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

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

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