Janus 2.0.0
High-performance C++20 dual-mode numerical framework
Loading...
Searching...
No Matches
Polynomial Chaos

Janus includes a PCE (Polynomial Chaos Expansion) layer in PolynomialChaos.hpp for spectral uncertainty quantification. It provides Askey-scheme basis polynomials, multidimensional basis construction, structured stochastic quadrature rules and sparse grids, coefficient recovery from projection or regression samples, and symbolic mean and variance propagation. The key benefit is that fitted PCE coefficients can remain symbolic casadi::MX expressions, so statistical moments can be differentiated with respect to design variables without nesting Monte Carlo inside an optimizer. This works in both numeric and symbolic modes.

Quick Start

#include <janus/janus.hpp>
// Build a 1D Legendre basis of degree <= 2
// Get quadrature rule for projection
// Evaluate your model at quadrature nodes
janus::NumericVector values(rule.nodes.size());
for (Eigen::Index i = 0; i < rule.nodes.size(); ++i) {
values(i) = std::sin(rule.nodes(i)); // Example: sin(xi)
}
// Recover PCE coefficients via projection
// Extract mean and variance
double mean = janus::pce_mean(coeffs);
double variance = janus::pce_variance(basis, coeffs);
Multidimensional polynomial chaos basis with fixed truncation/order.
Definition PolynomialChaos.hpp:456
Umbrella header that includes the entire Janus public API.
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
JanusVector< NumericScalar > NumericVector
Eigen::VectorXd equivalent.
Definition JanusTypes.hpp:67
Scalar pce_variance(const PolynomialChaosBasis &basis, const JanusVector< Scalar > &coefficients)
Compute PCE variance from coefficients.
Definition PolynomialChaos.hpp:680
UnivariateQuadratureRule stochastic_quadrature_rule(const PolynomialChaosDimension &dimension, int order, StochasticQuadratureRule rule=StochasticQuadratureRule::Gauss)
Build a one-dimensional stochastic quadrature rule with a fixed order.
Definition Quadrature.hpp:426
PolynomialChaosDimension legendre_dimension()
Create a uniform (Legendre) dimension on [-1, 1].
Definition PolynomialChaos.hpp:65

Core API

  • janus::hermite_dimension(): Hermite basis for standard normal variables.
  • janus::legendre_dimension(): Legendre basis for uniform variables on [-1, 1].
  • janus::jacobi_dimension(alpha, beta): Jacobi basis for beta-family variables on [-1, 1].
  • janus::laguerre_dimension(): Laguerre basis for exponential/gamma-family variables on [0, inf).
  • janus::pce_polynomial(dim, order, x): Evaluate a univariate basis function (normalized by default).
  • janus::pce_squared_norm(dim, order, normalized): Get the squared norm of a basis function.
  • janus::PolynomialChaosBasis(dims, degree, opts): Build a multidimensional basis with total-order or tensor-product truncation.
  • janus::pce_projection_coefficients(basis, rule, values): Recover coefficients via weighted projection.
  • janus::pce_regression_coefficients(basis, samples, values, ridge): Recover coefficients via regression.
  • janus::pce_mean(coeffs): Extract the mean from PCE coefficients.
  • janus::pce_variance(basis, coeffs): Extract the variance from PCE coefficients.

Usage Patterns

Supported Families

Use one PolynomialChaosDimension per uncertain input:

auto gaussian = janus::hermite_dimension();
auto uniform = janus::legendre_dimension();
auto beta_like = janus::jacobi_dimension(1.0, 2.0);
auto exponential = janus::laguerre_dimension(); // alpha = 0
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
PolynomialChaosDimension jacobi_dimension(double alpha, double beta)
Create a Beta-family (Jacobi) dimension on [-1, 1].
Definition PolynomialChaos.hpp:75

The canonical variable domains are:

  • Hermite: standard normal variable
  • Legendre: uniform variable on [-1, 1]
  • Jacobi: mapped beta-family variable on [-1, 1]
  • Laguerre: exponential / gamma-family variable on [0, inf)

Evaluate one univariate basis function with:

double psi2 = janus::pce_polynomial(uniform, 2, 0.25);
double raw_norm = janus::pce_squared_norm(uniform, 2, false);
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
Scalar pce_polynomial(const PolynomialChaosDimension &dimension, int degree, const Scalar &x, bool normalized=true)
Evaluate a univariate chaos basis polynomial.
Definition PolynomialChaos.hpp:413

By default pce_polynomial(...) returns the normalized basis function. Pass normalized = false if you want the classical raw polynomial instead.

Building a Multidimensional Basis

PolynomialChaosBasis builds the multi-index set and caches each term's squared norm:

This constructs a total-order basis of degree <= 2. To switch to tensor-product truncation:

2,
.normalized = true
});
@ TensorProduct
Definition PolynomialChaos.hpp:37
Basis construction controls for multidimensional PCE.
Definition PolynomialChaos.hpp:91

Inspect the generated terms and evaluate:

