Skip to main content

antecedent_graph/
error.rs

1//! Graph construction and validation errors.
2//!
3//! SPDX-License-Identifier: MIT OR Apache-2.0
4
5use core::fmt;
6
7use antecedent_core::{Lag, VariableId};
8
9/// Graph-layer errors.
10#[derive(Clone, Debug, Eq, PartialEq)]
11pub enum GraphError {
12    /// Unknown dense node.
13    UnknownNode {
14        /// Dense id.
15        id: u32,
16    },
17    /// Unknown variable name at an API boundary.
18    UnknownVariableName {
19        /// Requested name.
20        name: String,
21    },
22    /// Edge would introduce a directed cycle.
23    Cycle {
24        /// Source dense id.
25        from: u32,
26        /// Target dense id.
27        to: u32,
28    },
29    /// Invalid endpoint combination for this graph class.
30    InvalidEndpoints {
31        /// Explanation.
32        message: &'static str,
33    },
34    /// Contemporaneous self-edge is invalid.
35    ContemporaneousSelfEdge {
36        /// Variable.
37        variable: VariableId,
38    },
39    /// Duplicate edge.
40    DuplicateEdge {
41        /// From.
42        from: u32,
43        /// To.
44        to: u32,
45    },
46    /// Lagged self-edge with lag 0.
47    InvalidLag {
48        /// Lag value.
49        lag: Lag,
50    },
51    /// Node capacity exceeded.
52    TooManyNodes,
53    /// Bounded path search hit `max_paths` or `max_len` before exploring all candidates.
54    ///
55    /// Returned when m-separation would otherwise conclude "separated" after an incomplete
56    /// search (an unexplored active path may still exist). Finding an active path remains
57    /// conclusive even under truncation.
58    SearchBudgetExhausted {
59        /// Path-count budget.
60        max_paths: usize,
61        /// Path-length budget.
62        max_len: usize,
63    },
64}
65
66impl fmt::Display for GraphError {
67    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68        match self {
69            Self::UnknownNode { id } => write!(f, "unknown dense node {id}"),
70            Self::UnknownVariableName { name } => write!(f, "unknown variable name '{name}'"),
71            Self::Cycle { from, to } => write!(f, "edge {from}->{to} would create a cycle"),
72            Self::InvalidEndpoints { message } => write!(f, "invalid endpoints: {message}"),
73            Self::ContemporaneousSelfEdge { variable } => {
74                write!(f, "contemporaneous self-edge on {variable}")
75            }
76            Self::DuplicateEdge { from, to } => write!(f, "duplicate edge {from}->{to}"),
77            Self::InvalidLag { lag } => write!(f, "invalid lag {lag}"),
78            Self::TooManyNodes => write!(f, "too many nodes"),
79            Self::SearchBudgetExhausted { max_paths, max_len } => {
80                write!(f, "path search budget exhausted (max_paths={max_paths}, max_len={max_len})")
81            }
82        }
83    }
84}
85
86impl std::error::Error for GraphError {}