4 % @brief Schmidt
's exact MVA for networks with general scheduling disciplines.
10 % @brief Schmidt's exact MVA
for networks with general scheduling disciplines.
11 % @fn pfqn_schmidt(D, N, S, sched, v)
12 % @param D Service demand matrix.
13 % @param N Population vector.
14 % @param S Number of servers per station (matrix or vector).
15 % @param sched Scheduling discipline per station.
16 % @param v Visit ratio matrix (optional, defaults to ones).
17 % @
return XN System throughput.
18 % @
return QN Mean queue lengths.
19 % @
return UN Utilization.
20 % @
return CN Cycle times.
21 % @
return T Results table.
24function [XN,QN,UN,CN,T] = pfqn_schmidt(D,N,S,sched,v)
25% [XN,QN,UN,CN] = PFQN_SCHMIDT(D,N,S,SCHED,V)
27% utilization in general ld
case does not work
35% Default visit ratios to ones
if not provided
36if nargin < 5 || isempty(v)
40% Compute pure service times from demands: S_pure = D / v
41% D
is demands (= visit_ratio * service_time), so S_pure = D / v
42% Bcn calculations need pure service times, not demands
43S_pure = D ./ max(v, 1e-12); % Protect against division by zero
45C = length(closedClasses); % number of closed
classes
46Dc = D(:,closedClasses);
48prods = zeros(1,C); % needed
for fast hashing
50 prods(r)=prod(Nc(1:r-1)+1);
52% Start at nc=(0,...,0)
55L = cell(1, M); % mean queue-length
56Pc = cell(1, M); % state probabilities (empty cells
for stations that don
't need them)
58 % Always initialize L for ALL stations (queue lengths needed everywhere)
59 L{ist} = zeros(R, prod(1+Nc)); % mean queue-length
61 case SchedStrategy.INF
62 % No Pc needed for infinite server
64 if ~all(S(ist,:) == 1)
65 % Multi-server PS needs state probabilities
66 Pc{ist} = zeros(1 + sum(Nc), prod(1+Nc)); % Pr(j|N)
68 case SchedStrategy.FCFS
69 if all(D(ist,:)==D(ist,1)) % class-independent
70 if ~all(S(ist,:) == 1) % multi server
71 Pc{ist} = zeros(1 + sum(Nc), prod(1+Nc)); % Pr(j|N)
73 else % class-dependent - needs vector probabilities
74 Pc{ist} = zeros(prod(1+Nc), prod(1+Nc)); % Pr(jvec|N)
78% Per-station throughput like Java: x(ist,c,hkvec) = v(ist,c) * kvec(c) / denom
79x = zeros(M,C,prod(1+Nc));
80w = zeros(M,C,prod(1+Nc));
83 Pc{ist}(1 + 0, hashpop(kvec,Nc,C,prods)) = 1.0; %Pj(0|0) = 1
88while all(kvec>=0) && all(kvec <= Nc)
90 kprods = zeros(1,C); % needed for fast hashing
92 kprods(r)=prod(kvec(1:r-1)+1);
96 hkvec = hashpop(kvec,Nc,C,prods);
97 hkvec_c = hashpop(oner(kvec,c),Nc,C,prods);
98 if size(S(ist,:)) == 1
105 case SchedStrategy.INF
106 w(ist,c,hkvec) = D(ist,c);
107 case SchedStrategy.PS
109 % Sum queue lengths of ALL classes (arrival theorem)
110 totalQueueLength = sum(L{ist}(:, hkvec_c));
111 w(ist,c,hkvec) = Dc(ist,c) * (1 + totalQueueLength);
113 % Sum queue lengths of ALL classes (arrival theorem)
114 totalQueueLength = sum(L{ist}(:, hkvec_c));
115 w(ist,c,hkvec) = (Dc(ist,c) / ns) * (1 + totalQueueLength);
117 % Pc{ist}(j,...) = Pr(j-1 jobs) due to MATLAB 1-indexing
118 w(ist,c,hkvec) = w(ist,c,hkvec) + (ns-1-(j-1))*Pc{ist}(j, hkvec_c) * (Dc(ist,c) / ns);
121 case SchedStrategy.FCFS
122 if all(D(ist,:)==D(ist,1)) % product-form case
124 % Sum queue lengths of ALL classes (arrival theorem)
125 totalQueueLength = sum(L{ist}(:, hkvec_c));
126 w(ist,c,hkvec) = Dc(ist,c) * (1 + totalQueueLength);
128 % Sum queue lengths of ALL classes (arrival theorem)
129 totalQueueLength = sum(L{ist}(:, hkvec_c));
130 w(ist,c,hkvec) = (Dc(ist,c) / ns) * (1 + totalQueueLength);
132 % Pc{ist}(j,...) = Pr(j-1 jobs) due to MATLAB 1-indexing
133 w(ist,c,hkvec) = w(ist,c,hkvec) + (ns-1-(j-1))*Pc{ist}(j, hkvec_c) * (Dc(ist,c) / ns);
138 % Sum queue lengths of ALL classes (arrival theorem)
139 totalQueueLength = sum(L{ist}(:, hkvec_c));
140 w(ist,c,hkvec) = Dc(ist,c) * (1 + totalQueueLength);
142 % Multi-server FCFS class-dependent case
146 % Use Nc and prods for hash (matches Java)
147 hnvec_c = hashpop(oner(nvec,c),Nc,C,prods);
148 % Bcn calculation for multi-server using pure service times
152 % Weighted average service time based on queue composition
153 % Use epsilon protection for division (matches Java)
154 Bcn = S_pure(ist,c) + max(0,sum(nvec)-ns)/max(ns*(sum(nvec)-1), 1e-12) * (nvec*S_pure(ist,:)' - S_pure(ist,c));
156 w(ist,c,hkvec) = w(ist,c,hkvec) + Bcn * Pc{ist}(hnvec_c, hkvec_c);
158 nvec = pprod(nvec, kvec);
166 % Compute throughputs (per-station like Java)
168 % denom = sum over i of (v(i,c) * w(i,c,hkvec))
171 denom = denom + v(ist,c) * w(ist,c,hkvec);
173 % Per-station throughput: x(ist,c) = v(ist,c) * N(c) / denom
176 x(ist,c,hkvec) = v(ist,c) * kvec(c) / denom;
182 % Update queue lengths: L = x * w
185 L{ist}(c,hkvec) = x(ist,c,hkvec) * w(ist,c,hkvec);
187 if size(S(ist,:)) == 1
193 case SchedStrategy.PS
195 for n=1:min(S(ist),sum(kvec))
198 hkvec_c = hashpop(oner(kvec,c),Nc,C,prods);
199 Pc{ist}(1 + n, hkvec) = Pc{ist}(1 + n, hkvec) + Dc(ist,c) * (1/n) * x(ist,c,hkvec) * Pc{ist}(1+(n-1), hkvec_c);
202 Pc{ist}(1 + 0, hkvec) = max(eps,1-sum(Pc{ist}(1 + (1:min(S(ist),sum(kvec))), hkvec)));
205 case SchedStrategy.FCFS
206 if all(D(ist,:)==D(ist,1))
208 for n=1:(min(ns,sum(kvec))-1)
211 hkvec_c = hashpop(oner(kvec,c),Nc,C,prods);
212 Pc{ist}(1 + n, hkvec) = Pc{ist}(1 + n, hkvec) + Dc(ist,c) * (1/n) * x(ist,c,hkvec) * Pc{ist}(1+(n-1), hkvec_c);
215 Pc{ist}(1 + 0, hkvec) = max(eps,1-sum(Pc{ist}(1 + (1:min(ns,sum(kvec))), hkvec)));
220 nvec = pprod(nvec, kvec); % Skip zero vector like Java
223 % Use Nc and prods
for hash (matches Java)
224 hnvec = hashpop(nvec,Nc,C,prods);
228 % Use Nc and prods
for hash (matches Java)
229 hnvec_c = hashpop(oner(nvec,c),Nc,C,prods);
230 hkvec_c = hashpop(oner(kvec,c),Nc,C,prods);
231 % Bcn calculation
using pure service times (matches Java getBcn)
234 sumVal = nvec*S_pure(ist,:)
';
235 Bcn = Bcn + max(0,sum(nvec)-ns)/max(ns*(sum(nvec)-1), 1e-12) * (sumVal - S_pure(ist,c));
237 % Use 1/sum(nvec) instead of 1/nvec(c) to match Java
238 capacity_inv = 1/sum(nvec);
239 classProb = Bcn * capacity_inv * x(ist,c,hkvec) * Pc{ist}(hnvec_c, hkvec_c);
240 prob = prob + classProb;
243 Pc{ist}(hnvec, hkvec) = prob;
244 sumOfAllProbs = sumOfAllProbs + prob;
245 nvec = pprod(nvec, kvec);
247 Pc{ist}(1 + 0, hkvec) = max(1e-12, 1 - sumOfAllProbs);
251 kvec = pprod(kvec, Nc);
254% Throughput - compute system throughput as N(c) / sum(w) like Java
256 totalResponseTime = 0;
258 totalResponseTime = totalResponseTime + w(ist,c,hkvec);
260 if totalResponseTime > 0
261 XN(c) = Nc(c) / totalResponseTime;
270UN(1:M,closedClasses) = u(1:M,1:C); % this will return 0
272CN(1:M,closedClasses) = w(1:M,1:C,hkvec);
274 QN(ist,closedClasses) = L{ist}(closedClasses,hkvec);
277T = table(XN,CN,QN,UN); % for display purposes