Beispiel #1
0
def dextreme_I(type, mu, scale, x):
    """
    The pdf of the extreme value distribution type I 
    (aka the Gumbel distribution or Gumbel distribution type I):
    F = exp{-exp[-(x-mu)/scale]}       (max variant)
    f = exp[-(x-mu)/scale] * exp{-exp[-(x-mu)/scale]} / scale
    F = 1 - exp{-exp[+(x-mu)/scale]}   (min variant)
    f = exp[+(x-mu)/scale] * exp{-exp[+(x-mu)/scale]} / scale
    
    type must be 'max' or 'min'
    scale must be > 0.0
    """

    assert scale > 0.0, "scale must be positive in dextreme_I!"

    if type == 'max':
        fscale = float(scale)
        h = exp(-(x - mu) / fscale)
        g = exp(-h)
        pdf = h * g / fscale
    elif type == 'min':
        fscale = float(scale)
        h = exp((x - mu) / fscale)
        g = exp(-h)
        pdf = h * g / fscale
    else:
        raise Error("type must be either 'max' or 'min' in cextreme_I!")

    pdf = kept_within(0.0, pdf)

    return pdf
Beispiel #2
0
    def call_next_in_line(self, calltime):
        """
        Fetch the first arrival time at the front end of the line,
        remove it from the line, and make one server busy.
        
        Outputs:
        --------
        The arrival time at the front end of the line 
        """

        self.__length[calltime - self.__prevctl] = len(self.__line)
        self.__idleh[calltime - self.__prevcti] = self.nfreeserv
        self.__systemh[calltime-self.__prevcts] = len(self.__line) + \
                                              self.__nserv - self.__nfreeserv
        self.__prevctl = calltime
        self.__prevcti = calltime
        self.__prevcts = calltime

        arrivaltime = self.__line.shift()

        self.__nfreeserv -= 1
        if self.__nfreeserv < 0:
            raise Error("Number of servers are negative in call_next_in_line!")

        self.__wtimes.append(calltime - arrivaltime)

        self.__ninline = len(self.__line)

        return arrivaltime
Beispiel #3
0
def iextreme_I(prob, type='max', mu=0.0, scale=1.0):
    """
    Extreme value distribution type I (aka the Gumbel distribution or 
    Gumbel distribution type I):
    F = exp{-exp[-(x-mu)/scale]}       (max variant)
    f = exp[-(x-mu)/scale] * exp{-exp[-(x-mu)/scale]} / scale
    F = 1 - exp{-exp[+(x-mu)/scale]}   (min variant)
    f = exp[+(x-mu)/scale] * exp{-exp[+(x-mu)/scale]} / scale

    type must be 'max' or 'min'
    scale must be > 0.0
    """

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

    if    type == 'max':
        x = - scale*safelog(-safelog(prob)) + mu

    elif  type == 'min':
        x =   scale*safelog(-safelog(1.0-prob)) + mu

    else:
        raise Error("iextreme_I: type must be either 'max' or 'min'")

    return x
Beispiel #4
0
def dextreme_gen(type, shape, mu, scale, x):
    """
    The pdf of the generalized extreme value distribution:

    F = exp{-[1-shape*(x-mu)/scale]**(1/shape)}       (max version)
    f = [1-shape*(x-mu)/scale]**(1/shape-1) * 
                                 exp{-[1-shape*(x-mu)/scale]**(1/shape)} / scale

    F = 1 - exp{-[1+shape*(x-mu)/scale]**(1/shape)}   (min version)
    f = [1+shape*(x-mu)/scale]**(1/shape-1) * 
                                 exp{-[1+shape*(x-mu)/scale]**(1/shape)} / scale

    shape  < 0 => Type II
    shape  > 0 => Type III
    shape -> 0 => Type I - Gumbel
    type must be 'max' or 'min'
    scale must be > 0.0

    A REASONABLE SCHEME SEEMS TO BE mu = scale WHICH SEEMS TO LIMIT THE
    DISTRIBUTION TO EITHER SIDE OF THE Y-AXIS!
    """

    if shape == 0.0:
        pdf = dextreme_I(type, mu, scale, x)

    else:
        assert scale > 0.0, "scale must be positive in dextreme_gen!"

        if type == 'max':
            fscale = float(scale)
            epahs = 1.0 / shape
            crucial = 1.0 - shape * (x - mu) / float(scale)
            if crucial <= 0.0 and shape < 0.0:
                pdf = 0.0
            else:
                g = exp(-crucial**epahs)
                h = crucial**(epahs - 1.0)
                pdf = h * g / scale

        elif type == 'min':
            fscale = float(scale)
            epahs = 1.0 / shape
            crucial = 1.0 + shape * (x - mu) / float(scale)
            if crucial <= 0.0 and shape < 0.0:
                pdf = 0.0
            else:
                g = exp(-crucial**epahs)
                h = crucial**(epahs - 1.0)
                pdf = h * g / scale

        else:
            raise Error("type must be either 'max' or 'min' in dextreme_gen!")

    pdf = kept_within(0.0, pdf)

    return pdf
