optirs_core/sensitivity_analysis/mod.rs
1// Global Sensitivity Analysis (GSA) for Hyperparameter Exploration
2//
3// This module provides a suite of methods for analyzing how a model's output
4// responds to changes in its input hyperparameters. Sensitivity analysis is a
5// crucial step in understanding which hyperparameters are most influential and
6// can guide optimization, model interpretability and resource allocation.
7//
8// # Methods
9//
10// - [`SobolAnalyzer`] — Variance-based **global** sensitivity analysis using the
11// Saltelli sampling scheme. Decomposes the variance of the model output into
12// contributions from individual parameters (first-order indices) and their
13// interactions (total-order, optionally second-order indices).
14// - [`MorrisAnalyzer`] — Elementary Effects (Morris) **screening** method. Useful
15// when the cost of evaluating the model is high; identifies which inputs are
16// negligible, linear, or non-linear/interacting.
17// - [`OatAnalyzer`] — One-At-a-Time **local** sensitivity around a baseline.
18// Computes central- and forward-difference gradients to quantify the
19// instantaneous response of the model in the neighborhood of a point.
20//
21// # Typical workflow
22//
23// 1. Screen with Morris to filter out non-influential parameters.
24// 2. Quantify variance attribution for the surviving parameters with Sobol.
25// 3. Use the OAT analyzer for local diagnostics around the optimum.
26//
27// All analyzers operate on a black-box model `Fn(&Array1<F>) -> F` and the
28// rectangular parameter bounds `&[(F, F)]`.
29
30use crate::error::Result;
31use scirs2_core::ndarray::Array1;
32use scirs2_core::numeric::Float;
33
34pub mod morris;
35pub mod oat;
36pub mod sobol;
37
38pub use morris::{MorrisAnalyzer, MorrisIndices};
39pub use oat::{OatAnalyzer, OatResult};
40pub use sobol::SobolAnalyzer;
41
42/// Variance-based sensitivity indices.
43///
44/// `first_order[i]` is the fraction of the output variance that can be
45/// attributed to parameter `i` alone. `total_order[i]` additionally
46/// includes all interactions involving parameter `i`. When
47/// `second_order` is `Some`, `second_order[i][j]` quantifies the
48/// pure interaction between parameters `i` and `j` (excluding their
49/// own first-order contributions).
50#[derive(Debug, Clone)]
51pub struct SensitivityIndices<F: Float> {
52 /// First-order Sobol indices `S_i`, one per parameter.
53 pub first_order: Vec<F>,
54 /// Total-order Sobol indices `S_Ti`, one per parameter.
55 pub total_order: Vec<F>,
56 /// Optional second-order interaction indices `S_ij`.
57 pub second_order: Option<Vec<Vec<F>>>,
58 /// Human-readable names for the parameters; same length as `first_order`.
59 pub parameter_names: Vec<String>,
60}
61
62impl<F: Float> SensitivityIndices<F> {
63 /// Number of parameters described by the indices.
64 pub fn num_parameters(&self) -> usize {
65 self.first_order.len()
66 }
67}
68
69/// Trait implemented by all sensitivity-analysis algorithms in this module.
70///
71/// Implementors evaluate `model` at a number of sample points within the
72/// rectangular domain defined by `bounds` and return a populated
73/// [`SensitivityIndices`] structure.
74pub trait SensitivityAnalyzer<F: Float> {
75 /// Analyze the sensitivity of `model` over the rectangular domain
76 /// specified by `bounds`.
77 ///
78 /// `bounds[i]` is the `(min, max)` range for parameter `i`.
79 fn analyze(
80 &mut self,
81 model: &dyn Fn(&Array1<F>) -> F,
82 bounds: &[(F, F)],
83 ) -> Result<SensitivityIndices<F>>;
84}