예제 #1
0
 public static Double dekker(Function f, double a, double b, double tol, int nMax) {
   double fa = f.getValue(a);
   double fb = f.getValue(b);
   if (fa * fb >= 0.0) {
     System.out.println("Dekker method failed - root is not bracketed.");
     return null;
   }
   double bOld, fbOld;
   double temp;
   int n = 0;
   while (++n <= nMax) {
     if (Math.abs(fa) < Math.abs(fb)) {
       temp = a;
       a = b;
       b = temp;
       temp = fa;
       fa = fb;
       fb = temp;
     }
     bOld = b;
     fbOld = fb;
     if (Math.abs(fb - fa) > Constants.EPSILON) b -= fb * (b - a) / (fb - fa);
     else b = (a + b) / 2;
     fb = f.getValue(b);
     System.out.println(n + ". b = " + b + ", fb = " + fb);
     if ((Math.abs(fb) < Constants.EPSILON) || (Math.abs((b - a) / 2) < tol)) return b;
     if (fa * fb >= 0.0) {
       a = bOld;
       fa = fbOld;
     }
   }
   System.out.println("Dekker method failed - max number of iterations.");
   return b;
 }
예제 #2
0
 /**
  * Root-finding algorithm combining the bisection method, the secant method and inverse quadratic
  * interpolation. It has the reliability of bisection but it can be as quick as some of the less
  * reliable methods. The algorithm tries to use the potentially fast-converging secant method or
  * inverse quadratic interpolation if possible, but it falls back to the more robust bisection
  * method if necessary.
  *
  * @param args
  */
 public static Double brent(Function f, double a, double b, double tol, double delta, int nMax) {
   double fa = f.getValue(a);
   double fb = f.getValue(b);
   double fc = fa;
   if (fa * fb >= 0.0) {
     System.out.println("Brent method failed - root is not bracketed.");
     return null;
   }
   double c = a;
   double d = c;
   boolean mflag = true;
   double temp, s, fs;
   int n = 0;
   while (++n <= nMax) {
     if (Math.abs(fa) < Math.abs(fb)) {
       temp = a;
       a = b;
       b = temp;
       temp = fa;
       fa = fb;
       fb = temp;
     }
     if ((Math.abs(fc - fa) > Constants.EPSILON) && (Math.abs(fc - fb) > Constants.EPSILON))
       s =
           a * fb * fc / ((fa - fb) * (fa - fc))
               + b * fa * fc / ((fb - fa) * (fb - fc))
               + c * fa * fb / ((fc - fa) * (fc - fb));
     else s = b - fb * (b - a) / (fb - fa);
     if (((s <= (3 * a + b) / 4) || s >= b)
         || (mflag && ((Math.abs(s - b) >= Math.abs(b - c) / 2) || (Math.abs(b - c) < delta)))
         || (!mflag && ((Math.abs(s - b) >= Math.abs(c - d) / 2) || (Math.abs(c - d) < delta)))) {
       s = (a + b) / 2;
       mflag = true;
     } else mflag = false;
     fs = f.getValue(s);
     d = c;
     c = b;
     if (fa * fs < 0) {
       b = s;
       fb = fs;
     } else {
       a = s;
       fa = fs;
     }
     if (Math.abs(fa) < Math.abs(fb)) {
       temp = a;
       a = b;
       b = temp;
       temp = fa;
       fa = fb;
       fb = temp;
     }
     System.out.println(n + ". b = " + b + ", fb = " + fb);
     if ((Math.abs(fb) < Constants.EPSILON) || (Math.abs((b - a) / 2) < tol)) return b;
   }
   System.out.println("Brent method failed - max number of iterations.");
   return c;
 }
예제 #3
0
 public static void main(String[] args) {
   double[] c = new double[4];
   c[0] = -2;
   c[1] = -1;
   c[2] = 0;
   c[3] = 1;
   Function f = new Function(c);
   double root = RootFinding.brent(f, 1, 2, 0.000001, 0.00001, 25);
   System.out.println("Root at " + root + " with value " + f.getValue(root));
 }
