LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
SolverBA.m
1classdef SolverBA < NetworkSolver
2 % Bound Analysis solver for closed queueing networks.
3 %
4 % SolverBA is a dedicated home for asymptotic and hierarchical throughput/
5 % queue-length BOUNDS. Unlike SolverMVA (point estimates), each method
6 % returns an optimistic or pessimistic bound; the .upper/.lower pair for a
7 % family brackets the exact solution. Bounds need only demands (visits x
8 % service time) and populations -- no service-time distributions -- so the
9 % featset is deliberately narrow (closed product-form-parameterized models).
10 %
11 % Method families:
12 % Noniterative (SolverBA-native, solver_ba_analyzer):
13 % aba.* Asymptotic Bound Analysis (Denning-Buzen)
14 % bjb.* Balanced Job Bounds (Zahorjan et al.)
15 % pb.* Proportional Bounds (Eager-Sevcik)
16 % gb.* Geometric Bounds (Casale-Muntz-Serazzi)
17 % sb.* Simple bounds from power sums (Harel-Namn-Sturm); NOT a
18 % geometric variant despite sitting beside gb. Rejects delay
19 % stations, as does lr; gb accepts them.
20 % mwba.* Multiclass worst-case balanced bound
21 % Hierarchical / iterative (SolverBA-native, level-parameterized):
22 % pbh Performance Bound Hierarchy (Eager-Sevcik 1983), level option
23 % sib Successively Improving Bounds (Srinivasan 1985), level option
24 % cbh Convolutional Bound Hierarchies (Dowdy et al. 1984)
25 % bjbk / pbk iterative BJB(k)/PB(k) with delay (Casale et al. 2008)
26 % cub Composite Upper Bound, multiclass upper-only (Kerola 1986)
27 % mbjb multiclass Balanced Job Bounds lower (Kerola eq. 10; seeds cub)
28 % ssd multiServer Disaggregation bounds (Suri-Dallery 1986)
29 % ldbcmp LD-BCMP closed-open equivalence bound (Anselmi-Cremonesi 2008)
30 % LP-based reduction bounds (QRF library, solver_ba_qrf_analyzer):
31 % qr / qrf.mmi Quadratic Reduction Framework (single-class PH)
32 % lr / qrf.mmi.linear Linear Reduction variant
33 % qrf.mem, qrf.mmi.ld, qrf.bas.*, qrf.rsrd further QRF sub-methods
34 %
35 % Copyright (c) 2012-2026, Imperial College London
36 % All rights reserved.
37
38 methods
39 function self = SolverBA(model, varargin)
40 % SOLVERBA Create a bound-analysis solver instance
41 self@NetworkSolver(model, mfilename);
42 self.setOptions(Solver.parseOptions(varargin, SolverBA.defaultOptions));
43 self.setLang();
44 end
45
46 function sn = getStruct(self)
47 % GETSTRUCT Get model data structure for analysis
48 sn = self.model.getStruct(false);
49 end
50
51 [runtime, analyzer] = runAnalyzer(self, options);
52
53 function bounds = getBounds(self)
54 % GETBOUNDS Return the {lower,upper} bracket for the requested
55 % bound family as a struct with fields Xlower/Xupper (throughput)
56 % and Qlower/Qupper (queue lengths). The current method's family
57 % prefix (before the first '.') selects the family; a hierarchical
58 % method uses its own level option.
59 % One-sided families (cub upper-only, mbjb/ldbcmp lower-only)
60 % return NaN on the missing side.
61 fam = self.options.method;
62 dot = strfind(fam,'.');
63 if ~isempty(dot)
64 fam = fam(1:dot(1)-1);
65 end
66 valid = self.listValidMethods();
67 Tl = NaN; Ql = NaN; Tu = NaN; Qu = NaN;
68 if any(strcmp([fam,'.lower'], valid))
69 [Ql,~,~,Tl] = self.solveSide([fam,'.lower']);
70 end
71 if any(strcmp([fam,'.upper'], valid))
72 [Qu,~,~,Tu] = self.solveSide([fam,'.upper']);
73 end
74 bounds = struct('Tlower',Tl,'Tupper',Tu,'Qlower',Ql,'Qupper',Qu);
75 end
76
77 function [Q,U,R,T] = solveSide(self, method)
78 % SOLVESIDE Re-run the solver for one side of the bracket.
79 % The re-run instance inherits the CALLER'S FULL OPTION SET (level,
80 % verbose, tol, ...) and only overrides the method. Constructing it
81 % with just 'method' would silently reset options.level to its
82 % default of 2, so a hierarchical family (pbh/cbh/pbk/bjbk/sib)
83 % reached through getBounds would never tighten as level is raised.
84 s = SolverBA(self.model);
85 opts = self.options;
86 opts.method = method;
87 s.setOptions(opts);
88 [Q,U,R,T] = s.getAvg();
89 end
90
91 function BoundsTable = getBoundsTable(self, keepDisabled)
92 % GETBOUNDSTABLE Table of the {lower,upper} bracket per station and
93 % class, in the layout of GETAVGTABLE. Columns:
94 % Station, JobClass, Qlower, Qupper, Tlower, Tupper
95 % One-sided families (cub upper-only, mbjb/ldbcmp lower-only) carry
96 % NaN on the missing side; NaN is preserved, never replaced by zero.
97 if nargin < 2
98 keepDisabled = false;
99 end
100 b = self.getBounds();
101 sn = self.getStruct();
102 M = sn.nstations;
103 K = sn.nclasses;
104 Ql = SolverBA.expandBound(b.Qlower, M, K);
105 Qu = SolverBA.expandBound(b.Qupper, M, K);
106 Tl = SolverBA.expandBound(b.Tlower, M, K);
107 Tu = SolverBA.expandBound(b.Tupper, M, K);
108 [Qlval, Quval, Tlval, Tuval] = deal([]);
109 JobClass = {};
110 Station = {};
111 for ist = 1:M
112 for k = 1:K
113 vals = [Ql(ist,k), Qu(ist,k), Tl(ist,k), Tu(ist,k)];
114 finite = vals(~isnan(vals));
115 % Mirror getAvgTable's drop of disabled station-class pairs,
116 % but NaN-safe: a row is kept when any value that is present
117 % is nonzero, so an all-NaN side never removes the row.
118 if keepDisabled || isempty(finite) || any(finite ~= 0)
119 JobClass{end+1,1} = sn.classnames{k}; %#ok<AGROW>
120 Station{end+1,1} = sn.nodenames{sn.stationToNode(ist)}; %#ok<AGROW>
121 Qlval(end+1) = Ql(ist,k); %#ok<AGROW>
122 Quval(end+1) = Qu(ist,k); %#ok<AGROW>
123 Tlval(end+1) = Tl(ist,k); %#ok<AGROW>
124 Tuval(end+1) = Tu(ist,k); %#ok<AGROW>
125 end
126 end
127 end
128 Station = label(Station);
129 JobClass = label(JobClass);
130 Qlower = Qlval(:); Qupper = Quval(:);
131 Tlower = Tlval(:); Tupper = Tuval(:);
132 BoundsTable = Table(Station, JobClass, Qlower, Qupper, Tlower, Tupper);
133 BoundsTable = IndexedTable(BoundsTable);
134 end
135
136 function [allMethods] = listValidMethods(self)
137 % LISTVALIDMETHODS Valid bound methods for the current model.
138 % Hierarchical methods (pbh/sib/cbh/bjbk/pbk/cub/ssd/ldbcmp) are
139 % appended here as each backing pfqn_* algorithm is integrated.
140 allMethods = { ...
141 'default', ...
142 'aba.upper','aba.lower', ...
143 'bjb.upper','bjb.lower', ...
144 'pb.upper','pb.lower', ...
145 'gb.upper','gb.lower', ...
146 'sb.upper','sb.lower', ...
147 'mwba.upper','mwba.lower', ...
148 'pbh.upper','pbh.lower', ...
149 'pbk.upper','pbk.lower', ...
150 'bjbk.upper','bjbk.lower', ...
151 'cbh.upper','cbh.lower', ...
152 'ssd.upper','ssd.lower', ...
153 'cub.upper','mbjb.lower', ...
154 'sib.upper','sib.lower', ...
155 'ldbcmp.lower', ...
156 'qr','lr','lr.upper','lr.lower', ...
157 'qrf.mmi','qrf.mem','qrf.mmi.ld','qrf.mmi.linear', ...
158 'qrf.bas.mmi','qrf.bas.mem','qrf.bas','qrf.rsrd'};
159 end
160 end
161
162 methods (Static)
163 function Y = expandBound(X, M, K)
164 % EXPANDBOUND Normalize a bracket side to an (M,K) matrix. A
165 % one-sided family leaves its missing side as the scalar NaN
166 % returned by getBounds; expand it so the table keeps full shape
167 % with NaN entries rather than erroring or dropping the column.
168 if isempty(X)
169 Y = NaN(M,K);
170 elseif isscalar(X)
171 Y = repmat(X, M, K);
172 else
173 Y = X;
174 end
175 end
176
177 function libs = getLibrariesUsed(sn, options) %#ok<INUSL>
178 % GETLIBRARIESUSED External libraries used by SolverBA. The QRF
179 % reduction bounds solve an LP via the Optimization Toolbox.
180 libs = {};
181 if ~isempty(options) && isfield(options,'method') && ...
182 (startsWith(options.method,'qrf') || any(strcmp(options.method,{'qr','lr'})))
183 libs{end+1} = 'MATLAB Optimization Toolbox (fmincon)';
184 end
185 end
186
187 function options = defaultOptions
188 % OPTIONS = DEFAULTOPTIONS()
189 options = SolverOptions('MVA');
190 options.method = 'default';
191 % Hierarchy level for pbh/cbh (MVA steps / exact-convolved servers)
192 % and iteration count k for pbk/bjbk. Default 2.
193 options.level = 2;
194 end
195
196 function [bool, featSupported] = supports(model)
197 % SUPPORTS Whether SolverBA can bound the given model
198 featUsed = model.getUsedLangFeatures();
199 featSupported = SolverFeatureSet();
200 featSupported.setTrue({ ...
201 'ClassSwitch','DelayStation','Queue', ...
202 'Sink','Source','Router', ...
203 'ClosedClass','OpenClass', ...
204 'SchedStrategy_INF','SchedStrategy_PS', ...
205 'SchedStrategy_FCFS','SchedStrategy_LCFSPR', ...
206 'RoutingStrategy_PROB','RoutingStrategy_RAND', ...
207 'ClosedClass_multiclass'});
208 bool = SolverFeatureSet.supports(featSupported, featUsed);
209 end
210 end
211end
Definition Station.m:245