Janus 2.0.0
High-performance C++20 dual-mode numerical framework
Loading...
Searching...
No Matches
PolynomialChaos.hpp
Go to the documentation of this file.
1#pragma once
7
13#include <Eigen/SVD>
14#include <algorithm>
15#include <cmath>
16#include <numeric>
17#include <string>
18#include <vector>
19
20namespace janus {
21
31
39
52
60
68
75inline PolynomialChaosDimension jacobi_dimension(double alpha, double beta) {
77}
78
87
95
100 std::vector<int> multi_index;
101 double squared_norm = 1.0;
102};
103
104namespace detail {
105
106inline void validate_degree(int degree, const std::string &context) {
107 if (degree < 0) {
108 throw InvalidArgument(context + ": degree must be >= 0");
109 }
110}
111
112inline void validate_dimension(const PolynomialChaosDimension &dimension,
113 const std::string &context) {
114 switch (dimension.family) {
117 return;
119 if (dimension.alpha <= -1.0 || dimension.beta <= -1.0) {
120 throw InvalidArgument(context + ": Jacobi parameters must satisfy alpha > -1 and "
121 "beta > -1");
122 }
123 return;
125 if (dimension.alpha <= -1.0) {
126 throw InvalidArgument(context + ": Laguerre parameter must satisfy alpha > -1");
127 }
128 return;
129 }
130}
131
132template <JanusScalar Scalar> Scalar raw_hermite_polynomial(int degree, const Scalar &x) {
133 validate_degree(degree, "raw_hermite_polynomial");
134
135 if (degree == 0) {
136 return Scalar(1.0);
137 }
138 if (degree == 1) {
139 return x;
140 }
141
142 Scalar h_nm1 = Scalar(1.0);
143 Scalar h_n = x;
144 for (int n = 1; n < degree; ++n) {
145 Scalar h_np1 = x * h_n - static_cast<double>(n) * h_nm1;
146 h_nm1 = h_n;
147 h_n = h_np1;
148 }
149 return h_n;
150}
151
152template <JanusScalar Scalar> Scalar raw_legendre_polynomial(int degree, const Scalar &x) {
153 validate_degree(degree, "raw_legendre_polynomial");
154
155 if constexpr (std::floating_point<Scalar>) {
156 return legendre_poly(degree, x).first;
157 } else {
158 if (degree == 0) {
159 return Scalar(1.0);
160 }
161 if (degree == 1) {
162 return x;
163 }
164
165 Scalar p_nm1 = Scalar(1.0);
166 Scalar p_n = x;
167 for (int n = 1; n < degree; ++n) {
168 const double nn = static_cast<double>(n);
169 Scalar p_np1 = ((2.0 * nn + 1.0) * x * p_n - nn * p_nm1) / (nn + 1.0);
170 p_nm1 = p_n;
171 p_n = p_np1;
172 }
173 return p_n;
174 }
175}
176
177template <JanusScalar Scalar>
178Scalar raw_jacobi_polynomial(int degree, const Scalar &x, double alpha, double beta) {
179 validate_degree(degree, "raw_jacobi_polynomial");
180 validate_dimension(jacobi_dimension(alpha, beta), "raw_jacobi_polynomial");
181
182 if (degree == 0) {
183 return Scalar(1.0);
184 }
185 if (degree == 1) {
186 return 0.5 * ((alpha - beta) + (alpha + beta + 2.0) * x);
187 }
188
189 Scalar p_nm1 = Scalar(1.0);
190 Scalar p_n = 0.5 * ((alpha - beta) + (alpha + beta + 2.0) * x);
191
192 for (int n = 1; n < degree; ++n) {
193 const double nn = static_cast<double>(n);
194 const double two_n_ab = 2.0 * nn + alpha + beta;
195 const double a_n = 2.0 * (nn + 1.0) * (nn + alpha + beta + 1.0) * two_n_ab;
196 const Scalar b_n =
197 (two_n_ab + 1.0) * (two_n_ab * (two_n_ab + 2.0) * x + alpha * alpha - beta * beta);
198 const double c_n = 2.0 * (nn + alpha) * (nn + beta) * (two_n_ab + 2.0);
199 Scalar p_np1 = (b_n * p_n - c_n * p_nm1) / a_n;
200 p_nm1 = p_n;
201 p_n = p_np1;
202 }
203
204 return p_n;
205}
206
207template <JanusScalar Scalar>
208Scalar raw_laguerre_polynomial(int degree, const Scalar &x, double alpha) {
209 validate_degree(degree, "raw_laguerre_polynomial");
210 validate_dimension(laguerre_dimension(alpha), "raw_laguerre_polynomial");
211
212 if (degree == 0) {
213 return Scalar(1.0);
214 }
215 if (degree == 1) {
216 return Scalar(1.0 + alpha) - x;
217 }
218
219 Scalar l_nm1 = Scalar(1.0);
220 Scalar l_n = Scalar(1.0 + alpha) - x;
221
222 for (int n = 1; n < degree; ++n) {
223 const double nn = static_cast<double>(n);
224 Scalar l_np1 = ((2.0 * nn + 1.0 + alpha - x) * l_n - (nn + alpha) * l_nm1) / (nn + 1.0);
225 l_nm1 = l_n;
226 l_n = l_np1;
227 }
228
229 return l_n;
230}
231
232inline double squared_norm_raw(const PolynomialChaosDimension &dimension, int degree) {
233 validate_degree(degree, "squared_norm_raw");
234 validate_dimension(dimension, "squared_norm_raw");
235
236 switch (dimension.family) {
238 return std::exp(std::lgamma(static_cast<double>(degree) + 1.0));
239
241 return 2.0 / (2.0 * static_cast<double>(degree) + 1.0);
242
244 const double n = static_cast<double>(degree);
245 const double alpha = dimension.alpha;
246 const double beta = dimension.beta;
247 const double log_raw = (alpha + beta + 1.0) * std::log(2.0) -
248 std::log(2.0 * n + alpha + beta + 1.0) +
249 std::lgamma(n + alpha + 1.0) + std::lgamma(n + beta + 1.0) -
250 std::lgamma(n + 1.0) - std::lgamma(n + alpha + beta + 1.0);
251 return std::exp(log_raw);
252 }
253
255 return std::exp(std::lgamma(static_cast<double>(degree) + dimension.alpha + 1.0) -
256 std::lgamma(static_cast<double>(degree) + 1.0));
257 }
258
259 throw InvalidArgument("squared_norm_raw: unsupported family");
260}
261
262inline double squared_norm_probability(const PolynomialChaosDimension &dimension, int degree) {
263 if (dimension.family == PolynomialChaosFamily::Hermite) {
264 return squared_norm_raw(dimension, degree);
265 }
266 return squared_norm_raw(dimension, degree) / squared_norm_raw(dimension, 0);
267}
268
269inline bool multi_index_less(const std::vector<int> &lhs, const std::vector<int> &rhs) {
270 const int lhs_sum = std::accumulate(lhs.begin(), lhs.end(), 0);
271 const int rhs_sum = std::accumulate(rhs.begin(), rhs.end(), 0);
272 if (lhs_sum != rhs_sum) {
273 return lhs_sum < rhs_sum;
274 }
275 return lhs < rhs;
276}
277
278inline void total_order_recursive(int dim, int order, int axis, std::vector<int> &current,
279 std::vector<std::vector<int>> &indices) {
280 if (axis == dim) {
281 indices.push_back(current);
282 return;
283 }
284
285 const int used = std::accumulate(current.begin(), current.begin() + axis, 0);
286 const int remaining = order - used;
287 for (int degree = 0; degree <= remaining; ++degree) {
288 current[axis] = degree;
289 total_order_recursive(dim, order, axis + 1, current, indices);
290 }
291}
292
293inline void tensor_product_recursive(int dim, int order, int axis, std::vector<int> &current,
294 std::vector<std::vector<int>> &indices) {
295 if (axis == dim) {
296 indices.push_back(current);
297 return;
298 }
299
300 for (int degree = 0; degree <= order; ++degree) {
301 current[axis] = degree;
302 tensor_product_recursive(dim, order, axis + 1, current, indices);
303 }
304}
305
306inline std::vector<std::vector<int>> generate_multi_indices(int dim, int order,
307 PolynomialChaosTruncation truncation) {
308 std::vector<std::vector<int>> indices;
309 std::vector<int> current(static_cast<std::size_t>(dim), 0);
310
311 switch (truncation) {
313 total_order_recursive(dim, order, 0, current, indices);
314 break;
316 tensor_product_recursive(dim, order, 0, current, indices);
317 break;
318 }
319
320 std::sort(indices.begin(), indices.end(), multi_index_less);
321 return indices;
322}
323
324template <JanusScalar Scalar>
326 const std::string &context) {
327 if (values.rows() != op.cols()) {
328 throw InvalidArgument(context + ": sample value size must match the number of rows in the "
329 "design matrix");
330 }
331
332 JanusVector<Scalar> out(op.rows());
333 for (Eigen::Index i = 0; i < op.rows(); ++i) {
334 Scalar accum = Scalar(0.0);
335 for (Eigen::Index j = 0; j < op.cols(); ++j) {
336 accum += op(i, j) * values(j);
337 }
338 out(i) = accum;
339 }
340 return out;
341}
342
343template <JanusScalar Scalar>
345 const std::string &context) {
346 if (values.rows() != op.cols()) {
347 throw InvalidArgument(context + ": sample value rows must match the number of rows in the "
348 "design matrix");
349 }
350
351 JanusMatrix<Scalar> out(op.rows(), values.cols());
352 for (Eigen::Index i = 0; i < op.rows(); ++i) {
353 for (Eigen::Index col = 0; col < values.cols(); ++col) {
354 Scalar accum = Scalar(0.0);
355 for (Eigen::Index j = 0; j < op.cols(); ++j) {
356 accum += op(i, j) * values(j, col);
357 }
358 out(i, col) = accum;
359 }
360 }
361 return out;
362}
363
364inline void validate_samples(const NumericMatrix &samples, int dimension,
365 const std::string &context) {
366 if (samples.rows() == 0) {
367 throw InvalidArgument(context + ": sample matrix must contain at least one sample");
368 }
369 if (samples.cols() != dimension) {
370 throw InvalidArgument(context + ": sample matrix column count must match the PCE "
371 "dimension");
372 }
373}
374
375inline NumericMatrix regression_operator(const NumericMatrix &design_matrix, double ridge,
376 const std::string &context) {
377 if (design_matrix.rows() < design_matrix.cols()) {
378 throw InvalidArgument(context + ": need at least as many samples as basis terms for "
379 "regression");
380 }
381 if (ridge < 0.0) {
382 throw InvalidArgument(context + ": ridge regularization must be >= 0");
383 }
384
385 if (ridge == 0.0) {
386 Eigen::JacobiSVD<NumericMatrix> svd(design_matrix,
387 Eigen::ComputeThinU | Eigen::ComputeThinV);
388 if (svd.rank() < design_matrix.cols()) {
389 throw InvalidArgument(context + ": design matrix is rank deficient");
390 }
391 return svd.solve(NumericMatrix::Identity(design_matrix.rows(), design_matrix.rows()));
392 }
393
394 NumericMatrix gram = design_matrix.transpose() * design_matrix;
395 if (ridge > 0.0) {
396 gram.diagonal().array() += ridge;
397 }
398 return gram.ldlt().solve(design_matrix.transpose());
399}
400
401} // namespace detail
402
412template <JanusScalar Scalar>
413Scalar pce_polynomial(const PolynomialChaosDimension &dimension, int degree, const Scalar &x,
414 bool normalized = true) {
415 detail::validate_degree(degree, "pce_polynomial");
416 detail::validate_dimension(dimension, "pce_polynomial");
417
418 Scalar value = Scalar(0.0);
419 switch (dimension.family) {
421 value = detail::raw_hermite_polynomial(degree, x);
422 break;
424 value = detail::raw_legendre_polynomial(degree, x);
425 break;
427 value = detail::raw_jacobi_polynomial(degree, x, dimension.alpha, dimension.beta);
428 break;
430 value = detail::raw_laguerre_polynomial(degree, x, dimension.alpha);
431 break;
432 }
433
434 if (!normalized) {
435 return value;
436 }
437
438 const double norm = detail::squared_norm_probability(dimension, degree);
439 return value / janus::sqrt(Scalar(norm));
440}
441
445inline double pce_squared_norm(const PolynomialChaosDimension &dimension, int degree,
446 bool normalized = true) {
447 if (normalized) {
448 return 1.0;
449 }
450 return detail::squared_norm_probability(dimension, degree);
451}
452
457 public:
459
460 PolynomialChaosBasis(std::vector<PolynomialChaosDimension> dimensions, int order,
461 PolynomialChaosBasisOptions options = {})
462 : dimensions_(std::move(dimensions)), order_(order), options_(options) {
463 if (dimensions_.empty()) {
464 throw InvalidArgument("PolynomialChaosBasis: need at least one stochastic dimension");
465 }
466 if (order_ < 0) {
467 throw InvalidArgument("PolynomialChaosBasis: order must be >= 0");
468 }
469 for (const auto &dimension : dimensions_) {
470 detail::validate_dimension(dimension, "PolynomialChaosBasis");
471 }
472
473 const std::vector<std::vector<int>> indices = detail::generate_multi_indices(
474 static_cast<int>(dimensions_.size()), order_, options_.truncation);
475
476 terms_.reserve(indices.size());
477 squared_norms_.resize(static_cast<Eigen::Index>(indices.size()));
478 for (std::size_t i = 0; i < indices.size(); ++i) {
479 double norm = 1.0;
480 for (std::size_t axis = 0; axis < dimensions_.size(); ++axis) {
481 norm *= pce_squared_norm(dimensions_[axis], indices[i][axis], options_.normalized);
482 }
483 terms_.push_back(PolynomialChaosTerm{indices[i], norm});
484 squared_norms_(static_cast<Eigen::Index>(i)) = norm;
485 }
486 }
487
488 int dimension() const { return static_cast<int>(dimensions_.size()); }
489
490 int order() const { return order_; }
491
492 int size() const { return static_cast<int>(terms_.size()); }
493
494 bool normalized() const { return options_.normalized; }
495
496 PolynomialChaosTruncation truncation() const { return options_.truncation; }
497
498 const std::vector<PolynomialChaosDimension> &dimensions() const { return dimensions_; }
499
500 const std::vector<PolynomialChaosTerm> &terms() const { return terms_; }
501
502 const NumericVector &squared_norms() const { return squared_norms_; }
503
504 template <JanusScalar Scalar>
506 if (point.size() != dimension()) {
507 throw InvalidArgument("PolynomialChaosBasis::evaluate(point): point dimension must "
508 "match the basis dimension");
509 }
510
511 JanusVector<Scalar> values(size());
512 for (int term_idx = 0; term_idx < size(); ++term_idx) {
513 Scalar value = Scalar(1.0);
514 for (int axis = 0; axis < dimension(); ++axis) {
515 value *= pce_polynomial(dimensions_[static_cast<std::size_t>(axis)],
516 terms_[static_cast<std::size_t>(term_idx)]
517 .multi_index[static_cast<std::size_t>(axis)],
518 point(axis), options_.normalized);
519 }
520 values(term_idx) = value;
521 }
522 return values;
523 }
524
525 NumericMatrix evaluate(const NumericMatrix &samples) const {
526 detail::validate_samples(samples, dimension(), "PolynomialChaosBasis::evaluate(samples)");
527
528 NumericMatrix design(samples.rows(), size());
529 for (Eigen::Index row = 0; row < samples.rows(); ++row) {
530 NumericVector point = samples.row(row).transpose();
531 design.row(row) = evaluate(point).transpose();
532 }
533 return design;
534 }
535
536 private:
537 std::vector<PolynomialChaosDimension> dimensions_;
538 int order_ = 0;
540 std::vector<PolynomialChaosTerm> terms_;
541 NumericVector squared_norms_;
542};
543
553template <JanusScalar Scalar>
555 const NumericMatrix &samples,
556 const NumericVector &weights,
557 const JanusVector<Scalar> &sample_values) {
558 detail::validate_samples(samples, basis.dimension(), "pce_projection_coefficients");
559 if (weights.size() != samples.rows()) {
560 throw InvalidArgument("pce_projection_coefficients: weights size must match the number of "
561 "samples");
562 }
563 if (sample_values.size() != samples.rows()) {
564 throw InvalidArgument(
565 "pce_projection_coefficients: sample value size must match the number of samples");
566 }
567
568 const NumericMatrix design = basis.evaluate(samples);
569 JanusVector<Scalar> coeffs(basis.size());
570 for (int term_idx = 0; term_idx < basis.size(); ++term_idx) {
571 Scalar accum = Scalar(0.0);
572 for (Eigen::Index sample_idx = 0; sample_idx < samples.rows(); ++sample_idx) {
573 accum += weights(sample_idx) * design(sample_idx, term_idx) * sample_values(sample_idx);
574 }
575 coeffs(term_idx) = accum / basis.squared_norms()(term_idx);
576 }
577 return coeffs;
578}
579
589template <JanusScalar Scalar>
591 const NumericMatrix &samples,
592 const NumericVector &weights,
593 const JanusMatrix<Scalar> &sample_values) {
594 detail::validate_samples(samples, basis.dimension(), "pce_projection_coefficients");
595 if (weights.size() != samples.rows()) {
596 throw InvalidArgument("pce_projection_coefficients: weights size must match the number of "
597 "samples");
598 }
599 if (sample_values.rows() != samples.rows()) {
600 throw InvalidArgument("pce_projection_coefficients: sample value rows must match the "
601 "number of samples");
602 }
603
604 const NumericMatrix design = basis.evaluate(samples);
605 JanusMatrix<Scalar> coeffs(basis.size(), sample_values.cols());
606 for (int term_idx = 0; term_idx < basis.size(); ++term_idx) {
607 for (Eigen::Index col = 0; col < sample_values.cols(); ++col) {
608 Scalar accum = Scalar(0.0);
609 for (Eigen::Index sample_idx = 0; sample_idx < samples.rows(); ++sample_idx) {
610 accum += weights(sample_idx) * design(sample_idx, term_idx) *
611 sample_values(sample_idx, col);
612 }
613 coeffs(term_idx, col) = accum / basis.squared_norms()(term_idx);
614 }
615 }
616 return coeffs;
617}
618
628template <JanusScalar Scalar>
631 const JanusVector<Scalar> &sample_values, double ridge = 1e-12) {
632 detail::validate_samples(samples, basis.dimension(), "pce_regression_coefficients");
633 const NumericMatrix design = basis.evaluate(samples);
634 const NumericMatrix op =
635 detail::regression_operator(design, ridge, "pce_regression_coefficients");
636 return detail::apply_operator(op, sample_values, "pce_regression_coefficients");
637}
638
648template <JanusScalar Scalar>
651 const JanusMatrix<Scalar> &sample_values, double ridge = 1e-12) {
652 detail::validate_samples(samples, basis.dimension(), "pce_regression_coefficients");
653 const NumericMatrix design = basis.evaluate(samples);
654 const NumericMatrix op =
655 detail::regression_operator(design, ridge, "pce_regression_coefficients");
656 return detail::apply_operator(op, sample_values, "pce_regression_coefficients");
657}
658
665template <JanusScalar Scalar> Scalar pce_mean(const JanusVector<Scalar> &coefficients) {
666 if (coefficients.size() == 0) {
667 throw InvalidArgument("pce_mean: coefficient vector must be non-empty");
668 }
669 return coefficients(0);
670}
671
679template <JanusScalar Scalar>
680Scalar pce_variance(const PolynomialChaosBasis &basis, const JanusVector<Scalar> &coefficients) {
681 if (coefficients.size() != basis.size()) {
682 throw InvalidArgument("pce_variance: coefficient vector size must match the basis size");
683 }
684
685 Scalar variance = Scalar(0.0);
686 for (int i = 1; i < coefficients.size(); ++i) {
687 variance += basis.squared_norms()(i) * coefficients(i) * coefficients(i);
688 }
689 return variance;
690}
691
692} // namespace janus
Scalar and element-wise arithmetic functions (abs, sqrt, pow, exp, log, etc.).
C++20 concepts constraining valid Janus scalar types.
Custom exception hierarchy for Janus framework.
Core type aliases for numeric and symbolic Eigen/CasADi interop.
Orthogonal polynomial evaluation, spectral nodes, weights, and differentiation matrices.
Input validation failed (e.g., mismatched sizes, invalid parameters).
Definition JanusError.hpp:31
Multidimensional polynomial chaos basis with fixed truncation/order.
Definition PolynomialChaos.hpp:456
const std::vector< PolynomialChaosDimension > & dimensions() const
Definition PolynomialChaos.hpp:498
bool normalized() const
Definition PolynomialChaos.hpp:494
int dimension() const
Definition PolynomialChaos.hpp:488
const std::vector< PolynomialChaosTerm > & terms() const
Definition PolynomialChaos.hpp:500
PolynomialChaosBasis(std::vector< PolynomialChaosDimension > dimensions, int order, PolynomialChaosBasisOptions options={})
Definition PolynomialChaos.hpp:460
NumericMatrix evaluate(const NumericMatrix &samples) const
Definition PolynomialChaos.hpp:525
int order() const
Definition PolynomialChaos.hpp:490
const NumericVector & squared_norms() const
Definition PolynomialChaos.hpp:502
PolynomialChaosTruncation truncation() const
Definition PolynomialChaos.hpp:496
JanusVector< Scalar > evaluate(const JanusVector< Scalar > &point) const
Definition PolynomialChaos.hpp:505
int size() const
Definition PolynomialChaos.hpp:492
Smooth approximation of ReLU function: softplus(x) = (1/beta) * log(1 + exp(beta * x)).
Definition Diagnostics.hpp:131
Scalar raw_laguerre_polynomial(int degree, const Scalar &x, double alpha)
Definition PolynomialChaos.hpp:208
std::vector< std::vector< int > > generate_multi_indices(int dim, int order, PolynomialChaosTruncation truncation)
Definition PolynomialChaos.hpp:306
void tensor_product_recursive(int dim, int order, int axis, std::vector< int > &current, std::vector< std::vector< int > > &indices)
Definition PolynomialChaos.hpp:293
void validate_samples(const NumericMatrix &samples, int dimension, const std::string &context)
Definition PolynomialChaos.hpp:364
void validate_dimension(const PolynomialChaosDimension &dimension, const std::string &context)
Definition PolynomialChaos.hpp:112
Scalar raw_hermite_polynomial(int degree, const Scalar &x)
Definition PolynomialChaos.hpp:132
Scalar raw_legendre_polynomial(int degree, const Scalar &x)
Definition PolynomialChaos.hpp:152
Scalar raw_jacobi_polynomial(int degree, const Scalar &x, double alpha, double beta)
Definition PolynomialChaos.hpp:178
bool multi_index_less(const std::vector< int > &lhs, const std::vector< int > &rhs)
Definition PolynomialChaos.hpp:269
double squared_norm_probability(const PolynomialChaosDimension &dimension, int degree)
Definition PolynomialChaos.hpp:262
NumericMatrix regression_operator(const NumericMatrix &design_matrix, double ridge, const std::string &context)
Definition PolynomialChaos.hpp:375
void total_order_recursive(int dim, int order, int axis, std::vector< int > &current, std::vector< std::vector< int > > &indices)
Definition PolynomialChaos.hpp:278
double squared_norm_raw(const PolynomialChaosDimension &dimension, int degree)
Definition PolynomialChaos.hpp:232
void validate_degree(int degree, const std::string &context)
Definition PolynomialChaos.hpp:106
JanusVector< Scalar > apply_operator(const NumericMatrix &op, const JanusVector< Scalar > &values, const std::string &context)
Definition PolynomialChaos.hpp:325
Definition Diagnostics.hpp:19
JanusVector< Scalar > pce_projection_coefficients(const PolynomialChaosBasis &basis, const NumericMatrix &samples, const NumericVector &weights, const JanusVector< Scalar > &sample_values)
Compute PCE projection coefficients from weighted samples (vector).
Definition PolynomialChaos.hpp:554
Scalar pce_mean(const JanusVector< Scalar > &coefficients)
Extract PCE mean (zeroth coefficient).
Definition PolynomialChaos.hpp:665
Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > JanusMatrix
Dynamic-size matrix for both numeric and symbolic backends.
Definition JanusTypes.hpp:43
JanusMatrix< NumericScalar > NumericMatrix
Eigen::MatrixXd equivalent.
Definition JanusTypes.hpp:66
PolynomialChaosDimension hermite_dimension()
Create a standard normal (Hermite) dimension.
Definition PolynomialChaos.hpp:57
PolynomialChaosDimension laguerre_dimension(double alpha=0.0)
Create a Gamma-family (Laguerre) dimension on [0, inf).
Definition PolynomialChaos.hpp:84
T sqrt(const T &x)
Computes the square root of a scalar.
Definition Arithmetic.hpp:46
PolynomialChaosDimension jacobi_dimension(double alpha, double beta)
Create a Beta-family (Jacobi) dimension on [-1, 1].
Definition PolynomialChaos.hpp:75
JanusVector< NumericScalar > NumericVector
Eigen::VectorXd equivalent.
Definition JanusTypes.hpp:67
PolynomialChaosTruncation
Multi-index truncation strategy for a multidimensional basis.
Definition PolynomialChaos.hpp:35
@ TensorProduct
Definition PolynomialChaos.hpp:37
@ TotalOrder
Definition PolynomialChaos.hpp:36
Scalar pce_variance(const PolynomialChaosBasis &basis, const JanusVector< Scalar > &coefficients)
Compute PCE variance from coefficients.
Definition PolynomialChaos.hpp:680
auto norm(const Eigen::MatrixBase< Derived > &x, NormType type=NormType::L2)
Computes vector/matrix norm.
Definition Linalg.hpp:607
@ Hermite
Definition AutoDiff.hpp:31
double pce_squared_norm(const PolynomialChaosDimension &dimension, int degree, bool normalized=true)
Return the probability-measure squared norm of a univariate basis term.
Definition PolynomialChaos.hpp:445
PolynomialChaosFamily
Univariate Askey-scheme family used for a PCE input dimension.
Definition PolynomialChaos.hpp:25
@ Jacobi
Beta-family random variable on [-1, 1].
Definition PolynomialChaos.hpp:28
@ Hermite
Standard normal random variable via probabilists' Hermite polynomials.
Definition PolynomialChaos.hpp:26
@ Laguerre
Gamma / exponential-family random variable on [0, inf).
Definition PolynomialChaos.hpp:29
@ Legendre
Uniform random variable on [-1, 1].
Definition PolynomialChaos.hpp:27
JanusVector< Scalar > pce_regression_coefficients(const PolynomialChaosBasis &basis, const NumericMatrix &samples, const JanusVector< Scalar > &sample_values, double ridge=1e-12)
Compute PCE coefficients via least-squares regression (vector).
Definition PolynomialChaos.hpp:630
Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > JanusVector
Dynamic-size column vector for both numeric and symbolic backends.
Definition JanusTypes.hpp:49
std::pair< double, double > legendre_poly(int n, double x)
Evaluate Legendre polynomial P_n(x) and derivative P'_n(x).
Definition OrthogonalPolynomials.hpp:77
Scalar pce_polynomial(const PolynomialChaosDimension &dimension, int degree, const Scalar &x, bool normalized=true)
Evaluate a univariate chaos basis polynomial.
Definition PolynomialChaos.hpp:413
PolynomialChaosDimension legendre_dimension()
Create a uniform (Legendre) dimension on [-1, 1].
Definition PolynomialChaos.hpp:65
Basis construction controls for multidimensional PCE.
Definition PolynomialChaos.hpp:91
bool normalized
Use orthonormal basis functions when true.
Definition PolynomialChaos.hpp:93
PolynomialChaosTruncation truncation
Definition PolynomialChaos.hpp:92
One stochastic dimension in a polynomial chaos basis.
Definition PolynomialChaos.hpp:47
PolynomialChaosFamily family
Definition PolynomialChaos.hpp:48
double alpha
Definition PolynomialChaos.hpp:49
double beta
Definition PolynomialChaos.hpp:50
One multidimensional chaos basis term.
Definition PolynomialChaos.hpp:99
double squared_norm
Definition PolynomialChaos.hpp:101
std::vector< int > multi_index
Definition PolynomialChaos.hpp:100