示例#1
0
    def rinhomexpo_cum(self, lamt, suplamt):
        """
        Generates - cumulatively - inhomogeneously exponentially distributed 
        interarrival times (due to an inhomogeneous Poisson process) from 
        clock time = 0.0 (the algorithm is taken from Bratley, Fox & Schrage).

        'lamt' is an externally defined function of clock time that returns 
        the present arrival rate (arrival frequency). 'suplamt' is another 
        externally defined function that returns the supremum of the arrival 
        rate over the REMAINING time from the present clock time.

        NB. A SEPARATE STREAM MUST BE INSTANTIATED FOR EACH ONE OF THE VARIATES
        THAT ARE GENERATED USING THIS METHOD, EACH WITH A SEPARATE SEED!! 
        """

        errtxt1 = "All values from suplamt must be "
        errtxt1 += "non-negative floats in rinhomexpo_cum!"
        errtxt2 = "All values from lamt must be "
        errtxt2 += "non-negative floats in rinhomexpo_cum!"

        ticum = self.__ticum

        while True:
            lamsup = suplamt(ticum)
            assert lamsup >= 0.0, errortxt1
            u = self.runif01()
            ticum -= safediv(1.0, lamsup) * safelog(self.runif01())
            lam = lamt(ticum)
            assert lam >= 0.0, errortxt2
            if u * lamsup <= lam:
                break

        self.__ticum = ticum
        return ticum
示例#2
0
    def rinhomexpo_cum(self, lamt, suplamt):
        """
        Generates - cumulatively - inhomogeneously exponentially distributed 
        interarrival times (due to an inhomogeneous Poisson process) from 
        clock time = 0.0 (the algorithm is taken from Bratley, Fox & Schrage).

        'lamt' is an externally defined function of clock time that returns 
        the present arrival rate (arrival frequency). 'suplamt' is another 
        externally defined function that returns the supremum of the arrival 
        rate over the REMAINING time from the present clock time.

        NB. A SEPARATE STREAM MUST BE INSTANTIATED FOR EACH ONE OF THE VARIATES
        THAT ARE GENERATED USING THIS METHOD, EACH WITH A SEPARATE SEED!! 
        """

        errtxt1  = "All values from suplamt must be "
        errtxt1 += "non-negative floats in rinhomexpo_cum!"
        errtxt2  = "All values from lamt must be "
        errtxt2 += "non-negative floats in rinhomexpo_cum!"

        ticum = self.__ticum

        while True:
            lamsup =  suplamt(ticum)
            assert lamsup >= 0.0, errortxt1
            u      =  self.runif01()
            ticum -=  safediv(1.0, lamsup) * safelog(self.runif01())
            lam    =  lamt(ticum)
            assert lam >= 0.0, errortxt2
            if u*lamsup <= lam:
                break

        self.__ticum = ticum
        return ticum
示例#3
0
def ilogistic(prob, mu=0.0, scale=1.0):
    """
    The inverse of the logistic distribution:
    f = exp[-(x-m)/s] / (s*{1 + exp[-(x-m)/s]}**2)
    F = 1 / {1 + exp[-(x-m)/s]}
    x in R
    m is the mean and mode, s is a scale parameter (s >= 0)
    """

    _assertprob(prob, 'ilogistic')
    assert scale >= 0.0, "scale parameter in ilogistic must not be negative!"

    x  =  mu - scale*safelog(safediv(1.0, prob) - 1.0)

    return x
