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_LDES = 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 'ldes'
151 self.options.method = 'default';
152 self.solvers{1,1} = SolverLDES(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_LDES} = SolverLDES(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 bool = isStochastic(self)
262 % BOOL = ISSTOCHASTIC()
263 % If a delegate solver has already produced results, classify
264 % by the solver that actually ran (which knows the method it
265 % resolved at runtime). Before any run, the delegate choice is
266 % unknown, so classify conservatively: true if any feasible
267 % candidate is stochastic.
268 bool = false;
269 ran = false;
270 for s = 1:length(self.solvers)
271 if ~isempty(self.solvers{s}) && self.solvers{s}.hasResults()
272 ran = true;
273 if self.solvers{s}.isStochastic()
274 bool = true;
275 return;
276 end
277 end
278 end
279 if ~ran
280 if ~isempty(self.candidates)
281 list = self.candidates;
282 else
283 list = self.solvers;
284 end
285 for s = 1:length(list)
286 if ~isempty(list{s}) && list{s}.isStochastic()
287 bool = true;
288 return;
289 end
290 end
291 end
292 end
293
294 function allMethods = listValidMethods(self)
295 % ALLMETHODS = LISTVALIDMETHODS()
296 % List valid methods from all candidate solvers
297 allMethods = {'default', 'auto', 'heur', 'sim', 'exact', 'fast', 'accurate'}; % 'ai' not yet available
298 for s = 1:length(self.solvers)
299 if ~isempty(self.solvers{s})
300 try
301 solverMethods = self.solvers{s}.listValidMethods();
302 allMethods = unique([allMethods, solverMethods]);
303 catch
304 % Solver doesn't implement listValidMethods
305 end
306 end
307 end
308 end
309
310 end
311
312 methods
313 % delegate execution of method to chosen solver
314 varargout = delegate(self, method, nretout, varargin);
315
316 % chooseSolver: choses a solver from static properties of the model
317 solver = chooseSolver(self, method);
318 % Heuristic choice of solver
319 solver = chooseSolverHeur(self, method);
320 % Heuristic choice of solver for Avg* methods
321 solver = chooseAvgSolverHeur(self);
322
323 end
324
325 methods
326 function reset(self)
327 for s=1:length(self.solvers)
328 self.solvers{s}.reset();
329 end
330 end
331 function setChecks(self,bool)
332 for s=1:length(self.solvers)
333 self.solvers{s}.setChecks(bool);
334 end
335 end
336 end
337
338 methods
339 function AvgChainTable = getAvgChainTable(self)
340 % [AVGCHAINTABLE] = GETAVGCHAINTABLE(self)
341 try
342 AvgChainTable = self.delegate('getAvgChainTable', 1);
343 catch
344 line_error(mfilename, 'Fatal error in getAvgChainTable.')
345 end
346 end
347
348 function [AvgQLenTable, QT] = getAvgQLenTable(self, Q, keepDisabled)
349 % [AVGQLENTABLE, QT] = GETAVGQLENTABLE(self, Q, keepDisabled)
350 if nargin < 2
351 Q = [];
352 end
353 if nargin < 3
354 keepDisabled = false;
355 end
356 [AvgQLenTable, QT] = self.delegate('getAvgQLenTable', 2, Q, keepDisabled);
357 end
358
359 function [AvgTputTable, TT] = getAvgTputTable(self, T, keepDisabled)
360 % [AVGTPUTTABLE, TT] = GETAVGTPUTTABLE(self, T, keepDisabled)
361 if nargin < 2
362 T = [];
363 end
364 if nargin < 3
365 keepDisabled = false;
366 end
367 [AvgTputTable, TT] = self.delegate('getAvgTputTable', 2, T, keepDisabled);
368 end
369
370 function [AvgRespTTable, RT] = getAvgRespTTable(self, R, keepDisabled)
371 % [AVGRESPTTABLE, RT] = GETAVGRESPTTABLE(self, R, keepDisabled)
372 if nargin < 2
373 R = [];
374 end
375 if nargin < 3
376 keepDisabled = false;
377 end
378 [AvgRespTTable, RT] = self.delegate('getAvgRespTTable', 2, R, keepDisabled);
379 end
380
381 function [AvgUtilTable, UT] = getAvgUtilTable(self, U, keepDisabled)
382 % [AVGUTILTABLE, UT] = GETAVGUTILTABLE(self, U, keepDisabled)
383 if nargin < 2
384 U = [];
385 end
386 if nargin < 3
387 keepDisabled = false;
388 end
389 [AvgUtilTable, UT] = self.delegate('getAvgUtilTable', 2, U, keepDisabled);
390 end
391
392 function AvgSysTable = getAvgSysTable(self)
393 % [AVGSYSTABLE] = GETAVGSYSTABLE(self)
394 AvgSysTable = self.delegate('getAvgSysTable', 1);
395 end
396
397 function AvgNodeTable = getAvgNodeTable(self)
398 % [AVGNODETABLE] = GETAVGNODETABLE(self)
399 AvgNodeTable = self.delegate('getAvgNodeTable', 1);
400 end
401
402 function AvgTable = getAvgTable(self)
403 % [AVGTABLE] = GETAVGTABLE(self)
404 AvgTable = self.delegate('getAvgTable', 1);
405 end
406
407 function [QN,UN,RN,TN,AN,WN] = getAvg(self,Q,U,R,T)
408 %[QN,UN,RN,TN] = GETAVG(SELF,Q,U,R,T)
409
410 if nargin>1
411 [QN,UN,RN,TN,AN,WN] = self.delegate('getAvg', 6, Q,U,R,T);
412 else
413 [QN,UN,RN,TN,AN,WN] = self.delegate('getAvg', 6);
414 end
415 end
416
417 function [QNc,UNc,RNc,TNc] = getAvgChain(self,Q,U,R,T)
418 %[QNC,UNC,RNC,TNC] = GETAVGCHAIN(SELF,Q,U,R,T)
419
420 if nargin>1
421 [QNc,UNc,RNc,TNc] = self.delegate('getAvgChain', 4, Q,U,R,T);
422 else
423 [QNc,UNc,RNc,TNc] = self.delegate('getAvgChain', 4);
424 end
425 end
426
427 function [CNc,XNc] = getAvgSys(self,R,T)
428 %[CNC,XNC] = GETAVGSYS(SELF,R,T)
429
430 if nargin>1
431 [CNc,XNc] = self.delegate('getAvgSys', 2, R,T);
432 else
433 [CNc,XNc] = self.delegate('getAvgSys', 2);
434 end
435 end
436
437 function [QN,UN,RN,TN,AN,WN] = getAvgNode(self,Q,U,R,T,A)
438 if nargin>1
439 [QN,UN,RN,TN,AN,WN] = self.delegate('getAvgNode', 6, Q,U,R,T,A);
440 else
441 [QN,UN,RN,TN,AN,WN] = self.delegate('getAvgNode', 6);
442 end
443 end
444
445 function [AN] = getAvgArvRChain(self,A)
446 if nargin>1
447 AN = self.delegate('getAvgArvRChain', 1, A);
448 else
449 AN = self.delegate('getAvgArvRChain', 1);
450 end
451 end
452
453 function [QN] = getAvgQLenChain(self,Q)
454 if nargin>1
455 QN = self.delegate('getAvgQLenChain', 1, Q);
456 else
457 QN = self.delegate('getAvgQLenChain', 1);
458 end
459 end
460
461 function [UN] = getAvgUtilChain(self,U)
462 if nargin>1
463 UN = self.delegate('getAvgUtilChain', 1, U);
464 else
465 UN = self.delegate('getAvgUtilChain', 1);
466 end
467 end
468
469 function [RN] = getAvgRespTChain(self,R)
470 if nargin>1
471 RN = self.delegate('getAvgRespTChain', 1, R);
472 else
473 RN = self.delegate('getAvgRespTChain', 1);
474 end
475 end
476
477 function [TN] = getAvgTputChain(self,T)
478 if nargin>1
479 TN = self.delegate('getAvgTputChain', 1, T);
480 else
481 TN = self.delegate('getAvgTputChain', 1);
482 end
483 end
484
485 function [RN] = getAvgSysRespT(self,R)
486 if nargin>1
487 RN = self.delegate('getAvgSysRespT', 1, R);
488 else
489 RN = self.delegate('getAvgSysRespT', 1);
490 end
491 end
492
493 function [TN] = getAvgSysTput(self,T)
494 if nargin>1
495 TN = self.delegate('getAvgSysTput', 1, T);
496 else
497 TN = self.delegate('getAvgSysTput', 1);
498 end
499 end
500
501 function [QNt,UNt,TNt] = getTranAvg(self,Qt,Ut,Tt)
502 % [QNT,UNT,TNT] = GETTRANAVG(SELF,QT,UT,TT)
503
504 if nargin>1
505 [QNt,UNt,TNt] = self.delegate('getTranAvg', 3, Qt,Ut,Tt);
506 else
507 [QNt,UNt,TNt] = self.delegate('getTranAvg', 3);
508 end
509 end
510
511 function RD = getTranCdfPassT(self, R)
512 % RD = GETTRANCDFPASST(R)
513
514 if nargin>1
515 RD = self.delegate('getTranCdfPassT', 1, R);
516 else
517 RD = self.delegate('getTranCdfPassT', 1);
518 end
519 end
520
521 function RD = getTranCdfRespT(self, R)
522 % RD = GETTRANCDFRESPT(R)
523
524 if nargin>1
525 RD = self.delegate('getTranCdfRespT', 1, R);
526 else
527 RD = self.delegate('getTranCdfRespT', 1);
528 end
529 end
530
531 function [Pi_t, SSnode] = getTranProb(self, node)
532 % [PI, SS] = GETTRANPROB(NODE)
533 [Pi_t, SSnode] = self.delegate('getTranProb', 2, node);
534 end
535
536 function [Pi_t, SSnode_a] = getTranProbAggr(self, node)
537 % [PI, SS] = GETTRANPROBAGGR(NODE)
538 [Pi_t, SSnode_a] = self.delegate('getTranProbAggr', 2, node);
539 end
540
541 function [Pi_t, SSsys] = getTranProbSys(self)
542 % [PI, SS] = GETTRANPROBSYS()
543 [Pi_t, SSsys] = self.delegate('getTranProbSys', 2);
544 end
545
546 function [Pi_t, SSsysa] = getTranProbSysAggr(self)
547 % [PI, SS] = GETTRANPROBSYSAGGR()
548 [Pi_t, SSsysa] = self.delegate('getTranProbSysAggr', 2);
549 end
550
551 function sampleNodeState = sample(self, node, numEvents)
552 sampleNodeState = self.delegate('sample', 1, node, numEvents);
553 end
554
555 function stationStateAggr = sampleAggr(self, node, numEvents)
556 stationStateAggr = self.delegate('sampleAggr', 1, node, numEvents);
557 end
558
559 function tranSysState = sampleSys(self, numEvents)
560 tranSysState = self.delegate('sampleSys', 1, numEvents);
561 end
562
563 function sysStateAggr = sampleSysAggr(self, numEvents)
564 sysStateAggr = self.delegate('sampleSysAggr', 1, numEvents);
565 end
566
567 function RD = getCdfRespT(self, R)
568 if nargin>1
569 RD = self.delegate('getCdfRespT', 1, R);
570 else
571 RD = self.delegate('getCdfRespT', 1);
572 end
573 end
574
575 function Pnir = getProb(self, node, state)
576 Pnir = self.delegate('getProb', 1, node, state);
577 end
578
579 function Pnir = getProbAggr(self, node, state_a)
580 Pnir = self.delegate('getProbAggr', 1, node, state_a);
581 end
582
583 function Pn = getProbSys(self)
584 Pn = self.delegate('getProbSys',1);
585 end
586
587 function Pn = getProbSysAggr(self)
588 Pn = self.delegate('getProbSysAggr',1);
589 end
590
591 function [logNormConst] = getProbNormConstAggr(self)
592 logNormConst = self.delegate('getProbNormConstAggr',1);
593 end
594
595 % Basic metric methods
596 function QN = getAvgQLen(self)
597 % QN = GETAVGQLEN()
598 % Compute average queue-lengths at steady-state
599 QN = self.delegate('getAvgQLen', 1);
600 end
601
602 function UN = getAvgUtil(self)
603 % UN = GETAVGUTIL()
604 % Compute average utilizations at steady-state
605 UN = self.delegate('getAvgUtil', 1);
606 end
607
608 function RN = getAvgRespT(self)
609 % RN = GETAVGRESPT()
610 % Compute average response times at steady-state
611 RN = self.delegate('getAvgRespT', 1);
612 end
613
614 function WN = getAvgResidT(self)
615 % WN = GETAVGRESIDT()
616 % Compute average residence times at steady-state
617 WN = self.delegate('getAvgResidT', 1);
618 end
619
620 function WT = getAvgWaitT(self)
621 % WT = GETAVGWAITT()
622 % Compute average waiting time in queue excluding service
623 WT = self.delegate('getAvgWaitT', 1);
624 end
625
626 function TN = getAvgTput(self)
627 % TN = GETAVGTPUT()
628 % Compute average throughputs at steady-state
629 TN = self.delegate('getAvgTput', 1);
630 end
631
632 function AN = getAvgArvR(self)
633 % AN = GETAVGARVR()
634 % Compute average arrival rate at steady-state
635 AN = self.delegate('getAvgArvR', 1);
636 end
637
638 % Additional chain methods
639 function [WN] = getAvgResidTChain(self, W)
640 if nargin > 1
641 WN = self.delegate('getAvgResidTChain', 1, W);
642 else
643 WN = self.delegate('getAvgResidTChain', 1);
644 end
645 end
646
647 function [QN] = getAvgNodeQLenChain(self, Q)
648 if nargin > 1
649 QN = self.delegate('getAvgNodeQLenChain', 1, Q);
650 else
651 QN = self.delegate('getAvgNodeQLenChain', 1);
652 end
653 end
654
655 function [UN] = getAvgNodeUtilChain(self, U)
656 if nargin > 1
657 UN = self.delegate('getAvgNodeUtilChain', 1, U);
658 else
659 UN = self.delegate('getAvgNodeUtilChain', 1);
660 end
661 end
662
663 function [RN] = getAvgNodeRespTChain(self, R)
664 if nargin > 1
665 RN = self.delegate('getAvgNodeRespTChain', 1, R);
666 else
667 RN = self.delegate('getAvgNodeRespTChain', 1);
668 end
669 end
670
671 function [WN] = getAvgNodeResidTChain(self, W)
672 if nargin > 1
673 WN = self.delegate('getAvgNodeResidTChain', 1, W);
674 else
675 WN = self.delegate('getAvgNodeResidTChain', 1);
676 end
677 end
678
679 function [TN] = getAvgNodeTputChain(self, T)
680 if nargin > 1
681 TN = self.delegate('getAvgNodeTputChain', 1, T);
682 else
683 TN = self.delegate('getAvgNodeTputChain', 1);
684 end
685 end
686
687 function [AN] = getAvgNodeArvRChain(self, A)
688 if nargin > 1
689 AN = self.delegate('getAvgNodeArvRChain', 1, A);
690 else
691 AN = self.delegate('getAvgNodeArvRChain', 1);
692 end
693 end
694
695 % Additional table method
696 function [AvgNodeChainTable, QTc, UTc, RTc, WTc, ATc, TTc] = getAvgNodeChainTable(self, Q, U, R, T)
697 if nargin > 1
698 [AvgNodeChainTable, QTc, UTc, RTc, WTc, ATc, TTc] = self.delegate('getAvgNodeChainTable', 7, Q, U, R, T);
699 else
700 [AvgNodeChainTable, QTc, UTc, RTc, WTc, ATc, TTc] = self.delegate('getAvgNodeChainTable', 7);
701 end
702 end
703
704 % Probability method
705 function Pmarg = getProbMarg(self, node, jobclass, state_m)
706 % PMARG = GETPROBMARG(NODE, JOBCLASS, STATE_M)
707 % Return marginalized state probability for station and class
708 Pmarg = self.delegate('getProbMarg', 1, node, jobclass, state_m);
709 end
710
711 % Distribution method
712 function RD = getCdfPassT(self, R)
713 % RD = GETCDFPASST(R)
714 % Return cumulative distribution of passage times at steady-state
715 if nargin > 1
716 RD = self.delegate('getCdfPassT', 1, R);
717 else
718 RD = self.delegate('getCdfPassT', 1);
719 end
720 end
721
722 % Percentile method
723 function [PercRT, PercTable] = getPerctRespT(self, percentiles, jobclass)
724 % [PERCRT, PERCTABLE] = GETPERCTRESPT(SELF, PERCENTILES, JOBCLASS)
725 % Extract response time percentiles from CDF or solver-specific results
726 if nargin < 3
727 [PercRT, PercTable] = self.delegate('getPerctRespT', 2, percentiles);
728 else
729 [PercRT, PercTable] = self.delegate('getPerctRespT', 2, percentiles, jobclass);
730 end
731 end
732
733 % Handle methods
734 function [Q, U, R, T, A, W] = getAvgHandles(self)
735 % [Q,U,R,T,A,W] = GETAVGHANDLES()
736 [Q, U, R, T, A, W] = self.delegate('getAvgHandles', 6);
737 end
738
739 function [Qt, Ut, Tt] = getTranHandles(self)
740 % [QT,UT,TT] = GETTRANHANDLES()
741 [Qt, Ut, Tt] = self.delegate('getTranHandles', 3);
742 end
743
744 function Q = getAvgQLenHandles(self)
745 % Q = GETAVGQLENHANDLES()
746 Q = self.delegate('getAvgQLenHandles', 1);
747 end
748
749 function U = getAvgUtilHandles(self)
750 % U = GETAVGUTILHANDLES()
751 U = self.delegate('getAvgUtilHandles', 1);
752 end
753
754 function R = getAvgRespTHandles(self)
755 % R = GETAVGRESPTHANDLES()
756 R = self.delegate('getAvgRespTHandles', 1);
757 end
758
759 function T = getAvgTputHandles(self)
760 % T = GETAVGTPUTHANDLES()
761 T = self.delegate('getAvgTputHandles', 1);
762 end
763
764 function A = getAvgArvRHandles(self)
765 % A = GETAVGARVRHANDLES()
766 A = self.delegate('getAvgArvRHandles', 1);
767 end
768
769 function W = getAvgResidTHandles(self)
770 % W = GETAVGRESIDTHANDLES()
771 W = self.delegate('getAvgResidTHandles', 1);
772 end
773
774 % Kotlin-style aliases for table methods
775 function avg_table = avgTable(self)
776 % AVGTABLE Kotlin-style alias for getAvgTable
777 avg_table = self.getAvgTable();
778 end
779
780 function avg_sys_table = avgSysTable(self)
781 % AVGSYSTABLE Kotlin-style alias for getAvgSysTable
782 avg_sys_table = self.getAvgSysTable();
783 end
784
785 function avg_node_table = avgNodeTable(self)
786 % AVGNODETABLE Kotlin-style alias for getAvgNodeTable
787 avg_node_table = self.getAvgNodeTable();
788 end
789
790 function avg_chain_table = avgChainTable(self)
791 % AVGCHAINTABLE Kotlin-style alias for getAvgChainTable
792 avg_chain_table = self.getAvgChainTable();
793 end
794
795 function avg_node_chain_table = avgNodeChainTable(self)
796 % AVGNODECHAINTABLE Kotlin-style alias for getAvgNodeChainTable
797 avg_node_chain_table = self.getAvgNodeChainTable();
798 end
799
800 % Table -> T short aliases
801 function avg_table = avgT(self)
802 % AVGT Short alias for avgTable
803 avg_table = self.avgTable();
804 end
805
806 function avg_sys_table = avgSysT(self)
807 % AVGSYST Short alias for avgSysTable
808 avg_sys_table = self.avgSysTable();
809 end
810
811 function avg_node_table = avgNodeT(self)
812 % AVGNODET Short alias for avgNodeTable
813 avg_node_table = self.avgNodeTable();
814 end
815
816 function avg_chain_table = avgChainT(self)
817 % AVGCHAINT Short alias for avgChainTable
818 avg_chain_table = self.avgChainTable();
819 end
820
821 function avg_node_chain_table = avgNodeChainT(self)
822 % AVGNODECHAINT Short alias for avgNodeChainTable
823 avg_node_chain_table = self.avgNodeChainTable();
824 end
825
826 % Kotlin-style aliases for composite methods
827 function varargout = avgChain(self, varargin)
828 % AVGCHAIN Kotlin-style alias for getAvgChain
829 [varargout{1:nargout}] = self.getAvgChain(varargin{:});
830 end
831
832 function varargout = avgSys(self, varargin)
833 % AVGSYS Kotlin-style alias for getAvgSys
834 [varargout{1:nargout}] = self.getAvgSys(varargin{:});
835 end
836
837 function varargout = avgNode(self, varargin)
838 % AVGNODE Kotlin-style alias for getAvgNode
839 [varargout{1:nargout}] = self.getAvgNode(varargin{:});
840 end
841
842 function varargout = avg(self, varargin)
843 % AVG Kotlin-style alias for getAvg
844 [varargout{1:nargout}] = self.getAvg(varargin{:});
845 end
846
847 function sys_resp_time = avgSysRespT(self, varargin)
848 % AVGSYSRESPT Kotlin-style alias for getAvgSysRespT
849 sys_resp_time = self.getAvgSysRespT(varargin{:});
850 end
851
852 function sys_tput = avgSysTput(self, varargin)
853 % AVGSYSTPUT Kotlin-style alias for getAvgSysTput
854 sys_tput = self.getAvgSysTput(varargin{:});
855 end
856
857 % Kotlin-style aliases for chain methods
858 function arvr_chain = avgArvRChain(self, varargin)
859 % AVGARVCHAIN Kotlin-style alias for getAvgArvRChain
860 arvr_chain = self.getAvgArvRChain(varargin{:});
861 end
862
863 function qlen_chain = avgQLenChain(self, varargin)
864 % AVGQLENCHAIN Kotlin-style alias for getAvgQLenChain
865 qlen_chain = self.getAvgQLenChain(varargin{:});
866 end
867
868 function util_chain = avgUtilChain(self, varargin)
869 % AVGUTILCHAIN Kotlin-style alias for getAvgUtilChain
870 util_chain = self.getAvgUtilChain(varargin{:});
871 end
872
873 function resp_t_chain = avgRespTChain(self, varargin)
874 % AVGRESPTCHAIN Kotlin-style alias for getAvgRespTChain
875 resp_t_chain = self.getAvgRespTChain(varargin{:});
876 end
877
878 function resid_t_chain = avgResidTChain(self, varargin)
879 % AVGRESIDTCHAIN Kotlin-style alias for getAvgResidTChain
880 resid_t_chain = self.getAvgResidTChain(varargin{:});
881 end
882
883 function tput_chain = avgTputChain(self, varargin)
884 % AVGTPUTCHAIN Kotlin-style alias for getAvgTputChain
885 tput_chain = self.getAvgTputChain(varargin{:});
886 end
887
888 % Kotlin-style aliases for node chain methods
889 function node_arvr_chain = avgNodeArvRChain(self, varargin)
890 % AVGNODERVRCHAIN Kotlin-style alias for getAvgNodeArvRChain
891 node_arvr_chain = self.getAvgNodeArvRChain(varargin{:});
892 end
893
894 function node_qlen_chain = avgNodeQLenChain(self, varargin)
895 % AVGNODEQLENCHAIN Kotlin-style alias for getAvgNodeQLenChain
896 node_qlen_chain = self.getAvgNodeQLenChain(varargin{:});
897 end
898
899 function node_util_chain = avgNodeUtilChain(self, varargin)
900 % AVGNODEUTILCHAIN Kotlin-style alias for getAvgNodeUtilChain
901 node_util_chain = self.getAvgNodeUtilChain(varargin{:});
902 end
903
904 function node_resp_t_chain = avgNodeRespTChain(self, varargin)
905 % AVGNODERESPTCHAIN Kotlin-style alias for getAvgNodeRespTChain
906 node_resp_t_chain = self.getAvgNodeRespTChain(varargin{:});
907 end
908
909 function node_resid_t_chain = avgNodeResidTChain(self, varargin)
910 % AVGNODERESIDTCHAIN Kotlin-style alias for getAvgNodeResidTChain
911 node_resid_t_chain = self.getAvgNodeResidTChain(varargin{:});
912 end
913
914 function node_tput_chain = avgNodeTputChain(self, varargin)
915 % AVGNODETPUTCHAIN Kotlin-style alias for getAvgNodeTputChain
916 node_tput_chain = self.getAvgNodeTputChain(varargin{:});
917 end
918
919 % Kotlin-style aliases for transient methods
920 function varargout = tranAvg(self, varargin)
921 % TRANAVG Kotlin-style alias for getTranAvg
922 [varargout{1:nargout}] = self.getTranAvg(varargin{:});
923 end
924
925 function rd = tranCdfRespT(self, varargin)
926 % TRANCDFRESPT Kotlin-style alias for getTranCdfRespT
927 rd = self.getTranCdfRespT(varargin{:});
928 end
929
930 function rd = tranCdfPassT(self, varargin)
931 % TRANCDFPASST Kotlin-style alias for getTranCdfPassT
932 rd = self.getTranCdfPassT(varargin{:});
933 end
934
935 function varargout = tranProb(self, varargin)
936 % TRANPROB Kotlin-style alias for getTranProb
937 [varargout{1:nargout}] = self.getTranProb(varargin{:});
938 end
939
940 function varargout = tranProbAggr(self, varargin)
941 % TRANPROBAGGR Kotlin-style alias for getTranProbAggr
942 [varargout{1:nargout}] = self.getTranProbAggr(varargin{:});
943 end
944
945 function varargout = tranProbSys(self)
946 % TRANPROBSYS Kotlin-style alias for getTranProbSys
947 [varargout{1:nargout}] = self.getTranProbSys();
948 end
949
950 function varargout = tranProbSysAggr(self)
951 % TRANPROBSYSAGGR Kotlin-style alias for getTranProbSysAggr
952 [varargout{1:nargout}] = self.getTranProbSysAggr();
953 end
954
955 % Kotlin-style aliases for CDF methods
956 function rd = cdfRespT(self, varargin)
957 % CDFRESPT Kotlin-style alias for getCdfRespT
958 rd = self.getCdfRespT(varargin{:});
959 end
960
961 function rd = cdfPassT(self, varargin)
962 % CDFPASST Kotlin-style alias for getCdfPassT
963 rd = self.getCdfPassT(varargin{:});
964 end
965
966 function varargout = perctRespT(self, varargin)
967 % PERCTRESPT Kotlin-style alias for getPerctRespT
968 [varargout{1:nargout}] = self.getPerctRespT(varargin{:});
969 end
970
971 % Kotlin-style aliases for probability methods
972 function pstate = prob(self, varargin)
973 % PROB Kotlin-style alias for getProb
974 pstate = self.getProb(varargin{:});
975 end
976
977 function psysstate = probSys(self)
978 % PROBSYS Kotlin-style alias for getProbSys
979 psysstate = self.getProbSys();
980 end
981
982 function pnir = probAggr(self, varargin)
983 % PROBAGGR Kotlin-style alias for getProbAggr
984 pnir = self.getProbAggr(varargin{:});
985 end
986
987 function pnjoint = probSysAggr(self)
988 % PROBSYSAGGR Kotlin-style alias for getProbSysAggr
989 pnjoint = self.getProbSysAggr();
990 end
991
992 function pmarg = probMarg(self, varargin)
993 % PROBMARG Kotlin-style alias for getProbMarg
994 pmarg = self.getProbMarg(varargin{:});
995 end
996
997 function lnormconst = probNormConstAggr(self)
998 % PROBNORMCONSTAGGR Kotlin-style alias for getProbNormConstAggr
999 lnormconst = self.getProbNormConstAggr();
1000 end
1001
1002 % Kotlin-style aliases for handle methods
1003 function varargout = avgHandles(self)
1004 % AVGHANDLES Kotlin-style alias for getAvgHandles
1005 [varargout{1:nargout}] = self.getAvgHandles();
1006 end
1007
1008 function varargout = tranHandles(self)
1009 % TRANHANDLES Kotlin-style alias for getTranHandles
1010 [varargout{1:nargout}] = self.getTranHandles();
1011 end
1012
1013 function q = avgQLenHandles(self)
1014 % AVGQLENHANDLES Kotlin-style alias for getAvgQLenHandles
1015 q = self.getAvgQLenHandles();
1016 end
1017
1018 function u = avgUtilHandles(self)
1019 % AVGUTILHANDLES Kotlin-style alias for getAvgUtilHandles
1020 u = self.getAvgUtilHandles();
1021 end
1022
1023 function r = avgRespTHandles(self)
1024 % AVGRESPTHANDLES Kotlin-style alias for getAvgRespTHandles
1025 r = self.getAvgRespTHandles();
1026 end
1027
1028 function t = avgTputHandles(self)
1029 % AVGTPUTHANDLES Kotlin-style alias for getAvgTputHandles
1030 t = self.getAvgTputHandles();
1031 end
1032
1033 function a = avgArvRHandles(self)
1034 % AVGARVRHANDLES Kotlin-style alias for getAvgArvRHandles
1035 a = self.getAvgArvRHandles();
1036 end
1037
1038 function w = avgResidTHandles(self)
1039 % AVGRESIDTHANDLES Kotlin-style alias for getAvgResidTHandles
1040 w = self.getAvgResidTHandles();
1041 end
1042
1043 % Kotlin-style aliases for basic metric methods
1044 function qn = avgQLen(self)
1045 % AVGQLEN Kotlin-style alias for getAvgQLen
1046 qn = self.getAvgQLen();
1047 end
1048
1049 function un = avgUtil(self)
1050 % AVGUTIL Kotlin-style alias for getAvgUtil
1051 un = self.getAvgUtil();
1052 end
1053
1054 function rn = avgRespT(self)
1055 % AVGRESPT Kotlin-style alias for getAvgRespT
1056 rn = self.getAvgRespT();
1057 end
1058
1059 function wn = avgResidT(self)
1060 % AVGRESIDT Kotlin-style alias for getAvgResidT
1061 wn = self.getAvgResidT();
1062 end
1063
1064 function wt = avgWaitT(self)
1065 % AVGWAITT Kotlin-style alias for getAvgWaitT
1066 wt = self.getAvgWaitT();
1067 end
1068
1069 function tn = avgTput(self)
1070 % AVGTPUT Kotlin-style alias for getAvgTput
1071 tn = self.getAvgTput();
1072 end
1073
1074 function an = avgArvR(self)
1075 % AVGARVR Kotlin-style alias for getAvgArvR
1076 an = self.getAvgArvR();
1077 end
1078
1079 % Kotlin-style aliases for table methods with parameters
1080 function varargout = avgQLenTable(self, varargin)
1081 % AVGQLENTABLE Kotlin-style alias for getAvgQLenTable
1082 [varargout{1:nargout}] = self.getAvgQLenTable(varargin{:});
1083 end
1084
1085 function varargout = avgUtilTable(self, varargin)
1086 % AVGUTILTABLE Kotlin-style alias for getAvgUtilTable
1087 [varargout{1:nargout}] = self.getAvgUtilTable(varargin{:});
1088 end
1089
1090 function varargout = avgRespTTable(self, varargin)
1091 % AVGRESPTTABLE Kotlin-style alias for getAvgRespTTable
1092 [varargout{1:nargout}] = self.getAvgRespTTable(varargin{:});
1093 end
1094
1095 function varargout = avgTputTable(self, varargin)
1096 % AVGTPUTTABLE Kotlin-style alias for getAvgTputTable
1097 [varargout{1:nargout}] = self.getAvgTputTable(varargin{:});
1098 end
1099
1100 %% LayeredNetwork / EnsembleSolver methods
1101 % These methods are available when solving LayeredNetwork models
1102
1103 function [QN, UN, RN, TN, AN, WN] = getEnsembleAvg(self)
1104 % [QN, UN, RN, TN, AN, WN] = GETENSEMBLEAVG()
1105 % Get average performance metrics for LayeredNetwork ensemble models
1106 [QN, UN, RN, TN, AN, WN] = self.delegate('getEnsembleAvg', 6);
1107 end
1108
1109 function solver = getSolver(self, e)
1110 % SOLVER = GETSOLVER(E)
1111 % Get solver for ensemble model e (LayeredNetwork only)
1112 solver = self.delegate('getSolver', 1, e);
1113 end
1114
1115 function solver = setSolver(self, solver, e)
1116 % SOLVER = SETSOLVER(SOLVER, E)
1117 % Set solver for ensemble model e (LayeredNetwork only)
1118 if nargin < 3
1119 solver = self.delegate('setSolver', 1, solver);
1120 else
1121 solver = self.delegate('setSolver', 1, solver, e);
1122 end
1123 end
1124
1125 function E = getNumberOfModels(self)
1126 % E = GETNUMBEROFMODELS()
1127 % Get number of ensemble models (LayeredNetwork only)
1128 E = self.delegate('getNumberOfModels', 1);
1129 end
1130
1131 function it = getIteration(self)
1132 % IT = GETITERATION()
1133 % Get current iteration number (LayeredNetwork only)
1134 it = self.delegate('getIteration', 1);
1135 end
1136
1137 function AvgTables = getEnsembleAvgTables(self)
1138 % AVGTABLES = GETENSEMBLEAVGTABLES()
1139 % Get average tables for all ensemble models (LayeredNetwork only)
1140 AvgTables = self.delegate('getEnsembleAvgTables', 1);
1141 end
1142
1143 function state = get_state(self)
1144 % STATE = GET_STATE()
1145 % Export current solver state for continuation (SolverLN only)
1146 state = self.delegate('get_state', 1);
1147 end
1148
1149 function set_state(self, state)
1150 % SET_STATE(STATE)
1151 % Import solution state for continuation (SolverLN only)
1152 self.delegate('set_state', 0, state);
1153 end
1154
1155 function update_solver(self, solverFactory)
1156 % UPDATE_SOLVER(SOLVERFACTORY)
1157 % Change the solver for all layers (SolverLN only)
1158 self.delegate('update_solver', 0, solverFactory);
1159 end
1160
1161 % Kotlin-style aliases for LayeredNetwork/EnsembleSolver methods
1162 function varargout = ensembleAvg(self)
1163 % ENSEMBLEAVG Kotlin-style alias for getEnsembleAvg
1164 [varargout{1:nargout}] = self.getEnsembleAvg();
1165 end
1166
1167 function solver = solver(self, e)
1168 % SOLVER Kotlin-style alias for getSolver
1169 solver = self.getSolver(e);
1170 end
1171
1172 function it = iteration(self)
1173 % ITERATION Kotlin-style alias for getIteration
1174 it = self.getIteration();
1175 end
1176
1177 function e = numberOfModels(self)
1178 % NUMBEROFMODELS Kotlin-style alias for getNumberOfModels
1179 e = self.getNumberOfModels();
1180 end
1181
1182 function avg_tables = ensembleAvgTables(self)
1183 % ENSEMBLEAVGTABLES Kotlin-style alias for getEnsembleAvgTables
1184 avg_tables = self.getEnsembleAvgTables();
1185 end
1186
1187 function avg_tables = getEnsembleAvgTs(self)
1188 % GETENSEMBLEAVGTS Short alias for getEnsembleAvgTables
1189 avg_tables = self.getEnsembleAvgTables();
1190 end
1191
1192 function avg_tables = ensembleAvgTs(self)
1193 % ENSEMBLEAVGTS Short alias for ensembleAvgTables
1194 avg_tables = self.ensembleAvgTables();
1195 end
1196
1197 end
1198end
Definition Station.m:245