1classdef SolverCTMC < NetworkSolver
2 % Continuous-Time Markov Chain solver
for exact state-space analysis
4 % Implements exact analysis of queueing networks via CTMC formulation.
6 % Copyright (c) 2012-2026, Imperial College London
10 function self = SolverCTMC(model,varargin)
11 % SOLVERCTMC Create a CTMC solver instance
13 % @brief Creates a CTMC solver
for exact Markov chain analysis
14 % @param model Network model to be analyzed via CTMC formulation
15 % @param varargin Optional parameters (cutoff, method, etc.)
16 % @
return self SolverCTMC instance configured
for exact analysis
18 % Redirect a LayeredNetwork to
the solvers that accept one. This
19 % must precede
the NetworkSolver constructor: that constructor calls
20 % model.getAvgHandles(), which a LayeredNetwork does not implement,
21 % so
the redirect that used to live in runAnalyzer was unreachable
22 % and
the user saw
"Unrecognized method 'getAvgHandles'" instead.
23 if isa(model,
'LayeredNetwork')
24 line_error(mfilename, ['This model
is a LayeredNetwork. Use SolverLN ', ...
25 '(iterative) or SolverLQNS (external LQNS) instead of SolverCTMC.\n']);
27 self@NetworkSolver(model, mfilename);
28 self.setOptions(Solver.parseOptions(varargin, self.defaultOptions));
32 runtime = runAnalyzer(self, options)
33 Pnir = getProb(self, node, state)
35 Pnir = getProbAggr(self, ist)
37 Pn = getProbSysAggr(self)
38 [Pi_t, SSsysa] = getTranProbSysAggr(self)
39 [Pi_t, SSnode_a] = getTranProbAggr(self, node)
40 [Pi_t, SSsys] = getTranProbSys(self)
41 [Pi_t, SSnode] = getTranProb(self, node)
42 RD = getCdfRespT(self, R)
43 RD = getCdfSysRespT(self)
45 [stateSpace,nodeStateSpace] = getStateSpace(self, options)
46 stateSpaceAggr = getStateSpaceAggr(self)
48 % Reward computation methods
49 [Rt, t, names] = getTranReward(self, rewardName)
50 [R, names] = getAvgReward(self)
51 [V, t, names, stateSpace] = runRewardAnalyzer(self)
53 function [state_space, local_states] = stateSpace(self)
54 % STATESPACE Kotlin-style alias for getStateSpace
56 state_space = self.getStateSpace();
58 [state_space, local_states] = self.getStateSpace();
62 function Q = generator(self)
63 % GENERATOR Kotlin-style alias for getGenerator
64 Q = self.getGenerator();
67 [infGen, eventFilt, synchInfo, stateSpace, nodeStateSpace] = getSymbolicGenerator(self, invertSymbol)
68 [infGen, eventFilt, synchInfo] = getInfGen(self, options)
69 [infGen, eventFilt, synchInfo] = getGenerator(self, options)
71 tstate = sampleSys(self, numevents)
72 sampleAggr = sampleAggr(self, node, numEvents)
74 function MCTMC = getMarkedCTMC(self, options)
75 % MCTMC = GETMARKEDCTMC(options)
78 [infGen, eventFilt, synchInfo] = self.getInfGen();
80 [infGen, eventFilt, synchInfo] = getInfGen(self, options);
83 MCTMC = MarkedMarkovProcess(infGen, eventFilt, synchInfo);
86 function sn = getStruct(self)
89 % Get data structure summarizing
the model
90 sn = self.model.getStruct(true);
94 function [allMethods] = listValidMethods(self)
95 % allMethods = LISTVALIDMETHODS()
96 % List valid methods for this solver
97 sn = self.model.getStruct();
98 % QRF (Quadratic/Linear Reduction) LP-based bounds were moved to
99 % SolverBA (methods qr/lr/qrf.*); SolverCTMC no longer serves them.
100 allMethods = {
'default',
'gpu'};
102 function featSupported = getMethodFeatureSet(self, method) %#ok<INUSD>
103 % All CTMC methods share
the solver-level feature envelope.
105 % Defining
this is what lets NetworkSolver.supportsModelMethod name
106 %
the offending features: with no method feature set it falls back
107 % to
the coarse supports(model), which returns an empty reason, so
108 %
the gate could only report
"features not supported" without
111 % A non-Network model (e.g. a LayeredNetwork) has no
112 % getUsedLangFeatures, so it keeps
the coarse path and any
113 % structural checks or redirects that operate on such models.
114 if ~isa(self.model,
'Network')
118 featSupported = SolverCTMC.getFeatureSet();
126 function featSupported = getFeatureSet()
127 % FEATSUPPORTED = GETFEATURESET()
129 featSupported = SolverFeatureSet;
130 featSupported.setTrue({
'Source',
'Sink',...
131 'ClassSwitch',
'Delay',
'DelayStation',
'Queue',
'Router',...
132 'MAP',
'APH',
'MMPP2',
'MMAP',
'PH',
'Coxian',
'Erlang',
'Exp',
'HyperExp',...
133 'Det',
'Gamma',
'Lognormal',
'Pareto',
'Uniform',
'Weibull',...
134 'StatelessClassSwitcher',
'InfiniteServer',
'SharedServer',
'Buffer',
'Dispatcher',...
135 'Cache',
'CacheClassSwitcher', ...
136 'CacheRetrieval', ...
137 'Server',
'JobSink',
'RandomSource',
'ServiceTunnel',...
138 'SchedStrategy_INF',
'SchedStrategy_PS',...
139 'SchedStrategy_DPS',
'SchedStrategy_GPS',...
140 'SchedStrategy_SIRO',
'SchedStrategy_SEPT',...
141 'SchedStrategy_LEPT',
'SchedStrategy_FCFS',...
142 'SchedStrategy_HOL',
'SchedStrategy_LCFS',...
143 'SchedStrategy_LCFSPR',
'SchedStrategy_LCFSPRPRIO',
'SchedStrategy_FCFSPRPRIO',...
144 'SchedStrategy_PSPRIO',
'SchedStrategy_DPSPRIO',
'SchedStrategy_GPSPRIO',...
145 'SchedStrategy_LPS',...
146 'SchedStrategy_PAS',...
147 'SchedStrategy_OI',...
148 'SchedStrategy_POLLING',...
149 'RoutingStrategy_RROBIN',...
150 'RoutingStrategy_WRROBIN',...
151 'RoutingStrategy_JSQ',...
152 'RoutingStrategy_KCHOICES',...
153 'RoutingStrategy_PROB',
'RoutingStrategy_RAND',...
154 'ReplacementStrategy_RR',
'ReplacementStrategy_FIFO',
'ReplacementStrategy_SFIFO',
'ReplacementStrategy_LRU',...
155 'ReplacementStrategy_HLRU',
'ReplacementStrategy_CLIMB',
'ReplacementStrategy_QLRU',...
156 'ClosedClass',
'SelfLoopingClass',
'OpenClass',
'Replayer',...
157 'OpenSignal',
'ClosedSignal',...
158 'SignalType_NEGATIVE',
'SignalType_CATASTROPHE',...
159 'SignalBatchRemoval',
'SignalRemovalPolicy',...
160 'Place',
'Transition',
'Linkage',
'Enabling',
'Inhibiting',
'Timing',
'Firing',
'Storage',...
161 'Fork',
'Join',
'Forker',
'Joiner',...
162 'Balking',
'Reneging',
'Retrial',...
163 'LoadDependence',
'ClassDependence'});
166 function [bool, featSupported, featUsed] = supports(model)
167 % [BOOL, FEATSUPPORTED, FEATUSED] = SUPPORTS(MODEL)
169 featUsed = model.getUsedLangFeatures();
170 featSupported = SolverCTMC.getFeatureSet();
171 bool = SolverFeatureSet.supports(featSupported, featUsed);
174 function options = defaultOptions()
175 % OPTIONS = DEFAULTOPTIONS()
176 options = SolverOptions('CTMC');
179 function printInfGen(Q,SS)
187 line_printf('\n%s->%s: %f',mat2str(SS(s,:)),mat2str(SS(sp,:)),
double(Q(s,sp)));
194 function printEventFilt(sync,D,SS,myevents)
195 % PRINTEVENTFILT(SYNC,D,SS,MYEVENTS)
197 if nargin<4 %~exist('events','var')
198 myevents = 1:length(sync);
206 line_printf(
'\n%s-- %d: (%d,%d) => (%d,%d) -->%s: %f',mat2str(SS(s,:)),e,sync{e}.active{1}.node,sync{e}.active{1}.class,sync{e}.passive{1}.node,sync{e}.passive{1}.class,mat2str(SS(sp,:)),double(D{e}(s,sp)));
213 function libs = getLibrariesUsed(sn, options) %#ok<INUSD>
214 % GETLIBRARIESUSED Get list of external libraries used by CTMC solver