def test_map__sampling(d0, d1): NUM_SAMPLES = 100000 proc = MarkovArrival(d0, d1) samples = proc(NUM_SAMPLES) assert len(samples) == NUM_SAMPLES assert_allclose(np.mean(samples), proc.mean, rtol=0.05) assert_allclose(np.std(samples), proc.std, rtol=0.05) assert_allclose(np.var(samples), proc.var, rtol=0.05) assert_allclose( stats.lag(samples, 2), [proc.lag(1), proc.lag(2)], rtol=0.05 )
def test_map__invalid_matrices_call_fix_markovian_process(): d0 = np.asarray([[-0.9, -0.1], [0, -1]]) d1 = np.asarray([[0, 1.1], [1., 0.]]) with patch('pyqumo.arrivals.fix_markovian_arrival', return_value=((d0, d1), (0.1, 0.1))) as mock: _ = MarkovArrival(d0, d1, tol=0.2) mock.assert_called_once()
def departure(self) -> MarkovArrival: arrival, service = self._get_casted_arrival_and_service() # Aliasing matrices from arrival MAP and service PH d0 = arrival.d0 d1 = arrival.d1 w = arrival.order iw = np.eye(w) s = service.s tau = service.init_probs v = service.order iv = np.eye(v) ev = np.ones((v, 1)) m = self.capacity - 1 b = v * w ob = np.zeros((b, b)) # Building blocks d0_iv = np.kron(d0, iv) d1_iv = np.kron(d1, iv) d0_s = np.kron(d0, iv) + np.kron(iw, s) ct = np.kron(-s.dot(ev), tau) iw_ct = np.kron(iw, ct) r0 = np.kron(d1, np.kron(tau, ev)) ra = np.kron(d0 + d1, iv) + np.kron(iw, s) # Building departure D0 and D1 d0_dep = cbdiag(self.capacity, ((0, d0_s), (1, d1_iv))) d0_dep[m * b:, m * b:] = ra d0_left_col = np.vstack((d0_iv, ) + (ob, ) * self.capacity) d0_top_row = np.hstack((r0, ) + (ob, ) * m) d0_dep = np.hstack((d0_left_col, np.vstack((d0_top_row, d0_dep)))) D1_dep = cbdiag(self.capacity + 1, ((-1, iw_ct), )) return MarkovArrival(d0_dep, D1_dep)
def test_map__props(): d0 = [[-1, 0.5], [0.5, -1]] d1 = [[0, 0.5], [0.2, 0.3]] proc = MarkovArrival(d0, d1) assert_allclose(proc.generator, [[-1, 1], [0.7, -0.7]]) assert_allclose(proc.d0, d0) assert_allclose(proc.d(0), d0) assert_allclose(proc.d1, d1) assert_allclose(proc.d(1), d1) assert_allclose(proc.d(0), d0) assert proc.order == 2 # Test inverse of D0: assert_allclose(proc.d0n(-1), [[4/3, 2/3], [2/3, 4/3]]) assert_allclose(proc.d0n(-2), [[20/9, 16/9], [16/9, 20/9]]) # Test chains: assert_allclose(proc.ctmc.matrix, [[-1, 1], [0.7, -0.7]]) assert_allclose(proc.dtmc.matrix, [[2/15, 13/15], [4/15, 11/15]])
def departure(self): n = self.capacity a = self.arrival.rate b = self.service.rate d0 = cbdiag(n + 1, [(0, np.asarray([[-(a + b)]])), (1, np.asarray([[a]]))]) d0[0, 0] += b d0[n, n] += a d1 = cbdiag(n + 1, [(-1, np.asarray([[b]]))]) return MarkovArrival(d0, d1)
system_size_var=5.6015, queue_size_pmf=[ 0.09230753, 0.0630149, 0.07784193, 0.09615768, 0.11878301, 0.14673196, 0.18125713, 0.22390586 ], queue_size_avg=4.3708, queue_size_var=5.2010, utilization=0.9587, loss_prob=0.2239, bandwidth=32.5959, response_time=0.163, wait_time=0.134, ), '(MM1NQueue: arrival_rate=42, service_rate=34, capacity=8)'), # MAP/PH/1/N representation of M/M/1/N queue: (MapPh1NQueue(MarkovArrival.poisson(2), PhaseType.exponential(5), queue_capacity=4), QueueProps( arrival_rate=2, service_rate=5, departure_rate=1.9877, system_size_pmf=[0.6025, 0.2410, 0.0964, 0.0385, 0.0154, 0.0062], system_size_avg=0.6420, system_size_var=0.9624, queue_size_pmf=[0.8434, 0.0964, 0.0385, 0.0154, 0.0062], queue_size_avg=0.2444, queue_size_var=0.4284, utilization=0.3975, loss_prob=0.0062, bandwidth=1.9877,
# POISSON PROCESS # ####################### from pyqumo.random import Const, Uniform @pytest.mark.parametrize('proc, m1, m2, m3, l1, string', [ # Poisson process: (Poisson(1.0), 1, 2, 6, 0.0, '(Poisson: r=1)'), (Poisson(2.5), 0.4, 0.32, 0.384, 0.0, '(Poisson: r=2.5)'), # GI with uniform or constant distributions: (GIProcess(Const(3)), 3, 9, 27, 0, '(GI: f=(Const: value=3))'), (GIProcess(Uniform(2, 10)), 6, 124 / 3, 312, 0, '(GI: f=(Uniform: a=2, b=10))'), # MAP variants of Poisson or Erlang processes: ( MarkovArrival.poisson(2.5), 0.4, 0.32, 0.384, 0.0, '(MAP: d0=[[-2.5]], d1=[[2.5]])' ), ( MarkovArrival.erlang(3, rate=4.2), 0.714286, 0.680272, 0.809848, 0.0, '(MAP: d0=[[-4.2, 4.2, 0], [0, -4.2, 4.2], [0, 0, -4.2]], ' 'd1=[[0, 0, 0], [0, 0, 0], [4.2, 0, 0]])' ) ]) def test__props(proc, m1, m2, m3, l1, string): """ Validate basic statistical properties of the random process. """ # Compute basic props: rate = 1 / m1
], busy_avg=[1 / 10, 1 / 2, 1 / 4], busy_std=[3 / 10, 1 / 2, np.sqrt(3) / 4], # Scalar probabilities and rates: drop_prob=[0, 0, 0], delivery_prob=[1, 1, 1], utilization=[.1, .5, .25], # Intervals: departure_avg=[1, 1 / 3, 1 / 10], arrival_avg=[1, 1 / 3, 1 / 10], response_time_avg=[1 / 9, 1 / 3, 1 / 30], wait_time_avg=[1 / 90, 1 / 6, 1 / 120], delivery_delay_avg=[43 / 90, 11 / 30, 1 / 30]), TandemProps( arrival=[ MarkovArrival.poisson(1), None, None, HyperExponential([4.0], [1.0]) ], service=PhaseType.exponential(10), queue_capacity=np.inf, num_stations=4, # System and queue sizes: system_size_avg=[1 / 9, 1 / 9, 1 / 9, 1], system_size_std=[(10**.5) / 9, (10**.5) / 9, (10**.5) / 9, 2**.5], queue_size_avg=[1 / 90, 1 / 90, 1 / 90, 1 / 2], queue_size_std=[(109**.5) / 90, (109**.5) / 90, (109**.5) / 90, (5**.5) / 2], busy_avg=[.1, .1, .1, .5], busy_std=[.3, .3, .3, .5], # Scalar probabilities and rates: drop_prob=[0, 0, 0, 0],