LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
toMarginalAggr.m
1function [ni, nir] = toMarginalAggr(sn, ind, state_i, K, Ks, space_buf, space_srv, space_var) %#ok<INUSD>
2% TOMARGINALAGGR Compute aggregate marginal distributions for a specific node
3%
4% [NI, NIR] = TOMARGINALAGGR(SN, IND, STATE_I, K, KS, SPACE_BUF, SPACE_SRV, SPACE_VAR)
5%
6% @brief Computes aggregate marginal job counts from state information without phase details
7%
8% This function provides a simplified version of toMarginal that computes
9% aggregate job counts per node and per class, without considering individual
10% service phases. It is more efficient when phase-level detail is not required.
11%
12% @param sn Network structure or Network object
13% @param ind Node index to extract marginal information for
14% @param state_i Global state matrix or vector
15% @param K Vector of population for each class
16% @param Ks Matrix of populations per chain and class
17% @param space_buf Buffer space configuration
18% @param space_srv Service space configuration
19% @param space_var Variable space configuration
20%
21% @return ni Total jobs in node IND (aggregate across all classes)
22% @return nir Jobs per class in node IND [vector: classes]
23
24% Copyright (c) 2012-2026, Imperial College London
25% All rights reserved.
26
27if ~isstruct(sn) % the input can be a Network object too
28 sn=sn.getStruct();
29end
30% ind: node index
31ist = sn.nodeToStation(ind);
32%isf = sn.nodeToStateful(ind);
33R = sn.nclasses;
34if ~sn.isstation(ind) && sn.isstateful(ind) % if stateful node
35 ni = sum(state_i(1:(end-sum(sn.nvars(ind,:)))));
36 nir = state_i(1:(end-sum(sn.nvars(ind,:))));
37 return
38end
39
40% Place nodes: compute total jobs per class from state
41if sn.nodetype(ind) == NodeType.Place
42 state_len = size(state_i, 2);
43 % Check if this is queue-based state (FCFS/LCFS/HOL) vs count-based
44 % Queue-based: state contains class indices [1,1,2,1] meaning job arrivals
45 % Count-based: state contains counts per class [n1, n2, ...] or [buf(R), srv]
46 % Detect queue-based: length != R and length != 2*R and all values are valid class indices
47 is_queue_based = state_len ~= R && state_len ~= 2*R;
48 if is_queue_based && state_len > 0
49 % Check all values are valid class indices (1 to R)
50 all_vals = state_i(:);
51 is_queue_based = all(all_vals >= 1 & all_vals <= R);
52 end
53
54 if is_queue_based
55 % Queue-based format: count occurrences of each class
56 nir = zeros(size(state_i,1), R);
57 for r = 1:R
58 nir(:,r) = sum(state_i == r, 2);
59 end
60 elseif nargin >= 4 && ~isempty(K)
61 expected_len = R + sum(K);
62 if state_len == expected_len
63 % State has [buffer, server] format
64 buf_part = state_i(:, 1:R);
65 srv_part = state_i(:, (R+1):end);
66 nir = buf_part;
67 for r = 1:R
68 for k = 1:K(r)
69 nir(:,r) = nir(:,r) + srv_part(:, Ks(r)+k);
70 end
71 end
72 elseif state_len == R
73 % State is just counts per class (simple SIRO format)
74 nir = state_i;
75 else
76 % Unknown format - just take first R columns
77 nir = state_i(:, 1:min(R, state_len));
78 if size(nir, 2) < R
79 nir = [nir, zeros(size(nir,1), R - size(nir,2))];
80 end
81 end
82 else
83 % No K provided - assume state is counts per class
84 nir = state_i(:, 1:min(R, size(state_i, 2)));
85 if size(nir, 2) < R
86 nir = [nir, zeros(size(nir,1), R - size(nir,2))];
87 end
88 end
89 ni = sum(nir,2);
90 return
91end
92
93% Source nodes have infinite population but report queue length 0 (jobs are external)
94if sn.nodetype(ind) == NodeType.Source
95 nir = zeros(size(state_i,1), R);
96 ni = zeros(size(state_i,1), 1);
97 return
98end
99
100if nargin < 4
101 K = sn.phasessz(ist,:);
102end
103 if nargin < 5
104 Ks = sn.phaseshift(ist,:);
105end
106
107if nargin < 8
108 space_var = state_i(:,(end-sum(sn.nvars(ind,:))+1):end); % server state
109 space_srv = state_i(:,(end-sum(K)+1):(end-sum(sn.nvars(ind,:))));
110 space_buf = state_i(:,1:(end-sum(K)));
111end
112
113nir = zeros(size(state_i,1),R); % class-r jobs in service
114for r=1:R
115 for k=1:K(r)
116 nir(:,r) = nir(:,r) + space_srv(:,Ks(r)+k);
117 end
118end
119switch sn.sched(ist)
120 case SchedStrategy.EXT
121 for r=1:R
122 nir(:,r) = Inf;
123 end
124 case SchedStrategy.FCFS
125 for r=1:R
126 nir(:,r) = nir(:,r) + sum(space_buf==r,2); % class-r jobs in station
127 end
128 case SchedStrategy.HOL
129 for r=1:R
130 nir(:,r) = nir(:,r) + sum(space_buf==r,2); % class-r jobs in station
131 end
132 case SchedStrategy.LCFS
133 for r=1:R
134 nir(:,r) = nir(:,r) + sum(space_buf==r,2); % class-r jobs in station
135 end
136 case SchedStrategy.SIRO
137 for r=1:R
138 nir(:,r) = nir(:,r) + space_buf(:,r); % class-r jobs in station
139 end
140 case SchedStrategy.SEPT
141 for r=1:R
142 nir(:,r) = nir(:,r) + space_buf(:,r); % class-r jobs in station
143 end
144 case SchedStrategy.LEPT
145 for r=1:R
146 nir(:,r) = nir(:,r) + space_buf(:,r); % class-r jobs in station
147 end
148 %otherwise % possibly other stateful nodes
149 % no-op
150end
151
152for r=1:R
153 if isnan(sn.rates(ist,r)) && sn.nodetype(ind) ~= NodeType.Place % if disabled
154 nir(:,r) = 0;
155 end
156end
157
158ni = sum(nir,2); % total jobs in station
159end
Definition mmt.m:92