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    *      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  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  package org.hipparchus.linear;
23  
24  import org.hipparchus.exception.LocalizedCoreFormats;
25  import org.hipparchus.exception.MathIllegalArgumentException;
26  import org.hipparchus.exception.MathIllegalStateException;
27  import org.hipparchus.exception.NullArgumentException;
28  import org.hipparchus.util.IterationManager;
29  import org.hipparchus.util.MathUtils;
30  
31  /**
32   * This abstract class defines an iterative solver for the linear system A
33   * &middot; x = b. In what follows, the <em>residual</em> r is defined as r = b
34   * - A &middot; x, where A is the linear operator of the linear system, b is the
35   * right-hand side vector, and x the current estimate of the solution.
36   *
37   */
38  public abstract class IterativeLinearSolver {
39  
40      /** The object in charge of managing the iterations. */
41      private final IterationManager manager;
42  
43      /**
44       * Creates a new instance of this class, with default iteration manager.
45       *
46       * @param maxIterations the maximum number of iterations
47       */
48      public IterativeLinearSolver(final int maxIterations) {
49          this.manager = new IterationManager(maxIterations);
50      }
51  
52      /**
53       * Creates a new instance of this class, with custom iteration manager.
54       *
55       * @param manager the custom iteration manager
56       * @throws NullArgumentException if {@code manager} is {@code null}
57       */
58      public IterativeLinearSolver(final IterationManager manager)
59          throws NullArgumentException {
60          MathUtils.checkNotNull(manager);
61          this.manager = manager;
62      }
63  
64      /**
65       * Performs all dimension checks on the parameters of
66       * {@link #solve(RealLinearOperator, RealVector, RealVector) solve} and
67       * {@link #solveInPlace(RealLinearOperator, RealVector, RealVector) solveInPlace},
68       * and throws an exception if one of the checks fails.
69       *
70       * @param a the linear operator A of the system
71       * @param b the right-hand side vector
72       * @param x0 the initial guess of the solution
73       * @throws NullArgumentException if one of the parameters is {@code null}
74       * @throws MathIllegalArgumentException if {@code a} is not square
75       * @throws MathIllegalArgumentException if {@code b} or {@code x0} have
76       * dimensions inconsistent with {@code a}
77       */
78      protected static void checkParameters(final RealLinearOperator a,
79          final RealVector b, final RealVector x0) throws
80          MathIllegalArgumentException, NullArgumentException {
81          MathUtils.checkNotNull(a);
82          MathUtils.checkNotNull(b);
83          MathUtils.checkNotNull(x0);
84          if (a.getRowDimension() != a.getColumnDimension()) {
85              throw new MathIllegalArgumentException(LocalizedCoreFormats.NON_SQUARE_OPERATOR,
86                                                     a.getRowDimension(), a.getColumnDimension());
87          }
88          if (b.getDimension() != a.getRowDimension()) {
89              throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
90                                                     b.getDimension(), a.getRowDimension());
91          }
92          if (x0.getDimension() != a.getColumnDimension()) {
93              throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
94                                                     x0.getDimension(), a.getColumnDimension());
95          }
96      }
97  
98      /**
99       * Returns the iteration manager attached to this solver.
100      *
101      * @return the manager
102      */
103     public IterationManager getIterationManager() {
104         return manager;
105     }
106 
107     /**
108      * Returns an estimate of the solution to the linear system A &middot; x =
109      * b.
110      *
111      * @param a the linear operator A of the system
112      * @param b the right-hand side vector
113      * @return a new vector containing the solution
114      * @throws NullArgumentException if one of the parameters is {@code null}
115      * @throws MathIllegalArgumentException if {@code a} is not square
116      * @throws MathIllegalArgumentException if {@code b} has dimensions
117      * inconsistent with {@code a}
118      * @throws MathIllegalStateException at exhaustion of the iteration count,
119      * unless a custom
120      * {@link org.hipparchus.util.Incrementor.MaxCountExceededCallback callback}
121      * has been set at construction of the {@link IterationManager}
122      */
123     public RealVector solve(final RealLinearOperator a, final RealVector b)
124         throws MathIllegalArgumentException, NullArgumentException, MathIllegalStateException {
125         MathUtils.checkNotNull(a);
126         final RealVector x = new ArrayRealVector(a.getColumnDimension());
127         x.set(0.);
128         return solveInPlace(a, b, x);
129     }
130 
131     /**
132      * Returns an estimate of the solution to the linear system A &middot; x =
133      * b.
134      *
135      * @param a the linear operator A of the system
136      * @param b the right-hand side vector
137      * @param x0 the initial guess of the solution
138      * @return a new vector containing the solution
139      * @throws NullArgumentException if one of the parameters is {@code null}
140      * @throws MathIllegalArgumentException if {@code a} is not square
141      * @throws MathIllegalArgumentException if {@code b} or {@code x0} have
142      * dimensions inconsistent with {@code a}
143      * @throws MathIllegalStateException at exhaustion of the iteration count,
144      * unless a custom
145      * {@link org.hipparchus.util.Incrementor.MaxCountExceededCallback callback}
146      * has been set at construction of the {@link IterationManager}
147      */
148     public RealVector solve(RealLinearOperator a, RealVector b, RealVector x0)
149         throws MathIllegalArgumentException, NullArgumentException, MathIllegalStateException {
150         MathUtils.checkNotNull(x0);
151         return solveInPlace(a, b, x0.copy());
152     }
153 
154     /**
155      * Returns an estimate of the solution to the linear system A &middot; x =
156      * b. The solution is computed in-place (initial guess is modified).
157      *
158      * @param a the linear operator A of the system
159      * @param b the right-hand side vector
160      * @param x0 initial guess of the solution
161      * @return a reference to {@code x0} (shallow copy) updated with the
162      * solution
163      * @throws NullArgumentException if one of the parameters is {@code null}
164      * @throws MathIllegalArgumentException if {@code a} is not square
165      * @throws MathIllegalArgumentException if {@code b} or {@code x0} have
166      * dimensions inconsistent with {@code a}
167      * @throws MathIllegalStateException at exhaustion of the iteration count,
168      * unless a custom
169      * {@link org.hipparchus.util.Incrementor.MaxCountExceededCallback callback}
170      * has been set at construction of the {@link IterationManager}
171      */
172     public abstract RealVector solveInPlace(RealLinearOperator a, RealVector b,
173         RealVector x0) throws MathIllegalArgumentException, NullArgumentException, MathIllegalStateException;
174 }