Skip to main content

sim_lib_discrete_graph/
error.rs

1//! Error type for discrete graph algorithms.
2
3use sim_lib_discrete_algebra::AlgebraError;
4
5/// Errors raised by graph construction, algorithms, and verifiers.
6#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
7pub enum GraphError {
8    /// The graph is disconnected, so the requested result does not exist.
9    #[error("graph is disconnected")]
10    Disconnected,
11    /// A negative-weight cycle makes shortest paths undefined.
12    #[error("graph has a negative-weight cycle")]
13    NegativeCycle,
14    /// A negative edge weight was supplied to an algorithm that forbids it.
15    #[error("negative edge weight is not allowed here")]
16    NegativeWeight,
17    /// The algorithm was called on the wrong kind of graph.
18    #[error("wrong graph kind: {0}")]
19    WrongGraphKind(String),
20    /// An edge referenced a node index outside the node range.
21    #[error("invalid endpoint on edge {edge}: node {node} >= node count {len}")]
22    InvalidEndpoint {
23        /// The offending edge id.
24        edge: usize,
25        /// The out-of-range node index.
26        node: usize,
27        /// The number of nodes.
28        len: usize,
29    },
30    /// An edge id is not the storage index required by id-indexed consumers.
31    #[error(
32        "invalid edge id at storage index {index}: id {id} is not < edge count {len} and equal to its storage index"
33    )]
34    InvalidEdgeId {
35        /// The storage index where the edge was found.
36        index: usize,
37        /// The offending edge id.
38        id: usize,
39        /// The number of stored edge records.
40        len: usize,
41    },
42    /// A graph weight sum or path relaxation overflowed its representation.
43    #[error("graph weight overflow: {0}")]
44    WeightOverflow(String),
45    /// A floating-point or user-defined cost was not finite or comparable.
46    #[error("non-finite graph cost: {0}")]
47    NonFiniteCost(String),
48    /// An algorithm control was internally inconsistent.
49    #[error("invalid graph algorithm control: {0}")]
50    InvalidControl(String),
51    /// A work, memory, time, or cancellation bound stopped the algorithm.
52    #[error("graph algorithm stopped by control: {0}")]
53    ControlStopped(String),
54    /// A node index passed to an algorithm was outside the node range.
55    #[error("node {node} out of range: node count {count}")]
56    NodeOutOfRange {
57        /// The out-of-range node index.
58        node: usize,
59        /// The number of nodes.
60        count: usize,
61    },
62    /// A submitted certificate failed verification.
63    #[error("certificate invalid: {0}")]
64    CertificateInvalid(String),
65    /// An assignment matrix, policy, or submitted assignment was malformed.
66    #[error("invalid assignment: {0}")]
67    InvalidAssignment(String),
68    /// A staged feature is not yet implemented.
69    #[error("unsupported: {0}")]
70    Unsupported(String),
71}
72
73impl From<AlgebraError> for GraphError {
74    fn from(err: AlgebraError) -> Self {
75        match err {
76            // For a min-plus adjacency matrix, a divergent closure star means a
77            // negative-weight cycle.
78            AlgebraError::NoStar => GraphError::NegativeCycle,
79            other => GraphError::Unsupported(other.to_string()),
80        }
81    }
82}