106 const std::function<T(
const T&)>& lst,
107 const std::vector<T>& p,
const std::vector<T>& mu,
108 const std::function<T(
const T&)>& dlst =
109 std::function<T(
const T&)>()) {
111 "qsys_tandem_ub_ciucu requires transcendental arithmetic");
116 if (x.empty())
throw InputError(
"qsys_tandem_ub_ciucu: x must hold at least one threshold");
117 if (!lst)
throw InputError(
"qsys_tandem_ub_ciucu: lst must be supplied");
118 if (p.empty() || p.size() != mu.size())
119 throw InputError(
"qsys_tandem_ub_ciucu: p and mu must have the same number of phases");
121 for (std::size_t i = 0; i < p.size(); ++i) {
123 throw InputError(
"qsys_tandem_ub_ciucu: the phase probabilities p must be nonnegative");
125 throw InputError(
"qsys_tandem_ub_ciucu: the service rates mu must be positive");
129 if (psum - one > tolp || one - psum > tolp)
130 throw InputError(
"qsys_tandem_ub_ciucu: the phase probabilities p must sum to one");
131 for (std::size_t k = 0; k < x.size(); ++k)
132 if (x[k] < zero)
throw InputError(
"qsys_tandem_ub_ciucu: the thresholds x must be nonnegative");
135 for (std::size_t i = 1; i < mu.size(); ++i)
136 if (mu[i] < mu1) mu1 = mu[i];
139 const auto mgfY = [&p, &mu](
const T& t) {
141 for (std::size_t i = 0; i < p.size(); ++i) acc = acc + p[i] * mu[i] / (mu[i] - t);
144 const auto residual = [&mgfY, &lst, &one](
const T& t) {
return T(mgfY(t) * lst(t) - one); };
148 const T hi = mu1 * shrink;
149 if (residual(hi) <= zero)
150 throw InputError(
"qsys_tandem_ub_ciucu: no positive root of E[e^{theta(Y-X)}]=1 below "
151 "min(mu): the tandem is unstable or the service is not the lighter tail");
156 while (residual(lo) >= zero && lo > lomin) lo = lo / ten;
157 if (residual(lo) >= zero)
160 throw InputError(
"qsys_tandem_ub_ciucu: the tandem is unstable, E[X] <= E[Y]: "
161 "theta = 0 is the only root of E[e^{theta(Y-X)}]=1");
165 const T theta = rr.
root;
173 if (h > theta) h = theta / two;
174 const T d1 = (lst(T(theta - h)) - lst(T(theta + h))) / (two * h);
175 const T d2 = (lst(T(theta - h / two)) - lst(T(theta + h / two))) / h;
179 const T EexpZ = mgfY(theta);
182 T sumPOverMuMinusTheta = zero;
183 for (std::size_t i = 0; i < p.size(); ++i) {
184 const T dm = mu[i] - theta;
185 EZexp = EZexp + p[i] * mu[i] / (dm * dm);
186 EY = EY + p[i] / mu[i];
187 sumPOverMuMinusTheta = sumPOverMuMinusTheta + p[i] / dm;
190 const T C = theta * sumPOverMuMinusTheta / EZexp;
191 const T EUeV = EY - alpha * EexpZ;
192 const T EVeV = EZexp / EexpZ - alpha * EexpZ;
193 T D = -C * EUeV / EVeV;
194 if (!(D > zero)) D = zero;
195 const T B = D > zero ? T((C + D) / (mu1 - theta) - theta / mu1)
196 : T(C * (one / mu1 - alpha * EexpZ));
205 r.
analyzer =
"qsys_tandem_ub_ciucu";
206 r.
S.reserve(x.size());
207 r.
W.reserve(x.size());
208 for (std::size_t k = 0; k < x.size(); ++k) {
210 const T et = detail::num_exp(T(-theta * x[k]));
211 for (std::size_t i = 0; i < p.size(); ++i) {
213 const T dm = m - theta;
214 const T em = detail::num_exp(T(-m * x[k]));
215 acc = acc + p[i] * (em + m / dm * (A + B) * (et - em) +
216 m / (dm * dm) * (C + D) * ((dm * x[k] - one) * et + em));
218 r.
S.push_back(acc < one ? acc : one);
221 const T beta = lst(mu1);
222 for (std::size_t k = 0; k < x.size(); ++k) {
223 const T et = detail::num_exp(T(-theta * x[k]));
226 val = (one - two * theta * theta / (mu1 * (mu1 + theta)) +
227 theta * (mu1 - theta) / (mu1 + theta) * x[k]) * et +
228 beta * (theta * mu1 * alpha / (two * (mu1 - theta)) - theta / (two * mu1)) *
229 detail::num_exp(T(-mu1 * x[k]));
231 val = (one - two * theta / mu1 +
232 two * theta * theta * (two - alpha * mu1) /
233 ((mu1 + theta) * (mu1 + theta) * (one - alpha * mu1)) +
234 theta * theta * (mu1 - theta) /
235 (mu1 * (mu1 + theta) * (one - alpha * mu1)) * x[k]) * et;
237 r.
W.push_back(val < one ? val : one);
241 for (std::size_t k = 0; k < x.size(); ++k)
TandemUbResult< T > qsys_tandem_ub_ciucu(const std::vector< T > &x, const std::function< T(const T &)> &lst, const std::vector< T > &p, const std::vector< T > &mu, const std::function< T(const T &)> &dlst=std::function< T(const T &)>())
Tail bounds for a GI/Hn/1 -> .
RootResult< T > root_brent(F f, const T &a0, const T &b0, const T &tol, unsigned maxiter=200)
Brent's method on a bracket with a sign change.