LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
runAnalyzer.m
1function runtime = runAnalyzer(self, options)
2% RUNTIME = RUN()
3% Run the solver
4if nargin<2
5 options = self.getOptions;
6end
7
8iter = NaN;
9self.runAnalyzerChecks(options);
10
11sn = self.getStruct();
12if isfield(sn,'immfeed') && ~isempty(sn.immfeed) && any(sn.immfeed(:))
13 line_warning(mfilename,'SolverNC does not handle immediate feedback (immfeed); the solver will treat self-loops as class-switching with re-queueing.\n');
14end
15
16Solver.resetRandomGeneratorSeed(options.seed);
17
18% Show library attribution if verbose and not yet shown
19if options.verbose ~= VerboseLevel.SILENT && ~GlobalConstants.isLibraryAttributionShown()
20 sn = self.getStruct();
21 libs = SolverNC.getLibrariesUsed(sn, options);
22 if ~isempty(libs)
23 line_printf('The solver will leverage %s.\n', strjoin(libs, ', '));
24 GlobalConstants.setLibraryAttributionShown(true);
25 end
26end
27
28origmethod = options.method;
29
30%options.lang = 'java';
31
32switch options.lang
33 case 'java'
34 line_debug(options, 'NC: using lang=java, delegating to JLINE');
35 sn = self.getStruct;
36 jmodel = LINE2JLINE(self.model);
37 %M = jmodel.getNumberOfStatefulNodes;
38 M = jmodel.getNumberOfStations;
39 R = jmodel.getNumberOfClasses;
40 jsolver = JLINE.SolverNC(jmodel, options);
41 [QN,UN,RN,WN,AN,TN] = JLINE.arrayListToResults(jsolver.getAvgTable);
42 runtime = jsolver.result.runtime;
43 CN = [];
44 XN = [];
45 QN = reshape(QN',R,M)';
46 UN = reshape(UN',R,M)';
47 RN = reshape(RN',R,M)';
48 TN = reshape(TN',R,M)';
49 WN = reshape(WN',R,M)';
50 AN = reshape(AN',R,M)';
51 lG = NaN;
52 lastiter = NaN;
53 for ind = 1:sn.nnodes
54 if sn.nodetype(ind) == NodeType.Cache
55 self.model.nodes{ind}.setResultHitProb(JLINE.from_jline_matrix(jmodel.getNodeByIndex(ind-1).getHitRatio()));
56 self.model.nodes{ind}.setResultMissProb(JLINE.from_jline_matrix(jmodel.getNodeByIndex(ind-1).getMissRatio()));
57 end
58 end
59 %self.model.refreshChains();
60 self.model.refreshStruct(true);
61 self.setAvgResults(QN,UN,RN,TN,AN,WN,CN,XN,runtime,options.method,lastiter);
62 self.result.Prob.logNormConstAggr = lG;
63 return
64 case 'matlab'
65 line_debug(options, 'NC: using lang=matlab');
66 sn = getStruct(self); % doesn't need initial state
67
68 switch options.method
69 case 'default'
70 if sn.nstations == 2 && ~any(sn.nodetype == NodeType.Cache) && any(sn.nodetype == NodeType.Delay) && any(sn.nservers(isfinite(sn.nservers))>1)
71 options.method = 'comomld'; % default for multi-server models
72 line_debug(options, 'Default method: 2-station Delay+multiserver network, using comomld');
73 end
74 case 'exact'
75 if ~self.model.hasProductFormSolution
76 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.');
77 elseif isempty(sn.lldscaling)
78 % if exact is requested and does not override a lldscaling assigment
79 Nt = sum(sn.njobs);
80 if isfinite(Nt)
81 % trasform multi-server nodes into lld nodes
82 sn.lldscaling = ones(sn.nstations,Nt);
83 for i=1:sn.nstations
84 if sn.nservers(i) > 1 && isfinite(sn.nservers(i))
85 sn.lldscaling(i,:) = min(1:Nt,sn.nservers(i));
86 sn.nservers(i) = 1;
87 end
88 end
89 end
90 line_debug(options, 'Exact method: converted multiserver stations to load-dependent (Nt=%d)', Nt);
91 end
92 end
93
94 if self.enableChecks && ~self.supports(self.model)
95 line_error(mfilename,'This model contains features not supported by the solver.');
96 end
97
98 Solver.resetRandomGeneratorSeed(options.seed);
99
100 if sn.nclosedjobs == 0 && length(sn.nodetype)==3 && all(sort(sn.nodetype)' == sort([NodeType.Source,NodeType.Cache,NodeType.Sink])) % is a non-rentrant cache
101 line_debug(options, 'Non-reentrant cache (Source-Cache-Sink), routing to nc_cache_analyzer');
102 % random initialization
103 for ind = 1:sn.nnodes
104 if sn.nodetype(ind) == NodeType.Cache
105 prob = self.model.nodes{ind}.server.hitClass;
106 prob(prob>0) = 0.5;
107 self.model.nodes{ind}.setResultHitProb(prob);
108 self.model.nodes{ind}.setResultMissProb(1-prob);
109 end
110 end
111 self.model.refreshChains();
112 % start iteration
113 [QN,UN,RN,TN,CN,XN,lG,pij,runtime,actualmethod] = solver_nc_cache_analyzer(sn, options);
114 self.result.Prob.itemProb = pij;
115 for ind = 1:sn.nnodes
116 if sn.nodetype(ind) == NodeType.Cache
117 %prob = self.model.nodes{ind}.server.hitClass;
118 %prob(prob>0) = 0.5;
119 hitClass = self.model.nodes{ind}.getHitClass;
120 missClass = self.model.nodes{ind}.getMissClass;
121 hitprob = zeros(1,length(hitClass));
122 for k=1:length(self.model.nodes{ind}.getHitClass)
123 % for k=1:length(self.model.nodes{ind}.server.hitClass)
124 chain_k = sn.chains(:,k)>0;
125 inchain = sn.chains(chain_k,:)>0;
126 h = hitClass(k);
127 m = missClass(k);
128 if h>0 && m>0
129 hitprob(k) = XN(h) / sum(XN(inchain),"omitnan");
130 end
131 end
132 self.model.nodes{ind}.setResultHitProb(hitprob);
133 self.model.nodes{ind}.setResultMissProb(1-hitprob);
134 end
135 end
136 self.model.refreshChains;
137 else % queueing network
138 if any(sn.nodetype == NodeType.Cache) % if integrated caching-queueing
139 line_debug(options, 'Integrated caching-queueing network, routing to nc_cacheqn_analyzer');
140 [QN,UN,RN,TN,CN,XN,lG,hitprob,missprob,runtime,iter,actualmethod] = solver_nc_cacheqn_analyzer(self, options);
141 for ind = 1:sn.nnodes
142 if sn.nodetype(ind) == NodeType.Cache
143 self.model.nodes{ind}.setResultHitProb(hitprob(ind,:));
144 self.model.nodes{ind}.setResultMissProb(missprob(ind,:));
145 end
146 end
147 self.model.refreshStruct(true); % Force refresh to get updated actualhitprob/actualmissprob
148 sn = self.model.sn;
149 else % ordinary queueing network
150 % Check for open model with single FCR containing single Delay (loss network)
151 if ~sn_has_closed_classes(sn) && sn.nregions == 1
152 regionMatrix = sn.region{1};
153 % Find stations in FCR (those with non-negative constraints)
154 stationsInFCR = find(any(regionMatrix(:,1:end-1) >= 0, 2) | regionMatrix(:,end) >= 0);
155 if length(stationsInFCR) == 1 && isinf(sn.nservers(stationsInFCR(1)))
156 % Single delay node in FCR - check drop rule
157 if all(sn.regionrule(1,:) == DropStrategy.DROP)
158 % Use loss network solver
159 line_debug(options, 'Open model with single FCR + Delay node (DROP), routing to nc_lossn_analyzer');
160 [QN,UN,RN,TN,CN,XN,lG,runtime,iter,actualmethod] = solver_nc_lossn_analyzer(sn, options);
161 AN = sn_get_arvr_from_tput(sn, TN, self.getAvgTputHandles());
162 if strcmp(origmethod,'default') && exist('actualmethod','var') && ~strcmp(actualmethod,'default')
163 self.setAvgResults(QN,UN,RN,TN,AN,[],CN,XN,runtime,['default/' actualmethod],iter);
164 else
165 self.setAvgResults(QN,UN,RN,TN,AN,[],CN,XN,runtime,actualmethod,iter);
166 end
167 self.result.Prob.logNormConstAggr = real(lG);
168 return
169 else
170 % WAITQ (blocking) not supported - error and stop
171 line_error(mfilename, 'SolverNC does not support finite capacity regions with WAITQ (blocking) policy. Use DROP policy instead.');
172 end
173 end
174 end
175 if ~isempty(sn.lldscaling) || ~isempty(sn.cdscaling)
176 line_debug(options, 'Load-dependent scaling detected, routing to ncld_analyzer');
177 [QN,UN,RN,TN,CN,XN,lG,runtime,iter,actualmethod] = solver_ncld_analyzer(sn, options);
178 else
179 switch options.method
180 case 'exact'
181 if ~sn_has_open_classes(sn)
182 % multi-servers have already been transformed before
183 line_debug(options, 'NC method=exact, closed model, routing to ncld_analyzer');
184 [QN,UN,RN,TN,CN,XN,lG,runtime,iter,actualmethod] = solver_ncld_analyzer(sn, options);
185 else%if ~snHasClosedClasses(sn)
186 line_debug(options, 'NC method=exact, open model, routing to nc_analyzer');
187 [QN,UN,RN,TN,CN,XN,lG,runtime,iter,actualmethod] = solver_nc_analyzer(sn, options);
188 end
189 case {'rd','nrp','nrl','comomld'}
190 line_debug(options, 'NC method=%s, routing to ncld_analyzer', options.method);
191 [QN,UN,RN,TN,CN,XN,lG,runtime,iter,actualmethod] = solver_ncld_analyzer(sn, options);
192 otherwise
193 line_debug(options, 'NC method=%s, routing to nc_analyzer', options.method);
194 [QN,UN,RN,TN,CN,XN,lG,runtime,iter,actualmethod] = solver_nc_analyzer(sn, options);
195 end
196 end
197 end
198 end
199 % Compute average arrival rate at steady-state
200 AN = sn_get_arvr_from_tput(sn, TN, self.getAvgTputHandles());
201end
202if strcmp(origmethod,'default') && exist('actualmethod','var') && ~strcmp(actualmethod,'default')
203 self.setAvgResults(QN,UN,RN,TN,AN,[],CN,XN,runtime,['default/' actualmethod],iter);
204else
205 self.setAvgResults(QN,UN,RN,TN,AN,[],CN,XN,runtime,actualmethod,iter);
206end
207
208self.result.Prob.logNormConstAggr = real(lG);
209end
Definition mmt.m:124