80 const Eigen::MatrixBase<DerivedL>& L_LTDL_Q,
const Eigen::MatrixBase<DerivedD>& D_LTDL_Q,
81 const Eigen::Index& numCandidates = 2)
83 static_assert(DerivedA::ColsAtCompileTime == Eigen::Dynamic || DerivedA::ColsAtCompileTime == 1);
85 static_assert(DerivedD::ColsAtCompileTime == Eigen::Dynamic || DerivedD::ColsAtCompileTime == 1);
87 INS_ASSERT_USER_ERROR(a.rows() == D_LTDL_Q.rows(),
"Parameter 'a' and 'D_LTDL_Q' must have same dimension");
92 if (n == 1) {
return {}; }
93 double chi2 =
calcChi2(a, Q, L_LTDL_Q, D_LTDL_Q, numCandidates, 1.0);
97 typename DerivedL::PlainObject L = L_LTDL_Q.inverse();
98 typename DerivedD::PlainObject D = (1.0 / D_LTDL_Q.array()).matrix();
102 Eigen::VectorXd right = Eigen::VectorXd::Zero(n + 1);
104 Eigen::VectorXd left = Eigen::VectorXd::Zero(n + 1);
106 Eigen::VectorXd lef = Eigen::VectorXd::Zero(n);
107 Eigen::VectorXd end = Eigen::VectorXd::Zero(n);
108 Eigen::VectorXd dist = Eigen::VectorXd::Zero(n);
109 Eigen::VectorXd disall = Eigen::VectorXd::Zero(numCandidates);
110 Eigen::MatrixXd cands = Eigen::MatrixXd::Zero(n, numCandidates);
112 Eigen::Index imax = 0;
115 Eigen::Index ncan = 0;
117 Eigen::VectorXd dq = Eigen::VectorXd::Zero(n);
118 dq.head(n - 1) = D(seq(1, n - 1)).array() / D(seq(0, n - 2)).array();
119 dq(n - 1) = 1.0 / D(n - 1);
120 LOG_DATA(
"dq = {}", dq.transpose());
123 Eigen::Index iold = i;
125 auto BACKTS = [](
const Eigen::Index& n, Eigen::Index& i,
const auto& end,
auto& dist,
const auto& lef,
auto& left,
auto& ende) {
126 for (i++; i < n; i++)
128 if (dist(i) <= end(i))
131 left(i) = std::pow(dist(i) + lef(i), 2);
134 if (i == n - 1) { ende =
true; }
138 auto COLLECTs = [&chi2, &a]<
typename DerD>(
const Eigen::Index& n,
const Eigen::Index& maxcan,
const Eigen::MatrixBase<DerD>& D,
const auto& lef,
const auto& left,
const auto& right,
139 auto& dist,
auto& end, Eigen::Index& ncan,
auto& disall,
auto& cands,
double& tmax, Eigen::Index& imax) {
140 auto STOREs = [&n, &a](
const Eigen::Index& ican,
const Eigen::Index& ipos, Eigen::Index& imax,
const double& t,
double& tmax,
const auto& dist,
auto& cands,
auto& disall) {
141 cands(seq(0, n - 1), ipos) = dist(seq(0, n - 1)) + a;
144 LOG_DATA(
" disall = {}", disall.transpose());
147 for (Eigen::Index i = 0; i < ican; i++)
149 if (disall(i) > tmax)
157 double t = chi2 - (right(0) - left(0)) * D(0);
164 while (dist(0) <= end(0))
170 STOREs(ncan, ncan - 1, imax, t, tmax, dist, cands, disall);
174 STOREs(maxcan, imax, imax, t, tmax, dist, cands, disall);
176 t += (2 * (dist(0) + lef(0)) + 1) * D(0);
190 lef(i) += L(i + 1, i);
194 lef(i) = L(seq(i + 1, n - 1), i).dot(dist(seq(i + 1, n - 1)));
196 LOG_DATA(
" lef = {}", lef.transpose());
198 right(i) = (right(i + 1) - left(i + 1)) * dq(i);
199 LOG_DATA(
" right = {}", right.transpose());
200 auto reach = std::sqrt(right(i));
202 auto delta = a(i) - reach - lef(i);
204 dist(i) = std::ceil(delta) - a(i);
205 LOG_DATA(
" dist = {}", dist.transpose());
206 if (dist(i) > reach - lef(i))
208 BACKTS(n, i, end, dist, lef, left, ende);
212 end(i) = reach - lef(i) - 1;
213 LOG_DATA(
" end = {}", end.transpose());
214 left(i) = std::pow(dist(i) + lef(i), 2);
215 LOG_DATA(
" left = {}", left.transpose());
219 COLLECTs(n, numCandidates, D, lef, left, right, dist, end, ncan, disall, cands, tmax, imax);
220 BACKTS(n, i, end, dist, lef, left, ende);
229 return { cands.rightCols(ncan), disall.tail(ncan) };
244 const Eigen::MatrixBase<DerivedD>& D_LTDL_Q,
const Eigen::Index& numCandidates = 2)
246 static_assert(DerivedA::ColsAtCompileTime == Eigen::Dynamic || DerivedA::ColsAtCompileTime == 1);
248 static_assert(DerivedD::ColsAtCompileTime == Eigen::Dynamic || DerivedD::ColsAtCompileTime == 1);
250 INS_ASSERT_USER_ERROR(zh.rows() == D_LTDL_Q.rows(),
"Parameter 'zh' and 'D' must have same dimension");
255 if (n == 1) {
return {}; }
257 auto sgn = [](
auto x) {
258 int sgn = gcem::sgn(x);
259 return sgn ? sgn : 1;
262 Eigen::VectorXd dist = Eigen::VectorXd::Zero(n);
263 Eigen::VectorXd zb = Eigen::VectorXd::Zero(n);
264 Eigen::VectorXd z = Eigen::VectorXd::Zero(n);
265 Eigen::VectorXd step = Eigen::VectorXd::Zero(n);
266 Eigen::MatrixXd S = Eigen::MatrixXd::Zero(n, n);
268 Eigen::MatrixXd cands = Eigen::MatrixXd::Zero(n, numCandidates);
269 Eigen::VectorXd sqnorm = Eigen::VectorXd::Zero(numCandidates);
271 auto maxDist = std::numeric_limits<double>::infinity();
273 Eigen::Index count = 0;
275 zb(n - 1) = zh(n - 1);
276 z(n - 1) = std::round(zb(n - 1));
277 double y = zb(n - 1) - z(n - 1);
278 step(n - 1) = sgn(y);
279 auto imax = numCandidates - 1;
280 for (
size_t loop = 0; loop < 10000; loop++)
282 double newDist = dist(k) + std::pow(y, 2) / D_LTDL_Q(k);
283 if (newDist < maxDist)
289 S(k, seq(0, k)) = S(k + 1, seq(0, k)) + (z(k + 1) - zb(k + 1)) * L_LTDL_Q(k + 1, seq(0, k));
290 zb(k) = zh(k) + S(k, k);
291 z(k) = std::round(zb(k));
297 if (count < numCandidates)
299 if (count == 0 || newDist > sqnorm(imax)) { imax = count; }
300 cands.col(count) = z;
301 sqnorm(count) = newDist;
306 if (newDist < sqnorm(imax))
309 sqnorm(imax) = newDist;
310 sqnorm.maxCoeff(&imax);
312 maxDist = sqnorm(imax);
316 step(0) = -step(0) - sgn(step(0));
321 if (k == n - 1) {
break; }
326 step(k) = -step(k) - sgn(step(k));
335 return { cands.rightCols(count), sqnorm.tail(count) };