ellalgo_rs/
example1.rs

1use super::cutting_plane::OracleOptim;
2use ndarray::prelude::*;
3
4type Arr = Array1<f64>;
5
6#[derive(Debug, Default)]
7pub struct MyOracle;
8
9impl OracleOptim<Arr> for MyOracle {
10    type CutChoice = f64; // single cut
11
12    /// The function assess_optim takes in two parameters, xc and gamma, and returns a tuple containing an
13    /// array and a double, along with a boolean value.
14    ///
15    /// Arguments:
16    ///
17    /// * `xc`: The parameter `xc` is an array of length 2, representing the values of `x` and `y`
18    ///         respectively.
19    /// * `gamma`: The parameter `gamma` is a mutable reference to a `f64` variable. It is used to store the
20    ///         current best solution for the optimization problem.
21    fn assess_optim(&mut self, xc: &Arr, gamma: &mut f64) -> ((Arr, f64), bool) {
22        let x = xc[0];
23        let y = xc[1];
24        let f0 = x + y;
25        let f1 = f0 - 3.0;
26        if f1 > 0.0 {
27            return ((array![1.0, 1.0], f1), false);
28        }
29        let f2 = -x + y + 1.0;
30        if f2 > 0.0 {
31            return ((array![-1.0, 1.0], f2), false);
32        }
33        let f3 = *gamma - f0;
34        if f3 > 0.0 {
35            return ((array![-1.0, -1.0], f3), false);
36        }
37        *gamma = f0;
38        ((array![-1.0, -1.0], 0.0), true)
39    }
40}
41
42#[cfg(test)]
43mod tests {
44    use super::*;
45    use crate::cutting_plane::{cutting_plane_optim, Options};
46    use crate::ell::Ell;
47    // use ndarray::array;
48    // use super::ell_stable::EllStable;
49
50    /// Tests the feasibility of the optimization problem using the cutting plane method.
51    ///
52    /// This test creates a new `Ell` instance with a scalar radius of 10.0 and a center at `[0.0, 0.0]`.
53    /// It then creates a new `MyOracle` instance as the optimization oracle.
54    /// The `gamma` variable is initialized to negative infinity.
55    /// The `Options` struct is configured with a tolerance of 1e-10.
56    /// The `cutting_plane_optim` function is called with the oracle, ellipsoid, gamma, and options.
57    /// The test asserts that the best solution `xbest` is not `None`, and that the number of iterations is 25.
58    #[test]
59    pub fn test_feasible() {
60        let mut ellip = Ell::new_with_scalar(10.0, array![0.0, 0.0]);
61        let mut oracle = MyOracle;
62        let mut gamma = f64::NEG_INFINITY;
63        let options = Options {
64            tolerance: 1e-10,
65            ..Default::default()
66        };
67        let (xbest, num_iters) = cutting_plane_optim(&mut oracle, &mut ellip, &mut gamma, &options);
68        assert!(xbest.is_some());
69        assert_eq!(num_iters, 25);
70    }
71
72    #[test]
73    pub fn test_infeasible1() {
74        let mut ellip = Ell::new(array![10.0, 10.0], array![100.0, 100.0]); // wrong initial guess
75                                                                            // or ellipsoid is too small
76        let mut oracle = MyOracle;
77        let mut gamma = f64::NEG_INFINITY;
78        let options = Options::default();
79        let (xbest, _num_iters) =
80            cutting_plane_optim(&mut oracle, &mut ellip, &mut gamma, &options);
81        assert!(xbest.is_none());
82    }
83
84    #[test]
85    pub fn test_infeasible2() {
86        let mut ellip = Ell::new(array![10.0, 10.0], array![0.0, 0.0]);
87        let mut oracle = MyOracle;
88        // wrong initial guess
89        let options = Options::default();
90        let (xbest, _niter) = cutting_plane_optim(&mut oracle, &mut ellip, &mut 100.0, &options);
91        assert!(xbest.is_none());
92    }
93}