Ejemplo n.º 1
0
  public double execute(long in1, long in2) throws DMLRuntimeException {
    switch (bFunc) {
      case MAX:
      case CUMMAX:
        return (in1 >= in2 ? in1 : in2);

      case MIN:
      case CUMMIN:
        return (in1 <= in2 ? in1 : in2);

      case MAXINDEX:
        return (in1 >= in2) ? 1 : 0;
      case MININDEX:
        return (in1 <= in2) ? 1 : 0;

      case LOG:
        // if ( in1 <= 0 )
        //	throw new DMLRuntimeException("Builtin.execute(): logarithm can be computed only for
        // non-negative numbers.");
        if (FASTMATH) return (FastMath.log(in1) / FastMath.log(in2));
        else return (Math.log(in1) / Math.log(in2));
      case LOG_NZ:
        if (FASTMATH) return (in1 == 0) ? 0 : (FastMath.log(in1) / FastMath.log(in2));
        else return (in1 == 0) ? 0 : (Math.log(in1) / Math.log(in2));

      default:
        throw new DMLRuntimeException("Builtin.execute(): Unknown operation: " + bFunc);
    }
  }
 /**
  * Compute the logarithm of the PMF for a binomial distribution using the saddle point expansion.
  *
  * @param x the value at which the probability is evaluated.
  * @param n the number of trials.
  * @param p the probability of success.
  * @param q the probability of failure (1 - p).
  * @return log(p(x)).
  */
 static double logBinomialProbability(int x, int n, double p, double q) {
   double ret;
   if (x == 0) {
     if (p < 0.1) {
       ret = -getDeviancePart(n, n * q) - n * p;
     } else {
       ret = n * FastMath.log(q);
     }
   } else if (x == n) {
     if (q < 0.1) {
       ret = -getDeviancePart(n, n * p) - n * q;
     } else {
       ret = n * FastMath.log(p);
     }
   } else {
     ret =
         getStirlingError(n)
             - getStirlingError(x)
             - getStirlingError(n - x)
             - getDeviancePart(x, n * p)
             - getDeviancePart(n - x, n * q);
     double f = (MathUtils.TWO_PI * x * (n - x)) / n;
     ret = -0.5 * FastMath.log(f) + ret;
   }
   return ret;
 }
Ejemplo n.º 3
0
  /**
   * Calculate the probability of a new category being used for the item being sold. See
   * CategoryCountSpread.xlsx
   *
   * @param auctionNumber Count of auctions to submit, including this. Starts from 1.
   * @param logParam
   * @return
   */
  public static boolean useNewAuctionCategory(int auctionNumber, double logParam, double rand) {
    if (auctionNumber < 1 || logParam < 1) throw new IllegalArgumentException();

    if (auctionNumber == 1) return true;

    // log( (x + 1) / x), log-base to be given
    double probNewCat = FastMath.log(1 + (double) 1 / auctionNumber) / FastMath.log(logParam);
    return rand < probNewCat; // new category
  }
Ejemplo n.º 4
0
  public double execute(double in) throws DMLRuntimeException {
    switch (bFunc) {
      case SIN:
        return FASTMATH ? FastMath.sin(in) : Math.sin(in);
      case COS:
        return FASTMATH ? FastMath.cos(in) : Math.cos(in);
      case TAN:
        return FASTMATH ? FastMath.tan(in) : Math.tan(in);
      case ASIN:
        return FASTMATH ? FastMath.asin(in) : Math.asin(in);
      case ACOS:
        return FASTMATH ? FastMath.acos(in) : Math.acos(in);
      case ATAN:
        return Math.atan(in); // faster in Math
      case CEIL:
        return FASTMATH ? FastMath.ceil(in) : Math.ceil(in);
      case FLOOR:
        return FASTMATH ? FastMath.floor(in) : Math.floor(in);
      case LOG:
        return FASTMATH ? FastMath.log(in) : Math.log(in);
      case LOG_NZ:
        return (in == 0) ? 0 : FASTMATH ? FastMath.log(in) : Math.log(in);
      case ABS:
        return Math.abs(in); // no need for FastMath	
      case SIGN:
        return FASTMATH ? FastMath.signum(in) : Math.signum(in);
      case SQRT:
        return Math.sqrt(in); // faster in Math
      case EXP:
        return FASTMATH ? FastMath.exp(in) : Math.exp(in);
      case ROUND:
        return Math.round(in); // no need for FastMath

      case PLOGP:
        if (in == 0.0) return 0.0;
        else if (in < 0) return Double.NaN;
        else return (in * (FASTMATH ? FastMath.log(in) : Math.log(in)));

      case SPROP:
        // sample proportion: P*(1-P)
        return in * (1 - in);

      case SIGMOID:
        // sigmoid: 1/(1+exp(-x))
        return FASTMATH ? 1 / (1 + FastMath.exp(-in)) : 1 / (1 + Math.exp(-in));

      case SELP:
        // select positive: x*(x>0)
        return (in > 0) ? in : 0;

      default:
        throw new DMLRuntimeException("Builtin.execute(): Unknown operation: " + bFunc);
    }
  }
Ejemplo n.º 5
0
 /* (non-Javadoc)
  * @see net.finmath.stochastic.RandomVariableInterface#log()
  */
 public RandomVariable log() {
   if (isDeterministic()) {
     double newValueIfNonStochastic = FastMath.log(valueIfNonStochastic);
     return new RandomVariable(time, newValueIfNonStochastic);
   } else {
     double[] newRealizations = new double[realizations.length];
     for (int i = 0; i < newRealizations.length; i++)
       newRealizations[i] = FastMath.log(realizations[i]);
     return new RandomVariable(time, newRealizations);
   }
 }
