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 * <p> 027 * This abstract class defines preconditioned iterative solvers. When A is 028 * ill-conditioned, instead of solving system A · x = b directly, it is 029 * preferable to solve either 030 * <center> 031 * (M · A) · x = M · b 032 * </center> 033 * (left preconditioning), or 034 * <center> 035 * (A · M) · y = b, followed by 036 * M · y = x 037 * </center> 038 * (right preconditioning), where M approximates in some way A<sup>-1</sup>, 039 * while matrix-vector products of the type M · y remain comparatively 040 * easy to compute. In this library, M (not M<sup>-1</sup>!) is called the 041 * <em>preconditionner</em>. 042 * </p> 043 * <p> 044 * Concrete implementations of this abstract class must be provided with the 045 * preconditioner M, as a {@link RealLinearOperator}. 046 * </p> 047 * 048 * @version $Id: PreconditionedIterativeLinearSolver.java 1416643 2012-12-03 19:37:14Z tn $ 049 * @since 3.0 050 */ 051 public abstract class PreconditionedIterativeLinearSolver 052 extends IterativeLinearSolver { 053 054 /** 055 * Creates a new instance of this class, with default iteration manager. 056 * 057 * @param maxIterations the maximum number of iterations 058 */ 059 public PreconditionedIterativeLinearSolver(final int maxIterations) { 060 super(maxIterations); 061 } 062 063 /** 064 * Creates a new instance of this class, with custom iteration manager. 065 * 066 * @param manager the custom iteration manager 067 * @throws NullArgumentException if {@code manager} is {@code null} 068 */ 069 public PreconditionedIterativeLinearSolver(final IterationManager manager) 070 throws NullArgumentException { 071 super(manager); 072 } 073 074 /** 075 * Returns an estimate of the solution to the linear system A · x = 076 * b. 077 * 078 * @param a the linear operator A of the system 079 * @param m the preconditioner, M (can be {@code null}) 080 * @param b the right-hand side vector 081 * @param x0 the initial guess of the solution 082 * @return a new vector containing the solution 083 * @throws NullArgumentException if one of the parameters is {@code null} 084 * @throws NonSquareOperatorException if {@code a} or {@code m} is not 085 * square 086 * @throws DimensionMismatchException if {@code m}, {@code b} or 087 * {@code x0} have dimensions inconsistent with {@code a} 088 * @throws MaxCountExceededException at exhaustion of the iteration count, 089 * unless a custom 090 * {@link org.apache.commons.math3.util.Incrementor.MaxCountExceededCallback callback} 091 * has been set at construction of the {@link IterationManager} 092 */ 093 public RealVector solve(final RealLinearOperator a, 094 final RealLinearOperator m, final RealVector b, final RealVector x0) 095 throws NullArgumentException, NonSquareOperatorException, 096 DimensionMismatchException, MaxCountExceededException { 097 MathUtils.checkNotNull(x0); 098 return solveInPlace(a, m, b, x0.copy()); 099 } 100 101 /** {@inheritDoc} */ 102 @Override 103 public RealVector solve(final RealLinearOperator a, final RealVector b) 104 throws NullArgumentException, NonSquareOperatorException, 105 DimensionMismatchException, MaxCountExceededException { 106 MathUtils.checkNotNull(a); 107 final RealVector x = new ArrayRealVector(a.getColumnDimension()); 108 x.set(0.); 109 return solveInPlace(a, null, b, x); 110 } 111 112 /** {@inheritDoc} */ 113 @Override 114 public RealVector solve(final RealLinearOperator a, final RealVector b, 115 final RealVector x0) 116 throws NullArgumentException, NonSquareOperatorException, 117 DimensionMismatchException, MaxCountExceededException { 118 MathUtils.checkNotNull(x0); 119 return solveInPlace(a, null, b, x0.copy()); 120 } 121 122 /** 123 * Performs all dimension checks on the parameters of 124 * {@link #solve(RealLinearOperator, RealLinearOperator, RealVector, RealVector) solve} 125 * and 126 * {@link #solveInPlace(RealLinearOperator, RealLinearOperator, RealVector, RealVector) solveInPlace}, 127 * and throws an exception if one of the checks fails. 128 * 129 * @param a the linear operator A of the system 130 * @param m the preconditioner, M (can be {@code null}) 131 * @param b the right-hand side vector 132 * @param x0 the initial guess of the solution 133 * @throws NullArgumentException if one of the parameters is {@code null} 134 * @throws NonSquareOperatorException if {@code a} or {@code m} is not 135 * square 136 * @throws DimensionMismatchException if {@code m}, {@code b} or 137 * {@code x0} have dimensions inconsistent with {@code a} 138 */ 139 protected static void checkParameters(final RealLinearOperator a, 140 final RealLinearOperator m, final RealVector b, final RealVector x0) 141 throws NullArgumentException, NonSquareOperatorException, 142 DimensionMismatchException { 143 checkParameters(a, b, x0); 144 if (m != null) { 145 if (m.getColumnDimension() != m.getRowDimension()) { 146 throw new NonSquareOperatorException(m.getColumnDimension(), 147 m.getRowDimension()); 148 } 149 if (m.getRowDimension() != a.getRowDimension()) { 150 throw new DimensionMismatchException(m.getRowDimension(), 151 a.getRowDimension()); 152 } 153 } 154 } 155 156 /** 157 * Returns an estimate of the solution to the linear system A · x = 158 * b. 159 * 160 * @param a the linear operator A of the system 161 * @param m the preconditioner, M (can be {@code null}) 162 * @param b the right-hand side vector 163 * @return a new vector containing the solution 164 * @throws NullArgumentException if one of the parameters is {@code null} 165 * @throws NonSquareOperatorException if {@code a} or {@code m} is not 166 * square 167 * @throws DimensionMismatchException if {@code m} or {@code b} have 168 * dimensions inconsistent with {@code a} 169 * @throws MaxCountExceededException at exhaustion of the iteration count, 170 * unless a custom 171 * {@link org.apache.commons.math3.util.Incrementor.MaxCountExceededCallback callback} 172 * has been set at construction of the {@link IterationManager} 173 */ 174 public RealVector solve(RealLinearOperator a, RealLinearOperator m, 175 RealVector b) throws NullArgumentException, NonSquareOperatorException, 176 DimensionMismatchException, MaxCountExceededException { 177 MathUtils.checkNotNull(a); 178 final RealVector x = new ArrayRealVector(a.getColumnDimension()); 179 return solveInPlace(a, m, b, x); 180 } 181 182 /** 183 * Returns an estimate of the solution to the linear system A · x = 184 * b. The solution is computed in-place (initial guess is modified). 185 * 186 * @param a the linear operator A of the system 187 * @param m the preconditioner, M (can be {@code null}) 188 * @param b the right-hand side vector 189 * @param x0 the initial guess of the solution 190 * @return a reference to {@code x0} (shallow copy) updated with the 191 * solution 192 * @throws NullArgumentException if one of the parameters is {@code null} 193 * @throws NonSquareOperatorException if {@code a} or {@code m} is not 194 * square 195 * @throws DimensionMismatchException if {@code m}, {@code b} or 196 * {@code x0} have dimensions inconsistent with {@code a} 197 * @throws MaxCountExceededException at exhaustion of the iteration count, 198 * unless a custom 199 * {@link org.apache.commons.math3.util.Incrementor.MaxCountExceededCallback callback} 200 * has been set at construction of the {@link IterationManager} 201 */ 202 public abstract RealVector solveInPlace(RealLinearOperator a, 203 RealLinearOperator m, RealVector b, RealVector x0) throws 204 NullArgumentException, NonSquareOperatorException, 205 DimensionMismatchException, MaxCountExceededException; 206 207 /** {@inheritDoc} */ 208 @Override 209 public RealVector solveInPlace(final RealLinearOperator a, 210 final RealVector b, final RealVector x0) throws 211 NullArgumentException, NonSquareOperatorException, 212 DimensionMismatchException, MaxCountExceededException { 213 return solveInPlace(a, null, b, x0); 214 } 215 }