37 static inline double evaluate(
size_t deg,
double xi) {
38 if(deg == 0)
return 1.0;
39 if(deg == 1)
return xi;
40 double Hn_2 = 1.0, Hn_1 = xi, Hn = 0.0;
41 for(
size_t n = 2; n <= deg; ++n) {
42 Hn = xi * Hn_1 - (n - 1) * Hn_2;
51 for(
size_t i = 2; i <= deg; ++i) norm *= i;
56 Eigen::MatrixXd J = Eigen::MatrixXd::Zero(numPoints, numPoints);
57 for(
int i = 0; i < numPoints - 1; ++i) {
58 double beta = std::sqrt(i + 1.0);
70 static inline double mapToPhysical(
double xi,
double mean,
double stdDev) {
71 return mean + stdDev * xi;
76 return (x - mean) / stdDev;
95 static inline double evaluate(
size_t deg,
double xi) {
96 if(deg == 0)
return 1.0;
97 if(deg == 1)
return xi;
98 double Pn_2 = 1.0, Pn_1 = xi, Pn = 0.0;
99 for(
size_t n = 2; n <= deg; ++n) {
100 Pn = ((2 * n - 1) * xi * Pn_1 - (n - 1) * Pn_2) / n;
108 return 1.0 / (2.0 * deg + 1.0);
112 Eigen::MatrixXd J = Eigen::MatrixXd::Zero(numPoints, numPoints);
113 for(
int i = 0; i < numPoints - 1; ++i) {
114 double beta = std::sqrt((i + 1.0) * (i + 1.0) / ((2 * i + 1.0) * (2 * i + 3.0)));
126 static inline double mapToPhysical(
double xi,
double lowerBound,
double upperBound) {
127 return lowerBound + (upperBound - lowerBound) * (xi + 1.0) / 2.0;
131 static inline double mapToCanonical(
double x,
double lowerBound,
double upperBound) {
132 return 2.0 * (x - lowerBound) / (upperBound - lowerBound) - 1.0;
150 static inline double evaluate(
size_t deg,
double xi) {
151 if(deg == 0)
return 1.0;
152 if(deg == 1)
return xi;
153 double Tn_2 = 1.0, Tn_1 = xi, Tn = 0.0;
154 for(
size_t n = 2; n <= deg; ++n) {
155 Tn = 2.0 * xi * Tn_1 - Tn_2;
163 constexpr double pi = 3.14159265358979323846;
164 if(deg == 0)
return pi;
169 Eigen::MatrixXd J = Eigen::MatrixXd::Zero(numPoints, numPoints);
171 J(0, 1) = 1.0 / std::sqrt(2.0);
172 J(1, 0) = 1.0 / std::sqrt(2.0);
173 for(
int i = 1; i < numPoints - 1; ++i) {
181 static inline double mapToPhysical(
double xi,
double lowerBound,
double upperBound) {
182 return lowerBound + (upperBound - lowerBound) * (xi + 1.0) / 2.0;
185 static inline double mapToCanonical(
double x,
double lowerBound,
double upperBound) {
186 return 2.0 * (x - lowerBound) / (upperBound - lowerBound) - 1.0;
204 static inline double evaluate(
size_t deg,
double xi) {
205 if(deg == 0)
return 1.0;
206 if(deg == 1)
return 1.0 - xi;
207 double Ln_2 = 1.0, Ln_1 = 1.0 - xi, Ln = 0.0;
208 for(
size_t n = 1; n < deg; ++n) {
209 Ln = ((2.0 * n + 1.0 - xi) * Ln_1 - n * Ln_2) / (n + 1.0);
221 Eigen::MatrixXd J = Eigen::MatrixXd::Zero(numPoints, numPoints);
222 for(
int i = 0; i < numPoints; ++i) {
223 J(i, i) = 2.0 * i + 1.0;
224 if(i < numPoints - 1) {
225 double off_diag =
static_cast<double>(i + 1);
226 J(i, i + 1) = off_diag;
227 J(i + 1, i) = off_diag;
234 static inline double mapToPhysical(
double xi,
double location,
double scale) {
235 return location + scale * xi;
240 return (x - location) / scale;
300template <
typename Basis>
318 const int dim =
X.cols();
322 #pragma omp parallel for schedule(static)
326 for(
int d = 0;
d < dim; ++
d) {
337 template <
typename MatrixType>
339 typename MatrixType::Index
rows =
mat.rows();
340 typename MatrixType::Index
cols =
mat.cols();
341 out.write(
reinterpret_cast<const char*
>(&
rows),
sizeof(
rows));
342 out.write(
reinterpret_cast<const char*
>(&
cols),
sizeof(
cols));
343 out.write(
reinterpret_cast<const char*
>(
mat.data()),
rows *
cols *
sizeof(
typename MatrixType::Scalar));
346 template <
typename MatrixType>
348 typename MatrixType::Index
rows = 0,
cols = 0;
349 in.read(
reinterpret_cast<char*
>(&
rows),
sizeof(
rows));
350 in.read(
reinterpret_cast<char*
>(&
cols),
sizeof(
cols));
352 in.read(
reinterpret_cast<char*
>(
mat.data()),
rows *
cols *
sizeof(
typename MatrixType::Scalar));
359 void set(
size_t dimension,
size_t totalDegree,
const Eigen::VectorXd&
p1,
const Eigen::VectorXd&
p2,
double q = 1.0) {
360 if(
p1.size() != dimension ||
p2.size() != dimension) {
361 throw std::invalid_argument(
"Parameter vectors must match dimension.");
369 void fit(
const Eigen::Ref<const Eigen::MatrixXd>&
samples,
const Eigen::Ref<const Eigen::VectorXd>&
values) {
370 if(
samples.rows() !=
values.size())
throw std::invalid_argument(
"Dimension mismatch.");
377 Eigen::ColPivHouseholderQR<Eigen::MatrixXd>
qr(
A);
408 Eigen::VectorXd
sobolIndices = Eigen::VectorXd::Zero(dim);
416 for(
size_t d = 0;
d < dim; ++
d) {
425 for(
size_t d = 0;
d < dim; ++
d) {
434 Eigen::VectorXd
predictBatch(
const Eigen::Ref<const Eigen::MatrixXd>&
X)
const {
439 std::pair<double, double>
predict(
const Eigen::Ref<const Eigen::VectorXd> &
x)
const {
450 std::pair<double, double>
predictWithObs(
const Eigen::Ref<const Eigen::VectorXd> &
x,
const double &
yObs)
const {
452 throw std::runtime_error(
"predictWithObs requires a fitted model.");
458 if(std::abs(
denom) <= std::numeric_limits<double>::epsilon()) {
459 throw std::runtime_error(
"Rank-one update is singular.");
477 if(
i >= (
size_t)
xObs_.rows()) {
478 throw std::out_of_range(
"LOO index out of range.");
481 throw std::runtime_error(
"LOO prediction requires a fitted normal matrix inverse.");
484 Eigen::VectorXd
x =
xObs_.row(
i).transpose();
493 if(std::abs(
denom) <= std::numeric_limits<double>::epsilon()) {
494 throw std::runtime_error(
"LOO rank-one update is singular.");
511 throw std::runtime_error(
"Polynomial basis is not initialized.");
514 throw std::invalid_argument(
"Input vector size does not match the polynomial dimension.");
520 for(
size_t d = 0;
d < (
size_t)
x.size(); ++
d) {
522 double xi = Basis::mapToCanonical(
x(
d),
p1_[
d],
p2_[
d]);
533 throw std::runtime_error(
"Failed to open file for writing: " +
filename);
540 out.write(
reinterpret_cast<const char*
>(
p1_.data()),
p_size *
sizeof(
double));
541 out.write(
reinterpret_cast<const char*
>(
p2_.data()),
p_size *
sizeof(
double));
551 size_t dim =
idx.size();
552 out.write(
reinterpret_cast<const char*
>(&dim),
sizeof(dim));
553 out.write(
reinterpret_cast<const char*
>(
idx.data()), dim *
sizeof(
size_t));
568 throw std::runtime_error(
"Failed to open file for reading: " +
filename);
577 in.read(
reinterpret_cast<char*
>(
p1_.data()),
p_size *
sizeof(
double));
578 in.read(
reinterpret_cast<char*
>(
p2_.data()),
p_size *
sizeof(
double));
592 in.read(
reinterpret_cast<char*
>(&dim),
sizeof(dim));
611 if(
multiIndex_.
size() == 0)
throw std::runtime_error(
"Basis not set.");
621 for(
size_t d = 0;
d < dim; ++
d) {
632 for(
size_t d = 0;
d < dim; ++
d) {
638 for(
size_t d = 0;
d < dim; ++
d) {
std::size_t size() const
Definition poly.h:252
void print() const
Definition poly.cpp:20
const Index & operator[](std::size_t i) const
Definition poly.h:255
std::vector< size_t > Index
Definition poly.h:246
std::vector< Index > indices
Multi-index set matrix (each row corresponds to degree exponents vector).
Definition poly.h:247
void set(size_t dimension, size_t totalDegree, double q=1.0)
Definition poly.cpp:3
void generateRecursive(Index ¤t, int pos, size_t remaining, double currentQSum, double maxQSum, double q)
Definition poly.cpp:32
Implements multi-dimensional Polynomial Chaos Expansion (PCE) for spectral surrogate modeling.
Definition poly.h:301
void readEigenMatrix(std::ifstream &in, MatrixType &mat)
Definition poly.h:347
Eigen::VectorXd predictBatch(const Eigen::Ref< const Eigen::MatrixXd > &X) const
Definition poly.h:434
double residualVariance_
Running residual variance.
Definition poly.h:308
void fit(const Eigen::Ref< const Eigen::MatrixXd > &samples, const Eigen::Ref< const Eigen::VectorXd > &values)
Definition poly.h:369
Eigen::VectorXd yObs_
Training target response values.
Definition poly.h:307
size_t getNumBasisFunctions() const
Definition poly.h:606
void project(const std::function< double(const Eigen::VectorXd &)> &model, int pointsPerDim)
Definition poly.h:610
std::pair< double, double > predictLOO(const size_t &i) const
Definition poly.h:476
Eigen::MatrixXd normalMatrixInverse_
Precomputed inverse normal matrix (A^T A)^-1.
Definition poly.h:305
Eigen::VectorXd p1_
Mapping boundary lower limits/means.
Definition poly.h:311
void save(const std::string &filename) const
Definition poly.h:530
MultiIndex multiIndex_
Multi-index set defining the active polynomial terms.
Definition poly.h:303
double getAnalyticalVariance() const
Definition poly.h:393
Eigen::VectorXd computeBasisRow(const Eigen::Ref< const Eigen::VectorXd > &x) const
Definition poly.h:509
Eigen::VectorXd p2_
Mapping boundary upper limits/std devs.
Definition poly.h:312
Eigen::MatrixXd xObs_
Training input data in canonical space.
Definition poly.h:306
void load(const std::string &filename)
Definition poly.h:565
PolynomialExpansion()=default
Eigen::MatrixXd computeDesignMatrix(const Eigen::Ref< const Eigen::MatrixXd > &X) const
Definition poly.h:315
Eigen::VectorXd getSobolMainIndices() const
Definition poly.h:405
void set(size_t dimension, size_t totalDegree, const Eigen::VectorXd &p1, const Eigen::VectorXd &p2, double q=1.0)
Definition poly.h:359
double getAnalyticalMean() const
Definition poly.h:388
Eigen::VectorXd coefficients_
Estimated expansion coefficients vector.
Definition poly.h:304
std::pair< double, double > predictWithObs(const Eigen::Ref< const Eigen::VectorXd > &x, const double &yObs) const
Definition poly.h:450
void writeEigenMatrix(std::ofstream &out, const MatrixType &mat) const
Definition poly.h:338
std::pair< double, double > predict(const Eigen::Ref< const Eigen::VectorXd > &x) const
Definition poly.h:439
Multi-dimensional tensor product quadrature integrator.
Definition integrator.h:108
Definition classifier.h:17
Chebyshev orthogonal polynomial basis.
Definition poly.h:149
static double mapToPhysical(double xi, double lowerBound, double upperBound)
Definition poly.h:181
static double evaluate(size_t deg, double xi)
Definition poly.h:150
static double normSquared(size_t deg)
Definition poly.h:162
static double mapToCanonical(double x, double lowerBound, double upperBound)
Definition poly.h:185
static Eigen::MatrixXd getJacobiMatrix(int numPoints)
Definition poly.h:168
Hermite orthogonal polynomial basis.
Definition poly.h:36
static double mapToCanonical(double x, double mean, double stdDev)
Definition poly.h:75
static Eigen::MatrixXd getJacobiMatrix(int numPoints)
Definition poly.h:55
static double normSquared(size_t deg)
Definition poly.h:49
static double evaluate(size_t deg, double xi)
Definition poly.h:37
static double mapToPhysical(double xi, double mean, double stdDev)
Definition poly.h:70
static double getPDFWeight()
Definition poly.h:65
Laguerre orthogonal polynomial basis.
Definition poly.h:203
static double mapToCanonical(double x, double location, double scale)
Definition poly.h:239
static Eigen::MatrixXd getJacobiMatrix(int numPoints)
Definition poly.h:220
static double normSquared(size_t deg)
Definition poly.h:216
static double mapToPhysical(double xi, double location, double scale)
Definition poly.h:234
static double evaluate(size_t deg, double xi)
Definition poly.h:204
Legendre orthogonal polynomial basis.
Definition poly.h:94
static double getPDFWeight()
Definition poly.h:121
static double evaluate(size_t deg, double xi)
Definition poly.h:95
static double normSquared(size_t deg)
Definition poly.h:107
static Eigen::MatrixXd getJacobiMatrix(int numPoints)
Definition poly.h:111
static double mapToCanonical(double x, double lowerBound, double upperBound)
Definition poly.h:131
static double mapToPhysical(double xi, double lowerBound, double upperBound)
Definition poly.h:126