74 "lossn_asy requires transcendental arithmetic (Newton steps on exponentials)");
78 const std::size_t R = nu.size();
79 const std::size_t J = C.size();
81 throw InputError(
"lossn_asy: A must be " + std::to_string(J) +
"x" + std::to_string(R) +
84 for (std::size_t k = 0; k < R; ++k)
85 if (nu[k] < zero)
throw InputError(
"lossn_asy: nu, A and C must be nonnegative.");
86 for (std::size_t j = 0; j < J; ++j) {
87 if (C[j] < zero)
throw InputError(
"lossn_asy: nu, A and C must be nonnegative.");
88 for (std::size_t k = 0; k < R; ++k)
89 if (A(j, k) < zero)
throw InputError(
"lossn_asy: nu, A and C must be nonnegative.");
94 const int maxsweeps = 10000;
99 out.
a.assign(J, zero);
100 std::vector<char> dead(J, 0), lost(R, 0);
101 for (std::size_t j = 0; j < J; ++j) {
102 if (!(C[j] <= zero))
continue;
103 for (std::size_t k = 0; k < R; ++k)
104 if (A(j, k) > zero) dead[j] = 1;
107 for (std::size_t k = 0; k < R; ++k)
108 if (A(j, k) > zero) lost[k] = 1;
111 std::vector<T> nul = nu;
112 for (std::size_t k = 0; k < R; ++k)
113 if (lost[k]) nul[k] = zero;
115 std::vector<T> y(J, zero);
116 std::vector<T> s(R, zero);
117 std::vector<std::size_t> users;
118 std::vector<T> Aj, rest, base, e;
119 for (
int sweep = 1; sweep <= maxsweeps; ++sweep) {
122 for (std::size_t j = 0; j < J; ++j) {
123 if (dead[j])
continue;
125 for (std::size_t k = 0; k < R; ++k)
126 if (A(j, k) > zero && nul[k] > zero) users.push_back(k);
127 if (users.empty())
continue;
128 const std::size_t U = users.size();
130 rest.assign(U, zero);
131 base.assign(U, zero);
134 for (std::size_t u = 0; u < U; ++u) {
135 Aj[u] = A(j, users[u]);
136 rest[u] = T(s[users[u]] - Aj[u] * y[j]);
137 base[u] = T(nul[users[u]] * exp(T(-rest[u])));
138 sab += T(Aj[u] * base[u]);
142 if (!(T(C[j] - sab) >= zero)) {
145 for (std::size_t u = 0; u < U; ++u) g0 += T(Aj[u] * base[u] * exp(T(-Aj[u] * t)));
146 if (T(C[j] - g0) > zero) t = zero;
147 for (
int it = 1; it <= 100; ++it) {
148 T g = C[j], dg = zero;
149 for (std::size_t u = 0; u < U; ++u) {
150 e[u] = T(base[u] * exp(T(-Aj[u] * t)));
151 g -= T(Aj[u] * e[u]);
152 dg += T(Aj[u] * Aj[u] * e[u]);
154 const T step = T(-g / dg);
156 const T scale = t > one ? t : one;
157 if (abs(step) <= T(steptol * scale))
break;
160 const T anew = T(-expm1(T(-t)));
161 const T d = abs(T(anew + expm1(T(-y[j]))));
162 if (d > change) change = d;
163 for (std::size_t u = 0; u < U; ++u) s[users[u]] = T(rest[u] + Aj[u] * t);
166 if (change <= tol)
break;
168 for (std::size_t j = 0; j < J; ++j)
169 if (!dead[j]) out.
a[j] = T(-expm1(T(-y[j])));
171 out.
Loss.assign(R, zero);
172 out.
QLen.assign(R, zero);
173 for (std::size_t k = 0; k < R; ++k) {
178 for (std::size_t j = 0; j < J; ++j)
179 if (!dead[j]) ay += T(A(j, k) * y[j]);
180 out.
Loss[k] = T(-expm1(T(-ay)));
182 out.
QLen[k] = T(nu[k] * T(one - out.
Loss[k]));