sim-lib-discrete-graph 0.2.0

Discrete graph algorithms.
Documentation
//! Error type for discrete graph algorithms.

use sim_lib_discrete_algebra::AlgebraError;

/// Errors raised by graph construction, algorithms, and verifiers.
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum GraphError {
    /// The graph is disconnected, so the requested result does not exist.
    #[error("graph is disconnected")]
    Disconnected,
    /// A negative-weight cycle makes shortest paths undefined.
    #[error("graph has a negative-weight cycle")]
    NegativeCycle,
    /// A negative edge weight was supplied to an algorithm that forbids it.
    #[error("negative edge weight is not allowed here")]
    NegativeWeight,
    /// The algorithm was called on the wrong kind of graph.
    #[error("wrong graph kind: {0}")]
    WrongGraphKind(String),
    /// An edge referenced a node index outside the node range.
    #[error("invalid endpoint on edge {edge}: node {node} >= node count {len}")]
    InvalidEndpoint {
        /// The offending edge id.
        edge: usize,
        /// The out-of-range node index.
        node: usize,
        /// The number of nodes.
        len: usize,
    },
    /// An edge id is not the storage index required by id-indexed consumers.
    #[error(
        "invalid edge id at storage index {index}: id {id} is not < edge count {len} and equal to its storage index"
    )]
    InvalidEdgeId {
        /// The storage index where the edge was found.
        index: usize,
        /// The offending edge id.
        id: usize,
        /// The number of stored edge records.
        len: usize,
    },
    /// A graph weight sum or path relaxation overflowed its representation.
    #[error("graph weight overflow: {0}")]
    WeightOverflow(String),
    /// A floating-point or user-defined cost was not finite or comparable.
    #[error("non-finite graph cost: {0}")]
    NonFiniteCost(String),
    /// An algorithm control was internally inconsistent.
    #[error("invalid graph algorithm control: {0}")]
    InvalidControl(String),
    /// A work, memory, time, or cancellation bound stopped the algorithm.
    #[error("graph algorithm stopped by control: {0}")]
    ControlStopped(String),
    /// A node index passed to an algorithm was outside the node range.
    #[error("node {node} out of range: node count {count}")]
    NodeOutOfRange {
        /// The out-of-range node index.
        node: usize,
        /// The number of nodes.
        count: usize,
    },
    /// A submitted certificate failed verification.
    #[error("certificate invalid: {0}")]
    CertificateInvalid(String),
    /// An assignment matrix, policy, or submitted assignment was malformed.
    #[error("invalid assignment: {0}")]
    InvalidAssignment(String),
    /// A staged feature is not yet implemented.
    #[error("unsupported: {0}")]
    Unsupported(String),
}

impl From<AlgebraError> for GraphError {
    fn from(err: AlgebraError) -> Self {
        match err {
            // For a min-plus adjacency matrix, a divergent closure star means a
            // negative-weight cycle.
            AlgebraError::NoStar => GraphError::NegativeCycle,
            other => GraphError::Unsupported(other.to_string()),
        }
    }
}