5#ifndef LINE_API_MC_CTMC_TRANSIENT_H
6#define LINE_API_MC_CTMC_TRANSIENT_H
82template <
class T,
class F>
83void ode23(F f,
const T& t0,
const T& t1,
const std::vector<T>& y0,
double rtol,
double atol,
84 std::vector<T>& tout, std::vector<std::vector<T>>& yout) {
85 const std::size_t n = y0.size();
91 const T eps = std::numeric_limits<T>::epsilon();
92 const T span = t1 - t0;
93 if (!(span > zero))
throw InputError(
"ode23: the time interval must have positive length");
96 std::vector<T> y = y0, f1(n), f2(n), f3(n), f4(n), ytmp(n), ynew(n);
104 for (std::size_t i = 0; i < n; ++i) {
106 if (d < threshold) d = threshold;
107 const T v =
num_abs(T(f1[i] / d));
111 if (h * rh > one) h = one / rh;
120 if (h > hmax) h = hmax;
121 if (h < hmin) h = hmin;
127 bool nofailed =
true;
132 for (std::size_t i = 0; i < n; ++i)
135 for (std::size_t i = 0; i < n; ++i)
143 for (std::size_t i = 0; i < n; ++i) {
145 const T dn =
num_abs(T(ynew[i]));
147 if (d < threshold) d = threshold;
152 if (v > err) err = v;
156 if (!(err > rtolT))
break;
158 throw NumericError(
"ode23: step size underflow, the system is too stiff for ode23");
162 if (h < hmin) h = hmin;
207 double rtol = 1e-3,
double atol = 1e-6,
bool stiff =
false) {
209 "ctmc_transient requires transcendental arithmetic: the ode23 step controller "
210 "raises the error ratio to the power 1/3, and the result is an approximation of "
211 "pi0 exp(Qt) governed by a tolerance rather than an exact quantity");
212 const std::size_t n = Q.
rows();
213 if (Q.
cols() != n)
throw InputError(
"ctmc_transient: generator is not square");
214 if (pi0.size() != n)
throw InputError(
"ctmc_transient: pi0 has the wrong length");
217 std::vector<std::vector<T>> yv;
221 for (std::size_t i = 0; i < n; ++i)
222 for (std::size_t j = 0; j < n; ++j) QT(j, i) = Q(i, j);
227 [&Q, n](
const T&,
const std::vector<T>& y) {
229 for (std::size_t j = 0; j < n; ++j) {
231 for (std::size_t i = 0; i < n; ++i) s += y[i] * Q(i, j);
236 [&QT](
const T&,
const std::vector<T>&) {
return QT; }, t0, t1, pi0, oo);
241 [&Q, n](
const std::vector<T>& y, std::vector<T>& dy) {
242 for (std::size_t j = 0; j < n; ++j) {
244 for (std::size_t i = 0; i < n; ++i) s += y[i] * Q(i, j);
248 t0, t1, pi0, rtol, atol, tv, yv);
254 for (std::size_t k = 0; k < yv.size(); ++k)
255 for (std::size_t j = 0; j < n; ++j) r.
pi(k, j) = yv[k][j];
267 double atol = 1e-6) {
268 const std::size_t n = Q.
rows();
269 if (n == 0)
throw InputError(
"ctmc_transient: empty generator");
295 const std::vector<T>& grid);
299 const T& t0,
const T& t1,
const T& dt) {
301 throw InputError(
"ctmc_transient_on_grid: the timestep must be positive");
302 if (r.
t.empty())
return r;
307 for (
double x = d0; x <= d1 + 1e-12 * (d1 - d0); x += dd)
341 const std::vector<T>& grid) {
342 if (r.
t.empty() || grid.empty())
return r;
343 const std::size_t n = Q.
rows();
350 for (std::size_t g = 0; g < grid.size(); ++g) {
354 const std::size_t k1 = (k + 1 < r.
t.size()) ? k + 1 : k;
356 if (k1 == k || b <= a) {
357 for (std::size_t j = 0; j < n; ++j) out.
pi(g, j) = r.
pi(k, j);
364 double u = (x - a) / (b - a);
365 if (u < 0.0) u = 0.0;
366 if (u > 1.0) u = 1.0;
367 for (std::size_t j = 0; j < n; ++j)
NumericError(const std::string &what)
The exception types the port throws.
Dense matrix and non-owning view.
TransientResult< T > ctmc_transient_on_grid(const Matrix< T > &Q, const TransientResult< T > &r, const std::vector< T > &grid)
Resample an adaptive transient onto the uniform grid t0 : dt : t1.
TransientResult< T > ctmc_transient(const Matrix< T > &Q, const std::vector< T > &pi0, const T &t0, const T &t1, double rtol=1e-3, double atol=1e-6, bool stiff=false)
Transient distribution of a CTMC over a time interval, by integrating the forward equations d pi/dt =...
Conservation laws of a layered queueing network, enumerated from its structure.
OdeSolution< T > ode_rosenbrock4(const F &f, const J &jac, const T &t0, const T &t1, const std::vector< T > &y0, const OdeOptions< T > &opt)
Integrate y' = f(t,y) from t0 to t1 with an analytic Jacobian.
Number-type abstraction for the templated API port.
Adaptive stiff ODE integrator: a four-stage Rosenbrock method of order four with an embedded order-th...
T atol
absolute tolerance per component
T rtol
relative tolerance per component
Result of an integration.
std::vector< std::vector< T > > y
y[i] is the state at t[i]
std::vector< T > t
accepted time points, t[0] = t0
std::vector< T > t
accepted time points, the first being t0
Matrix< T > pi
one row per time point