LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
map_m1ps_cdfrespt.m
1function [W_bar, W_bar_n] = map_m1ps_cdfrespt(C, D, mu, x, varargin)
2% MAP_M1PS_CDFRESPT Compute sojourn time distribution in MAP/M/1-PS queue
3%
4% W_bar = MAP_M1PS_CDFRESPT(C, D, mu, x) computes the complementary
5% distribution function of the sojourn time in a MAP/M/1 processor-sharing
6% queue at the points specified in x.
7%
8% [W_bar, W_bar_n] = MAP_M1PS_CDFRESPT(C, D, mu, x) also returns the
9% conditional complementary distributions W_bar_n{i} for customers finding
10% i-1 customers in the system on arrival.
11%
12% [...] = MAP_M1PS_CDFRESPT(C, D, mu, x, 'Param', Value) specifies optional
13% parameters:
14% 'Epsilon' - Truncation parameter for queue length (default: 1e-11)
15% 'EpsilonPrime' - Truncation parameter for uniformization (default: 1e-10)
16% 'Verbose' - Display computation progress (default: false)
17%
18% Input:
19% C - M x M matrix governing MAP transitions without arrivals
20% D - M x M matrix governing MAP transitions with arrivals
21% mu - Service rate (scalar, mu > 0)
22% x - Vector of time points at which to evaluate W_bar(x) = Pr[W > x]
23%
24% Output:
25% W_bar - Vector of same size as x, containing Pr[W > x]
26% W_bar_n - Cell array of conditional distributions (optional)
27%
28% The processor-sharing (PS) discipline shares the server equally among
29% all customers. When n customers are present, each receives service at
30% rate 1/n.
31%
32% The algorithm implements Theorem 1 from:
33% Masuyama, H., & Takine, T. (2003). Sojourn time distribution in a
34% MAP/M/1 processor-sharing queue. Operations Research Letters, 31(6),
35% 406-412.
36%
37% Example:
38% % M/M/1-PS queue with lambda=0.8, mu=1
39% lambda = 0.8; mu = 1;
40% C = -lambda; D = lambda; % Poisson arrivals
41% x = linspace(0, 10, 100);
42% W_bar = map_m1ps_cdfrespt(C, D, mu, x);
43% plot(x, W_bar);
44% xlabel('x'); ylabel('Pr[W > x]');
45% title('Sojourn time distribution for M/M/1-PS');
46
47% Copyright (c) 2012-2025, Imperial College London
48% All rights reserved.
49
50%% Parse input arguments
51p = inputParser;
52addRequired(p, 'C', @(x) ismatrix(x) && size(x,1) == size(x,2));
53addRequired(p, 'D', @(x) ismatrix(x) && size(x,1) == size(x,2));
54addRequired(p, 'mu', @(x) isscalar(x) && x > 0);
55addRequired(p, 'x', @(x) isnumeric(x) && all(x >= 0));
56addParameter(p, 'Epsilon', 1e-11, @(x) isscalar(x) && x > 0 && x < 1);
57addParameter(p, 'EpsilonPrime', 1e-10, @(x) isscalar(x) && x > 0 && x < 1);
58addParameter(p, 'Verbose', false, @islogical);
59
60parse(p, C, D, mu, x, varargin{:});
61epsilon = p.Results.Epsilon;
62epsilon_prime = p.Results.EpsilonPrime;
63verbose = p.Results.Verbose;
64
65%% Validate inputs
66M = size(C, 1);
67if size(D, 1) ~= M || size(D, 2) ~= M
68 error('MAP_M1PS_CDFRESPT:DimensionMismatch', 'C and D must have the same size');
69end
70
71I = eye(M);
72e = ones(M, 1);
73
74%% Compute MAP parameters
75% Stationary probability vector pi of the underlying Markov chain
76% Solve: pi*(C + D) = 0, pi*e = 1
77Q = C + D;
78% Replace last row of Q with normalization constraint
79A = Q';
80A(end,:) = e';
81b = zeros(M, 1);
82b(end) = 1;
83pi = (A \ b)';
84
85% Mean arrival rate
86lambda = pi * D * e;
87
88if verbose
89 fprintf('MAP/M/1-PS Sojourn Time Computation\n');
90 fprintf(' M (states): %d\n', M);
91 fprintf(' lambda (arrival rate): %.4f\n', lambda);
92 fprintf(' mu (service rate): %.4f\n', mu);
93 fprintf(' rho (utilization): %.4f\n', lambda/mu);
94end
95
96% Check stability condition
97rho = lambda / mu;
98if rho >= 1
99 error('MAP_M1PS_CDFRESPT:Unstable', ...
100 'System is unstable (rho = %.4f >= 1)', rho);
101end
102
103%% Compute R matrix
104if verbose
105 fprintf('Computing R matrix...\n');
106end
107R = compute_R_matrix(C, D, mu);
108
109if verbose
110 fprintf(' R = %.6f\n', R);
111end
112
113%% Determine truncation point N(epsilon) for queue length
114% Find minimum N such that: (1/lambda) * sum_{n=0}^N pi_0 * R^n * D * e > 1 - epsilon
115% where pi_0 = pi * (I - R)
116pi_0 = pi * (I - R);
117
118% Compute spectral radius of R to estimate required N
119rho_R = max(abs(eig(R)));
120
121if rho_R >= 1
122 error('MAP_M1PS_CDFRESPT:UnstableR', 'R matrix has spectral radius >= 1');
123end
124
125% Estimate N based on spectral radius:
126% We need rho_R^N < epsilon * (1 - rho_R)
127% N > log(epsilon * (1 - rho_R)) / log(rho_R)
128if rho_R > 0
129 N_estimate = ceil(log(epsilon * (1 - rho_R)) / log(rho_R));
130else
131 N_estimate = 1;
132end
133
134% Cap at reasonable maximum to avoid excessive computation
135N_max = 10000;
136N_epsilon = min(max(N_estimate, 10), N_max);
137
138if verbose
139 fprintf(' Spectral radius of R: %.6f\n', rho_R);
140 fprintf(' Estimated N: %d, using N(epsilon): %d (capped at %d)\n', N_estimate, N_epsilon, N_max);
141end
142
143%% Compute uniformization parameter theta
144theta = max(abs(diag(C)));
145
146%% Initialize output
147x = x(:)'; % Ensure row vector
148num_points = length(x);
149W_bar = zeros(1, num_points);
150
151if nargout > 1
152 W_bar_n = cell(N_epsilon + 1, 1);
153 for n = 0:N_epsilon
154 W_bar_n{n+1} = zeros(1, num_points);
155 end
156end
157
158%% Compute sojourn time distribution for each x
159for idx = 1:num_points
160 x_val = x(idx);
161
162 % Determine truncation points L and R_upper for uniformization
163 % Find L and R_upper such that: sum_{k=L}^R_upper Poisson(theta+mu, x_val) > 1 - epsilon_prime
164 mean_val = (theta + mu) * x_val;
165
166 % Use Poisson quantiles to find L and R_upper
167 if mean_val > 0
168 L = max(0, floor(mean_val - 10*sqrt(mean_val)));
169 R_upper = ceil(mean_val + 10*sqrt(mean_val));
170
171 % Refine to meet epsilon_prime requirement
172 pmf = poisspdf(L:R_upper, mean_val);
173 cumsum_pmf = sum(pmf);
174 while cumsum_pmf < 1 - epsilon_prime && R_upper < 10000
175 R_upper = R_upper + 10;
176 pmf = poisspdf(L:R_upper, mean_val);
177 cumsum_pmf = sum(pmf);
178 end
179 else
180 L = 0;
181 R_upper = 0;
182 end
183
184 K_max = R_upper;
185
186 if verbose && idx == 1
187 fprintf(' K(epsilon_prime): %d (uniformization truncation)\n', K_max);
188 end
189
190 % Compute h_{n,k} for n=0,...,N_epsilon and k=0,...,K_max
191 if verbose && idx == 1
192 fprintf('Computing h_{n,k} recursion...\n');
193 end
194 h = compute_h_recursive(C, D, mu, N_epsilon, K_max, theta);
195
196 % Compute W_bar(x) using equation (8)
197 % W_bar(x) = (1/lambda) * sum_{n=0}^{N} pi_0 * R^n * D * sum_{k=L}^{R} ...
198 % [(theta+mu)^k * x^k / k!] * exp(-(theta+mu)*x) * h_{n,k}
199
200 theta_plus_mu = theta + mu;
201
202 for n = 0:N_epsilon
203 % Compute pi_0 * R^n * D
204 if n == 0
205 weight = pi_0 * D;
206 R_power_n = 1;
207 else
208 R_power_n = R^n;
209 weight = pi_0 * R_power_n * D;
210 end
211
212 % Compute sum over k
213 sum_k = zeros(M, 1);
214 for k = L:K_max
215 % Use poisspdf to avoid numerical overflow with factorial
216 poisson_term = poisspdf(k, theta_plus_mu * x_val);
217 sum_k = sum_k + poisson_term * h{n+1, k+1};
218 end
219
220 term_n = (1/lambda) * weight * sum_k;
221 W_bar(idx) = W_bar(idx) + term_n;
222
223 % Store conditional distribution if requested
224 if nargout > 1
225 W_bar_n{n+1}(idx) = sum(sum_k) / M; % Average over states
226 end
227 end
228end
229
230if verbose
231 fprintf('Computation complete.\n');
232end
233
234end
235
236%% ========================================================================
237% LOCAL HELPER FUNCTIONS
238% ========================================================================
239
240function R = compute_R_matrix(C, D, mu)
241% Compute rate matrix R for MAP/M/1 queue
242% Solves: D + R(C - mu*I) + mu*R^2 = O
243
244M = size(C, 1);
245I = eye(M);
246
247% For scalar case (M=1), use quadratic formula
248if M == 1
249 % mu*R^2 + (C - mu)*R + D = 0
250 a = mu;
251 b = C - mu;
252 c = D;
253 discriminant = b^2 - 4*a*c;
254
255 if discriminant < 0
256 error('compute_R_matrix:NoRealSolution', 'No real solution for R');
257 end
258
259 % Two solutions
260 R1 = (-b - sqrt(discriminant)) / (2*a);
261 R2 = (-b + sqrt(discriminant)) / (2*a);
262
263 % Choose minimal nonnegative solution
264 if R1 >= 0 && R1 < 1
265 R = R1;
266 elseif R2 >= 0 && R2 < 1
267 R = R2;
268 else
269 error('compute_R_matrix:NoValidSolution', 'No valid solution in [0,1) for R');
270 end
271else
272 % For matrix case, use fixed-point iteration
273 % From D + R*(C - mu*I) + mu*R^2 = 0, we can derive:
274 % R*(mu*I - C) = D + mu*R^2
275 % R = (D + mu*R^2) * inv(mu*I - C)
276 % which gives the fixed-point iteration: R_new = (D + mu*R_old^2) / (mu*I - C)
277
278 % Initial approximation
279 R = -D / (C - mu*I);
280 max_iter = 5000;
281 tol = 1e-10;
282
283 % Precompute (mu*I - C) for efficiency
284 muI_minus_C = mu*I - C;
285
286 for iter = 1:max_iter
287 R_old = R;
288 % Fixed-point iteration
289 R = (D + mu*(R*R)) / muI_minus_C;
290
291 % Check convergence
292 if norm(R - R_old, inf) < tol
293 break;
294 end
295 end
296
297 if iter == max_iter
298 warning('compute_R_matrix:SlowConvergence', ...
299 'R computation did not converge within %d iterations', max_iter);
300 end
301end
302
303% Ensure non-negativity (numerical errors might produce small negative values)
304R(R < 0) = 0;
305
306% Verify solution
307check = D + R*(C - mu*I) + mu*(R*R);
308if norm(check, inf) > 1e-4
309 warning('compute_R_matrix:LargeResidual', ...
310 'Large residual in R computation: ||residual|| = %e', norm(check, inf));
311end
312
313end
314
315function h = compute_h_recursive(C, D, mu, N, K, theta)
316% Recursive computation of h_{n,k} coefficients
317%
318% The h_{n,k} vectors satisfy the recursion (Theorem 1):
319% h_{n,0} = e (vector of ones), for n = 0, 1, ...
320% h_{n,k+1} = 1/(theta+mu) * [n*mu/(n+1) * h_{n-1,k} + (theta*I + C) * h_{n,k}
321% + D * h_{n+1,k}]
322% where h_{-1,k} = 0 for all k
323
324M = size(C, 1);
325I = eye(M);
326e = ones(M, 1);
327
328% Pre-compute constant matrices
329theta_plus_mu = theta + mu;
330theta_I_plus_C = theta * I + C;
331
332% Initialize cell array to store h_{n,k}
333% h{n+1, k+1} stores h_{n,k} (shift indices by 1)
334h = cell(N+1, K+1);
335
336% Base case: h_{n,0} = e for all n
337for n = 0:N
338 h{n+1, 1} = e;
339end
340
341% Recursive computation: fill column by column (increasing k)
342for k = 0:K-1
343 for n = 0:N
344 % Compute h_{n,k+1} using the recursion formula
345 % h_{n,k+1} = 1/(theta+mu) * [n*mu/(n+1) * h_{n-1,k}
346 % + (theta*I + C) * h_{n,k}
347 % + D * h_{n+1,k}]
348
349 term1 = zeros(M, 1);
350 term2 = theta_I_plus_C * h{n+1, k+1};
351 term3 = zeros(M, 1);
352
353 % First term: n*mu/(n+1) * h_{n-1,k}
354 if n > 0
355 term1 = (n * mu / (n + 1)) * h{n, k+1};
356 end
357
358 % Third term: D * h_{n+1,k}
359 if n < N
360 term3 = D * h{n+2, k+1};
361 end
362
363 h{n+1, k+2} = (term1 + term2 + term3) / theta_plus_mu;
364 end
365end
366
367end