示例#4
0
    def rpiecexpo_cum(self, times, lamt):
        """
        Generates - cumulatively - piecewise exponentially distributed 
        interarrival times from clock time = 0.0 (the algorithm is taken 
        from Bratley, Fox & Schrage).
        
        'times' is a list or tuple containing the points at which the arrival 
        rate (= arrival frequency) changes (the first break time point must 
        be 0.0). 'lamt' is a list or tuple containing the arrival rates between 
        break points. The number of elements in 'times' must be one more than 
        the number of elements in 'lamt'!

        The algorithm cranking out the numbers is cyclic - the procedure 
        starts over from time zero when the last break point is reached. 
        THE PREVENT THE RESTART FROM TAKING PLACE, A (VERY) LARGE NUMBER 
        MUST BE GIVEN AS THE LAST BREAK POINT (the cyclicity is rarely 
        needed or desired in practice).
        
        NB. A SEPARATE STREAM MUST BE INSTANTIATED FOR EACH ONE OF THE VARIATES 
        THAT ARE GENERATED USING THIS METHOD, EACH WITH A SEPARATE SEED!! 
        """

        ntimes  = len(times)
        errtxt1 = "No. of arrival rates and no. of break points "
        errtxt2 = "are incompatible in rpiecexpo_cum!"
        errtext = errtxt1 + errtxt2
        assert len(lamt) == ntimes-1, errtext

        r = ntimes*[0.0]
        for k in range(1, ntimes):
            assert lamt[k-1] >= 0.0, \
                     "All lamt must be non-negative floats in rpiecexpo_cum!"
            r[k]  =  r[k-1]  +  lamt[k-1] * (times[k]-times[k-1])

        cumul  = self.__cumul
        cumul -= safelog(self.runif01())
        
        iseg  = 0
        while r[iseg+1] <= cumul:
            iseg = iseg + 1
        tcum  =  times[iseg] + safediv(cumul-r[iseg], lamt[iseg])

        tcum  =  kept_within(0.0, tcum)

        self.__cumul = cumul   # NB  THIS IS NOT CUMULATIVE TIME!
        return tcum
示例#5
0
    def rexpo_cum(self, lam):
        """
        Generates - cumulatively - exponentially distributed interarrival times 
        with arrival rate (arrivale frequency) 'lam' from clock time = 0.0.

        NB. A SEPARATE STREAM MUST BE INSTANTIATED FOR EACH ONE OF THE VARIATES 
        THAT ARE GENERATED USING THIS METHOD, EACH WITH A SEPARATE SEED!! 
        """

        assert lam >= 0.0, \
                    "Arrival rate must be a non-negative float in rexpo_cum!"

        tcum  =  self.__tcum
        tcum -=  safediv(1.0, lam) * safelog(self.runif01())

        self.__tcum = tcum
        return tcum
示例#6
0
    def rpiecexpo_cum(self, times, lamt):
        """
        Generates - cumulatively - piecewise exponentially distributed 
        interarrival times from clock time = 0.0 (the algorithm is taken 
        from Bratley, Fox & Schrage).
        
        'times' is a list or tuple containing the points at which the arrival 
        rate (= arrival frequency) changes (the first break time point must 
        be 0.0). 'lamt' is a list or tuple containing the arrival rates between 
        break points. The number of elements in 'times' must be one more than 
        the number of elements in 'lamt'!

        The algorithm cranking out the numbers is cyclic - the procedure 
        starts over from time zero when the last break point is reached. 
        THE PREVENT THE RESTART FROM TAKING PLACE, A (VERY) LARGE NUMBER 
        MUST BE GIVEN AS THE LAST BREAK POINT (the cyclicity is rarely 
        needed or desired in practice).
        
        NB. A SEPARATE STREAM MUST BE INSTANTIATED FOR EACH ONE OF THE VARIATES 
        THAT ARE GENERATED USING THIS METHOD, EACH WITH A SEPARATE SEED!! 
        """

        ntimes = len(times)
        errtxt1 = "No. of arrival rates and no. of break points "
        errtxt2 = "are incompatible in rpiecexpo_cum!"
        errtext = errtxt1 + errtxt2
        assert len(lamt) == ntimes - 1, errtext

        r = ntimes * [0.0]
        for k in range(1, ntimes):
            assert lamt[k-1] >= 0.0, \
                     "All lamt must be non-negative floats in rpiecexpo_cum!"
            r[k] = r[k - 1] + lamt[k - 1] * (times[k] - times[k - 1])

        cumul = self.__cumul
        cumul -= safelog(self.runif01())

        iseg = 0
        while r[iseg + 1] <= cumul:
            iseg = iseg + 1
        tcum = times[iseg] + safediv(cumul - r[iseg], lamt[iseg])

        tcum = kept_within(0.0, tcum)

        self.__cumul = cumul  # NB  THIS IS NOT CUMULATIVE TIME!
        return tcum
