Skip to main content

uncertain_numerics/
lib.rs

1//! Probabilistic numerical methods with explicit uncertainty over computational
2//! quantities.
3//!
4//! `uncertain-numerics` treats numerical computation as an inference problem.
5//! Instead of returning only a point estimate of an integral or of the solution
6//! of a linear system, each method returns a validated Gaussian posterior: its
7//! mean is the estimate and its variance states how much the computation still
8//! does not know. Every statistical and numerical assumption behind that
9//! posterior is explicit, documented, and tested.
10//!
11//! # What is implemented
12//!
13//! | Area | Entry points |
14//! | --- | --- |
15//! | One-dimensional Bayesian quadrature | [`BayesianQuadrature`], [`RbfKernel`], [`GaussianMeasure`], [`ScalarNormalPosterior`] |
16//! | Active Bayesian quadrature | [`ActiveBayesianQuadrature`], [`VarianceReductionAcquisition`] |
17//! | Probabilistic linear solvers | [`SpdLinearSystem`], [`GaussianLinearBelief`], [`ResidualProjectionSolver`], [`AConjugateProjectionSolver`], [`CovarianceGreedyProjectionSolver`] |
18//! | Building blocks | [`GaussianConditioner`], [`KernelMean`], [`KernelIntegral`], [`ScalarKernel`], [`ContinuousProbabilityMeasure`] |
19//!
20//! # Example
21//!
22//! Infer the integral of `cos(x)` against a standard Gaussian measure from seven
23//! function evaluations, together with its posterior uncertainty:
24//!
25//! ```
26//! use uncertain_numerics::{BayesianQuadrature, GaussianMeasure, RbfKernel};
27//!
28//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
29//! let kernel = RbfKernel::new(1.0, 1.0)?; // signal variance, length scale
30//! let measure = GaussianMeasure::new(0.0, 1.0)?; // p(x) = N(0, 1)
31//! let quadrature = BayesianQuadrature::new(kernel, measure, 1.0e-10);
32//!
33//! let nodes = [-3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0];
34//! let values: Vec<f64> = nodes.iter().copied().map(f64::cos).collect();
35//! let posterior = quadrature.posterior(&nodes, &values)?;
36//!
37//! // Exactly, E[cos X] = exp(-1/2) for X ~ N(0, 1).
38//! let exact = (-0.5_f64).exp();
39//! println!("{} ± {}", posterior.mean(), posterior.standard_deviation());
40//! assert!((posterior.mean() - exact).abs() < 3.0 * posterior.standard_deviation());
41//! # Ok(())
42//! # }
43//! ```
44//!
45//! # Numerical policy
46//!
47//! - Inputs are validated at the API boundary. Invalid values produce typed
48//!   errors that implement [`std::error::Error`]; they never propagate as `NaN`.
49//! - Linear systems are solved from a reusable Cholesky factorization. Explicit
50//!   inverses are never formed.
51//! - Jitter is a caller-supplied constant added to the diagonal. Because it
52//!   changes the posterior, it is never increased automatically to make a
53//!   factorization succeed.
54//! - Posterior variances that are negative by more than machine roundoff are
55//!   reported as errors rather than clamped.
56//!
57//! # Interpreting the uncertainty
58//!
59//! Posterior uncertainty is conditional on the numerical model. Under the
60//! assumed prior the reported intervals are empirically calibrated, which the
61//! integration tests verify. Under misspecification, for example an RBF length
62//! scale that is far too smooth for the integrand, the posterior can be
63//! confidently wrong. The `docs/` directory of the repository records the known
64//! failure modes and the calibration status of each linear-solver policy.
65//!
66//! # Minimum supported Rust version
67//!
68//! Rust 1.85. Raising the MSRV is treated as at least a minor version bump.
69
70// Applied here rather than in `[lints.rust]` so that examples and integration
71// tests, which have no crate-level docs, are not affected.
72#![warn(missing_docs)]
73
74mod a_conjugate_solver;
75mod active;
76mod active_design;
77mod active_design_error;
78mod active_error;
79mod bayesian_quadrature;
80mod bayesian_quadrature_error;
81mod conditioning;
82mod conditioning_error;
83mod covariance_greedy_solver;
84mod error;
85mod kernel;
86mod kernel_error;
87mod kernel_integral;
88mod kernel_mean;
89mod linear_belief;
90mod linear_solver_error;
91mod linear_system;
92mod measure;
93mod measure_error;
94mod posterior;
95mod probabilistic_linear_solver;
96
97pub use a_conjugate_solver::{
98    AConjugateLinearSolveResult, AConjugateLinearSolveStep, AConjugateProjectionSolver,
99};
100pub use active::{SelectedCandidate, VarianceReductionAcquisition};
101pub use active_design::{
102    ActiveBayesianQuadrature, ActiveDesignResult, ActiveDesignStep, ActiveTermination,
103};
104pub use active_design_error::ActiveDesignError;
105pub use active_error::ActiveSelectionError;
106pub use bayesian_quadrature::BayesianQuadrature;
107pub use bayesian_quadrature_error::BayesianQuadratureError;
108pub use conditioning::GaussianConditioner;
109pub use conditioning_error::ConditioningError;
110pub use covariance_greedy_solver::{
111    CovarianceGreedyProjectionSolver, CovarianceGreedySolveResult, CovarianceGreedyStep,
112    CovarianceGreedyTermination, CovarianceTraceAcquisition, SelectedLinearDirection,
113};
114pub use error::PosteriorError;
115pub use kernel::{RbfKernel, ScalarKernel};
116pub use kernel_error::KernelError;
117pub use kernel_integral::KernelIntegral;
118pub use kernel_mean::KernelMean;
119pub use linear_belief::GaussianLinearBelief;
120pub use linear_solver_error::LinearSolverError;
121pub use linear_system::SpdLinearSystem;
122pub use measure::{ContinuousProbabilityMeasure, GaussianMeasure};
123pub use measure_error::MeasureError;
124pub use posterior::ScalarNormalPosterior;
125pub use probabilistic_linear_solver::{
126    LinearSolveStep, LinearSolveTermination, ProbabilisticLinearSolveResult,
127    ResidualProjectionSolver,
128};
129
130/// Compiles and runs every Rust code block in the README as a doctest, so the
131/// examples shown on GitHub and crates.io can never drift from the real API.
132#[cfg(doctest)]
133#[doc = include_str!("../README.md")]
134mod readme_doctests {}