LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
qsys_dmc.m
1function result = qsys_dmc(lambda_arr, mu, c, varargin)
2% QSYS_DMC Analyzes a D/M/c queue (deterministic interarrivals, exp service).
3%
4% RESULT = QSYS_DMC(LAMBDA, MU, C) returns time-average performance metrics
5% by embedding the system at arrival epochs and integrating over the
6% inter-arrival cycle. The death-only sub-generator A[m,m-1] = min(m,c)*MU
7% encodes service completions; X_{n+1} = expm(A*s)[X_n+1, :].
8%
9% Optional name-value parameters:
10% 'truncation' - state-space truncation (default auto)
11% 'quadSteps' - trapezoidal-rule steps over a cycle (default 200)
12%
13% RESULT struct fields:
14% meanQueueLength - time-average E[N]
15% meanWaitingQueue - time-average Lq = E[(N-c)+]
16% meanWaitingTime - Wq = Lq / lambda
17% meanSojournTime - Wq + 1/MU
18% utilization - rho = lambda / (c*mu)
19% analyzer - identifier
20%
21% See also qsys_mapdc, qsys_mdc_crommelin
22
23p = inputParser;
24addParameter(p, 'truncation', -1);
25addParameter(p, 'quadSteps', 200);
26parse(p, varargin{:});
27truncation = p.Results.truncation;
28quadSteps = p.Results.quadSteps;
29
30if lambda_arr <= 0
31 line_error(mfilename, 'Arrival rate must be positive');
32end
33if mu <= 0
34 line_error(mfilename, 'Service rate must be positive');
35end
36if c < 1
37 line_error(mfilename, 'Number of servers must be >= 1');
38end
39rho = lambda_arr / (c * mu);
40if rho >= 1 - 1e-12
41 line_error(mfilename, sprintf('Load rho=%g must be strictly less than 1', rho));
42end
43
44s = 1.0 / lambda_arr;
45
46if truncation > 0
47 nMax = truncation;
48else
49 nMax = max(200, min(2500, floor(15.0 / (1.0 - rho)) + 200));
50end
51n = nMax + 1;
52
53% Death-only sub-generator
54A = zeros(n);
55for m = 0:nMax
56 rate = min(m, c) * mu;
57 A(m+1, m+1) = -rate;
58 if m > 0
59 A(m+1, m) = rate;
60 end
61end
62
63expAs = expm(A * s);
64expAdt = expm(A * (s / quadSteps));
65
66% Embedded DTMC at arrival epochs: row X (1-indexed) represents
67% "number in system before arrival = X-1". After arrival the state is
68% min(X, n-1) which corresponds to row min(X, n-1) + 1 of expAs.
69yIdx = min((1:n), n - 1) + 1;
70P = zeros(n);
71for X = 1:n
72 Y = yIdx(X);
73 P(X, :) = expAs(Y, :);
74end
75
76% Stationary at arrival epochs: solve (P^T - I) pi = 0 with sum pi = 1
77M = P' - eye(n);
78M(end, :) = 1.0;
79b = zeros(n, 1); b(end) = 1.0;
80piArr = M \ b;
81
82% Time-average via cycle integration
83weightsLq = max((0:nMax) - c, 0);
84weightsN = (0:nMax);
85
86LqAtT = zeros(n, quadSteps + 1);
87NAtT = zeros(n, quadSteps + 1);
88expAt = eye(n);
89for k = 0:quadSteps
90 if k > 0
91 expAt = expAt * expAdt;
92 end
93 LqAtT(:, k+1) = expAt * weightsLq';
94 NAtT(:, k+1) = expAt * weightsN';
95end
96ts = linspace(0, s, quadSteps + 1);
97LqInt = trapz(ts, LqAtT, 2) / s;
98NInt = trapz(ts, NAtT, 2) / s;
99
100LqTime = sum(piArr .* LqInt(yIdx));
101NTime = sum(piArr .* NInt(yIdx));
102Wq = LqTime / lambda_arr;
103W = Wq + 1.0 / mu;
104
105result = struct();
106result.meanQueueLength = NTime;
107result.meanWaitingQueue = LqTime;
108result.meanWaitingTime = Wq;
109result.meanSojournTime = W;
110result.utilization = rho;
111result.analyzer = sprintf('Crommelin-DMc:c=%d', c);
112
113end