@@ -127,7 +127,8 @@ class Kde1d
127127 const Eigen::VectorXd& weights);
128128 double calculate_infl (const size_t & n,
129129 const double & f0,
130- const double & b,
130+ const double & f1,
131+ const double & f2,
131132 const double & bandwidth,
132133 const double & s,
133134 const double & weight);
@@ -322,7 +323,7 @@ Kde1d::fit(const Eigen::VectorXd& x, const Eigen::VectorXd& weights)
322323
323324 // calculate effective degrees of freedom
324325 interp::InterpolationGrid infl_grid (
325- grid_points, fitted.col (1 ).cwiseMin (2 .0 ).cwiseMax (0 ), 0 );
326+ grid_points, fitted.col (1 ).cwiseMin (3 .0 ).cwiseMax (0 ), 0 );
326327 Eigen::VectorXd influences = infl_grid.interpolate (xx).array () * (1 - prob0_);
327328 edf_ = influences.sum () + (prob0_ > 0 );
328329
@@ -571,6 +572,7 @@ Kde1d::fit_lp(const Eigen::VectorXd& x,
571572 fft::KdeFFT kde_fft (
572573 x, bandwidth_, grid_points (0 ), grid_points (m - 1 ), weights);
573574 Eigen::VectorXd f0 = kde_fft.kde_drv (0 );
575+ Eigen::VectorXd f1 (f0.size ()), f2 (f0.size ());
574576
575577 Eigen::VectorXd wbin = Eigen::VectorXd::Ones (m);
576578 if (weights.size ()) {
@@ -592,11 +594,11 @@ Kde1d::fit_lp(const Eigen::VectorXd& x,
592594 return res;
593595
594596 // degree > 0
595- Eigen::VectorXd f1 = kde_fft.kde_drv (1 );
597+ f1 = kde_fft.kde_drv (1 );
596598 Eigen::VectorXd S = Eigen::VectorXd::Constant (f0.size (), bandwidth_);
597599 Eigen::VectorXd b = f1.cwiseQuotient (f0);
598600 if (degree_ == 2 ) {
599- Eigen::VectorXd f2 = kde_fft.kde_drv (2 );
601+ f2 = kde_fft.kde_drv (2 );
600602 // D/R is notation from Hjort and Jones' AoS paper
601603 Eigen::VectorXd D = f2.cwiseQuotient (f0) - b.cwiseProduct (b);
602604 Eigen::VectorXd R = 1 / (1.0 + bandwidth_ * bandwidth_ * D.array ()).sqrt ();
@@ -608,9 +610,8 @@ Kde1d::fit_lp(const Eigen::VectorXd& x,
608610 res.col (0 ) = res.col (0 ).array () * (-0.5 * b.array ().pow (2 ) * S.array ()).exp ();
609611
610612 for (size_t k = 0 ; k < m; k++) {
611- // TODO: weights
612613 res (k, 1 ) =
613- calculate_infl (x.size (), f0 (k), b (k), bandwidth_, S (k), wbin (k));
614+ calculate_infl (x.size (), f0 (k), f1 (k), f2 (k), bandwidth_, S (k), wbin (k));
614615 if (std::isnan (res (k, 0 )))
615616 res.row (k).setZero ();
616617 }
@@ -623,35 +624,36 @@ Kde1d::fit_lp(const Eigen::VectorXd& x,
623624inline double
624625Kde1d::calculate_infl (const size_t & n,
625626 const double & f0,
626- const double & b,
627+ const double & f1,
628+ const double & f2,
627629 const double & bandwidth,
628630 const double & s,
629631 const double & weight)
630632{
631633 double M_inverse00;
632- double bandwidth2 = std::pow (bandwidth, 2 );
633- double b2 = std::pow (b, 2 );
634+ double B = bandwidth * bandwidth;
634635 if (degree_ == 0 ) {
635636 M_inverse00 = 1 / f0;
636637 } else if (degree_ == 1 ) {
637638 Eigen::Matrix2d M;
638639 M (0 , 0 ) = f0;
639- M (0 , 1 ) = bandwidth2 * b * f0 ;
640+ M (0 , 1 ) = B * f1 ;
640641 M (1 , 0 ) = M (0 , 1 );
641- M (1 , 1 ) = f0 * bandwidth2 + f0 * bandwidth2 * bandwidth2 * b2 ;
642+ M (1 , 1 ) = f0 * B + B * f1 * f1 * B / f0 ;
642643 M_inverse00 = M.inverse ()(0 , 0 );
643644 } else {
644645 Eigen::Matrix3d M;
645646 M (0 , 0 ) = f0;
646- M (0 , 1 ) = f0 * b ;
647+ M (0 , 1 ) = B * f1 ;
647648 M (1 , 0 ) = M (0 , 1 );
648- M (1 , 1 ) = f0 * bandwidth2 + f0 * b2;
649- M (1 , 2 ) = 0.5 * f0 * (3.0 / s * b + b * b2);
649+ M (1 , 1 ) = B * f2 * B + B * f0;
650+ M (2 , 0 ) = M (1 , 1 ) / 2 ;
651+ M (0 , 2 ) = M (1 , 1 ) / 2 ;
652+ double s2 = B * f1 / f0;
653+ M (1 , 2 ) = f0 / 2 * (3 / s * s2 + std::pow (s2, 3 ));
650654 M (2 , 1 ) = M (1 , 2 );
651- M (2 , 2 ) = 0.25 * f0;
652- M (2 , 2 ) *= 3.0 / std::pow (s, 2 ) + 6.0 / s * b2 + b2 * b2;
653- M (0 , 2 ) = M (2 , 2 );
654- M (2 , 0 ) = M (2 , 2 );
655+ M (2 , 2 ) =
656+ f0 / 4 * (3 / (s * s) + 6 / s * std::pow (s2, 2 ) + std::pow (s2, 4 ));
655657 M_inverse00 = M.inverse ()(0 , 0 );
656658 }
657659
0 commit comments