use crate::{NonLinearSystemError, SolveOutcomeFreedomAnalysis, solver::Model};
pub(crate) trait Analysis: Sized {
fn analyze(model: Model<'_>) -> Result<Self, NonLinearSystemError>;
fn no_constraints() -> Self;
}
#[derive(Default, Debug)]
pub(crate) struct NoAnalysis;
impl Analysis for NoAnalysis {
#[mutants::skip]
fn analyze(_: Model<'_>) -> Result<Self, NonLinearSystemError> {
Ok(Self)
}
#[mutants::skip]
fn no_constraints() -> Self {
Self
}
}
#[derive(Default, Debug)]
#[cfg_attr(not(feature = "unstable-exhaustive"), non_exhaustive)]
pub struct FreedomAnalysis {
underconstrained: Vec<crate::Id>,
}
impl Analysis for FreedomAnalysis {
fn analyze(model: Model<'_>) -> Result<Self, NonLinearSystemError> {
model.freedom_analysis()
}
#[mutants::skip]
fn no_constraints() -> Self {
Self {
underconstrained: Vec::new(),
}
}
}
impl FreedomAnalysis {
pub(crate) fn new(underconstrained: Vec<crate::Id>) -> Self {
Self { underconstrained }
}
pub fn is_underconstrained(&self) -> bool {
!self.underconstrained.is_empty()
}
pub fn underconstrained(&self) -> &[crate::Id] {
&self.underconstrained
}
pub fn into_underconstrained(self) -> Vec<crate::Id> {
self.underconstrained
}
}
impl From<FreedomAnalysis> for Vec<crate::Id> {
fn from(analysis: FreedomAnalysis) -> Vec<crate::Id> {
analysis.into_underconstrained()
}
}
#[derive(Debug)]
pub(crate) struct SolveOutcomeAnalysis<A> {
pub analysis: A,
pub outcome: crate::SolveOutcome,
}
impl From<SolveOutcomeFreedomAnalysis> for SolveOutcomeAnalysis<FreedomAnalysis> {
fn from(value: SolveOutcomeFreedomAnalysis) -> Self {
Self {
analysis: value.analysis,
outcome: value.outcome,
}
}
}
impl From<SolveOutcomeAnalysis<FreedomAnalysis>> for SolveOutcomeFreedomAnalysis {
fn from(value: SolveOutcomeAnalysis<FreedomAnalysis>) -> Self {
Self {
analysis: value.analysis,
outcome: value.outcome,
}
}
}