1function [W_bar, W_bar_n] = map_m1ps_sojourn(C, D, mu, x, varargin)
2% MAP_M1PS_SOJOURN Compute sojourn time distribution in MAP/M/1-PS queue
4% W_bar = MAP_M1PS_SOJOURN(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.
8% [W_bar, W_bar_n] = MAP_M1PS_SOJOURN(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.
12% [...] = MAP_M1PS_SOJOURN(C, D, mu, x,
'Param', Value) specifies optional
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)
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]
25% W_bar - Vector of same size as x, containing Pr[W > x]
26% W_bar_n - Cell array of conditional distributions (optional)
28% The processor-sharing (PS) discipline shares the server equally among
29% all customers. When n customers are present, each receives service at
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),
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_sojourn(C, D, mu, x);
44% xlabel(
'x'); ylabel(
'Pr[W > x]');
45% title(
'Sojourn time distribution for M/M/1-PS');
47% See also: MAP_M1PS_H_RECURSIVE, MAP_COMPUTE_R
49% Copyright (c) 2012-2025, Imperial College London
52%% Parse input arguments
54addRequired(p,
'C', @(x) ismatrix(x) && size(x,1) == size(x,2));
55addRequired(p,
'D', @(x) ismatrix(x) && size(x,1) == size(x,2));
56addRequired(p,
'mu', @(x) isscalar(x) && x > 0);
57addRequired(p,
'x', @(x) isnumeric(x) && all(x >= 0));
58addParameter(p,
'Epsilon', 1e-11, @(x) isscalar(x) && x > 0 && x < 1);
59addParameter(p,
'EpsilonPrime', 1e-10, @(x) isscalar(x) && x > 0 && x < 1);
60addParameter(p,
'Verbose',
false, @islogical);
62parse(p, C, D, mu, x, varargin{:});
63epsilon = p.Results.Epsilon;
64epsilon_prime = p.Results.EpsilonPrime;
65verbose = p.Results.Verbose;
69if size(D, 1) ~= M || size(D, 2) ~= M
70 error(
'MAP_M1PS_SOJOURN:DimensionMismatch',
'C and D must have the same size');
76%% Compute MAP parameters
77% Stationary probability vector pi of the underlying Markov chain
78% Solve: pi*(C + D) = 0, pi*e = 1
88 fprintf(
'MAP/M/1-PS Sojourn Time Computation\n');
89 fprintf(
' M (states): %d\n', M);
90 fprintf(
' lambda (arrival rate): %.4f\n', lambda);
91 fprintf(
' mu (service rate): %.4f\n', mu);
92 fprintf(
' rho (utilization): %.4f\n', lambda/mu);
95% Check stability condition
98 error(
'MAP_M1PS_SOJOURN:Unstable', ...
99 'System is unstable (rho = %.4f >= 1)', rho);
104 fprintf(
'Computing R matrix...\n');
106R = map_compute_R(C, D, mu);
108%% Determine truncation point N(epsilon)
for queue length
109% Find minimum N such that: (1/lambda) * sum_{n=0}^N pi_0 * R^n * D * e > 1 - epsilon
110% where pi_0 = pi * (I - R)
116 cumsum_prob = cumsum_prob + (1/lambda) * pi_0 * (R^n) * D * e;
117 if cumsum_prob > 1 - epsilon
124 N_epsilon = 100; % Default fallback
125 warning(
'MAP_M1PS_SOJOURN:TruncationDefault', ...
126 'Could not determine N(epsilon), using default N=%d', N_epsilon);
130 fprintf(
' N(epsilon): %d (queue length truncation)\n', N_epsilon);
133%% Compute uniformization parameter theta
134theta = max(abs(diag(C)));
137x = x(:)
'; % Ensure row vector
138num_points = length(x);
139W_bar = zeros(1, num_points);
142 W_bar_n = cell(N_epsilon + 1, 1);
144 W_bar_n{n+1} = zeros(1, num_points);
148%% Compute sojourn time distribution for each x
149for idx = 1:num_points
152 % Determine truncation points L and R for uniformization
153 % Find L and R such that: sum_{k=L}^R Poisson(theta+mu, x_val) > 1 - epsilon_prime
154 mean_val = (theta + mu) * x_val;
156 % Use Poisson quantiles to find L and R
158 L = max(0, floor(mean_val - 10*sqrt(mean_val)));
159 R = ceil(mean_val + 10*sqrt(mean_val));
161 % Refine to meet epsilon_prime requirement
162 pmf = poisspdf(L:R, mean_val);
163 cumsum_pmf = sum(pmf);
164 while cumsum_pmf < 1 - epsilon_prime && R < 10000
166 pmf = poisspdf(L:R, mean_val);
167 cumsum_pmf = sum(pmf);
176 if verbose && idx == 1
177 fprintf(' K(epsilon_prime): %d (uniformization truncation)\n
', K_max);
180 % Compute h_{n,k} for n=0,...,N_epsilon and k=0,...,K_max
181 if verbose && idx == 1
182 fprintf('Computing h_{n,k} recursion...\n
');
184 h = map_m1ps_h_recursive(C, D, mu, N_epsilon, K_max);
186 % Compute W_bar(x) using equation (8)
187 % W_bar(x) = (1/lambda) * sum_{n=0}^{N} pi_0 * R^n * D * sum_{k=L}^{R} ...
188 % [(theta+mu)^k * x^k / k!] * exp(-(theta+mu)*x) * h_{n,k}
190 theta_plus_mu = theta + mu;
191 exp_factor = exp(-theta_plus_mu * x_val);
194 % Compute pi_0 * R^n * D
198 weight = pi_0 * (R^n) * D;
204 poisson_term = ((theta_plus_mu * x_val)^k / factorial(k)) * exp_factor;
205 sum_k = sum_k + poisson_term * h{n+1, k+1};
208 W_bar(idx) = W_bar(idx) + (1/lambda) * weight * sum_k;
210 % Store conditional distribution if requested
212 W_bar_n{n+1}(idx) = sum(sum_k) / M; % Average over states
218 fprintf('Computation complete.\n
');