1function [isMmck, muRate] = mam_detect_mmck(sn, ist, K, mmapNode)
2% MAM_DETECT_MMCK Decide
if station ist matches
the M/M/c/K assumptions.
4% Returns isMmck=
true (and
the shared service rate muRate) only when:
5% -
the aggregated arrival
MMAP at
the node
is single-phase (i.e. Poisson
6% superposition of class arrivals)
7% - every active class has Exp service (procid==EXP) at
the station
8% - all active classes share
the same exponential service rate
13% K - number of classes
14% mmapNode - cell array {D0, D1, D_c1, D_c2, ...} for
the aggregated
18% isMmck - logical, true if
the M/M/c/K closed
form is exact
19% muRate -
the shared service rate (NaN when isMmck
is false)
21% Copyright (c) 2012-2026, Imperial College London
27if isempty(mmapNode) || ~iscell(mmapNode) || size(mmapNode{1}, 1) ~= 1
28 return; % arrivals are not single-phase Poisson superposition
33 if sn.procid(ist, k) ~= ProcessType.EXP
34 % Disabled (NaN rate) classes are skipped; everything
else must be Exp
35 if isnan(sn.rates(ist, k))
40 if isnan(sn.rates(ist, k)) || sn.rates(ist, k) <= 0
41 continue; % no inflow
for this class
43 muVals(end+1) = sn.rates(ist, k); %#ok<AGROW>
50if max(muVals) - min(muVals) > 1e-9 * max(1, max(muVals))
51 return; % per-
class service rates differ