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 · x = b directly, it is
27 * preferable to solve either
28 * <pre>
29 * (M · A) · x = M · b
30 * </pre>
31 * (left preconditioning), or
32 * <pre>
33 * (A · M) · y = b, followed by
34 * M · 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 · 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 · 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 · 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 · 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 }