87 const std::vector<T>& Z,
const std::vector<int>& mi,
88 const std::vector<int>& groups) {
89 const std::size_t M = L.
rows();
90 const std::size_t R = N.size();
92 throw InputError(
"pfqn_sens_mom: demand matrix and population vector disagree on the class count");
93 if (!Z.empty() && Z.size() != R)
94 throw InputError(
"pfqn_sens_mom: think-time vector has the wrong length");
95 if (!mi.empty() && mi.size() != M)
96 throw InputError(
"pfqn_sens_mom: multiplicity vector has the wrong length");
98 std::vector<int> grp = groups.empty() ? std::vector<int>(R, 0) : groups;
100 throw InputError(
"pfqn_sens_mom: groups must have one label per class");
103 if (g < 0)
throw InputError(
"pfqn_sens_mom: group labels start at zero");
104 if (
static_cast<std::size_t
>(g) + 1 > G) G =
static_cast<std::size_t
>(g) + 1;
107 std::vector<bool> seen(G,
false);
108 for (
int g : grp) seen[
static_cast<std::size_t
>(g)] =
true;
109 for (std::size_t g = 0; g < G; ++g)
111 throw InputError(
"pfqn_sens_mom: groups must label the classes consecutively with no empty group");
115 const std::size_t P = M * G;
118 res.
XN.assign(R, zero);
132 bool anyPositive =
false;
134 if (v < 0)
throw InputError(
"pfqn_sens_mom: negative population");
135 if (v > 0) anyPositive =
true;
137 if (!anyPositive || M == 0 || R == 0)
return res;
139 const auto Zr = [&](std::size_t r) -> T {
return Z.empty() ? zero : Z[r]; };
140 const auto miT = [&](std::size_t i) -> T {
143 const auto pidx = [&](std::size_t h, std::size_t g) {
return h * G + g; };
149 std::vector<Matrix<T>> D1(totpop,
Matrix<T>(M, P, zero));
150 std::vector<Matrix<T>> D2(totpop,
Matrix<T>(M, P, zero));
155 std::vector<Matrix<T>> D1Qg(P,
Matrix<T>(M, G, zero));
156 std::vector<Matrix<T>> D2Qg(P,
Matrix<T>(M, G, zero));
158 std::vector<T> Cs(M, zero), dCNtot(P, zero), d2CNtot(P, zero), dX(P, zero), d2X(P, zero);
159 Matrix<T> dCs(M, P, zero), d2Cs(M, P, zero);
161 for (std::size_t k = 1; k < totpop; ++k) {
164 for (std::size_t p = 0; p < P; ++p) {
168 for (std::size_t s = 0; s < R; ++s) {
169 const std::size_t row = n[s] > 0 ? k - radix[s] : 0;
170 const std::size_t gs =
static_cast<std::size_t
>(grp[s]);
174 for (std::size_t p = 0; p < P; ++p) {
178 for (std::size_t i = 0; i < M; ++i) {
179 const T A = miT(i) + Qtot(row, i);
181 res.
CN(i, s) = Cs[i];
183 for (std::size_t p = 0; p < P; ++p) {
184 const T dA = D1[row](i, p);
185 const T d2A = D2[row](i, p);
186 if (p == pidx(i, gs)) {
187 dCs(i, p) = L(i, s) * (A + dA);
190 dCs(i, p) = L(i, s) * dA;
191 d2Cs(i, p) = L(i, s) * d2A;
193 dCNtot[p] += dCs(i, p);
194 d2CNtot[p] += d2Cs(i, p);
199 const T den = Zr(s) + CNtot;
203 for (std::size_t p = 0; p < P; ++p) {
208 const T den2 = den * den;
209 const T den3 = den2 * den;
210 res.
XN[s] = nsT / den;
211 for (std::size_t p = 0; p < P; ++p) {
212 dX[p] = -nsT * dCNtot[p] / den2;
213 d2X[p] = -nsT * d2CNtot[p] / den2 +
219 for (std::size_t i = 0; i < M; ++i) {
220 res.
QN(i, s) = res.
XN[s] * Cs[i];
221 Qtot(k, i) += res.
QN(i, s);
222 Qg(i, gs) += res.
QN(i, s);
223 for (std::size_t p = 0; p < P; ++p) {
224 const T dQ = dX[p] * Cs[i] + res.
XN[s] * dCs(i, p);
225 const T d2Q = d2X[p] * Cs[i] +
227 res.
XN[s] * d2Cs(i, p);
230 D1Qg[p](i, gs) += dQ;
231 D2Qg[p](i, gs) += d2Q;
237 for (std::size_t i = 0; i < M; ++i)
238 for (std::size_t r = 0; r < R; ++r) res.
UN(i, r) = res.
XN[r] * L(i, r);
240 for (std::size_t i = 0; i < M; ++i)
241 for (std::size_t g = 0; g < G; ++g) {
242 res.
m(i, g) = Qg(i, g);
243 for (std::size_t j = 0; j < M; ++j)
244 for (std::size_t g2 = 0; g2 < G; ++g2)
245 res.
dm(pidx(i, g), pidx(j, g2)) = D1Qg[pidx(j, g2)](i, g);
246 res.
d2m(i, g) = D2Qg[pidx(i, g)](i, g);
251 for (std::size_t a = 0; a < P; ++a)
252 for (std::size_t b = 0; b < P; ++b) {
253 const T d =
num_abs(T(res.
dm(a, b) - res.
dm(b, a)));
256 for (std::size_t a = 0; a < P; ++a)
257 for (std::size_t b = 0; b < P; ++b)
260 for (std::size_t i = 0; i < M; ++i)
261 for (std::size_t g = 0; g < G; ++g) {
262 const T d1 = res.
dm(pidx(i, g), pidx(i, g));
263 const T mi_g = res.
m(i, g);
265 res.
M2(i, g) = d1 + mi_g * mi_g;
266 res.
M3(i, g) = res.
d2m(i, g) +