Exemplo n.º 1
0
 /**
  * Test if x is an approximate real root.
  *
  * @param x approximate real root.
  * @param f univariate polynomial, non-zero.
  * @param fp univariate polynomial, non-zero, deriviative of f.
  * @param eps requested interval length.
  * @return true if x is a decimal approximation of a real v with f(v) = 0 with |d-v| < eps,
  *     else false.
  */
 public boolean isApproximateRoot(
     BigDecimal x, GenPolynomial<BigDecimal> f, GenPolynomial<BigDecimal> fp, BigDecimal eps) {
   if (x == null) {
     throw new IllegalArgumentException("null root not allowed");
   }
   if (f == null || f.isZERO() || f.isConstant() || eps == null) {
     return true;
   }
   BigDecimal dc = BigDecimal.ONE; // only for clarity
   // f(x)
   BigDecimal fx = PolyUtil.<BigDecimal>evaluateMain(dc, f, x);
   // System.out.println("fx    = " + fx);
   if (fx.isZERO()) {
     return true;
   }
   // f'(x)
   BigDecimal fpx = PolyUtil.<BigDecimal>evaluateMain(dc, fp, x); // f'(d)
   // System.out.println("fpx   = " + fpx);
   if (fpx.isZERO()) {
     return false;
   }
   BigDecimal d = fx.divide(fpx);
   if (d.isZERO()) {
     return true;
   }
   if (d.abs().compareTo(eps) <= 0) {
     return true;
   }
   System.out.println("x     = " + x);
   System.out.println("d     = " + d);
   return false;
 }
Exemplo n.º 2
0
  /**
   * Approximate real root.
   *
   * @param iv real root isolating interval with f(left) * f(right) &lt; 0.
   * @param f univariate polynomial, non-zero.
   * @param eps requested interval length.
   * @return a decimal approximation d such that |d-v| &lt; eps, for f(v) = 0, v real.
   */
  public BigDecimal approximateRoot(Interval<C> iv, GenPolynomial<C> f, C eps)
      throws NoConvergenceException {
    if (iv == null) {
      throw new IllegalArgumentException("null interval not allowed");
    }
    BigDecimal d = iv.toDecimal();
    if (f == null || f.isZERO() || f.isConstant() || eps == null) {
      return d;
    }
    if (iv.length().compareTo(eps) < 0) {
      return d;
    }
    BigDecimal left = new BigDecimal(iv.left.getRational());
    BigDecimal right = new BigDecimal(iv.right.getRational());
    BigDecimal e = new BigDecimal(eps.getRational());
    BigDecimal q = new BigDecimal("0.25");
    // System.out.println("left  = " + left);
    // System.out.println("right = " + right);
    e = e.multiply(d); // relative error
    // System.out.println("e     = " + e);
    BigDecimal dc = BigDecimal.ONE;
    // polynomials with decimal coefficients
    GenPolynomialRing<BigDecimal> dfac = new GenPolynomialRing<BigDecimal>(dc, f.ring);
    GenPolynomial<BigDecimal> df = PolyUtil.<C>decimalFromRational(dfac, f);
    GenPolynomial<C> fp = PolyUtil.<C>baseDeriviative(f);
    GenPolynomial<BigDecimal> dfp = PolyUtil.<C>decimalFromRational(dfac, fp);

    // Newton Raphson iteration: x_{n+1} = x_n - f(x_n)/f'(x_n)
    int i = 0;
    final int MITER = 50;
    int dir = 0;
    while (i++ < MITER) {
      BigDecimal fx = PolyUtil.<BigDecimal>evaluateMain(dc, df, d); // f(d)
      if (fx.isZERO()) {
        return d;
      }
      BigDecimal fpx = PolyUtil.<BigDecimal>evaluateMain(dc, dfp, d); // f'(d)
      if (fpx.isZERO()) {
        throw new NoConvergenceException("zero deriviative should not happen");
      }
      BigDecimal x = fx.divide(fpx);
      BigDecimal dx = d.subtract(x);
      // System.out.println("dx = " + dx);
      if (d.subtract(dx).abs().compareTo(e) <= 0) {
        return dx;
      }
      while (dx.compareTo(left) < 0 || dx.compareTo(right) > 0) { // dx < left: dx - left < 0
        // dx > right: dx - right > 0
        // System.out.println("trying to leave interval");
        if (i++ > MITER) { // dx > right: dx - right > 0
          throw new NoConvergenceException("no convergence after " + i + " steps");
        }
        if (i > MITER / 2 && dir == 0) {
          BigDecimal sd = new BigDecimal(iv.randomPoint().getRational());
          d = sd;
          x = sd.getZERO();
          logger.info("trying new random starting point " + d);
          i = 0;
          dir = 1;
        }
        if (i > MITER / 2 && dir == 1) {
          BigDecimal sd = new BigDecimal(iv.randomPoint().getRational());
          d = sd;
          x = sd.getZERO();
          logger.info("trying new random starting point " + d);
          // i = 0;
          dir = 2; // end
        }
        x = x.multiply(q); // x * 1/4
        dx = d.subtract(x);
        // System.out.println(" x = " + x);
        // System.out.println("dx = " + dx);
      }
      d = dx;
    }
    throw new NoConvergenceException("no convergence after " + i + " steps");
  }