LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
SolverAuto.m
1classdef SolverAuto
2 % SolverAuto Automatic solver selection based on model characteristics
3 %
4 % SolverAuto is an intelligent solver that automatically selects the most
5 % appropriate solution method based on the characteristics of the queueing
6 % network model. It analyzes model properties such as network type, class
7 % types, scheduling policies, and size to determine the optimal solver.
8 %
9 % @brief Intelligent automatic solver selection for queueing network models
10 %
11 % The solver can choose from multiple candidate solvers including:
12 % - MVA (Mean Value Analysis) for product-form networks
13 % - NC (Normalizing Constant) for closed networks
14 % - MAM (Matrix Analytic Methods) for non-product-form features
15 % - Fluid approximation for large-scale models
16 % - JMT simulation for complex models
17 % - SSA (Stochastic State-space Analysis) for detailed analysis
18 % - CTMC (Continuous Time Markov Chain) for small state spaces
19 % - LQNS for layered queueing networks
20 %
21 % The selection process considers model complexity, solver accuracy,
22 % and computational efficiency to provide optimal performance.
23
24 % Copyright (c) 2012-2026, Imperial College London
25 % All rights reserved.
26
27 properties (Hidden, Access = public)
28 enableChecks;
29 end
30
31 properties (Hidden)
32 % Network solvers
33 CANDIDATE_MVA = 1;
34 CANDIDATE_NC = 2;
35 CANDIDATE_MAM = 3;
36 CANDIDATE_FLUID = 4;
37 CANDIDATE_JMT = 5;
38 CANDIDATE_SSA = 6;
39 CANDIDATE_CTMC = 7;
40 CANDIDATE_DES = 8;
41 % LayeredNetwork solvers
42 CANDIDATE_LQNS = 1;
43 CANDIDATE_LN_NC = 2;
44 CANDIDATE_LN_MVA = 3;
45 CANDIDATE_LN_MAM = 4;
46 CANDIDATE_LN_FLUID = 5;
47 % Environment solvers
48 CANDIDATE_ENV_MVA = 1;
49 CANDIDATE_ENV_NC = 2;
50 CANDIDATE_ENV_FLUID = 3;
51 end
52
53 properties (Hidden)
54 candidates; % feasible solvers
55 solvers;
56 options;
57 end
58
59 properties
60 model;
61 name;
62 end
63
64 methods
65 % Constructor
66 function self = SolverAuto(model, varargin)
67 % SOLVERAUTO Create an automatic solver instance
68 %
69 % @brief Creates a SolverAuto instance that automatically selects solvers
70 % @param model Network or LayeredNetwork model to be solved
71 % @param varargin Optional parameters for solver configuration
72 % @return self SolverAuto instance configured for the given model
73 self.options = Solver.parseOptions(varargin, Solver.defaultOptions);
74 self.model = model;
75 self.name = 'SolverAuto';
76 if self.options.verbose
77 %line_printf('Running LINE version %s',model.getVersion);
78 end
79 switch self.options.method
80 case 'sim'
81 % Best simulator - JMT for most cases
82 self.options.method = 'default';
83 switch class(model)
84 case 'Network'
85 self.solvers{1,1} = SolverJMT(model,self.options);
86 case 'LayeredNetwork'
87 self.solvers{1,1} = SolverLQNS(model,self.options);
88 case 'Environment'
89 self.solvers{1,1} = SolverENV(model,@(m) SolverJMT(m,'verbose',false),self.options);
90 end
91 case 'exact'
92 % Best exact method - NC for closed, CTMC for small state space
93 self.options.method = 'default';
94 switch class(model)
95 case 'Network'
96 sn = model.getStruct(true);
97 if all(isfinite(sn.njobs)) % closed network
98 self.solvers{1,1} = SolverNC(model,self.options);
99 else
100 self.solvers{1,1} = SolverCTMC(model,self.options);
101 end
102 case 'LayeredNetwork'
103 self.solvers{1,1} = SolverLN(model,@(m) SolverNC(m,'verbose',false),self.options);
104 case 'Environment'
105 self.solvers{1,1} = SolverENV(model,@(m) SolverNC(m,'verbose',false),self.options);
106 end
107 case 'fast'
108 % Fast approximate method - MVA (fastest analytical)
109 self.options.method = 'default';
110 switch class(model)
111 case 'Network'
112 self.solvers{1,1} = SolverMVA(model,self.options);
113 case 'LayeredNetwork'
114 self.solvers{1,1} = SolverLN(model,@(m) SolverMVA(m,'verbose',false),self.options);
115 case 'Environment'
116 self.solvers{1,1} = SolverENV(model,@(m) SolverMVA(m,'verbose',false),self.options);
117 end
118 case 'accurate'
119 % Accurate approximate method - Fluid or MAM
120 self.options.method = 'default';
121 switch class(model)
122 case 'Network'
123 self.solvers{1,1} = SolverFluid(model,self.options);
124 case 'LayeredNetwork'
125 self.solvers{1,1} = SolverLN(model,@(m) SolverFluid(m,'verbose',false),self.options);
126 case 'Environment'
127 self.solvers{1,1} = SolverENV(model,@(m) SolverFluid(m,'verbose',false),self.options);
128 end
129 case 'mam'
130 self.options.method = 'default';
131 self.solvers{1,1} = SolverMAM(model,self.options);
132 case 'mva'
133 self.options.method = 'default';
134 self.solvers{1,1} = SolverMVA(model,self.options);
135 case 'nc'
136 self.options.method = 'default';
137 self.solvers{1,1} = SolverNC(model,self.options);
138 case 'fluid'
139 self.options.method = 'default';
140 self.solvers{1,1} = SolverFluid(model,self.options);
141 case 'jmt'
142 self.options.method = 'default';
143 self.solvers{1,1} = SolverJMT(model,self.options);
144 case 'ssa'
145 self.options.method = 'default';
146 self.solvers{1,1} = SolverSSA(model,self.options);
147 case 'ctmc'
148 self.options.method = 'default';
149 self.solvers{1,1} = SolverCTMC(model,self.options);
150 case 'des'
151 self.options.method = 'default';
152 self.solvers{1,1} = SolverDES(model,self.options);
153 case 'env'
154 self.options.method = 'default';
155 self.solvers{1,1} = SolverENV(model,@(m) SolverMVA(m,'verbose',false),self.options);
156 case 'ln'
157 self.options.method = 'default';
158 self.solvers{1,1} = SolverLN(model,self.options);
159 case 'lqns'
160 self.options.method = 'default';
161 self.solvers{1,1} = SolverLQNS(model,self.options);
162 case {'default','heur'} % 'ai' method not yet available
163 %solvers sorted from fastest to slowest
164 self.solvers = {};
165 switch class(model)
166 case 'Network'
167 self.solvers{1,self.CANDIDATE_MAM} = SolverMAM(model);
168 self.solvers{1,self.CANDIDATE_MVA} = SolverMVA(model);
169 self.solvers{1,self.CANDIDATE_NC} = SolverNC(model);
170 self.solvers{1,self.CANDIDATE_FLUID} = SolverFluid(model);
171 self.solvers{1,self.CANDIDATE_JMT} = SolverJMT(model);
172 self.solvers{1,self.CANDIDATE_SSA} = SolverSSA(model);
173 self.solvers{1,self.CANDIDATE_CTMC} = SolverCTMC(model);
174 self.solvers{1,self.CANDIDATE_DES} = SolverDES(model);
175 boolSolver = false(length(self.solvers),1);
176 for s=1:length(self.solvers)
177 boolSolver(s) = self.solvers{s}.supports(self.model);
178 self.solvers{s}.setOptions(self.options);
179 end
180 self.candidates = {self.solvers{find(boolSolver)}}; %#ok<FNDSB>
181 case 'LayeredNetwork'
182 self.solvers{1,self.CANDIDATE_LQNS} = SolverLQNS(model,self.options);
183 self.solvers{1,self.CANDIDATE_LN_NC} = SolverLN(model,@(m) SolverNC(m,'verbose', false),self.options);
184 self.solvers{1,self.CANDIDATE_LN_MVA} = SolverLN(model,@(m) SolverMVA(m,'verbose', false),self.options);
185 self.solvers{1,self.CANDIDATE_LN_MAM} = SolverLN(model,@(m) SolverMAM(m,'verbose', false),self.options);
186 self.solvers{1,self.CANDIDATE_LN_FLUID} = SolverLN(model,@(m) SolverFluid(m,'verbose', false),self.options);
187 self.candidates = self.solvers;
188 case 'Environment'
189 self.solvers{1,self.CANDIDATE_ENV_MVA} = SolverENV(model,@(m) SolverMVA(m,'verbose', false),self.options);
190 self.solvers{1,self.CANDIDATE_ENV_NC} = SolverENV(model,@(m) SolverNC(m,'verbose', false),self.options);
191 self.solvers{1,self.CANDIDATE_ENV_FLUID} = SolverENV(model,@(m) SolverFluid(m,'verbose', false),self.options);
192 self.candidates = self.solvers;
193 end
194 end
195 %turn off warnings temporarily
196 wstatus = warning('query');
197 warning off;
198 warning(wstatus);
199 end
200
201 function sn = getStruct(self)
202 % QN = GETSTRUCT()
203
204 % Get data structure summarizing the model
205 sn = self.model.getStruct(true);
206 end
207
208 function out = getName(self)
209 % OUT = GETNAME()
210 % Get solver name
211 out = self.name;
212 end
213
214 function model = getModel(self)
215 % MODEL = GETMODEL()
216 % Get the model being solved
217 model = self.model;
218 end
219
220 function results = getResults(self)
221 % RESULTS = GETRESULTS()
222 % Return results data structure from chosen solver
223 results = self.delegate('getResults', 1);
224 end
225
226 function bool = hasResults(self)
227 % BOOL = HASRESULTS()
228 % Check if the solver has computed results
229 bool = self.delegate('hasResults', 1);
230 end
231
232 function options = getOptions(self)
233 % OPTIONS = GETOPTIONS()
234 % Return options data structure
235 options = self.options;
236 end
237
238 function self = setOptions(self, options)
239 % SELF = SETOPTIONS(OPTIONS)
240 % Set a new options data structure for all candidate solvers
241 self.options = options;
242 for s = 1:length(self.solvers)
243 if ~isempty(self.solvers{s})
244 self.solvers{s}.setOptions(options);
245 end
246 end
247 end
248
249 function bool = supports(self, model)
250 % BOOL = SUPPORTS(MODEL)
251 % Check if any candidate solver supports the given model
252 bool = false;
253 for s = 1:length(self.solvers)
254 if ~isempty(self.solvers{s}) && self.solvers{s}.supports(model)
255 bool = true;
256 return;
257 end
258 end
259 end
260
261 function allMethods = listValidMethods(self)
262 % ALLMETHODS = LISTVALIDMETHODS()
263 % List valid methods from all candidate solvers
264 allMethods = {'default', 'auto', 'heur', 'sim', 'exact', 'fast', 'accurate'}; % 'ai' not yet available
265 for s = 1:length(self.solvers)
266 if ~isempty(self.solvers{s})
267 try
268 solverMethods = self.solvers{s}.listValidMethods();
269 allMethods = unique([allMethods, solverMethods]);
270 catch
271 % Solver doesn't implement listValidMethods
272 end
273 end
274 end
275 end
276
277 end
278
279 methods
280 % delegate execution of method to chosen solver
281 varargout = delegate(self, method, nretout, varargin);
282
283 % chooseSolver: choses a solver from static properties of the model
284 solver = chooseSolver(self, method);
285 % AI-based choice solver
286 solver = chooseSolverAI(self, method);
287 % Heuristic choice of solver
288 solver = chooseSolverHeur(self, method);
289 % AI-based choice solver for Avg* methods
290 solver = chooseAvgSolverAI(self);
291 % Heuristic choice of solver for Avg* methods
292 solver = chooseAvgSolverHeur(self);
293
294 end
295
296 methods
297 function reset(self)
298 for s=1:length(self.solvers)
299 self.solvers{s}.reset();
300 end
301 end
302 function setChecks(self,bool)
303 for s=1:length(self.solvers)
304 self.solvers{s}.setChecks(bool);
305 end
306 end
307 end
308
309 methods
310 function AvgChainTable = getAvgChainTable(self)
311 % [AVGCHAINTABLE] = GETAVGCHAINTABLE(self)
312 try
313 AvgChainTable = self.delegate('getAvgChainTable', 1);
314 catch
315 line_error(mfilename, 'Fatal error in getAvgChainTable.')
316 end
317 end
318
319 function [AvgQLenTable, QT] = getAvgQLenTable(self, Q, keepDisabled)
320 % [AVGQLENTABLE, QT] = GETAVGQLENTABLE(self, Q, keepDisabled)
321 if nargin < 2
322 Q = [];
323 end
324 if nargin < 3
325 keepDisabled = false;
326 end
327 [AvgQLenTable, QT] = self.delegate('getAvgQLenTable', 2, Q, keepDisabled);
328 end
329
330 function [AvgTputTable, TT] = getAvgTputTable(self, T, keepDisabled)
331 % [AVGTPUTTABLE, TT] = GETAVGTPUTTABLE(self, T, keepDisabled)
332 if nargin < 2
333 T = [];
334 end
335 if nargin < 3
336 keepDisabled = false;
337 end
338 [AvgTputTable, TT] = self.delegate('getAvgTputTable', 2, T, keepDisabled);
339 end
340
341 function [AvgRespTTable, RT] = getAvgRespTTable(self, R, keepDisabled)
342 % [AVGRESPTTABLE, RT] = GETAVGRESPTTABLE(self, R, keepDisabled)
343 if nargin < 2
344 R = [];
345 end
346 if nargin < 3
347 keepDisabled = false;
348 end
349 [AvgRespTTable, RT] = self.delegate('getAvgRespTTable', 2, R, keepDisabled);
350 end
351
352 function [AvgUtilTable, UT] = getAvgUtilTable(self, U, keepDisabled)
353 % [AVGUTILTABLE, UT] = GETAVGUTILTABLE(self, U, keepDisabled)
354 if nargin < 2
355 U = [];
356 end
357 if nargin < 3
358 keepDisabled = false;
359 end
360 [AvgUtilTable, UT] = self.delegate('getAvgUtilTable', 2, U, keepDisabled);
361 end
362
363 function AvgSysTable = getAvgSysTable(self)
364 % [AVGSYSTABLE] = GETAVGSYSTABLE(self)
365 AvgSysTable = self.delegate('getAvgSysTable', 1);
366 end
367
368 function AvgNodeTable = getAvgNodeTable(self)
369 % [AVGNODETABLE] = GETAVGNODETABLE(self)
370 AvgNodeTable = self.delegate('getAvgNodeTable', 1);
371 end
372
373 function AvgTable = getAvgTable(self)
374 % [AVGTABLE] = GETAVGTABLE(self)
375 AvgTable = self.delegate('getAvgTable', 1);
376 end
377
378 function [QN,UN,RN,TN,AN,WN] = getAvg(self,Q,U,R,T)
379 %[QN,UN,RN,TN] = GETAVG(SELF,Q,U,R,T)
380
381 if nargin>1
382 [QN,UN,RN,TN,AN,WN] = self.delegate('getAvg', 6, Q,U,R,T);
383 else
384 [QN,UN,RN,TN,AN,WN] = self.delegate('getAvg', 6);
385 end
386 end
387
388 function [QNc,UNc,RNc,TNc] = getAvgChain(self,Q,U,R,T)
389 %[QNC,UNC,RNC,TNC] = GETAVGCHAIN(SELF,Q,U,R,T)
390
391 if nargin>1
392 [QNc,UNc,RNc,TNc] = self.delegate('getAvgChain', 4, Q,U,R,T);
393 else
394 [QNc,UNc,RNc,TNc] = self.delegate('getAvgChain', 4);
395 end
396 end
397
398 function [CNc,XNc] = getAvgSys(self,R,T)
399 %[CNC,XNC] = GETAVGSYS(SELF,R,T)
400
401 if nargin>1
402 [CNc,XNc] = self.delegate('getAvgSys', 2, R,T);
403 else
404 [CNc,XNc] = self.delegate('getAvgSys', 2);
405 end
406 end
407
408 function [QN,UN,RN,TN,AN,WN] = getAvgNode(self,Q,U,R,T,A)
409 if nargin>1
410 [QN,UN,RN,TN,AN,WN] = self.delegate('getAvgNode', 6, Q,U,R,T,A);
411 else
412 [QN,UN,RN,TN,AN,WN] = self.delegate('getAvgNode', 6);
413 end
414 end
415
416 function [AN] = getAvgArvRChain(self,A)
417 if nargin>1
418 AN = self.delegate('getAvgArvRChain', 1, A);
419 else
420 AN = self.delegate('getAvgArvRChain', 1);
421 end
422 end
423
424 function [QN] = getAvgQLenChain(self,Q)
425 if nargin>1
426 QN = self.delegate('getAvgQLenChain', 1, Q);
427 else
428 QN = self.delegate('getAvgQLenChain', 1);
429 end
430 end
431
432 function [UN] = getAvgUtilChain(self,U)
433 if nargin>1
434 UN = self.delegate('getAvgUtilChain', 1, U);
435 else
436 UN = self.delegate('getAvgUtilChain', 1);
437 end
438 end
439
440 function [RN] = getAvgRespTChain(self,R)
441 if nargin>1
442 RN = self.delegate('getAvgRespTChain', 1, R);
443 else
444 RN = self.delegate('getAvgRespTChain', 1);
445 end
446 end
447
448 function [TN] = getAvgTputChain(self,T)
449 if nargin>1
450 TN = self.delegate('getAvgTputChain', 1, T);
451 else
452 TN = self.delegate('getAvgTputChain', 1);
453 end
454 end
455
456 function [RN] = getAvgSysRespT(self,R)
457 if nargin>1
458 RN = self.delegate('getAvgSysRespT', 1, R);
459 else
460 RN = self.delegate('getAvgSysRespT', 1);
461 end
462 end
463
464 function [TN] = getAvgSysTput(self,T)
465 if nargin>1
466 TN = self.delegate('getAvgSysTput', 1, T);
467 else
468 TN = self.delegate('getAvgSysTput', 1);
469 end
470 end
471
472 function [QNt,UNt,TNt] = getTranAvg(self,Qt,Ut,Tt)
473 % [QNT,UNT,TNT] = GETTRANAVG(SELF,QT,UT,TT)
474
475 if nargin>1
476 [QNt,UNt,TNt] = self.delegate('getTranAvg', 3, Qt,Ut,Tt);
477 else
478 [QNt,UNt,TNt] = self.delegate('getTranAvg', 3);
479 end
480 end
481
482 function RD = getTranCdfPassT(self, R)
483 % RD = GETTRANCDFPASST(R)
484
485 if nargin>1
486 RD = self.delegate('getTranCdfPassT', 1, R);
487 else
488 RD = self.delegate('getTranCdfPassT', 1);
489 end
490 end
491
492 function RD = getTranCdfRespT(self, R)
493 % RD = GETTRANCDFRESPT(R)
494
495 if nargin>1
496 RD = self.delegate('getTranCdfRespT', 1, R);
497 else
498 RD = self.delegate('getTranCdfRespT', 1);
499 end
500 end
501
502 function [Pi_t, SSnode] = getTranProb(self, node)
503 % [PI, SS] = GETTRANPROB(NODE)
504 [Pi_t, SSnode] = self.delegate('getTranProb', 2, node);
505 end
506
507 function [Pi_t, SSnode_a] = getTranProbAggr(self, node)
508 % [PI, SS] = GETTRANPROBAGGR(NODE)
509 [Pi_t, SSnode_a] = self.delegate('getTranProbAggr', 2, node);
510 end
511
512 function [Pi_t, SSsys] = getTranProbSys(self)
513 % [PI, SS] = GETTRANPROBSYS()
514 [Pi_t, SSsys] = self.delegate('getTranProbSys', 2);
515 end
516
517 function [Pi_t, SSsysa] = getTranProbSysAggr(self)
518 % [PI, SS] = GETTRANPROBSYSAGGR()
519 [Pi_t, SSsysa] = self.delegate('getTranProbSysAggr', 2);
520 end
521
522 function sampleNodeState = sample(self, node, numSamples)
523 sampleNodeState = self.delegate('sample', 1, node, numSamples);
524 end
525
526 function stationStateAggr = sampleAggr(self, node, numSamples)
527 stationStateAggr = self.delegate('sampleAggr', 1, node, numSamples);
528 end
529
530 function tranSysState = sampleSys(self, numSamples)
531 tranSysState = self.delegate('sampleSys', 1, numSamples);
532 end
533
534 function sysStateAggr = sampleSysAggr(self, numSamples)
535 sysStateAggr = self.delegate('sampleSysAggr', 1, numSamples);
536 end
537
538 function RD = getCdfRespT(self, R)
539 if nargin>1
540 RD = self.delegate('getCdfRespT', 1, R);
541 else
542 RD = self.delegate('getCdfRespT', 1);
543 end
544 end
545
546 function Pnir = getProb(self, node, state)
547 Pnir = self.delegate('getProb', 1, node, state);
548 end
549
550 function Pnir = getProbAggr(self, node, state_a)
551 Pnir = self.delegate('getProbAggr', 1, node, state_a);
552 end
553
554 function Pn = getProbSys(self)
555 Pn = self.delegate('getProbSys',1);
556 end
557
558 function Pn = getProbSysAggr(self)
559 Pn = self.delegate('getProbSysAggr',1);
560 end
561
562 function [logNormConst] = getProbNormConstAggr(self)
563 logNormConst = self.delegate('getProbNormConstAggr',1);
564 end
565
566 % Basic metric methods
567 function QN = getAvgQLen(self)
568 % QN = GETAVGQLEN()
569 % Compute average queue-lengths at steady-state
570 QN = self.delegate('getAvgQLen', 1);
571 end
572
573 function UN = getAvgUtil(self)
574 % UN = GETAVGUTIL()
575 % Compute average utilizations at steady-state
576 UN = self.delegate('getAvgUtil', 1);
577 end
578
579 function RN = getAvgRespT(self)
580 % RN = GETAVGRESPT()
581 % Compute average response times at steady-state
582 RN = self.delegate('getAvgRespT', 1);
583 end
584
585 function WN = getAvgResidT(self)
586 % WN = GETAVGRESIDT()
587 % Compute average residence times at steady-state
588 WN = self.delegate('getAvgResidT', 1);
589 end
590
591 function WT = getAvgWaitT(self)
592 % WT = GETAVGWAITT()
593 % Compute average waiting time in queue excluding service
594 WT = self.delegate('getAvgWaitT', 1);
595 end
596
597 function TN = getAvgTput(self)
598 % TN = GETAVGTPUT()
599 % Compute average throughputs at steady-state
600 TN = self.delegate('getAvgTput', 1);
601 end
602
603 function AN = getAvgArvR(self)
604 % AN = GETAVGARVR()
605 % Compute average arrival rate at steady-state
606 AN = self.delegate('getAvgArvR', 1);
607 end
608
609 % Additional chain methods
610 function [WN] = getAvgResidTChain(self, W)
611 if nargin > 1
612 WN = self.delegate('getAvgResidTChain', 1, W);
613 else
614 WN = self.delegate('getAvgResidTChain', 1);
615 end
616 end
617
618 function [QN] = getAvgNodeQLenChain(self, Q)
619 if nargin > 1
620 QN = self.delegate('getAvgNodeQLenChain', 1, Q);
621 else
622 QN = self.delegate('getAvgNodeQLenChain', 1);
623 end
624 end
625
626 function [UN] = getAvgNodeUtilChain(self, U)
627 if nargin > 1
628 UN = self.delegate('getAvgNodeUtilChain', 1, U);
629 else
630 UN = self.delegate('getAvgNodeUtilChain', 1);
631 end
632 end
633
634 function [RN] = getAvgNodeRespTChain(self, R)
635 if nargin > 1
636 RN = self.delegate('getAvgNodeRespTChain', 1, R);
637 else
638 RN = self.delegate('getAvgNodeRespTChain', 1);
639 end
640 end
641
642 function [WN] = getAvgNodeResidTChain(self, W)
643 if nargin > 1
644 WN = self.delegate('getAvgNodeResidTChain', 1, W);
645 else
646 WN = self.delegate('getAvgNodeResidTChain', 1);
647 end
648 end
649
650 function [TN] = getAvgNodeTputChain(self, T)
651 if nargin > 1
652 TN = self.delegate('getAvgNodeTputChain', 1, T);
653 else
654 TN = self.delegate('getAvgNodeTputChain', 1);
655 end
656 end
657
658 function [AN] = getAvgNodeArvRChain(self, A)
659 if nargin > 1
660 AN = self.delegate('getAvgNodeArvRChain', 1, A);
661 else
662 AN = self.delegate('getAvgNodeArvRChain', 1);
663 end
664 end
665
666 % Additional table method
667 function [AvgNodeChainTable, QTc, UTc, RTc, WTc, ATc, TTc] = getAvgNodeChainTable(self, Q, U, R, T)
668 if nargin > 1
669 [AvgNodeChainTable, QTc, UTc, RTc, WTc, ATc, TTc] = self.delegate('getAvgNodeChainTable', 7, Q, U, R, T);
670 else
671 [AvgNodeChainTable, QTc, UTc, RTc, WTc, ATc, TTc] = self.delegate('getAvgNodeChainTable', 7);
672 end
673 end
674
675 % Probability method
676 function Pmarg = getProbMarg(self, node, jobclass, state_m)
677 % PMARG = GETPROBMARG(NODE, JOBCLASS, STATE_M)
678 % Return marginalized state probability for station and class
679 Pmarg = self.delegate('getProbMarg', 1, node, jobclass, state_m);
680 end
681
682 % Distribution method
683 function RD = getCdfPassT(self, R)
684 % RD = GETCDFPASST(R)
685 % Return cumulative distribution of passage times at steady-state
686 if nargin > 1
687 RD = self.delegate('getCdfPassT', 1, R);
688 else
689 RD = self.delegate('getCdfPassT', 1);
690 end
691 end
692
693 % Percentile method
694 function [PercRT, PercTable] = getPerctRespT(self, percentiles, jobclass)
695 % [PERCRT, PERCTABLE] = GETPERCTRESPT(SELF, PERCENTILES, JOBCLASS)
696 % Extract response time percentiles from CDF or solver-specific results
697 if nargin < 3
698 [PercRT, PercTable] = self.delegate('getPerctRespT', 2, percentiles);
699 else
700 [PercRT, PercTable] = self.delegate('getPerctRespT', 2, percentiles, jobclass);
701 end
702 end
703
704 % Handle methods
705 function [Q, U, R, T, A, W] = getAvgHandles(self)
706 % [Q,U,R,T,A,W] = GETAVGHANDLES()
707 [Q, U, R, T, A, W] = self.delegate('getAvgHandles', 6);
708 end
709
710 function [Qt, Ut, Tt] = getTranHandles(self)
711 % [QT,UT,TT] = GETTRANHANDLES()
712 [Qt, Ut, Tt] = self.delegate('getTranHandles', 3);
713 end
714
715 function Q = getAvgQLenHandles(self)
716 % Q = GETAVGQLENHANDLES()
717 Q = self.delegate('getAvgQLenHandles', 1);
718 end
719
720 function U = getAvgUtilHandles(self)
721 % U = GETAVGUTILHANDLES()
722 U = self.delegate('getAvgUtilHandles', 1);
723 end
724
725 function R = getAvgRespTHandles(self)
726 % R = GETAVGRESPTHANDLES()
727 R = self.delegate('getAvgRespTHandles', 1);
728 end
729
730 function T = getAvgTputHandles(self)
731 % T = GETAVGTPUTHANDLES()
732 T = self.delegate('getAvgTputHandles', 1);
733 end
734
735 function A = getAvgArvRHandles(self)
736 % A = GETAVGARVRHANDLES()
737 A = self.delegate('getAvgArvRHandles', 1);
738 end
739
740 function W = getAvgResidTHandles(self)
741 % W = GETAVGRESIDTHANDLES()
742 W = self.delegate('getAvgResidTHandles', 1);
743 end
744
745 % Kotlin-style aliases for table methods
746 function avg_table = avgTable(self)
747 % AVGTABLE Kotlin-style alias for getAvgTable
748 avg_table = self.getAvgTable();
749 end
750
751 function avg_sys_table = avgSysTable(self)
752 % AVGSYSTABLE Kotlin-style alias for getAvgSysTable
753 avg_sys_table = self.getAvgSysTable();
754 end
755
756 function avg_node_table = avgNodeTable(self)
757 % AVGNODETABLE Kotlin-style alias for getAvgNodeTable
758 avg_node_table = self.getAvgNodeTable();
759 end
760
761 function avg_chain_table = avgChainTable(self)
762 % AVGCHAINTABLE Kotlin-style alias for getAvgChainTable
763 avg_chain_table = self.getAvgChainTable();
764 end
765
766 function avg_node_chain_table = avgNodeChainTable(self)
767 % AVGNODECHAINTABLE Kotlin-style alias for getAvgNodeChainTable
768 avg_node_chain_table = self.getAvgNodeChainTable();
769 end
770
771 % Table -> T short aliases
772 function avg_table = avgT(self)
773 % AVGT Short alias for avgTable
774 avg_table = self.avgTable();
775 end
776
777 function avg_sys_table = avgSysT(self)
778 % AVGSYST Short alias for avgSysTable
779 avg_sys_table = self.avgSysTable();
780 end
781
782 function avg_node_table = avgNodeT(self)
783 % AVGNODET Short alias for avgNodeTable
784 avg_node_table = self.avgNodeTable();
785 end
786
787 function avg_chain_table = avgChainT(self)
788 % AVGCHAINT Short alias for avgChainTable
789 avg_chain_table = self.avgChainTable();
790 end
791
792 function avg_node_chain_table = avgNodeChainT(self)
793 % AVGNODECHAINT Short alias for avgNodeChainTable
794 avg_node_chain_table = self.avgNodeChainTable();
795 end
796
797 % Kotlin-style aliases for composite methods
798 function varargout = avgChain(self, varargin)
799 % AVGCHAIN Kotlin-style alias for getAvgChain
800 [varargout{1:nargout}] = self.getAvgChain(varargin{:});
801 end
802
803 function varargout = avgSys(self, varargin)
804 % AVGSYS Kotlin-style alias for getAvgSys
805 [varargout{1:nargout}] = self.getAvgSys(varargin{:});
806 end
807
808 function varargout = avgNode(self, varargin)
809 % AVGNODE Kotlin-style alias for getAvgNode
810 [varargout{1:nargout}] = self.getAvgNode(varargin{:});
811 end
812
813 function varargout = avg(self, varargin)
814 % AVG Kotlin-style alias for getAvg
815 [varargout{1:nargout}] = self.getAvg(varargin{:});
816 end
817
818 function sys_resp_time = avgSysRespT(self, varargin)
819 % AVGSYSRESPT Kotlin-style alias for getAvgSysRespT
820 sys_resp_time = self.getAvgSysRespT(varargin{:});
821 end
822
823 function sys_tput = avgSysTput(self, varargin)
824 % AVGSYSTPUT Kotlin-style alias for getAvgSysTput
825 sys_tput = self.getAvgSysTput(varargin{:});
826 end
827
828 % Kotlin-style aliases for chain methods
829 function arvr_chain = avgArvRChain(self, varargin)
830 % AVGARVCHAIN Kotlin-style alias for getAvgArvRChain
831 arvr_chain = self.getAvgArvRChain(varargin{:});
832 end
833
834 function qlen_chain = avgQLenChain(self, varargin)
835 % AVGQLENCHAIN Kotlin-style alias for getAvgQLenChain
836 qlen_chain = self.getAvgQLenChain(varargin{:});
837 end
838
839 function util_chain = avgUtilChain(self, varargin)
840 % AVGUTILCHAIN Kotlin-style alias for getAvgUtilChain
841 util_chain = self.getAvgUtilChain(varargin{:});
842 end
843
844 function resp_t_chain = avgRespTChain(self, varargin)
845 % AVGRESPTCHAIN Kotlin-style alias for getAvgRespTChain
846 resp_t_chain = self.getAvgRespTChain(varargin{:});
847 end
848
849 function resid_t_chain = avgResidTChain(self, varargin)
850 % AVGRESIDTCHAIN Kotlin-style alias for getAvgResidTChain
851 resid_t_chain = self.getAvgResidTChain(varargin{:});
852 end
853
854 function tput_chain = avgTputChain(self, varargin)
855 % AVGTPUTCHAIN Kotlin-style alias for getAvgTputChain
856 tput_chain = self.getAvgTputChain(varargin{:});
857 end
858
859 % Kotlin-style aliases for node chain methods
860 function node_arvr_chain = avgNodeArvRChain(self, varargin)
861 % AVGNODERVRCHAIN Kotlin-style alias for getAvgNodeArvRChain
862 node_arvr_chain = self.getAvgNodeArvRChain(varargin{:});
863 end
864
865 function node_qlen_chain = avgNodeQLenChain(self, varargin)
866 % AVGNODEQLENCHAIN Kotlin-style alias for getAvgNodeQLenChain
867 node_qlen_chain = self.getAvgNodeQLenChain(varargin{:});
868 end
869
870 function node_util_chain = avgNodeUtilChain(self, varargin)
871 % AVGNODEUTILCHAIN Kotlin-style alias for getAvgNodeUtilChain
872 node_util_chain = self.getAvgNodeUtilChain(varargin{:});
873 end
874
875 function node_resp_t_chain = avgNodeRespTChain(self, varargin)
876 % AVGNODERESPTCHAIN Kotlin-style alias for getAvgNodeRespTChain
877 node_resp_t_chain = self.getAvgNodeRespTChain(varargin{:});
878 end
879
880 function node_resid_t_chain = avgNodeResidTChain(self, varargin)
881 % AVGNODERESIDTCHAIN Kotlin-style alias for getAvgNodeResidTChain
882 node_resid_t_chain = self.getAvgNodeResidTChain(varargin{:});
883 end
884
885 function node_tput_chain = avgNodeTputChain(self, varargin)
886 % AVGNODETPUTCHAIN Kotlin-style alias for getAvgNodeTputChain
887 node_tput_chain = self.getAvgNodeTputChain(varargin{:});
888 end
889
890 % Kotlin-style aliases for transient methods
891 function varargout = tranAvg(self, varargin)
892 % TRANAVG Kotlin-style alias for getTranAvg
893 [varargout{1:nargout}] = self.getTranAvg(varargin{:});
894 end
895
896 function rd = tranCdfRespT(self, varargin)
897 % TRANCDFRESPT Kotlin-style alias for getTranCdfRespT
898 rd = self.getTranCdfRespT(varargin{:});
899 end
900
901 function rd = tranCdfPassT(self, varargin)
902 % TRANCDFPASST Kotlin-style alias for getTranCdfPassT
903 rd = self.getTranCdfPassT(varargin{:});
904 end
905
906 function varargout = tranProb(self, varargin)
907 % TRANPROB Kotlin-style alias for getTranProb
908 [varargout{1:nargout}] = self.getTranProb(varargin{:});
909 end
910
911 function varargout = tranProbAggr(self, varargin)
912 % TRANPROBAGGR Kotlin-style alias for getTranProbAggr
913 [varargout{1:nargout}] = self.getTranProbAggr(varargin{:});
914 end
915
916 function varargout = tranProbSys(self)
917 % TRANPROBSYS Kotlin-style alias for getTranProbSys
918 [varargout{1:nargout}] = self.getTranProbSys();
919 end
920
921 function varargout = tranProbSysAggr(self)
922 % TRANPROBSYSAGGR Kotlin-style alias for getTranProbSysAggr
923 [varargout{1:nargout}] = self.getTranProbSysAggr();
924 end
925
926 % Kotlin-style aliases for CDF methods
927 function rd = cdfRespT(self, varargin)
928 % CDFRESPT Kotlin-style alias for getCdfRespT
929 rd = self.getCdfRespT(varargin{:});
930 end
931
932 function rd = cdfPassT(self, varargin)
933 % CDFPASST Kotlin-style alias for getCdfPassT
934 rd = self.getCdfPassT(varargin{:});
935 end
936
937 function varargout = perctRespT(self, varargin)
938 % PERCTRESPT Kotlin-style alias for getPerctRespT
939 [varargout{1:nargout}] = self.getPerctRespT(varargin{:});
940 end
941
942 % Kotlin-style aliases for probability methods
943 function pstate = prob(self, varargin)
944 % PROB Kotlin-style alias for getProb
945 pstate = self.getProb(varargin{:});
946 end
947
948 function psysstate = probSys(self)
949 % PROBSYS Kotlin-style alias for getProbSys
950 psysstate = self.getProbSys();
951 end
952
953 function pnir = probAggr(self, varargin)
954 % PROBAGGR Kotlin-style alias for getProbAggr
955 pnir = self.getProbAggr(varargin{:});
956 end
957
958 function pnjoint = probSysAggr(self)
959 % PROBSYSAGGR Kotlin-style alias for getProbSysAggr
960 pnjoint = self.getProbSysAggr();
961 end
962
963 function pmarg = probMarg(self, varargin)
964 % PROBMARG Kotlin-style alias for getProbMarg
965 pmarg = self.getProbMarg(varargin{:});
966 end
967
968 function lnormconst = probNormConstAggr(self)
969 % PROBNORMCONSTAGGR Kotlin-style alias for getProbNormConstAggr
970 lnormconst = self.getProbNormConstAggr();
971 end
972
973 % Kotlin-style aliases for handle methods
974 function varargout = avgHandles(self)
975 % AVGHANDLES Kotlin-style alias for getAvgHandles
976 [varargout{1:nargout}] = self.getAvgHandles();
977 end
978
979 function varargout = tranHandles(self)
980 % TRANHANDLES Kotlin-style alias for getTranHandles
981 [varargout{1:nargout}] = self.getTranHandles();
982 end
983
984 function q = avgQLenHandles(self)
985 % AVGQLENHANDLES Kotlin-style alias for getAvgQLenHandles
986 q = self.getAvgQLenHandles();
987 end
988
989 function u = avgUtilHandles(self)
990 % AVGUTILHANDLES Kotlin-style alias for getAvgUtilHandles
991 u = self.getAvgUtilHandles();
992 end
993
994 function r = avgRespTHandles(self)
995 % AVGRESPTHANDLES Kotlin-style alias for getAvgRespTHandles
996 r = self.getAvgRespTHandles();
997 end
998
999 function t = avgTputHandles(self)
1000 % AVGTPUTHANDLES Kotlin-style alias for getAvgTputHandles
1001 t = self.getAvgTputHandles();
1002 end
1003
1004 function a = avgArvRHandles(self)
1005 % AVGARVRHANDLES Kotlin-style alias for getAvgArvRHandles
1006 a = self.getAvgArvRHandles();
1007 end
1008
1009 function w = avgResidTHandles(self)
1010 % AVGRESIDTHANDLES Kotlin-style alias for getAvgResidTHandles
1011 w = self.getAvgResidTHandles();
1012 end
1013
1014 % Kotlin-style aliases for basic metric methods
1015 function qn = avgQLen(self)
1016 % AVGQLEN Kotlin-style alias for getAvgQLen
1017 qn = self.getAvgQLen();
1018 end
1019
1020 function un = avgUtil(self)
1021 % AVGUTIL Kotlin-style alias for getAvgUtil
1022 un = self.getAvgUtil();
1023 end
1024
1025 function rn = avgRespT(self)
1026 % AVGRESPT Kotlin-style alias for getAvgRespT
1027 rn = self.getAvgRespT();
1028 end
1029
1030 function wn = avgResidT(self)
1031 % AVGRESIDT Kotlin-style alias for getAvgResidT
1032 wn = self.getAvgResidT();
1033 end
1034
1035 function wt = avgWaitT(self)
1036 % AVGWAITT Kotlin-style alias for getAvgWaitT
1037 wt = self.getAvgWaitT();
1038 end
1039
1040 function tn = avgTput(self)
1041 % AVGTPUT Kotlin-style alias for getAvgTput
1042 tn = self.getAvgTput();
1043 end
1044
1045 function an = avgArvR(self)
1046 % AVGARVR Kotlin-style alias for getAvgArvR
1047 an = self.getAvgArvR();
1048 end
1049
1050 % Kotlin-style aliases for table methods with parameters
1051 function varargout = avgQLenTable(self, varargin)
1052 % AVGQLENTABLE Kotlin-style alias for getAvgQLenTable
1053 [varargout{1:nargout}] = self.getAvgQLenTable(varargin{:});
1054 end
1055
1056 function varargout = avgUtilTable(self, varargin)
1057 % AVGUTILTABLE Kotlin-style alias for getAvgUtilTable
1058 [varargout{1:nargout}] = self.getAvgUtilTable(varargin{:});
1059 end
1060
1061 function varargout = avgRespTTable(self, varargin)
1062 % AVGRESPTTABLE Kotlin-style alias for getAvgRespTTable
1063 [varargout{1:nargout}] = self.getAvgRespTTable(varargin{:});
1064 end
1065
1066 function varargout = avgTputTable(self, varargin)
1067 % AVGTPUTTABLE Kotlin-style alias for getAvgTputTable
1068 [varargout{1:nargout}] = self.getAvgTputTable(varargin{:});
1069 end
1070
1071 %% LayeredNetwork / EnsembleSolver methods
1072 % These methods are available when solving LayeredNetwork models
1073
1074 function [QN, UN, RN, TN, AN, WN] = getEnsembleAvg(self)
1075 % [QN, UN, RN, TN, AN, WN] = GETENSEMBLEAVG()
1076 % Get average performance metrics for LayeredNetwork ensemble models
1077 [QN, UN, RN, TN, AN, WN] = self.delegate('getEnsembleAvg', 6);
1078 end
1079
1080 function solver = getSolver(self, e)
1081 % SOLVER = GETSOLVER(E)
1082 % Get solver for ensemble model e (LayeredNetwork only)
1083 solver = self.delegate('getSolver', 1, e);
1084 end
1085
1086 function solver = setSolver(self, solver, e)
1087 % SOLVER = SETSOLVER(SOLVER, E)
1088 % Set solver for ensemble model e (LayeredNetwork only)
1089 if nargin < 3
1090 solver = self.delegate('setSolver', 1, solver);
1091 else
1092 solver = self.delegate('setSolver', 1, solver, e);
1093 end
1094 end
1095
1096 function E = getNumberOfModels(self)
1097 % E = GETNUMBEROFMODELS()
1098 % Get number of ensemble models (LayeredNetwork only)
1099 E = self.delegate('getNumberOfModels', 1);
1100 end
1101
1102 function it = getIteration(self)
1103 % IT = GETITERATION()
1104 % Get current iteration number (LayeredNetwork only)
1105 it = self.delegate('getIteration', 1);
1106 end
1107
1108 function AvgTables = getEnsembleAvgTables(self)
1109 % AVGTABLES = GETENSEMBLEAVGTABLES()
1110 % Get average tables for all ensemble models (LayeredNetwork only)
1111 AvgTables = self.delegate('getEnsembleAvgTables', 1);
1112 end
1113
1114 function state = get_state(self)
1115 % STATE = GET_STATE()
1116 % Export current solver state for continuation (SolverLN only)
1117 state = self.delegate('get_state', 1);
1118 end
1119
1120 function set_state(self, state)
1121 % SET_STATE(STATE)
1122 % Import solution state for continuation (SolverLN only)
1123 self.delegate('set_state', 0, state);
1124 end
1125
1126 function update_solver(self, solverFactory)
1127 % UPDATE_SOLVER(SOLVERFACTORY)
1128 % Change the solver for all layers (SolverLN only)
1129 self.delegate('update_solver', 0, solverFactory);
1130 end
1131
1132 % Kotlin-style aliases for LayeredNetwork/EnsembleSolver methods
1133 function varargout = ensembleAvg(self)
1134 % ENSEMBLEAVG Kotlin-style alias for getEnsembleAvg
1135 [varargout{1:nargout}] = self.getEnsembleAvg();
1136 end
1137
1138 function solver = solver(self, e)
1139 % SOLVER Kotlin-style alias for getSolver
1140 solver = self.getSolver(e);
1141 end
1142
1143 function it = iteration(self)
1144 % ITERATION Kotlin-style alias for getIteration
1145 it = self.getIteration();
1146 end
1147
1148 function e = numberOfModels(self)
1149 % NUMBEROFMODELS Kotlin-style alias for getNumberOfModels
1150 e = self.getNumberOfModels();
1151 end
1152
1153 function avg_tables = ensembleAvgTables(self)
1154 % ENSEMBLEAVGTABLES Kotlin-style alias for getEnsembleAvgTables
1155 avg_tables = self.getEnsembleAvgTables();
1156 end
1157
1158 function avg_tables = getEnsembleAvgTs(self)
1159 % GETENSEMBLEAVGTS Short alias for getEnsembleAvgTables
1160 avg_tables = self.getEnsembleAvgTables();
1161 end
1162
1163 function avg_tables = ensembleAvgTs(self)
1164 % ENSEMBLEAVGTS Short alias for ensembleAvgTables
1165 avg_tables = self.ensembleAvgTables();
1166 end
1167
1168 end
1169end