diff --git a/src/convergence.rs b/src/convergence.rs index d03359c..ab49639 100644 --- a/src/convergence.rs +++ b/src/convergence.rs @@ -8,6 +8,11 @@ use smallvec::SmallVec; pub struct ConvergenceOptions { pub max_iter: usize, pub epsilon: f64, + /// EP damping factor in natural-parameter space: each per-factor + /// update writes `α·new + (1−α)·old`. `1.0` is undamped (default); + /// `< 1.0` stabilises oscillating fixed-point loops at the cost of + /// more iterations. Must be in `(0.0, 1.0]`. + pub alpha: f64, } impl Default for ConvergenceOptions { @@ -15,6 +20,7 @@ impl Default for ConvergenceOptions { Self { max_iter: crate::ITERATIONS, epsilon: crate::EPSILON, + alpha: 1.0, } } } @@ -29,3 +35,14 @@ pub struct ConvergenceReport { pub per_iteration_time: SmallVec<[Duration; 32]>, pub slices_skipped: usize, } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn default_alpha_is_one_for_undamped_behavior() { + let opts = ConvergenceOptions::default(); + assert_eq!(opts.alpha, 1.0); + } +} diff --git a/src/history.rs b/src/history.rs index bb56750..9ef7653 100644 --- a/src/history.rs +++ b/src/history.rs @@ -1368,6 +1368,7 @@ mod tests { h.convergence = ConvergenceOptions { max_iter: 11, epsilon: EPSILON, + alpha: 1.0, }; h.converge().unwrap(); @@ -1685,6 +1686,7 @@ mod tests { .convergence(ConvergenceOptions { max_iter: 30, epsilon: 1e-6, + alpha: 1.0, }) .build();