118 const std::vector<bool>& isDelay,
119 const std::vector<std::function<T(
const std::vector<int>&)>>& mu) {
120 const std::size_t M = D.
rows(), R = N.size();
121 if (M == 0 || R == 0)
throw InputError(
"pfqn_mvaoi_marg: empty model");
122 if (D.
cols() != R)
throw InputError(
"pfqn_mvaoi_marg: D and N disagree on the class count");
123 if (isDelay.size() != M || mu.size() != M)
124 throw InputError(
"pfqn_mvaoi_marg: isDelay and mu must have one entry per station");
125 for (std::size_t r = 0; r < R; ++r)
126 if (N[r] < 0)
throw InputError(
"pfqn_mvaoi_marg: negative population");
132 std::vector<std::size_t> oi_list;
133 std::vector<bool> isOI(M,
false);
134 for (std::size_t i = 0; i < M; ++i)
137 oi_list.push_back(i);
139 const std::size_t nOI = oi_list.size();
142 "pfqn_mvaoi_marg: at least one order-independent station is required");
145 std::vector<std::function<T(
const std::vector<int>&)>> muM(nOI);
146 for (std::size_t o = 0; o < nOI; ++o) {
147 const std::function<T(
const std::vector<int>&)> f = mu[oi_list[o]];
148 muM[o] = [f, zero](
const std::vector<int>& n) -> T {
150 for (
int x : n) tot += x;
151 if (tot == 0)
return zero;
152 return f(detail::microstate(n));
156 std::map<std::vector<int>, std::vector<T>> X_cache;
157 std::map<std::vector<int>,
Matrix<T>> Q_cache;
158 std::vector<std::map<std::vector<int>, std::map<std::vector<int>, T>>> pM(nOI);
160 const std::vector<int> zeroK(R, 0);
161 X_cache[zeroK] = std::vector<T>(R, zero);
163 for (std::size_t o = 0; o < nOI; ++o) pM[o][zeroK][zeroK] = one;
165 std::vector<std::vector<int>> pops = detail::enum_vecs(N);
166 std::stable_sort(pops.begin(), pops.end(),
167 [](
const std::vector<int>& a,
const std::vector<int>& b) {
169 for (int x : a) sa += x;
170 for (int x : b) sb += x;
171 if (sa != sb) return sa < sb;
176 const auto oi_marginal = [&](
const std::vector<int>& k,
const std::vector<T>& Xk,
177 const std::function<T(
const std::vector<int>&)>& mrate,
178 const std::map<std::vector<int>, std::map<std::vector<int>, T>>&
cache) {
179 std::map<std::vector<int>, T> out;
180 const std::vector<std::vector<int>> vecs = detail::enum_vecs(k);
182 bool haveZero =
false;
183 for (std::size_t idx = 0; idx < vecs.size(); ++idx) {
184 const std::vector<int>& n = vecs[idx];
186 for (
int x : n) tot += x;
191 const T rate = mrate(n);
192 if (!(rate > zero))
continue;
194 for (std::size_t r = 0; r < R; ++r) {
195 if (n[r] < 1 || k[r] < 1)
continue;
196 std::vector<int> nr = n, kr = k;
199 auto itk =
cache.find(kr);
200 if (itk ==
cache.end())
continue;
201 auto itn = itk->second.find(nr);
202 if (itn == itk->second.end())
continue;
203 acc += Xk[r] * itn->second;
205 const T p = acc / rate;
209 if (haveZero) out[std::vector<int>(R, 0)] = one - psum;
213 for (std::size_t pidx = 0; pidx < pops.size(); ++pidx) {
214 const std::vector<int>& k = pops[pidx];
216 for (
int x : k) ktot += x;
217 if (ktot == 0)
continue;
221 std::vector<T> A(R, zero);
222 for (std::size_t r = 0; r < R; ++r) {
223 if (k[r] == 0)
continue;
224 std::vector<int> kr = k;
227 for (std::size_t i = 0; i < M; ++i) {
228 if (isOI[i])
continue;
230 Rfix(i, r) = D(i, r);
233 for (std::size_t t = 0; t < R; ++t) s += Qkr(i, t);
234 Rfix(i, r) = D(i, r) * (one + s);
240 std::vector<T> Xk(R, zero);
241 for (std::size_t r = 0; r < R; ++r)
244 std::vector<std::map<std::vector<int>, T>> marg(nOI);
245 for (
int it = 0; it < 2000; ++it) {
246 std::vector<T> QMtot(R, zero);
247 for (std::size_t o = 0; o < nOI; ++o) {
248 marg[o] = oi_marginal(k, Xk, muM[o], pM[o]);
249 for (
auto itm = marg[o].begin(); itm != marg[o].end(); ++itm)
250 for (std::size_t r = 0; r < R; ++r)
253 std::vector<T> Xnew(R, zero);
254 for (std::size_t r = 0; r < R; ++r)
255 if (k[r] > 0 && A[r] > zero) {
257 Xnew[r] = (v > zero) ? v : zero;
260 for (std::size_t r = 0; r < R; ++r) {
261 const T d =
num_abs(T(Xnew[r] - Xk[r]));
268 for (std::size_t r = 0; r < R; ++r) Xk[r] = half * Xk[r] + half * Xnew[r];
270 for (std::size_t o = 0; o < nOI; ++o) marg[o] = oi_marginal(k, Xk, muM[o], pM[o]);
273 for (std::size_t o = 0; o < nOI; ++o)
274 for (
auto itm = marg[o].begin(); itm != marg[o].end(); ++itm)
275 for (std::size_t r = 0; r < R; ++r)
277 for (std::size_t r = 0; r < R; ++r)
278 for (std::size_t i = 0; i < M; ++i)
279 if (!isOI[i]) Qk(i, r) = Xk[r] * Rfix(i, r);
283 for (std::size_t o = 0; o < nOI; ++o) pM[o][k] = marg[o];
287 res.
X = X_cache.at(N);
288 res.
Q = Q_cache.at(N);