1function [F, t, p] = qsys_ldps_workload(lambda, B, alpha, N, t, ngrid)
2% [F,t,p] = QSYS_LDPS_WORKLOAD(lambda,B,alpha,N,t) - Stationary distribution of
3%
the quantity of work in a single-stage load-dependent processor sharing
4% station with Poisson arrivals and blocking.
6% Assumed model (Cohen, 1979, Sect. 9;
the model of Sect. 7 with one stage):
7% - a single service stage fed by a Poisson arrival stream of rate lambda;
8% - blocking capacity N: a request arriving when N requests are already
9% present
is lost and leaves no trace on
the state;
10% - generalized processor sharing: when x requests are present each of them
11% accrues service at rate f(x), so
the stage completes work at total rate
12% x*f(x). This function
is parametrized by
the LINE load-dependent total
13% rate scaling alpha(x)=x*f(x), i.e.
the argument of setLoadDependence at
15% - required service times are i.i.d. with absolutely continuous
16% distribution B and finite mean beta.
17% The result
is insensitive to B beyond its shape only through
the equilibrium
18% residual distribution Psi below;
the state probabilities p depend on B only
21% Let psi_t denote
the total amount of service still to be given to
the
22% requests present at time t. Cohen (1979) eqs. (9.1)-(9.3) give
24% Pr{psi_t < psi} = sum_{h=0}^{N} p_h Psi^{h*}(psi),
25% p_h = (rho^h/h!) phi(h) / sum_{k=0}^{N} (rho^k/k!) phi(k), rho=lambda*beta
26% phi(h) = 1/prod_{k=1}^{h} f(k), phi(0)=1,
27% Psi(psi) = int_0^psi (1-B(v))/beta dv,
29% with Psi^{h*}
the h-fold convolution of Psi and Psi^{0*} degenerate at zero.
30% Substituting f(k)=alpha(k)/k
the factorial cancels, leaving
32% p_h propto rho^h / prod_{k=1}^{h} alpha(k),
34% which
is the familiar load-dependent birth-death form. Psi
is the
35% equilibrium (residual life) distribution of B, so psi_t
is a mixture of
36% h-fold convolutions of residual service times, with an atom p_0 at zero.
39% lambda : Poisson arrival rate (finite, positive)
40% B : Distribution
object for the required service time (continuous,
41% finite positive mean)
42% alpha : rate scaling alpha(n)=n*f(n)
for n=1..N (finite, positive)
43% N : blocking capacity (finite positive integer)
44% t : optional grid at which
the CDF
is returned. Default: an
45% automatically sized grid covering
the bulk of
the distribution.
46% ngrid : optional number of points of
the internal uniform quadrature
47% grid on which
the convolutions are formed. Default 2001.
49% F : F(j) = Pr{psi_t <= t(j)}. Note F(1)=p(1)=Pr{psi_t=0} when t(1)=0,
50% since
the workload has an atom at zero of size p_0.
51% t : grid at which F
is reported
52% p : (1,N+1) vector, p(h+1)=Pr{x_t=h},
the stationary number in system
54% This
is the model of Cohen (1979) Sect. 9 only. It
is not
the weighted
55% GPS/DPS discipline of SchedStrategy.GPS, whose per-class weights this
56% formula does not represent.
58% Reference: J.W. Cohen, "The multiple phase service network with generalized
59% processor sharing", Acta Informatica 12, 245-284 (1979), Sect. 9.
61% Copyright (c) 2012-2026, Imperial College London
65 line_error(mfilename,'Requires at least four inputs: lambda, B, alpha, N.');
68%% gating: reject anything outside
the assumed model
69if ~isnumeric(lambda) || ~isscalar(lambda) || ~isfinite(lambda) || lambda <= 0
70 line_error(mfilename,'lambda must be a finite positive scalar,
the rate of
the Poisson arrival stream.');
72if ~isa(B,'Distribution')
73 line_error(mfilename,'B must be a Distribution
object giving
the required service time.');
75if B.isDisabled() || B.isImmediate()
76 line_error(mfilename,'B must be an active service time distribution, not Disabled or Immediate.');
79 line_error(mfilename,'B must be a continuous distribution: Cohen (1979) Sect. 9 assumes an absolutely continuous required service time.');
82if ~isfinite(beta) || beta <= 0
83 line_error(mfilename,'B must have a finite positive mean.');
85if ~isnumeric(N) || ~isscalar(N) || ~isfinite(N) || N < 1 || N ~= round(N)
86 line_error(mfilename,'N must be a finite positive integer,
the blocking capacity of
the service stage.');
88if ~isnumeric(alpha) || ~isvector(alpha) || isempty(alpha)
89 line_error(mfilename,'alpha must be a numeric vector holding
the rate scaling alpha(n)=n*f(n).');
93 line_error(mfilename,sprintf('alpha must supply
the rate scaling for n=1..%d, but only %d entries were given.',N,numel(alpha)));
96if any(~isfinite(alpha)) || any(alpha <= 0)
97 line_error(mfilename,'alpha(n) must be finite and strictly positive for n=1..N, since every request in a busy stage
is served at a positive rate.');
100%% stationary number in system, eq. (9.1)
101% p_h propto rho^h/prod_{k<=h} alpha(k), accumulated in logs so that large
102% rho or large N
do not overflow before normalization.
104logw = [0, cumsum(log(rho) - log(alpha))];
105logw = logw - max(logw);
110% Psi has mean m1e,
the mean of
the equilibrium residual life of B. The
111% workload
is a mixture of h-fold convolutions of Psi, so sizing
the grid on
112%
the largest h carrying non-negligible mass covers
the bulk of
the support.
113m1e = beta * (1 + B.getSCV()) / 2;
114if ~isfinite(m1e) || m1e <= 0
115 line_error(mfilename,
'B must have a finite second moment: the equilibrium residual service time is otherwise undefined.');
117userGrid = nargin >= 5 && ~isempty(t);
119 if ~isnumeric(t) || ~isvector(t) || any(~isfinite(t)) || any(t < 0)
120 line_error(mfilename,'t must be a vector of finite non-negative times.');
128 hmax = find(p > 1e-12, 1, 'last') - 1;
129 if isempty(hmax) || hmax < 1
132 tmax = m1e * (hmax + 8*sqrt(hmax));
133 tmax = max(tmax, 8*m1e);
136% Internal uniform grid:
the convolutions below need a constant step. The
137% result
is interpolated back onto t when
the caller supplied one.
138% Accuracy
is second order in
the step for an absolutely continuous B,
the
139% case Cohen assumes. It falls back to first order when B has an atom, so
140% that 1-B
is discontinuous and
the equilibrium density
is a step: Det
is the
141% extreme case. Raise ngrid for those. Measured against closed forms,
the
142% error of F decays by 4.00x per grid doubling for Exp service (Erlang
143% mixture oracle) and by about 2x for Det service (Irwin-Hall mixture
144% oracle), confirming
the two regimes.
145if nargin < 6 || isempty(ngrid)
148if ~isnumeric(ngrid) || ~isscalar(ngrid) || ~isfinite(ngrid) || ngrid < 2 || ngrid ~= round(ngrid)
149 line_error(mfilename,'ngrid must be a finite integer of at least 2.');
151tg = linspace(0, tmax, ngrid);
154%% equilibrium residual service distribution, eq. (9.3)
155% Density of Psi
is (1-B(v))/beta. evalCDF
is not vectorized by every
156% Distribution subclass, so it
is evaluated pointwise.
157e = arrayfun(@(v) (1 - B.evalCDF(v)) / beta, tg);
159%% workload distribution, eq. (9.2)
160% F = sum_h p_h Psi^{h*}. The h=0 term
is degenerate at zero, contributing
the
161% atom p_0 over
the whole non-negative grid.
162Fg = p(1) * ones(1, ngrid);
166 dens = local_convtrap(dens, e, dt, ngrid);
168 Fg = Fg + p(h+1) * cumtrapz(tg, dens);
172 F = interp1(tg, Fg, t,
'linear');
179function c = local_convtrap(f, g, dt, n)
180% Convolution of two densities sampled on a uniform grid,
using the
181% trapezoidal rule rather than
the rectangle rule implied by a bare conv().
182% The correction matters here because
the equilibrium density does not vanish
183% at
the origin: e(0)=1/beta. Writing t_i=i*dt,
185% (f*g)(t_i) = int_0^{t_i} f(v) g(t_i-v) dv
186% ~ dt*[ sum_{j=0}^{i} f_j g_{i-j} - (f_0 g_i + f_i g_0)/2 ],
188% i.e. conv() less half of each endpoint. Without
the correction each
189% convolution over-counts by dt*f_0*g_i, which accumulates over h and drives
190%
the mixture CDF above one.
193c = c - dt * (f(1)*g(1:n) + f(1:n)*g(1)) / 2;