12 std::vector<double>& tau_out, std::vector<double>& sigma2_out) {
15 const size_t n = timeseries.size();
19 for (
double x : timeseries)
21 mean /=
static_cast<double>(
n);
23 for (
double x : timeseries) {
27 v /=
static_cast<double>(
n);
28 tau_out.push_back(tau0);
29 sigma2_out.push_back(v);
34 size_t max_m = std::max<size_t>(2,
n / 4);
36 while (m <= max_m && n >= 3 * m) {
37 size_t num_triplets = (
n - 2 * m) / m;
41 std::vector<double> clusters;
42 clusters.reserve(num_triplets + 3);
43 for (
size_t i = 0; i < num_triplets + 2 && (i + 1) * m <=
n; ++i) {
45 for (
size_t k = 0; k < m; ++k)
46 sum += timeseries[i * m + k];
47 clusters.push_back(sum /
static_cast<double>(m));
49 if (clusters.size() < 3)
53 for (
size_t i = 0; i + 2 < clusters.size(); ++i) {
54 double d = clusters[i + 2] - 2.0 * clusters[i + 1] + clusters[i];
60 double sigma2 = 0.5 * (acc /
static_cast<double>(cnt));
61 tau_out.push_back(
static_cast<double>(m) * tau0);
62 sigma2_out.push_back(sigma2);
63 m = (m >= 2) ? m * 2 : m + 1;
68 const std::vector<double>& sigma2_arr) {
70 if (tau_arr.size() < 3 || sigma2_arr.size() != tau_arr.size()) {
74 const size_t n = tau_arr.size();
75 Eigen::MatrixXd X(
static_cast<Eigen::Index
>(
n), 4);
76 Eigen::VectorXd y(
static_cast<Eigen::Index
>(
n));
77 for (
size_t i = 0; i <
n; ++i) {
78 double t = tau_arr[i];
79 X(
static_cast<Eigen::Index
>(i), 0) = 1.0 / (2.0 * t);
80 X(
static_cast<Eigen::Index
>(i), 1) = 2.0 * std::log(2.0);
81 X(
static_cast<Eigen::Index
>(i), 2) = t / 6.0;
82 X(
static_cast<Eigen::Index
>(i), 3) = t * t / 20.0;
83 y(
static_cast<Eigen::Index
>(i)) = sigma2_arr[i];
86 Eigen::VectorXd beta = X.colPivHouseholderQr().solve(y);
87 c.
Q = std::sqrt(std::max(beta(0), 1e-12));
88 c.
B = std::sqrt(std::max(beta(1), 1e-12));
89 c.
K = std::sqrt(std::max(beta(2), 1e-12));
90 c.
R = std::sqrt(std::max(beta(3), 1e-12));
92 c.
tau_min = std::sqrt(3.0 * c.
Q * c.
Q / (c.
K * c.
K + 1e-20));
95 c.
tau_min = std::clamp(c.
tau_min, tau_arr.front(), tau_arr.back());
97 c.
sigma_min = std::sqrt(c.
Q * c.
Q / (2.0 * tm) + 2.0 * std::log(2.0) * c.
B * c.
B +
98 c.
K * c.
K * tm / 6.0 + c.
R * c.
R * tm * tm / 20.0);