In o.a.c.m3.SymmLQ.State

- the current solution is now refined at each iteration, as the overhead is negligible
  - SymmLQ.State.xL is no longer a reference to the parameter x passed to its constructor. This way, all transparent updates of the vector x are removed.
  - SymmLQ.State.moveToCG(RealVector) is renamed SymmLQ.State.refineSolution(RealVector).
In o.a.c.m3.SymmLQ.solveInPlace()
  - SymmLQ.State.init() is now called explicitly
  - a new DefaultIterativeLinearSolverEvent is created each time it is needed (no "clever" object reuse)
  - SymmLQ.State.refineSolution(RealVector) is called explicitly
See MATH-761.

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1304574 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Sebastien Brisard 2012-03-23 19:51:12 +00:00
parent 20fa2579ec
commit 5762e65833
1 changed files with 34 additions and 88 deletions

View File

@ -360,8 +360,6 @@ public class SymmLQ
* @param minv the inverse of the preconditioner, M<sup>-1</sup>
* (can be {@code null})
* @param b the right-hand side vector
* @param x the vector to be updated with the solution; {@code x} should
* not be considered as an initial guess (<a href="#initguess">more</a>)
* @param goodb usually {@code false}, except if {@code x} is expected
* to contain a large multiple of {@code b}
* @param shift the amount to be subtracted to all diagonal elements of
@ -373,7 +371,6 @@ public class SymmLQ
public State(final RealLinearOperator a,
final RealLinearOperator minv,
final RealVector b,
final RealVector x,
final boolean goodb,
final double shift,
final double delta,
@ -381,14 +378,13 @@ public class SymmLQ
this.a = a;
this.minv = minv;
this.b = b;
this.xL = x;
this.xL = new ArrayRealVector(b.getDimension());
this.goodb = goodb;
this.shift = shift;
this.minvb = minv == null ? b : minv.operate(b);
this.hasConverged = false;
this.check = check;
this.delta = delta;
init();
}
/**
@ -483,19 +479,19 @@ public class SymmLQ
* the convergence tests involve only cgnorm, so we're unlikely to stop
* at an LQ point, except if the iteration limit interferes.
*
* @param xC the vector to be updated with the refined value of xL
* @param x the vector to be updated with the refined value of xL
*/
void moveToCG(final RealVector xC) {
void refineSolution(final RealVector x) {
final int n = this.xL.getDimension();
if (lqnorm < cgnorm) {
if (!goodb) {
xC.setSubVector(0, this.xL);
x.setSubVector(0, this.xL);
} else {
final double step = bstep / beta1;
for (int i = 0; i < n; i++) {
final double bi = minvb.getEntry(i);
final double xi = this.xL.getEntry(i);
xC.setEntry(i, xi + step * bi);
x.setEntry(i, xi + step * bi);
}
}
} else {
@ -508,14 +504,14 @@ public class SymmLQ
for (int i = 0; i < n; i++) {
final double xi = this.xL.getEntry(i);
final double wi = wbar.getEntry(i);
xC.setEntry(i, xi + zbar * wi);
x.setEntry(i, xi + zbar * wi);
}
} else {
for (int i = 0; i < n; i++) {
final double xi = this.xL.getEntry(i);
final double wi = wbar.getEntry(i);
final double bi = minvb.getEntry(i);
xC.setEntry(i, xi + zbar * wi + step * bi);
x.setEntry(i, xi + zbar * wi + step * bi);
}
}
}
@ -526,7 +522,7 @@ public class SymmLQ
* value of the state variables of {@code this} object correspond to k =
* 1.
*/
private void init() {
void init() {
this.xL.set(0.);
/*
* Set up y for the first Lanczos vector. y and beta1 will be zero
@ -808,24 +804,6 @@ public class SymmLQ
return beta < MACH_PREC;
}
/**
* Returns the right-hand side vector.
*
* @return the right-hand side vector, b
*/
RealVector getRightHandSideVector() {
return b;
}
/**
* Returns the current estimate of the solution (LQ point).
*
* @return the solution, xL
*/
RealVector getSolution() {
return xL;
}
/**
* Returns the norm of the updated, preconditioned residual.
*
@ -836,57 +814,6 @@ public class SymmLQ
}
}
/**
* The type of all events fired by this implementation of the SYMMLQ method.
*
* @version $Id$
*/
private static class SymmLQEvent extends IterativeLinearSolverEvent {
/** Identifier. */
private static final long serialVersionUID = 2012012801L;
/** A reference to the state of this solver. */
private final transient State state;
/**
* Creates a new instance of this class.
*
* @param source the iterative algorithm on which the event initially
* occurred
* @param state the state of this solver at the time of creation
*/
public SymmLQEvent(final SymmLQ source, final State state) {
super(source, source.getIterationManager().getIterations());
this.state = state;
}
/** {@inheritDoc} */
@Override
public int getIterations() {
return ((SymmLQ) getSource()).getIterationManager().getIterations();
}
/** {@inheritDoc} */
@Override
public double getNormOfResidual() {
return state.getNormOfResidual();
}
/** {@inheritDoc} */
@Override
public RealVector getRightHandSideVector() {
return RealVector.unmodifiableRealVector(state.getRightHandSideVector());
}
/** {@inheritDoc} */
@Override
public RealVector getSolution() {
final RealVector x = state.getSolution().copy();
state.moveToCG(x);
return x;
}
}
/** Key for the exception context. */
private static final String OPERATOR = "operator";
@ -1213,12 +1140,16 @@ public class SymmLQ
manager.resetIterationCount();
manager.incrementIterationCount();
final State state = new State(a, minv, b, x.copy(), goodb, shift, delta, check);
/*
* There is no need to create a new SymmLQEvent each time the state is
* updated, as SymmLQEvent keeps a reference to the current state.
*/
final IterativeLinearSolverEvent event = new SymmLQEvent(this, state);
final State state;
state = new State(a, minv, b, goodb, shift, delta, check);
state.init();
state.refineSolution(x);
IterativeLinearSolverEvent event;
event = new DefaultIterativeLinearSolverEvent(this,
manager.getIterations(),
x,
b,
state.getNormOfResidual());
if (state.bEqualsNullVector()) {
/* If b = 0 exactly, stop with x = 0. */
manager.fireTerminationEvent(event);
@ -1231,12 +1162,27 @@ public class SymmLQ
if (!earlyStop) {
do {
manager.incrementIterationCount();
event = new DefaultIterativeLinearSolverEvent(this,
manager.getIterations(),
x,
b,
state.getNormOfResidual());
manager.fireIterationStartedEvent(event);
state.update();
state.refineSolution(x);
event = new DefaultIterativeLinearSolverEvent(this,
manager.getIterations(),
x,
b,
state.getNormOfResidual());
manager.fireIterationPerformedEvent(event);
} while (!state.hasConverged());
}
state.moveToCG(x);
event = new DefaultIterativeLinearSolverEvent(this,
manager.getIterations(),
x,
b,
state.getNormOfResidual());
manager.fireTerminationEvent(event);
return x;
}