def CheckMMAPRepresentation(H, prec=None): """ Checks if the input matrixes define a continuous time MMAP. All matrices D0...DK must have the same size, D0 must be a transient generator matrix, D1 has only non-negative elements, and the rowsum of D0+D1+...+DK is 0 (up to the numerical precision). Parameters ---------- D : list/cell of matrices, length(K) The D0...DK matrices of the MMAP to check Returns ------- r : bool The result of the check """ if prec == None: prec = butools.checkPrecision if np.min(np.hstack(H[1:])) < -prec: if butools.verbose: print( "CheckMMAPRepresentation: Some of the matrices H1 ... HM have a negative element!" ) return False return CheckMAPRepresentation(H[0], SumMatrixList(H[1:]), prec)
def CheckDMMAPRepresentation(D, prec=None): """ Checks if the input matrixes define a discrete time MMAP. All matrices D0...DK must have the same size, D0 must be a transient probability matrix, D1 has only non-negative elements, and the rowsum of D0+D1+...+DK is 1 (up to the numerical precision). Parameters ---------- D : list/cell of matrices, length(K) The D0...DK matrices of the DMMAP to check Returns ------- r : bool The result of the check """ if prec == None: prec = butools.checkPrecision if np.min(np.hstack(D)) < -prec: if butools.verbose: print( "CheckDMMAPRepresentation: Some of the matrices D1 ... DM have negative elements!" ) return False return CheckDMAPRepresentation(D[0], SumMatrixList(D[1:]), prec)
def MarginalDistributionFromDMRAP(H): """ Returns the matrix geometrically distributed marginal distribution of a discrete marked rational arrival process. Parameters ---------- H : list/cell of matrices of shape(M,M), length(N) The H0...HN matrices of the DMRAP precision : double, optional Numerical precision for checking if the input is valid. The default value is 1e-14 Returns ------- alpha : matrix, shape (1,M) The initial vector of the matrix geometrically distributed marginal distribution A : matrix, shape (M,M) The matrix parameter of the matrix geometrically distributed marginal distribution """ if butools.checkInput and not CheckDMRAPRepresentation(H): raise Exception( "MarginalDistributionFromDMRAP: Input is not a valid DMRAP representation!" ) return (DRPSolve( la.inv(ml.eye(H[0].shape[0]) - H[0]) * SumMatrixList(H[1:])), H[0])
def CheckDMRAPRepresentation(H, prec=None): """ Checks if the input matrixes define a discrete time MRAP. All matrices H0...HK must have the same size, the dominant eigenvalue of H0 is real and less than 1, and the rowsum of H0+H1+...+HK is 1 (up to the numerical precision). Parameters ---------- H : list/cell of matrices, length(K) The H0...HK matrices of the DMRAP to check Returns ------- r : bool The result of the check """ if prec == None: prec = butools.checkPrecision return CheckDRAPRepresentation(H[0], SumMatrixList(H[1:]), prec)
def RandomDMMAP(order, types, mean=10.0, zeroEntries=0, maxTrials=1000, prec=1e-7): """ Returns a random discrete Markovian arrival process. Parameters ---------- order : int The size of the DMAP mean : double, optional The mean inter-arrival times of the DMMAP types : int The number of different arrival types zeroEntries : int, optional The number of zero entries in the D0 and D1 matrices maxTrials : int, optional The maximum number of trials to find a proper DMMAP (that has an irreducible phase process and none of its parameters is all-zero) prec : double, optional Numerical precision for checking the irreducibility. The default value is 1e-14. Returns ------- D : list/cell of matrices of shape(M,M), length(types+1) The D0...Dtypes matrices of the DMMAP Notes ----- If it fails, try to increase the 'maxTrials' parameter, or/and the 'mean' parameter. """ # distribute the zero entries among the rows def allZeroDistr(states, zeros): if states == 1: return [[zeros]] else: o = [] for i in range(zeros + 1): x = allZeroDistr(states - 1, zeros - i) for j in range(len(x)): xt = x[j] xt.append(i) xt.sort() # check if we have it already if o.count(xt) == 0: o.append(xt) return o if zeroEntries > (types + 1) * order * order - 2 * order: raise Exception( "RandomDMAP/DMMAP: Too many zero entries requested! Try to decrease the zeroEntries parameter!" ) zeroDistr = allZeroDistr(order, zeroEntries) trials = 1 while trials < maxTrials: # select a configuration from zeroDistr: it is a list describing the zero entries in each row zdix = np.random.permutation(len(zeroDistr)) for k in range(len(zeroDistr)): zDistr = zeroDistr[zdix[k]] bad = False for d in zDistr: if d >= (types + 1) * order - 1: bad = True break if bad: continue B = np.zeros((order, (types + 1) * order)) for i in range(order): rp = np.random.permutation((types + 1) * order - 1) a = np.zeros((types + 1) * order - 1) for j in range((types + 1) * order - 1 - zDistr[i]): a[rp[j]] = np.random.rand() B[i, 0:i] = a[0:i] B[i, i + 1:] = a[i:] # construct DMMAP matrices D = [] sc = np.zeros(order) for i in range(types + 1): Di = ml.matrix(B[:, i * order:(i + 1) * order]) D.append(Di) sc += np.sum(Di, 1).A.flatten() if np.any(sc == 0): continue for i in range(types + 1): D[i] = Diag(1.0 / sc) * D[i] # check if it is a proper DMAP (irreducible phase process & no full zero matrix) sumD = SumMatrixList(D) if la.matrix_rank(D[0]) == order and la.matrix_rank( ml.eye(D[0].shape[0]) - sumD) == order - 1: alpha = DTMCSolve(sumD) if np.min(np.abs(alpha)) > prec: fullZero = False for Di in D: if np.all(Di == 0.0): fullZero = True break if not fullZero: # diagonals of matrix A: d = np.random.rand(order) # scale to the mean value Dv = [] for i in range(types + 1): Dv.append(Diag(1 - d) * D[i]) Dv[0] = Dv[0] + Diag(d) try: m = MarginalMomentsFromDMMAP(Dv, 1)[0] d = 1 - (1 - d) * m / mean for i in range(types + 1): D[i] = Diag(1 - d) * D[i] D[0] = D[0] + Diag(d) if CheckDMMAPRepresentation(D): return D except: pass trials += 1 raise Exception( "No feasible random DMAP/DMMAP found with such many zero entries! Try to increase the maxTrials parameter!" )
def LagkJointMomentsFromDMRAP(H, K=0, L=1): """ Returns the lag-L joint moments of a discrete marked rational arrival process. Parameters ---------- H : list/cell of matrices of shape(M,M), length(N) The H0...HN matrices of the DMRAP to check K : int, optional The dimension of the matrix of joint moments to compute. If K=0, the MxM joint moments will be computed. The default value is 0 L : int, optional The lag at which the joint moments are computed. The default value is 1 prec : double, optional Numerical precision to check if the input is valid. The default value is 1e-14 Returns ------- Nm : list/cell of matrices of shape(K+1,K+1), length(L) The matrices containing the lag-L joint moments, starting from moment 0. """ if butools.checkInput and not CheckDMRAPRepresentation(H): raise Exception( "LagkJointMomentsFromDMRAP: Input is not a valid DMRAP representation!" ) if K == 0: K = H[0].shape[0] - 1 M = len(H) - 1 H0 = H[0] sumH = SumMatrixList(H[1:]) H0i = la.inv(ml.eye(H0.shape[0]) - H0) P = H0i * sumH pi = DRPSolve(P) Pw = ml.eye(H0.shape[0]) H0p = [ml.matrix(Pw)] Pw = Pw * H0i H0p.append(Pw) for i in range(2, K + 1): Pw = Pw * i * H0i * H0 H0p.append(ml.matrix(Pw)) Pl = la.matrix_power(P, L - 1) Nm = [] for m in range(M): Nmm = ml.zeros((K + 1, K + 1)) for i in range(K + 1): for j in range(K + 1): Nmm[i, j] = np.sum(pi * H0p[i] * H0i * H[m + 1] * Pl * H0p[j]) row1 = np.array([MomsFromFactorialMoms(Nmm[0, 1:].A.flatten())]) col1 = np.array([MomsFromFactorialMoms(Nmm[1:, 0].A.flatten())]).T mid = JMomsFromJFactorialMoms(Nmm[1:, 1:]) Nm.append(np.bmat([[[[Nmm[0, 0]]], row1], [col1, mid]])) return Nm
def SamplesFromDMMAP(D, k, initial=None): """ Generates random samples from a discrete marked Markovian arrival process. Parameters ---------- D : list of matrices of shape(M,M), length(N) The D0...DN matrices of the DMMAP K : integer The number of samples to generate. prec : double, optional Numerical precision to check if the input DMMAP is valid. The default value is 1e-14. Returns ------- x : matrix, shape(K,2) The random samples. Each row consists of two columns: the (discrete) inter-arrival time and the type of the arrival. """ if butools.checkInput and not CheckDMMAPRepresentation(D): raise Exception( "SamplesFromDMMAP: Input is not a valid DMMAP representation!") N = D[0].shape[0] if initial == None: # draw initial state according to the stationary distribution stst = DTMCSolve(SumMatrixList(D)).A.flatten() cummInitial = np.cumsum(stst) r = rand() state = 0 while cummInitial[state] <= r: state += 1 else: state = initial # auxilary variables sojourn = 1.0 / (1.0 - np.diag(D[0])) logp = np.log(np.diag(D[0])) nextpr = ml.matrix(np.diag(sojourn)) * D[0] nextpr = nextpr - ml.matrix(np.diag(np.diag(nextpr))) for i in range(1, len(D)): nextpr = np.hstack((nextpr, np.diag(sojourn) * D[i])) nextpr = np.cumsum(nextpr, 1) if len(D) > 2: x = np.empty((k, 2)) else: x = np.empty(k) for n in range(k): time = 0 # play state transitions while state < N: time += 1 + int(np.log(rand()) / logp[state]) r = rand() nstate = 0 while nextpr[state, nstate] <= r: nstate += 1 state = nstate if len(D) > 2: x[n, 0] = time x[n, 1] = state // N else: x[n] = time state = state % N return x