Ejemplo n.º 6
0
  /**
   * Returns the regularized beta function I(x, a, b).
   *
   * <p>The implementation of this method is based on:
   *
   * <ul>
   *   <li><a href="http://mathworld.wolfram.com/RegularizedBetaFunction.html">Regularized Beta
   *       Function</a>.
   *   <li><a href="http://functions.wolfram.com/06.21.10.0001.01">Regularized Beta Function</a>.
   * </ul>
   *
   * @param x the value.
   * @param a Parameter {@code a}.
   * @param b Parameter {@code b}.
   * @param epsilon When the absolute value of the nth item in the series is less than epsilon the
   *     approximation ceases to calculate further elements in the series.
   * @param maxIterations Maximum number of "iterations" to complete.
   * @return the regularized beta function I(x, a, b)
   * @throws org.apache.commons.math3.exception.MaxCountExceededException if the algorithm fails to
   *     converge.
   */
  public static double regularizedBeta(
      double x, final double a, final double b, double epsilon, int maxIterations) {
    double ret;

    if (Double.isNaN(x)
        || Double.isNaN(a)
        || Double.isNaN(b)
        || x < 0
        || x > 1
        || a <= 0.0
        || b <= 0.0) {
      ret = Double.NaN;
    } else if (x > (a + 1.0) / (a + b + 2.0)) {
      ret = 1.0 - regularizedBeta(1.0 - x, b, a, epsilon, maxIterations);
    } else {
      ContinuedFraction fraction =
          new ContinuedFraction() {

            @Override
            protected double getB(int n, double x) {
              double ret;
              double m;
              if (n % 2 == 0) { // even
                m = n / 2.0;
                ret = (m * (b - m) * x) / ((a + (2 * m) - 1) * (a + (2 * m)));
              } else {
                m = (n - 1.0) / 2.0;
                ret = -((a + m) * (a + b + m) * x) / ((a + (2 * m)) * (a + (2 * m) + 1.0));
              }
              return ret;
            }

            @Override
            protected double getA(int n, double x) {
              return 1.0;
            }
          };
      ret =
          FastMath.exp(
                  (a * FastMath.log(x))
                      + (b * FastMath.log(1.0 - x))
                      - FastMath.log(a)
                      - logBeta(a, b))
              * 1.0
              / fraction.evaluate(x, epsilon, maxIterations);
    }

    return ret;
  }
Ejemplo n.º 7
0
  /**
   * Returns the value of log[Γ(b) / Γ(a + b)] for a ≥ 0 and b ≥ 10. Based on the <em>NSWC Library
   * of Mathematics Subroutines</em> double precision implementation, {@code DLGDIV}. In {@code
   * BetaTest.testLogGammaMinusLogGammaSum()}, this private method is accessed through reflection.
   *
   * @param a First argument.
   * @param b Second argument.
   * @return the value of {@code log(Gamma(b) / Gamma(a + b))}.
   * @throws NumberIsTooSmallException if {@code a < 0.0} or {@code b < 10.0}.
   */
  private static double logGammaMinusLogGammaSum(final double a, final double b)
      throws NumberIsTooSmallException {

    if (a < 0.0) {
      throw new NumberIsTooSmallException(a, 0.0, true);
    }
    if (b < 10.0) {
      throw new NumberIsTooSmallException(b, 10.0, true);
    }

    /*
     * d = a + b - 0.5
     */
    final double d;
    final double w;
    if (a <= b) {
      d = b + (a - 0.5);
      w = deltaMinusDeltaSum(a, b);
    } else {
      d = a + (b - 0.5);
      w = deltaMinusDeltaSum(b, a);
    }

    final double u = d * FastMath.log1p(a / b);
    final double v = a * (FastMath.log(b) - 1.0);

    return u <= v ? (w - u) - v : (w - v) - u;
  }
Ejemplo n.º 8
0
  /**
   * Compute the <a href="http://mathworld.wolfram.com/NaturalLogarithm.html" TARGET="_top"> natural
   * logarithm</a> of this complex number. Implements the formula:
   *
   * <pre>
   *  <code>
   *   log(a + bi) = ln(|a + bi|) + arg(a + bi)i
   *  </code>
   * </pre>
   *
   * where ln on the right hand side is {@link java.lang.Math#log}, {@code |a + bi|} is the modulus,
   * {@link Complex#abs}, and {@code arg(a + bi) = }{@link java.lang.Math#atan2}(b, a). <br>
   * Returns {@link Complex#NaN} if either real or imaginary part of the input argument is {@code
   * NaN}. <br>
   * Infinite (or critical) values in real or imaginary parts of the input may result in infinite or
   * NaN values returned in parts of the result.
   *
   * <pre>
   *  Examples:
   *  <code>
   *   log(1 &plusmn; INFINITY i) = INFINITY &plusmn; (&pi;/2)i
   *   log(INFINITY + i) = INFINITY + 0i
   *   log(-INFINITY + i) = INFINITY + &pi;i
   *   log(INFINITY &plusmn; INFINITY i) = INFINITY &plusmn; (&pi;/4)i
   *   log(-INFINITY &plusmn; INFINITY i) = INFINITY &plusmn; (3&pi;/4)i
   *   log(0 + 0i) = -INFINITY + 0i
   *  </code>
   * </pre>
   *
   * @return the value <code>ln &nbsp; this</code>, the natural logarithm of {@code this}.
   * @since 1.2
   */
  public Complex log() {
    if (isNaN) {
      return NaN;
    }

    return createComplex(FastMath.log(abs()), FastMath.atan2(imaginary, real));
  }
