1use pounce_common::types::Index;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13#[repr(i32)]
14pub enum ApplicationReturnStatus {
15 SolveSucceeded = 0,
16 SolvedToAcceptableLevel = 1,
17 InfeasibleProblemDetected = 2,
18 SearchDirectionBecomesTooSmall = 3,
19 DivergingIterates = 4,
20 UserRequestedStop = 5,
21 FeasiblePointFound = 6,
22
23 MaximumIterationsExceeded = -1,
24 RestorationFailed = -2,
25 ErrorInStepComputation = -3,
26 MaximumCpuTimeExceeded = -4,
27 MaximumWallTimeExceeded = -5,
28
29 NotEnoughDegreesOfFreedom = -10,
30 InvalidProblemDefinition = -11,
31 InvalidOption = -12,
32 InvalidNumberDetected = -13,
33
34 UnrecoverableException = -100,
35 NonIpoptExceptionThrown = -101,
36 InsufficientMemory = -102,
37 InternalError = -199,
38}
39
40impl ApplicationReturnStatus {
41 pub fn as_int(self) -> Index {
42 self as Index
43 }
44
45 pub fn upstream_name(self) -> &'static str {
56 match self {
57 Self::SolveSucceeded => "Solve_Succeeded",
58 Self::SolvedToAcceptableLevel => "Solved_To_Acceptable_Level",
59 Self::InfeasibleProblemDetected => "Infeasible_Problem_Detected",
60 Self::SearchDirectionBecomesTooSmall => "Search_Direction_Becomes_Too_Small",
61 Self::DivergingIterates => "Diverging_Iterates",
62 Self::UserRequestedStop => "User_Requested_Stop",
63 Self::FeasiblePointFound => "Feasible_Point_Found",
64 Self::MaximumIterationsExceeded => "Maximum_Iterations_Exceeded",
65 Self::RestorationFailed => "Restoration_Failed",
66 Self::ErrorInStepComputation => "Error_In_Step_Computation",
67 Self::MaximumCpuTimeExceeded => "Maximum_CpuTime_Exceeded",
68 Self::MaximumWallTimeExceeded => "Maximum_WallTime_Exceeded",
69 Self::NotEnoughDegreesOfFreedom => "Not_Enough_Degrees_Of_Freedom",
70 Self::InvalidProblemDefinition => "Invalid_Problem_Definition",
71 Self::InvalidOption => "Invalid_Option",
72 Self::InvalidNumberDetected => "Invalid_Number_Detected",
73 Self::UnrecoverableException => "Unrecoverable_Exception",
74 Self::NonIpoptExceptionThrown => "NonIpopt_Exception_Thrown",
75 Self::InsufficientMemory => "Insufficient_Memory",
76 Self::InternalError => "Internal_Error",
77 }
78 }
79}
80
81#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
83#[repr(i32)]
84pub enum AlgorithmMode {
85 RegularMode = 0,
86 RestorationPhaseMode = 1,
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
96 fn integer_values_match_upstream() {
97 assert_eq!(ApplicationReturnStatus::SolveSucceeded.as_int(), 0);
98 assert_eq!(ApplicationReturnStatus::SolvedToAcceptableLevel.as_int(), 1);
99 assert_eq!(
100 ApplicationReturnStatus::InfeasibleProblemDetected.as_int(),
101 2
102 );
103 assert_eq!(
104 ApplicationReturnStatus::SearchDirectionBecomesTooSmall.as_int(),
105 3
106 );
107 assert_eq!(ApplicationReturnStatus::DivergingIterates.as_int(), 4);
108 assert_eq!(ApplicationReturnStatus::UserRequestedStop.as_int(), 5);
109 assert_eq!(ApplicationReturnStatus::FeasiblePointFound.as_int(), 6);
110
111 assert_eq!(
112 ApplicationReturnStatus::MaximumIterationsExceeded.as_int(),
113 -1
114 );
115 assert_eq!(ApplicationReturnStatus::RestorationFailed.as_int(), -2);
116 assert_eq!(ApplicationReturnStatus::ErrorInStepComputation.as_int(), -3);
117 assert_eq!(ApplicationReturnStatus::MaximumCpuTimeExceeded.as_int(), -4);
118 assert_eq!(
119 ApplicationReturnStatus::MaximumWallTimeExceeded.as_int(),
120 -5
121 );
122
123 assert_eq!(
124 ApplicationReturnStatus::NotEnoughDegreesOfFreedom.as_int(),
125 -10
126 );
127 assert_eq!(
128 ApplicationReturnStatus::InvalidProblemDefinition.as_int(),
129 -11
130 );
131 assert_eq!(ApplicationReturnStatus::InvalidOption.as_int(), -12);
132 assert_eq!(ApplicationReturnStatus::InvalidNumberDetected.as_int(), -13);
133
134 assert_eq!(
135 ApplicationReturnStatus::UnrecoverableException.as_int(),
136 -100
137 );
138 assert_eq!(
139 ApplicationReturnStatus::NonIpoptExceptionThrown.as_int(),
140 -101
141 );
142 assert_eq!(ApplicationReturnStatus::InsufficientMemory.as_int(), -102);
143 assert_eq!(ApplicationReturnStatus::InternalError.as_int(), -199);
144
145 assert_eq!(AlgorithmMode::RegularMode as i32, 0);
146 assert_eq!(AlgorithmMode::RestorationPhaseMode as i32, 1);
147 }
148
149 const ALL_STATUSES: [ApplicationReturnStatus; 20] = [
150 ApplicationReturnStatus::SolveSucceeded,
151 ApplicationReturnStatus::SolvedToAcceptableLevel,
152 ApplicationReturnStatus::InfeasibleProblemDetected,
153 ApplicationReturnStatus::SearchDirectionBecomesTooSmall,
154 ApplicationReturnStatus::DivergingIterates,
155 ApplicationReturnStatus::UserRequestedStop,
156 ApplicationReturnStatus::FeasiblePointFound,
157 ApplicationReturnStatus::MaximumIterationsExceeded,
158 ApplicationReturnStatus::RestorationFailed,
159 ApplicationReturnStatus::ErrorInStepComputation,
160 ApplicationReturnStatus::MaximumCpuTimeExceeded,
161 ApplicationReturnStatus::MaximumWallTimeExceeded,
162 ApplicationReturnStatus::NotEnoughDegreesOfFreedom,
163 ApplicationReturnStatus::InvalidProblemDefinition,
164 ApplicationReturnStatus::InvalidOption,
165 ApplicationReturnStatus::InvalidNumberDetected,
166 ApplicationReturnStatus::UnrecoverableException,
167 ApplicationReturnStatus::NonIpoptExceptionThrown,
168 ApplicationReturnStatus::InsufficientMemory,
169 ApplicationReturnStatus::InternalError,
170 ];
171
172 #[test]
177 fn upstream_names_match_upstream_spelling() {
178 assert_eq!(
179 ApplicationReturnStatus::SolveSucceeded.upstream_name(),
180 "Solve_Succeeded"
181 );
182 assert_eq!(
183 ApplicationReturnStatus::InfeasibleProblemDetected.upstream_name(),
184 "Infeasible_Problem_Detected"
185 );
186 assert_eq!(
187 ApplicationReturnStatus::MaximumIterationsExceeded.upstream_name(),
188 "Maximum_Iterations_Exceeded"
189 );
190 assert_eq!(
193 ApplicationReturnStatus::MaximumCpuTimeExceeded.upstream_name(),
194 "Maximum_CpuTime_Exceeded"
195 );
196 assert_eq!(
197 ApplicationReturnStatus::NonIpoptExceptionThrown.upstream_name(),
198 "NonIpopt_Exception_Thrown"
199 );
200 }
201
202 #[test]
207 fn upstream_names_are_debug_names_with_separators() {
208 for status in ALL_STATUSES {
209 assert_eq!(
210 status.upstream_name().replace('_', ""),
211 format!("{status:?}"),
212 "upstream name for {status:?} is not its Debug name with separators",
213 );
214 }
215 }
216
217 #[test]
220 fn upstream_names_are_unique() {
221 let mut names: Vec<&str> = ALL_STATUSES.iter().map(|s| s.upstream_name()).collect();
222 names.sort_unstable();
223 let before = names.len();
224 names.dedup();
225 assert_eq!(before, names.len(), "duplicate upstream status name");
226 }
227}