Skip to main content

pounce_linsol/
summary.rs

1//! Linear-solver post-mortem summary — shared shape that concrete
2//! backends populate and downstream report builders consume.
3//!
4//! Kept dep-light on purpose: no serde derives here. The CLI's solve
5//! report crate owns the serializable mirror.
6
7/// Aggregate stats accumulated over the lifetime of one linear-solver
8/// instance. All fields default to zero / `None` so a backend that
9/// declines to populate them still produces a valid summary.
10#[derive(Debug, Clone, Default)]
11pub struct LinearSolverSummary {
12    /// Short identifier of the backend that produced this summary:
13    /// `"feral"`, `"ma57"`, etc. Empty for the `Default` value.
14    pub solver_name: String,
15    /// Number of `factor()` calls completed (including those that
16    /// reused the cached symbolic factorisation).
17    pub n_factors: u64,
18    /// Of `n_factors`, how many reused the previous symbolic
19    /// factorisation (sparsity pattern unchanged). Healthy IPM workloads
20    /// expect this to dominate after the first iter.
21    pub n_pattern_reuse: u64,
22    /// Of `n_factors`, how many required a fresh symbolic factorisation
23    /// (sparsity pattern changed). Inverse of `n_pattern_reuse` modulo
24    /// the very first factor.
25    pub n_pattern_changes: u64,
26    /// Maximum `nnz(L) / nnz(A)` observed across factors. Values much
27    /// greater than ~10 on KKT-style systems indicate ordering trouble.
28    pub max_fill_ratio: Option<f64>,
29    /// Minimum `|pivot|` observed across factors. Approaches the
30    /// working-precision floor when the matrix is near-singular.
31    pub min_abs_pivot: Option<f64>,
32    /// Maximum `|pivot|` observed across factors.
33    pub max_abs_pivot: Option<f64>,
34    /// Inertia of the final factorisation as `(positive, negative, zero)`.
35    pub last_inertia: Option<(usize, usize, usize)>,
36    /// `nnz(A)` of the final factorisation's matrix.
37    pub last_nnz_a: Option<usize>,
38    /// `nnz(L)` of the final factorisation.
39    pub last_nnz_l: Option<usize>,
40}
41
42impl LinearSolverSummary {
43    /// Returns `true` if the summary carries no signal beyond the
44    /// solver name — useful for "did we collect anything?" checks.
45    pub fn is_empty(&self) -> bool {
46        self.n_factors == 0
47    }
48}