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 }