LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
solver_nc.m
1function [Q,U,R,T,C,X,lG,STeff,it,method] = solver_nc(sn, options)
2
3M = sn.nstations; %number of stations
4nservers = sn.nservers;
5NK = sn.njobs'; % initial population per class
6sched = sn.sched;
7C = sn.nchains;
8SCV = sn.scv;
9V = cellsum(sn.visits);
10ST = 1 ./ sn.rates;
11ST(isnan(ST)) = 0;
12ST0 = ST;
13
14% Check for special LCFS + LCFS-PR 2-station network
15lcfsStat = find(sched == SchedStrategy.LCFS);
16lcfsprStat = find(sched == SchedStrategy.LCFSPR);
17if ~isempty(lcfsStat) && ~isempty(lcfsprStat)
18 % Validate LCFS network topology
19 if length(lcfsStat) ~= 1 || length(lcfsprStat) ~= 1
20 line_error(mfilename, 'LCFS NC requires exactly one LCFS and one LCFS-PR station.');
21 end
22 Nchain = zeros(1,C);
23 for c=1:C
24 inchain = sn.inchain{c};
25 Nchain(c) = sum(NK(inchain)); %#ok<FNDSB>
26 end
27 if any(isinf(Nchain))
28 line_error(mfilename, 'LCFS NC requires a closed queueing network.');
29 end
30 % Check for self-loops in routing matrix
31 rt = sn.rt;
32 nclasses = sn.nclasses;
33 for ist = [lcfsStat, lcfsprStat]
34 for r = 1:nclasses
35 if rt((ist-1)*nclasses+r, (ist-1)*nclasses+r) > 0
36 line_error(mfilename, 'LCFS NC does not support self-loops at stations.');
37 end
38 end
39 end
40 % Call specialized LCFS NC solver
41 [Q,U,R,T,C,X,lG] = solver_nc_lcfsqn(sn, options, lcfsStat, lcfsprStat);
42 STeff = ST;
43 it = 1;
44 method = 'lcfsqn.ca';
45 return;
46elseif ~isempty(lcfsStat)
47 % LCFS without LCFS-PR is not supported
48 line_error(mfilename, 'LCFS scheduling requires a paired LCFS-PR station.');
49end
50
51Nchain = zeros(1,C);
52for c=1:C
53 inchain = sn.inchain{c};
54 Nchain(c) = sum(NK(inchain)); %#ok<FNDSB>
55end
56openChains = find(isinf(Nchain));
57closedChains = find(~isinf(Nchain));
58
59gamma = zeros(1,M);
60eta_1 = zeros(1,M);
61eta = ones(1,M);
62C = sn.nchains;
63
64if all(sched~=SchedStrategy.FCFS) options.iter_max=1; end
65it = 0;
66while max(abs(1-eta./eta_1)) > options.iter_tol & it < options.iter_max
67 it = it + 1;
68 eta_1 = eta;
69
70 if it==1
71 lambda = zeros(1,C);
72 [Lchain,STchain,Vchain,alpha,Nchain] = sn_get_demands_chain(sn);
73 for c=1:C
74 inchain = sn.inchain{c};
75 isOpenChain = any(isinf(sn.njobs(inchain)));
76 for ist=1:M
77 % we assume that the visits in L(i,inchain) are equal to 1
78 if isOpenChain && ist == sn.refstat(inchain(1)) % if this is a source ST = 1 / arrival rates
79 lambda(c) = 1 ./ STchain(ist,c);
80 end
81 end
82 end
83 else
84 for c=1:C
85 inchain = sn.inchain{c};
86 for ist=1:M
87 % we assume that the visits in L(i,inchain) are equal to 1
88 STchain(ist,c) = ST(ist,inchain) * alpha(ist,inchain)';
89 Lchain(ist,c) = Vchain(ist,c) * STchain(ist,c);
90 end
91 end
92 end
93
94 STchain(~isfinite(STchain))=0;
95 Lchain(~isfinite(Lchain))=0;
96
97 Lms = zeros(M,C);
98 Z = zeros(M,C);
99 Zms = zeros(M,C);
100 infServers = [];
101 for ist=1:M
102 if isinf(nservers(ist)) % infinite server
103 infServers(end+1) = ist;
104 Lms(ist,:) = 0;
105 Z(ist,:) = Lchain(ist,:);
106 Zms(ist,:) = 0;
107 else
108 if strcmpi(options.method,'exact') && nservers(ist)>1
109 %options.method = 'default';
110 if options.verbose
111 line_warning(mfilename,sprintf('%s does not support exact multiserver yet. Switching to approximate method.\n', 'SolverNC'));
112 end
113 end
114 % Seidmann's approximation
115 Lms(ist,:) = Lchain(ist,:) / nservers(ist);
116 Z(ist,:) = 0;
117 Zms(ist,:) = Lchain(ist,:) * (nservers(ist)-1)/nservers(ist);
118 end
119 end
120
121 % step 1
122 [lG, Xchain, Qchain, method] = pfqn_nc(lambda,Lms,Nchain,sum(Z,1)+sum(Zms,1), options);
123
124 if sum(Zms,1) > GlobalConstants.FineTol
125 % in this case, we need to use the iterative approximation below
126 Xchain=[];
127 Qchain=[];
128 end
129
130 if isempty(lG)
131 [Q,U,R,T,C,X,lG,STeff,it,method] = deal([],[],[],[],[],[],[],[],1,options.method);
132 return
133 end
134
135 if isempty(Xchain)
136 Xchain=lambda;
137 Qchain = zeros(M,C);
138 for r=closedChains
139 lGr(r) = pfqn_nc(lambda,Lms,oner(Nchain,r),sum(Z,1)+sum(Zms,1), options);
140 Xchain(r) = exp(lGr(r) - lG);
141 for ist=1:M
142 if Lchain(ist,r)>0
143 if isinf(nservers(ist)) % infinite server
144 Qchain(ist,r) = Lchain(ist,r) * Xchain(r);
145 else
146 % add replica of station i and move job of class r
147 % in separate class
148 % this is the most costly operation so we record
149 % method here
150 [lGar(ist,r),~,~,method] = pfqn_nc([lambda,0],[Lms(setdiff(1:size(Lms,1),ist),:),zeros(size(Lms,1)-1,1); Lms(ist,:),1], [oner(Nchain,r),1], [sum(Z,1)+sum(Zms,1),0], options);
151 Qchain(ist,r) = Zms(ist,r) * Xchain(r) + Lms(ist,r) * exp(lGar(ist,r) - lG);
152 end
153 end
154 end
155 Qchain(isnan(Qchain))=0;
156 end
157 for r=openChains
158 for ist=1:M
159 Qchain(ist,r) = lambda(r)*Lchain(ist,r)/(1-lambda(openChains)*Lchain(ist,openChains)'/nservers(ist))*(1+sum(Qchain(ist,closedChains)));
160 end
161 end
162 else
163 % just fill the delay servers
164 for r=1:C
165 for ist=1:M
166 if Lchain(ist,r)>0
167 if isinf(nservers(ist)) % infinite server
168 Qchain(ist,r) = Lchain(ist,r) * Xchain(r);
169 end
170 end
171 end
172 end
173 end
174
175 if isnan(Xchain)
176 if options.verbose
177 line_warning(mfilename,'Normalizing constant computations produced a floating-point range exception. Model is likely too large.\n');
178 end
179 end
180
181 Z = sum(Z(1:M,:),1);
182
183 Rchain = Qchain ./ repmat(Xchain,M,1) ./ Vchain;
184 Rchain(infServers,:) = Lchain(infServers,:) ./ Vchain(infServers,:);
185 Tchain = repmat(Xchain,M,1) .* Vchain;
186
187 %Uchain = Tchain .* Lchain;
188 %Cchain = Nchain ./ Xchain - Z;
189
190 [Q,U,R,T,~,X] = sn_deaggregate_chain_results(sn, Lchain, ST, STchain, Vchain, alpha, [], [], Rchain, Tchain, [], Xchain);
191 STeff = ST;% effective service time at the last iteration
192 [ST,gamma,~,~,~,~,eta] = npfqn_nonexp_approx(options.config.highvar,sn,ST0,V,SCV,T,U,gamma,nservers);
193end
194
195Q=abs(Q); R=abs(R); X=abs(X); U=abs(U);
196X(~isfinite(X))=0; U(~isfinite(U))=0; Q(~isfinite(Q))=0; R(~isfinite(R))=0;
197
198% renormalize qlen and tput to correct for unforeseen population constraint deviations
199for c=1:sn.nchains
200 inchain = sn.inchain{c};
201 Nchain(c) = sum(NK(inchain)); %#ok<FNDSB>
202 if isfinite(Nchain(c))
203 q_den = sum(sum(Q(:,inchain)));
204 if q_den > 0
205 ratio = Nchain(c)/ q_den;
206 else
207 ratio = 0;
208 end
209 Q(:,inchain) = ratio * Q(:,inchain);
210 X(inchain) = ratio * X(inchain);
211 T(:,inchain) = ratio * T(:,inchain);
212 U(:,inchain) = ratio * U(:,inchain);
213 R(:,inchain) = Q(:,inchain) ./ T(:,inchain);
214 end
215end
216end