示例#7
0
    def rexpo_cum(self, lam):
        """
        Generates - cumulatively - exponentially distributed interarrival times 
        with arrival rate (arrivale frequency) 'lam' from clock time = 0.0.

        NB. A SEPARATE STREAM MUST BE INSTANTIATED FOR EACH ONE OF THE VARIATES 
        THAT ARE GENERATED USING THIS METHOD, EACH WITH A SEPARATE SEED!! 
        """

        assert lam >= 0.0, \
                    "Arrival rate must be a non-negative float in rexpo_cum!"

        tcum = self.__tcum
        tcum -= safediv(1.0, lam) * safelog(self.runif01())

        self.__tcum = tcum
        return tcum
示例#8
0
    def rconst_cum(self, lamc):
        """
        Generates - cumulatively - constantly spaced interarrival times with 
        arrival rate (arrival frequency) lamc from clock time = 0.0. 

        NB  A dummy random number is picked each time the method is called 
        for reasons of synchronization.

        NB. A SEPARATE STREAM MUST BE INSTANTIATED FOR EACH ONE OF THE VARIATES 
        THAT ARE GENERATED USING THIS METHOD, EACH WITH A SEPARATE SEED!! 
        """

        assert lamc >= 0.0, \
                    "Arrival rate must be a non-negative float in rconst_cum!"

        tcum  = self.__tcum
        tcum += safediv(1.0, lamc)

        self.__tcum = tcum
        return tcum
示例#9
0
    def rconst_cum(self, lamc):
        """
        Generates - cumulatively - constantly spaced interarrival times with 
        arrival rate (arrival frequency) lamc from clock time = 0.0. 

        NB  A dummy random number is picked each time the method is called 
        for reasons of synchronization.

        NB. A SEPARATE STREAM MUST BE INSTANTIATED FOR EACH ONE OF THE VARIATES 
        THAT ARE GENERATED USING THIS METHOD, EACH WITH A SEPARATE SEED!! 
        """

        assert lamc >= 0.0, \
                    "Arrival rate must be a non-negative float in rconst_cum!"

        tcum = self.__tcum
        tcum += safediv(1.0, lamc)

        self.__tcum = tcum
        return tcum
示例#10
0
    def rgamma(self, alpha, lam, xmax=float('inf')):
        """
        The gamma distribution:
        f = lam * exp(-lam*x) * (lam*x)**(alpha-1) / gamma(alpha)
        The cdf is the integral = the incomplete gamma ratio.
        x, alpha >= 0; lam > 0.0
         
        The generator is a slight modification of Python's 
        built-in "gammavariate". 
        """

        assert alpha >= 0.0, "alpha must be non-negative in rgamma!"
        assert lam > 0.0, "lambda must be a positive float in rgamma!"
        assert xmax  >= 0.0, \
                    "variate max must be a non-negative float in rgamma!"

        f, i = modf(alpha)
        if f == 0.0:
            if 1.0 <= i and i <= GeneralRandomStream.__GAMMA2ERLANG:
                return self.rerlang(int(i), 1.0 / lam, xmax)

        if alpha < 1.0:
            # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle
            # (according to Python's "gammavariate")
            alphainv = 1.0 / alpha
            alpham1 = alpha - 1.0
            while True:
                while True:
                    u = self.runif01()
                    b = (E + alpha) / E
                    p = b * u
                    if p <= 1.0:
                        w = p**alphainv
                    else:
                        w = -safelog((b - p) * alphainv)
                    u1 = self.runif01()
                    if p > 1.0:
                        if u1 <= w**(alpham1):
                            break
                    elif u1 <= exp(-w):
                        break
                x = w / lam
                if x <= xmax: break

        else:  # elif 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
            # (according to Python's "gammavariate")

            ainv = sqrt(2.0 * alpha - 1.0)
            beta = 1.0 / ainv
            bbb = alpha - GeneralRandomStream.__LN4
            ccc = alpha + ainv

            while True:
                while True:
                    u1 = self.runif01()
                    u2 = self.runif01()
                    v = beta * safelog(safediv(u1, 1.0 - u1))
                    w = alpha * exp(v)
                    c1 = u1 * u1 * u2
                    r = bbb + ccc * v - w
                    c2 = r + 2.5040773967762742 - 4.5 * c1
                    # 2.5040773967762742 = 1.0 + log(4.5)
                    if c2 >= 0.0 or r >= safelog(c1):
                        break
                x = w / lam
                if x <= xmax: break

        x = kept_within(0.0, x)
        return x
