1function [Q,U,R,T,C,X,lG,runtime,iter] = solver_mva_bound_analyzer(sn, options)
2% [Q,U,R,T,C,X,LG,RUNTIME,ITER] = SOLVER_MVA_BOUND_ANALYZER(QN, OPTIONS)
4% Copyright (c) 2012-2026, Imperial College London
14line_debug(
'MVA bound analyzer starting: method=%s, nclasses=%d, njobs=%s', options.method, sn.nclasses, mat2str(sn.njobs));
18 line_debug(
'Using ABA upper bound');
19 if sn.nclasses==1 && sn.nclosedjobs >0 % closed single-
class queueing network
20 if any(sn.nservers(sn.sched ~= SchedStrategy.INF)>1)
21 line_error(mfilename,'Unsupported method for a model with multi-server stations.');
24 Z = sum(V(sn.sched == SchedStrategy.INF) ./ sn.rates(sn.sched == SchedStrategy.INF));
25 D = V(sn.sched ~= SchedStrategy.INF) ./ sn.rates(sn.sched ~= SchedStrategy.INF);
28 C(1,1) = Z + N * sum(D);
29 X(1,1) = min( 1/Dmax, N / (Z + sum(D)));
31 R(:,1) = 1 ./ sn.rates * N;
32 R(sn.sched == SchedStrategy.INF,1) = 1 ./ sn.rates(sn.sched == SchedStrategy.INF,1);
33 Q(:,1) = T(:,1) .* R(:,1);
34 U(:,1) = T(:,1) ./ sn.rates;
35 U((sn.sched == SchedStrategy.INF),1) = Q((sn.sched == SchedStrategy.INF),1);
36 lG = - N*log(X(1,1)); % approx
40 line_debug(
'Using ABA lower bound');
41 if sn.nclasses==1 && sn.nclosedjobs >0 % closed single-
class queueing network
42 if any(sn.nservers(sn.sched ~= SchedStrategy.INF)>1)
43 line_error(mfilename,'Unsupported method for a model with multi-server stations.');
46 Z = sum(V(sn.sched == SchedStrategy.INF) ./ sn.rates(sn.sched == SchedStrategy.INF));
47 D = V(sn.sched ~= SchedStrategy.INF) ./ sn.rates(sn.sched ~= SchedStrategy.INF);
49 X(1,1) = N / (Z + N*sum(D));
52 R(:,1) = 1 ./ sn.rates;
53 Q(:,1) = T(:,1) .* R(:,1);
54 U(:,1) = T(:,1) ./ sn.rates;
55 U((sn.sched == SchedStrategy.INF),1) = Q((sn.sched == SchedStrategy.INF),1);
56 lG = - N*log(X(1,1)); % approx
60 line_debug(
'Using BJB upper bound');
61 if sn.nclasses==1 && sn.nclosedjobs >0 % closed single-
class queueing network
62 if any(sn.nservers(sn.sched ~= SchedStrategy.INF)>1)
63 line_error(mfilename,'Unsupported method for a model with multi-server stations.');
66 Z = sum(V(sn.sched == SchedStrategy.INF) ./ sn.rates(sn.sched == SchedStrategy.INF));
67 D = V(sn.sched ~= SchedStrategy.INF) ./ sn.rates(sn.sched ~= SchedStrategy.INF);
70 Xaba_upper_1 = min( 1/Dmax, (N-1) / (Z + sum(D)));
71 Xaba_lower_1 = (N-1) / (Z + (N-1)*sum(D));
72 C(1,1) = (Z+sum(D)+max(D)*(N-1-Z*Xaba_lower_1));
73 X(1,1) = min(1/Dmax, N / (Z+sum(D)+mean(D)*(N-1-Z*Xaba_upper_1)));
75 % RN undefined in the literature so we use ABA upper
76 R(:,1) = 1 ./ sn.rates * N;
78 %RN(sn.sched ~= SchedStrategy.INF,1) = NaN * D+ max(D) ./ V(sn.sched ~= SchedStrategy.INF) .* (N-1-Z*Xaba_lower_1) / (sn.nstations - sum(sn.sched == SchedStrategy.INF));
79 R(sn.sched == SchedStrategy.INF,1) = 1 ./ sn.rates(sn.sched == SchedStrategy.INF,1);
80 Q(:,1) = T(:,1) .* R(:,1);
81 U(:,1) = T(:,1) ./ sn.rates;
82 U((sn.sched == SchedStrategy.INF),1) = Q((sn.sched == SchedStrategy.INF),1);
83 lG = - N*log(X(1,1)); % approx
87 line_debug(
'Using BJB lower bound');
88 if sn.nclasses==1 && sn.nclosedjobs >0 % closed single-
class queueing network
89 if any(sn.nservers(sn.sched ~= SchedStrategy.INF)>1)
90 line_error(mfilename,'Unsupported method for a model with multi-server stations.');
93 Z = sum(V(sn.sched == SchedStrategy.INF) ./ sn.rates(sn.sched == SchedStrategy.INF));
94 D = V(sn.sched ~= SchedStrategy.INF) ./ sn.rates(sn.sched ~= SchedStrategy.INF);
97 Xaba_upper_1 = min( 1/Dmax, (N-1) / (Z + sum(D)));
98 Xaba_lower_1 = (N-1) / (Z + (N-1)*sum(D));
99 C(1,1) = (Z+sum(D)+mean(D)*(N-1-Z*Xaba_upper_1));
100 X(1,1) = N / (Z+sum(D)+max(D)*(N-1-Z*Xaba_lower_1));
101 T(:,1) = V .* X(1,1);
102 % RN undefined in the literature so we use ABA lower
103 R(:,1) = 1 ./ sn.rates;
105 %RN(sn.sched ~= SchedStrategy.INF,1) = NaN * 1 ./ sn.rates(sn.sched ~= SchedStrategy.INF,1) + mean(D) ./ V(sn.sched ~= SchedStrategy.INF) .* (N-1-Z*Xaba_upper_1) / (sn.nstations - sum(sn.sched == SchedStrategy.INF));
106 R(sn.sched == SchedStrategy.INF,1) = 1 ./ sn.rates(sn.sched == SchedStrategy.INF,1);
107 Q(:,1) = T(:,1) .* R(:,1);
108 U(:,1) = T(:,1) ./ sn.rates;
109 U((sn.sched == SchedStrategy.INF),1) = Q((sn.sched == SchedStrategy.INF),1);
110 lG = - N*log(X(1,1)); % approx
114 line_debug(
'Using PB upper bound');
115 if sn.nclasses==1 && sn.nclosedjobs >0 % closed single-
class queueing network
116 if any(sn.nservers(sn.sched ~= SchedStrategy.INF)>1)
117 line_error(mfilename,'Unsupported method for a model with multi-server stations.');
120 Z = sum(V(sn.sched == SchedStrategy.INF) ./ sn.rates(sn.sched == SchedStrategy.INF));
121 D = V(sn.sched ~= SchedStrategy.INF) ./ sn.rates(sn.sched ~= SchedStrategy.INF);
124 Xaba_upper_1 = min( 1/Dmax, (N-1) / (Z + sum(D)));
125 Xaba_lower_1 = (N-1) / (Z + (N-1)*sum(D));
126 Dpb2 = sum(D.^2)/sum(D);
127 DpbN = sum(D.^N)/sum(D.^(N-1));
128 C(1,1) = (Z+sum(D)+DpbN*(N-1-Z*Xaba_lower_1));
129 X(1,1) = min(1/Dmax, N / (Z+sum(D)+Dpb2*(N-1-Z*Xaba_upper_1)));
130 T(:,1) = V .* X(1,1);
131 % RN undefined in the literature so we use ABA upper
132 R(:,1) = 1 ./ sn.rates * N;
134 %RN(sn.sched ~= SchedStrategy.INF,1) = NaN * 1 ./ sn.rates(sn.sched ~= SchedStrategy.INF,1) + (D.^N/sum(D.^(N-1))) ./ V(sn.sched ~= SchedStrategy.INF) * (N-1-Z*Xaba_upper_1);
135 R(sn.sched == SchedStrategy.INF,1) = 1 ./ sn.rates(sn.sched == SchedStrategy.INF,1);
136 Q(:,1) = T(:,1) .* R(:,1);
137 U(:,1) = T(:,1) ./ sn.rates;
138 U((sn.sched == SchedStrategy.INF),1) = Q((sn.sched == SchedStrategy.INF),1);
139 lG = - N*log(X(1,1)); % approx
143 line_debug(
'Using PB lower bound');
144 if sn.nclasses==1 && sn.nclosedjobs >0 % closed single-
class queueing network
145 if any(sn.nservers(sn.sched ~= SchedStrategy.INF)>1)
146 line_error(mfilename,'Unsupported method for a model with multi-server stations.');
149 Z = sum(V(sn.sched == SchedStrategy.INF) ./ sn.rates(sn.sched == SchedStrategy.INF));
150 D = V(sn.sched ~= SchedStrategy.INF) ./ sn.rates(sn.sched ~= SchedStrategy.INF);
153 Xaba_upper_1 = min( 1/Dmax, (N-1) / (Z + sum(D)));
154 Xaba_lower_1 = (N-1) / (Z + (N-1)*sum(D));
155 Dpb2 = sum(D.^2)/sum(D);
156 DpbN = sum(D.^N)/sum(D.^(N-1));
157 C(1,1) = (Z+sum(D)+Dpb2*(N-1-Z*Xaba_upper_1));
158 X(1,1) = N / (Z+sum(D)+DpbN*(N-1-Z*Xaba_lower_1));
159 T(:,1) = V .* X(1,1);
160 % RN undefined in the literature so we use ABA lower
161 R(:,1) = 1 ./ sn.rates;
163 %RN(sn.sched ~= SchedStrategy.INF,1) = NaN * 1 ./ sn.rates(sn.sched ~= SchedStrategy.INF,1) + (D.^2/sum(D)) ./ V(sn.sched ~= SchedStrategy.INF) * (N-1-Z*Xaba_upper_1);
164 R(sn.sched == SchedStrategy.INF,1) = 1 ./ sn.rates(sn.sched == SchedStrategy.INF,1);
165 Q(:,1) = T(:,1) .* R(:,1);
166 U(:,1) = T(:,1) ./ sn.rates;
167 U((sn.sched == SchedStrategy.INF),1) = Q((sn.sched == SchedStrategy.INF),1);
168 lG = - N*log(X(1,1)); % approx
172 line_debug(
'Using SB upper bound');
173 if sn.nclasses==1 && sn.nclosedjobs >0 % closed single-
class queueing network
174 if any(sn.nservers(sn.sched ~= SchedStrategy.INF)>1)
175 line_error(mfilename,'Unsupported method for a model with multi-server stations.');
177 if any(sn.sched == SchedStrategy.INF)
178 line_error(mfilename,'Unsupported method for a model with infinite-server stations.');
181 D = V(sn.sched ~= SchedStrategy.INF) ./ sn.rates(sn.sched ~= SchedStrategy.INF);
182 Z = sum(V(sn.sched == SchedStrategy.INF) ./ sn.rates(sn.sched == SchedStrategy.INF));
188 C(1,1) = Z+A1+(N-1)*(A1*A2+A3)/(A1^2+A2);
189 X(1,1) = min([1/Dmax,N / (Z+A1+(N-1)*(A1*A2+A3)/(A1^2+A2))]);
190 T(:,1) = V .* X(1,1);
191 % RN undefined in the literature so we use ABA lower
192 R(:,1) = 1 ./ sn.rates;
194 %RN(sn.sched ~= SchedStrategy.INF,1) = NaN * 1 ./ sn.rates(sn.sched ~= SchedStrategy.INF,1) + (D.^2/sum(D)) ./ V(sn.sched ~= SchedStrategy.INF) * (N-1-Z*Xaba_upper_1);
195 R(sn.sched == SchedStrategy.INF,1) = 1 ./ sn.rates(sn.sched == SchedStrategy.INF,1);
196 Q(:,1) = T(:,1) .* R(:,1);
197 U(:,1) = T(:,1) ./ sn.rates;
198 U((sn.sched == SchedStrategy.INF),1) = Q((sn.sched == SchedStrategy.INF),1);
199 lG = - N*log(X(1,1)); % approx
203 line_debug(
'Using SB lower bound');
204 if sn.nclasses==1 && sn.nclosedjobs >0 % closed single-
class queueing network
205 if any(sn.nservers(sn.sched ~= SchedStrategy.INF)>1)
206 line_error(mfilename,'Unsupported method for a model with multi-server stations.');
208 if any(sn.sched == SchedStrategy.INF)
209 line_error(mfilename,'Unsupported method for a model with infinite-server stations.');
212 D = V(sn.sched ~= SchedStrategy.INF) ./ sn.rates(sn.sched ~= SchedStrategy.INF);
213 Z = sum(V(sn.sched == SchedStrategy.INF) ./ sn.rates(sn.sched == SchedStrategy.INF));
217 C(1,1) = Z+A1+(N-1)*(AN/A1)^(1/(N-1));
218 X(1,1) = N / (Z+A1+(N-1)*(AN/A1)^(1/(N-1)));
219 T(:,1) = V .* X(1,1);
220 % RN undefined in the literature so we use ABA lower
221 R(:,1) = 1 ./ sn.rates;
223 %RN(sn.sched ~= SchedStrategy.INF,1) = NaN * 1 ./ sn.rates(sn.sched ~= SchedStrategy.INF,1) + (D.^2/sum(D)) ./ V(sn.sched ~= SchedStrategy.INF) * (N-1-Z*Xaba_upper_1);
224 R(sn.sched == SchedStrategy.INF,1) = 1 ./ sn.rates(sn.sched == SchedStrategy.INF,1);
225 Q(:,1) = T(:,1) .* R(:,1);
226 U(:,1) = T(:,1) ./ sn.rates;
227 U((sn.sched == SchedStrategy.INF),1) = Q((sn.sched == SchedStrategy.INF),1);
228 lG = - N*log(X(1,1)); % approx
232 line_debug(
'Using GB upper bound');
233 if sn.nclasses==1 && sn.nclosedjobs >0 % closed single-
class queueing network
234 if any(sn.nservers(sn.sched ~= SchedStrategy.INF)>1)
235 line_error(mfilename,'Unsupported method for a model with multi-server stations.');
238 Z = sum(V(sn.sched == SchedStrategy.INF) ./ sn.rates(sn.sched == SchedStrategy.INF));
239 D = V(sn.sched ~= SchedStrategy.INF) ./ sn.rates(sn.sched ~= SchedStrategy.INF);
242 X(1,1) = min(1/Dmax, pfqn_xzgsbup(D,N,Z));
243 C(1,1) = N / pfqn_xzgsblow(D,N,Z);
244 T(:,1) = V .* X(1,1);
245 XNlow = pfqn_xzgsblow(D,N,Z);
248 if sn.sched(i) == SchedStrategy.INF
249 R(i,1) = 1 / sn.rates(i);
250 Q(i,1) = X(1,1) * R(i,1);
253 Q(i,1) = pfqn_qzgbup(D,N,Z,k);
254 R(i,1) = Q(i,1) / XNlow / V(i) ;
257 R(sn.sched == SchedStrategy.INF,1) = 1 ./ sn.rates(sn.sched == SchedStrategy.INF,1);
258 U(:,1) = T(:,1) ./ sn.rates;
259 U((sn.sched == SchedStrategy.INF),1) = Q((sn.sched == SchedStrategy.INF),1);
260 lG = - N*log(X(1,1)); % approx
264 line_debug(
'Using GB lower bound');
265 if sn.nclasses==1 && sn.nclosedjobs >0 % closed single-
class queueing network
266 if any(sn.nservers(sn.sched ~= SchedStrategy.INF)>1)
267 line_error(mfilename,'Unsupported method for a model with multi-server stations.');
270 Z = sum(V(sn.sched == SchedStrategy.INF) ./ sn.rates(sn.sched == SchedStrategy.INF));
271 D = V(sn.sched ~= SchedStrategy.INF) ./ sn.rates(sn.sched ~= SchedStrategy.INF);
273 X(1,1) = pfqn_xzgsblow(D,N,Z);
274 C(1,1) = N / pfqn_xzgsbup(D,N,Z);
275 T(:,1) = V .* X(1,1);
276 XNup = pfqn_xzgsbup(D,N,Z);
279 if sn.sched(i) == SchedStrategy.INF
280 R(i,1) = 1 / sn.rates(i);
281 Q(i,1) = X(1,1) * R(i,1);
284 Q(i,1) = pfqn_qzgblow(D,N,Z,k);
285 R(i,1) = Q(i,1) / XNup / V(i) ;
288 U(:,1) = T(:,1) ./ sn.rates;
289 U((sn.sched == SchedStrategy.INF),1) = Q((sn.sched == SchedStrategy.INF),1);
290 lG = - N*log(X(1,1)); % approx