mirror of
https://github.com/apache/commons-math.git
synced 2025-02-08 19:15:18 +00:00
added a forceSide method to UnivariateRealsolversUtils to allow selecting a bracketing side
even for non-bracketing solvers like Bren or Newton git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1144831 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
208824f3b6
commit
bdd6b2b578
@ -17,11 +17,11 @@
|
|||||||
package org.apache.commons.math.analysis.solvers;
|
package org.apache.commons.math.analysis.solvers;
|
||||||
|
|
||||||
import org.apache.commons.math.analysis.UnivariateRealFunction;
|
import org.apache.commons.math.analysis.UnivariateRealFunction;
|
||||||
import org.apache.commons.math.exception.util.LocalizedFormats;
|
|
||||||
import org.apache.commons.math.exception.NullArgumentException;
|
|
||||||
import org.apache.commons.math.exception.NoBracketingException;
|
import org.apache.commons.math.exception.NoBracketingException;
|
||||||
import org.apache.commons.math.exception.NumberIsTooLargeException;
|
|
||||||
import org.apache.commons.math.exception.NotStrictlyPositiveException;
|
import org.apache.commons.math.exception.NotStrictlyPositiveException;
|
||||||
|
import org.apache.commons.math.exception.NullArgumentException;
|
||||||
|
import org.apache.commons.math.exception.NumberIsTooLargeException;
|
||||||
|
import org.apache.commons.math.exception.util.LocalizedFormats;
|
||||||
import org.apache.commons.math.util.FastMath;
|
import org.apache.commons.math.util.FastMath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -77,6 +77,90 @@ public class UnivariateRealSolverUtils {
|
|||||||
return solver.solve(Integer.MAX_VALUE, function, x0, x1);
|
return solver.solve(Integer.MAX_VALUE, function, x0, x1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Force a root found by a non-bracketing solver to lie on a specified side,
|
||||||
|
* as if the solver was a bracketing one.
|
||||||
|
* @param maxEval maximal number of new evaluations of the function
|
||||||
|
* (evaluations already done for finding the root should have already been subtracted
|
||||||
|
* from this number)
|
||||||
|
* @param f function to solve
|
||||||
|
* @param bracketing bracketing solver to use for shifting the root
|
||||||
|
* @param baseRoot original root found by a previous non-bracketing solver
|
||||||
|
* @param min minimal bound of the search interval
|
||||||
|
* @param max maximal bound of the search interval
|
||||||
|
* @param allowedSolutions the kind of solutions that the root-finding algorithm may
|
||||||
|
* accept as solutions.
|
||||||
|
*/
|
||||||
|
public static double forceSide(final int maxEval, final UnivariateRealFunction f,
|
||||||
|
final BracketedUnivariateRealSolver<UnivariateRealFunction> bracketing,
|
||||||
|
final double baseRoot, final double min, final double max,
|
||||||
|
final AllowedSolutions allowedSolutions) {
|
||||||
|
|
||||||
|
if (allowedSolutions == AllowedSolutions.ANY_SIDE) {
|
||||||
|
// no further bracketing required
|
||||||
|
return baseRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find a very small interval bracketing the root
|
||||||
|
final double step = FastMath.max(bracketing.getAbsoluteAccuracy(),
|
||||||
|
FastMath.abs(baseRoot * bracketing.getRelativeAccuracy()));
|
||||||
|
double xLo = baseRoot - step;
|
||||||
|
double fLo = f.value(xLo);
|
||||||
|
double xHi = baseRoot + step;
|
||||||
|
double fHi = f.value(xHi);
|
||||||
|
int remainingEval = maxEval - 2;
|
||||||
|
while ((remainingEval > 0) && (xLo >= min) && (xHi <= max)) {
|
||||||
|
|
||||||
|
if ((fLo > 0 && fHi < 0) || (fLo < 0 && fHi > 0)) {
|
||||||
|
// compute the root on the selected side
|
||||||
|
return bracketing.solve(remainingEval, f, xLo, xHi, baseRoot, allowedSolutions);
|
||||||
|
}
|
||||||
|
|
||||||
|
// try increasing the interval
|
||||||
|
boolean changeLo = false;
|
||||||
|
boolean changeHi = false;
|
||||||
|
if (fLo < fHi) {
|
||||||
|
// increasing function
|
||||||
|
if (fLo >= 0) {
|
||||||
|
changeLo = true;
|
||||||
|
} else {
|
||||||
|
changeHi = true;
|
||||||
|
}
|
||||||
|
} else if (fLo > fHi) {
|
||||||
|
// decreasing function
|
||||||
|
if (fLo <= 0) {
|
||||||
|
changeLo = true;
|
||||||
|
} else {
|
||||||
|
changeHi = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// unknown variation
|
||||||
|
changeLo = true;
|
||||||
|
changeHi = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the lower bound
|
||||||
|
if (changeLo) {
|
||||||
|
xLo -= step;
|
||||||
|
fLo = f.value(xLo);
|
||||||
|
remainingEval--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the higher bound
|
||||||
|
if (changeHi) {
|
||||||
|
xHi += step;
|
||||||
|
fHi = f.value(xHi);
|
||||||
|
remainingEval--;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NoBracketingException(LocalizedFormats.FAILED_BRACKETING,
|
||||||
|
xLo, xHi, fLo, fHi,
|
||||||
|
maxEval - remainingEval, maxEval, baseRoot,
|
||||||
|
min, max);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method attempts to find two values a and b satisfying <ul>
|
* This method attempts to find two values a and b satisfying <ul>
|
||||||
* <li> <code> lowerBound <= a < initial < b <= upperBound</code> </li>
|
* <li> <code> lowerBound <= a < initial < b <= upperBound</code> </li>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user