LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
test_lossn_mci.m
1function test_lossn_mci()
2% TEST_LOSSN_MCI Validate Monte Carlo summation for loss networks
3% against exact enumeration, Erlang-B, and the Erlang fixed point.
4
5fprintf('=== test_lossn_mci ===\n');
6rng(12345);
7npass = 0; nfail = 0;
8
9% ---------------------------------------------------------------
10% Test 1: single-link Erlang-B (J=1, one class, unit demand)
11% Exact blocking = ErlangB(rho, C).
12% ---------------------------------------------------------------
13rho = 8; Ccap = 10;
14[~, Loss, lG, ci] = lossn_mci(rho, 1, Ccap, struct('samples',2e5,'seed',1));
15exactB = erlangB_ref(rho, Ccap);
16[gExact, ~] = lossn_exact(rho, 1, Ccap);
17fprintf('\n[T1] M/M/C/C Erlang-B rho=%g C=%d\n', rho, Ccap);
18fprintf(' blocking exact=%.6f mci=%.6f CI=[%.6f,%.6f]\n', ...
19 exactB, Loss, ci.loss(1,1), ci.loss(1,2));
20fprintf(' lG exact=%.6f mci=%.6f\n', log(gExact), lG);
21[npass,nfail] = check(npass, nfail, ci.loss(1,1) <= exactB && exactB <= ci.loss(1,2), 'T1 blocking in CI');
22[npass,nfail] = check(npass, nfail, abs(lG-log(gExact)) < 0.05, 'T1 lG matches exact');
23
24% ---------------------------------------------------------------
25% Test 2: two-link multirate network, exact enumeration
26% Link1 shared by both classes, class2 needs 2 circuits on link2.
27% ---------------------------------------------------------------
28nu = [3.0, 1.5];
29A = [1 1; 1 2]; % 2 links x 2 classes
30Cv = [4; 5];
31[gEx, betaEx] = lossn_exact(nu, A, Cv);
32[QLen, Loss, lG, ci] = lossn_mci(nu, A, Cv, struct('samples',3e5,'seed',2));
33fprintf('\n[T2] two-link multirate, exact enumeration\n');
34fprintf(' lG exact=%.6f mci=%.6f\n', log(gEx), lG);
35for r = 1:2
36 fprintf(' class %d: beta exact=%.6f mci=%.6f CI=[%.6f,%.6f]\n', ...
37 r, betaEx(r), Loss(r), ci.loss(r,1), ci.loss(r,2));
38 [npass,nfail] = check(npass, nfail, ...
39 ci.loss(r,1) <= betaEx(r) && betaEx(r) <= ci.loss(r,2), ...
40 sprintf('T2 class %d blocking in CI', r));
41end
42[npass,nfail] = check(npass, nfail, abs(lG-log(gEx)) < 0.05, 'T2 lG matches exact');
43% carried load consistency: QLen = nu*(1-beta)
44[npass,nfail] = check(npass, nfail, max(abs(QLen - nu.*(1-Loss))) < 1e-9, 'T2 QLen=nu*(1-beta)');
45
46% ---------------------------------------------------------------
47% Test 3: reproducibility with fixed seed
48% ---------------------------------------------------------------
49[~, L1] = lossn_mci(nu, A, Cv, struct('samples',5e4,'seed',7));
50[~, L2] = lossn_mci(nu, A, Cv, struct('samples',5e4,'seed',7));
51fprintf('\n[T3] reproducibility: max|L1-L2|=%.2e\n', max(abs(L1-L2)));
52[npass,nfail] = check(npass, nfail, isequal(L1,L2), 'T3 fixed seed reproducible');
53
54% ---------------------------------------------------------------
55% Test 4: paper star network (Figure 1, Table 1) light traffic.
56% 4 links, 12 classes. Compare against exact enumeration is
57% infeasible (>1e12 states); cross-check against Erlang FP order
58% of magnitude and that class-blocking CIs bracket the FP estimate
59% loosely (FP is an approximation, so only sanity, not equality).
60% ---------------------------------------------------------------
61[nu4, A4, C4] = star_network('light');
62% lossn_erlangfp returns blocking probability; convert to acceptance.
63% Blocking here is a deep-tail event (well below 1%), so cross-check the
64% well-conditioned acceptance probabilities of the two methods.
65[~, LossFP] = lossn_erlangfp(nu4, A4, C4);
66accFP = 1 - LossFP;
67[~, LossMC, lG4, ci4] = lossn_mci(nu4, A4, C4, struct('samples',2e5,'seed',3));
68accMC = 1 - LossMC;
69fprintf('\n[T4] star network (light traffic), lG=%.4f\n', lG4);
70fprintf(' class FP-accept MCI-accept MCI-beta%% MCI-CI%%\n');
71for r = 1:numel(nu4)
72 fprintf(' %5d %.6f %.6f %.4f [%.4f,%.4f]\n', r, accFP(r), accMC(r), ...
73 100*LossMC(r), 100*ci4.loss(r,1), 100*ci4.loss(r,2));
74end
75% All blocking probabilities must be valid probabilities.
76[npass,nfail] = check(npass, nfail, all(LossMC>=0 & LossMC<=1), 'T4 valid probabilities');
77% Two independent methods (Erlang FP vs Monte Carlo) must agree on the
78% well-conditioned acceptance probabilities.
79[npass,nfail] = check(npass, nfail, ...
80 max(abs(accMC - accFP)) < 0.02, 'T4 MCI vs FP acceptance agree');
81
82% ---------------------------------------------------------------
83% Test 5: variance reduction -- heuristic gamma vs gamma=nu (rho)
84% Section 3.2: importance sampling narrows CI in heavy traffic.
85% ---------------------------------------------------------------
86[nuH, AH, CH] = star_network('heavy');
87[~, ~, ~, ciIS] = lossn_mci(nuH, AH, CH, struct('samples',1e5,'seed',4));
88[~, ~, ~, ciRho] = lossn_mci(nuH, AH, CH, struct('samples',1e5,'seed',4,'gamma',nuH));
89wIS = mean(ciIS.accept(:,2) - ciIS.accept(:,1));
90wRho = mean(ciRho.accept(:,2) - ciRho.accept(:,1));
91fprintf('\n[T5] heavy traffic mean CI width: gamma=heuristic %.5f, gamma=rho %.5f (imp=%.2fx)\n', ...
92 wIS, wRho, wRho/wIS);
93[npass,nfail] = check(npass, nfail, wIS <= wRho*1.02, 'T5 heuristic gamma not worse than rho');
94
95fprintf('\n=== RESULT: %d passed, %d failed ===\n', npass, nfail);
96if nfail > 0
97 error('test_lossn_mci: %d checks failed', nfail);
98end
99end
100
101% ---------------------------------------------------------------
102function [np, nf] = check(np, nf, cond, name)
103if cond
104 np = np + 1; fprintf(' PASS: %s\n', name);
105else
106 nf = nf + 1; fprintf(' FAIL: %s\n', name);
107end
108end
109
110function [g, beta] = lossn_exact(nu, A, C)
111% Exact normalization constant and class blocking by box enumeration.
112nu = nu(:)'; C = C(:);
113R = numel(nu); J = numel(C);
114N = zeros(1,R);
115for k = 1:R
116 pos = A(:,k) > 0;
117 N(k) = floor(min(C(pos)./A(pos,k)));
118end
119% enumerate all n in box {0..N_k}
120grids = cell(1,R);
121for k = 1:R, grids{k} = 0:N(k); end
122[out{1:R}] = ndgrid(grids{:});
123States = zeros(numel(out{1}), R);
124for k = 1:R, States(:,k) = out{k}(:); end
125% product-form weight q(n) = prod nu^n / n!
126logq = States * log(nu(:)) - sum(gammaln(States+1), 2);
127AV = States * A';
128feas = all(AV <= C(:)', 2);
129mq = max(logq(feas));
130g = exp(mq) * sum(exp(logq(feas) - mq));
131beta = zeros(1,R);
132for r = 1:R
133 Cr = (C - A(:,r))';
134 feasR = all(AV <= Cr, 2);
135 gr = exp(mq) * sum(exp(logq(feasR) - mq));
136 beta(r) = 1 - gr/g;
137end
138end
139
140function b = erlangB_ref(rho, C)
141% Reference Erlang-B via stable recursion.
142inv = 1;
143for k = 1:C
144 inv = 1 + inv * k / rho;
145end
146b = 1 / inv;
147end
148
149function [nu, A, C] = star_network(regime)
150% Four-leaf star network of Ross-Wang Table 1 / Figure 1.
151% Links C1=90,C2=100,C3=110,C4=120. Six leaf pairs, two classes each
152% (1 circuit and 5 circuits) -> 12 classes. Routes as in Table 1.
153C = [90; 100; 110; 120];
154routes = [1 2; 1 3; 1 4; 2 3; 2 4; 3 4]; % 6 pairs
155switch regime
156 case 'light', base = 9.0; hi = 1.6;
157 case 'moderate', base = 10.0; hi = 2.0;
158 case 'heavy', base = 15.0; hi = 3.0;
159 otherwise, error('unknown regime');
160end
161K = 12;
162A = zeros(4, K);
163nu = zeros(1, K);
164for p = 1:6
165 % 1-circuit class
166 A(routes(p,1), p) = 1; A(routes(p,2), p) = 1; nu(p) = base;
167 % 5-circuit class
168 A(routes(p,1), 6+p) = 5; A(routes(p,2), 6+p) = 5; nu(6+p) = hi;
169end
170end
Definition Station.m:245