简体   繁体   中英

Where does “ainv” come from?

Python's random module has the following method in it:

def gammavariate(self, alpha, beta):
    """Gamma distribution.  Not the gamma function!

    Conditions on the parameters are alpha > 0 and beta > 0.

    The probability distribution function is:

                x ** (alpha - 1) * math.exp(-x / beta)
      pdf(x) =  --------------------------------------
                  math.gamma(alpha) * beta ** alpha

    """

    # alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2

    # Warning: a few older sources define the gamma distribution in terms
    # of alpha > -1.0
    if alpha <= 0.0 or beta <= 0.0:
        raise ValueError('gammavariate: alpha and beta must be > 0.0')

    random = self.random
    if alpha > 1.0:

        # Uses R.C.H. Cheng, "The generation of Gamma
        # variables with non-integral shape parameters",
        # Applied Statistics, (1977), 26, No. 1, p71-74

        ainv = _sqrt(2.0 * alpha - 1.0)
        bbb = alpha - LOG4
        ccc = alpha + ainv

        while 1:
            u1 = random()
            if not 1e-7 < u1 < .9999999:
                continue
            u2 = 1.0 - random()
            v = _log(u1/(1.0-u1))/ainv
            x = alpha*_exp(v)
            z = u1*u1*u2
            r = bbb+ccc*v-x
            if r + SG_MAGICCONST - 4.5*z >= 0.0 or r >= _log(z):
                return x * beta

    elif alpha == 1.0:
        # expovariate(1)
        u = random()
        while u <= 1e-7:
            u = random()
        return -_log(u) * beta

    else:   # alpha is between 0 and 1 (exclusive)

        # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle

        while 1:
            u = random()
            b = (_e + alpha)/_e
            p = b*u
            if p <= 1.0:
                x = p ** (1.0/alpha)
            else:
                x = -_log((b-p)/alpha)
            u1 = random()
            if p > 1.0:
                if u1 <= x ** (alpha - 1.0):
                    break
            elif u1 <= _exp(-x):
                break
        return x * beta

While porting the code over to Java for use, my IDE has been complaining that there is a typo (misspelling) for the ainv variable name. Where does this name come from, and what is the justification behind it? If anyone can find reference material for Applied Statistics, (1977), 26, No. 1, p71-74 , being able to read those pages may be helpful.

Addendum

This may or may not be of use to anyone, but here is a partial implementation of the class that was ported over. The code appears to be complete, but JetBrains Intellij IDEA complains about ainv 's spelling if it is not added to the IDE's dictionary. This has led to some indecision as to whether or not it should be considered to be correctly spelled. It is the only typo the program is complaining about.

import java.util.Random;

class XRandom extends Random {
    static final double LOG4 = Math.log(4);
    static final double SG_MAGIC_CONST = 1 + Math.log(4.5);

    double gammaVariate(double alpha, double beta) {
        if (alpha <= 0 || beta <= 0)
            throw new RuntimeException("gammaVariate: alpha and beta must be > 0");
        if (alpha > 1) {
            double ainv, bbb, ccc, u1, v, x, z, r;
            ainv = Math.sqrt(2 * alpha - 1);
            bbb = alpha - LOG4;
            ccc = alpha + ainv;
            while (true) {
                u1 = this.nextDouble();
                if (u1 <= 1e-7 || u1 >= .9999999)
                    continue;
                v = Math.log(u1 / (1 - u1)) / ainv;
                x = alpha * Math.exp(v);
                z = u1 * u1 * (1 - this.nextDouble());
                r = bbb + ccc * v - x;
                if (r + SG_MAGIC_CONST - 4.5 * z >= 0 || r >= Math.log(z))
                    return x * beta;
            }
        }
        if (alpha < 1) {
            double b, p, x, u1;
            while (true) {
                b = (Math.E + alpha) / Math.E;
                p = b * this.nextDouble();
                x = p <= 1 ? Math.pow(p, 1 / alpha) : -Math.log((b - p) / alpha);
                u1 = this.nextDouble();
                if (p > 1) {
                    if (u1 <= Math.pow(x, alpha - 1))
                        break;
                } else if (u1 <= Math.exp(-x))
                    break;
            }
            return x * beta;
        }
        double u;
        do {
            u = this.nextDouble();
        } while (u <= 1e-7);
        return -Math.log(u) * beta;
    }
}

Not sure why the IDE thinks it's a typo, but don't you just need to declare the ainv variable?

double ainv = Math.sqrt(2.0 * alpha - 1.0) ;

As for it's purpose, it looks to be just an intermediate calculation that's used in two other places.

I found page 71 here , but it looks like pages 72-75 require an account to view them at full resolution.

在此输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM