math_audio_optimisation/
error.rs1use thiserror::Error;
8
9#[derive(Debug, Error)]
11pub enum DEError {
12 #[error("bounds mismatch: lower has {lower_len} elements, upper has {upper_len}")]
14 BoundsMismatch {
15 lower_len: usize,
17 upper_len: usize,
19 },
20
21 #[error("invalid bounds at index {index}: lower ({lower}) > upper ({upper})")]
23 InvalidBounds {
24 index: usize,
26 lower: f64,
28 upper: f64,
30 },
31
32 #[error("population size ({pop_size}) must be >= 4 for DE algorithm")]
34 PopulationTooSmall {
35 pop_size: usize,
37 },
38
39 #[error("invalid mutation factor: {factor} (must be in [0, 2])")]
41 InvalidMutationFactor {
42 factor: f64,
44 },
45
46 #[error("invalid crossover rate: {rate} (must be in [0, 1])")]
48 InvalidCrossoverRate {
49 rate: f64,
51 },
52
53 #[error("x0 dimension mismatch: expected {expected}, got {got}")]
55 X0DimensionMismatch {
56 expected: usize,
58 got: usize,
60 },
61
62 #[error("integrality mask dimension mismatch: expected {expected}, got {got}")]
64 IntegralityDimensionMismatch {
65 expected: usize,
67 got: usize,
69 },
70
71 #[error("invalid optimizer configuration: {message}")]
73 InvalidConfig {
74 message: String,
76 },
77}
78
79pub type Result<T> = std::result::Result<T, DEError>;
81
82impl DEError {
83 pub fn is_bounds_error(&self) -> bool {
87 matches!(
88 self,
89 DEError::BoundsMismatch { .. } | DEError::InvalidBounds { .. }
90 )
91 }
92
93 pub fn is_config_error(&self) -> bool {
98 matches!(
99 self,
100 DEError::PopulationTooSmall { .. }
101 | DEError::InvalidMutationFactor { .. }
102 | DEError::InvalidCrossoverRate { .. }
103 | DEError::InvalidConfig { .. }
104 )
105 }
106
107 pub fn is_dimension_error(&self) -> bool {
111 matches!(
112 self,
113 DEError::X0DimensionMismatch { .. } | DEError::IntegralityDimensionMismatch { .. }
114 )
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121
122 #[test]
123 fn test_error_display() {
124 let err = DEError::BoundsMismatch {
125 lower_len: 3,
126 upper_len: 5,
127 };
128 assert_eq!(
129 err.to_string(),
130 "bounds mismatch: lower has 3 elements, upper has 5"
131 );
132 }
133
134 #[test]
135 fn test_is_bounds_error() {
136 let bounds_err = DEError::BoundsMismatch {
137 lower_len: 1,
138 upper_len: 2,
139 };
140 let config_err = DEError::PopulationTooSmall { pop_size: 2 };
141
142 assert!(bounds_err.is_bounds_error());
143 assert!(!config_err.is_bounds_error());
144 }
145
146 #[test]
147 fn test_is_config_error() {
148 let config_err = DEError::InvalidCrossoverRate { rate: 1.5 };
149 let bounds_err = DEError::InvalidBounds {
150 index: 0,
151 lower: 5.0,
152 upper: 3.0,
153 };
154
155 assert!(config_err.is_config_error());
156 assert!(!bounds_err.is_config_error());
157 }
158
159 #[test]
160 fn test_is_dimension_error() {
161 let dim_err = DEError::X0DimensionMismatch {
162 expected: 10,
163 got: 5,
164 };
165 let bounds_err = DEError::BoundsMismatch {
166 lower_len: 1,
167 upper_len: 2,
168 };
169
170 assert!(dim_err.is_dimension_error());
171 assert!(!bounds_err.is_dimension_error());
172 }
173}