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}