Beispiel #5
0
def squaredim(matrix, caller='caller'):
    """
    Test for squareness. 
    """

    nrows, ncols = sized(matrix, 'squaredim')
    if ncols != nrows:
        errortext = "Unsquare matrix in " + caller + "!"
        raise Error(errortext)
    else:
        ndim = ncols

    return ndim
Beispiel #6
0
def xabs(x):
    """
    Replaces the built-in abs. Handles real and complex numbers and scalars 
    as well as lists/tuples, matrix row vectors and matrix column vectors 
    having the nested type of structure defined in the Matrix class.
    
    Arguments:
    ----------
    x       The argument may be a float or a complex number or a list/tuple, 
            or a nested list/tuple vector structure containing floats or
            complex numbers

    Outputs:
    --------
    The absolute value of the input (float) 
    """

    try:
        nrows = len(x)    # OK it's a list

        try:
            ncols = len(x[0])    # OK it's even a matrix vector!

            if   nrows == 1:     # It's a matrix row vector
                a2 = 0.0
                for k in range(0, ncols):
                    z  =  complex(x[0][k])
                    a2 =  a2 + z.real*z.real + z.imag*z.imag
            elif ncols == 1:     # It's a matrix column vector
                a2 = 0.0
                for k in range(0, nrows):
                    z  =  complex(x[k][0])
                    a2 =  a2 + z.real*z.real + z.imag*z.imag
            else:
                raise Error("abs: argument not a vector nor a scalar")

        except TypeError: # It was a list but not a matrix vector
            a2 = 0.0
            for k in range(0, nrows):
                z  =  complex(x[k])
                a2 =  a2 + z.real*z.real + z.imag*z.imag

    except TypeError:   # Well, it was merely a scalar!
        z  =  complex(x)
        a2 =  z.real*z.real + z.imag*z.imag

    return sqrt(a2)

# end of xabs

#-------------------------------------------------------------------------------
Beispiel #7
0
    def zero(self, nrows, ncols):
        """
        Create a zero matrix with dimension nrows*ncols from scratch. 
        """

        if self:
            raise Error("Instance matrix exists already in Matrix.zero!")

        for k in range(0, nrows):
            row = array('d', ncols * [0.0])
            self.append(row)

        self.__nrows = nrows
        self.__ncols = ncols
Beispiel #8
0
def cextreme_gen(type, shape, mu, scale, x):
    """
    Generalized extreme value distribution:

    F = exp{-[1-shape*(x-mu)/scale]**(1/shape)}       (max version)
    f = [1-shape*(x-mu)/scale]**(1/shape-1) * 
                               exp{-[1-shape*(x-mu)/scale]**(1/shape)} / scale

    F = 1 - exp{-[1+shape*(x-mu)/scale]**(1/shape)}   (min version)
    f = [1+shape*(x-mu)/scale]**(1/shape-1) * 
                               exp{-[1+shape*(x-mu)/scale]**(1/shape)} / scale
    shape  < 0 => Type II
    shape  > 0 => Type III
    shape -> 0 => Type I - Gumbel

    type must be 'max' or 'min'
    scale must be > 0.0

    A REASONABLE SCHEME SEEMS TO BE mu = scale WHICH SEEMS TO LIMIT THE
    DISTRIBUTION TO EITHER SIDE OF THE Y-AXIS!
    """

    if shape == 0.0:
        cdf = cextreme_I(type, mu, scale, x)

    else:
        assert scale > 0.0, "scale must be positive in cextreme_gen!"

        if type == 'max':
            crucial = 1.0 - shape * (x - mu) / float(scale)
            if crucial <= 0.0 and shape < 0.0:
                cdf = 0.0
            else:
                y = crucial**(1.0 / shape)
                cdf = exp(-y)

        elif type == 'min':
            crucial = 1.0 + shape * (x - mu) / float(scale)
            if crucial <= 0.0 and shape < 0.0:
                cdf = 1.0
            else:
                y = crucial**(1.0 / shape)
                cdf = 1.0 - exp(-y)

        else:
            raise Error("type must be either 'max' or 'min' in cextreme_gen!")

    cdf = kept_within(0.0, cdf, 1.0)

    return cdf