Ejemplo n.º 9
0
  private double onePoint(double x0, double x1, double[] point) {
    final IMonteCarloModel<Double, Double> mc = factory.createModel(x0, x1, point);
    mc.addSamples(samples);
    final double value = mc.getStats().value();

    return FastMath.log(value);
  }
Ejemplo n.º 10
0
 @Override
 public IComplexNumber log() {
   IComplexNumber result = dup();
   float real = (float) result.realComponent();
   float imaginary = (float) result.imaginaryComponent();
   double modulus = FastMath.sqrt(real * real + imaginary * imaginary);
   double arg = FastMath.atan2(imaginary, real);
   return result.set(FastMath.log(modulus), arg);
 }
Ejemplo n.º 11
0
 public static ItemType chooseOldItemType(double logParam, List<ItemType> itemTypes, double rand) {
   // sum of log values for each category in itemTypesUsed
   // log( (x + 1) / x), log-base to be given
   double totalWeight = FastMath.log(logParam, itemTypes.size() + 1);
   // x = 2 * k ^ (y - 1), where k is the log base, y is a random number between 1 and totalWeight
   // basically given a random number, decides which category to reuse.
   double scaledRand = rand * totalWeight;
   int index =
       (int) (FastMath.pow(logParam, scaledRand))
           - 1; // gives a value between 0 and itemTypesUsed.size() exclusive
   return itemTypes.get(index);
 }
Ejemplo n.º 12
0
  /**
   * {@inheritDoc}
   *
   * <p>Returns {@code 0} when {@code p= = 0} and {@code Double.POSITIVE_INFINITY} when {@code p ==
   * 1}.
   */
  @Override
  public double inverseCumulativeProbability(double p) throws OutOfRangeException {
    double ret;

    if (p < 0.0 || p > 1.0) {
      throw new OutOfRangeException(p, 0.0, 1.0);
    } else if (p == 1.0) {
      ret = Double.POSITIVE_INFINITY;
    } else {
      ret = -mean * FastMath.log(1.0 - p);
    }

    return ret;
  }
Ejemplo n.º 13
0
  /**
   * Returns the value of log Γ(a + b) for 1 ≤ a, b ≤ 2. Based on the <em>NSWC Library of
   * Mathematics Subroutines</em> double precision implementation, {@code DGSMLN}. In {@code
   * BetaTest.testLogGammaSum()}, this private method is accessed through reflection.
   *
   * @param a First argument.
   * @param b Second argument.
   * @return the value of {@code log(Gamma(a + b))}.
   * @throws OutOfRangeException if {@code a} or {@code b} is lower than {@code 1.0} or greater than
   *     {@code 2.0}.
   */
  private static double logGammaSum(final double a, final double b) throws OutOfRangeException {

    if ((a < 1.0) || (a > 2.0)) {
      throw new OutOfRangeException(a, 1.0, 2.0);
    }
    if ((b < 1.0) || (b > 2.0)) {
      throw new OutOfRangeException(b, 1.0, 2.0);
    }

    final double x = (a - 1.0) + (b - 1.0);
    if (x <= 0.5) {
      return Gamma.logGamma1p(1.0 + x);
    } else if (x <= 1.5) {
      return Gamma.logGamma1p(x) + FastMath.log1p(x);
    } else {
      return Gamma.logGamma1p(x - 1.0) + FastMath.log(x * (1.0 + x));
    }
  }
