ruqu_neural_decoder/
error.rs

1//! Error types for the Neural Quantum Error Decoder
2//!
3//! This module provides error types for syndrome translation, graph encoding,
4//! Mamba decoding, and feature fusion operations.
5
6use thiserror::Error;
7
8/// Result type for neural decoder operations
9pub type Result<T> = std::result::Result<T, NeuralDecoderError>;
10
11/// Errors that can occur in neural decoder operations
12#[derive(Error, Debug)]
13pub enum NeuralDecoderError {
14    /// Invalid syndrome dimensions
15    #[error("Invalid syndrome dimensions: expected {expected}x{expected}, got {actual_rows}x{actual_cols}")]
16    InvalidSyndromeDimension {
17        /// Expected dimension
18        expected: usize,
19        /// Actual row count
20        actual_rows: usize,
21        /// Actual column count
22        actual_cols: usize,
23    },
24
25    /// Invalid embedding dimension
26    #[error("Invalid embedding dimension: expected {expected}, got {actual}")]
27    InvalidEmbeddingDimension {
28        /// Expected dimension
29        expected: usize,
30        /// Actual dimension
31        actual: usize,
32    },
33
34    /// Invalid hidden state dimension
35    #[error("Invalid hidden state dimension: expected {expected}, got {actual}")]
36    InvalidHiddenDimension {
37        /// Expected dimension
38        expected: usize,
39        /// Actual dimension
40        actual: usize,
41    },
42
43    /// Invalid attention heads configuration
44    #[error("Embedding dimension {embed_dim} must be divisible by number of heads {num_heads}")]
45    InvalidAttentionHeads {
46        /// Embedding dimension
47        embed_dim: usize,
48        /// Number of heads
49        num_heads: usize,
50    },
51
52    /// Empty graph
53    #[error("Detector graph is empty")]
54    EmptyGraph,
55
56    /// Invalid detector index
57    #[error("Invalid detector index: {0}")]
58    InvalidDetector(usize),
59
60    /// Invalid boundary type
61    #[error("Invalid boundary type: {0}")]
62    InvalidBoundary(String),
63
64    /// Decoding failed
65    #[error("Decoding failed: {0}")]
66    DecodingFailed(String),
67
68    /// Fusion error
69    #[error("Feature fusion error: {0}")]
70    FusionError(String),
71
72    /// MinCut integration error
73    #[error("MinCut integration error: {0}")]
74    MinCutError(String),
75
76    /// Shape mismatch
77    #[error("Shape mismatch: expected {expected:?}, got {actual:?}")]
78    ShapeMismatch {
79        /// Expected shape
80        expected: Vec<usize>,
81        /// Actual shape
82        actual: Vec<usize>,
83    },
84
85    /// Numerical instability
86    #[error("Numerical instability detected: {0}")]
87    NumericalInstability(String),
88
89    /// Configuration error
90    #[error("Configuration error: {0}")]
91    ConfigError(String),
92
93    /// Internal error
94    #[error("Internal error: {0}")]
95    InternalError(String),
96}
97
98impl NeuralDecoderError {
99    /// Create a dimension mismatch error for syndromes
100    pub fn syndrome_dim(expected: usize, rows: usize, cols: usize) -> Self {
101        Self::InvalidSyndromeDimension {
102            expected,
103            actual_rows: rows,
104            actual_cols: cols,
105        }
106    }
107
108    /// Create an embedding dimension error
109    pub fn embed_dim(expected: usize, actual: usize) -> Self {
110        Self::InvalidEmbeddingDimension { expected, actual }
111    }
112
113    /// Create a hidden dimension error
114    pub fn hidden_dim(expected: usize, actual: usize) -> Self {
115        Self::InvalidHiddenDimension { expected, actual }
116    }
117
118    /// Create an attention heads error
119    pub fn attention_heads(embed_dim: usize, num_heads: usize) -> Self {
120        Self::InvalidAttentionHeads {
121            embed_dim,
122            num_heads,
123        }
124    }
125
126    /// Create a shape mismatch error
127    pub fn shape_mismatch(expected: Vec<usize>, actual: Vec<usize>) -> Self {
128        Self::ShapeMismatch { expected, actual }
129    }
130
131    /// Check if the error is recoverable
132    pub fn is_recoverable(&self) -> bool {
133        matches!(
134            self,
135            Self::InvalidDetector(_)
136                | Self::InvalidBoundary(_)
137                | Self::ConfigError(_)
138        )
139    }
140
141    /// Check if the error is related to dimensions
142    pub fn is_dimension_error(&self) -> bool {
143        matches!(
144            self,
145            Self::InvalidSyndromeDimension { .. }
146                | Self::InvalidEmbeddingDimension { .. }
147                | Self::InvalidHiddenDimension { .. }
148                | Self::InvalidAttentionHeads { .. }
149                | Self::ShapeMismatch { .. }
150        )
151    }
152}
153
154impl From<ruvector_mincut::MinCutError> for NeuralDecoderError {
155    fn from(err: ruvector_mincut::MinCutError) -> Self {
156        Self::MinCutError(err.to_string())
157    }
158}
159
160impl From<String> for NeuralDecoderError {
161    fn from(msg: String) -> Self {
162        Self::InternalError(msg)
163    }
164}
165
166impl From<&str> for NeuralDecoderError {
167    fn from(msg: &str) -> Self {
168        Self::InternalError(msg.to_string())
169    }
170}
171
172#[cfg(test)]
173mod tests {
174    use super::*;
175
176    #[test]
177    fn test_error_display() {
178        let err = NeuralDecoderError::syndrome_dim(5, 3, 4);
179        assert!(err.to_string().contains("5"));
180        assert!(err.to_string().contains("3"));
181        assert!(err.to_string().contains("4"));
182
183        let err = NeuralDecoderError::embed_dim(128, 64);
184        assert!(err.to_string().contains("128"));
185        assert!(err.to_string().contains("64"));
186    }
187
188    #[test]
189    fn test_is_recoverable() {
190        assert!(NeuralDecoderError::InvalidDetector(0).is_recoverable());
191        assert!(NeuralDecoderError::InvalidBoundary("test".to_string()).is_recoverable());
192        assert!(!NeuralDecoderError::EmptyGraph.is_recoverable());
193        assert!(!NeuralDecoderError::DecodingFailed("test".to_string()).is_recoverable());
194    }
195
196    #[test]
197    fn test_is_dimension_error() {
198        assert!(NeuralDecoderError::syndrome_dim(5, 3, 4).is_dimension_error());
199        assert!(NeuralDecoderError::embed_dim(128, 64).is_dimension_error());
200        assert!(NeuralDecoderError::attention_heads(128, 3).is_dimension_error());
201        assert!(!NeuralDecoderError::EmptyGraph.is_dimension_error());
202    }
203
204    #[test]
205    fn test_from_string() {
206        let err: NeuralDecoderError = "test error".into();
207        assert!(matches!(err, NeuralDecoderError::InternalError(_)));
208        assert!(err.to_string().contains("test error"));
209    }
210}