1function [G, lG] = pfqn_ncoi(Z, N, mu,
visits, options)
2% [G, LG] = PFQN_NCOI(Z, N, MU, OPTIONS)
4% Normalizing constant
for a closed product-
form queueing network that
5% comprises a single aggregated infinite-server (delay) node and an
6% arbitrary number of order-independent (OI) / pass-and-swap stations with
9% The OI stations are analyzed by the balanced-fairness recursion of
10% Bonald & Proutiere (2003),
"Insensitive bandwidth sharing in data
11% networks", combined with the multichain convolution over stations. For a
12% single OI station with rank rate mu(supp(n)) the balance function
is
13% Phi(0) = 1, Phi(n) = (1/mu(n)) *
sum_{r: n_r>0} Phi(n - e_r),
14% and G(N)
is obtained by convolving the per-station balance functions with
15% the multinomial delay
factor F_Z(n) = prod_r Z_r^{n_r} / n_r!,
16% g_0(n) = F_Z(n), g_m(n) =
sum_{0<=x<=n} Phi_m(x) g_{m-1}(n-x),
19% This
is a MACROSTATE routine: both the balance functions and the
20% convolution are tabulated over the count lattice 0 <= n <= N, never over
21% orderings. That
is legitimate exactly because an OI rate
is permutation-
22% invariant, so Phi(n) -- itself the sum of the ordered-prefix weights
23% prod_p 1/mu(c_1..c_p) over all orderings c of the multiset n -- closes on
24% the count vector. With a non-empty swap graph that closure fails and the
25% microstate routine PFQN_PAS_NC must be used instead.
27% COST. With L = prod_r (N_r+1) the balance functions cost O(M R L) and the
28% convolutions O(M
sum_{n<=N} prod_r (n_r+1)) = O(M prod_r (N_r+1)(N_r+2)/2),
29% i.e. the order of a load-dependent Buzen convolution: polynomial in the
30% population
for a fixed number of classes.
33% Z - (1 x R) think-time demand vector of the aggregated delay node.
34% Z(r) = 1/sigma_r
for a delay with per-
class rate sigma_r.
35% N - (1 x R) closed population vector, finite.
36% mu - cell array {1 x M} of function handles, one per OI station. Each
37% mu{m}(n) returns the total service rate of station m given the
38% per-
class occupancy (count) vector n (1 x R). For an order-
39% independent station
this rate depends only on the support of n
40% (which classes are present), i.e. mu{m}(n) = sum of the capacities
41% of the servers compatible with the classes present in n. A station
42% state whose rate
is non-positive
is unreachable and
is assigned a
43% zero balance value. May be empty to model a pure delay network.
44% options - solver options (optional, currently unused; accepted
for
45% signature parity with the other pfqn_* routines).
48% G - Normalizing constant G(N).
51% Example (IS + two OI stations, R classes):
52% oirate = @(n) sum(mu1(any(compat1(:, find(n>0)) ~= 0, 2)));
53% oirate2 = @(n) sum(mu2(any(compat2(:, find(n>0)) ~= 0, 2)));
54% G = pfqn_ncoi(1./sigma, N, {oirate, oirate2});
56% See also PFQN_PAS_NC, PFQN_OI_FNC, PFQN_OI_INSVC, PFQN_MVAOI.
58% Copyright (c) 2012-2026, Imperial College London
62 options =
struct(); %#ok<NASGU>
67if nargin < 3 || isempty(mu)
79 line_error(mfilename,
'Z and N must have the same number of classes.');
82 line_error(mfilename,
'pfqn_ncoi requires finite (closed) populations.');
89% Per-OI-station
class visit ratios. Default unit
visits reproduce the plain
90% rank-rate balance; general
visits enter as a per-
class weight on the
91% balanced-fairness recurrence, Phi^v(n)=(1/mu(n)) sum_r v_r Phi^v(n-e_r), the
92% v-weighted balance whose
class-r geometric
factor prod_r v_r^{n_r} carries
93% the OI-station visit ratio (see _kb/06-solver-catalog.md, NC OI analyzer).
94if nargin < 4 || isempty(
visits)
95 visits = repmat({ones(1, R)}, 1, M);
98 for mm = 1:M,
visits{mm} = vmat(mm, :); end
101% Count lattice 0 <= n <= N, flattened
column-major; lin(v) = 1 + sum(v.*strides)
102%
is affine, so lin(x+y) = lin(x) + lin(y) - 1, which the convolution exploits.
105strides = [1, cumprod(dims(1:end-1))];
106counts = zeros(ngrid, R);
109 [sub{:}] = ind2sub(dims, k);
110 counts(k, :) = [sub{:}] - 1;
112[~, ord] = sort(sum(counts, 2)); % population-increasing sweep order
114% Delay balance function: the multinomial
factor F_Z(n). A
class with
115% population but no delay demand makes the state infeasible (weight zero).
127 logf = logf + v(r) * log(Z(r)) - gammaln(v(r) + 1);
135% Convolve in one OI station at a time.
137 Phim = oi_nc_balance(counts, ord, strides, mu{m}, R, ngrid,
visits{m});
138 gnext = zeros(ngrid, 1);
146 % Linear indices of the sub-box 0 <= y <= rem, built by mixed radix.
149 ylin = bsxfun(@plus, ylin(:), strides(d) * (0:rem(d)));
152 base = 1 + sum(x .* strides);
153 gnext(base + ylin - 1) = gnext(base + ylin - 1) + px * g(ylin);
162function Phi = oi_nc_balance(counts, ord, strides, murate, R, ngrid, vis)
163% v-weighted balanced-fairness recursion
164% Phi(n) = (1/mu(n))
sum_{r: n_r>0} v_r Phi(n-e_r), over the count lattice,
165% swept in population-increasing order. vis
is the 1xR
class visit vector.
166if nargin < 7 || isempty(vis), vis = ones(1, R); end
167Phi = zeros(ngrid, 1);
177 continue % unreachable station state: zero balance value
182 acc = acc + vis(r) * Phi(k - strides(r));