Beispiel #9
0
def xmap(func, x):
    """
    Replaces the built-in map and can be used for matrices belonging to 
    the misclib.Matrix class, or lists with the same structure, as well as 
    ordinary lists and tuples.

    Arguments:
    ----------
    func    function defined externally that takes 'x' as its 
            sole non-default argument,

    x	    an ordinary list, tuple, array or a Matrix

    Outputs:
    ---------
    The modified list 
    """

    if isinstance(x, Matrix):
        nrows = len(x)
        ncols = len(x[0])  # It's even a matrix!
        z = []
        for k in range(0, nrows):
            y = []
            for j in range(0, ncols):
                y.append(func(x[k][j]))
            y = array('d', y)
            z.append(y)

    elif is_darray(x):
        nrows = len(x)
        #z     = []
        z = array('d', z)
        for k in range(0, nrows):
            z.append(func(x[k]))
        #z = array('d', z)

    elif isinstance(x, (tuple, Stack, list)):
        nrows = len(x)
        z = []
        for k in range(0, nrows):
            z.append(func(x[k]))

    else:
        errtxt1 = "input state vector must be a tuple, a stack, "
        errtxt2 = "a list, a 'd' array or a Matrix!"
        raise Error(errtxt1 + errtxt2)

    return z
Beispiel #10
0
    def blank(self, nrows, ncols):
        """
        Create a matrix with dimension nrows*ncols containing only NaN 
        elements from scratch. 
        """

        if self:
            raise Error("Instance matrix exists already in Matrix.blank!")

        for k in range(0, nrows):
            row = array('d', ncols * [float('nan')])
            self.append(row)

        self.__nrows = nrows
        self.__ncols = ncols
Beispiel #11
0
    def unity(self, ndim):
        """
        Create a unity matrix from scratch. 
        """

        if self:
            raise Error("Instance matrix exists already in Matrix.unity!")

        for k in range(0, ndim):
            row = array('d', ndim * [0.0])
            row[k] = 1.0
            self.append(row)

        self.__nrows = ndim
        self.__ncols = ndim
Beispiel #12
0
    def splice(self, *arg):
        """
        Same as the push method but None is returned and iflag is not used 
        (the method is motivated by the fact that there is a corresponding 
        Stack method).
        """

        raise Error("splice is not implemented in the Heap class!")

    # end of splice


# ------------------------------------------------------------------------------

# end of Heap

# ------------------------------------------------------------------------------
Beispiel #13
0
    def __setattr__(self, attr_name, value):
        """
        This method overrides the built-in __setattr__ and makes the values of 
        the internal attributes externally available more difficult to screw 
        up from the outside.
        """

        if attr_name == "ninline"   \
        or attr_name == "nfreeserv" \
        or attr_name == "narriv"    \
        or attr_name == "nbalked"   \
        or attr_name == "renegers"  \
        or attr_name == "nreneged"  \
        or attr_name == "nescaped"  :
            errtxt1 = ": Can't change value/length of attribute"
            errtxt2 = " from the outside!"
            raise Error(attr_name + errtxt1 + errtxt2)

        else:
            self.__dict__[attr_name] = value
Beispiel #14
0
def iextreme_gen(prob, type, shape, mu=0.0, scale=1.0):
    """
    Generalized extreme value distribution:

    F = exp{-[1-shape*(x-mu)/scale]**(1/shape)}       (max version)
    f = [1-shape*(x-mu)/scale]**(1/shape-1) * 
                                exp{-[1-shape*(x-mu)/scale]**(1/shape)} / scale

    F = 1 - exp{-[1+shape*(x-mu)/scale]**(1/shape)}   (min version)
    f = [1+shape*(x-mu)/scale]**(1/shape-1) * 
                                exp{-[1+shape*(x-mu)/scale]**(1/shape)} / scale

    shape  < 0 => Type II
    shape  > 0 => Type III
    shape -> 0 => Type I - Gumbel

    type must be 'max' or 'min'
    scale must be > 0.0

    A REASONABLE SCHEME SEEMS TO BE mu = scale WHICH SEEMS TO LIMIT THE
    DISTRIBUTION TO EITHER SIDE OF THE Y-AXIS!
    """

    if shape == 0.0:
        x = iextreme_I(prob, type, mu, scale)

    else:
        _assertprob(prob, 'iextreme_gen')
        assert scale >= 0.0

        if   type == 'max':
            x = scale*(1.0-(-safelog(prob))**shape)/shape + mu

        elif type == 'min':
            x = scale*((-safelog(1.0-prob))**shape-1.0)/shape + mu

        else:
            raise Error("iextreme_gen: type must be either 'max' or 'min'")

    return x
