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