ellalgo_rs/
example3.rs

1use super::cutting_plane::{OracleFeas, OracleFeas2};
2use ndarray::prelude::*;
3
4type Arr = Array1<f64>;
5
6/// A struct representing a custom oracle for some optimization problem.
7///
8/// This oracle is used to evaluate the feasibility of a given solution.
9/// It keeps track of an index `idx` and a target value `target`.
10#[derive(Debug)]
11pub struct MyOracle3 {
12    /// The index of the current solution being evaluated.
13    pub idx: i32,
14    /// The target value for the optimization problem.
15    pub target: f64,
16}
17
18// impl MyOracle3 {
19//     /// Creates a new `MyOracle3` instance with the index set to 0 and the target value set to a very small negative number.
20//     #[inline]
21//     pub fn new() -> Self {
22//         MyOracle3 {
23//             idx: 0,
24//             target: -1e100,
25//         }
26//     }
27// }
28
29impl Default for MyOracle3 {
30    /// Creates a new `MyOracle3` instance with the index set to 0 and the target value set to a very small negative number.
31    ///
32    /// This is the default implementation for the `MyOracle3` struct, which is used to represent a custom oracle for some optimization problem.
33    /// The oracle is used to evaluate the feasibility of a given solution, and this default implementation initializes the index to 0 and the target value to a very small negative number.
34    #[inline]
35    fn default() -> Self {
36        MyOracle3 {
37            idx: -1,
38            target: -1e100,
39        }
40    }
41}
42
43impl OracleFeas<Arr> for MyOracle3 {
44    type CutChoice = f64; // single cut
45
46    /// The function assess_feas takes in an array xc and checks if it satisfies two constraints,
47    /// returning an optional tuple of an array and a float if any constraint is violated.
48    ///
49    /// Arguments:
50    ///
51    /// * `xc`: The parameter `xc` is an array of size 2, representing the coordinates of a point in a
52    ///         2-dimensional space. The first element `xc[0]` represents the x-coordinate, and the second
53    ///         element `xc[1]` represents the y-coordinate.
54    ///
55    /// Returns:
56    ///
57    /// The function `assess_feas` returns an `Option` containing a tuple `(Arr, f64)`.
58    fn assess_feas(&mut self, xc: &Arr) -> Option<(Arr, f64)> {
59        let x = xc[0];
60        let y = xc[1];
61
62        let num_constraints = 4;
63        for _ in 0..num_constraints {
64            self.idx += 1;
65            if self.idx == num_constraints {
66                self.idx = 0; // round robin
67            }
68            let fj = match self.idx {
69                0 => -x - 1.0,
70                1 => -y - 2.0,
71                2 => x + y - 1.0,
72                3 => 2.0 * x - 3.0 * y - self.target,
73                _ => unreachable!(),
74            };
75            if fj > 0.0 {
76                return Some((
77                    match self.idx {
78                        0 => array![-1.0, 0.0],
79                        1 => array![0.0, -1.0],
80                        2 => array![1.0, 1.0],
81                        3 => array![2.0, -3.0],
82                        _ => unreachable!(),
83                    },
84                    fj,
85                ));
86            }
87        }
88        None
89    }
90}
91
92impl OracleFeas2<Arr> for MyOracle3 {
93    fn update(&mut self, gamma: f64) {
94        self.target = gamma;
95    }
96}
97
98#[cfg(test)]
99mod tests {
100    use super::*;
101    use crate::cutting_plane::{bsearch, BSearchAdaptor, Options};
102    use crate::ell::Ell;
103    // use ndarray::array;
104    // use super::ell_stable::EllStable;
105
106    #[test]
107    pub fn test_feasible() {
108        let ellip = Ell::new_with_scalar(100.0, array![0.0, 0.0]);
109        let omega = MyOracle3::default();
110        let options = Options {
111            tolerance: 1e-8,
112            ..Default::default()
113        };
114        let mut adaptor = BSearchAdaptor::new(omega, ellip, options);
115        let mut intrvl = (-100.0, 100.0);
116        let options2 = Options {
117            tolerance: 1e-8,
118            ..Default::default()
119        };
120        let (feasible, num_iters) = bsearch(&mut adaptor, &mut intrvl, &options2);
121        assert!(feasible);
122        assert_eq!(num_iters, 34);
123    }
124}