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 * · x = b. In what follows, the <em>residual</em> r is defined as r = b 34 * - A · 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 · 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 · 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 · 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 }