001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.math3.linear;
018
019 import org.apache.commons.math3.exception.DimensionMismatchException;
020 import org.apache.commons.math3.exception.MaxCountExceededException;
021 import org.apache.commons.math3.exception.NullArgumentException;
022 import org.apache.commons.math3.util.IterationManager;
023 import org.apache.commons.math3.util.MathUtils;
024
025 /**
026 * This abstract class defines an iterative solver for the linear system A
027 * · x = b. In what follows, the <em>residual</em> r is defined as r = b
028 * - A · x, where A is the linear operator of the linear system, b is the
029 * right-hand side vector, and x the current estimate of the solution.
030 *
031 * @version $Id: IterativeLinearSolver.java 1416643 2012-12-03 19:37:14Z tn $
032 * @since 3.0
033 */
034 public abstract class IterativeLinearSolver {
035
036 /** The object in charge of managing the iterations. */
037 private final IterationManager manager;
038
039 /**
040 * Creates a new instance of this class, with default iteration manager.
041 *
042 * @param maxIterations the maximum number of iterations
043 */
044 public IterativeLinearSolver(final int maxIterations) {
045 this.manager = new IterationManager(maxIterations);
046 }
047
048 /**
049 * Creates a new instance of this class, with custom iteration manager.
050 *
051 * @param manager the custom iteration manager
052 * @throws NullArgumentException if {@code manager} is {@code null}
053 */
054 public IterativeLinearSolver(final IterationManager manager)
055 throws NullArgumentException {
056 MathUtils.checkNotNull(manager);
057 this.manager = manager;
058 }
059
060 /**
061 * Performs all dimension checks on the parameters of
062 * {@link #solve(RealLinearOperator, RealVector, RealVector) solve} and
063 * {@link #solveInPlace(RealLinearOperator, RealVector, RealVector) solveInPlace},
064 * and throws an exception if one of the checks fails.
065 *
066 * @param a the linear operator A of the system
067 * @param b the right-hand side vector
068 * @param x0 the initial guess of the solution
069 * @throws NullArgumentException if one of the parameters is {@code null}
070 * @throws NonSquareOperatorException if {@code a} is not square
071 * @throws DimensionMismatchException if {@code b} or {@code x0} have
072 * dimensions inconsistent with {@code a}
073 */
074 protected static void checkParameters(final RealLinearOperator a,
075 final RealVector b, final RealVector x0) throws
076 NullArgumentException, NonSquareOperatorException,
077 DimensionMismatchException {
078 MathUtils.checkNotNull(a);
079 MathUtils.checkNotNull(b);
080 MathUtils.checkNotNull(x0);
081 if (a.getRowDimension() != a.getColumnDimension()) {
082 throw new NonSquareOperatorException(a.getRowDimension(),
083 a.getColumnDimension());
084 }
085 if (b.getDimension() != a.getRowDimension()) {
086 throw new DimensionMismatchException(b.getDimension(),
087 a.getRowDimension());
088 }
089 if (x0.getDimension() != a.getColumnDimension()) {
090 throw new DimensionMismatchException(x0.getDimension(),
091 a.getColumnDimension());
092 }
093 }
094
095 /**
096 * Returns the iteration manager attached to this solver.
097 *
098 * @return the manager
099 */
100 public IterationManager getIterationManager() {
101 return manager;
102 }
103
104 /**
105 * Returns an estimate of the solution to the linear system A · x =
106 * b.
107 *
108 * @param a the linear operator A of the system
109 * @param b the right-hand side vector
110 * @return a new vector containing the solution
111 * @throws NullArgumentException if one of the parameters is {@code null}
112 * @throws NonSquareOperatorException if {@code a} is not square
113 * @throws DimensionMismatchException if {@code b} has dimensions
114 * inconsistent with {@code a}
115 * @throws MaxCountExceededException at exhaustion of the iteration count,
116 * unless a custom
117 * {@link org.apache.commons.math3.util.Incrementor.MaxCountExceededCallback callback}
118 * has been set at construction of the {@link IterationManager}
119 */
120 public RealVector solve(final RealLinearOperator a, final RealVector b)
121 throws NullArgumentException, NonSquareOperatorException,
122 DimensionMismatchException, MaxCountExceededException {
123 MathUtils.checkNotNull(a);
124 final RealVector x = new ArrayRealVector(a.getColumnDimension());
125 x.set(0.);
126 return solveInPlace(a, b, x);
127 }
128
129 /**
130 * Returns an estimate of the solution to the linear system A · x =
131 * b.
132 *
133 * @param a the linear operator A of the system
134 * @param b the right-hand side vector
135 * @param x0 the initial guess of the solution
136 * @return a new vector containing the solution
137 * @throws NullArgumentException if one of the parameters is {@code null}
138 * @throws NonSquareOperatorException if {@code a} is not square
139 * @throws DimensionMismatchException if {@code b} or {@code x0} have
140 * dimensions inconsistent with {@code a}
141 * @throws MaxCountExceededException at exhaustion of the iteration count,
142 * unless a custom
143 * {@link org.apache.commons.math3.util.Incrementor.MaxCountExceededCallback callback}
144 * has been set at construction of the {@link IterationManager}
145 */
146 public RealVector solve(RealLinearOperator a, RealVector b, RealVector x0)
147 throws NullArgumentException, NonSquareOperatorException,
148 DimensionMismatchException, MaxCountExceededException {
149 MathUtils.checkNotNull(x0);
150 return solveInPlace(a, b, x0.copy());
151 }
152
153 /**
154 * Returns an estimate of the solution to the linear system A · x =
155 * b. The solution is computed in-place (initial guess is modified).
156 *
157 * @param a the linear operator A of the system
158 * @param b the right-hand side vector
159 * @param x0 initial guess of the solution
160 * @return a reference to {@code x0} (shallow copy) updated with the
161 * solution
162 * @throws NullArgumentException if one of the parameters is {@code null}
163 * @throws NonSquareOperatorException if {@code a} is not square
164 * @throws DimensionMismatchException if {@code b} or {@code x0} 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.math3.util.Incrementor.MaxCountExceededCallback callback}
169 * has been set at construction of the {@link IterationManager}
170 */
171 public abstract RealVector solveInPlace(RealLinearOperator a, RealVector b,
172 RealVector x0) throws NullArgumentException, NonSquareOperatorException,
173 DimensionMismatchException, MaxCountExceededException;
174 }