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
72pub type Result<T> = std::result::Result<T, DEError>;
74
75impl DEError {
76 pub fn is_bounds_error(&self) -> bool {
80 matches!(
81 self,
82 DEError::BoundsMismatch { .. } | DEError::InvalidBounds { .. }
83 )
84 }
85
86 pub fn is_config_error(&self) -> bool {
91 matches!(
92 self,
93 DEError::PopulationTooSmall { .. }
94 | DEError::InvalidMutationFactor { .. }
95 | DEError::InvalidCrossoverRate { .. }
96 )
97 }
98
99 pub fn is_dimension_error(&self) -> bool {
103 matches!(
104 self,
105 DEError::X0DimensionMismatch { .. } | DEError::IntegralityDimensionMismatch { .. }
106 )
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113
114 #[test]
115 fn test_error_display() {
116 let err = DEError::BoundsMismatch {
117 lower_len: 3,
118 upper_len: 5,
119 };
120 assert_eq!(
121 err.to_string(),
122 "bounds mismatch: lower has 3 elements, upper has 5"
123 );
124 }
125
126 #[test]
127 fn test_is_bounds_error() {
128 let bounds_err = DEError::BoundsMismatch {
129 lower_len: 1,
130 upper_len: 2,
131 };
132 let config_err = DEError::PopulationTooSmall { pop_size: 2 };
133
134 assert!(bounds_err.is_bounds_error());
135 assert!(!config_err.is_bounds_error());
136 }
137
138 #[test]
139 fn test_is_config_error() {
140 let config_err = DEError::InvalidCrossoverRate { rate: 1.5 };
141 let bounds_err = DEError::InvalidBounds {
142 index: 0,
143 lower: 5.0,
144 upper: 3.0,
145 };
146
147 assert!(config_err.is_config_error());
148 assert!(!bounds_err.is_config_error());
149 }
150
151 #[test]
152 fn test_is_dimension_error() {
153 let dim_err = DEError::X0DimensionMismatch {
154 expected: 10,
155 got: 5,
156 };
157 let bounds_err = DEError::BoundsMismatch {
158 lower_len: 1,
159 upper_len: 2,
160 };
161
162 assert!(dim_err.is_dimension_error());
163 assert!(!bounds_err.is_dimension_error());
164 }
165}