View Javadoc
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  
19  import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
20  import org.apache.commons.math4.legacy.exception.MaxCountExceededException;
21  import org.apache.commons.math4.legacy.exception.NullArgumentException;
22  
23  /**
24   * <p>
25   * This abstract class defines preconditioned iterative solvers. When A is
26   * ill-conditioned, instead of solving system A &middot; x = b directly, it is
27   * preferable to solve either
28   * <pre>
29   * (M &middot; A) &middot; x = M &middot; b
30   * </pre>
31   * (left preconditioning), or
32   * <pre>
33   * (A &middot; M) &middot; y = b, &nbsp;&nbsp;&nbsp;&nbsp;followed by
34   * M &middot; y = x
35   * </pre>
36   * (right preconditioning), where M approximates in some way A<sup>-1</sup>,
37   * while matrix-vector products of the type M &middot; y remain comparatively
38   * easy to compute. In this library, M (not M<sup>-1</sup>!) is called the
39   * <em>preconditionner</em>.
40   *
41   * <p>
42   * Concrete implementations of this abstract class must be provided with the
43   * preconditioner M, as a {@link RealLinearOperator}.
44   * </p>
45   *
46   * @since 3.0
47   */
48  public abstract class PreconditionedIterativeLinearSolver
49      extends IterativeLinearSolver {
50  
51      /**
52       * Creates a new instance of this class, with default iteration manager.
53       *
54       * @param maxIterations the maximum number of iterations
55       */
56      public PreconditionedIterativeLinearSolver(final int maxIterations) {
57          super(maxIterations);
58      }
59  
60      /**
61       * Creates a new instance of this class, with custom iteration manager.
62       *
63       * @param manager the custom iteration manager
64       * @throws NullArgumentException if {@code manager} is {@code null}
65       */
66      public PreconditionedIterativeLinearSolver(final IterationManager manager)
67          throws NullArgumentException {
68          super(manager);
69      }
70  
71      /**
72       * Returns an estimate of the solution to the linear system A &middot; x =
73       * b.
74       *
75       * @param a the linear operator A of the system
76       * @param m the preconditioner, M (can be {@code null})
77       * @param b the right-hand side vector
78       * @param x0 the initial guess of the solution
79       * @return a new vector containing the solution
80       * @throws NullArgumentException if one of the parameters is {@code null}
81       * @throws NonSquareOperatorException if {@code a} or {@code m} is not
82       * square
83       * @throws DimensionMismatchException if {@code m}, {@code b} or
84       * {@code x0} have dimensions inconsistent with {@code a}
85       * @throws MaxCountExceededException at exhaustion of the iteration count,
86       * unless a custom
87       * {@link org.apache.commons.math4.legacy.core.IntegerSequence.Incrementor.MaxCountExceededCallback callback}
88       * has been set at construction of the {@link IterationManager}
89       */
90      public RealVector solve(final RealLinearOperator a,
91          final RealLinearOperator m, final RealVector b, final RealVector x0)
92          throws NullArgumentException, NonSquareOperatorException,
93          DimensionMismatchException, MaxCountExceededException {
94          NullArgumentException.check(x0);
95          return solveInPlace(a, m, b, x0.copy());
96      }
97  
98      /** {@inheritDoc} */
99      @Override
100     public RealVector solve(final RealLinearOperator a, final RealVector b)
101         throws NullArgumentException, NonSquareOperatorException,
102         DimensionMismatchException, MaxCountExceededException {
103         NullArgumentException.check(a);
104         final RealVector x = new ArrayRealVector(a.getColumnDimension());
105         x.set(0.);
106         return solveInPlace(a, null, b, x);
107     }
108 
109     /** {@inheritDoc} */
110     @Override
111     public RealVector solve(final RealLinearOperator a, final RealVector b,
112                             final RealVector x0)
113         throws NullArgumentException, NonSquareOperatorException,
114         DimensionMismatchException, MaxCountExceededException {
115         NullArgumentException.check(x0);
116         return solveInPlace(a, null, b, x0.copy());
117     }
118 
119     /**
120      * Performs all dimension checks on the parameters of
121      * {@link #solve(RealLinearOperator, RealLinearOperator, RealVector, RealVector) solve}
122      * and
123      * {@link #solveInPlace(RealLinearOperator, RealLinearOperator, RealVector, RealVector) solveInPlace},
124      * and throws an exception if one of the checks fails.
125      *
126      * @param a the linear operator A of the system
127      * @param m the preconditioner, M (can be {@code null})
128      * @param b the right-hand side vector
129      * @param x0 the initial guess of the solution
130      * @throws NullArgumentException if one of the parameters is {@code null}
131      * @throws NonSquareOperatorException if {@code a} or {@code m} is not
132      * square
133      * @throws DimensionMismatchException if {@code m}, {@code b} or
134      * {@code x0} have dimensions inconsistent with {@code a}
135      */
136     protected static void checkParameters(final RealLinearOperator a,
137         final RealLinearOperator m, final RealVector b, final RealVector x0)
138         throws NullArgumentException, NonSquareOperatorException,
139         DimensionMismatchException {
140         checkParameters(a, b, x0);
141         if (m != null) {
142             if (m.getColumnDimension() != m.getRowDimension()) {
143                 throw new NonSquareOperatorException(m.getColumnDimension(),
144                                                      m.getRowDimension());
145             }
146             if (m.getRowDimension() != a.getRowDimension()) {
147                 throw new DimensionMismatchException(m.getRowDimension(),
148                                                      a.getRowDimension());
149             }
150         }
151     }
152 
153     /**
154      * Returns an estimate of the solution to the linear system A &middot; x =
155      * b.
156      *
157      * @param a the linear operator A of the system
158      * @param m the preconditioner, M (can be {@code null})
159      * @param b the right-hand side vector
160      * @return a new vector containing the solution
161      * @throws NullArgumentException if one of the parameters is {@code null}
162      * @throws NonSquareOperatorException if {@code a} or {@code m} is not
163      * square
164      * @throws DimensionMismatchException if {@code m} or {@code b} have
165      * dimensions inconsistent with {@code a}
166      * @throws MaxCountExceededException at exhaustion of the iteration count,
167      * unless a custom
168      * {@link org.apache.commons.math4.legacy.core.IntegerSequence.Incrementor.MaxCountExceededCallback callback}
169      * has been set at construction of the {@link IterationManager}
170      */
171     public RealVector solve(RealLinearOperator a, RealLinearOperator m,
172         RealVector b) throws NullArgumentException, NonSquareOperatorException,
173         DimensionMismatchException, MaxCountExceededException {
174         NullArgumentException.check(a);
175         final RealVector x = new ArrayRealVector(a.getColumnDimension());
176         return solveInPlace(a, m, b, x);
177     }
178 
179     /**
180      * Returns an estimate of the solution to the linear system A &middot; x =
181      * b. The solution is computed in-place (initial guess is modified).
182      *
183      * @param a the linear operator A of the system
184      * @param m the preconditioner, M (can be {@code null})
185      * @param b the right-hand side vector
186      * @param x0 the initial guess of the solution
187      * @return a reference to {@code x0} (shallow copy) updated with the
188      * solution
189      * @throws NullArgumentException if one of the parameters is {@code null}
190      * @throws NonSquareOperatorException if {@code a} or {@code m} is not
191      * square
192      * @throws DimensionMismatchException if {@code m}, {@code b} or
193      * {@code x0} have dimensions inconsistent with {@code a}
194      * @throws MaxCountExceededException at exhaustion of the iteration count,
195      * unless a custom
196      * {@link org.apache.commons.math4.legacy.core.IntegerSequence.Incrementor.MaxCountExceededCallback callback}
197      * has been set at construction of the {@link IterationManager}
198      */
199     public abstract RealVector solveInPlace(RealLinearOperator a,
200         RealLinearOperator m, RealVector b, RealVector x0) throws
201         NullArgumentException, NonSquareOperatorException,
202         DimensionMismatchException, MaxCountExceededException;
203 
204     /** {@inheritDoc} */
205     @Override
206     public RealVector solveInPlace(final RealLinearOperator a,
207         final RealVector b, final RealVector x0) throws
208         NullArgumentException, NonSquareOperatorException,
209         DimensionMismatchException, MaxCountExceededException {
210         return solveInPlace(a, null, b, x0);
211     }
212 }