SymmLQ.java

  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. import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
  19. import org.apache.commons.math4.legacy.exception.MaxCountExceededException;
  20. import org.apache.commons.math4.legacy.exception.NullArgumentException;
  21. import org.apache.commons.math4.legacy.exception.util.ExceptionContext;
  22. import org.apache.commons.math4.core.jdkmath.JdkMath;

  23. /**
  24.  * <p>
  25.  * Implementation of the SYMMLQ iterative linear solver proposed by <a
  26.  * href="#PAIG1975">Paige and Saunders (1975)</a>. This implementation is
  27.  * largely based on the FORTRAN code by Pr. Michael A. Saunders, available <a
  28.  * href="http://www.stanford.edu/group/SOL/software/symmlq/f77/">here</a>.
  29.  * </p>
  30.  * <p>
  31.  * SYMMLQ is designed to solve the system of linear equations A &middot; x = b
  32.  * where A is an n &times; n self-adjoint linear operator (defined as a
  33.  * {@link RealLinearOperator}), and b is a given vector. The operator A is not
  34.  * required to be positive definite. If A is known to be definite, the method of
  35.  * conjugate gradients might be preferred, since it will require about the same
  36.  * number of iterations as SYMMLQ but slightly less work per iteration.
  37.  * </p>
  38.  * <p>
  39.  * SYMMLQ is designed to solve the system (A - shift &middot; I) &middot; x = b,
  40.  * where shift is a specified scalar value. If shift and b are suitably chosen,
  41.  * the computed vector x may approximate an (unnormalized) eigenvector of A, as
  42.  * in the methods of inverse iteration and/or Rayleigh-quotient iteration.
  43.  * Again, the linear operator (A - shift &middot; I) need not be positive
  44.  * definite (but <em>must</em> be self-adjoint). The work per iteration is very
  45.  * slightly less if shift = 0.
  46.  * </p>
  47.  * <p><b>Preconditioning</b></p>
  48.  * <p>
  49.  * Preconditioning may reduce the number of iterations required. The solver may
  50.  * be provided with a positive definite preconditioner
  51.  * M = P<sup>T</sup> &middot; P
  52.  * that is known to approximate
  53.  * (A - shift &middot; I)<sup>-1</sup> in some sense, where matrix-vector
  54.  * products of the form M &middot; y = x can be computed efficiently. Then
  55.  * SYMMLQ will implicitly solve the system of equations
  56.  * P &middot; (A - shift &middot; I) &middot; P<sup>T</sup> &middot;
  57.  * x<sub>hat</sub> = P &middot; b, i.e.
  58.  * A<sub>hat</sub> &middot; x<sub>hat</sub> = b<sub>hat</sub>,
  59.  * where
  60.  * A<sub>hat</sub> = P &middot; (A - shift &middot; I) &middot; P<sup>T</sup>,
  61.  * b<sub>hat</sub> = P &middot; b,
  62.  * and return the solution
  63.  * x = P<sup>T</sup> &middot; x<sub>hat</sub>.
  64.  * The associated residual is
  65.  * r<sub>hat</sub> = b<sub>hat</sub> - A<sub>hat</sub> &middot; x<sub>hat</sub>
  66.  *                 = P &middot; [b - (A - shift &middot; I) &middot; x]
  67.  *                 = P &middot; r.
  68.  * </p>
  69.  * <p>
  70.  * In the case of preconditioning, the {@link IterativeLinearSolverEvent}s that
  71.  * this solver fires are such that
  72.  * {@link IterativeLinearSolverEvent#getNormOfResidual()} returns the norm of
  73.  * the <em>preconditioned</em>, updated residual, ||P &middot; r||, not the norm
  74.  * of the <em>true</em> residual ||r||.
  75.  * </p>
  76.  * <p><b><a id="stopcrit">Default stopping criterion</a></b></p>
  77.  * <p>
  78.  * A default stopping criterion is implemented. The iterations stop when || rhat
  79.  * || &le; &delta; || Ahat || || xhat ||, where xhat is the current estimate of
  80.  * the solution of the transformed system, rhat the current estimate of the
  81.  * corresponding residual, and &delta; a user-specified tolerance.
  82.  * </p>
  83.  * <p><b>Iteration count</b></p>
  84.  * <p>
  85.  * In the present context, an iteration should be understood as one evaluation
  86.  * of the matrix-vector product A &middot; x. The initialization phase therefore
  87.  * counts as one iteration. If the user requires checks on the symmetry of A,
  88.  * this entails one further matrix-vector product in the initial phase. This
  89.  * further product is <em>not</em> accounted for in the iteration count. In
  90.  * other words, the number of iterations required to reach convergence will be
  91.  * identical, whether checks have been required or not.
  92.  * </p>
  93.  * <p>
  94.  * The present definition of the iteration count differs from that adopted in
  95.  * the original FOTRAN code, where the initialization phase was <em>not</em>
  96.  * taken into account.
  97.  * </p>
  98.  * <p><b><a id="initguess">Initial guess of the solution</a></b></p>
  99.  * <p>
  100.  * The {@code x} parameter in
  101.  * <ul>
  102.  * <li>{@link #solve(RealLinearOperator, RealVector, RealVector)},</li>
  103.  * <li>{@link #solve(RealLinearOperator, RealLinearOperator, RealVector, RealVector)}},</li>
  104.  * <li>{@link #solveInPlace(RealLinearOperator, RealVector, RealVector)},</li>
  105.  * <li>{@link #solveInPlace(RealLinearOperator, RealLinearOperator, RealVector, RealVector)},</li>
  106.  * <li>{@link #solveInPlace(RealLinearOperator, RealLinearOperator, RealVector, RealVector, boolean, double)},</li>
  107.  * </ul>
  108.  * should not be considered as an initial guess, as it is set to zero in the
  109.  * initial phase. If x<sub>0</sub> is known to be a good approximation to x, one
  110.  * should compute r<sub>0</sub> = b - A &middot; x, solve A &middot; dx = r0,
  111.  * and set x = x<sub>0</sub> + dx.
  112.  *
  113.  * <p><b><a id="context">Exception context</a></b></p>
  114.  * <p>
  115.  * Besides standard {@link DimensionMismatchException}, this class might throw
  116.  * {@link NonSelfAdjointOperatorException} if the linear operator or the
  117.  * preconditioner are not symmetric. In this case, the {@link ExceptionContext}
  118.  * provides more information
  119.  * <ul>
  120.  * <li>key {@code "operator"} points to the offending linear operator, say L,</li>
  121.  * <li>key {@code "vector1"} points to the first offending vector, say x,
  122.  * <li>key {@code "vector2"} points to the second offending vector, say y, such
  123.  * that x<sup>T</sup> &middot; L &middot; y &ne; y<sup>T</sup> &middot; L
  124.  * &middot; x (within a certain accuracy).</li>
  125.  * </ul>
  126.  *
  127.  * <p>
  128.  * {@link NonPositiveDefiniteOperatorException} might also be thrown in case the
  129.  * preconditioner is not positive definite. The relevant keys to the
  130.  * {@link ExceptionContext} are
  131.  * <ul>
  132.  * <li>key {@code "operator"}, which points to the offending linear operator,
  133.  * say L,</li>
  134.  * <li>key {@code "vector"}, which points to the offending vector, say x, such
  135.  * that x<sup>T</sup> &middot; L &middot; x &lt; 0.</li>
  136.  * </ul>
  137.  *
  138.  * <p><b>References</b></p>
  139.  * <dl>
  140.  * <dt><a id="PAIG1975">Paige and Saunders (1975)</a></dt>
  141.  * <dd>C. C. Paige and M. A. Saunders, <a
  142.  * href="http://www.stanford.edu/group/SOL/software/symmlq/PS75.pdf"><em>
  143.  * Solution of Sparse Indefinite Systems of Linear Equations</em></a>, SIAM
  144.  * Journal on Numerical Analysis 12(4): 617-629, 1975</dd>
  145.  * </dl>
  146.  *
  147.  * @since 3.0
  148.  */
  149. public class SymmLQ
  150.     extends PreconditionedIterativeLinearSolver {

  151.     /*
  152.      * IMPLEMENTATION NOTES
  153.      * --------------------
  154.      * The implementation follows as closely as possible the notations of Paige
  155.      * and Saunders (1975). Attention must be paid to the fact that some
  156.      * quantities which are relevant to iteration k can only be computed in
  157.      * iteration (k+1). Therefore, minute attention must be paid to the index of
  158.      * each state variable of this algorithm.
  159.      *
  160.      * 1. Preconditioning
  161.      *    ---------------
  162.      * The Lanczos iterations associated with Ahat and bhat read
  163.      *   beta[1] = ||P * b||
  164.      *   v[1] = P * b / beta[1]
  165.      *   beta[k+1] * v[k+1] = Ahat * v[k] - alpha[k] * v[k] - beta[k] * v[k-1]
  166.      *                      = P * (A - shift * I) * P' * v[k] - alpha[k] * v[k]
  167.      *                        - beta[k] * v[k-1]
  168.      * Multiplying both sides by P', we get
  169.      *   beta[k+1] * (P' * v)[k+1] = M * (A - shift * I) * (P' * v)[k]
  170.      *                               - alpha[k] * (P' * v)[k]
  171.      *                               - beta[k] * (P' * v[k-1]),
  172.      * and
  173.      *   alpha[k+1] = v[k+1]' * Ahat * v[k+1]
  174.      *              = v[k+1]' * P * (A - shift * I) * P' * v[k+1]
  175.      *              = (P' * v)[k+1]' * (A - shift * I) * (P' * v)[k+1].
  176.      *
  177.      * In other words, the Lanczos iterations are unchanged, except for the fact
  178.      * that we really compute (P' * v) instead of v. It can easily be checked
  179.      * that all other formulas are unchanged. It must be noted that P is never
  180.      * explicitly used, only matrix-vector products involving are invoked.
  181.      *
  182.      * 2. Accounting for the shift parameter
  183.      *    ----------------------------------
  184.      * Is trivial: each time A.operate(x) is invoked, one must subtract shift * x
  185.      * to the result.
  186.      *
  187.      * 3. Accounting for the goodb flag
  188.      *    -----------------------------
  189.      * When goodb is set to true, the component of xL along b is computed
  190.      * separately. From Paige and Saunders (1975), equation (5.9), we have
  191.      *   wbar[k+1] = s[k] * wbar[k] - c[k] * v[k+1],
  192.      *   wbar[1] = v[1].
  193.      * Introducing wbar2[k] = wbar[k] - s[1] * ... * s[k-1] * v[1], it can
  194.      * easily be verified by induction that wbar2 follows the same recursive
  195.      * relation
  196.      *   wbar2[k+1] = s[k] * wbar2[k] - c[k] * v[k+1],
  197.      *   wbar2[1] = 0,
  198.      * and we then have
  199.      *   w[k] = c[k] * wbar2[k] + s[k] * v[k+1]
  200.      *          + s[1] * ... * s[k-1] * c[k] * v[1].
  201.      * Introducing w2[k] = w[k] - s[1] * ... * s[k-1] * c[k] * v[1], we find,
  202.      * from (5.10)
  203.      *   xL[k] = zeta[1] * w[1] + ... + zeta[k] * w[k]
  204.      *         = zeta[1] * w2[1] + ... + zeta[k] * w2[k]
  205.      *           + (s[1] * c[2] * zeta[2] + ...
  206.      *           + s[1] * ... * s[k-1] * c[k] * zeta[k]) * v[1]
  207.      *         = xL2[k] + bstep[k] * v[1],
  208.      * where xL2[k] is defined by
  209.      *   xL2[0] = 0,
  210.      *   xL2[k+1] = xL2[k] + zeta[k+1] * w2[k+1],
  211.      * and bstep is defined by
  212.      *   bstep[1] = 0,
  213.      *   bstep[k] = bstep[k-1] + s[1] * ... * s[k-1] * c[k] * zeta[k].
  214.      * We also have, from (5.11)
  215.      *   xC[k] = xL[k-1] + zbar[k] * wbar[k]
  216.      *         = xL2[k-1] + zbar[k] * wbar2[k]
  217.      *           + (bstep[k-1] + s[1] * ... * s[k-1] * zbar[k]) * v[1].
  218.      */

  219.     /**
  220.      * <p>
  221.      * A simple container holding the non-final variables used in the
  222.      * iterations. Making the current state of the solver visible from the
  223.      * outside is necessary, because during the iterations, {@code x} does not
  224.      * <em>exactly</em> hold the current estimate of the solution. Indeed,
  225.      * {@code x} needs in general to be moved from the LQ point to the CG point.
  226.      * Besides, additional upudates must be carried out in case {@code goodb} is
  227.      * set to {@code true}.
  228.      * </p>
  229.      * <p>
  230.      * In all subsequent comments, the description of the state variables refer
  231.      * to their value after a call to {@link #update()}. In these comments, k is
  232.      * the current number of evaluations of matrix-vector products.
  233.      * </p>
  234.      */
  235.     private static final class State {
  236.         /** The cubic root of {@link #MACH_PREC}. */
  237.         static final double CBRT_MACH_PREC;

  238.         /** The machine precision. */
  239.         static final double MACH_PREC;

  240.         /** Reference to the linear operator. */
  241.         private final RealLinearOperator a;

  242.         /** Reference to the right-hand side vector. */
  243.         private final RealVector b;

  244.         /** {@code true} if symmetry of matrix and conditioner must be checked. */
  245.         private final boolean check;

  246.         /**
  247.          * The value of the custom tolerance &delta; for the default stopping
  248.          * criterion.
  249.          */
  250.         private final double delta;

  251.         /** The value of beta[k+1]. */
  252.         private double beta;

  253.         /** The value of beta[1]. */
  254.         private double beta1;

  255.         /** The value of bstep[k-1]. */
  256.         private double bstep;

  257.         /** The estimate of the norm of P * rC[k]. */
  258.         private double cgnorm;

  259.         /** The value of dbar[k+1] = -beta[k+1] * c[k-1]. */
  260.         private double dbar;

  261.         /**
  262.          * The value of gamma[k] * zeta[k]. Was called {@code rhs1} in the
  263.          * initial code.
  264.          */
  265.         private double gammaZeta;

  266.         /** The value of gbar[k]. */
  267.         private double gbar;

  268.         /** The value of max(|alpha[1]|, gamma[1], ..., gamma[k-1]). */
  269.         private double gmax;

  270.         /** The value of min(|alpha[1]|, gamma[1], ..., gamma[k-1]). */
  271.         private double gmin;

  272.         /** Copy of the {@code goodb} parameter. */
  273.         private final boolean goodb;

  274.         /** {@code true} if the default convergence criterion is verified. */
  275.         private boolean hasConverged;

  276.         /** The estimate of the norm of P * rL[k-1]. */
  277.         private double lqnorm;

  278.         /** Reference to the preconditioner, M. */
  279.         private final RealLinearOperator m;

  280.         /**
  281.          * The value of (-eps[k+1] * zeta[k-1]). Was called {@code rhs2} in the
  282.          * initial code.
  283.          */
  284.         private double minusEpsZeta;

  285.         /** The value of M * b. */
  286.         private final RealVector mb;

  287.         /** The value of beta[k]. */
  288.         private double oldb;

  289.         /** The value of beta[k] * M^(-1) * P' * v[k]. */
  290.         private RealVector r1;

  291.         /** The value of beta[k+1] * M^(-1) * P' * v[k+1]. */
  292.         private RealVector r2;

  293.         /**
  294.          * The value of the updated, preconditioned residual P * r. This value is
  295.          * given by {@code min(}{@link #cgnorm}{@code , }{@link #lqnorm}{@code )}.
  296.          */
  297.         private double rnorm;

  298.         /** Copy of the {@code shift} parameter. */
  299.         private final double shift;

  300.         /** The value of s[1] * ... * s[k-1]. */
  301.         private double snprod;

  302.         /**
  303.          * An estimate of the square of the norm of A * V[k], based on Paige and
  304.          * Saunders (1975), equation (3.3).
  305.          */
  306.         private double tnorm;

  307.         /**
  308.          * The value of P' * wbar[k] or P' * (wbar[k] - s[1] * ... * s[k-1] *
  309.          * v[1]) if {@code goodb} is {@code true}. Was called {@code w} in the
  310.          * initial code.
  311.          */
  312.         private RealVector wbar;

  313.         /**
  314.          * A reference to the vector to be updated with the solution. Contains
  315.          * the value of xL[k-1] if {@code goodb} is {@code false}, (xL[k-1] -
  316.          * bstep[k-1] * v[1]) otherwise.
  317.          */
  318.         private final RealVector xL;

  319.         /** The value of beta[k+1] * P' * v[k+1]. */
  320.         private RealVector y;

  321.         /** The value of zeta[1]^2 + ... + zeta[k-1]^2. */
  322.         private double ynorm2;

  323.         /** The value of {@code b == 0} (exact floating-point equality). */
  324.         private boolean bIsNull;

  325.         static {
  326.             MACH_PREC = JdkMath.ulp(1.);
  327.             CBRT_MACH_PREC = JdkMath.cbrt(MACH_PREC);
  328.         }

  329.         /**
  330.          * Creates and inits to k = 1 a new instance of this class.
  331.          *
  332.          * @param a the linear operator A of the system
  333.          * @param m the preconditioner, M (can be {@code null})
  334.          * @param b the right-hand side vector
  335.          * @param goodb usually {@code false}, except if {@code x} is expected
  336.          * to contain a large multiple of {@code b}
  337.          * @param shift the amount to be subtracted to all diagonal elements of
  338.          * A
  339.          * @param delta the &delta; parameter for the default stopping criterion
  340.          * @param check {@code true} if self-adjointedness of both matrix and
  341.          * preconditioner should be checked
  342.          */
  343.         State(final RealLinearOperator a,
  344.             final RealLinearOperator m,
  345.             final RealVector b,
  346.             final boolean goodb,
  347.             final double shift,
  348.             final double delta,
  349.             final boolean check) {
  350.             this.a = a;
  351.             this.m = m;
  352.             this.b = b;
  353.             this.xL = new ArrayRealVector(b.getDimension());
  354.             this.goodb = goodb;
  355.             this.shift = shift;
  356.             this.mb = m == null ? b : m.operate(b);
  357.             this.hasConverged = false;
  358.             this.check = check;
  359.             this.delta = delta;
  360.         }

  361.         /**
  362.          * Performs a symmetry check on the specified linear operator, and throws an
  363.          * exception in case this check fails. Given a linear operator L, and a
  364.          * vector x, this method checks that
  365.          * x' &middot; L &middot; y = y' &middot; L &middot; x
  366.          * (within a given accuracy), where y = L &middot; x.
  367.          *
  368.          * @param l the linear operator L
  369.          * @param x the candidate vector x
  370.          * @param y the candidate vector y = L &middot; x
  371.          * @param z the vector z = L &middot; y
  372.          * @throws NonSelfAdjointOperatorException when the test fails
  373.          */
  374.         private static void checkSymmetry(final RealLinearOperator l,
  375.             final RealVector x, final RealVector y, final RealVector z)
  376.             throws NonSelfAdjointOperatorException {
  377.             final double s = y.dotProduct(y);
  378.             final double t = x.dotProduct(z);
  379.             final double epsa = (s + MACH_PREC) * CBRT_MACH_PREC;
  380.             if (JdkMath.abs(s - t) > epsa) {
  381.                 final NonSelfAdjointOperatorException e;
  382.                 e = new NonSelfAdjointOperatorException();
  383.                 final ExceptionContext context = e.getContext();
  384.                 context.setValue(SymmLQ.OPERATOR, l);
  385.                 context.setValue(SymmLQ.VECTOR1, x);
  386.                 context.setValue(SymmLQ.VECTOR2, y);
  387.                 context.setValue(SymmLQ.THRESHOLD, Double.valueOf(epsa));
  388.                 throw e;
  389.             }
  390.         }

  391.         /**
  392.          * Throws a new {@link NonPositiveDefiniteOperatorException} with
  393.          * appropriate context.
  394.          *
  395.          * @param l the offending linear operator
  396.          * @param v the offending vector
  397.          * @throws NonPositiveDefiniteOperatorException in any circumstances
  398.          */
  399.         private static void throwNPDLOException(final RealLinearOperator l,
  400.             final RealVector v) throws NonPositiveDefiniteOperatorException {
  401.             final NonPositiveDefiniteOperatorException e;
  402.             e = new NonPositiveDefiniteOperatorException();
  403.             final ExceptionContext context = e.getContext();
  404.             context.setValue(OPERATOR, l);
  405.             context.setValue(VECTOR, v);
  406.             throw e;
  407.         }

  408.         /**
  409.          * A clone of the BLAS {@code DAXPY} function, which carries out the
  410.          * operation y &larr; a &middot; x + y. This is for internal use only: no
  411.          * dimension checks are provided.
  412.          *
  413.          * @param a the scalar by which {@code x} is to be multiplied
  414.          * @param x the vector to be added to {@code y}
  415.          * @param y the vector to be incremented
  416.          */
  417.         private static void daxpy(final double a, final RealVector x,
  418.             final RealVector y) {
  419.             final int n = x.getDimension();
  420.             for (int i = 0; i < n; i++) {
  421.                 y.setEntry(i, a * x.getEntry(i) + y.getEntry(i));
  422.             }
  423.         }

  424.         /**
  425.          * A BLAS-like function, for the operation z &larr; a &middot; x + b
  426.          * &middot; y + z. This is for internal use only: no dimension checks are
  427.          * provided.
  428.          *
  429.          * @param a the scalar by which {@code x} is to be multiplied
  430.          * @param x the first vector to be added to {@code z}
  431.          * @param b the scalar by which {@code y} is to be multiplied
  432.          * @param y the second vector to be added to {@code z}
  433.          * @param z the vector to be incremented
  434.          */
  435.         private static void daxpbypz(final double a, final RealVector x,
  436.             final double b, final RealVector y, final RealVector z) {
  437.             final int n = z.getDimension();
  438.             for (int i = 0; i < n; i++) {
  439.                 final double zi;
  440.                 zi = a * x.getEntry(i) + b * y.getEntry(i) + z.getEntry(i);
  441.                 z.setEntry(i, zi);
  442.             }
  443.         }

  444.         /**
  445.          * <p>
  446.          * Move to the CG point if it seems better. In this version of SYMMLQ,
  447.          * the convergence tests involve only cgnorm, so we're unlikely to stop
  448.          * at an LQ point, except if the iteration limit interferes.
  449.          * </p>
  450.          * <p>
  451.          * Additional upudates are also carried out in case {@code goodb} is set
  452.          * to {@code true}.
  453.          * </p>
  454.          *
  455.          * @param x the vector to be updated with the refined value of xL
  456.          */
  457.          void refineSolution(final RealVector x) {
  458.             final int n = this.xL.getDimension();
  459.             if (lqnorm < cgnorm) {
  460.                 if (!goodb) {
  461.                     x.setSubVector(0, this.xL);
  462.                 } else {
  463.                     final double step = bstep / beta1;
  464.                     for (int i = 0; i < n; i++) {
  465.                         final double bi = mb.getEntry(i);
  466.                         final double xi = this.xL.getEntry(i);
  467.                         x.setEntry(i, xi + step * bi);
  468.                     }
  469.                 }
  470.             } else {
  471.                 final double anorm = JdkMath.sqrt(tnorm);
  472.                 final double diag = gbar == 0. ? anorm * MACH_PREC : gbar;
  473.                 final double zbar = gammaZeta / diag;
  474.                 final double step = (bstep + snprod * zbar) / beta1;
  475.                 // ynorm = JdkMath.sqrt(ynorm2 + zbar * zbar);
  476.                 if (!goodb) {
  477.                     for (int i = 0; i < n; i++) {
  478.                         final double xi = this.xL.getEntry(i);
  479.                         final double wi = wbar.getEntry(i);
  480.                         x.setEntry(i, xi + zbar * wi);
  481.                     }
  482.                 } else {
  483.                     for (int i = 0; i < n; i++) {
  484.                         final double xi = this.xL.getEntry(i);
  485.                         final double wi = wbar.getEntry(i);
  486.                         final double bi = mb.getEntry(i);
  487.                         x.setEntry(i, xi + zbar * wi + step * bi);
  488.                     }
  489.                 }
  490.             }
  491.         }

  492.         /**
  493.          * Performs the initial phase of the SYMMLQ algorithm. On return, the
  494.          * value of the state variables of {@code this} object correspond to k =
  495.          * 1.
  496.          */
  497.          void init() {
  498.             this.xL.set(0.);
  499.             /*
  500.              * Set up y for the first Lanczos vector. y and beta1 will be zero
  501.              * if b = 0.
  502.              */
  503.             this.r1 = this.b.copy();
  504.             this.y = this.m == null ? this.b.copy() : this.m.operate(this.r1);
  505.             if (this.m != null && this.check) {
  506.                 checkSymmetry(this.m, this.r1, this.y, this.m.operate(this.y));
  507.             }

  508.             this.beta1 = this.r1.dotProduct(this.y);
  509.             if (this.beta1 < 0.) {
  510.                 throwNPDLOException(this.m, this.y);
  511.             }
  512.             if (this.beta1 == 0.) {
  513.                 /* If b = 0 exactly, stop with x = 0. */
  514.                 this.bIsNull = true;
  515.                 return;
  516.             }
  517.             this.bIsNull = false;
  518.             this.beta1 = JdkMath.sqrt(this.beta1);
  519.             /* At this point
  520.              *   r1 = b,
  521.              *   y = M * b,
  522.              *   beta1 = beta[1].
  523.              */
  524.             final RealVector v = this.y.mapMultiply(1. / this.beta1);
  525.             this.y = this.a.operate(v);
  526.             if (this.check) {
  527.                 checkSymmetry(this.a, v, this.y, this.a.operate(this.y));
  528.             }
  529.             /*
  530.              * Set up y for the second Lanczos vector. y and beta will be zero
  531.              * or very small if b is an eigenvector.
  532.              */
  533.             daxpy(-this.shift, v, this.y);
  534.             final double alpha = v.dotProduct(this.y);
  535.             daxpy(-alpha / this.beta1, this.r1, this.y);
  536.             /*
  537.              * At this point
  538.              *   alpha = alpha[1]
  539.              *   y     = beta[2] * M^(-1) * P' * v[2]
  540.              */
  541.             /* Make sure r2 will be orthogonal to the first v. */
  542.             final double vty = v.dotProduct(this.y);
  543.             final double vtv = v.dotProduct(v);
  544.             daxpy(-vty / vtv, v, this.y);
  545.             this.r2 = this.y.copy();
  546.             if (this.m != null) {
  547.                 this.y = this.m.operate(this.r2);
  548.             }
  549.             this.oldb = this.beta1;
  550.             this.beta = this.r2.dotProduct(this.y);
  551.             if (this.beta < 0.) {
  552.                 throwNPDLOException(this.m, this.y);
  553.             }
  554.             this.beta = JdkMath.sqrt(this.beta);
  555.             /*
  556.              * At this point
  557.              *   oldb = beta[1]
  558.              *   beta = beta[2]
  559.              *   y  = beta[2] * P' * v[2]
  560.              *   r2 = beta[2] * M^(-1) * P' * v[2]
  561.              */
  562.             this.cgnorm = this.beta1;
  563.             this.gbar = alpha;
  564.             this.dbar = this.beta;
  565.             this.gammaZeta = this.beta1;
  566.             this.minusEpsZeta = 0.;
  567.             this.bstep = 0.;
  568.             this.snprod = 1.;
  569.             this.tnorm = alpha * alpha + this.beta * this.beta;
  570.             this.ynorm2 = 0.;
  571.             this.gmax = JdkMath.abs(alpha) + MACH_PREC;
  572.             this.gmin = this.gmax;

  573.             if (this.goodb) {
  574.                 this.wbar = new ArrayRealVector(this.a.getRowDimension());
  575.                 this.wbar.set(0.);
  576.             } else {
  577.                 this.wbar = v;
  578.             }
  579.             updateNorms();
  580.         }

  581.         /**
  582.          * Performs the next iteration of the algorithm. The iteration count
  583.          * should be incremented prior to calling this method. On return, the
  584.          * value of the state variables of {@code this} object correspond to the
  585.          * current iteration count {@code k}.
  586.          */
  587.         void update() {
  588.             final RealVector v = y.mapMultiply(1. / beta);
  589.             y = a.operate(v);
  590.             daxpbypz(-shift, v, -beta / oldb, r1, y);
  591.             final double alpha = v.dotProduct(y);
  592.             /*
  593.              * At this point
  594.              *   v     = P' * v[k],
  595.              *   y     = (A - shift * I) * P' * v[k] - beta[k] * M^(-1) * P' * v[k-1],
  596.              *   alpha = v'[k] * P * (A - shift * I) * P' * v[k]
  597.              *           - beta[k] * v[k]' * P * M^(-1) * P' * v[k-1]
  598.              *         = v'[k] * P * (A - shift * I) * P' * v[k]
  599.              *           - beta[k] * v[k]' * v[k-1]
  600.              *         = alpha[k].
  601.              */
  602.             daxpy(-alpha / beta, r2, y);
  603.             /*
  604.              * At this point
  605.              *   y = (A - shift * I) * P' * v[k] - alpha[k] * M^(-1) * P' * v[k]
  606.              *       - beta[k] * M^(-1) * P' * v[k-1]
  607.              *     = M^(-1) * P' * (P * (A - shift * I) * P' * v[k] -alpha[k] * v[k]
  608.              *       - beta[k] * v[k-1])
  609.              *     = beta[k+1] * M^(-1) * P' * v[k+1],
  610.              * from Paige and Saunders (1975), equation (3.2).
  611.              *
  612.              * WATCH-IT: the two following lines work only because y is no longer
  613.              * updated up to the end of the present iteration, and is
  614.              * reinitialized at the beginning of the next iteration.
  615.              */
  616.             r1 = r2;
  617.             r2 = y;
  618.             if (m != null) {
  619.                 y = m.operate(r2);
  620.             }
  621.             oldb = beta;
  622.             beta = r2.dotProduct(y);
  623.             if (beta < 0.) {
  624.                 throwNPDLOException(m, y);
  625.             }
  626.             beta = JdkMath.sqrt(beta);
  627.             /*
  628.              * At this point
  629.              *   r1 = beta[k] * M^(-1) * P' * v[k],
  630.              *   r2 = beta[k+1] * M^(-1) * P' * v[k+1],
  631.              *   y  = beta[k+1] * P' * v[k+1],
  632.              *   oldb = beta[k],
  633.              *   beta = beta[k+1].
  634.              */
  635.             tnorm += alpha * alpha + oldb * oldb + beta * beta;
  636.             /*
  637.              * Compute the next plane rotation for Q. See Paige and Saunders
  638.              * (1975), equation (5.6), with
  639.              *   gamma = gamma[k-1],
  640.              *   c     = c[k-1],
  641.              *   s     = s[k-1].
  642.              */
  643.             final double gamma = JdkMath.sqrt(gbar * gbar + oldb * oldb);
  644.             final double c = gbar / gamma;
  645.             final double s = oldb / gamma;
  646.             /*
  647.              * The relations
  648.              *   gbar[k] = s[k-1] * (-c[k-2] * beta[k]) - c[k-1] * alpha[k]
  649.              *           = s[k-1] * dbar[k] - c[k-1] * alpha[k],
  650.              *   delta[k] = c[k-1] * dbar[k] + s[k-1] * alpha[k],
  651.              * are not stated in Paige and Saunders (1975), but can be retrieved
  652.              * by expanding the (k, k-1) and (k, k) coefficients of the matrix in
  653.              * equation (5.5).
  654.              */
  655.             final double deltak = c * dbar + s * alpha;
  656.             gbar = s * dbar - c * alpha;
  657.             final double eps = s * beta;
  658.             dbar = -c * beta;
  659.             final double zeta = gammaZeta / gamma;
  660.             /*
  661.              * At this point
  662.              *   gbar   = gbar[k]
  663.              *   deltak = delta[k]
  664.              *   eps    = eps[k+1]
  665.              *   dbar   = dbar[k+1]
  666.              *   zeta   = zeta[k-1]
  667.              */
  668.             final double zetaC = zeta * c;
  669.             final double zetaS = zeta * s;
  670.             final int n = xL.getDimension();
  671.             for (int i = 0; i < n; i++) {
  672.                 final double xi = xL.getEntry(i);
  673.                 final double vi = v.getEntry(i);
  674.                 final double wi = wbar.getEntry(i);
  675.                 xL.setEntry(i, xi + wi * zetaC + vi * zetaS);
  676.                 wbar.setEntry(i, wi * s - vi * c);
  677.             }
  678.             /*
  679.              * At this point
  680.              *   x = xL[k-1],
  681.              *   ptwbar = P' wbar[k],
  682.              * see Paige and Saunders (1975), equations (5.9) and (5.10).
  683.              */
  684.             bstep += snprod * c * zeta;
  685.             snprod *= s;
  686.             gmax = JdkMath.max(gmax, gamma);
  687.             gmin = JdkMath.min(gmin, gamma);
  688.             ynorm2 += zeta * zeta;
  689.             gammaZeta = minusEpsZeta - deltak * zeta;
  690.             minusEpsZeta = -eps * zeta;
  691.             /*
  692.              * At this point
  693.              *   snprod       = s[1] * ... * s[k-1],
  694.              *   gmax         = max(|alpha[1]|, gamma[1], ..., gamma[k-1]),
  695.              *   gmin         = min(|alpha[1]|, gamma[1], ..., gamma[k-1]),
  696.              *   ynorm2       = zeta[1]^2 + ... + zeta[k-1]^2,
  697.              *   gammaZeta    = gamma[k] * zeta[k],
  698.              *   minusEpsZeta = -eps[k+1] * zeta[k-1].
  699.              * The relation for gammaZeta can be retrieved from Paige and
  700.              * Saunders (1975), equation (5.4a), last line of the vector
  701.              * gbar[k] * zbar[k] = -eps[k] * zeta[k-2] - delta[k] * zeta[k-1].
  702.              */
  703.             updateNorms();
  704.         }

  705.         /**
  706.          * Computes the norms of the residuals, and checks for convergence.
  707.          * Updates {@link #lqnorm} and {@link #cgnorm}.
  708.          */
  709.         private void updateNorms() {
  710.             final double anorm = JdkMath.sqrt(tnorm);
  711.             final double ynorm = JdkMath.sqrt(ynorm2);
  712.             final double epsa = anorm * MACH_PREC;
  713.             final double epsx = anorm * ynorm * MACH_PREC;
  714.             final double epsr = anorm * ynorm * delta;
  715.             final double diag = gbar == 0. ? epsa : gbar;
  716.             lqnorm = JdkMath.sqrt(gammaZeta * gammaZeta +
  717.                                    minusEpsZeta * minusEpsZeta);
  718.             final double qrnorm = snprod * beta1;
  719.             cgnorm = qrnorm * beta / JdkMath.abs(diag);

  720.             /*
  721.              * Estimate cond(A). In this version we look at the diagonals of L
  722.              * in the factorization of the tridiagonal matrix, T = L * Q.
  723.              * Sometimes, T[k] can be misleadingly ill-conditioned when T[k+1]
  724.              * is not, so we must be careful not to overestimate acond.
  725.              */
  726.             final double acond;
  727.             if (lqnorm <= cgnorm) {
  728.                 acond = gmax / gmin;
  729.             } else {
  730.                 acond = gmax / JdkMath.min(gmin, JdkMath.abs(diag));
  731.             }
  732.             if (acond * MACH_PREC >= 0.1) {
  733.                 throw new IllConditionedOperatorException(acond);
  734.             }
  735.             if (beta1 <= epsx) {
  736.                 /*
  737.                  * x has converged to an eigenvector of A corresponding to the
  738.                  * eigenvalue shift.
  739.                  */
  740.                 throw new SingularOperatorException();
  741.             }
  742.             rnorm = JdkMath.min(cgnorm, lqnorm);
  743.             hasConverged = cgnorm <= epsx || cgnorm <= epsr;
  744.         }

  745.         /**
  746.          * Returns {@code true} if the default stopping criterion is fulfilled.
  747.          *
  748.          * @return {@code true} if convergence of the iterations has occurred
  749.          */
  750.         boolean hasConverged() {
  751.             return hasConverged;
  752.         }

  753.         /**
  754.          * Returns {@code true} if the right-hand side vector is zero exactly.
  755.          *
  756.          * @return the boolean value of {@code b == 0}
  757.          */
  758.         boolean bEqualsNullVector() {
  759.             return bIsNull;
  760.         }

  761.         /**
  762.          * Returns {@code true} if {@code beta} is essentially zero. This method
  763.          * is used to check for early stop of the iterations.
  764.          *
  765.          * @return {@code true} if {@code beta < }{@link #MACH_PREC}
  766.          */
  767.         boolean betaEqualsZero() {
  768.             return beta < MACH_PREC;
  769.         }

  770.         /**
  771.          * Returns the norm of the updated, preconditioned residual.
  772.          *
  773.          * @return the norm of the residual, ||P * r||
  774.          */
  775.         double getNormOfResidual() {
  776.             return rnorm;
  777.         }
  778.     }

  779.     /** Key for the exception context. */
  780.     private static final String OPERATOR = "operator";

  781.     /** Key for the exception context. */
  782.     private static final String THRESHOLD = "threshold";

  783.     /** Key for the exception context. */
  784.     private static final String VECTOR = "vector";

  785.     /** Key for the exception context. */
  786.     private static final String VECTOR1 = "vector1";

  787.     /** Key for the exception context. */
  788.     private static final String VECTOR2 = "vector2";

  789.     /** {@code true} if symmetry of matrix and conditioner must be checked. */
  790.     private final boolean check;

  791.     /**
  792.      * The value of the custom tolerance &delta; for the default stopping
  793.      * criterion.
  794.      */
  795.     private final double delta;

  796.     /**
  797.      * Creates a new instance of this class, with <a href="#stopcrit">default
  798.      * stopping criterion</a>. Note that setting {@code check} to {@code true}
  799.      * entails an extra matrix-vector product in the initial phase.
  800.      *
  801.      * @param maxIterations the maximum number of iterations
  802.      * @param delta the &delta; parameter for the default stopping criterion
  803.      * @param check {@code true} if self-adjointedness of both matrix and
  804.      * preconditioner should be checked
  805.      */
  806.     public SymmLQ(final int maxIterations, final double delta,
  807.                   final boolean check) {
  808.         super(maxIterations);
  809.         this.delta = delta;
  810.         this.check = check;
  811.     }

  812.     /**
  813.      * Creates a new instance of this class, with <a href="#stopcrit">default
  814.      * stopping criterion</a> and custom iteration manager. Note that setting
  815.      * {@code check} to {@code true} entails an extra matrix-vector product in
  816.      * the initial phase.
  817.      *
  818.      * @param manager the custom iteration manager
  819.      * @param delta the &delta; parameter for the default stopping criterion
  820.      * @param check {@code true} if self-adjointedness of both matrix and
  821.      * preconditioner should be checked
  822.      */
  823.     public SymmLQ(final IterationManager manager, final double delta,
  824.                   final boolean check) {
  825.         super(manager);
  826.         this.delta = delta;
  827.         this.check = check;
  828.     }

  829.     /**
  830.      * Returns {@code true} if symmetry of the matrix, and symmetry as well as
  831.      * positive definiteness of the preconditioner should be checked.
  832.      *
  833.      * @return {@code true} if the tests are to be performed
  834.      */
  835.     public final boolean getCheck() {
  836.         return check;
  837.     }

  838.     /**
  839.      * {@inheritDoc}
  840.      *
  841.      * @throws NonSelfAdjointOperatorException if {@link #getCheck()} is
  842.      * {@code true}, and {@code a} or {@code m} is not self-adjoint
  843.      * @throws NonPositiveDefiniteOperatorException if {@code m} is not
  844.      * positive definite
  845.      * @throws IllConditionedOperatorException if {@code a} is ill-conditioned
  846.      */
  847.     @Override
  848.     public RealVector solve(final RealLinearOperator a,
  849.         final RealLinearOperator m, final RealVector b) throws
  850.         NullArgumentException, NonSquareOperatorException,
  851.         DimensionMismatchException, MaxCountExceededException,
  852.         NonSelfAdjointOperatorException, NonPositiveDefiniteOperatorException,
  853.         IllConditionedOperatorException {
  854.         NullArgumentException.check(a);
  855.         final RealVector x = new ArrayRealVector(a.getColumnDimension());
  856.         return solveInPlace(a, m, b, x, false, 0.);
  857.     }

  858.     /**
  859.      * Returns an estimate of the solution to the linear system (A - shift
  860.      * &middot; I) &middot; x = b.
  861.      * <p>
  862.      * If the solution x is expected to contain a large multiple of {@code b}
  863.      * (as in Rayleigh-quotient iteration), then better precision may be
  864.      * achieved with {@code goodb} set to {@code true}; this however requires an
  865.      * extra call to the preconditioner.
  866.      * </p>
  867.      * <p>
  868.      * {@code shift} should be zero if the system A &middot; x = b is to be
  869.      * solved. Otherwise, it could be an approximation to an eigenvalue of A,
  870.      * such as the Rayleigh quotient b<sup>T</sup> &middot; A &middot; b /
  871.      * (b<sup>T</sup> &middot; b) corresponding to the vector b. If b is
  872.      * sufficiently like an eigenvector corresponding to an eigenvalue near
  873.      * shift, then the computed x may have very large components. When
  874.      * normalized, x may be closer to an eigenvector than b.
  875.      * </p>
  876.      *
  877.      * @param a the linear operator A of the system
  878.      * @param m the preconditioner, M (can be {@code null})
  879.      * @param b the right-hand side vector
  880.      * @param goodb usually {@code false}, except if {@code x} is expected to
  881.      * contain a large multiple of {@code b}
  882.      * @param shift the amount to be subtracted to all diagonal elements of A
  883.      * @return a reference to {@code x} (shallow copy)
  884.      * @throws NullArgumentException if one of the parameters is {@code null}
  885.      * @throws NonSquareOperatorException if {@code a} or {@code m} is not square
  886.      * @throws DimensionMismatchException if {@code m} or {@code b} have dimensions
  887.      * inconsistent with {@code a}
  888.      * @throws MaxCountExceededException at exhaustion of the iteration count,
  889.      * unless a custom
  890.      * {@link org.apache.commons.math4.legacy.core.IntegerSequence.Incrementor.MaxCountExceededCallback callback}
  891.      * has been set at construction of the {@link IterationManager}
  892.      * @throws NonSelfAdjointOperatorException if {@link #getCheck()} is
  893.      * {@code true}, and {@code a} or {@code m} is not self-adjoint
  894.      * @throws NonPositiveDefiniteOperatorException if {@code m} is not
  895.      * positive definite
  896.      * @throws IllConditionedOperatorException if {@code a} is ill-conditioned
  897.      */
  898.     public RealVector solve(final RealLinearOperator a,
  899.         final RealLinearOperator m, final RealVector b, final boolean goodb,
  900.         final double shift) throws NullArgumentException,
  901.         NonSquareOperatorException, DimensionMismatchException,
  902.         MaxCountExceededException, NonSelfAdjointOperatorException,
  903.         NonPositiveDefiniteOperatorException, IllConditionedOperatorException {
  904.         NullArgumentException.check(a);
  905.         final RealVector x = new ArrayRealVector(a.getColumnDimension());
  906.         return solveInPlace(a, m, b, x, goodb, shift);
  907.     }

  908.     /**
  909.      * {@inheritDoc}
  910.      *
  911.      * @param x not meaningful in this implementation; should not be considered
  912.      * as an initial guess (<a href="#initguess">more</a>)
  913.      * @throws NonSelfAdjointOperatorException if {@link #getCheck()} is
  914.      * {@code true}, and {@code a} or {@code m} is not self-adjoint
  915.      * @throws NonPositiveDefiniteOperatorException if {@code m} is not positive
  916.      * definite
  917.      * @throws IllConditionedOperatorException if {@code a} is ill-conditioned
  918.      */
  919.     @Override
  920.     public RealVector solve(final RealLinearOperator a,
  921.         final RealLinearOperator m, final RealVector b, final RealVector x)
  922.         throws NullArgumentException, NonSquareOperatorException,
  923.         DimensionMismatchException, NonSelfAdjointOperatorException,
  924.         NonPositiveDefiniteOperatorException, IllConditionedOperatorException,
  925.         MaxCountExceededException {
  926.         NullArgumentException.check(x);
  927.         return solveInPlace(a, m, b, x.copy(), false, 0.);
  928.     }

  929.     /**
  930.      * {@inheritDoc}
  931.      *
  932.      * @throws NonSelfAdjointOperatorException if {@link #getCheck()} is
  933.      * {@code true}, and {@code a} is not self-adjoint
  934.      * @throws IllConditionedOperatorException if {@code a} is ill-conditioned
  935.      */
  936.     @Override
  937.     public RealVector solve(final RealLinearOperator a, final RealVector b)
  938.         throws NullArgumentException, NonSquareOperatorException,
  939.         DimensionMismatchException, NonSelfAdjointOperatorException,
  940.         IllConditionedOperatorException, MaxCountExceededException {
  941.         NullArgumentException.check(a);
  942.         final RealVector x = new ArrayRealVector(a.getColumnDimension());
  943.         x.set(0.);
  944.         return solveInPlace(a, null, b, x, false, 0.);
  945.     }

  946.     /**
  947.      * Returns the solution to the system (A - shift &middot; I) &middot; x = b.
  948.      * <p>
  949.      * If the solution x is expected to contain a large multiple of {@code b}
  950.      * (as in Rayleigh-quotient iteration), then better precision may be
  951.      * achieved with {@code goodb} set to {@code true}.
  952.      * </p>
  953.      * <p>
  954.      * {@code shift} should be zero if the system A &middot; x = b is to be
  955.      * solved. Otherwise, it could be an approximation to an eigenvalue of A,
  956.      * such as the Rayleigh quotient b<sup>T</sup> &middot; A &middot; b /
  957.      * (b<sup>T</sup> &middot; b) corresponding to the vector b. If b is
  958.      * sufficiently like an eigenvector corresponding to an eigenvalue near
  959.      * shift, then the computed x may have very large components. When
  960.      * normalized, x may be closer to an eigenvector than b.
  961.      * </p>
  962.      *
  963.      * @param a the linear operator A of the system
  964.      * @param b the right-hand side vector
  965.      * @param goodb usually {@code false}, except if {@code x} is expected to
  966.      * contain a large multiple of {@code b}
  967.      * @param shift the amount to be subtracted to all diagonal elements of A
  968.      * @return a reference to {@code x}
  969.      * @throws NullArgumentException if one of the parameters is {@code null}
  970.      * @throws NonSquareOperatorException if {@code a} is not square
  971.      * @throws DimensionMismatchException if {@code b} has dimensions
  972.      * inconsistent with {@code a}
  973.      * @throws MaxCountExceededException at exhaustion of the iteration count,
  974.      * unless a custom
  975.      * {@link org.apache.commons.math4.legacy.core.IntegerSequence.Incrementor.MaxCountExceededCallback callback}
  976.      * has been set at construction of the {@link IterationManager}
  977.      * @throws NonSelfAdjointOperatorException if {@link #getCheck()} is
  978.      * {@code true}, and {@code a} is not self-adjoint
  979.      * @throws IllConditionedOperatorException if {@code a} is ill-conditioned
  980.      */
  981.     public RealVector solve(final RealLinearOperator a, final RealVector b,
  982.         final boolean goodb, final double shift) throws NullArgumentException,
  983.         NonSquareOperatorException, DimensionMismatchException,
  984.         NonSelfAdjointOperatorException, IllConditionedOperatorException,
  985.         MaxCountExceededException {
  986.         NullArgumentException.check(a);
  987.         final RealVector x = new ArrayRealVector(a.getColumnDimension());
  988.         return solveInPlace(a, null, b, x, goodb, shift);
  989.     }

  990.     /**
  991.      * {@inheritDoc}
  992.      *
  993.      * @param x not meaningful in this implementation; should not be considered
  994.      * as an initial guess (<a href="#initguess">more</a>)
  995.      * @throws NonSelfAdjointOperatorException if {@link #getCheck()} is
  996.      * {@code true}, and {@code a} is not self-adjoint
  997.      * @throws IllConditionedOperatorException if {@code a} is ill-conditioned
  998.      */
  999.     @Override
  1000.     public RealVector solve(final RealLinearOperator a, final RealVector b,
  1001.         final RealVector x) throws NullArgumentException,
  1002.         NonSquareOperatorException, DimensionMismatchException,
  1003.         NonSelfAdjointOperatorException, IllConditionedOperatorException,
  1004.         MaxCountExceededException {
  1005.         NullArgumentException.check(x);
  1006.         return solveInPlace(a, null, b, x.copy(), false, 0.);
  1007.     }

  1008.     /**
  1009.      * {@inheritDoc}
  1010.      *
  1011.      * @param x the vector to be updated with the solution; {@code x} should
  1012.      * not be considered as an initial guess (<a href="#initguess">more</a>)
  1013.      * @throws NonSelfAdjointOperatorException if {@link #getCheck()} is
  1014.      * {@code true}, and {@code a} or {@code m} is not self-adjoint
  1015.      * @throws NonPositiveDefiniteOperatorException if {@code m} is not
  1016.      * positive definite
  1017.      * @throws IllConditionedOperatorException if {@code a} is ill-conditioned
  1018.      */
  1019.     @Override
  1020.     public RealVector solveInPlace(final RealLinearOperator a,
  1021.         final RealLinearOperator m, final RealVector b, final RealVector x)
  1022.         throws NullArgumentException, NonSquareOperatorException,
  1023.         DimensionMismatchException, NonSelfAdjointOperatorException,
  1024.         NonPositiveDefiniteOperatorException, IllConditionedOperatorException,
  1025.         MaxCountExceededException {
  1026.         return solveInPlace(a, m, b, x, false, 0.);
  1027.     }

  1028.     /**
  1029.      * Returns an estimate of the solution to the linear system (A - shift
  1030.      * &middot; I) &middot; x = b. The solution is computed in-place.
  1031.      * <p>
  1032.      * If the solution x is expected to contain a large multiple of {@code b}
  1033.      * (as in Rayleigh-quotient iteration), then better precision may be
  1034.      * achieved with {@code goodb} set to {@code true}; this however requires an
  1035.      * extra call to the preconditioner.
  1036.      * </p>
  1037.      * <p>
  1038.      * {@code shift} should be zero if the system A &middot; x = b is to be
  1039.      * solved. Otherwise, it could be an approximation to an eigenvalue of A,
  1040.      * such as the Rayleigh quotient b<sup>T</sup> &middot; A &middot; b /
  1041.      * (b<sup>T</sup> &middot; b) corresponding to the vector b. If b is
  1042.      * sufficiently like an eigenvector corresponding to an eigenvalue near
  1043.      * shift, then the computed x may have very large components. When
  1044.      * normalized, x may be closer to an eigenvector than b.
  1045.      * </p>
  1046.      *
  1047.      * @param a the linear operator A of the system
  1048.      * @param m the preconditioner, M (can be {@code null})
  1049.      * @param b the right-hand side vector
  1050.      * @param x the vector to be updated with the solution; {@code x} should
  1051.      * not be considered as an initial guess (<a href="#initguess">more</a>)
  1052.      * @param goodb usually {@code false}, except if {@code x} is expected to
  1053.      * contain a large multiple of {@code b}
  1054.      * @param shift the amount to be subtracted to all diagonal elements of A
  1055.      * @return a reference to {@code x} (shallow copy).
  1056.      * @throws NullArgumentException if one of the parameters is {@code null}
  1057.      * @throws NonSquareOperatorException if {@code a} or {@code m} is not square
  1058.      * @throws DimensionMismatchException if {@code m}, {@code b} or {@code x}
  1059.      * have dimensions inconsistent with {@code a}.
  1060.      * @throws MaxCountExceededException at exhaustion of the iteration count,
  1061.      * unless a custom
  1062.      * {@link org.apache.commons.math4.legacy.core.IntegerSequence.Incrementor.MaxCountExceededCallback callback}
  1063.      * has been set at construction of the {@link IterationManager}
  1064.      * @throws NonSelfAdjointOperatorException if {@link #getCheck()} is
  1065.      * {@code true}, and {@code a} or {@code m} is not self-adjoint
  1066.      * @throws NonPositiveDefiniteOperatorException if {@code m} is not positive
  1067.      * definite
  1068.      * @throws IllConditionedOperatorException if {@code a} is ill-conditioned
  1069.      */
  1070.     public RealVector solveInPlace(final RealLinearOperator a,
  1071.         final RealLinearOperator m, final RealVector b,
  1072.         final RealVector x, final boolean goodb, final double shift)
  1073.         throws NullArgumentException, NonSquareOperatorException,
  1074.         DimensionMismatchException, NonSelfAdjointOperatorException,
  1075.         NonPositiveDefiniteOperatorException, IllConditionedOperatorException,
  1076.         MaxCountExceededException {
  1077.         checkParameters(a, m, b, x);

  1078.         final IterationManager manager = getIterationManager();
  1079.         /* Initialization counts as an iteration. */
  1080.         manager.resetIterationCount();
  1081.         manager.incrementIterationCount();

  1082.         final State state;
  1083.         state = new State(a, m, b, goodb, shift, delta, check);
  1084.         state.init();
  1085.         state.refineSolution(x);
  1086.         IterativeLinearSolverEvent event;
  1087.         event = new DefaultIterativeLinearSolverEvent(this,
  1088.                                                       manager.getIterations(),
  1089.                                                       x,
  1090.                                                       b,
  1091.                                                       state.getNormOfResidual());
  1092.         if (state.bEqualsNullVector()) {
  1093.             /* If b = 0 exactly, stop with x = 0. */
  1094.             manager.fireTerminationEvent(event);
  1095.             return x;
  1096.         }
  1097.         /* Cause termination if beta is essentially zero. */
  1098.         final boolean earlyStop;
  1099.         earlyStop = state.betaEqualsZero() || state.hasConverged();
  1100.         manager.fireInitializationEvent(event);
  1101.         if (!earlyStop) {
  1102.             do {
  1103.                 manager.incrementIterationCount();
  1104.                 event = new DefaultIterativeLinearSolverEvent(this,
  1105.                                                               manager.getIterations(),
  1106.                                                               x,
  1107.                                                               b,
  1108.                                                               state.getNormOfResidual());
  1109.                 manager.fireIterationStartedEvent(event);
  1110.                 state.update();
  1111.                 state.refineSolution(x);
  1112.                 event = new DefaultIterativeLinearSolverEvent(this,
  1113.                                                               manager.getIterations(),
  1114.                                                               x,
  1115.                                                               b,
  1116.                                                               state.getNormOfResidual());
  1117.                 manager.fireIterationPerformedEvent(event);
  1118.             } while (!state.hasConverged());
  1119.         }
  1120.         event = new DefaultIterativeLinearSolverEvent(this,
  1121.                                                       manager.getIterations(),
  1122.                                                       x,
  1123.                                                       b,
  1124.                                                       state.getNormOfResidual());
  1125.         manager.fireTerminationEvent(event);
  1126.         return x;
  1127.     }

  1128.     /**
  1129.      * {@inheritDoc}
  1130.      *
  1131.      * @param x the vector to be updated with the solution; {@code x} should
  1132.      * not be considered as an initial guess (<a href="#initguess">more</a>)
  1133.      * @throws NonSelfAdjointOperatorException if {@link #getCheck()} is
  1134.      * {@code true}, and {@code a} is not self-adjoint
  1135.      * @throws IllConditionedOperatorException if {@code a} is ill-conditioned
  1136.      */
  1137.     @Override
  1138.     public RealVector solveInPlace(final RealLinearOperator a,
  1139.         final RealVector b, final RealVector x) throws NullArgumentException,
  1140.         NonSquareOperatorException, DimensionMismatchException,
  1141.         NonSelfAdjointOperatorException, IllConditionedOperatorException,
  1142.         MaxCountExceededException {
  1143.         return solveInPlace(a, null, b, x, false, 0.);
  1144.     }
  1145. }