示例#11
0
    def rbeta(self, a, b, x1, x2):
        """
        The beta distribution f = x**(a-1) * (1-x)**(b-1) / beta(a, b)
        The cdf is the integral = the incomplete beta or the incomplete 
        beta/complete beta depending on how the incomplete beta function 
        is defined.
        x, a, b >= 0; x2 > x1 
        
        The algorithm is due to Berman (1970)/Jonck (1964) (for a and b < 1.0) 
        and Cheng (1978) as described in Bratley, Fox and Schrage.
        """

        assert a  > 0.0, \
                        "shape parameters a and b must both be > 0.0 in rbeta!"
        assert b  > 0.0, \
                        "shape parameters a and b must both be > 0.0 in rbeta!"
        assert x2 >= x1, \
                         "support span must not be negative in rbeta!"

        if x2 == x1: return x1

        if a == 1.0 and b == 1.0:
            y = self.runif01()

        elif is_posinteger(a) and is_posinteger(b):
            nstop = int(a + b - 1.0)
            r = []
            for k in range(0, nstop):
                r.append(self.runif01())
            r.sort()
            y = r[int(a - 1.0)]

        elif a < 1.0 and b < 1.0:
            a1 = 1.0 / a
            b1 = 1.0 / b
            while True:
                u = pow(self.runif01(), a1)
                v = pow(self.runif01(), b1)
                if u + v <= 1.0:
                    y = u / (u + v)
                    break

        else:
            alpha = a + b
            if min(a, b) <= 1.0: beta = 1.0 / min(a, b)
            else: beta = sqrt((alpha - 2.0) / (2.0 * a * b - alpha))
            gamma = a + 1.0 / beta
            while True:
                u1 = self.runif01()
                u2 = self.runif01()
                u1 = kept_within(TINY, u1, ONEMMACHEPS)
                u2 = kept_within(TINY, u2, HUGE)
                comp1 = safelog(u1 * u1 * u2)
                v = beta * safelog(safediv(u1, 1.0 - u1))
                w = a * exp(v)
                comp2 =  alpha*safelog(alpha/(b+w)) + gamma*v - \
                                                     GeneralRandomStream.__LN4
                if comp2 >= comp1:
                    y = w / (b + w)
                    break

        x = y * (x2 - x1) + x1
        x = kept_within(x1, x, x2)

        return x