Ejemplo n.º 14
0
  private void calculateCoherence() {
    LOG.info("calculating coherence scores");

    coherenceScores = new double[model.numberOfTopics()];

    for (int k = 0; k < model.numberOfTopics(); k++) {
      for (int m = 1; m < numberOfTerms; m++) {
        for (int n = 0; n < m; n++) {
          int i = term2id.get(model.topTermIds()[k][m]);
          int j = term2id.get(model.topTermIds()[k][n]);

          if (occurrenceCounts[j] > 0) {
            coherenceScores[k] +=
                FastMath.log(
                    (double) (cooccurrenceCounts[i][j] + 1d) / (double) occurrenceCounts[j]);
          }
        }
      }
    }
  }
 /**
  * A part of the deviance portion of the saddle point approximation.
  *
  * <p>References:
  *
  * <ol>
  *   <li>Catherine Loader (2000). "Fast and Accurate Computation of Binomial Probabilities.". <a
  *       target="_blank" href="http://www.herine.net/stat/papers/dbinom.pdf">
  *       http://www.herine.net/stat/papers/dbinom.pdf</a>
  * </ol>
  *
  * @param x the x value.
  * @param mu the average.
  * @return a part of the deviance.
  */
 static double getDeviancePart(double x, double mu) {
   double ret;
   if (FastMath.abs(x - mu) < 0.1 * (x + mu)) {
     double d = x - mu;
     double v = d / (x + mu);
     double s1 = v * d;
     double s = Double.NaN;
     double ej = 2.0 * x * v;
     v *= v;
     int j = 1;
     while (s1 != s) {
       s = s1;
       ej *= v;
       s1 = s + ej / ((j * 2) + 1);
       ++j;
     }
     ret = s1;
   } else {
     ret = x * FastMath.log(x / mu) + mu - x;
   }
   return ret;
 }
 /** {@inheritDoc} * */
 @Override
 public double logDensity(double x) {
   recomputeZ();
   if (x < 0 || x > 1) {
     return Double.NEGATIVE_INFINITY;
   } else if (x == 0) {
     if (alpha < 1) {
       throw new NumberIsTooSmallException(
           LocalizedFormats.CANNOT_COMPUTE_BETA_DENSITY_AT_0_FOR_SOME_ALPHA, alpha, 1, false);
     }
     return Double.NEGATIVE_INFINITY;
   } else if (x == 1) {
     if (beta < 1) {
       throw new NumberIsTooSmallException(
           LocalizedFormats.CANNOT_COMPUTE_BETA_DENSITY_AT_1_FOR_SOME_BETA, beta, 1, false);
     }
     return Double.NEGATIVE_INFINITY;
   } else {
     double logX = FastMath.log(x);
     double log1mX = FastMath.log1p(-x);
     return (alpha - 1) * logX + (beta - 1) * log1mX - z;
   }
 }
 /**
  * Compute the error of Stirling's series at the given value.
  *
  * <p>References:
  *
  * <ol>
  *   <li>Eric W. Weisstein. "Stirling's Series." From MathWorld--A Wolfram Web Resource. <a
  *       target="_blank" href="http://mathworld.wolfram.com/StirlingsSeries.html">
  *       http://mathworld.wolfram.com/StirlingsSeries.html</a>
  * </ol>
  *
  * @param z the value.
  * @return the Striling's series error.
  */
 static double getStirlingError(double z) {
   double ret;
   if (z < 15.0) {
     double z2 = 2.0 * z;
     if (FastMath.floor(z2) == z2) {
       ret = EXACT_STIRLING_ERRORS[(int) z2];
     } else {
       ret = Gamma.logGamma(z + 1.0) - (z + 0.5) * FastMath.log(z) + z - HALF_LOG_2_PI;
     }
   } else {
     double z2 = z * z;
     ret =
         (0.083333333333333333333
                 - (0.00277777777777777777778
                         - (0.00079365079365079365079365
                                 - (0.000595238095238095238095238
                                         - 0.0008417508417508417508417508 / z2)
                                     / z2)
                             / z2)
                     / z2)
             / z;
   }
   return ret;
 }
/**
 * Utility class used by various distributions to accurately compute their respective probability
 * mass functions. The implementation for this class is based on the Catherine Loader's <a
 * target="_blank" href="http://www.herine.net/stat/software/dbinom.html">dbinom</a> routines.
 *
 * <p>This class is not intended to be called directly.
 *
 * <p>References:
 *
 * <ol>
 *   <li>Catherine Loader (2000). "Fast and Accurate Computation of Binomial Probabilities.". <a
 *       target="_blank" href="http://www.herine.net/stat/papers/dbinom.pdf">
 *       http://www.herine.net/stat/papers/dbinom.pdf</a>
 * </ol>
 *
 * @since 2.1
 * @version $Id: SaddlePointExpansion.java 1538368 2013-11-03 13:57:37Z erans $
 */
final class SaddlePointExpansion {

  /** 1/2 * log(2 &#960;). */
  private static final double HALF_LOG_2_PI = 0.5 * FastMath.log(MathUtils.TWO_PI);

  /** exact Stirling expansion error for certain values. */
  private static final double[] EXACT_STIRLING_ERRORS = {
    0.0, /* 0.0 */
    0.1534264097200273452913848, /* 0.5 */
    0.0810614667953272582196702, /* 1.0 */
    0.0548141210519176538961390, /* 1.5 */
    0.0413406959554092940938221, /* 2.0 */
    0.03316287351993628748511048, /* 2.5 */
    0.02767792568499833914878929, /* 3.0 */
    0.02374616365629749597132920, /* 3.5 */
    0.02079067210376509311152277, /* 4.0 */
    0.01848845053267318523077934, /* 4.5 */
    0.01664469118982119216319487, /* 5.0 */
    0.01513497322191737887351255, /* 5.5 */
    0.01387612882307074799874573, /* 6.0 */
    0.01281046524292022692424986, /* 6.5 */
    0.01189670994589177009505572, /* 7.0 */
    0.01110455975820691732662991, /* 7.5 */
    0.010411265261972096497478567, /* 8.0 */
    0.009799416126158803298389475, /* 8.5 */
    0.009255462182712732917728637, /* 9.0 */
    0.008768700134139385462952823, /* 9.5 */
    0.008330563433362871256469318, /* 10.0 */
    0.007934114564314020547248100, /* 10.5 */
    0.007573675487951840794972024, /* 11.0 */
    0.007244554301320383179543912, /* 11.5 */
    0.006942840107209529865664152, /* 12.0 */
    0.006665247032707682442354394, /* 12.5 */
    0.006408994188004207068439631, /* 13.0 */
    0.006171712263039457647532867, /* 13.5 */
    0.005951370112758847735624416, /* 14.0 */
    0.005746216513010115682023589, /* 14.5 */
    0.005554733551962801371038690 /* 15.0 */
  };

  /** Default constructor. */
  private SaddlePointExpansion() {
    super();
  }

