sablib
Loading...
Searching...
No Matches
pspline.cpp
Go to the documentation of this file.
1
6
7#include "../misc/diff.h"
8#include "../misc/bspline.h"
9
10#include "pspline.h"
11
12namespace sablib {
13
14//
15// Implementation of PSpline() function
16//
17const std::vector<double> PSpline(
18 const std::vector<double> & y, const unsigned int knots_num,
19 const unsigned int degree, const unsigned int s, const double lambda
20)
21{
22 if(y.size() == 0) {
23 throw std::invalid_argument("PSpline(): the length of y is zero.");
24 }
25
26 if(knots_num == 0) {
27 throw std::invalid_argument("PSpline(): knots_num is zero.");
28 }
29
30 if(degree == 0) {
31 throw std::invalid_argument("PSpline(): degree is zero.");
32 }
33
34 if(y.size() < knots_num) {
35 throw std::invalid_argument("PSpline(): knots_num is larger than length of y.");
36 }
37
38 if(s == 0 || s > 3) {
39 throw std::invalid_argument("PSpline(): s must be 1, 2 or 3.");
40 }
41
42 if(lambda <= 0) {
43 throw std::invalid_argument("PSpline(): non-positive lambda value is given.");
44 }
45
46 Eigen::VectorXd yy = Eigen::VectorXd::Map(y.data(), y.size());
47 Eigen::VectorXd xx = Eigen::VectorXd::LinSpaced(yy.size(), 0, 1);
48
49 Eigen::VectorXd interior_knots = Eigen::VectorXd::LinSpaced(knots_num, 0, 1);
50 Eigen::VectorXd knots(knots_num + degree * 2);
51
52 for(unsigned int i = 0; i < degree; i++) {
53 knots(i) = interior_knots(0);
54 knots(knots.size() - 1 - i) = interior_knots(knots_num - 1);
55 }
56
57 knots.block(degree, 0, knots_num, 1) = interior_knots;
58
59 BSpline bs(degree, knots);
60 Eigen::SparseMatrix<double> B = bs.DesignMatrix(xx);
61 Eigen::SparseMatrix<double> I, D, lambdaDTD, BTB;
62
63 I.resize(B.cols(), B.cols());
64 I.setIdentity();
65 D = Diff(I, s);
66 lambdaDTD = lambda * (D.transpose() * D);
67 BTB = B.transpose() * B;
68
69 Eigen::SimplicialCholesky< Eigen::SparseMatrix<double> > solver;
70
71 solver.compute(BTB + lambdaDTD);
72
73 if(solver.info() != Eigen::Success) {
74 throw std::runtime_error("PSpline(): solver calculation fails.");
75 }
76
77 Eigen::VectorXd coefficients = solver.solve(B.transpose() * yy);
78 std::vector<double> result(yy.size());
79
80 for(int i = 0; i < xx.size(); i++) {
81 result[i] = bs.Interpolate(xx(i), coefficients);
82 }
83
84 return result;
85}
86
87}; // namespace sablib
B-Spline basis functions and interpolation.
A class for B-Spline operations including basis function calculation and interpolation.
Definition bspline.h:24
const Eigen::SparseMatrix< Scalar > DesignMatrix(const Eigen::VectorX< Scalar > &x) const
Constructs the design matrix (collocation matrix) for a given set of x-coordinates.
Definition bspline.h:267
const Scalar Interpolate(const Scalar x, const Eigen::VectorX< Scalar > &coefficients) const
Interpolates the value at a given x-coordinate using provided B-Spline coefficients.
Definition bspline.h:315
MATLAB-like diff() function.
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.
Definition diff.h:32
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).
Definition pspline.cpp:17
Smoothing using penalized Spline(P-Spline).