ellalgo_rs/
example1.rs

1use super::cutting_plane::OracleOptim;
2use ndarray::prelude::*;
3
4type Arr = Array1<f64>;
5
6#[derive(Debug)]
7pub struct MyOracle {}
8
9impl OracleOptim<Arr> for MyOracle {
10    type CutChoices = f64; // single cut
11
12    /// The function assess_optim takes in two parameters, z and gamma, and returns a tuple containing an
13    /// array and a double, along with a boolean value.
14    ///
15    /// Arguments:
16    ///
17    /// * `z`: The parameter `z` 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, z: &Arr, gamma: &mut f64) -> ((Arr, f64), bool) {
22        let x = z[0];
23        let y = z[1];
24
25        // constraint 1: x + y <= 3
26        let fj = x + y - 3.0;
27        if fj > 0.0 {
28            return ((array![1.0, 1.0], fj), false);
29        }
30        // constraint 2: x - y >= 1
31        let fj = -x + y + 1.0;
32        if fj > 0.0 {
33            return ((array![-1.0, 1.0], fj), false);
34        }
35        // objective: maximize x + y
36        let f0 = x + y;
37        let fj = *gamma - f0;
38        if fj < 0.0 {
39            *gamma = f0;
40            return ((array![-1.0, -1.0], 0.0), true);
41        }
42        ((array![-1.0, -1.0], fj), false)
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49    use crate::cutting_plane::{cutting_plane_optim, Options};
50    use crate::ell::Ell;
51    // use ndarray::array;
52    // use super::ell_stable::EllStable;
53
54    #[test]
55    pub fn test_feasible() {
56        let mut ell = Ell::new(array![10.0, 10.0], array![0.0, 0.0]);
57        let mut oracle = MyOracle {};
58        let mut gamma = -1.0e100; // std::numeric_limits<double>::min()
59        let options = Options {
60            max_iters: 2000,
61            tol: 1e-10,
62        };
63        let (x_opt, _niter) = cutting_plane_optim(&mut oracle, &mut ell, &mut gamma, &options);
64        assert!(x_opt.is_some());
65        if let Some(x) = x_opt {
66            assert!(x[0] >= 0.0);
67        }
68    }
69
70    #[test]
71    pub fn test_infeasible1() {
72        let mut ell = Ell::new(array![10.0, 10.0], array![100.0, 100.0]); // wrong initial guess
73                                                                          // or ellipsoid is too small
74        let mut oracle = MyOracle {};
75        let mut gamma = -1.0e100; // std::numeric_limits<double>::min()
76        let options = Options {
77            max_iters: 2000,
78            tol: 1e-12,
79        };
80        let (x_opt, _niter) = cutting_plane_optim(&mut oracle, &mut ell, &mut gamma, &options);
81        assert_eq!(x_opt, None);
82    }
83
84    #[test]
85    pub fn test_infeasible2() {
86        let mut ell = 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 {
90            max_iters: 2000,
91            tol: 1e-12,
92        };
93        let (x_opt, _niter) = cutting_plane_optim(&mut oracle, &mut ell, &mut 100.0, &options);
94        assert_eq!(x_opt, None);
95    }
96}