81 for (std::size_t c = 1; c <=
lqn.ncalls; ++c)
82 if (
lqn.calltype[c] == CallType::FWD) any_fwd =
true;
88 const std::size_t ncalls0 =
lqn.ncalls;
90 for (std::size_t cidx = 1; cidx <= ncalls0; ++cidx) {
91 if (
lqn.calltype[cidx] != CallType::SYNC)
continue;
92 const std::size_t aidx =
lqn.callpair_src[cidx];
93 const std::size_t tidx =
lqn.parent[aidx];
94 const T base_mean =
lqn.callproc_mean[cidx];
95 if (base_mean <= zero)
continue;
99 std::vector<std::size_t> frontier{
lqn.callpair_dst[cidx]};
100 std::vector<T> probs{one};
101 std::vector<std::size_t> visited;
102 auto seen = [](
const std::vector<std::size_t>& v, std::size_t x) {
103 for (std::size_t e : v)
104 if (e == x)
return true;
108 while (!frontier.empty()) {
109 const std::size_t eidx = frontier.front();
110 const T p_path = probs.front();
111 frontier.erase(frontier.begin());
112 probs.erase(probs.begin());
113 if (seen(visited, eidx))
continue;
114 visited.push_back(eidx);
116 for (std::size_t fcidx = 1; fcidx <= ncalls0; ++fcidx) {
117 if (
lqn.calltype[fcidx] != CallType::FWD)
continue;
118 if (
lqn.callpair_src[fcidx] != eidx)
continue;
119 const T fprob =
lqn.callproc_mean[fcidx];
120 const std::size_t tgt =
lqn.callpair_dst[fcidx];
121 const T pseudo_mean = T(base_mean * p_path * fprob);
125 if (pseudo_mean > zero &&
lqn.parent[tgt] != tidx) {
127 std::size_t mrow = 0;
128 for (std::size_t scan = 1; scan <=
lqn.ncalls; ++scan)
129 if (
lqn.calltype[scan] == CallType::SYNC &&
130 lqn.callpair_src[scan] == aidx &&
lqn.callpair_dst[scan] == tgt) {
137 lqn.callproc_mean[mrow] = T(
lqn.callproc_mean[mrow] + pseudo_mean);
139 const std::size_t ncall =
lqn.ncalls + 1;
141 const std::size_t target_tidx =
lqn.parent[tgt];
142 lqn.calltype.push_back(CallType::SYNC);
143 lqn.callpair_src.push_back(aidx);
144 lqn.callpair_dst.push_back(tgt);
145 lqn.callproc_mean.push_back(pseudo_mean);
146 lqn.callnames.push_back(
lqn.names[aidx] +
"=>" +
lqn.names[tgt]);
147 lqn.callhashnames.push_back(
lqn.hashnames[aidx] +
"=>" +
149 lqn.callsof[aidx].push_back(ncall);
150 lqn.iscaller.set(tidx, target_tidx);
151 lqn.iscaller.set(aidx, target_tidx);
152 lqn.iscaller.set(tidx, tgt);
153 lqn.iscaller.set(aidx, tgt);
154 lqn.issynccaller.set(tidx, target_tidx);
155 lqn.issynccaller.set(aidx, target_tidx);
156 lqn.issynccaller.set(tidx, tgt);
157 lqn.issynccaller.set(aidx, tgt);
158 lqn.graph.set(aidx, tgt, one);
159 lqn.taskgraph.set(tidx, target_tidx, one);
163 if (!seen(visited, tgt) && !seen(frontier, tgt)) {
164 frontier.push_back(tgt);
165 probs.push_back(T(p_path * fprob));
193 const T& y_ik,
const T& t_k, T& a, T& b, T& c, T& d) {
266 const std::vector<T>& y_aj) {
270 if (clientPhases.
rows() < 1 || clientPhases.
cols() < 5)
272 "lqn_overtake_markov: clientPhases must have five columns "
273 "[nSlices service y_ij y_ik t_k] and one row per client phase 0..maxPhaseA");
274 const std::size_t nStates = clientPhases.
rows();
275 const std::size_t maxPhaseA = nStates - 1;
276 if (y_aj.size() < nStates)
278 "lqn_overtake_markov: y_aj must hold the total call count and one entry per client "
283 std::vector<T> a(nStates, zero), b(nStates, zero), c(nStates, zero), d(nStates, zero);
284 for (std::size_t p = 0; p < nStates; ++p) {
285 const T prA = (p == maxPhaseA) ? prVisit : one;
286 detail::ln_set_rates(xj, prA, clientPhases(p, 0), clientPhases(p, 1), clientPhases(p, 2),
287 clientPhases(p, 3), clientPhases(p, 4), a[p], b[p], c[p], d[p]);
300 auto prod_of_b = [&](std::size_t k) {
return T(b[k] / (one - d[k])); };
301 Matrix<T> over(nStates, nStates, zero), next(nStates, nStates, zero);
302 for (std::size_t i0 = 0; i0 < nStates; ++i0) {
304 for (std::size_t r0 = 0; r0 < nStates; ++r0)
305 if (r0 != i0) temp = T(temp * prod_of_b(r0));
306 T product = T(one / (one - (b[i0] * temp + d[i0])));
309 over(i0, r0) = T(c[i0] * product);
310 next(i0, r0) = T(a[i0] * product);
311 r0 = (r0 == 0) ? maxPhaseA : r0 - 1;
312 product = T(product * prod_of_b(r0));
320 std::vector<T> nextProb(nStates, zero);
321 if (maxPhaseA >= 1) nextProb[maxPhaseA] = one;
324 for (std::size_t i = 1; i <= maxPhaseA; ++i) {
325 if (clientPhases(i, 2) == zero)
continue;
327 for (std::size_t r = 1; r <= maxPhaseA; ++r) acc = T(acc + nextProb[r] * over(i, r));
329 prOt = T(prOt + acc * (y_aj[0] / y_aj[i]));
T lqn_overtake_markov(const Matrix< T > &clientPhases, const T &prVisit, const T &xj, const std::vector< T > &y_aj)
Overtaking probability from the LQNS phased-server Markov chain.