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 * This abstract class defines an iterative solver for the linear system A 027 * · x = b. In what follows, the <em>residual</em> r is defined as r = b 028 * - A · x, where A is the linear operator of the linear system, b is the 029 * right-hand side vector, and x the current estimate of the solution. 030 * 031 * @version $Id: IterativeLinearSolver.java 1416643 2012-12-03 19:37:14Z tn $ 032 * @since 3.0 033 */ 034 public abstract class IterativeLinearSolver { 035 036 /** The object in charge of managing the iterations. */ 037 private final IterationManager manager; 038 039 /** 040 * Creates a new instance of this class, with default iteration manager. 041 * 042 * @param maxIterations the maximum number of iterations 043 */ 044 public IterativeLinearSolver(final int maxIterations) { 045 this.manager = new IterationManager(maxIterations); 046 } 047 048 /** 049 * Creates a new instance of this class, with custom iteration manager. 050 * 051 * @param manager the custom iteration manager 052 * @throws NullArgumentException if {@code manager} is {@code null} 053 */ 054 public IterativeLinearSolver(final IterationManager manager) 055 throws NullArgumentException { 056 MathUtils.checkNotNull(manager); 057 this.manager = manager; 058 } 059 060 /** 061 * Performs all dimension checks on the parameters of 062 * {@link #solve(RealLinearOperator, RealVector, RealVector) solve} and 063 * {@link #solveInPlace(RealLinearOperator, RealVector, RealVector) solveInPlace}, 064 * and throws an exception if one of the checks fails. 065 * 066 * @param a the linear operator A of the system 067 * @param b the right-hand side vector 068 * @param x0 the initial guess of the solution 069 * @throws NullArgumentException if one of the parameters is {@code null} 070 * @throws NonSquareOperatorException if {@code a} is not square 071 * @throws DimensionMismatchException if {@code b} or {@code x0} have 072 * dimensions inconsistent with {@code a} 073 */ 074 protected static void checkParameters(final RealLinearOperator a, 075 final RealVector b, final RealVector x0) throws 076 NullArgumentException, NonSquareOperatorException, 077 DimensionMismatchException { 078 MathUtils.checkNotNull(a); 079 MathUtils.checkNotNull(b); 080 MathUtils.checkNotNull(x0); 081 if (a.getRowDimension() != a.getColumnDimension()) { 082 throw new NonSquareOperatorException(a.getRowDimension(), 083 a.getColumnDimension()); 084 } 085 if (b.getDimension() != a.getRowDimension()) { 086 throw new DimensionMismatchException(b.getDimension(), 087 a.getRowDimension()); 088 } 089 if (x0.getDimension() != a.getColumnDimension()) { 090 throw new DimensionMismatchException(x0.getDimension(), 091 a.getColumnDimension()); 092 } 093 } 094 095 /** 096 * Returns the iteration manager attached to this solver. 097 * 098 * @return the manager 099 */ 100 public IterationManager getIterationManager() { 101 return manager; 102 } 103 104 /** 105 * Returns an estimate of the solution to the linear system A · x = 106 * b. 107 * 108 * @param a the linear operator A of the system 109 * @param b the right-hand side vector 110 * @return a new vector containing the solution 111 * @throws NullArgumentException if one of the parameters is {@code null} 112 * @throws NonSquareOperatorException if {@code a} is not square 113 * @throws DimensionMismatchException if {@code b} has dimensions 114 * inconsistent with {@code a} 115 * @throws MaxCountExceededException at exhaustion of the iteration count, 116 * unless a custom 117 * {@link org.apache.commons.math3.util.Incrementor.MaxCountExceededCallback callback} 118 * has been set at construction of the {@link IterationManager} 119 */ 120 public RealVector solve(final RealLinearOperator a, final RealVector b) 121 throws NullArgumentException, NonSquareOperatorException, 122 DimensionMismatchException, MaxCountExceededException { 123 MathUtils.checkNotNull(a); 124 final RealVector x = new ArrayRealVector(a.getColumnDimension()); 125 x.set(0.); 126 return solveInPlace(a, b, x); 127 } 128 129 /** 130 * Returns an estimate of the solution to the linear system A · x = 131 * b. 132 * 133 * @param a the linear operator A of the system 134 * @param b the right-hand side vector 135 * @param x0 the initial guess of the solution 136 * @return a new vector containing the solution 137 * @throws NullArgumentException if one of the parameters is {@code null} 138 * @throws NonSquareOperatorException if {@code a} is not square 139 * @throws DimensionMismatchException if {@code b} or {@code x0} have 140 * dimensions inconsistent with {@code a} 141 * @throws MaxCountExceededException at exhaustion of the iteration count, 142 * unless a custom 143 * {@link org.apache.commons.math3.util.Incrementor.MaxCountExceededCallback callback} 144 * has been set at construction of the {@link IterationManager} 145 */ 146 public RealVector solve(RealLinearOperator a, RealVector b, RealVector x0) 147 throws NullArgumentException, NonSquareOperatorException, 148 DimensionMismatchException, MaxCountExceededException { 149 MathUtils.checkNotNull(x0); 150 return solveInPlace(a, b, x0.copy()); 151 } 152 153 /** 154 * Returns an estimate of the solution to the linear system A · x = 155 * b. The solution is computed in-place (initial guess is modified). 156 * 157 * @param a the linear operator A of the system 158 * @param b the right-hand side vector 159 * @param x0 initial guess of the solution 160 * @return a reference to {@code x0} (shallow copy) updated with the 161 * solution 162 * @throws NullArgumentException if one of the parameters is {@code null} 163 * @throws NonSquareOperatorException if {@code a} is not square 164 * @throws DimensionMismatchException if {@code b} or {@code x0} 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.math3.util.Incrementor.MaxCountExceededCallback callback} 169 * has been set at construction of the {@link IterationManager} 170 */ 171 public abstract RealVector solveInPlace(RealLinearOperator a, RealVector b, 172 RealVector x0) throws NullArgumentException, NonSquareOperatorException, 173 DimensionMismatchException, MaxCountExceededException; 174 }