LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
mam_truncate_renorm.m
1function [meanQ, lossProb, p_norm] = mam_truncate_renorm(D_arr, pie_cell, D0_cell, capK)
2% MAM_TRUNCATE_RENORM Finite-buffer marginal for MMAP[K]/PH[K]/1/FCFS.
3%
4% Solves the infinite-buffer MMAP[K]/PH[K]/1/FCFS queue via BUTools
5% MMAPPH1FCFS, truncates the marginal queue length distribution at the
6% buffer capacity capK, and renormalizes. For an M/M/1 input the
7% renormalized distribution coincides exactly with the M/M/1/K marginal;
8% for general MMAP/PH it is an ASTA-style approximation.
9%
10% INPUT
11% D_arr - cell array passed as the MMAP argument to MMAPPH1FCFS,
12% e.g. {D0, D_class1, D_class2, ...}
13% pie_cell - cell array of per-class PH initial distributions
14% D0_cell - cell array of per-class PH subgenerators (T matrices)
15% capK - buffer capacity (max number of jobs in system, integer >= 1)
16%
17% OUTPUT
18% meanQ - mean number of jobs in system (clipped to [0, capK])
19% lossProb - blocking probability = renormalized boundary mass p(N=capK)
20% (PASTA-exact for Poisson arrivals)
21% p_norm - renormalized truncated marginal as 1x(capK+1) row vector
22%
23% Multi-class: MMAPPH1FCFS returns the joint (aggregate) marginal at the
24% station; callers split per-class with the lambda_k/lambda_total fraction
25% (FCFS Little's-law decomposition), mirroring the convention used by the
26% closed-class branch of solver_mam_basic.
27%
28% Multi-server: callers must pre-scale the PH service mean by 1/c (the
29% existing "surrogate-delay" trick); the helper then returns the marginal
30% of the scaled M/M/1/K system, which is treated as an approximation of
31% the M/M/c/K marginal. The c-1/c surrogate-delay term is omitted under
32% finite cap because it would double-count physical jobs already bounded
33% by capK.
34%
35% See also MMAPPH1FCFS.
36%
37% Copyright (c) 2012-2026, Imperial College London
38% All rights reserved.
39
40% Multi-class needs aggregation: MMAPPH1FCFS('ncDistr') returns the per-class
41% marginal P(N_k=n), not the joint P(N_total=n) that the truncation requires.
42% Aggregate to a single-class MMAP/PH/1 by summing arrival matrices and
43% building a workload-weighted PH mixture for service.
44nClasses = numel(pie_cell);
45if nClasses > 1
46 D0 = D_arr{1};
47 Dsum = zeros(size(D0));
48 for k=1:nClasses
49 Dsum = Dsum + D_arr{k+1};
50 end
51 e_arr = ones(size(D0,1), 1);
52 theta = ctmc_solve(D0 + Dsum);
53 lambda_k = zeros(1, nClasses);
54 for k=1:nClasses
55 lambda_k(k) = theta * D_arr{k+1} * e_arr;
56 end
57 sumL = sum(lambda_k);
58 if sumL > 0
59 w = lambda_k / sumL;
60 else
61 w = ones(1, nClasses) / nClasses;
62 end
63 n_k = cellfun(@(p) numel(p), pie_cell);
64 n_total = sum(n_k);
65 alpha_mix = zeros(1, n_total);
66 T_mix = zeros(n_total, n_total);
67 offset = 0;
68 for k=1:nClasses
69 alpha_mix(offset+1 : offset+n_k(k)) = w(k) * pie_cell{k}(:)';
70 T_mix(offset+1:offset+n_k(k), offset+1:offset+n_k(k)) = D0_cell{k};
71 offset = offset + n_k(k);
72 end
73 D_call = {D0, Dsum};
74 pie_call = {alpha_mix};
75 D0_call = {T_mix};
76else
77 D_call = D_arr;
78 pie_call = pie_cell;
79 D0_call = D0_cell;
80end
81
82pdistr = MMAPPH1FCFS(D_call, pie_call, D0_call, 'ncDistr', capK + 1);
83pdistr = abs(pdistr(:)');
84nLevels = capK + 1;
85if numel(pdistr) < nLevels
86 pdistr(end+1:nLevels) = 0;
87end
88p_in = pdistr(1:nLevels);
89massIn = sum(p_in);
90if massIn <= 0
91 p_norm = zeros(1, nLevels);
92 p_norm(1) = 1;
93else
94 p_norm = p_in / massIn;
95end
96meanQ = max(0, min(capK, (0:capK) * p_norm(:)));
97lossProb = p_norm(end);
98end