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