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 */ 017package org.apache.commons.math4.legacy.linear; 018 019import org.apache.commons.math4.legacy.exception.DimensionMismatchException; 020import org.apache.commons.math4.legacy.exception.MaxCountExceededException; 021import org.apache.commons.math4.legacy.exception.NullArgumentException; 022 023/** 024 * <p> 025 * This abstract class defines preconditioned iterative solvers. When A is 026 * ill-conditioned, instead of solving system A · x = b directly, it is 027 * preferable to solve either 028 * <pre> 029 * (M · A) · x = M · b 030 * </pre> 031 * (left preconditioning), or 032 * <pre> 033 * (A · M) · y = b, followed by 034 * M · y = x 035 * </pre> 036 * (right preconditioning), where M approximates in some way A<sup>-1</sup>, 037 * while matrix-vector products of the type M · y remain comparatively 038 * easy to compute. In this library, M (not M<sup>-1</sup>!) is called the 039 * <em>preconditionner</em>. 040 * 041 * <p> 042 * Concrete implementations of this abstract class must be provided with the 043 * preconditioner M, as a {@link RealLinearOperator}. 044 * </p> 045 * 046 * @since 3.0 047 */ 048public abstract class PreconditionedIterativeLinearSolver 049 extends IterativeLinearSolver { 050 051 /** 052 * Creates a new instance of this class, with default iteration manager. 053 * 054 * @param maxIterations the maximum number of iterations 055 */ 056 public PreconditionedIterativeLinearSolver(final int maxIterations) { 057 super(maxIterations); 058 } 059 060 /** 061 * Creates a new instance of this class, with custom iteration manager. 062 * 063 * @param manager the custom iteration manager 064 * @throws NullArgumentException if {@code manager} is {@code null} 065 */ 066 public PreconditionedIterativeLinearSolver(final IterationManager manager) 067 throws NullArgumentException { 068 super(manager); 069 } 070 071 /** 072 * Returns an estimate of the solution to the linear system A · x = 073 * b. 074 * 075 * @param a the linear operator A of the system 076 * @param m the preconditioner, M (can be {@code null}) 077 * @param b the right-hand side vector 078 * @param x0 the initial guess of the solution 079 * @return a new vector containing the solution 080 * @throws NullArgumentException if one of the parameters is {@code null} 081 * @throws NonSquareOperatorException if {@code a} or {@code m} is not 082 * square 083 * @throws DimensionMismatchException if {@code m}, {@code b} or 084 * {@code x0} have dimensions inconsistent with {@code a} 085 * @throws MaxCountExceededException at exhaustion of the iteration count, 086 * unless a custom 087 * {@link org.apache.commons.math4.legacy.core.IntegerSequence.Incrementor.MaxCountExceededCallback callback} 088 * has been set at construction of the {@link IterationManager} 089 */ 090 public RealVector solve(final RealLinearOperator a, 091 final RealLinearOperator m, final RealVector b, final RealVector x0) 092 throws NullArgumentException, NonSquareOperatorException, 093 DimensionMismatchException, MaxCountExceededException { 094 NullArgumentException.check(x0); 095 return solveInPlace(a, m, b, x0.copy()); 096 } 097 098 /** {@inheritDoc} */ 099 @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}