conspire/math/optimize/
mod.rs

1#[cfg(test)]
2mod test;
3
4mod constraint;
5mod gradient_descent;
6mod line_search;
7mod newton_raphson;
8
9pub use constraint::EqualityConstraint;
10pub use gradient_descent::GradientDescent;
11pub use line_search::LineSearch;
12pub use newton_raphson::NewtonRaphson;
13
14use crate::{
15    defeat_message,
16    math::{
17        TestError,
18        integrate::IntegrationError,
19        matrix::square::{Banded, SquareMatrixError},
20    },
21};
22use std::fmt::{self, Debug, Display, Formatter};
23
24/// Zeroth-order root-finding algorithms.
25pub trait ZerothOrderRootFinding<X> {
26    fn root(
27        &self,
28        function: impl Fn(&X) -> Result<X, OptimizeError>,
29        initial_guess: X,
30        equality_constraint: EqualityConstraint,
31    ) -> Result<X, OptimizeError>;
32}
33
34/// First-order root-finding algorithms.
35pub trait FirstOrderRootFinding<F, J, X> {
36    fn root(
37        &self,
38        function: impl Fn(&X) -> Result<F, OptimizeError>,
39        jacobian: impl Fn(&X) -> Result<J, OptimizeError>,
40        initial_guess: X,
41        equality_constraint: EqualityConstraint,
42    ) -> Result<X, OptimizeError>;
43}
44
45/// First-order optimization algorithms.
46pub trait FirstOrderOptimization<F, X> {
47    fn minimize(
48        &self,
49        function: impl Fn(&X) -> Result<F, OptimizeError>,
50        jacobian: impl Fn(&X) -> Result<X, OptimizeError>,
51        initial_guess: X,
52        equality_constraint: EqualityConstraint,
53    ) -> Result<X, OptimizeError>;
54}
55
56/// Second-order optimization algorithms.
57pub trait SecondOrderOptimization<F, J, H, X> {
58    fn minimize(
59        &self,
60        function: impl Fn(&X) -> Result<F, OptimizeError>,
61        jacobian: impl Fn(&X) -> Result<J, OptimizeError>,
62        hessian: impl Fn(&X) -> Result<H, OptimizeError>,
63        initial_guess: X,
64        equality_constraint: EqualityConstraint,
65        banded: Option<Banded>,
66    ) -> Result<X, OptimizeError>;
67}
68
69/// Possible errors encountered when optimizing.
70pub enum OptimizeError {
71    Generic(String),
72    MaximumStepsReached(usize, String),
73    NotMinimum(String, String),
74    SingularMatrix,
75}
76
77impl From<OptimizeError> for TestError {
78    fn from(error: OptimizeError) -> Self {
79        Self {
80            message: error.to_string(),
81        }
82    }
83}
84
85impl From<IntegrationError> for OptimizeError {
86    fn from(_error: IntegrationError) -> Self {
87        todo!()
88    }
89}
90
91impl From<SquareMatrixError> for OptimizeError {
92    fn from(_error: SquareMatrixError) -> Self {
93        Self::SingularMatrix
94    }
95}
96
97impl Debug for OptimizeError {
98    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
99        let error = match self {
100            Self::Generic(message) => message.to_string(),
101            Self::MaximumStepsReached(steps, solver) => {
102                format!(
103                    "\x1b[1;91mMaximum number of steps ({steps}) reached.\x1b[0;91m\n\
104                     In solver: {solver}."
105                )
106            }
107            Self::NotMinimum(solution, solver) => {
108                format!(
109                    "\x1b[1;91mThe obtained solution is not a minimum.\x1b[0;91m\n\
110                     For solution: {solution}.\n\
111                     In solver: {solver}."
112                )
113            }
114            Self::SingularMatrix => "\x1b[1;91mMatrix is singular.".to_string(),
115        };
116        write!(f, "\n{error}\n\x1b[0;2;31m{}\x1b[0m\n", defeat_message())
117    }
118}
119
120impl Display for OptimizeError {
121    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
122        let error = match self {
123            Self::Generic(message) => message.to_string(),
124            Self::MaximumStepsReached(steps, solver) => {
125                format!(
126                    "\x1b[1;91mMaximum number of steps ({steps}) reached.\x1b[0;91m\n\
127                     In solver: {solver}."
128                )
129            }
130            Self::NotMinimum(solution, solver) => {
131                format!(
132                    "\x1b[1;91mThe obtained solution is not a minimum.\x1b[0;91m\n\
133                     For solution: {solution}.\n\
134                     In solver: {solver}."
135                )
136            }
137            Self::SingularMatrix => "\x1b[1;91mMatrix is singular.".to_string(),
138        };
139        write!(f, "{error}\x1b[0m")
140    }
141}