LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
solver_amvald.m
1function [Q,U,R,T,C,X,lG,totiter] = solver_amvald(sn, Lchain,STchain,Vchain,alpha,Nchain,SCVchain,refstatchain, options)
2totiter = 0;
3max_totiter = min(options.iter_max, 10000); % Hard cap for stability
4
5M = sn.nstations;
6K = sn.nchains;
7Nt = sum(Nchain(isfinite(Nchain)));
8delta = (Nt - 1) / Nt;
9deltaclass = (Nchain - 1) ./ Nchain;
10deltaclass(isinf(Nchain)) = 1;
11tol = options.iter_tol;
12nservers = sn.nservers;
13schedparam = sn.schedparam;
14lldscaling = sn.lldscaling;
15cdscaling = sn.cdscaling;
16ljdscaling = sn.ljdscaling;
17ljdcutoffs = sn.ljdcutoffs;
18ljcdscaling = sn.ljcdscaling;
19ljcdcutoffs = sn.ljcdcutoffs;
20sched = sn.sched;
21classprio = sn.classprio;
22
23Uchain = zeros(M,K);
24Tchain = zeros(M,K);
25Cchain_s = zeros(1,K);
26
27%% initialize Q,X, U
28Qchain = options.init_sol;
29if isempty(Qchain)
30 % balanced initialization
31 Qchain = ones(M,K);
32 Qchain = Qchain ./ repmat(sum(Qchain,1),size(Qchain,1),1) .* repmat(Nchain,size(Qchain,1),1);
33 Qchain(isinf(Qchain))=0; % open classes
34 for r=find(isinf(Nchain)) % open classes
35 Qchain(refstatchain(r),r)=0;
36 end
37end
38
39nnzclasses = find(Nchain>0);
40Xchain = 1./sum(STchain,1);
41for r=find(isinf(Nchain)) % open classes
42 Xchain(r) = 1 ./ STchain(refstatchain(r),r);
43end
44
45for k=1:M
46 for r=nnzclasses
47 if isinf(nservers(k)) % infinite server
48 Uchain(k,r) = Vchain(k,r)*STchain(k,r)*Xchain(r);
49 else
50 Uchain(k,r) = Vchain(k,r)*STchain(k,r)*Xchain(r)/nservers(k);
51 end
52 end
53end
54
55switch options.method
56 case {'lin','qdlin'}
57 gamma = zeros(K,M,K); % class-based customer fraction corrections
58 tau = zeros(K,K); % throughput difference
59 otherwise
60 gamma = zeros(K,M); % total customer fraction corrections
61 tau = zeros(K,K); % throughput difference
62end
63
64%% main loop
65omicron = 0.5; % under-relaxation parameter
66outer_iter = 0;
67while (outer_iter < 2 || max(max(abs(Qchain-QchainOuter_1))) > tol) && outer_iter < sqrt(options.iter_max) && totiter <= max_totiter
68 outer_iter = outer_iter + 1;
69 QchainOuter_1 = Qchain;
70 XchainOuter_1 = Xchain;
71 UchainOuter_1 = Uchain;
72
73 if isfinite(Nt) && Nt>0
74 switch options.method
75 %case {'aql','qdaql'}
76 %line_error(mfilename,'AQL is currently disabled in SolverMVA, please use the SolverJMT implementation (method jmva.aql).');
77 case {'lin','qdlin'}
78 % iteration at population N-1_s
79 for s=1:K
80 if isfinite(Nchain(s)) % don't recur on open classes
81 iter_s = 0;
82 Nchain_s = oner(Nchain,s);
83 Qchain_s = Qchain * (Nt-1)/Nt;
84 Xchain_s = Xchain * (Nt-1)/Nt;
85 Uchain_s = Uchain * (Nt-1)/Nt;
86 while (iter_s < 2 || max(max(abs(Qchain_s-Qchain_s_1))) > tol) && iter_s <= sqrt(options.iter_max)
87 iter_s = iter_s + 1;
88
89 Qchain_s_1 = Qchain_s;
90 Xchain_s_1 = Xchain_s;
91 Uchain_s_1 = Uchain_s;
92
93 [Wchain_s, STeff_s] = solver_amvald_forward(M, K, nservers, schedparam, lldscaling, cdscaling, ljdscaling, ljdcutoffs, ljcdscaling, ljcdcutoffs, sched, classprio, gamma, tau, Qchain_s_1, Xchain_s_1, Uchain_s_1, STchain, Vchain, Nchain_s, SCVchain, options);
94 totiter = totiter + 1;
95 if totiter >= max_totiter
96 break
97 end
98
99 %% update other metrics
100 for r=nnzclasses
101 if sum(Wchain_s(:,r)) == 0
102 Xchain_s(r) = 0;
103 else
104 if isinf(Nchain_s(r))
105 Cchain_s(r) = Vchain(:,r)' * Wchain_s(:,r);
106 % X(r) remains constant
107 elseif Nchain(r)==0
108 Xchain_s(r) = 0;
109 Cchain_s(r) = 0;
110 else
111 Cchain_s(r) = Vchain(:,r)' * Wchain_s(:,r);
112 Xchain_s(r) = omicron * Nchain_s(r) / Cchain_s(r) + (1-omicron) * Xchain_s_1(r);
113 end
114 end
115 for k=1:M
116 Rchain_s(k,r) = Vchain(k,r) * Wchain_s(k,r);
117 Qchain_s(k,r) = omicron * Xchain_s(r) * Vchain(k,r) * Wchain_s(k,r) + (1-omicron) * Qchain_s_1(k,r);
118 Tchain_s(k,r) = Xchain_s(r) * Vchain(k,r);
119 Uchain_s(k,r) = omicron * Vchain(k,r) * STeff_s(k,r) * Xchain_s(r) + (1-omicron) * Uchain_s_1(k,r);
120 end
121 end
122 end
123
124 switch options.method
125 case {'lin'}
126 for k=1:M
127 for r=nnzclasses
128 if ~isinf(Nchain(r)) && Nchain_s(r)>0
129 gamma(s,k,r) = Qchain_s_1(k,r)./Nchain_s(r) - QchainOuter_1(k,r)./Nchain(r);
130 end
131 end
132 end
133 otherwise
134 for k=1:M
135 gamma(s,k) = sum(Qchain_s_1(k,:),2)/(Nt-1) - sum(QchainOuter_1(k,:),2)/Nt;
136 end
137 end
138
139 for r=nnzclasses
140 tau(s,r) = Xchain_s_1(r) - XchainOuter_1(r); % save throughput for priority AMVA
141 end
142 end
143 % Check if iteration limit exceeded (break out of for s loop)
144 if totiter >= max_totiter
145 break
146 end
147 end
148 end
149 end
150 % Check if iteration limit exceeded (break out of outer while loop)
151 if totiter >= max_totiter
152 break
153 end
154
155 iter = 0;
156 % iteration at population N
157 while (iter < 2 || max(max(abs(Qchain-Qchain_1))) > tol) && iter <= sqrt(options.iter_max)
158 iter = iter + 1;
159
160 Qchain_1 = Qchain;
161 Xchain_1 = Xchain;
162 Uchain_1 = Uchain;
163
164 [Wchain, STeff] = solver_amvald_forward(M, K, nservers, schedparam, lldscaling, cdscaling, ljdscaling, ljdcutoffs, ljcdscaling, ljcdcutoffs, sched, classprio, gamma, tau, Qchain_1, Xchain_1, Uchain_1, STchain, Vchain, Nchain, SCVchain, options);
165 totiter = totiter + 1;
166 if totiter >= max_totiter
167 break
168 end
169
170
171 %% update other metrics
172 for r=nnzclasses
173 if sum(Wchain(:,r)) == 0
174 Xchain(r) = 0;
175 else
176 if isinf(Nchain(r))
177 Cchain_s(r) = Vchain(:,r)'*Wchain(:,r);
178 % X(r) remains constant
179 elseif Nchain(r)==0
180 Xchain(r) = 0;
181 Cchain_s(r) = 0;
182 else
183 Cchain_s(r) = Vchain(:,r)'*Wchain(:,r);
184 Xchain(r) = omicron * Nchain(r) / Cchain_s(r) + (1-omicron) *Xchain_1(r);
185 end
186 end
187 for k=1:M
188 Rchain(k,r) = Vchain(k,r) * Wchain(k,r);
189 Qchain(k,r) = omicron * Xchain(r) * Vchain(k,r) * Wchain(k,r) + (1-omicron) * Qchain_1(k,r);
190 Tchain(k,r) = Xchain(r) * Vchain(k,r);
191 Uchain(k,r) = omicron * Vchain(k,r) * STeff(k,r) * Xchain(r) + (1-omicron) * Uchain_1(k,r);
192 end
193 end
194 end
195end
196
197
198% the next block is a coarse approximation for LD and CD, would need
199% cdterm and qterm in it but these are hidden within the iteration calls
200for k=1:M
201 for r=1:K
202 if Vchain(k,r) * STeff(k,r) >0
203 switch sn.sched(k)
204 case {SchedStrategy.FCFS, SchedStrategy.SIRO, SchedStrategy.PS, SchedStrategy.LCFSPR, SchedStrategy.DPS, SchedStrategy.HOL}
205 if sum(Uchain(k,:))>1
206 Uchain(k,r) = min(1,sum(Uchain(k,:))) * Vchain(k,r) * STeff(k,r) * Xchain(r) / ((Vchain(k,:) .* STeff(k,:)) * Xchain(:));
207 end
208 end
209 end
210 end
211end
212
213Rchain = Qchain./Tchain;
214Xchain(~isfinite(Xchain))=0;
215Uchain(~isfinite(Uchain))=0;
216%Qchain(~isfinite(Qchain))=0;
217Rchain(~isfinite(Rchain))=0;
218
219Xchain(Nchain==0)=0;
220Uchain(:,Nchain==0)=0;
221%Qchain(:,Nchain==0)=0;
222Rchain(:,Nchain==0)=0;
223Tchain(:,Nchain==0)=0;
224
225if isempty(sn.lldscaling) && isempty(sn.cdscaling) && ~sn_has_joint_dependence(sn)
226 [Q,U,R,T,C,X] = sn_deaggregate_chain_results(sn, Lchain, [], STchain, Vchain, alpha, [], [], Rchain, Tchain, [], Xchain);
227else
228 [Q,U,R,T,C,X] = sn_deaggregate_chain_results(sn, Lchain, [], STchain, Vchain, alpha, [], Uchain, Rchain, Tchain, [], Xchain);
229end
230
231% estimate normalizing constant for closed classes
232ccl = isfinite(Nchain);
233Nclosed = Nchain(ccl);
234Xclosed = Xchain(ccl);
235lG = - Nclosed(Xclosed>options.tol) * log(Xclosed(Xclosed>options.tol))'; % asymptotic approximation
236end