1function runtime = runAnalyzer(self, options)
8 options = self.getOptions;
10sn = getStruct(self); %
this gets modified later on so pass by copy
12% Convert non-Markovian distributions to PH
13sn = sn_nonmarkov_toph(sn, options);
15orig_method = options.method;
16self.runAnalyzerChecks(options);
17Solver.resetRandomGeneratorSeed(options.seed);
19% Show library attribution
if verbose and not yet shown
20if options.verbose ~= VerboseLevel.SILENT && ~GlobalConstants.isLibraryAttributionShown()
21 libs = SolverFLD.getLibrariesUsed(sn, options);
23 line_printf(
'The solver will leverage %s.\n', strjoin(libs,
', '));
24 GlobalConstants.setLibraryAttributionShown(
true);
28%options.lang =
'java';
30hasOpenClasses = sn_has_open_classes(sn);
33 line_debug(options,
'FLD: using lang=java, delegating to JLINE');
34 jmodel = LINE2JLINE(self.model);
35 %M = jmodel.getNumberOfStatefulNodes;
36 M = jmodel.getNumberOfStations;
37 R = jmodel.getNumberOfClasses;
39 case {
'default',
'closing',
'matrix',
'rmf'}
40 jsolver = JLINE.SolverFluid(jmodel, options);
42 line_warning(mfilename,
'This solver does not support the specified method. Setting to default.\n');
43 options.method =
'default';
44 jsolver = JLINE.SolverFluid(jmodel, options);
46 [QN,UN,RN,WN,AN,TN] = JLINE.arrayListToResults(jsolver.getAvgTable);
50 QN = reshape(QN
',R,M)';
51 UN = reshape(UN
',R,M)';
52 RN = reshape(RN
',R,M)';
53 WN = reshape(WN
',R,M)';
54 AN = reshape(AN
',R,M)';
55 TN = reshape(TN
',R,M)';
58 self.setAvgResults(QN,UN,RN,TN,AN,WN,CN,XN,runtime,options.method,lastiter);
59 self.result.Prob.logNormConstAggr = lG;
60 self.result.solverSpecific.sn = JLINE.from_jline_struct(jmodel);
61 self.result.solverSpecific.odeStateVec = JLINE.from_jline_matrix(jsolver.result.odeStateVec);
64 line_debug(options,
'FLD: using lang=matlab');
66 case {
'matrix',
'pnorm'}
67 line_debug(options,
'FLD method: matrix/pnorm requested');
68 % Matrix method now supports mixed/open models per Ruuskanen et al., PEVA 151 (2021)
70 line_error(mfilename,
'The matrix solver does not support DPS scheduling. Use options.method=''closing'' instead.');
73 options.method =
'closing';
74 line_debug(options,
'FLD method: closing');
76 % Use rmf
for cache models, closing
for DPS, matrix otherwise
77 if any(sn.nodetype == NodeType.Cache)
78 options.method = 'rmf';
80 options.method = 'closing';
82 options.method = 'matrix';
84 line_debug(options, 'FLD default method resolved to: %s', options.method);
85 case {
'statedep',
'softmin'}
86 line_debug(options,
'FLD method: %s', options.method);
88 case {
'diffusion',
'fluid.diffusion'}
89 line_debug(options,
'FLD method: diffusion approximation');
90 % Diffusion approximation - validated in solver_fluid_diffusion
91 %
do nothing here, validation happens in the solver itself
92 case {
'mfq',
'fluid.mfq',
'butools'}
93 line_debug(options,
'FLD method: Markovian fluid queue (BUTools)');
94 % Markovian fluid queue method
using BUTools
for single-queue analysis
95 % Validation and fallback happens in solver_fluid_analyzer
96 case {
'rmf',
'fluid.rmf'}
97 line_debug(options,
'FLD method: refined mean field (cache analysis)');
98 % Refined mean field method
for multi-list cache analysis
99 % Uses DDPP framework with 1/N correction
101 line_error(mfilename,sprintf(
'The ''%s'' method is unsupported by this solver.',options.method));
105if isinf(options.timespan(1))
106 if options.verbose == 2
107 line_warning(mfilename,'%s requires options.timespan(1) to be finite. Setting it to 0.\n',mfilename);
109 options.timespan(1) = 0;
112if options.timespan(1) == options.timespan(2)
113 line_warning(mfilename,'%s: timespan
is a single point, unsupported. Setting options.timespace(1) to 0.\n',mfilename);
114 options.timespan(1) = 0;
117if self.enableChecks && ~self.supports(self.model)
118 line_error(mfilename,'This model contains features not supported by the solver.');
121self.setOptions(options);
128Q = zeros(M,K); R = zeros(M,K); T = zeros(M,K);
129U = zeros(M,K); C = zeros(1,K); X = zeros(1,K);
132s0prior = sn.stateprior;
133s0_sz = cellfun(@(x) size(x,1), s0)';
134s0_id = pprod(s0_sz-1);
136while s0_id>=0 % for all possible initial states
139 if sn.isstateful(ind)
140 isf = sn.nodeToStateful(ind);
141 s0prior_val = s0prior_val * s0prior{isf}(1+s0_id(isf)); % update prior
142 %sn.state{isf} = s0{isf}(1+s0_id(isf),:); % assign initial state to network
143 self.model.nodes{ind}.setState(s0{isf}(1+s0_id(isf),:));
146 sn = self.model.getStruct;
147 sn = sn_nonmarkov_toph(sn, options); % Re-apply conversion after fresh
struct
151 % [Qfull, Ufull, Rfull, Tfull, Cfull, Xfull, t, Qfull_t, Ufull_t, Tfull_t, lastSol] = JLINE.runFluidAnalyzer(self.model, options);
153 [Qfull, Ufull, Rfull, Tfull, Cfull, Xfull, t, Qfull_t, Ufull_t, Tfull_t, lastSol, iter, aoiResults] = solver_fluid_analyzer(sn, options);
156 [t,uniqueIdx] = unique(t);
157 if isempty(lastSol) %
if solution fails
158 Q = NaN*ones(M,K); R = NaN*ones(M,K);
159 T = NaN*ones(M,K); U = NaN*ones(M,K);
160 C = NaN*ones(1,K); X = NaN*ones(1,K);
161 Qt = cell(M,K); Ut = cell(M,K); Tt = cell(M,K);
164 Qt{ist,r} = [NaN,NaN];
165 Ut{ist,r} = [NaN,NaN];
166 Tt{ist,r} = [NaN,NaN];
170 if isempty(self.result) && max(size(Qt))==0 %~exist(
'Qt',
'var')
171 Q = Qfull*s0prior_val;
172 R = Rfull*s0prior_val;
173 T = Tfull*s0prior_val;
174 U = Ufull*s0prior_val;
175 C = Cfull*s0prior_val;
176 X = Xfull*s0prior_val;
182 if ~isempty(Qfull_t{ist,r}) && length(Qfull_t{ist,r}) >= max(uniqueIdx)
183 Qfull_t{ist,r} = Qfull_t{ist,r}(uniqueIdx);
184 Ufull_t{ist,r} = Ufull_t{ist,r}(uniqueIdx);
185 Tfull_t{ist,r} = Tfull_t{ist,r}(uniqueIdx);
186 Qt{ist,r} = [Qfull_t{ist,r} * s0prior_val,t];
187 Ut{ist,r} = [Ufull_t{ist,r} * s0prior_val,t];
188 Tt{ist,r} = [Tfull_t{ist,r} * s0prior_val,t];
190 Qt{ist,r} = [NaN,NaN];
191 Ut{ist,r} = [NaN,NaN];
192 Tt{ist,r} = [NaN,NaN];
197 Q = Q + Qfull*s0prior_val;
198 R = R + Rfull*s0prior_val;
199 T = T + Tfull*s0prior_val;
200 U = U + Ufull*s0prior_val;
201 C = C + Cfull*s0prior_val;
202 X = X + Xfull*s0prior_val;
205 [t,uniqueIdx] = unique(t);
206 Qfull_t{ist,r} = Qfull_t{ist,r}(uniqueIdx);
207 Ufull_t{ist,r} = Ufull_t{ist,r}(uniqueIdx);
208 % Tfull_t{i,r} = Tfull_t{i,r}(uniqueIdx);
210 tunion =
union(Qt{ist,r}(:,2), t);
211 dataOld = interp1(Qt{ist,r}(:,2),Qt{ist,r}(:,1),tunion);
212 dataNew = interp1(t,Qfull_t{ist,r},tunion);
213 Qt{ist,r} = [dataOld + s0prior_val * dataNew, tunion];
215 dataOld = interp1(Ut{ist,r}(:,2),Ut{ist,r}(:,1),tunion);
216 dataNew = interp1(t,Ufull_t{ist,r},tunion);
217 Ut{ist,r} = [dataOld + s0prior_val * dataNew, tunion];
219 % dataOld = interp1(Tt{i,r}(:,2),Tt{i,r}(:,1),tunion);
220 % dataNew = interp1(t,Tfull_t{i,r},tunion);
221 % Tt{i,r} = [dataOld + s0prior_val * dataNew, tunion];
227 s0_id=pprod(s0_id,s0_sz-1); % update initial state
229% Now we restore the original state
231 if sn.isstateful(ind)
232 isf = sn.nodeToStateful(ind);
233 self.model.nodes{ind}.setState(cur_state{isf});
237self.result.solverSpecific = lastSol;
238% Store AoI results
if available
239if exist(
'aoiResults',
'var') && ~isempty(aoiResults)
240 self.result.solverSpecific.aoiResults = aoiResults;
242QN = Q; UN=U; RN=R; TN=T; CN=C; XN=X;
244% For cache models solved with rmf, update hit/miss probs in the model
245if any(strcmp(options.method, {
'rmf',
'fluid.rmf'})) && any(sn.nodetype == NodeType.Cache)
246 caches = find(sn.nodetype == NodeType.Cache);
247 % Retrieve hitprob/missprob from the cacheqn result stored in lastSol
248 if isfield(lastSol, 'cacheHitProb')
249 for cIdx = 1:length(caches)
251 self.model.
nodes{ind}.setResultHitProb(lastSol.cacheHitProb(cIdx,:));
252 self.model.nodes{ind}.setResultMissProb(lastSol.cacheMissProb(cIdx,:));
254 self.model.refreshStruct(
true);
255 sn = self.model.getStruct(
true);
259% Compute average arrival rate at steady-state
260AN = sn_get_arvr_from_tput(sn, TN, self.getAvgTputHandles());
261if strcmp(orig_method,
'default') && ~strcmp(options.method,
'default')
262 self.setAvgResults(QN,UN,RN,TN,AN,[],CN,XN,runtime,['default/',options.method],iter);
264 self.setAvgResults(QN,UN,RN,TN,AN,[],CN,XN,runtime,options.method,iter);
267self.setTranAvgResults(Qt,Ut,Rt,Tt,Ct,Xt,runtime);