LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
Solver.m
1classdef Solver < handle
2 % Abstract base class for all LINE model solution algorithms
3 %
4 % Provides common interface and infrastructure for queueing network analysis.
5 %
6 % Copyright (c) 2012-2026, Imperial College London
7 % All rights reserved.
8
9 properties (Constant)
10 VERBOSE_SILENT = 0;
11 VERBOSE_STD = 1;
12 VERBOSE_DEBUG = 2;
13 end
14
15 properties (Hidden, Access = public)
16 enableChecks;
17 end
18
19 properties (Access = public)
20 options; % Data structure with solver options
21 name; % Solver name
22 model; % Model to be solved
23 result; % last result
24 obj;
25 end
26
27 methods (Hidden)
28 %Constructor
29 function self = Solver(model, name, options)
30 % SELF = SOLVER(MODEL, NAME, OPTIONS)
31 if nargin<3 %~exist('options','var')
32 options = self.defaultOptions;
33 end
34 self.model = model; % passed by reference for cache update
35 self.name = name;
36 self.options = options;
37 self.enableChecks = true;
38 end
39 end
40
41 methods (Abstract) % implemented with errors for Octave compatibility
42 sn = getStruct(self);
43 runtime = runAnalyzer(self, options)% generic method to run the solver
44 bool = supports(self,model);
45 end
46
47
48 methods
49 function model = getModel(self)
50 model = self.model;
51 end
52
53 function self = setChecks(self, bool)
54 self.enableChecks = bool;
55 end
56 function out = getName(self)
57 % OUT = GETNAME()
58 % Get solver name
59 out = self.name;
60 end
61 function results = getResults(self)
62 % RESULTS = GETRESULTS()
63 % Return results data structure
64 results = self.result;
65 end
66
67 function bool = hasResults(self)
68 % BOOL = HASRESULTS()
69 % Check if the model has been solved
70 bool = ~isempty(self.result);
71 end
72
73 function bool = isStochastic(self)
74 % BOOL = ISSTOCHASTIC()
75 % True if the solver, with its currently configured method,
76 % returns stochastic estimates (i.e., results depend on the
77 % random seed, as in simulation or Monte Carlo integration).
78 % A solver run with method 'default' may resolve the actual
79 % method only at runtime; once results are available, the
80 % classification therefore uses the method recorded in
81 % result.Avg.method (e.g. 'default/imci' when the NC default
82 % path resolved to Monte Carlo integration).
83 method = self.options.method;
84 if ~isempty(self.result) && isfield(self.result,'Avg') && ...
85 isfield(self.result.Avg,'method') && ~isempty(self.result.Avg.method) && ...
86 ischar(self.result.Avg.method)
87 method = self.result.Avg.method;
88 end
89 bool = self.isStochasticMethod(method);
90 end
91
92 function bool = isStochasticMethod(self, method) %#ok<INUSD>
93 % BOOL = ISSTOCHASTICMETHOD(METHOD)
94 % Classify a (possibly runtime-resolved) method name of this
95 % solver as stochastic. Deterministic by default; subclasses
96 % with simulation-based or sampling-based methods override this.
97 bool = false;
98 end
99
100 function options = getOptions(self)
101 % OPTIONS = GETOPTIONS()
102 % Return options data structure
103 options = self.options;
104 end
105
106 function reset(self)
107 % RESET()
108 % Dispose previously stored results
109 self.result = [];
110 Solver.resetRandomGeneratorSeed(self.options.seed);
111 end
112
113 function self = setOptions(self, options)
114 % SELF = SETOPTIONS(OPTIONS)
115 % Set a new options data structure
116 self.options = options;
117 end
118
119 end
120
121 methods (Static)
122
123 function resetRandomGeneratorSeed(seed)
124 % RESETRANDOMGENERATORSEED(SEED)
125 % Assign a new seed to the random number generator
126 warning('off','MATLAB:RandStream:ActivatingLegacyGenerators');
127 warning('off','MATLAB:RandStream:ReadingInactiveLegacyGeneratorState');
128 rng(seed,'twister');
129 end
130
131 function bool = isJavaAvailable()
132 % BOOL = ISJAVAAVAILABLE()
133 % Check if Java dependencies are available for the solver
134 bool = true;
135 if ispc % windows
136 [~,ret] = dos('java -version');
137 if strfind(ret,'not recognized') %#ok<STRIFCND>
138 bool = false;
139 end
140 else %linux
141 [~,ret] = unix('java -version');
142 if strfind(ret,'command not found') %#ok<STRIFCND>
143 bool = false;
144 end
145 end
146 end
147
148 function [optList, allOpt] = listValidOptions()
149 % OPTLIST = LISTVALIDOPTIONS()
150 % List valid fields for options data structure
151 optList = {'cache','cutoff','force','init_sol','iter_max','iter_tol','lang','tol', ...
152 'keep','method','odesolvers','samples','seed','stiff', 'timespan','timestep','timeout','verbose','config.multiserver','config.fork_join','fork_join','confint','level'};
153 %,'amva.aql','aql','amva.qdaql','qdaql','mom','brute','jmva.ls','jmt.jmva.ls'
154 allOpt = {'cache','cutoff','force','init_sol','iter_max','iter_tol','lang','tol', ...
155 'keep','method','odesolvers','samples','seed','stiff', 'timespan','timestep','timeout','verbose','config.multiserver','config.fork_join','fork_join','confint','level', ...
156 'default','exact','auto','ctmc','ctmc.gpu','gpu','mva','mva.exact','mva.amva','mva.qna','sqni','mva.sqni',...
157 'amva','amva.bs','amva.qd','bs','qd','amva.qli','qli','amva.fli','fli','amva.lin','lin','amva.qdlin','qdlin',...
158 'ssa','ssa.parallel','serial','parallel','nrm',...
159 'jmt','jsim','replication','jmva','jmva.amva','jmva.mva','jmva.recal','jmva.mom','jmva.comom','jmva.chow','jmva.bs','jmva.aql','jmva.lin','jmva.dmlin','jmt.jsim',...
160 'jmt.jmva','jmt.jmva.mva','jmt.jmva.amva','jmt.jmva.recal','jmt.jmva.comom','jmt.jmva.chow','jmt.jmva.bs','jmt.jmva.aql','jmt.jmva.lin','jmt.jmva.dmlin',...
161 'ca','comom','comomld','gm','propfair','recal','kt', 'rd', 'nrp', 'nrl', ...
162 'nc.brute','nc.ca','nc.comom','nc.comomld','nc.gm','nc.mom','nc.propfair','nc.recal','nc.kt', 'nc.rd', 'nc.nr.probit', 'nc.nr.logit', ...
163 'fluid','matrix','softmin','statedep','closing','diffusion','fluid.softmin','fluid.statedep','fluid.closing','fluid.matrix','fluid.diffusion',...
164 'nc','nc.exact','nc.imci','ls','nc.ls','nc.cub','cub','le','nc.le','nc.panacea','panacea','nc.mmint2','mmint2','nc.gleint','gleint','mam','dec.source','dec.mmap',...
165 'mmk','gigk', 'gigk.kingman_approx', ...
166 'mm1','mg1','gm1','gig1','gim1','gig1.kingman','gig1.gelenbe','gig1.heyman','gig1.kimura','gig1.allen','gig1.kobayashi','gig1.klb','gig1.marchal',...
167 'aba.upper','aba.lower','gb.upper','gb.lower','sb.upper','sb.lower','bjb.upper','bjb.lower','pb.upper','pb.lower','mwba.upper','mwba.lower', ...
168 'pbh.upper','pbh.lower','pbk.upper','pbk.lower','bjbk.upper','bjbk.lower','cub.upper','cub.lower'};
169 end
170
171 function bool = isValidOption(optName)
172 % BOOL = ISVALIDOPTION(OPTNAME)
173 % Check if the given option exists for the solver
174 [~,allOpts] = Solver.listValidOptions();
175 bool = any(cell2mat(findstring(optName, allOpts))==1);
176 end
177
178 function options = defaultOptions()
179 % OPTIONS = DEFAULTOPTIONS()
180 % Return default options
181 options = lineDefaults;
182 end
183
184 function [enabled, level] = parseConfInt(confint)
185 % [ENABLED, LEVEL] = PARSECONFINT(CONFINT)
186 % Parse confidence interval option value
187 % Returns enabled (true/false) and confidence level (0.0-1.0)
188 if islogical(confint)
189 enabled = confint;
190 level = 0.95; % default 95% confidence
191 elseif isnumeric(confint) && confint > 0 && confint < 1
192 enabled = true;
193 level = confint;
194 elseif isnumeric(confint) && confint == 0
195 enabled = false;
196 level = 0.95;
197 else
198 enabled = false;
199 level = 0.95;
200 end
201 end
202
203 function options = parseOptions(varargin, defaultOptions)
204 % OPTIONS = PARSEOPTIONS(VARARGIN, DEFAULTOPTIONS)
205 % Parse option parameters into options data structure
206 if isempty(varargin)
207 options = defaultOptions;
208 elseif isstruct(varargin{1})
209 options = varargin{1};
210 elseif ischar(varargin{1})
211 if length(varargin)>1 && isstruct(varargin{2}) % options struct after method field
212 options = varargin{2};
213 varargin(2) = [];
214 elseif isscalar(varargin)
215 options = defaultOptions;
216 options.method = varargin{1};
217 else
218 options = defaultOptions;
219 end
220 [optList, allOpt] = Solver.listValidOptions();
221 allMethodsList = setdiff(allOpt, optList);
222 while ~isempty(varargin)
223 if Solver.isValidOption(varargin{1}) || startsWith(varargin{1},'config.')
224 switch varargin{1}
225 case allMethodsList
226 options.method = varargin{1};
227 varargin(1) = [];
228 otherwise
229 switch varargin{1}
230 case 'config.eventcache'
231 options.config.eventcache = varargin{2};
232 case 'config.warmupfrac'
233 options.config.warmupfrac = varargin{2};
234 case 'config.highvar'
235 options.config.highvar = varargin{2};
236 case 'config.multiserver'
237 options.config.multiserver = varargin{2};
238 case 'config.np_priority'
239 options.config.np_priority = varargin{2};
240 case 'config.fork_join'
241 options.config.fork_join = varargin{2};
242 case 'fork_join'
243 options.config.fork_join = varargin{2};
244 case 'verbose'
245 % Convert string verbose level to VerboseLevel constant
246 if ischar(varargin{2}) || isstring(varargin{2})
247 switch upper(char(varargin{2}))
248 case 'SILENT'
249 options.verbose = VerboseLevel.SILENT;
250 case 'STD'
251 options.verbose = VerboseLevel.STD;
252 case 'DEBUG'
253 options.verbose = VerboseLevel.DEBUG;
254 otherwise
255 options.verbose = varargin{2};
256 end
257 else
258 options.verbose = varargin{2};
259 end
260 otherwise
261 options.(varargin{1}) = varargin{2};
262 end
263 varargin(1) = [];
264 varargin(1) = [];
265 end
266 else
267 %line_warning(mfilename,sprintf('Option "%s" does not exist. Ignoring.',varargin{1}));
268 varargin(1) = [];
269 end
270 end
271 else
272 line_error(mfilename,'Invalid parameter.');
273 end
274 end
275
276 end
277end
Definition Station.m:245