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