1function [Q,U,R,T,C,X,lG,hitprob,missprob,runtime,it] = solver_mva_cacheqn_analyzer(self, options)
2% [Q,U,R,T,C,X,LG,RUNTIME,ITER] = SOLVER_MVA_CACHEQN_ANALYZER(SELF, OPTIONS)
4% Copyright (c) 2012-2026, Imperial College London
7snorig = self.model.getStruct;
12line_debug(
'MVA cacheqn analyzer starting: method=%s, nclasses=%d', options.method, K);
14statefulNodes = find(sn.isstateful)
';
15statefulNodesClasses = [];
16for ind=statefulNodes %#ok<FXSET>
17 statefulNodesClasses(end+1:end+K)= ((ind-1)*K+1):(ind*K);
21caches = find(sn.nodetype == NodeType.Cache);
23hitprob = zeros(length(caches),K);
24missprob = zeros(length(caches),K);
26for it=1:options.iter_max
28 ch = sn.nodeparam{ind};
29 hitClass = ch.hitclass;
30 missClass = ch.missclass;
31 inputClass = find(hitClass);
35 % initial random value of arrival rates to the cache
36 lambda_1(inputClass) = rand(1,length(inputClass));
38 sn.nodetype(ind) = NodeType.ClassSwitch;
41 % solution of isolated cache
44 lambda_cache = zeros(u,n,h);
49 if ~isnan(ch.pread{v})
50 lambda_cache(v,k,l) = lambda(v) * ch.pread{v}(k);
58 % Default linear cache routing: items flow from list l to list l+1
62 Rmat = diag(ones(1, h), 1);
68 gamma = cache_gamma_lp(lambda_cache,Rcost);
72 [~,~,pij] = cache_mva(gamma, m);
73 pij = [abs(1-sum(pij,2)),pij];
74 missrate(ind,:) = zeros(1,u);
76 missrate(ind,v) = lambda_cache(v,:,1)*pij(:,1);
79 line_debug('Default method:
using FPI approximation
for cache\n
');
80 line_debug('Using FPI approximation, calling cache_miss_fpi
');
81 [~,missrate(ind,:)] = cache_miss_fpi(gamma, m, lambda_cache);
83 missprob(ind,:) = missrate(ind,:) ./ lambda; % we set to NaN if no arrivals
84 hitprob(ind,:) = 1 - missprob(ind,:);
85 hitprob(isnan(hitprob)) = 0;
86 missprob(isnan(missprob)) = 0;
88 % bring back the isolated model results into the queueing model
90 sn.rtnodes((ind-1)*K+r,:) = 0;
92 if sn.connmatrix(ind,jnd)
93 sn.rtnodes((ind-1)*K+r,(jnd-1)*K+hitClass(r)) = hitprob(ind,r);
94 sn.rtnodes((ind-1)*K+r,(jnd-1)*K+missClass(r)) = missprob(ind,r);
98 sn.rt = dtmc_stochcomp(sn.rtnodes,statefulNodesClasses);
100 [visits, nodevisits, sn] = sn_refresh_visits(sn, sn.chains, sn.rt, sn.rtnodes);
102 sn.nodevisits = nodevisits;
104 switch options.method
105 case {'aba.upper
', 'aba.lower
', 'bjb.upper
', 'bjb.lower
', 'pb.upper
', 'pb.lower
', 'gb.upper
', 'gb.lower
', 'sb.upper
', 'sb.lower
'}
106 [Q,U,R,T,C,X,lG,runtime] = solver_mva_bound_analyzer(sn, options);
108 if ~isempty(sn.lldscaling) || ~isempty(sn.cdscaling)
109 [Q,U,R,T,C,X,lG,runtime] = solver_mvald_analyzer(sn, options);
111 [Q,U,R,T,C,X,lG,runtime] = solver_mva_analyzer(sn, options);
114 nodevisits = cellsum(nodevisits);
117 c = find(sn.chains(:,r));
118 inchain = find(sn.chains(c,:));
120 lambda(r) = sum(X(inchain)) * nodevisits(ind,r) / nodevisits(sn.stationToNode(sn.refstat(r)),sn.refclass(c));
122 lambda(r) = sum(X(inchain)) * nodevisits(ind,r) / nodevisits(sn.stationToNode(sn.refstat(r)),r);
126 if norm(lambda-lambda_1,1) < options.iter_tol