for (const auto &term : basis.terms()) {
// term.multi_index, term.squared_norm
}
xi << 0.25, -0.4;
janus::NumericVector psi = basis.evaluate(xi);

Sample Matrix Layout

For projection and regression, Janus expects the sample matrix as:

  • rows: sample points
  • columns: stochastic dimensions
// For one uncertain variable:
janus::NumericMatrix samples(nodes.size(), 1);
samples.col(0) = nodes;
// For d uncertain variables and N sample points, samples should be N x d.
JanusMatrix< NumericScalar > NumericMatrix
Eigen::MatrixXd equivalent.
Definition JanusTypes.hpp:66
NumericVector lgl_nodes(int N)
Compute Legendre-Gauss-Lobatto nodes on [-1, 1].
Definition OrthogonalPolynomials.hpp:138

Structured Quadrature Rules

For probability-measure quadrature, prefer Quadrature.hpp over manually assembling nodes and weights:

The returned weights already integrate against the probability measure, so for Legendre/uniform variables they sum to 1 directly. You do not need the extra 0.5 scaling that raw lgl_weights(...) require.

For bounded-support families, nested refinement is available:

auto coarse =
2,
@ ClenshawCurtis
Nested Clenshaw-Curtis-like rule on bounded support.
Definition Quadrature.hpp:56
UnivariateQuadratureRule stochastic_quadrature_level(const PolynomialChaosDimension &dimension, int level, StochasticQuadratureRule rule=StochasticQuadratureRule::AutoNested)
Build a one-dimensional stochastic quadrature rule from a refinement level.
Definition Quadrature.hpp:456

For higher-dimensional problems:

auto sparse_grid = janus::smolyak_sparse_grid(
3);
StochasticQuadratureGrid smolyak_sparse_grid(const std::vector< PolynomialChaosDimension > &dimensions, int level, SmolyakQuadratureOptions options={})
Build a Smolyak sparse grid on probability measures.
Definition Quadrature.hpp:554

See Stochastic Quadrature Guide for the full rule set and sparse-grid details.

Projection Coefficients

Use weighted projection when you already have quadrature-like nodes and weights:

auto rule =
janus::NumericVector values(rule.nodes.size());
for (Eigen::Index i = 0; i < rule.nodes.size(); ++i) {
values(i) = 1.2 * janus::pce_polynomial(janus::legendre_dimension(), 0, rule.nodes(i))
+ 0.5 * janus::pce_polynomial(janus::legendre_dimension(), 1, rule.nodes(i))
- 0.7 * janus::pce_polynomial(janus::legendre_dimension(), 2, rule.nodes(i));
}
janus::pce_projection_coefficients(basis, rule, values);

If you already have your own samples matrix and weights vector, the original overloads still work:

janus::pce_projection_coefficients(basis, samples, weights, values);

Regression Coefficients

Use regression when you have collocation samples without matching quadrature weights:

// continued from "Projection Coefficients" above (reuses basis, values)
nodes << -1.0, -0.6, -0.2, 0.2, 0.6, 1.0;
janus::NumericMatrix samples(nodes.size(), 1);
samples.col(0) = nodes;
janus::pce_regression_coefficients(basis, samples, values, 0.0);
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

The final ridge argument is an optional Tikhonov regularization parameter. When ridge = 0, Janus rejects rank-deficient design matrices instead of silently returning a bad fit.

Symbolic Moments

The main Janus-specific payoff is that the sampled response can stay symbolic:

// continued from "Regression Coefficients" above (reuses basis, nodes, samples)
auto a = janus::sym("a");
janus::SymbolicVector sample_values(nodes.size());
for (Eigen::Index i = 0; i < nodes.size(); ++i) {
sample_values(i) = (1.0 + a) * janus::pce_polynomial(janus::legendre_dimension(), 0, nodes(i))
+ (0.25 * a) * janus::pce_polynomial(janus::legendre_dimension(), 2, nodes(i));
}
auto coeffs = janus::pce_regression_coefficients(basis, samples, sample_values, 0.0);
auto mean = janus::pce_mean(coeffs);
auto variance = janus::pce_variance(basis, coeffs);
JanusVector< SymbolicScalar > SymbolicVector
Eigen vector of MX elements.
Definition JanusTypes.hpp:72
SymbolicScalar sym(const std::string &name)
Create a named symbolic scalar variable.
Definition JanusTypes.hpp:90

Because coeffs, mean, and variance are symbolic expressions, you can differentiate them directly:

auto dmean_da = janus::jacobian(mean, a);
auto dvariance_da = janus::jacobian(variance, a);
auto jacobian(const Expr &expression, const Vars &...variables)
Computes Jacobian of an expression with respect to variables.
Definition AutoDiff.hpp:109

With the default normalized basis:

  • pce_mean(coeffs) returns the constant coefficient
  • pce_variance(basis, coeffs) returns the sum of squared non-constant coefficients

If you build the basis with .normalized = false, Janus uses each term's stored squared norm instead.

See Also