  /**
   * Compute the error of Stirling's series at the given value.
   *
   * <p>References:
   *
   * <ol>
   *   <li>Eric W. Weisstein. "Stirling's Series." From MathWorld--A Wolfram Web Resource. <a
   *       target="_blank" href="http://mathworld.wolfram.com/StirlingsSeries.html">
   *       http://mathworld.wolfram.com/StirlingsSeries.html</a>
   * </ol>
   *
   * @param z the value.
   * @return the Striling's series error.
   */
  static double getStirlingError(double z) {
    double ret;
    if (z < 15.0) {
      double z2 = 2.0 * z;
      if (FastMath.floor(z2) == z2) {
        ret = EXACT_STIRLING_ERRORS[(int) z2];
      } else {
        ret = Gamma.logGamma(z + 1.0) - (z + 0.5) * FastMath.log(z) + z - HALF_LOG_2_PI;
      }
    } else {
      double z2 = z * z;
      ret =
          (0.083333333333333333333
                  - (0.00277777777777777777778
                          - (0.00079365079365079365079365
                                  - (0.000595238095238095238095238
                                          - 0.0008417508417508417508417508 / z2)
                                      / z2)
                              / z2)
                      / z2)
              / z;
    }
    return ret;
  }

  /**
   * A part of the deviance portion of the saddle point approximation.
   *
   * <p>References:
   *
   * <ol>
   *   <li>Catherine Loader (2000). "Fast and Accurate Computation of Binomial Probabilities.". <a
   *       target="_blank" href="http://www.herine.net/stat/papers/dbinom.pdf">
   *       http://www.herine.net/stat/papers/dbinom.pdf</a>
   * </ol>
   *
   * @param x the x value.
   * @param mu the average.
   * @return a part of the deviance.
   */
  static double getDeviancePart(double x, double mu) {
    double ret;
    if (FastMath.abs(x - mu) < 0.1 * (x + mu)) {
      double d = x - mu;
      double v = d / (x + mu);
      double s1 = v * d;
      double s = Double.NaN;
      double ej = 2.0 * x * v;
      v *= v;
      int j = 1;
      while (s1 != s) {
        s = s1;
        ej *= v;
        s1 = s + ej / ((j * 2) + 1);
        ++j;
      }
      ret = s1;
    } else {
      ret = x * FastMath.log(x / mu) + mu - x;
    }
    return ret;
  }

  /**
   * Compute the logarithm of the PMF for a binomial distribution using the saddle point expansion.
   *
   * @param x the value at which the probability is evaluated.
   * @param n the number of trials.
   * @param p the probability of success.
   * @param q the probability of failure (1 - p).
   * @return log(p(x)).
   */
  static double logBinomialProbability(int x, int n, double p, double q) {
    double ret;
    if (x == 0) {
      if (p < 0.1) {
        ret = -getDeviancePart(n, n * q) - n * p;
      } else {
        ret = n * FastMath.log(q);
      }
    } else if (x == n) {
      if (q < 0.1) {
        ret = -getDeviancePart(n, n * p) - n * q;
      } else {
        ret = n * FastMath.log(p);
      }
    } else {
      ret =
          getStirlingError(n)
              - getStirlingError(x)
              - getStirlingError(n - x)
              - getDeviancePart(x, n * p)
              - getDeviancePart(n - x, n * q);
      double f = (MathUtils.TWO_PI * x * (n - x)) / n;
      ret = -0.5 * FastMath.log(f) + ret;
    }
    return ret;
  }
}
Ejemplo n.º 19
0
  /**
   * Returns the value of log B(p, q) for 0 ≤ x ≤ 1 and p, q > 0. Based on the <em>NSWC Library of
   * Mathematics Subroutines</em> implementation, {@code DBETLN}.
   *
   * @param p First argument.
   * @param q Second argument.
   * @return the value of {@code log(Beta(p, q))}, {@code NaN} if {@code p <= 0} or {@code q <= 0}.
   */
  public static double logBeta(final double p, final double q) {
    if (Double.isNaN(p) || Double.isNaN(q) || (p <= 0.0) || (q <= 0.0)) {
      return Double.NaN;
    }

    final double a = FastMath.min(p, q);
    final double b = FastMath.max(p, q);
    if (a >= 10.0) {
      final double w = sumDeltaMinusDeltaSum(a, b);
      final double h = a / b;
      final double c = h / (1.0 + h);
      final double u = -(a - 0.5) * FastMath.log(c);
      final double v = b * FastMath.log1p(h);
      if (u <= v) {
        return (((-0.5 * FastMath.log(b) + HALF_LOG_TWO_PI) + w) - u) - v;
      } else {
        return (((-0.5 * FastMath.log(b) + HALF_LOG_TWO_PI) + w) - v) - u;
      }
    } else if (a > 2.0) {
      if (b > 1000.0) {
        final int n = (int) FastMath.floor(a - 1.0);
        double prod = 1.0;
        double ared = a;
        for (int i = 0; i < n; i++) {
          ared -= 1.0;
          prod *= ared / (1.0 + ared / b);
        }
        return (FastMath.log(prod) - n * FastMath.log(b))
            + (Gamma.logGamma(ared) + logGammaMinusLogGammaSum(ared, b));
      } else {
        double prod1 = 1.0;
        double ared = a;
        while (ared > 2.0) {
          ared -= 1.0;
          final double h = ared / b;
          prod1 *= h / (1.0 + h);
        }
        if (b < 10.0) {
          double prod2 = 1.0;
          double bred = b;
          while (bred > 2.0) {
            bred -= 1.0;
            prod2 *= bred / (ared + bred);
          }
          return FastMath.log(prod1)
              + FastMath.log(prod2)
              + (Gamma.logGamma(ared) + (Gamma.logGamma(bred) - logGammaSum(ared, bred)));
        } else {
          return FastMath.log(prod1) + Gamma.logGamma(ared) + logGammaMinusLogGammaSum(ared, b);
        }
      }
    } else if (a >= 1.0) {
      if (b > 2.0) {
        if (b < 10.0) {
          double prod = 1.0;
          double bred = b;
          while (bred > 2.0) {
            bred -= 1.0;
            prod *= bred / (a + bred);
          }
          return FastMath.log(prod)
              + (Gamma.logGamma(a) + (Gamma.logGamma(bred) - logGammaSum(a, bred)));
        } else {
          return Gamma.logGamma(a) + logGammaMinusLogGammaSum(a, b);
        }
      } else {
        return Gamma.logGamma(a) + Gamma.logGamma(b) - logGammaSum(a, b);
      }
    } else {
      if (b >= 10.0) {
        return Gamma.logGamma(a) + logGammaMinusLogGammaSum(a, b);
      } else {
        // The following command is the original NSWC implementation.
        // return Gamma.logGamma(a) +
        // (Gamma.logGamma(b) - Gamma.logGamma(a + b));
        // The following command turns out to be more accurate.
        return FastMath.log(Gamma.gamma(a) * Gamma.gamma(b) / Gamma.gamma(a + b));
      }
    }
  }
