85 const std::vector<SchedStrategy>& sched,
const Matrix<T>& v) {
86 const std::size_t M = D.
rows();
87 const std::size_t R = N.size();
89 throw InputError(
"pfqn_schmidt: demand matrix and population vector disagree on the class count");
90 if (sched.size() != M)
91 throw InputError(
"pfqn_schmidt: scheduling vector has the wrong station count");
93 throw InputError(
"pfqn_schmidt: server-count matrix has the wrong shape");
95 throw InputError(
"pfqn_schmidt: visit-ratio matrix has the wrong shape");
97 if (n < 0)
throw InputError(
"pfqn_schmidt: negative population");
98 for (std::size_t i = 0; i < M; ++i)
99 for (std::size_t c = 0; c < S.
cols(); ++c)
100 if (S(i, c) < 1)
throw InputError(
"pfqn_schmidt: server count below one");
108 res.
XN.assign(R, zero);
112 if (M == 0)
return res;
115 if (!v.
empty()) vis = v;
118 for (std::size_t i = 0; i < M; ++i)
119 for (std::size_t c = 0; c < R; ++c) {
120 const T den = vis(i, c) > tiny ? vis(i, c) : tiny;
121 Sp(i, c) = D(i, c) / den;
124 const std::vector<std::size_t> prods =
plane_sizes(N);
127 for (
int n : N) Ntot += n;
129 auto nserv = [&](std::size_t i, std::size_t c) {
130 return S.
cols() == 1 ? S(i, 0) : S(i,
static_cast<std::size_t
>(c));
133 std::vector<bool> classIndep(M,
true);
134 for (std::size_t i = 0; i < M; ++i)
135 for (std::size_t c = 1; c < R; ++c)
136 if (D(i, c) != D(i, 0)) classIndep[i] =
false;
138 std::vector<detail::SchmidtPc> kind(M, detail::SchmidtPc::None);
139 for (std::size_t i = 0; i < M; ++i) {
141 for (std::size_t c = 0; c < (S.
cols() == 1 ? std::size_t(1) : R); ++c)
142 if (nserv(i, c) != 1) single =
false;
147 if (!single) kind[i] = detail::SchmidtPc::Scalar;
151 if (!single) kind[i] = detail::SchmidtPc::Scalar;
153 kind[i] = detail::SchmidtPc::Vector;
159 std::vector<Matrix<T>> Lq(M,
Matrix<T>(R, total, zero));
160 std::vector<Matrix<T>> Pc(M);
161 for (std::size_t i = 0; i < M; ++i) {
162 if (kind[i] == detail::SchmidtPc::Scalar)
163 Pc[i] =
Matrix<T>(
static_cast<std::size_t
>(1 + Ntot), total, zero);
164 else if (kind[i] == detail::SchmidtPc::Vector)
166 if (kind[i] != detail::SchmidtPc::None) Pc[i](0, 0) = one;
170 std::vector<T> x(M * R * total, zero), w(M * R * total, zero);
172 std::vector<int> kvec(R, 0);
173 std::size_t hlast = 0;
176 const std::size_t hk =
pop_index(kvec, prods);
179 for (
int t : kvec) kpop += t;
181 for (std::size_t i = 0; i < M; ++i)
182 for (std::size_t c = 0; c < R; ++c) {
183 if (kvec[c] <= 0)
continue;
184 const std::size_t hkc = hk - prods[c];
185 const int ns = nserv(i, c);
186 T& wi = w[(i * R + c) * total + hk];
191 const bool vectorPc = kind[i] == detail::SchmidtPc::Vector;
192 if (!vectorPc || ns == 1) {
194 for (std::size_t r = 0; r < R; ++r) qtot += Lq[i](r, hkc);
196 wi = D(i, c) * (one + qtot);
199 wi = D(i, c) / nsT * (one + qtot);
200 for (
int j = 1; j <= ns - 1; ++j)
202 Pc[i](
static_cast<std::size_t
>(j - 1), hkc) * (D(i, c) / nsT);
207 std::vector<int> nvec(R, 0);
212 for (
int t : nvec) nsum += t;
213 const std::size_t hnc =
pop_index(nvec, prods) - prods[c];
217 for (std::size_t r = 0; r < R; ++r)
220 const T den = den0 > tiny ? den0 : tiny;
224 wi += Bcn * Pc[i](hnc, hkc);
231 for (std::size_t c = 0; c < R; ++c) {
233 for (std::size_t i = 0; i < M; ++i) denom += vis(i, c) * w[(i * R + c) * total + hk];
234 for (std::size_t i = 0; i < M; ++i)
235 x[(i * R + c) * total + hk] =
239 for (std::size_t i = 0; i < M; ++i) {
240 for (std::size_t c = 0; c < R; ++c)
241 Lq[i](c, hk) = x[(i * R + c) * total + hk] * w[(i * R + c) * total + hk];
243 if (kind[i] == detail::SchmidtPc::Scalar) {
245 const int s0 = nserv(i, 0);
247 ? (s0 < kpop ? s0 : kpop)
248 : (s0 < kpop ? s0 : kpop) - 1;
249 for (
long n = 1; n <= jmax; ++n)
250 for (std::size_t c = 0; c < R; ++c) {
251 if (kvec[c] <= 0)
continue;
252 const std::size_t hkc = hk - prods[c];
253 Pc[i](
static_cast<std::size_t
>(n), hk) +=
255 Pc[i](
static_cast<std::size_t
>(n - 1), hkc);
259 : (s0 < kpop ? s0 : kpop);
261 for (
long n = 1; n <= top; ++n) acc += Pc[i](static_cast<std::size_t>(n), hk);
262 const T p0 = one - acc;
263 Pc[i](0, hk) = p0 > epsT ? p0 : epsT;
265 }
else if (kind[i] == detail::SchmidtPc::Vector) {
266 const int ns = nserv(i, 0);
269 std::vector<int> nvec(R, 0);
272 const std::size_t hn =
pop_index(nvec, prods);
274 for (
int t : nvec) nsum += t;
276 for (std::size_t c = 0; c < R; ++c) {
277 if (nvec[c] <= 0 || kvec[c] <= 0)
continue;
278 const std::size_t hnc = hn - prods[c];
279 const std::size_t hkc = hk - prods[c];
283 for (std::size_t r = 0; r < R; ++r)
286 const T den = den0 > tiny ? den0 : tiny;
291 x[(i * R + c) * total + hk] * Pc[i](hnc, hkc);
293 Pc[i](hn, hk) = prob;
297 const T p0 = one - sumAll;
298 Pc[i](0, hk) = p0 > tiny ? p0 : tiny;
305 for (std::size_t c = 0; c < R; ++c) {
307 for (std::size_t i = 0; i < M; ++i) tot += w[(i * R + c) * total + hlast];
310 for (std::size_t i = 0; i < M; ++i)
311 for (std::size_t c = 0; c < R; ++c) {
313 res.
CN(i, c) = w[(i * R + c) * total + hlast];
314 res.
QN(i, c) = Lq[i](c, hlast);