1function [g, Xi, Phi] = pfqn_oi_insvc(oirate, N, options)
2% [G, XI, PHI] = PFQN_OI_INSVC(OIRATE, N, OPTIONS)
4% Conditional mean number of IN-SERVICE jobs per
class at an order-independent
5% (OI) station, as a function of
the per-
class count vector n. This
is the
6% quantity underlying
the LINE utilization convention at OI stations,
8% with c
the number of servers and sir_r
the number of
class-r jobs receiving a
9% strictly positive service rate.
11% In an OI station
the state
is the ordered list c = (c_1,...,c_n) of job
12% classes (position 1 = head) and
the job in position p
is served at
the rank
14% Delta_p(c) = mu(c_1..c_p) - mu(c_1..c_{p-1}),
15% so that
the total rate telescopes to mu(c). Position p
is IN SERVICE when
17% sir_r(c) = #{p : c_p = r, Delta_p(c) > 0}.
18% Note that sir_r counts JOBS, not servers: a single job served concurrently by
19% several compatible servers counts once. This matches
the definition used by
20%
the exact CTMC solver (State.toMarginal, PAS branch) and by LDES.
22% Because mu
is permutation-invariant (a function of
the count vector),
the
23% unnormalized weight of an ordering c of
the multiset n factorizes over its
24% prefixes as w(c) = prod_{p=1}^{|n|} 1/mu(n(c_1..c_p)), and
the OI balance
25% function
is Phi(n) = sum_{orderings c of n} w(c), which obeys
the standard
26% balanced-fairness recursion (condition on
the tail element c_{|n|}):
28% Phi(0) = 1, Phi(n) = (1/mu(n)) sum_{r: n_r>0} Phi(n - e_r).
30% Conditioning
the same way on
the tail element and using
31% sir_r(c) = sir_r(c_1..c_{|n|-1}) + [c_{|n|} = r] * 1{mu(n) > mu(n - e_r)}
32% gives
the companion recursion
for the sir-weighted balance
33% Xi_r(n) = sum_{orderings c of n} w(c) sir_r(c):
36% Xi_r(n) = (1/mu(n)) [ sum_{s: n_s>0} Xi_r(n - e_s)
37% + 1{n_r > 0} 1{mu(n) > mu(n - e_r)} Phi(n - e_r) ].
39% Given n, every ordering carries
the same
class-weight
factor prod_r x_r^{n_r},
40% so
the conditional law of
the ordering
is w(c)/Phi(n) and
42% E[sir_r | n] = Xi_r(n) / Phi(n) =: g_r(n),
44% a function of
the count vector alone. The station
's in-service mean then
45% follows from the count marginal pM by E[sir_r] = sum_n pM(n) g_r(n), or, in
46% normalizing-constant form, from the functional-server identity of
47% PFQN_OI_FNC applied to f(n) = g_r(n) (note g_r(0) = 0, as required).
50% oirate - function handle mu(n) returning the OI total service rate for the
51% per-class count vector n (1 x R). mu(0) is taken as 0.
52% N - (1 x R) closed population vector, finite.
53% options - solver options (optional, currently unused).
56% g - (prod(N+1) x R) table, column-major over the lattice 0 <= n <= N, with
57% g(1 + sum(n .* stride), r) = E[sir_r | n].
58% Xi - (prod(N+1) x R) table with the sir-weighted balance Xi_r(n).
59% Phi - (prod(N+1) x 1) table with the OI balance function Phi(n).
61% See also PFQN_OI_FNC, PFQN_OI_NC, PFQN_MVAOI, PFQN_MVAOI_MARG.
63% Copyright (c) 2012-2026, Imperial College London
67 options = struct(); %#ok<NASGU>
69if ~isa(oirate, 'function_handle
')
70 line_error(mfilename, 'oirate must be a function handle mu(n).
');
73if any(~isfinite(N)) || any(N < 0)
74 line_error(mfilename, 'pfqn_oi_insvc requires finite nonnegative populations.');
80 stride(d) = stride(d-1) * shp(d-1);
84% Decode
the lattice once and tabulate
the rank rate mu(n).
85subs = zeros(total, R);
89 subs(i, d) = mod(li, shp(d));
90 li = floor(li / shp(d));
95 if sum(subs(i, :)) > 0
96 muv(i) = oirate(subs(i, :));
100Phi = zeros(total, 1);
110 % Unreachable state (no server can serve this composition): zero weight.
118 sPhi = sPhi + Phi(j);
119 sXi = sXi + Xi(j, :);
128 acc = acc + Phi(j); %
the tail class-r job
is in service
131 Xi(i, r) = acc / mun;
138 g(i, :) = Xi(i, :) / Phi(i);