215 if (params.empty())
return detail::wf_unit_params<T>();
216 if (params.size() == 1)
return params[0];
220 for (std::size_t k = 1; k < params.size(); ++k) {
221 const std::vector<T>& a2 = params[k].alpha;
223 const std::size_t n1 = acc.
alpha.size(), n2 = a2.size(), np = n1 * n2;
224 const T e1 = detail::wf_exit_prob(acc.
alpha), e2 = detail::wf_exit_prob(a2);
225 const std::vector<T> r1 = detail::wf_exit_rate(acc.
T_), r2 = detail::wf_exit_rate(T2);
227 std::vector<T> na(np + n1 + n2, zero);
228 for (std::size_t i = 0; i < n1; ++i)
229 for (std::size_t j = 0; j < n2; ++j) na[i * n2 + j] = T(acc.
alpha[i] * a2[j]);
230 for (std::size_t i = 0; i < n1; ++i) na[np + i] = T(e2 * acc.
alpha[i]);
231 for (std::size_t j = 0; j < n2; ++j) na[np + n1 + j] = T(e1 * a2[j]);
233 Matrix<T> nt(np + n1 + n2, np + n1 + n2, zero);
235 for (std::size_t i = 0; i < n1; ++i)
236 for (std::size_t j = 0; j < n2; ++j) {
237 const std::size_t r = i * n2 + j;
238 for (std::size_t ii = 0; ii < n1; ++ii) nt(r, ii * n2 + j) += acc.
T_(i, ii);
239 for (std::size_t jj = 0; jj < n2; ++jj) nt(r, i * n2 + jj) += T2(j, jj);
242 for (std::size_t i = 0; i < n1; ++i)
243 for (std::size_t j = 0; j < n2; ++j) nt(i * n2 + j, np + i) = r2[j];
245 for (std::size_t i = 0; i < n1; ++i)
246 for (std::size_t j = 0; j < n2; ++j) nt(i * n2 + j, np + n1 + j) = r1[i];
247 detail::wf_place(nt, acc.
T_, np, np);
248 detail::wf_place(nt, T2, np + n1, np + n1);
326 const std::vector<int>& serviceNodes,
327 const std::vector<int>& forkNodes,
328 const std::vector<int>& joinNodes,
329 const std::vector<int>& routerNodes,
331 detail::wf_check(linkMatrix);
334 std::map<int, ServiceParameters<T>> params = serviceParams;
335 const std::set<int> serviceSet(serviceNodes.begin(), serviceNodes.end());
338 const std::vector<std::vector<int>> sequences =
detect_sequences(m, serviceNodes);
339 if (!sequences.empty()) {
340 std::vector<std::size_t> drop;
341 for (std::size_t i = 0; i < m.
rows(); ++i) {
342 const int a = detail::wf_id(m, i, 0), b = detail::wf_id(m, i, 1);
343 if (!serviceSet.count(a) || !serviceSet.count(b))
continue;
344 for (std::size_t s = 0; s < sequences.size(); ++s)
345 for (std::size_t j = 0; j + 1 < sequences[s].size(); ++j)
346 if (sequences[s][j] == a && sequences[s][j + 1] == b) {
348 j = sequences[s].size();
351 m = detail::wf_remove_rows(m, drop);
352 for (std::size_t s = 0; s < sequences.size(); ++s) {
353 const std::vector<int>& seq = sequences[s];
354 if (seq.size() < 2)
continue;
355 detail::wf_replace_node(m, seq.back(), seq.front());
356 std::vector<ServiceParameters<T>> sp;
357 for (std::size_t j = 0; j < seq.size(); ++j) {
358 typename std::map<int, ServiceParameters<T>>::const_iterator it = params.find(seq[j]);
359 if (it != params.end()) sp.push_back(it->second);
362 for (std::size_t j = 1; j < seq.size(); ++j) params.erase(seq[j]);
367 const std::vector<std::vector<int>> parallels =
369 for (std::size_t p = 0; p < parallels.size(); ++p) {
370 const std::vector<int>& par = parallels[p];
371 if (par.size() < 2)
continue;
372 int forkNode = -1, joinNode = -1;
374 m = detail::wf_remove_rows(m, detail::wf_rows_involving(m, par));
375 detail::wf_replace_node(m, forkNode, par.front());
376 detail::wf_replace_node(m, joinNode, par.front());
377 std::vector<ServiceParameters<T>> sp;
378 for (std::size_t j = 0; j < par.size(); ++j) {
379 typename std::map<int, ServiceParameters<T>>::const_iterator it = params.find(par[j]);
380 if (it != params.end()) sp.push_back(it->second);
383 for (std::size_t j = 1; j < par.size(); ++j) params.erase(par[j]);
387 const std::vector<int> loops =
detect_loops(m, serviceNodes, routerNodes, joinNodes);
388 const std::set<int> routerSet(routerNodes.begin(), routerNodes.end());
389 for (std::size_t l = 0; l < loops.size(); ++l) {
390 const int loopNode = loops[l];
394 std::vector<int> routers;
395 for (std::size_t i = 0; i < m.
rows(); ++i) {
396 const int a = detail::wf_id(m, i, 0), b = detail::wf_id(m, i, 1);
397 if (!((a == loopNode && routerSet.count(b)) || (b == loopNode && routerSet.count(a))))
399 if (routerSet.count(a)) routers.push_back(a);
400 if (routerSet.count(b)) routers.push_back(b);
402 std::sort(routers.begin(), routers.end());
403 routers.erase(std::unique(routers.begin(), routers.end()), routers.end());
405 const std::set<int> rs(routers.begin(), routers.end());
406 std::vector<std::size_t> drop;
407 for (std::size_t i = 0; i < m.
rows(); ++i) {
408 const int a = detail::wf_id(m, i, 0), b = detail::wf_id(m, i, 1);
409 if ((a == loopNode && rs.count(b)) || (b == loopNode && rs.count(a)))
412 m = detail::wf_remove_rows(m, drop);
413 for (std::size_t r = 0; r < routers.size(); ++r)
414 detail::wf_replace_node(m, routers[r], loopNode);
415 for (std::size_t i = 0; i < m.
rows(); ++i)
416 if (detail::wf_id(m, i, 0) == loopNode) m(i, 2) = one;
418 typename std::map<int, ServiceParameters<T>>::iterator it = params.find(loopNode);
419 if (it != params.end()) it->second =
convolve_loop(it->second, loopProb);
423 const std::vector<BranchPattern<T>> branches =
detect_branches(m, serviceNodes, joinNodes);
424 for (std::size_t b = 0; b < branches.size(); ++b) {
427 m = detail::wf_remove_rows(m, detail::wf_rows_involving(m, br.
branchNodes));
430 std::vector<ServiceParameters<T>> sp;
431 for (std::size_t j = 0; j < br.
branchNodes.size(); ++j) {
432 typename std::map<int, ServiceParameters<T>>::const_iterator it =
434 if (it != params.end()) sp.push_back(it->second);