16 const std::vector<double> & y,
const unsigned int knots_num,
17 const unsigned int degree,
const unsigned int s,
const double lambda
21 throw std::invalid_argument(
"PSpline(): the length of y is zero.");
25 throw std::invalid_argument(
"PSpline(): knots_num is zero.");
29 throw std::invalid_argument(
"PSpline(): degree is zero.");
32 if(y.size() < knots_num) {
33 throw std::invalid_argument(
"PSpline(): knots_num is larger than length of y.");
37 throw std::invalid_argument(
"PSpline(): s must be 1, 2 or 3.");
41 throw std::invalid_argument(
"PSpline(): non-positive lambda value is given.");
44 Eigen::VectorXd yy = Eigen::VectorXd::Map(y.data(), y.size());
45 Eigen::VectorXd xx = Eigen::VectorXd::LinSpaced(yy.size(), 0, 1);
47 Eigen::VectorXd interior_knots = Eigen::VectorXd::LinSpaced(knots_num, 0, 1);
48 Eigen::VectorXd knots(knots_num + degree * 2);
50 for(
unsigned int i = 0; i < degree; i++) {
51 knots(i) = interior_knots(0);
52 knots(knots.size() - 1 - i) = interior_knots(knots_num - 1);
55 knots.block(degree, 0, knots_num, 1) = interior_knots;
59 Eigen::SparseMatrix<double> I, D, lambdaDTD, BTB;
61 I.resize(B.cols(), B.cols());
64 lambdaDTD = lambda * (D.transpose() * D);
65 BTB = B.transpose() * B;
67 Eigen::SimplicialCholesky< Eigen::SparseMatrix<double> > solver;
69 solver.compute(BTB + lambdaDTD);
71 if(solver.info() != Eigen::Success) {
72 throw std::runtime_error(
"PSpline(): solver calculation fails.");
75 Eigen::VectorXd coefficients = solver.solve(B.transpose() * yy);
76 std::vector<double> result(yy.size());
78 for(
int i = 0; i < xx.size(); i++) {
const Derived::PlainObject Diff(const Eigen::MatrixBase< Derived > &m0, const int n=1, const Dir dir=Dir::RowWise)
Calculates the n-th discrete difference along the given axis.
const std::vector< double > PSpline(const std::vector< double > &y, const unsigned int knots_num, const unsigned int degree, const unsigned int s, const double lambda)
Smoothes the input data using P-Splines (Penalized B-Splines).