Ejemplo n.º 20
0
  // Qf <- function(par)
  private double qF(double[] par, ArrayRealVector y, ArrayRealVector w) {

    // fv <- solve((exp(-par[1])*W) + (exp(-par[2])*G),
    // (exp(-par[1])*W)%*%as.vector(y))
    solver =
        new QRDecomposition(
                wM.scalarMultiply(FastMath.exp(-par[0]))
                    .add(gM.scalarMultiply(FastMath.exp(-par[1]))))
            .getSolver();

    fv = (ArrayRealVector) solver.solve(wM.scalarMultiply(FastMath.exp(-par[0])).operate(y));

    // b <- diff(fv, differences=order)
    b = MatrixFunctions.diffV(fv, Controls.RW_ORDER);

    // DT <-  determinant((exp(-par[1])*W) + (exp(-par[2])*G))$modulus
    double dt =
        new LUD(
                wM.scalarMultiply(FastMath.exp(-par[0]))
                    .add(gM.scalarMultiply(FastMath.exp(-par[1]))))
            .getDeterminant();

    // f <- -(N/2)*log(2*pi*exp(par[1])) +           # 1
    tempV = y.subtract(fv);
    double f =
        -(n / 2) * FastMath.log(2 * FastMath.PI * FastMath.exp(par[0]))

            //               .5*sum(log(weights))-                   # 2
            + 0.5 * MatrixFunctions.sumV(MatrixFunctions.logVec(w))

            //               sum(weights*(y-fv)^2)/(2*exp(par[1])) + # 3
            - MatrixFunctions.sumV(w.ebeMultiply(tempV).ebeMultiply(tempV))
                / (2 * FastMath.exp(par[0]))

            //               (N/2)*log(2*pi) -                       # 4
            + (n * FastMath.log(2 * FastMath.PI)) / 2

            //               ((N-order)/2)*log(2*pi*exp(par[2]))-    # 5
            - ((n - Controls.RW_ORDER) * FastMath.log(2 * FastMath.PI * FastMath.exp(par[1]))) / 2

            //              sum(b^2)/(2*exp(par[2])) -              # 6
            - MatrixFunctions.sumV(b.ebeMultiply(b)) / (2 * FastMath.exp(par[1]))

            //               .5*DT								   # 7
            - 0.5 * dt;

    // attributes(f) <- NULL
    // Pen <- if (penalty==TRUE) delta[1]*(par[1]-shift[1])^2
    // + delta[2]*(par[2]-shift[2])^2 else 0 -f+Pen
    double pen = 0;
    if (Controls.PENALTY) {
      pen =
          delta.getEntry(0) * (par[0] - Controls.RW_SHIFT[0]) * (par[0] - Controls.RW_SHIFT[0])
              + delta.getEntry(1)
                  * (par[1] - Controls.RW_SHIFT[1])
                  * (par[1] - Controls.RW_SHIFT[1]);
    }

    // -f+Pen  # no penalty  yet
    return (-f + pen);
  }