Beispiel #15
0
def bracketzero(func,
                x1,
                x2,
                caller='caller',
                factor=GOLDPHI1,
                maxniter=32):  # GOLDPHI1 is approx. 1.6
    """
    Bracket a root by expanding from the input "guesses" x1, x2. 
    NB. It is not required that x2 > x1.
    Designed for use prior to any of the one-variable equation solvers. 
    
    The function carries out a maximum of 'maxniter' iterations, 
    each one expanding the original span by a factor of 'factor', 
    until a span is reached in which there is a zero crossing.
    """

    assert factor > 1.0, "Expansion factor must be > 1.0 in bracketzero!"
    assert is_posinteger(maxniter), \
       "Maximum number of iterations must be a positive integer in bracketzero!"

    lo = min(x1, x2)
    up = max(x1, x2)

    flo = func(lo)
    fup = func(up)

    for k in range(0, maxniter):

        if fsign(flo) != fsign(fup): return lo, up

        if abs(flo) < abs(fup):
            lo += factor * (lo - up)
            flo = func(lo)
        else:
            up += factor * (up - lo)
            fup = func(up)

    errtxt1 = "Root bracketing failed after " + str(maxniter)
    errtxt2 = " iterations in bracketzero " + "(called from " + caller + ")"
    raise Error(errtxt1 + errtxt2)
Beispiel #16
0
def cextreme_I(type, mu, scale, x):
    """
    Extreme value distribution type I (aka the Gumbel distribution or 
    Gumbel distribution type I):
    F = exp{-exp[-(x-mu)/scale]}       (max variant)
    f = exp[-(x-mu)/scale] * exp{-exp[-(x-mu)/scale]} / scale
    F = 1 - exp{-exp[+(x-mu)/scale]}   (min variant)
    f = exp[+(x-mu)/scale] * exp{-exp[+(x-mu)/scale]} / scale

    type must be 'max' or 'min'
    scale must be > 0.0
    """

    assert scale > 0.0, "scale must be positive in cextreme_I!"

    if type == 'max': cdf = exp(-exp(-(x - mu) / float(scale)))
    elif type == 'min': cdf = 1.0 - exp(-exp((x - mu) / float(scale)))
    else:
        raise Error("type must be either 'max' or 'min' in cextreme_I!")

    cdf = kept_within(0.0, cdf, 1.0)

    return cdf
Beispiel #17
0
    def __init__(self, line, nserv):
        """
        line  is 'Line' or 'LineStack'
        nserv is the initial number of servers
        """

        # Attributes made available from the outside (not assignable, though):
        # --------------------------------------------------------------------

        self.__narriv = 0  # Accumulated number of arrivers until present

        self.__ninline = 0  # Present number waiting in line

        self.__nfreeserv = nserv  # Present number of free servers

        self.__nbalked = 0  # Accumulated number of balkers

        self.__nreneged = 0  # Accumulated number of renegers

        self.__nescaped = 0  # = self.__nbalked + self.__nreneged

        # Attributes not available from the outside:
        # --------------------------------------------------------------------

        self.__nserv = nserv  # Initial number of free servers

        if line == 'Line': self.__line = Deque()
        elif line == 'LineStack': self.__line = Stack()
        else: raise Error("'line' must be 'Line' or 'LineStack' in ABCLine!")

        # dict containing the "reneging times" (time
        self.__renegers = {}  # points of the future reneging events) with
        # the corresponding arrival times as keys

        self.__wtimes = array('d', [])
        # 'd' array of waiting times for those not escaped

        self.__length = {}  # dict containing the line length history with
        # the corresponding time spans as keys

        self.__prevctl = 0.0  # The previous clock time when the line length
        # was last changed

        # dict containing the history of the number of
        self.__systemh = {}  # customers in the system with the corresponding
        # time spans as keys

        self.__prevcts = 0.0  # The previous clock time when the number of
        # customers in system was last changed

        self.__length = {}  # dict containing the line length history with
        # the corresponding time spans as keys

        self.__prevctl = 0.0  # The previous clock time when the line length
        # was last changed

        # dict containing the history of the number of
        self.__idleh = {}  # of free/idle servers in the system with the
        # corresponding time spans as keys

        self.__prevcti = 0.0  # The previous clock time when the number of