1function [Pmarg, logPmarg] = getProbMarg(self, node)
2% [PMARG, LOGPMARG] = GETPROBMARG(NODE)
4% Probability distribution
for TOTAL queue length at a station.
5% Returns
P(n total jobs)
for n=0,1,...,N, summing over all
class combinations.
7% Compare with getProbAggr: returns probability of a specific per-
class
8% distribution, e.g.,
P(2
class-1, 1
class-2).
11% node - Queue or node
object
14% Pmarg - Vector where Pmarg(n+1) =
P(n total jobs at node)
15% logPmarg - Log probabilities
for numerical stability
17if GlobalConstants.DummyMode
23% Get network structure
26% Store original node parameter and convert to station index
29 ist = sn.nodeToStation(node.index);
31 % If given station index, need to find corresponding node
33 % Find node with this station index
34 for i = 1:length(sn.nodetype)
35 if sn.nodeToStation(i) == ist
36 node_obj = sn.
nodes{i};
42% Get population and
class information
45 line_error(mfilename,
'getProbMarg not yet implemented for models with open classes.');
48R = sn.nclasses; % Number of
classes
49Ntotal = sum(N); % Total population
51% Initialize output vectors
52Pmarg = zeros(1, Ntotal + 1);
53logPmarg = -Inf * ones(1, Ntotal + 1);
55% For each possible total queue length
57 % Enumerate all ways to partition n jobs across R
classes
58 % subject to constraint: n_r <= N(r)
for each class
59 partitions = generate_partitions(n, R, N);
61 % Sum probabilities over all partitions
63 for p = 1:size(partitions, 1)
64 state_vec = partitions(p, :);
66 % Get probability for this specific class distribution
67 % Note: getProbAggr already supports LD models via pfqn_ncld
68 % Gets unnormalized values (we normalize at the end)
69 prob = self.getProbAggr(node_obj, state_vec);
73 % Log-sum-exp trick for numerical stability
77 log_prob_n = log_prob_n + log(1 + exp(log_p - log_prob_n));
83 if isfinite(log_prob_n)
84 Pmarg(n + 1) = exp(log_prob_n);
85 logPmarg(n + 1) = log_prob_n;
88 logPmarg(n + 1) = -Inf;
92% Normalize to ensure probabilities sum to 1
93total_prob = sum(Pmarg);
94if total_prob > 0 && abs(total_prob - 1.0) > 1e-10
95 Pmarg = Pmarg / total_prob;
96 logPmarg = logPmarg - log(total_prob);
101function partitions = generate_partitions(n, R, N_max)
102% GENERATE_PARTITIONS Enumerate all ways to partition n into R non-negative integers
104% @param n Total to partition
105% @param R Number of parts
106% @param N_max Maximum value for each part (vector of length R)
107% @return partitions Matrix where each row
is a valid partition
110 % Base case: single class
114 partitions = zeros(0, 1);
119% Recursive case: try all possible values for first class
121for n1 = 0:min(n, N_max(1))
122 % Recursively partition remaining jobs across remaining
classes
123 sub_partitions = generate_partitions(n - n1, R - 1, N_max(2:end));
125 if ~isempty(sub_partitions)
126 % Prepend n1 to each sub-partition
127 partitions = [partitions; n1 * ones(size(sub_partitions, 1), 1), sub_partitions];