Ejemplo n.º 21
0
  /**
   * The main fitting method of Random Walk smoother.
   *
   * @param additiveFit - object of AdditiveFit class
   * @return residuals
   */
  public ArrayRealVector solve(AdditiveFit additiveFit) {

    ArrayRealVector y = additiveFit.getZ();
    ArrayRealVector w = additiveFit.getW();
    int whichDistParameter = additiveFit.getWhichDistParameter();

    // if (any(is.na(y)))
    for (int i = 0; i < y.getDimension(); i++) {
      if (Double.isNaN(y.getEntry(i))) {

        // weights[is.na(y)] <- 0
        w.setEntry(i, 0.0);

        // y[is.na(y)] <- 0
        y.setEntry(i, 0.0);
      }
    }

    // N <- length(y)
    n = y.getDimension();
    // -------------------------------------------------------  BECOMES VERY SLOW HERE
    // W <- diag.spam(x=weights)  # weights
    wM = (BlockRealMatrix) MatrixUtils.createRealDiagonalMatrix(w.getDataRef());

    // E <- diag.spam(N)
    eM = MatrixFunctions.buildIdentityMatrix(n);

    // D <- diff(E, diff = order) # order
    dM = MatrixFunctions.diff(eM, Controls.RW_ORDER);
    // -------------------------------------------------------  FREEZES HERE
    // G <- t(D)%*%D
    gM = dM.transpose().multiply(dM);

    // logsig2e <- log(sig2e) # getting logs
    double logsig2e = FastMath.log(sigmasHash.get(whichDistParameter)[0]);

    // logsig2b <- log(sig2b)
    double logsig2b = FastMath.log(sigmasHash.get(whichDistParameter)[1]);

    // fv <- solve(exp(-logsig2e)*W + exp(-logsig2b)*G,
    // (exp(-logsig2e)*W)%*% as.vector(y))
    solver =
        new QRDecomposition(
                wM.scalarMultiply(FastMath.exp(-logsig2e))
                    .add(gM.scalarMultiply(FastMath.exp(-logsig2b))))
            .getSolver();

    fv = (ArrayRealVector) solver.solve(wM.scalarMultiply(FastMath.exp(-logsig2e)).operate(y));

    // if (sig2e.fix==FALSE && sig2b.fix==FALSE) # both estimated{
    if (Controls.SIG2E_FIX) {
      if (Controls.SIG2B_FIX) {

        // out <- list()
        // par <- c(logsig2e, logsig2b)
        // out$par <- par
        // value.of.Q <- -Qf(par)
        valueOfQ = -qF(new double[] {logsig2e, logsig2b}, y, w);

        // se <- NULL
        se = null;

      } else {

        // par <- log(sum((D%*%fv)^2)/N)
        tempV = (ArrayRealVector) dM.operate(fv);
        logsig2b = FastMath.log(MatrixFunctions.sumV(tempV.ebeMultiply(tempV)) / n);

        // Qf1 <- function(par)  Qf(c(logsig2e, par))
        // out<-nlminb(start = par,objective = Qf1,
        // lower = c(-20), upper = c(20))

        nonLinObj1.setResponse(y);
        nonLinObj1.setWeights(w);
        nonLinObj1.setLogsig2e(logsig2e);

        maxiter = new MaxIter(Controls.BOBYQA_MAX_ITER);
        maxeval = new MaxEval(Controls.BOBYQA_MAX_EVAL);
        initguess = new InitialGuess(new double[] {logsig2b, logsig2b});
        bounds =
            new SimpleBounds(
                new double[] {-Double.MAX_VALUE, -Double.MAX_VALUE},
                new double[] {Double.MAX_VALUE, Double.MAX_VALUE});
        obj = new ObjectiveFunction(nonLinObj1);
        PointValuePair values =
            optimizer.optimize(maxiter, maxeval, obj, initguess, bounds, GoalType.MINIMIZE);

        logsig2b = values.getPoint()[0];

        if (logsig2b > 20.0) {
          logsig2b = 20.0;
          valueOfQ = -qF(new double[] {logsig2e, logsig2b}, y, w);
        } else if (logsig2b < -20.0) {
          logsig2b = -20.0;
          valueOfQ = -qF(new double[] {logsig2e, logsig2b}, y, w);
        } else {
          valueOfQ = -values.getValue();
        }

        // out$hessian <- optimHess(out$par, Qf1)
        // value.of.Q <- -out$objective
        // shes <- 1/out$hessian
        // se1 <- ifelse(shes>0, sqrt(shes), NA)
        // par <- c(logsig2e, out$par)
        // names(par) <- c("logsig2e", "logsig2b")
        /// out$par <- par
        // se <- c(NA, se1)
        // System.out.println(logsig2e+"   "+logsig2b +"   "+qF(new double[]{logsig2e, logsig2b}, y,
        // w));
      }
    } else {
      if (Controls.SIG2B_FIX) {

        // par <- log(sum(weights*(y-fv)^2)/N)
        tempV = y.subtract(fv);
        logsig2e = FastMath.log(MatrixFunctions.sumV(tempV.ebeMultiply(tempV).ebeMultiply(w)) / n);

        // Qf2 <- function(par)  Qf(c(par, logsig2b))
        // out <- nlminb(start = par, objective = Qf2,
        // lower = c(-20),  upper = c(20))
        nonLinObj2.setResponse(y);
        nonLinObj2.setWeights(w);
        nonLinObj2.setLogsig2b(logsig2b);

        maxiter = new MaxIter(Controls.BOBYQA_MAX_ITER);
        maxeval = new MaxEval(Controls.BOBYQA_MAX_EVAL);
        initguess = new InitialGuess(new double[] {logsig2e, logsig2e});
        bounds =
            new SimpleBounds(
                new double[] {-Double.MAX_VALUE, -Double.MAX_VALUE},
                new double[] {Double.MAX_VALUE, Double.MAX_VALUE});
        obj = new ObjectiveFunction(nonLinObj2);
        PointValuePair values =
            optimizer.optimize(maxiter, maxeval, obj, initguess, bounds, GoalType.MINIMIZE);

        logsig2e = values.getPoint()[0];

        // out$hessian <- optimHess(out$par, Qf2)
        // value.of.Q <- -out$objective
        if (logsig2e > 20.0) {
          logsig2e = 20.0;
          valueOfQ = -qF(new double[] {logsig2e, logsig2b}, y, w);
        } else if (logsig2e < -20.0) {
          logsig2e = -20.0;
          valueOfQ = -qF(new double[] {logsig2e, logsig2b}, y, w);
        } else {
          valueOfQ = -values.getValue();
        }

        // shes <- 1/out$hessian
        // se1 <- ifelse(shes>0, sqrt(shes), NA)
        // par <- c( out$par, logsig2b)
        // names(par) <- c("logsig2e", "logsig2b")
        // out$par <- par
        // se <- c(se1, NA)
        // System.out.println(logsig2e+"   "+logsig2b +"   "+qF(new double[]{logsig2e, logsig2b}, y,
        // w));

      } else {

        // par <- c(logsig2e <- log(sum(weights*(y-fv)^2)/N),
        // logsig2b <-log(sum((D%*%fv)^2)/N))
        tempV = y.subtract(fv);
        logsig2e = FastMath.log(MatrixFunctions.sumV(w.ebeMultiply(tempV).ebeMultiply(tempV)) / n);

        tempV = (ArrayRealVector) dM.operate(fv);
        logsig2b = FastMath.log(MatrixFunctions.sumV(tempV.ebeMultiply(tempV)) / n);

        nonLinObj.setResponse(y);
        nonLinObj.setWeights(w);

        // out <- nlminb(start = par, objective = Qf,
        // lower = c(-20, -20),  upper = c(20, 20))
        maxiter = new MaxIter(Controls.BOBYQA_MAX_ITER);
        maxeval = new MaxEval(Controls.BOBYQA_MAX_EVAL);
        initguess = new InitialGuess(new double[] {logsig2e, logsig2b});
        bounds = new SimpleBounds(new double[] {-20.0, -20.0}, new double[] {20.0, 20.0});
        obj = new ObjectiveFunction(nonLinObj);
        PointValuePair values =
            optimizer.optimize(maxiter, maxeval, obj, initguess, bounds, GoalType.MINIMIZE);

        logsig2e = values.getPoint()[0];
        logsig2b = values.getPoint()[1];

        // System.out.println(logsig2e+"   "+logsig2b +"   "+values.getValue());

        // out$hessian <- optimHess(out$par, Qf) !!! Missing in Java
        // value.of.Q <- -out$objective
        valueOfQ = -values.getValue();

        // shes <- try(solve(out$hessian))
        // se <- if (any(class(shes)%in%"try-error"))
        // rep(NA_real_,2) else sqrt(diag(shes))
      }
    }

    // fv <- solve(exp(-out$par[1])*W + exp(-out$par[2])*G,
    // (exp(-out$par[1])*W)%*% as.vector(y))
    solver =
        new QRDecomposition(
                wM.scalarMultiply(FastMath.exp(-logsig2e))
                    .add(gM.scalarMultiply(FastMath.exp(-logsig2b))))
            .getSolver();

    fv = (ArrayRealVector) solver.solve(wM.scalarMultiply(FastMath.exp(-logsig2e)).operate(y));

    sigmasHash.put(
        whichDistParameter, new Double[] {FastMath.exp(logsig2e), FastMath.exp(logsig2b)});

    // b <- diff(fv, differences=order)
    b = MatrixFunctions.diffV(fv, Controls.RW_ORDER);

    // tr1 <- order + sum(b^2)/(exp(out$par[2])) # this always right
    // attributes(tr1) <- NULL
    double tr1 =
        Controls.RW_ORDER + MatrixFunctions.sumV(b.ebeMultiply(b)) / (FastMath.exp(logsig2b));

    tempV = null;
    return y.subtract(fv);
  }
