215 const std::vector<std::vector<std::size_t> >& subnets,
216 const std::vector<std::vector<std::size_t> >& localclasses,
218 std::size_t maxiter = 1000) {
219 const std::size_t M = L.
rows(), R = L.
cols();
220 if (N.size() != R)
throw InputError(
"pfqn_clust: L and N disagree on the class count");
221 if (!Z.empty() && Z.size() != R)
throw InputError(
"pfqn_clust: Z has the wrong length");
222 if (subnets.size() != localclasses.size())
223 throw InputError(
"pfqn_clust: subnets and localclasses disagree on the cluster count");
226 const std::vector<T> Zv = Z.empty() ? std::vector<T>(R, zero) : Z;
234 if (M == 0)
return r;
236 std::vector<std::vector<std::size_t> > nets = subnets, locals = localclasses;
237 if (nets.empty() || locals.empty()) {
238 std::vector<std::size_t> bottleneck(R, 0);
239 for (std::size_t s = 0; s < R; ++s) {
242 for (std::size_t i = 0; i < M; ++i) {
243 if (!(L(i, s) > zero))
continue;
244 const T u = L(i, s) * r.
XN[s];
245 if (!any || u > best) {
252 std::vector<std::size_t> centres;
253 for (std::size_t s = 0; s < R; ++s)
254 if (std::find(centres.begin(), centres.end(), bottleneck[s]) == centres.end())
255 centres.push_back(bottleneck[s]);
256 std::sort(centres.begin(), centres.end());
259 std::vector<bool> covered(M,
false);
260 for (std::size_t g = 0; g < centres.size(); ++g) {
261 std::vector<std::size_t> cls;
262 for (std::size_t s = 0; s < R; ++s)
263 if (bottleneck[s] == centres[g]) cls.push_back(s);
264 std::vector<std::size_t> st;
265 for (std::size_t i = 0; i < M; ++i)
266 for (std::size_t a = 0; a < cls.size(); ++a)
267 if (L(i, cls[a]) > zero) {
271 if (st.empty()) st.push_back(centres[g]);
272 for (std::size_t a = 0; a < st.size(); ++a) covered[st[a]] =
true;
274 locals.push_back(cls);
276 std::vector<std::size_t> missing;
277 for (std::size_t i = 0; i < M; ++i)
278 if (!covered[i]) missing.push_back(i);
279 if (!missing.empty()) {
280 nets.push_back(missing);
281 locals.push_back(std::vector<std::size_t>());
284 const std::size_t G = nets.size();
285 std::vector<int> owner(R, -1);
286 for (std::size_t g = 0; g < G; ++g)
287 for (std::size_t a = 0; a < locals[g].size(); ++a)
288 owner[locals[g][a]] =
static_cast<int>(g);
290 for (std::size_t it = 1; it <= maxiter; ++it) {
293 std::vector<T> Qk(M, zero);
294 for (std::size_t i = 0; i < M; ++i)
295 for (std::size_t s = 0; s < R; ++s) Qk[i] += r.
QN(i, s);
297 for (std::size_t g = 0; g < G; ++g) {
298 const std::vector<std::size_t>& S = nets[g];
299 const std::vector<std::size_t>& LC = locals[g];
300 if (LC.empty() || S.empty())
continue;
301 std::vector<bool> inS(M,
false);
302 for (std::size_t a = 0; a < S.size(); ++a) inS[S[a]] =
true;
303 std::vector<bool> isLocal(R,
false);
304 for (std::size_t a = 0; a < LC.size(); ++a) isLocal[LC[a]] =
true;
305 std::vector<bool> isForeign(R,
false);
306 for (std::size_t s = 0; s < R; ++s) {
307 if (isLocal[s])
continue;
308 for (std::size_t a = 0; a < S.size(); ++a)
309 if (L(S[a], s) > zero) {
315 std::vector<T> Zeff(LC.size(), zero);
316 for (std::size_t a = 0; a < LC.size(); ++a) {
317 const std::size_t c = LC[a];
320 for (std::size_t i = 0; i < M; ++i)
322 p += L(i, c) * T(one + Qk[i]) / T(one + L(i, c) * r.
XN[c] / N[c]);
323 Zeff[a] = T(Zv[c] + p);
326 std::vector<T> Uk(S.size(), zero);
328 for (std::size_t b = 0; b < S.size(); ++b) {
329 const std::size_t i = S[b];
331 for (std::size_t s = 0; s < R; ++s)
332 if (isForeign[s] && N[s] > zero)
333 u += L(i, s) * r.
XN[s] / T(one + L(i, s) * r.
XN[s] / N[s]);
334 Uk[b] = (u < cap) ? u : cap;
336 Matrix<T> Lsub(S.size(), LC.size(), zero);
337 std::vector<T> Nsub(LC.size(), zero);
338 for (std::size_t b = 0; b < S.size(); ++b)
339 for (std::size_t a = 0; a < LC.size(); ++a) Lsub(b, a) = L(S[b], LC[a]);
340 for (std::size_t a = 0; a < LC.size(); ++a) Nsub[a] = N[LC[a]];
342 const detail::SubnetSolution<T> sub =
343 detail::clust_subnet(Lsub, Nsub, Zeff, Uk, inner, tol, maxiter);
344 for (std::size_t a = 0; a < LC.size(); ++a) {
345 r.
XN[LC[a]] = sub.X[a];
346 for (std::size_t b = 0; b < S.size(); ++b) r.
QN(S[b], LC[a]) = sub.Q(b, a);
349 for (std::size_t a = 0; a < LC.size(); ++a) {
350 const std::size_t c = LC[a];
351 if (!(N[c] > zero))
continue;
352 for (std::size_t i = 0; i < M; ++i)
354 r.
QN(i, c) = r.
XN[c] * L(i, c) * T(one + Qk[i]) /
355 T(one + L(i, c) * r.
XN[c] / N[c]);
359 for (std::size_t s = 0; s < R; ++s)
361 for (std::size_t i = 0; i < M; ++i) r.
QN(i, s) = r.
XN[s] * L(i, s);
364 for (std::size_t i = 0; i < M; ++i)
365 for (std::size_t s = 0; s < R; ++s) {
375 for (std::size_t i = 0; i < M; ++i)
376 for (std::size_t s = 0; s < R; ++s) {
377 r.
UN(i, s) = r.
XN[s] * L(i, s);
378 r.
RN(i, s) = (N[s] == zero || r.
XN[s] == zero) ? zero : T(r.
QN(i, s) / r.
XN[s]);