98 const std::vector<T>& Z,
const std::vector<int>& mi) {
99 const std::size_t M = L.
rows();
100 const std::size_t R = N.size();
102 throw InputError(
"pfqn_sens_mva: demand matrix and population vector disagree on the class count");
103 if (!Z.empty() && Z.size() != R)
104 throw InputError(
"pfqn_sens_mva: think-time vector has the wrong length");
105 if (!mi.empty() && mi.size() != M)
106 throw InputError(
"pfqn_sens_mva: multiplicity vector has the wrong length");
111 res.
XN.assign(R, zero);
120 bool anyPositive =
false;
122 if (v < 0)
throw InputError(
"pfqn_sens_mva: negative population");
123 if (v > 0) anyPositive =
true;
125 if (!anyPositive || M == 0 || R == 0)
return res;
127 const auto Zr = [&](std::size_t r) -> T {
return Z.empty() ? zero : Z[r]; };
128 const auto miT = [&](std::size_t i) -> T {
138 std::vector<Matrix<T>> Qcls(totpop,
Matrix<T>(M, R, zero));
140 std::vector<Matrix<T>> Ssum(totpop,
Matrix<T>(M, R, zero));
142 std::vector<std::size_t> rows(R, 0);
144 for (std::size_t k = 1; k < totpop; ++k) {
148 for (std::size_t s = 0; s < R; ++s) {
150 const std::size_t row = n[s] > 0 ? k - radix[s] : 0;
153 for (std::size_t i = 0; i < M; ++i) {
154 res.
CN(i, s) = L(i, s) * (miT(i) + Qtot(row, i));
155 CNtot += res.
CN(i, s);
157 const T den = Zr(s) + CNtot;
163 Xall(k, s) = res.
XN[s];
164 for (std::size_t i = 0; i < M; ++i) {
165 res.
QN(i, s) = res.
XN[s] * res.
CN(i, s);
166 Qcls[k](i, s) = res.
QN(i, s);
167 Qtot(k, i) += res.
QN(i, s);
172 for (std::size_t j = 0; j < M; ++j) {
173 for (std::size_t kk = 0; kk < R; ++kk) {
174 const T Qjk = Qcls[k](j, kk);
176 for (std::size_t t = 0; t < R; ++t) {
177 const T Qjt = Qcls[k](j, t);
178 T wkt = Qjt * (Qcls[rows[t]](j, kk) - Qjk);
179 if (kk == t) wkt += Qjt;
180 wkt += Xall(k, t) * L(j, t) * Ssum[rows[t]](j, kk);
181 res.
QCov[j](kk, t) = wkt;
189 for (std::size_t i = 0; i < M; ++i)
190 for (std::size_t r = 0; r < R; ++r) res.
UN(i, r) = res.
XN[r] * L(i, r);
193 for (std::size_t i = 0; i < M; ++i) {
194 for (std::size_t r = 0; r < R; ++r) {
195 for (std::size_t s = r + 1; s < R; ++s) {
199 res.
QCov[i](r, s) = avg;
200 res.
QCov[i](s, r) = avg;
204 for (std::size_t r = 0; r < R; ++r) {
206 for (std::size_t s = 0; s < R; ++s) tot += res.
QCov[i](r, s);
std::vector< int > sens_lattice_decode(std::size_t k, const std::vector< int > &N, const std::vector< std::size_t > &radix)
Decode a lattice index back into a population vector.
SensMvaResult< T > pfqn_sens_mva(const Matrix< T > &L, const std::vector< int > &N, const std::vector< T > &Z, const std::vector< int > &mi)
Exact per-station queue-length variances and covariances of a closed product-form network,...