예제 #4
0
 /**
  * Root-finding algorithm that starts with an initial guess which is reasonably close to the true
  * root, then the function is approximated by its tangent line (which can be computed using the
  * tools of calculus), and one computes the x-intercept of this tangent line (which is easily done
  * with elementary algebra). This x-intercept will typically be a better approximation to the
  * function's root than the original guess, and the method can be iterated.
  */
 public static Double newton(Function f, double x, double x1, double tol, int nMax) {
   Function d = f.getDerivative();
   int n = 0;
   double fx = f.getValue(x);
   double dx;
   while (++n <= nMax) {
     if ((Math.abs(fx) < Constants.EPSILON) || (Math.abs(x1 - x) < tol)) return x;
     dx = fx / d.getValue(x);
     x1 = x;
     x = x - dx;
     fx = f.getValue(x);
   }
   System.out.println("Newton method failed - max number of iterations.");
   return x;
 }
예제 #5
0
 /**
  * Root-finding algorithm that uses a succession of roots of secant lines to better approximate a
  * root of a function f. The secant method can be thought of as a finite difference approximation
  * of Newton's method. However, the method was developed independently of Newton's method, and
  * predated the latter by over 3,000 years.
  */
 public static Double secant(Function f, double x, double x1, double tol, int nMax) {
   int n = 0;
   double x2 = 0;
   double fx1 = f.getValue(x1);
   double fx = f.getValue(x);
   while (++n <= nMax) {
     if ((Math.abs(fx1) < Constants.EPSILON) || (Math.abs(x1 - x) < tol)) return x;
     x2 = x1 - fx1 * (x1 - x) / (fx1 - fx);
     x = x1;
     fx = fx1;
     x1 = x2;
     fx1 = f.getValue(x1);
   }
   System.out.println("Bisection method failed - max number of iterations.");
   return x;
 }
예제 #6
0
 /**
  * Root-finding algorithm that repeatedly bisects an interval and then selects a subinterval in
  * which a root must lie for further processing. It is a very simple and robust method, but it is
  * also relatively slow. Because of this, it is often used to obtain a rough approximation to a
  * solution which is then used as a starting point for more rapidly converging methods The method
  * is also called the interval halving method, the binary search method, or the dichotomy method.
  */
 public static Double bisection(Function f, double a, double b, double tol, int nMax) {
   double fa = f.getValue(a);
   double fb = f.getValue(b);
   double fc;
   if (fa * fb >= 0.0) {
     System.out.println("Bisection method failed - root is not bracketed.");
     return null;
   }
   double signA = Math.signum(fa);
   double c = 0;
   int n = 0;
   while (++n <= nMax) {
     c = (a + b) / 2;
     fc = f.getValue(c);
     System.out.println(n + ". c = " + c + ", fc = " + fc);
     if ((Math.abs(fc) < Constants.EPSILON) || ((b - a) / 2 < tol)) return c;
     if (Math.signum(fc) == signA) a = c;
     else b = c;
   }
   System.out.println("Bisection method failed - max number of iterations.");
   return c;
 }
예제 #7
0
 /**
  * Root-finding algorithm that uses quadratic interpolation to approximate the inverse of f. This
  * algorithm is rarely used on its own, but it is important because it forms part of the popular
  * Brent's method.
  */
 public static Double inverseQuadraticInterpolation(
     Function f, double x, double x1, double x2, double tol, int nMax) {
   int n = 0;
   double x0;
   double fx = f.getValue(x);
   double fx1 = f.getValue(x1);
   double fx2 = f.getValue(x2);
   while (++n <= nMax) {
     if ((Math.abs(fx) < Constants.EPSILON) || (Math.abs(x1 - x) < tol)) return x;
     x0 =
         x2 * fx1 * fx / ((fx2 - fx1) * (fx2 - fx))
             + x1 * fx2 * fx / ((fx1 - fx2) * (fx1 - fx))
             + x * fx2 * fx1 / (((fx - fx2) * (fx - fx1)));
     x2 = x1;
     fx2 = fx1;
     x1 = x;
     fx1 = fx;
     x = x0;
     fx = f.getValue(x);
   }
   System.out.println("Inverse Quadratic Interpolation method failed - max number of iterations.");
   return x;
 }