1function runtime = runAnalyzer(self, options)
5 options = self.getOptions;
9self.runAnalyzerChecks(options);
10Solver.resetRandomGeneratorSeed(options.seed);
12% Show library attribution
if verbose and not yet shown
13if options.verbose ~= VerboseLevel.SILENT && ~GlobalConstants.isLibraryAttributionShown()
14 sn = self.getStruct();
15 libs = SolverNC.getLibrariesUsed(sn, options);
17 line_printf(
'The solver will leverage %s.\n', strjoin(libs,
', '));
18 GlobalConstants.setLibraryAttributionShown(
true);
22origmethod = options.method;
24%options.lang =
'java';
28 line_debug(options,
'NC: using lang=java, delegating to JLINE');
30 jmodel = LINE2JLINE(self.model);
31 %M = jmodel.getNumberOfStatefulNodes;
32 M = jmodel.getNumberOfStations;
33 R = jmodel.getNumberOfClasses;
34 jsolver = JLINE.SolverNC(jmodel, options);
35 [QN,UN,RN,WN,AN,TN] = JLINE.arrayListToResults(jsolver.getAvgTable);
36 runtime = jsolver.result.runtime;
39 QN = reshape(QN
',R,M)';
40 UN = reshape(UN
',R,M)';
41 RN = reshape(RN
',R,M)';
42 TN = reshape(TN
',R,M)';
43 WN = reshape(WN
',R,M)';
44 AN = reshape(AN
',R,M)';
48 if sn.nodetype(ind) == NodeType.Cache
49 self.model.nodes{ind}.setResultHitProb(JLINE.from_jline_matrix(jmodel.getNodeByIndex(ind-1).getHitRatio()));
50 self.model.nodes{ind}.setResultMissProb(JLINE.from_jline_matrix(jmodel.getNodeByIndex(ind-1).getMissRatio()));
53 %self.model.refreshChains();
54 self.model.refreshStruct(
true);
55 self.setAvgResults(QN,UN,RN,TN,AN,WN,CN,XN,runtime,options.method,lastiter);
56 self.result.Prob.logNormConstAggr = lG;
59 line_debug(options,
'NC: using lang=matlab');
60 sn = getStruct(self); % doesn
't need initial state
64 if sn.nstations == 2 && ~any(sn.nodetype == NodeType.Cache) && any(sn.nodetype == NodeType.Delay) && any(sn.nservers(isfinite(sn.nservers))>1)
65 options.method = 'comomld
'; % default for multi-server models
66 line_debug(options, 'Default method: 2-station Delay+multiserver network,
using comomld
');
69 if ~self.model.hasProductFormSolution
70 line_error(mfilename,'The exact method
requires the model to have a product-form solution. This model does not have one. You can use Network.hasProductFormSolution() to check before running the solver.
');
71 elseif isempty(sn.lldscaling)
72 % if exact is requested and does not override a lldscaling assigment
75 % trasform multi-server nodes into lld nodes
76 sn.lldscaling = ones(sn.nstations,Nt);
78 if sn.nservers(i) > 1 && isfinite(sn.nservers(i))
79 sn.lldscaling(i,:) = min(1:Nt,sn.nservers(i));
84 line_debug(options, 'Exact method: converted multiserver stations to load-dependent (Nt=%d)
', Nt);
88 if self.enableChecks && ~self.supports(self.model)
89 line_error(mfilename,'This model contains features not supported by the solver.
');
92 Solver.resetRandomGeneratorSeed(options.seed);
94 if sn.nclosedjobs == 0 && length(sn.nodetype)==3 && all(sort(sn.nodetype)' == sort([NodeType.Source,NodeType.Cache,NodeType.Sink])) %
is a non-rentrant cache
95 line_debug(options,
'Non-reentrant cache (Source-Cache-Sink), routing to nc_cache_analyzer');
96 % random initialization
98 if sn.nodetype(ind) == NodeType.Cache
99 prob = self.model.nodes{ind}.server.hitClass;
101 self.model.nodes{ind}.setResultHitProb(prob);
102 self.model.nodes{ind}.setResultMissProb(1-prob);
105 self.model.refreshChains();
107 [QN,UN,RN,TN,CN,XN,lG,pij,runtime,actualmethod] = solver_nc_cache_analyzer(sn, options);
108 self.result.Prob.itemProb = pij;
109 for ind = 1:sn.nnodes
110 if sn.nodetype(ind) == NodeType.Cache
111 %prob = self.model.nodes{ind}.server.hitClass;
113 hitClass = self.model.nodes{ind}.getHitClass;
114 missClass = self.model.nodes{ind}.getMissClass;
115 hitprob = zeros(1,length(hitClass));
116 for k=1:length(self.model.nodes{ind}.getHitClass)
117 %
for k=1:length(self.model.nodes{ind}.server.hitClass)
118 chain_k = sn.chains(:,k)>0;
119 inchain = sn.chains(chain_k,:)>0;
123 hitprob(k) = XN(h) / sum(XN(inchain),"omitnan");
126 self.model.
nodes{ind}.setResultHitProb(hitprob);
127 self.model.nodes{ind}.setResultMissProb(1-hitprob);
130 self.model.refreshChains;
131 else % queueing network
132 if any(sn.nodetype == NodeType.Cache) %
if integrated caching-queueing
133 line_debug(options,
'Integrated caching-queueing network, routing to nc_cacheqn_analyzer');
134 [QN,UN,RN,TN,CN,XN,lG,hitprob,missprob,runtime,iter,actualmethod] = solver_nc_cacheqn_analyzer(self, options);
135 for ind = 1:sn.nnodes
136 if sn.nodetype(ind) == NodeType.Cache
137 self.model.nodes{ind}.setResultHitProb(hitprob(ind,:));
138 self.model.nodes{ind}.setResultMissProb(missprob(ind,:));
141 self.model.refreshStruct(
true); % Force refresh to get updated actualhitprob/actualmissprob
143 else % ordinary queueing network
144 % Check
for open model with single FCR containing single Delay (loss network)
145 if ~sn_has_closed_classes(sn) && sn.nregions == 1
146 regionMatrix = sn.region{1};
147 % Find stations in FCR (those with non-negative constraints)
148 stationsInFCR = find(any(regionMatrix(:,1:end-1) >= 0, 2) | regionMatrix(:,end) >= 0);
149 if length(stationsInFCR) == 1 && isinf(sn.nservers(stationsInFCR(1)))
150 % Single delay node in FCR - check drop rule
151 if all(sn.regionrule(1,:) == DropStrategy.DROP)
152 % Use loss network solver
153 line_debug(options,
'Open model with single FCR + Delay node (DROP), routing to nc_lossn_analyzer');
154 [QN,UN,RN,TN,CN,XN,lG,runtime,iter,actualmethod] = solver_nc_lossn_analyzer(sn, options);
155 AN = sn_get_arvr_from_tput(sn, TN, self.getAvgTputHandles());
156 if strcmp(origmethod,
'default') && exist(
'actualmethod',
'var') && ~strcmp(actualmethod,
'default')
157 self.setAvgResults(QN,UN,RN,TN,AN,[],CN,XN,runtime,['default/' actualmethod],iter);
159 self.setAvgResults(QN,UN,RN,TN,AN,[],CN,XN,runtime,actualmethod,iter);
161 self.result.Prob.logNormConstAggr = real(lG);
164 % WAITQ (blocking) not supported - error and stop
165 line_error(mfilename, 'SolverNC does not support finite capacity regions with WAITQ (blocking) policy. Use DROP policy instead.');
169 if ~isempty(sn.lldscaling) || ~isempty(sn.cdscaling)
170 line_debug(options, 'Load-dependent scaling detected, routing to ncld_analyzer');
171 [QN,UN,RN,TN,CN,XN,lG,runtime,iter,actualmethod] = solver_ncld_analyzer(sn, options);
173 switch options.method
175 if ~sn_has_open_classes(sn)
176 % multi-servers have already been transformed before
177 line_debug(options, 'NC method=exact, closed model, routing to ncld_analyzer');
178 [QN,UN,RN,TN,CN,XN,lG,runtime,iter,actualmethod] = solver_ncld_analyzer(sn, options);
179 else%if ~snHasClosedClasses(sn)
180 line_debug(options, 'NC method=exact, open model, routing to nc_analyzer');
181 [QN,UN,RN,TN,CN,XN,lG,runtime,iter,actualmethod] = solver_nc_analyzer(sn, options);
183 case {
'rd',
'nrp',
'nrl',
'comomld'}
184 line_debug(options,
'NC method=%s, routing to ncld_analyzer', options.method);
185 [QN,UN,RN,TN,CN,XN,lG,runtime,iter,actualmethod] = solver_ncld_analyzer(sn, options);
187 line_debug(options,
'NC method=%s, routing to nc_analyzer', options.method);
188 [QN,UN,RN,TN,CN,XN,lG,runtime,iter,actualmethod] = solver_nc_analyzer(sn, options);
193 % Compute average arrival rate at steady-state
194 AN = sn_get_arvr_from_tput(sn, TN, self.getAvgTputHandles());
196if strcmp(origmethod,
'default') && exist(
'actualmethod',
'var') && ~strcmp(actualmethod,
'default')
197 self.setAvgResults(QN,UN,RN,TN,AN,[],CN,XN,runtime,['default/' actualmethod],iter);
199 self.setAvgResults(QN,UN,RN,TN,AN,[],CN,XN,runtime,actualmethod,iter);
202self.result.Prob.logNormConstAggr = real(lG);