306 const std::size_t M = S.
rows(), J = S.
cols();
307 if (xi.
rows() != M || xi.
cols() != J)
308 throw InputError(
"pfqn_sdr: S and xi must have the same shape");
310 throw InputError(
"pfqn_sdr: the population vector must have one entry per chain");
315 std::size_t Ntot = 0;
316 for (std::size_t j = 0; j < J; ++j) Ntot += N[j];
317 for (std::size_t b = 1; b < c.
B; ++b)
318 for (std::size_t k = 0; k < sdr.
branch[b].size(); ++k)
319 if (sdr.
branch[b][k] >= M)
320 throw InputError(
"pfqn_sdr: the SDR structure references a centre index beyond "
321 "the number of centres");
325 for (std::size_t i = 0; i < M; ++i)
326 for (std::size_t k = 1; k <= Ntot; ++k) {
327 const T a = (!alpha.empty() && i < alpha.rows() && (k - 1) < alpha.cols())
330 beta(i, k) = beta(i, k - 1) * a;
334 for (std::size_t i = 0; i < M; ++i)
335 for (std::size_t j = 0; j < J; ++j) gamma(i, j) = xi(i, j) * S(i, j);
341 for (std::size_t b = 1; b < c.
B; ++b) {
342 const std::size_t t = sdr.
level[b];
343 for (std::size_t n = 1; n <= Ntot; ++n) {
344 const double f = sdr.
C[t - 1] *
static_cast<double>(n - 1) + sdr.
d(t - 1, b);
348 Matrix<T> OmTT(c.
T + 1, Ntot + 1, one), OmPrev(c.
T + 1, Ntot + 1, one);
349 for (std::size_t t = 1; t <= c.
T; ++t)
350 for (std::size_t n = 1; n <= Ntot; ++n) {
351 const double f = sdr.
C[t - 1] *
static_cast<double>(n - 1) + c.
Dtt[t];
354 const double g = sdr.
C[t - 2] *
static_cast<double>(n - 1) + c.
Dprev[t];
359 std::vector<std::vector<std::size_t>> states;
360 states.push_back(std::vector<std::size_t>());
361 for (std::size_t j = 0; j < J; ++j) {
362 std::vector<std::vector<std::size_t>> comps;
363 detail::sdr_compositions(N[j], M, comps);
364 std::vector<std::vector<std::size_t>> next;
365 next.reserve(states.size() * comps.size());
366 for (std::size_t a = 0; a < states.size(); ++a)
367 for (std::size_t b = 0; b < comps.size(); ++b) {
368 std::vector<std::size_t> row = states[a];
369 row.insert(row.end(), comps[b].begin(), comps[b].end());
376 std::vector<T> fact(Ntot + 1, one);
377 for (std::size_t k = 1; k <= Ntot; ++k)
386 std::vector<T> w(states.size(), zero);
388 for (std::size_t s = 0; s < states.size(); ++s) {
389 const std::vector<std::size_t>& flat = states[s];
390 std::vector<std::size_t> ni(M, 0);
391 for (std::size_t i = 0; i < M; ++i)
392 for (std::size_t j = 0; j < J; ++j) ni[i] += flat[j * M + i];
396 for (std::size_t i = 0; i < M && alive; ++i) {
397 weight = weight * fact[ni[i]] / beta(i, ni[i]);
398 for (std::size_t j = 0; j < J; ++j) {
399 const std::size_t nij = flat[j * M + i];
400 if (nij == 0)
continue;
401 if (!(gamma(i, j) > zero)) {
405 for (std::size_t k = 0; k < nij; ++k) weight = weight * gamma(i, j);
406 weight = weight / fact[nij];
409 if (!alive)
continue;
411 std::vector<std::size_t> m(c.
B, 0);
412 for (std::size_t b = 1; b < c.
B && alive; ++b) {
413 for (std::size_t k = 0; k < sdr.
branch[b].size(); ++k) m[b] += ni[sdr.
branch[b][k]];
414 if (Delta(b, m[b]) == zero) alive =
false;
415 weight = weight * Delta(b, m[b]);
417 if (!alive)
continue;
418 for (std::size_t t = 1; t <= c.
T && alive; ++t) {
420 for (std::size_t k = 0; k < c.
inA[t].size(); ++k) v += m[c.
inA[t][k]];
421 if (OmTT(t, v) == zero) {
425 weight = weight / OmTT(t, v);
426 if (t > 1) weight = weight * OmPrev(t, v);
428 if (!alive)
continue;
433 throw InputError(
"pfqn_sdr: the SDR network has no reachable state at the given "
434 "populations: the routing coefficients forbid every state");
437 for (std::size_t s = 0; s < states.size(); ++s) {
438 if (w[s] == zero)
continue;
439 const T p = w[s] / Gs;
440 const std::vector<std::size_t>& flat = states[s];
441 for (std::size_t i = 0; i < M; ++i) {
442 std::size_t nitot = 0;
443 for (std::size_t j = 0; j < J; ++j) nitot += flat[j * M + i];
444 for (std::size_t j = 0; j < J; ++j) {
445 const std::size_t nij = flat[j * M + i];
449 if (nitot > 0 && S(i, j) > zero) {
450 const T a = (!alpha.empty() && i < alpha.rows() && (nitot - 1) < alpha.cols())
451 ? alpha(i, nitot - 1)
453 res.
XN(i, j) = res.
XN(i, j) +
460 for (std::size_t i = 0; i < M; ++i)
461 for (std::size_t j = 0; j < J; ++j) {
462 res.
UN(i, j) = res.
XN(i, j) * S(i, j);
463 if (res.
XN(i, j) > zero) res.
RN(i, j) = res.
QN(i, j) / res.
XN(i, j);
554 const std::size_t M = S.
rows(), J = S.
cols();
555 if (xi.
rows() != M || xi.
cols() != J)
556 throw InputError(
"pfqn_sdrmva: S and xi must have the same shape");
558 throw InputError(
"pfqn_sdrmva: the population vector must have one entry per chain");
561 for (std::size_t b = 1; b < c0.
B; ++b)
562 if (sdr.
branch[b].size() != 1)
563 throw UnsupportedError(
"pfqn_sdrmva: every SDR branch must hold a single centre; the MVA "
564 "and convolution of Krzesinski (1987) Section 4 is stated that way "
565 "and its general case is in an unpublished technical report. Use "
566 "pfqn_sdr, which evaluates eq. (16) exactly for any branch topology");
567 for (std::size_t t = 0; t < c0.
T; ++t)
569 throw UnsupportedError(
"pfqn_sdrmva: every C_t must be negative; Section 2.5 assumes it and "
570 "Section 4 is written for C_t = -1");
574 for (std::size_t t = 0; t < c0.
T; ++t) {
575 const double k = -sdr.
C[t];
577 for (std::size_t b = 0; b < sdr1.
d.
cols(); ++b) sdr1.
d(t, b) = sdr.
d(t, b) / k;
582 std::size_t Ntot = 0;
583 for (std::size_t j = 0; j < J; ++j) Ntot += N[j];
586 for (std::size_t i = 0; i < M; ++i)
587 for (std::size_t j = 0; j < J; ++j) gamma(i, j) = xi(i, j) * S(i, j);
588 Matrix<T> alp(M, Ntot > 0 ? Ntot : 1, one);
589 for (std::size_t i = 0; i < M; ++i)
590 for (std::size_t k = 0; k < alp.
cols(); ++k)
591 if (!alpha.empty() && i < alpha.rows() && k < alpha.cols()) alp(i, k) = alpha(i, k);
593 const std::vector<std::vector<std::size_t>> latt = detail::sdr_lattice(N);
594 const std::size_t nl = latt.size();
596 std::vector<bool> inV(M,
false);
597 std::vector<double> dvec(M, 0.0);
598 std::vector<bool> hasd(M,
false);
599 std::vector<std::size_t> lvl(M, 0);
600 for (std::size_t b = 1; b < c.
B; ++b) {
601 const std::size_t i = sdr1.
branch[b][0];
603 lvl[i] = sdr1.
level[b];
604 dvec[i] = sdr1.
d(sdr1.
level[b] - 1, b);
607 std::vector<std::size_t> mv;
608 for (std::size_t i = 0; i < M; ++i)
609 if (!inV[i]) mv.push_back(i);
613 std::vector<Matrix<T>> Q;
614 std::vector<std::vector<T>> Tp;
617 auto set_mva = [&](
const std::vector<std::size_t>& cidx,
bool sdrset) {
620 o.Tp.assign(nl, std::vector<T>(J, zero));
621 o.g.assign(nl, zero);
622 const std::size_t
nc = cidx.size();
623 const std::size_t z = detail::sdr_key(std::vector<std::size_t>(J, 0), N);
625 for (std::size_t v = 0; v < nl; ++v) {
627 for (std::size_t j = 0; j < J; ++j) tot += latt[v][j];
628 o.g[v] = (tot == 0) ? one : zero;
633 std::vector<std::vector<std::vector<T>>>
Ps(
634 nc, std::vector<std::vector<T>>(Ntot + 1, std::vector<T>(nl, zero)));
636 for (std::size_t k = 0; k <
nc; ++k)
Ps[k][0][z] = one;
638 std::vector<std::size_t> ord(nl);
639 for (std::size_t v = 0; v < nl; ++v) ord[v] = v;
640 std::stable_sort(ord.begin(), ord.end(), [&](std::size_t a, std::size_t b) {
641 std::size_t sa = 0, sb = 0;
642 for (std::size_t j = 0; j < J; ++j) { sa += latt[a][j]; sb += latt[b][j]; }
645 for (std::size_t oi = 0; oi < nl; ++oi) {
646 const std::size_t v = ord[oi];
647 const std::vector<std::size_t>& V = latt[v];
649 for (std::size_t j = 0; j < J; ++j) vv += V[j];
650 if (vv == 0)
continue;
651 std::vector<std::vector<T>> A(
nc, std::vector<T>(J, zero));
652 std::vector<std::size_t> vm(J, 0);
653 std::vector<bool> hasm(J,
false);
654 for (std::size_t j = 0; j < J; ++j) {
655 if (V[j] == 0)
continue;
656 std::vector<std::size_t> Vm = V;
658 vm[j] = detail::sdr_key(Vm, N);
660 for (std::size_t k = 0; k <
nc; ++k) {
662 for (std::size_t n = 1; n <= vv; ++n) {
663 const double df = sdrset ? (dvec[cidx[k]] -
static_cast<double>(n - 1)) : 1.0;
664 if (df <= 0.0)
break;
672 for (std::size_t j = 0; j < J; ++j) {
673 if (!hasm[j])
continue;
675 for (std::size_t k = 0; k <
nc; ++k) den = den + gamma(cidx[k], j) * A[k][j];
679 for (std::size_t k = 0; k <
nc; ++k)
680 for (std::size_t j = 0; j < J; ++j) {
681 if (!hasm[j])
continue;
682 o.Q[v](cidx[k], j) = gamma(cidx[k], j) * o.Tp[v][j] * A[k][j];
684 for (std::size_t k = 0; k <
nc; ++k) {
686 for (std::size_t n = 1; n <= vv; ++n) {
687 const double df = sdrset ? (dvec[cidx[k]] -
static_cast<double>(n - 1)) : 1.0;
688 if (df <= 0.0)
break;
690 for (std::size_t j = 0; j < J; ++j) {
691 if (!hasm[j])
continue;
692 acc = acc + gamma(cidx[k], j) * o.Tp[v][j] *
Ps[k][n - 1][vm[j]];
695 tot = tot +
Ps[k][n][v];
697 Ps[k][0][v] = one - tot;
699 for (std::size_t j = 0; j < J; ++j)
700 if (hasm[j] && o.Tp[v][j] > zero) {
701 o.g[v] = o.g[vm[j]] / o.Tp[v][j];
708 const SetOut comp = set_mva(mv,
false);
710 std::vector<T> Gin(nl, zero);
711 Gin[detail::sdr_key(std::vector<std::size_t>(J, 0), N)] = one;
712 std::vector<Matrix<T>> Qin(nl,
Matrix<T>(M, J, zero));
713 std::vector<std::vector<T>> Ain(nl, std::vector<T>(M, zero));
714 for (std::size_t tt = c.T; tt >= 1; --tt) {
715 std::vector<std::size_t> St, inner;
716 for (std::size_t i = 0; i < M; ++i) {
717 if (inV[i] && lvl[i] == tt) St.push_back(i);
718 else if (inV[i] && lvl[i] > tt) inner.push_back(i);
720 const SetOut lev = set_mva(St,
true);
721 std::vector<T> Gnew(nl, zero);
722 std::vector<Matrix<T>> Qnew(nl, Matrix<T>(M, J, zero));
723 std::vector<std::vector<T>> Tnew(nl, std::vector<T>(J, zero));
724 std::vector<std::vector<T>> Anew(nl, std::vector<T>(M, zero));
725 for (std::size_t v = 0; v < nl; ++v) {
726 const std::vector<std::size_t>& V = latt[v];
728 for (std::size_t j = 0; j < J; ++j) vv += V[j];
729 const double omr = detail::sdr_omega_cum(c, tt, vv);
730 if (omr == 0.0)
continue;
731 std::vector<T> anum(M, zero);
732 const std::vector<std::vector<std::size_t>> sub = detail::sdr_lattice(V);
733 for (std::size_t q = 0; q < sub.
size(); ++q) {
734 std::vector<std::size_t> VL(J);
735 for (std::size_t j = 0; j < J; ++j) VL[j] = V[j] - sub[q][j];
736 const std::size_t iL = detail::sdr_key(sub[q], N), iVL = detail::sdr_key(VL, N);
737 const T pb = num_traits<T>::from_double(omr) * lev.g[iVL] * Gin[iL];
738 if (pb == zero)
continue;
739 Gnew[v] = Gnew[v] + pb;
740 for (std::size_t k = 0; k < St.size(); ++k)
741 for (std::size_t j = 0; j < J; ++j)
742 Qnew[v](St[k], j) = Qnew[v](St[k], j) + lev.Q[iVL](St[k], j) * pb;
743 for (std::size_t j = 0; j < J; ++j) Tnew[v][j] = Tnew[v][j] + lev.Tp[iVL][j] * pb;
744 for (std::size_t q2 = 0; q2 < inner.size(); ++q2) {
745 const std::size_t i = inner[q2];
746 for (std::size_t j = 0; j < J; ++j)
747 Qnew[v](i, j) = Qnew[v](i, j) + Qin[iL](i, j) * pb;
748 anum[i] = anum[i] + Ain[iL][i] * pb;
751 if (Gnew[v] > zero) {
752 for (std::size_t i = 0; i < M; ++i)
753 for (std::size_t j = 0; j < J; ++j) Qnew[v](i, j) = Qnew[v](i, j) / Gnew[v];
754 for (std::size_t j = 0; j < J; ++j) Tnew[v][j] = Tnew[v][j] / Gnew[v];
759 const T st = num_traits<T>::from_double(detail::sdr_omega_step(c, tt, vv));
760 for (std::size_t k = 0; k < St.size(); ++k) {
762 for (std::size_t j = 0; j < J; ++j) qi = qi + Qnew[v](St[k], j);
763 Anew[v][St[k]] = st * (num_traits<T>::from_double(dvec[St[k]]) - qi);
765 for (std::size_t q2 = 0; q2 < inner.size(); ++q2)
766 Anew[v][inner[q2]] = st * anum[inner[q2]] / Gnew[v];
776 std::vector<Matrix<T>> Qall(nl, Matrix<T>(M, J, zero));
777 std::vector<std::vector<T>> Tall(nl, std::vector<T>(J, zero));
778 std::vector<std::vector<T>> Aall(nl, std::vector<T>(M, zero));
779 std::vector<T> Gall(nl, zero);
780 for (std::size_t v = 0; v < nl; ++v) {
781 const std::vector<std::size_t>& Np = latt[v];
782 const std::vector<std::vector<std::size_t>> sub = detail::sdr_lattice(Np);
783 for (std::size_t q = 0; q < sub.
size(); ++q) {
784 std::vector<std::size_t> C2(J);
785 for (std::size_t j = 0; j < J; ++j) C2[j] = Np[j] - sub[q][j];
786 const std::size_t iV = detail::sdr_key(sub[q], N), iC = detail::sdr_key(C2, N);
787 const T pb = comp.g[iC] * Gin[iV];
788 if (pb == zero)
continue;
789 Gall[v] = Gall[v] + pb;
790 for (std::size_t k = 0; k < mv.size(); ++k)
791 for (std::size_t j = 0; j < J; ++j)
792 Qall[v](mv[k], j) = Qall[v](mv[k], j) + comp.Q[iC](mv[k], j) * pb;
793 for (std::size_t i = 0; i < M; ++i) {
794 if (!inV[i])
continue;
795 for (std::size_t j = 0; j < J; ++j)
796 Qall[v](i, j) = Qall[v](i, j) + Qin[iV](i, j) * pb;
797 Aall[v][i] = Aall[v][i] + Ain[iV][i] * pb;
799 for (std::size_t j = 0; j < J; ++j) Tall[v][j] = Tall[v][j] + comp.Tp[iC][j] * pb;
801 if (Gall[v] > zero) {
802 for (std::size_t i = 0; i < M; ++i) {
803 for (std::size_t j = 0; j < J; ++j) Qall[v](i, j) = Qall[v](i, j) / Gall[v];
804 Aall[v][i] = Aall[v][i] / Gall[v];
806 for (std::size_t j = 0; j < J; ++j) Tall[v][j] = Tall[v][j] / Gall[v];
810 const std::size_t vN = detail::sdr_key(N, N);
817 for (std::size_t j = 0; j < J; ++j) {
818 if (N[j] == 0)
continue;
819 std::vector<std::size_t> Nm = N;
821 const std::size_t vm = detail::sdr_key(Nm, N);
822 for (std::size_t i = 0; i < M; ++i)
823 res.XN(i, j) = inV[i] ? xi(i, j) * Tall[vN][j] * Aall[vm][i]
824 : xi(i, j) * Tall[vN][j];
826 for (std::size_t i = 0; i < M; ++i)
827 for (std::size_t j = 0; j < J; ++j) {
828 res.UN(i, j) = res.XN(i, j) * S(i, j);
829 if (res.XN(i, j) > zero) res.RN(i, j) = res.QN(i, j) / res.XN(i, j);