resopt 0.3.0

Declarative constrained residual optimization in Rust
Documentation
/// Solve diagnostics intended for expert users.
#[derive(Debug, Clone, PartialEq)]
pub struct SolveDiagnostics {
    iterations: usize,
    termination_reason: String,
    solve_time_seconds: f64,
    max_constraint_violation: Option<f64>,
}

impl SolveDiagnostics {
    pub fn new(
        iterations: usize,
        termination_reason: String,
        solve_time_seconds: f64,
        max_constraint_violation: Option<f64>,
    ) -> Self {
        Self {
            iterations,
            termination_reason,
            solve_time_seconds,
            max_constraint_violation,
        }
    }

    pub fn iterations(&self) -> usize {
        self.iterations
    }

    pub fn termination_reason(&self) -> &str {
        &self.termination_reason
    }

    pub fn solve_time_seconds(&self) -> f64 {
        self.solve_time_seconds
    }

    pub fn max_constraint_violation(&self) -> Option<f64> {
        self.max_constraint_violation
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn accessors() {
        let d = SolveDiagnostics::new(42, "converged".into(), 0.5, Some(1e-10));
        assert_eq!(d.iterations(), 42);
        assert_eq!(d.termination_reason(), "converged");
        assert!((d.solve_time_seconds() - 0.5).abs() < f64::EPSILON);
        assert!((d.max_constraint_violation().unwrap() - 1e-10).abs() < f64::EPSILON);
    }

    #[test]
    fn no_violation() {
        let d = SolveDiagnostics::new(0, "n/a".into(), 0.0, None);
        assert!(d.max_constraint_violation().is_none());
    }

    #[test]
    fn clone_and_eq() {
        let a = SolveDiagnostics::new(1, "done".into(), 0.01, None);
        assert_eq!(a, a.clone());
    }
}