Ejemplo n.º 22
0
  /*
   * Builtin functions with two inputs
   */
  public double execute(double in1, double in2) throws DMLRuntimeException {
    switch (bFunc) {

        /*
         * Arithmetic relational operators (==, !=, <=, >=) must be instead of
         * <code>Double.compare()</code> due to the inconsistencies in the way
         * NaN and -0.0 are handled. The behavior of methods in
         * <code>Double</code> class are designed mainly to make Java
         * collections work properly. For more details, see the help for
         * <code>Double.equals()</code> and <code>Double.comapreTo()</code>.
         */
      case MAX:
      case CUMMAX:
        // return (Double.compare(in1, in2) >= 0 ? in1 : in2);
        return (in1 >= in2 ? in1 : in2);
      case MIN:
      case CUMMIN:
        // return (Double.compare(in1, in2) <= 0 ? in1 : in2);
        return (in1 <= in2 ? in1 : in2);

        // *** HACK ALERT *** HACK ALERT *** HACK ALERT ***
        // rowIndexMax() and its siblings require comparing four values, but
        // the aggregation API only allows two values. So the execute()
        // method receives as its argument the two cell values to be
        // compared and performs just the value part of the comparison. We
        // return an integer cast down to a double, since the aggregation
        // API doesn't have any way to return anything but a double. The
        // integer returned takes on three posssible values: //
        // .     0 => keep the index associated with in1 //
        // .     1 => use the index associated with in2 //
        // .     2 => use whichever index is higher (tie in value) //
      case MAXINDEX:
        if (in1 == in2) {
          return 2;
        } else if (in1 > in2) {
          return 1;
        } else { // in1 < in2
          return 0;
        }
      case MININDEX:
        if (in1 == in2) {
          return 2;
        } else if (in1 < in2) {
          return 1;
        } else { // in1 > in2
          return 0;
        }
        // *** END HACK ***
      case LOG:
        // if ( in1 <= 0 )
        //	throw new DMLRuntimeException("Builtin.execute(): logarithm can be computed only for
        // non-negative numbers.");
        if (FASTMATH) return (FastMath.log(in1) / FastMath.log(in2));
        else return (Math.log(in1) / Math.log(in2));
      case LOG_NZ:
        if (FASTMATH) return (in1 == 0) ? 0 : (FastMath.log(in1) / FastMath.log(in2));
        else return (in1 == 0) ? 0 : (Math.log(in1) / Math.log(in2));

      default:
        throw new DMLRuntimeException("Builtin.execute(): Unknown operation: " + bFunc);
    }
  }