cobyla_argmin/
lib.rs

1#![doc = include_str!("../README.md")]
2
3mod cobyla;
4mod cobyla_solver;
5mod cobyla_state;
6pub use crate::cobyla_solver::*;
7pub use crate::cobyla_state::*;
8
9/// Failed termination status of the optimization process
10#[derive(Debug, Clone, Copy)]
11pub enum FailStatus {
12    Failure,
13    InvalidArgs,
14    OutOfMemory,
15    RoundoffLimited,
16    ForcedStop,
17    UnexpectedError,
18}
19
20/// Successful termination status of the optimization process
21#[derive(Debug, Clone, Copy)]
22pub enum SuccessStatus {
23    Success,
24    StopValReached,
25    FtolReached,
26    XtolReached,
27    MaxEvalReached,
28    MaxTimeReached,
29}
30
31/// Tolerances used as termination criteria.
32/// For all, condition is disabled if value is not strictly positive.
33/// ```rust
34/// # use crate::cobyla_argmin::StopTols;
35/// let stop_tol = StopTols {
36///     ftol_rel: 1e-4,
37///     xtol_abs: vec![1e-3; 3],   // size should be equal to x dim
38///     ..StopTols::default()      // default stop conditions are disabled
39/// };  
40/// ```
41#[derive(Debug, Clone, Default)]
42pub struct StopTols {
43    /// Relative tolerance on function value, algorithm stops when `func(x)` changes by less than `ftol_rel * func(x)`
44    pub ftol_rel: f64,
45    /// Absolute tolerance on function value, algorithm stops when `func(x)` change is less than `ftol_rel`
46    pub ftol_abs: f64,
47    /// Relative tolerance on optimization parameters, algorithm stops when all `x[i]` changes by less than `xtol_rel * x[i]`
48    pub xtol_rel: f64,
49    /// Relative tolerance on optimization parameters, algorithm stops when `x[i]` changes by less than `xtol_abs[i]`
50    pub xtol_abs: Vec<f64>,
51}
52
53/// An enum for specifying the initial change of x which correspond to the `rhobeg`
54/// argument of the original Powell's algorithm (hence the name)
55pub enum RhoBeg {
56    /// Used when all x components changes are specified with a single given value
57    All(f64),
58    /// Used to set the components with the given x-dim-sized vector
59    Set(Vec<f64>),
60}
61
62#[cfg(test)]
63mod tests {
64    use crate::CobylaSolver;
65    use approx::assert_abs_diff_eq;
66    use argmin::core::{CostFunction, Error, Executor, State};
67
68    /// Problem cost function
69    fn paraboloid(x: &[f64], _data: &mut ()) -> f64 {
70        10. * (x[0] + 1.).powf(2.) + x[1].powf(2.)
71    }
72
73    /// Problem Definition for CobylaSolver : minimize paraboloid(x) subject to x0 >= 0
74    struct ParaboloidProblem;
75
76    impl CostFunction for ParaboloidProblem {
77        type Param = Vec<f64>;
78        type Output = Vec<f64>;
79
80        fn cost(&self, x: &Self::Param) -> Result<Self::Output, Error> {
81            let fx = paraboloid(x, &mut ());
82            Ok(vec![fx, x[0]])
83        }
84    }
85
86    #[test]
87    fn test_paraboloid() {
88        let problem = ParaboloidProblem;
89        let solver = CobylaSolver::new(vec![1., 1.]);
90
91        let res = Executor::new(problem, solver)
92            .timer(true)
93            .configure(|state| state.max_iters(100).iprint(0))
94            .run()
95            .unwrap();
96
97        assert_abs_diff_eq!(0., res.state().get_best_param().unwrap()[0], epsilon = 1e-2);
98        assert_abs_diff_eq!(0., res.state().get_best_param().unwrap()[1], epsilon = 1e-2);
99        assert_abs_diff_eq!(10., res.state().get_best_cost(), epsilon = 1e-2);
100    }
101}