示例#12
0
    def rgamma(self, alpha, lam, xmax=float('inf')):
        """
        The gamma distribution:
        f = lam * exp(-lam*x) * (lam*x)**(alpha-1) / gamma(alpha)
        The cdf is the integral = the incomplete gamma ratio.
        x, alpha >= 0; lam > 0.0
         
        The generator is a slight modification of Python's 
        built-in "gammavariate". 
        """

        assert alpha >= 0.0, "alpha must be non-negative in rgamma!"
        assert  lam  >  0.0, "lambda must be a positive float in rgamma!"
        assert xmax  >= 0.0, \
                    "variate max must be a non-negative float in rgamma!"

        f, i = modf(alpha)
        if f == 0.0:
            if 1.0 <= i and i <= GeneralRandomStream.__GAMMA2ERLANG:
                return self.rerlang(int(i), 1.0/lam, xmax)

        if alpha < 1.0:
            # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle
            # (according to Python's "gammavariate")
            alphainv = 1.0 / alpha
            alpham1  = alpha - 1.0
            while True:
                while True:
                    u = self.runif01()
                    b = (E+alpha) / E
                    p = b * u
                    if p <= 1.0:
                        w = p ** alphainv
                    else:
                        w = -safelog((b-p)*alphainv)
                    u1 = self.runif01()
                    if p > 1.0:
                        if u1 <= w ** (alpham1):
                            break
                    elif u1 <= exp(-w):
                        break
                x = w / lam
                if x <= xmax: break

        else:   # elif 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
            # (according to Python's "gammavariate")

            ainv = sqrt(2.0*alpha - 1.0)
            beta = 1.0 / ainv
            bbb  = alpha - GeneralRandomStream.__LN4
            ccc  = alpha + ainv

            while True:
                while True:
                    u1 = self.runif01()
                    u2 = self.runif01()
                    v  = beta * safelog(safediv(u1, 1.0-u1))
                    w  = alpha * exp(v)
                    c1 = u1 * u1 * u2
                    r  = bbb + ccc*v - w
                    c2 = r + 2.5040773967762742 - 4.5*c1
                                        # 2.5040773967762742 = 1.0 + log(4.5)
                    if c2 >= 0.0 or r >= safelog(c1):
                        break
                x = w / lam
                if x <= xmax: break

        x = kept_within(0.0, x)
        return x
示例#13
0
    def rbeta(self, a, b, x1, x2):
        """
        The beta distribution f = x**(a-1) * (1-x)**(b-1) / beta(a, b)
        The cdf is the integral = the incomplete beta or the incomplete 
        beta/complete beta depending on how the incomplete beta function 
        is defined.
        x, a, b >= 0; x2 > x1 
        
        The algorithm is due to Berman (1970)/Jonck (1964) (for a and b < 1.0) 
        and Cheng (1978) as described in Bratley, Fox and Schrage.
        """

        assert a  > 0.0, \
                        "shape parameters a and b must both be > 0.0 in rbeta!"
        assert b  > 0.0, \
                        "shape parameters a and b must both be > 0.0 in rbeta!"
        assert x2 >= x1, \
                         "support span must not be negative in rbeta!"

        if x2 == x1: return x1

        if a == 1.0 and b == 1.0:
            y = self.runif01()

        elif is_posinteger(a) and is_posinteger(b):
            nstop = int(a + b - 1.0)
            r = []
            for k in range(0, nstop):
                r.append(self.runif01())
            r.sort()
            y = r[int(a-1.0)]

        elif a < 1.0 and b < 1.0:
            a1 = 1.0 / a
            b1 = 1.0 / b
            while True:
                u = pow(self.runif01(), a1)
                v = pow(self.runif01(), b1)
                if u + v <= 1.0:
                    y = u / (u+v)
                    break

        else:
            alpha = a + b
            if min(a, b) <= 1.0: beta = 1.0 / min(a, b)
            else:                beta = sqrt((alpha-2.0)/(2.0*a*b-alpha))
            gamma = a + 1.0/beta
            while True:
                u1    =  self.runif01()
                u2    =  self.runif01()
                u1    =  kept_within(TINY, u1, ONEMMACHEPS)
                u2    =  kept_within(TINY, u2, HUGE)
                comp1 =  safelog(u1*u1*u2)
                v     =  beta * safelog(safediv(u1, 1.0-u1))
                w     =  a * exp(v)
                comp2 =  alpha*safelog(alpha/(b+w)) + gamma*v - \
                                                     GeneralRandomStream.__LN4
                if comp2 >= comp1:
                    y = w / (b+w)
                    break

        x = y*(x2-x1) + x1
        x = kept_within(x1, x, x2)

        return x