123 const std::vector<std::function<T(
const std::vector<int>&)>>& mu,
125 const std::size_t R = N.size();
126 if (R == 0)
throw InputError(
"pfqn_mvaoi: empty population vector");
127 if (Z.size() != R)
throw InputError(
"pfqn_mvaoi: Z and N disagree on the class count");
128 if (mu.empty())
throw InputError(
"pfqn_mvaoi: mu must be a nonempty list of OI rate handles");
129 const std::size_t K = mu.size();
130 for (std::size_t i = 0; i < K; ++i)
131 if (!mu[i])
throw InputError(
"pfqn_mvaoi: each mu[i] must be callable");
132 const std::size_t J = Dli.
empty() ? 0 : Dli.
rows();
133 if (J > 0 && Dli.
cols() != R)
134 throw InputError(
"pfqn_mvaoi: Dli and N disagree on the class count");
135 if (!visits.
empty() && (visits.
rows() != K || visits.
cols() != R))
136 throw InputError(
"pfqn_mvaoi: visits must be K x R");
137 for (std::size_t r = 0; r < R; ++r)
138 if (N[r] < 0)
throw InputError(
"pfqn_mvaoi: pfqn_mvaoi requires finite closed populations");
142 std::map<std::vector<int>, std::vector<T>> Xc;
143 std::map<std::vector<int>,
Matrix<T>> Qlc;
144 std::vector<std::map<std::vector<int>, std::vector<T>>> Dc(K), Qc(K);
145 std::vector<std::map<std::vector<int>, std::vector<std::pair<bool, T>>>> Rc(K);
150 std::vector<std::vector<std::vector<int>>> comps(R);
151 for (std::size_t r = 0; r < R; ++r)
153 std::vector<std::pair<int, std::pair<Matrix<int>, std::vector<int>>>> states;
155 std::vector<std::size_t> idx(R, 0);
159 std::vector<int> Nn(R, 0);
161 for (std::size_t r = 0; r < R; ++r) {
162 const std::vector<int>& c = comps[r][idx[r]];
163 for (std::size_t i = 0; i < K; ++i) S(i, r) = c[i];
167 states.push_back(std::make_pair(tot, std::make_pair(S, Nn)));
170 if (++idx[d] < comps[d].size())
break;
176 std::stable_sort(states.begin(), states.end(),
177 [](
const std::pair<
int, std::pair<
Matrix<int>, std::vector<int>>>& x,
178 const std::pair<
int, std::pair<
Matrix<int>, std::vector<int>>>& y) {
179 return x.first < y.first;
183 std::function<T(std::size_t, std::size_t,
const Matrix<int>&,
const std::vector<int>&)> rho_fn =
184 [&](std::size_t i, std::size_t r,
const Matrix<int>& S,
const std::vector<int>& Mv) -> T {
185 const std::vector<int> rkey = detail::mvaoi_key(S, Mv);
186 auto it = Rc[i].find(rkey);
187 if (it != Rc[i].end() && it->second[r].first)
return it->second[r].second;
189 for (
int x : Mv) tot += x;
191 if (it == Rc[i].end())
192 it = Rc[i].insert(std::make_pair(rkey, std::vector<std::pair<bool, T>>(
193 R, std::make_pair(
false, zero))))
195 it->second[r] = std::make_pair(
true, one);
199 for (std::size_t t = 0; t < R; ++t)
200 if (t != r && Mv[t] > 0) {
204 if (rs == R)
throw NumericError(
"pfqn_mvaoi: rho recursion has no class to decrement");
205 const std::vector<T>& xu = Xc.at(detail::mvaoi_key(S, Mv));
208 const std::vector<T>& xu2 = Xc.at(detail::mvaoi_key(Sp, Mv));
210 if (xu2[rs] > zero) ratio = xu[rs] / xu2[rs];
211 std::vector<int> Mm = Mv;
213 const T v = rho_fn(i, r, S, Mm) * ratio;
214 it = Rc[i].find(rkey);
215 if (it == Rc[i].end())
216 it = Rc[i].insert(std::make_pair(
217 rkey, std::vector<std::pair<bool, T>>(R, std::make_pair(
false, zero))))
219 it->second[r] = std::make_pair(
true, v);
223 for (std::size_t p = 0; p < states.size(); ++p) {
225 const std::vector<int>& Nn = states[p].second.second;
226 const std::vector<int> key = detail::mvaoi_key(S, Nn);
227 if (states[p].first == 0) {
230 Xc[key] = std::vector<T>(R, zero);
232 for (std::size_t i = 0; i < K; ++i) {
233 Dc[i][key] = std::vector<T>(R, zero);
234 Qc[i][key] = std::vector<T>(R, zero);
240 std::vector<Matrix<T>> Qsub(K,
Matrix<T>(R, R, zero));
241 for (std::size_t i = 0; i < K; ++i) {
242 for (std::size_t r = 0; r < R; ++r) {
243 if (Nn[r] == 0)
continue;
244 std::vector<int> Nr = Nn;
247 std::vector<int> occ(R, 0);
248 for (std::size_t t = 0; t < R; ++t) occ[t] = S(i, t);
250 const T mur = mu[i](occ);
251 const T vir = visits.
empty() ? one : visits(i, r);
252 if (mur > zero) Dt(i, r) = (vir / mur) * rho_fn(i, r, S, Nr);
256 const std::vector<T>& xs = Xc.at(detail::mvaoi_key(S, Nr));
257 const std::vector<T>& xs2 = Xc.at(detail::mvaoi_key(Sp, Nr));
259 const std::vector<T>& Dprev = Dc[i].at(detail::mvaoi_key(S, Nr));
260 Dt(i, r) = (xs[r] / xs2[r]) * Dprev[r];
264 for (std::size_t s = 0; s < R; ++s) {
265 if (Nn[s] == 0)
continue;
268 std::vector<int> Ns = Nn;
270 const std::vector<T>& q = Qc[i].at(detail::mvaoi_key(Ss, Ns));
271 for (std::size_t t = 0; t < R; ++t) Qsub[i](s, t) = q[t];
277 for (std::size_t r = 0; r < R; ++r) {
278 if (Nn[r] == 0)
continue;
279 std::vector<int> Nr = Nn;
281 const Matrix<T>& Qli_prev = Qlc.at(detail::mvaoi_key(S, Nr));
282 for (std::size_t j = 0; j < J; ++j) {
284 for (std::size_t t = 0; t < R; ++t) s += Qli_prev(j, t);
285 betaLI(j, r) = Dli(j, r) * (one + s);
290 std::vector<std::size_t> idx;
291 for (std::size_t r = 0; r < R; ++r)
292 if (Nn[r] > 0) idx.push_back(r);
293 const std::size_t m = idx.size();
295 for (std::size_t a = 0; a < m; ++a) {
296 const std::size_t r = idx[a];
297 for (std::size_t b = 0; b < m; ++b) {
298 const std::size_t s = idx[b];
302 for (std::size_t j = 0; j < J; ++j) val += betaLI(j, r);
303 for (std::size_t i = 0; i < K; ++i) val += Dt(i, r) * (one + Qsub[i](r, r));
305 for (std::size_t i = 0; i < K; ++i) val += Dt(i, s) * Qsub[i](s, r);
311 std::vector<T> Xk(R, zero);
312 for (std::size_t a = 0; a < m; ++a) {
313 const std::size_t r = idx[a];
315 std::vector<int> Nr = Nn;
317 const std::vector<T>& Xner = Xc.at(detail::mvaoi_key(S, Nr));
318 for (std::size_t b = 0; b < m; ++b) {
319 if (b == a)
continue;
320 const std::size_t s = idx[b];
321 std::vector<int> Ns = Nn;
323 const std::vector<T>& Xnes = Xc.at(detail::mvaoi_key(S, Ns));
324 if (Xnes[r] > zero) denom += A(a, b) * (Xner[s] / Xnes[r]);
330 for (std::size_t r = 0; r < R; ++r) {
331 if (Nn[r] == 0)
continue;
332 for (std::size_t j = 0; j < J; ++j) Qk_li(j, r) = Xk[r] * betaLI(j, r);
334 for (std::size_t i = 0; i < K; ++i) {
335 std::vector<T> U(R, zero), Qi(R, zero), Drow(R, zero);
336 for (std::size_t r = 0; r < R; ++r) {
338 U[r] = Dt(i, r) * Xk[r];
340 for (std::size_t r = 0; r < R; ++r) {
342 for (std::size_t t = 0; t < R; ++t) s += U[t] * Qsub[i](t, r);
352 const std::vector<int> keyN = detail::mvaoi_key(zeroS, N);
356 for (std::size_t i = 0; i < K; ++i) {
357 const std::vector<T>& q = Qc[i].at(keyN);
358 for (std::size_t r = 0; r < R; ++r) res.
Qoi(i, r) = q[r];
360 res.
Qli = Qlc.at(keyN);
361 res.
Qdelay.assign(R, zero);
362 for (std::size_t r = 0; r < R; ++r) res.
Qdelay[r] = res.
X[r] * Z[r];
363 if (!want_soi)
return res;
366 std::vector<std::size_t> shp(R), stride(R, 1);
367 std::size_t total = 1;
368 for (std::size_t d = 0; d < R; ++d) shp[d] = static_cast<std::size_t>(N[d]) + 1;
369 for (std::size_t d = 1; d < R; ++d) stride[d] = stride[d - 1] * shp[d - 1];
370 for (std::size_t d = 0; d < R; ++d) total *= shp[d];
371 std::vector<std::vector<int>> subs(total, std::vector<int>(R, 0));
372 std::vector<int> ssum(total, 0);
373 for (std::size_t i = 0; i < total; ++i) {
375 for (std::size_t d = 0; d < R; ++d) {
376 subs[i][d] =
static_cast<int>(li % shp[d]);
378 ssum[i] += subs[i][d];
381 std::vector<std::size_t> ord(total);
382 for (std::size_t i = 0; i < total; ++i) ord[i] = i;
383 std::stable_sort(ord.begin(), ord.end(),
384 [&](std::size_t a, std::size_t b) { return ssum[a] < ssum[b]; });
387 for (std::size_t i = 0; i < total; ++i) {
388 const std::vector<T>& x = Xc.at(detail::mvaoi_key(zeroS, subs[i]));
389 for (std::size_t r = 0; r < R; ++r) Xlat(i, r) = x[r];
393 for (std::size_t mm = 0; mm < K; ++mm) {
395 std::vector<T> muv(total, zero);
396 for (std::size_t i = 0; i < total; ++i)
397 if (ssum[i] > 0) muv[i] = mu[mm](subs[i]);
400 for (std::size_t bb = 0; bb < total; ++bb) {
401 const std::size_t b = ord[bb];
402 if (ssum[b] == 0)
continue;
404 for (std::size_t aa = 0; aa < total; ++aa) {
405 const std::size_t a = ord[aa];
406 if (ssum[a] == 0)
continue;
408 for (std::size_t r = 0; r < R; ++r)
409 if (subs[a][r] > subs[b][r]) {
413 if (!fits || !(muv[a] > zero))
continue;
415 for (std::size_t r = 0; r < R; ++r)
417 acc += Xlat(b, r) * pMv(a - stride[r], b - stride[r]);
418 pMv(a, b) = acc / muv[a];
421 pMv(0, b) = one - acc0;
423 const std::size_t idxN = total - 1;
424 for (std::size_t r = 0; r < R; ++r) {
426 for (std::size_t a = 0; a < total; ++a) s += pMv(a, idxN) * gm.
g(a, r);