LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
qsys_mg1_psjf.m
1function [W, rho_total] = qsys_mg1_psjf(lambda, mu, cs)
2% QSYS_MG1_PSJF Compute mean response time for M/G/1/PSJF queue
3%
4% [W, RHO] = QSYS_MG1_PSJF(LAMBDA, MU, CS) computes the mean response time
5% for each job class in an M/G/1 queue with Preemptive Shortest Job First
6% (PSJF) scheduling.
7%
8% Under PSJF, priority is based on a job's original size (not remaining size).
9% Jobs with smaller original sizes always preempt jobs with larger sizes.
10%
11% For PSJF, the mean response time for a job of size x is given by
12% (Section 3.2 of Wierman-Harchol-Balter 2003):
13%
14% E[T(x)]^PSJF = (lambda * integral_0^x t^2*f(t)dt) / (2*(1-rho(x))^2)
15% + x / (1 - rho(x))
16%
17% where:
18% - rho(x) = lambda * integral_0^x t*f(t)dt (truncated load)
19% - f(t) is the service time density (mixture of exponentials)
20%
21% For exponential service, the expected response time for class k is computed
22% by integrating E[T(x)] over the exponential distribution of class k sizes.
23%
24% CLASSIFICATION (Wierman-Harchol-Balter 2003):
25% PSJF is "Always Unfair" - some job size is treated unfairly under all
26% loads and all service distributions.
27%
28% PARAMETERS:
29% lambda : Vector of arrival rates per class
30% mu : Vector of service rates per class
31% cs : Vector of coefficients of variation per class (cs=1 for exponential)
32%
33% RETURNS:
34% W : Vector of mean response times per class
35% rho : Overall system utilization (modified for Little's law)
36%
37% REFERENCES:
38% - A. Wierman and M. Harchol-Balter, "Classifying scheduling policies with
39% respect to unfairness in an M/GI/1", SIGMETRICS 2003, Section 3.2.
40% - L. Kleinrock, "Queueing Systems, Volume II: Computer Applications",
41% Wiley, 1976.
42%
43% Copyright (c) 2012-2026, Imperial College London
44% All rights reserved.
45
46% Ensure inputs are column vectors
47lambda = reshape(lambda, [], 1);
48mu = reshape(mu, [], 1);
49cs = reshape(cs, [], 1);
50
51% Validate input lengths
52if ~isequal(length(lambda), length(mu), length(cs))
53 error('qsys_mg1_psjf:InvalidInput', ...
54 'lambda, mu, and cs must have the same length');
55end
56
57% Validate positive values
58if any(lambda <= 0) || any(mu <= 0) || any(cs < 0)
59 error('qsys_mg1_psjf:InvalidInput', ...
60 'lambda and mu must be positive, cs must be non-negative');
61end
62
63K = length(lambda);
64
65% Overall utilization
66rho_total = sum(lambda ./ mu);
67
68% Stability check
69if rho_total >= 1
70 error('qsys_mg1_psjf:UnstableSystem', ...
71 sprintf('System is unstable: utilization rho = %g >= 1', rho_total));
72end
73
74% Check if all classes are exponential (cs = 1)
75if all(abs(cs - 1) < 1e-6)
76 % Use specialized formula for exponential service
77 W = qsys_mg1_psjf_exp(lambda, mu);
78else
79 % General case: use numerical integration
80 W = qsys_mg1_psjf_general(lambda, mu, cs);
81end
82
83% Compute rhohat = Q/(1+Q) to match qsys convention
84Q = sum(lambda .* W);
85rho_total = Q / (1 + Q);
86
87end
88
89function W = qsys_mg1_psjf_exp(lambda, mu)
90% Specialized PSJF formula for exponential service times
91%
92% For exponential service, we integrate E[T(x)] over the exponential
93% distribution of job sizes. The service time mixture PDF is:
94% f(t) = sum_i (lambda_i/lambda_total) * mu_i * exp(-mu_i * t)
95%
96% The expected response time for class k is:
97% E[T_k] = integral_0^inf E[T(x)] * f_k(x) dx
98%
99% where f_k(x) = mu_k * exp(-mu_k * x) and
100% E[T(x)] = x/(1-rho(x)) + m2(x)/(2*(1-rho(x))^2)
101
102K = length(lambda);
103lambda_total = sum(lambda);
104p = lambda / lambda_total; % mixing probabilities
105
106W = zeros(K, 1);
107
108for k = 1:K
109 % Integrate E[T(x)] * f_k(x) from 0 to infinity
110 % Use numerical integration with appropriate upper limit
111 mu_k = mu(k);
112
113 % Upper limit: 20 mean service times covers 99.9999998% of exponential
114 x_max = 20 / mu_k;
115
116 % Response time function for a job of size x
117 T_of_x = @(x) compute_psjf_response(x, lambda, mu, p, lambda_total);
118
119 % Exponential density for class k
120 f_k = @(x) mu_k * exp(-mu_k * x);
121
122 % Integrand: E[T(x)] * f_k(x)
123 integrand = @(x) T_of_x(x) .* f_k(x);
124
125 % Numerical integration
126 W(k) = integral(integrand, 0, x_max, 'RelTol', 1e-8, 'AbsTol', 1e-10);
127end
128
129end
130
131function T = compute_psjf_response(x, lambda, mu, p, lambda_total)
132% Compute PSJF response time E[T(x)] for a job of size x
133%
134% E[T(x)] = x/(1-rho(x)) + m2(x)/(2*(1-rho(x))^2)
135%
136% where:
137% rho(x) = lambda * integral_0^x t * f(t) dt
138% m2(x) = lambda * integral_0^x t^2 * f(t) dt
139%
140% For mixture of exponentials:
141% integral_0^x t * mu_i * exp(-mu_i*t) dt = 1/mu_i - (1/mu_i + x)*exp(-mu_i*x)
142% integral_0^x t^2 * mu_i * exp(-mu_i*t) dt = 2/mu_i^2 - (2/mu_i^2 + 2x/mu_i + x^2)*exp(-mu_i*x)
143
144K = length(lambda);
145
146% Handle vectorized x
147T = zeros(size(x));
148
149for j = 1:numel(x)
150 xj = x(j);
151
152 % Compute truncated first moment: integral_0^x t * f(t) dt
153 m1_x = 0;
154 for i = 1:K
155 mu_i = mu(i);
156 % integral_0^x t * mu_i * exp(-mu_i*t) dt
157 int_t = 1/mu_i - (1/mu_i + xj) * exp(-mu_i * xj);
158 m1_x = m1_x + p(i) * int_t;
159 end
160
161 % Truncated load
162 rho_x = lambda_total * m1_x;
163
164 % Compute truncated second moment: integral_0^x t^2 * f(t) dt
165 m2_x = 0;
166 for i = 1:K
167 mu_i = mu(i);
168 % integral_0^x t^2 * mu_i * exp(-mu_i*t) dt
169 int_t2 = 2/mu_i^2 - (2/mu_i^2 + 2*xj/mu_i + xj^2) * exp(-mu_i * xj);
170 m2_x = m2_x + p(i) * int_t2;
171 end
172
173 % Scale by lambda_total for m2 term
174 m2_x_scaled = lambda_total * m2_x;
175
176 % PSJF response time formula
177 if rho_x >= 1
178 T(j) = Inf;
179 else
180 T(j) = xj / (1 - rho_x) + m2_x_scaled / (2 * (1 - rho_x)^2);
181 end
182end
183
184end
185
186function W = qsys_mg1_psjf_general(lambda, mu, cs)
187% General PSJF formula for non-exponential service (numerical integration)
188% Uses Gamma approximation for service time distributions
189
190K = length(lambda);
191lambda_total = sum(lambda);
192
193% For non-exponential, use class-based approximation (original formula)
194% with numerical correction for variance
195
196mean_service = 1 ./ mu;
197[~, sort_idx] = sort(mean_service, 'ascend');
198
199lambda_sorted = lambda(sort_idx);
200mu_sorted = mu(sort_idx);
201cs_sorted = cs(sort_idx);
202
203rho_i = lambda_sorted ./ mu_sorted;
204
205W_sorted = zeros(K, 1);
206
207for k = 1:K
208 x = 1 / mu_sorted(k);
209 rho_x = sum(rho_i(1:k));
210
211 m2_x = 0;
212 for i = 1:k
213 E_S2_i = (1 + cs_sorted(i)^2) / mu_sorted(i)^2;
214 m2_x = m2_x + lambda_sorted(i) * E_S2_i;
215 end
216
217 if rho_x >= 1
218 W_sorted(k) = Inf;
219 else
220 waiting_term = m2_x / (2 * (1 - rho_x)^2);
221 service_term = x / (1 - rho_x);
222 W_sorted(k) = waiting_term + service_term;
223 end
224end
225
226[~, unsort_idx] = sort(sort_idx);
227W = W_sorted(unsort_idx);
228
229end