LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
lossn_mci.m
1%{ @file lossn_mci.m
2 % @brief Monte Carlo importance-sampling summation for loss networks
3 %
4 % @author LINE Development Team
5%}
6
7%{
8 % @brief Estimates the product-form normalization constant and class
9 % blocking probabilities of a loss network by Monte Carlo summation.
10 %
11 % @details
12 % Implements the importance-sampling Monte Carlo summation method of
13 % Ross and Wang, "Monte Carlo Summation Applied to Product-Form Loss
14 % Networks", Probability in the Engineering and Informational Sciences,
15 % 6 (1992), 323-348.
16 %
17 % A loss network has links j=1..J with capacity C(j) and classes (routes)
18 % r=1..R with offered load nu(r) and per-link circuit requirement A(j,r).
19 % The state n=(n_1,..,n_R) is feasible iff A*n <= C (set Omega). The
20 % equilibrium distribution is product form with normalization constant
21 % g(C) = sum_{n in Omega} prod_r nu(r)^n_r / n_r! .
22 % The class-r acceptance probability is 1-beta_r = g(C-A(:,r))/g(C).
23 %
24 % States are sampled from the importance distribution (Eq. 6)
25 % p(n) = (1/c) prod_r gamma_r^n_r / n_r!, n in {0..N_1}x..x{0..N_R},
26 % with N_r = min_j floor(C_j/A_jr) over A_jr>0. Ratio estimators (Eq. 8)
27 % give unbiased/consistent g and consistent blocking with delta-method
28 % confidence intervals.
29 %
30 % @par Syntax:
31 % @code
32 % [QLen, Loss, lG, ci, nsamples] = lossn_mci(nu, A, C)
33 % [QLen, Loss, lG, ci, nsamples] = lossn_mci(nu, A, C, options)
34 % @endcode
35 %
36 % @par Parameters:
37 % <table>
38 % <tr><th>Name<th>Description
39 % <tr><td>nu<td>Offered load of route (class) r (1xR vector)
40 % <tr><td>A<td>Circuit requirement of link j for route r (JxR matrix)
41 % <tr><td>C<td>Available capacity of link j (Jx1 vector)
42 % <tr><td>options<td>struct with optional fields: samples (default 1e5),
43 % gamma (1xR importance params, default Sec. 3.4
44 % heuristic), seed (rng seed), alpha (CI level,
45 % default 0.05)
46 % </table>
47 %
48 % @par Returns:
49 % <table>
50 % <tr><th>Name<th>Description
51 % <tr><td>QLen<td>Mean carried load (E[n_r]) for route r (1xR)
52 % <tr><td>Loss<td>Blocking probability beta_r for route r (1xR)
53 % <tr><td>lG<td>Log of the estimated normalization constant g(C)
54 % <tr><td>ci<td>struct with confidence intervals and point estimates:
55 % .accept (Rx2), .loss (Rx2), .acceptPoint (1xR),
56 % .lossPoint (1xR), .level (1-alpha)
57 % <tr><td>nsamples<td>Number of Monte Carlo samples used
58 % </table>
59%}
60function [QLen, Loss, lG, ci, nsamples] = lossn_mci(nu, A, C, options)
61if nargin < 4 || isempty(options)
62 options = struct();
63end
64nu = nu(:)'; % 1xR
65C = C(:); % Jx1
66R = numel(nu);
67J = numel(C);
68if size(A,1) ~= J || size(A,2) ~= R
69 line_error(mfilename, sprintf('A must be %dx%d (J x R).', J, R));
70end
71
72nsamples = getfielddef(options, 'samples', 1e5);
73alpha = getfielddef(options, 'alpha', 0.05);
74seed = getfielddef(options, 'seed', []);
75gamma = getfielddef(options, 'gamma', []);
76if ~isempty(seed)
77 rng(seed);
78end
79S = nsamples;
80
81% Per-class maximum feasible occupancy N_r = min_j floor(C_j/A_jr)
82N = zeros(1, R);
83for k = 1:R
84 pos = A(:,k) > 0;
85 if any(pos)
86 N(k) = floor(min(C(pos) ./ A(pos, k)));
87 else
88 N(k) = 0; % class uses no link: cannot admit connections
89 end
90end
91
92% Importance-sampling parameters gamma (Section 3.4 heuristic)
93if isempty(gamma)
94 load_j = zeros(J, 1);
95 for j = 1:J
96 load_j(j) = sum(A(j,:) .* nu) / C(j);
97 end
98 delta = max(load_j);
99 b = max(A, [], 1); % 1xR, b_k = max_j A_jk
100 base = 1 - 0.15 * (1 - delta);
101 base = max(base, 1e-6);
102 gamma = nu .* (base .^ b);
103end
104gamma = gamma(:)';
105gamma = max(gamma, 1e-300);
106
107% Normalization constant c of the importance distribution (log space)
108log_c = 0;
109for k = 1:R
110 l = 0:N(k);
111 logterms = l * log(gamma(k)) - gammaln(l + 1);
112 log_c = log_c + logsumexp(logterms);
113end
114
115% Draw S i.i.d. samples V (S x R), each column truncated Poisson(gamma_k)
116V = zeros(S, R);
117for k = 1:R
118 l = 0:N(k);
119 logpmf = l * log(gamma(k)) - gammaln(l + 1);
120 pmf = exp(logpmf - logsumexp(logpmf));
121 cdf = cumsum(pmf);
122 cdf(end) = 1; % guard rounding
123 u = rand(S, 1);
124 idx = sum(u > cdf(:)', 2); % # of thresholds exceeded = value
125 V(:, k) = idx;
126end
127
128% Feasibility indicators
129AV = V * A'; % S x J, row s = A*n_s
130inOmega = all(AV <= C(:)', 2); % S x 1
131inOmegaK = false(S, R);
132for k = 1:R
133 Ck = (C - A(:,k))'; % 1 x J capacity for Omega(C-A_.k)
134 inOmegaK(:, k) = all(AV <= Ck, 2);
135end
136
137% Likelihood ratio alpha^i = prod_k (nu_k/gamma_k)^V_k (log space)
138logratio = log(nu) - log(gamma); % 1xR
139log_alpha = V * logratio'; % S x 1
140
141% Normalization constant estimate g(C) = (c/S) sum alpha 1(Omega)
142laO = log_alpha(inOmega);
143if isempty(laO)
144 lG = -Inf;
145else
146 m = max(laO);
147 lG = log_c + m + log(sum(exp(laO - m))) - log(S);
148end
149
150% Ratio estimators for acceptance (Eq. 8) with shifted weights for stability
151if any(inOmega)
152 M = max(log_alpha(inOmega));
153else
154 M = 0;
155end
156w = exp(log_alpha - M); % S x 1 scaled likelihood ratios
157Z = w .* inOmega; % denominator summand
158meanZ = mean(Z);
159
160crit = sqrt(2) * erfinv(1 - alpha); % standard-normal 1-alpha/2 quantile
161accept = zeros(1, R);
162acceptCI = zeros(R, 2);
163for k = 1:R
164 Y = w .* inOmegaK(:, k);
165 meanY = mean(Y);
166 if meanZ <= 0
167 phi = NaN; half = NaN;
168 else
169 phi = meanY / meanZ;
170 varY = var(Y);
171 varZ = var(Z);
172 covYZ = sum((Y - meanY) .* (Z - meanZ)) / (S - 1);
173 sig2 = (varY - 2*phi*covYZ + phi^2*varZ) / (S * meanZ^2);
174 sig2 = max(sig2, 0);
175 half = crit * sqrt(sig2);
176 end
177 accept(k) = phi;
178 acceptCI(k, :) = [phi - half, phi + half];
179end
180
181Loss = 1 - accept;
182QLen = nu .* accept;
183
184ci = struct();
185ci.accept = acceptCI;
186ci.loss = [1 - acceptCI(:,2), 1 - acceptCI(:,1)];
187ci.acceptPoint = accept;
188ci.lossPoint = Loss;
189ci.level = 1 - alpha;
190end
191
192function s = logsumexp(x)
193x = x(:)';
194m = max(x);
195if isinf(m)
196 s = m;
197else
198 s = m + log(sum(exp(x - m)));
199end
200end
201
202function v = getfielddef(s, f, d)
203if isfield(s, f) && ~isempty(s.(f))
204 v = s.(f);
205else
206 v = d;
207end
208end
Definition Station.m:245