LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
getAvgSys.m
1function [CNchain,XNchain] = getAvgSys(self,R,T)
2% [CNCHAIN,XNCHAIN] = GETAVGSYS(SELF,R,T)
3
4% Return average system metrics at steady state
5%
6% Copyright (c) 2012-2026, Imperial College London
7% All rights reserved.
8
9sn = self.model.getStruct();
10if nargin < 3
11 R = self.getAvgRespTHandles;
12 T = self.getAvgTputHandles;
13end
14[~,~,RN,TN] = self.getAvg([],[],R,T,[],[]);
15RN(sn.nodeToStation(find(sn.nodetype == NodeType.Join)), :) = 0;
16for f=find(sn.nodetype == NodeType.Fork)'
17 % find join associated to fork f
18 joinIdx = find(sn.fj(f,:));
19 if isempty(joinIdx)
20 % No join nodes for this fork, no synchronisation delay
21 continue;
22 end
23 for c=1:sn.nchains
24 inchain = sn.inchain{c};
25 nJobsChain = sum(sn.njobs(find(sn.chains(c,:)))); %#ok<FNDSB>
26 if isinf(nJobsChain) % limit this calculation to open chains as we can use Little's Law for closed chains
27 for r=inchain
28 if RN(sn.nodeToStation(joinIdx), r) == 0
29 % Find the parallel paths coming out of the fork
30 %[ri, stat, RN] = ModelAdapter.paths(sn, self.model.getLinkedRoutingMatrix{r,r}, f, joinIdx, r, RN, 0, []);
31 [ri, stat, RN] = ModelAdapter.pathsCS(sn, cell2mat(self.model.getLinkedRoutingMatrix), f, joinIdx, r, RN, 0, []);
32 lambdai = 1./ri;
33 d0 = 0;
34 parallel_branches = length(ri);
35 for pow=0:(parallel_branches - 1)
36 current_sum = sum(1./sum(nchoosek(lambdai, pow + 1),2));
37 d0 = d0 + (-1)^pow * current_sum;
38 end
39 RN(sn.nodeToStation(joinIdx), r) = d0; % this also includes the mean time in the fork section for class r
40 RN(stat, r) = 0; % this is already counted in d0
41 end
42 end
43 end
44 end
45end
46
47refstats = sn.refstat;
48completes = true(1,sn.nclasses);
49for r=1:sn.nclasses
50 completes(r) = T{refstats(r),r}.class.completes;
51end
52
53%if any(isinf(sn.njobs')) % if the model has any open class
54% TODO: this could be optimised by computing the statistics
55% only for open chains
56
57% compute chain visits
58alpha = zeros(sn.nstations,sn.nclasses);
59CNclass = zeros(1,sn.nclasses);
60for c=1:sn.nchains
61 inchain = sn.inchain{c};
62 for r=inchain
63 CNclass(r)=0;
64 if ~isempty(RN) % if not empty
65 for i=1:sn.nstations
66 if ~(isinf(sn.njobs(r)) && i==sn.refstat(r)) % if not source
67 CNclass(r) = CNclass(r) + sn.visits{c}(sn.stationToStateful(i),r)*RN(i,r)/sn.visits{c}(sn.stationToStateful(sn.refstat(r)),r);
68 end
69 end
70 end
71 end
72end
73
74for c=1:sn.nchains
75 inchain = sn.inchain{c};
76 completingclasses = sn.chains(c,:) & completes;
77 for i=1:sn.nstations
78 if sn.refclass(c)>0
79 for k=intersect(find(sn.refclass), inchain) % for all classes within the chain (a class belongs to a single chain, the reference station must be identical for all classes within a chain )
80 alpha(i,k) = alpha(i,k) + sn.visits{c}(sn.stationToStateful(i),k)/sum(sn.visits{c}(sn.stationToStateful(sn.refstat(k)),completingclasses));
81 end
82 else
83 for k=inchain % for all classes within the chain (a class belongs to a single chain, the reference station must be identical for all classes within a chain )
84 alpha(i,k) = alpha(i,k) + sn.visits{c}(i,k)/sum(sn.visits{c}(sn.stationToStateful(sn.refstat(k)),completingclasses));
85 end
86 end
87 end
88end
89alpha(~isfinite(alpha))=0;
90%end
91
92% compute average chain metrics
93CNchain = zeros(1,sn.nchains);
94XNchain = zeros(1,sn.nchains);
95for c=1:sn.nchains
96 inchain = sn.inchain{c};
97 completingclasses = find(sn.chains(c,:) & completes);
98 if ~isempty(TN)
99 XNchain(c) = 0;
100 % all classes in same chain must share the same refstation, so we use the first one
101 ref = refstats(inchain(1));
102 % we now compute the incoming system throughput to the
103 % reference station from completing classes
104 for i=1:sn.nstations
105 for r=completingclasses(:)'
106 if any(intersect(find(sn.refclass), inchain))
107 for s=intersect(find(sn.refclass), inchain)
108 if ~isnan(TN(i,r))
109 XNchain(c) = XNchain(c) + sn.rt((i-1)*sn.nclasses + r, (ref-1)*sn.nclasses + s )*TN(i,r);
110 end
111 end
112 else
113 for s=inchain(:)'
114 if ~isnan(TN(i,r))
115 XNchain(c) = XNchain(c) + sn.rt((i-1)*sn.nclasses + r, (ref-1)*sn.nclasses + s )*TN(i,r);
116 end
117 end
118 end
119 end
120 end
121 end
122
123 % If this is a closed chain we simply apply Little's law
124 nJobsChain = sum(sn.njobs(find(sn.chains(c,:)))); %#ok<FNDSB>
125 if isinf(nJobsChain)
126 if length(inchain) ~= length(completingclasses)
127 line_error(mfilename,'Edge-based chain definition not yet supported for open queueing networks.');
128 %else
129 % we use nan sum to disregard response at stations where
130 % the class is not defined
131 % CNchain(c) = sumfinite(alpha(refstats(inchain(1)),inchain).*CNclass(inchain));
132 end
133 CNchain(c) = sumfinite(alpha(refstats(inchain(1)),inchain).*CNclass(inchain));
134 else
135 CNchain(c) = nJobsChain/XNchain(c);
136 end
137end
138self.result.XN = XNchain;
139self.result.CN = CNchain;
140end