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