123 const std::vector<long>& c,
const std::vector<char>& insens,
126 detail::check_dims(M, R, mu, Cs, P, c, insens,
"me_oqn");
127 if (lambda0.
rows() != M || lambda0.
cols() != R || Ca0.
rows() != M || Ca0.
cols() != R)
128 throw InputError(
"me_oqn: lambda0 and Ca0 must be M x R");
135 std::vector<Matrix<T>> Peff = P;
137 for (std::size_t i = 0; i < M; ++i) {
138 for (std::size_t r = 0; r < R; ++r) {
139 const T pii = P[r](i, i);
140 if (!(pii > zero))
continue;
141 if (pii >= one)
throw InputError(
"me_oqn: a self-loop probability of one");
142 mueff(i, r) = mu(i, r) * (one - pii);
143 Cseff(i, r) = pii + (one - pii) * Cs(i, r);
144 for (std::size_t j = 0; j < M; ++j) Peff[r](i, j) = P[r](i, j) / (one - pii);
145 Peff[r](i, i) = zero;
153 for (std::size_t r = 0; r < R; ++r) {
155 std::vector<T> b(M, zero);
156 for (std::size_t i = 0; i < M; ++i) {
157 for (std::size_t j = 0; j < M; ++j) A(i, j) = (i == j ? one : zero) - P[r](j, i);
158 b[i] = lambda0(i, r);
160 const std::vector<T> x = detail::linear_solve(A, b);
161 for (std::size_t i = 0; i < M; ++i) {
163 lameff(i, r) = x[i] * (one - P[r](i, i));
169 for (std::size_t i = 0; i < M; ++i)
170 for (std::size_t r = 0; r < R; ++r) {
171 if (!(mu(i, r) > zero))
continue;
172 if (detail::is_is(c, i))
173 out.
rho(i, r) = lameff(i, r) / mueff(i, r);
177 for (std::size_t i = 0; i < M; ++i) {
178 if (detail::is_is(c, i))
continue;
180 for (std::size_t r = 0; r < R; ++r) s += out.
rho(i, r);
181 if (s >= one)
throw NumericError(
"me_oqn: the network is unstable, utilization >= 1");
189 for (
long it = 1; it <=
opt.maxiter; ++it) {
194 for (std::size_t i = 0; i < M; ++i) {
196 for (std::size_t r = 0; r < R; ++r) rho_i += out.
rho(i, r);
197 if (detail::is_is(c, i)) {
198 for (std::size_t r = 0; r < R; ++r)
199 if (lameff(i, r) > zero && mueff(i, r) > zero)
200 out.
L(i, r) = lameff(i, r) / mueff(i, r);
201 }
else if (c[i] == 1) {
203 for (std::size_t r = 0; r < R; ++r)
204 if (lameff(i, r) > zero && mueff(i, r) > zero)
205 out.
L(i, r) = out.
rho(i, r) / (one - rho_i);
208 for (std::size_t u = 0; u < R; ++u)
209 if (lameff(i, u) > zero && mueff(i, u) > zero)
210 resid += lameff(i, u) * (Cseff(i, u) + out.
Ca(i, u)) /
211 (mueff(i, u) * mueff(i, u));
212 for (std::size_t r = 0; r < R; ++r)
213 if (lameff(i, r) > zero && mueff(i, r) > zero)
214 out.
L(i, r) = out.
rho(i, r) * (out.
Ca(i, r) + one) / two +
215 lameff(i, r) * resid / (two * (one - rho_i));
219 for (std::size_t u = 0; u < R; ++u)
220 if (lameff(i, u) > zero && mueff(i, u) > zero) lam_a += lameff(i, u);
221 if (!(lam_a > zero))
continue;
222 T inv_a = zero, ES = zero, ES2 = zero;
223 for (std::size_t u = 0; u < R; ++u) {
224 if (!(lameff(i, u) > zero && mueff(i, u) > zero))
continue;
225 const T wu = lameff(i, u) / lam_a;
226 inv_a += wu / (out.
Ca(i, u) + one);
227 ES += wu / mueff(i, u);
228 ES2 += wu * (Cseff(i, u) + one) / (mueff(i, u) * mueff(i, u));
230 const T Ca_a = -one + one / inv_a;
231 const T Cs_a = ES2 / (ES * ES) - one;
232 const T L_a = detail::ge_gec_mql(lam_a, Ca_a, T(one / ES), Cs_a, c[i]);
233 const T Lq_a = L_a - lam_a * ES;
234 for (std::size_t r = 0; r < R; ++r)
235 if (lameff(i, r) > zero && mueff(i, r) > zero)
237 (lameff(i, r) / lam_a) * Lq_a;
242 for (std::size_t j = 0; j < M; ++j) {
244 for (std::size_t r = 0; r < R; ++r) rho_j += out.
rho(j, r);
245 for (std::size_t r = 0; r < R; ++r) {
246 if (!(lameff(j, r) > zero))
continue;
247 if (detail::is_is(c, j)) {
248 out.
Cd(j, r) = out.
Ca(j, r);
249 }
else if (c[j] == 1) {
250 const T den = out.
L(j, r) + rho_j - out.
rho(j, r);
251 const T rhohat = den == zero ? zero : out.
rho(j, r) * out.
L(j, r) / den;
252 out.
Cd(j, r) = two * out.
L(j, r) * (one - rhohat) +
253 out.
Ca(j, r) * (one - two * rhohat);
255 out.
Cd(j, r) = rho_j * (one - rho_j) + (one - rho_j) * out.
Ca(j, r) +
256 rho_j * rho_j * Cseff(j, r);
262 for (std::size_t i = 0; i < M; ++i) {
263 for (std::size_t r = 0; r < R; ++r) {
264 if (!(lameff(i, r) > zero))
continue;
266 for (std::size_t j = 0; j < M; ++j) {
267 const T pji = Peff[r](j, i);
268 if (!(pji > zero) || !(lameff(j, r) > zero))
continue;
269 const T Cdji = one + pji * (out.
Cd(j, r) - one);
270 sum_inv += (lameff(j, r) * pji / lameff(i, r)) / (Cdji + one);
272 if (lambda0(i, r) > zero)
273 sum_inv += (lambda0(i, r) / lameff(i, r)) / (Ca0(i, r) + one);
274 if (sum_inv > zero) out.
Ca(i, r) = -one + one / sum_inv;
279 for (std::size_t i = 0; i < M; ++i)
280 for (std::size_t r = 0; r < R; ++r) {
281 const T d =
num_abs(T(out.
Ca(i, r) - Caold(i, r)));
282 if (d > delta) delta = d;
292 for (std::size_t i = 0; i < M; ++i)
293 for (std::size_t r = 0; r < R; ++r)
294 if (out.
lambda(i, r) > zero) out.
W(i, r) = out.
L(i, r) / out.
lambda(i, r);
296 out.
X.assign(R, zero);
297 for (std::size_t r = 0; r < R; ++r)
298 for (std::size_t i = 0; i < M; ++i) out.
X[r] += lambda0(i, r);