ellalgo_rs/quasicvx.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 fn default() -> Self {
13 MyOracle { idx: -1 }
14 }
15}
16
17impl OracleOptim<Arr> for MyOracle {
18 type CutChoice = f64; // single cut
19
20 /// The function assesses optimization based on input values and returns a tuple along with a
21 /// boolean flag.
22 ///
23 /// Arguments:
24 ///
25 /// * `xc`: The `xc` parameter in the `assess_optim` function represents an array containing two
26 /// elements. The first element, `xc[0]`, is assigned to the variable `sqrtx`, and the second
27 /// element, `xc[1]`, is assigned to the variable `logy`. These
28 /// * `gamma`: The `gamma` parameter is a mutable reference to a `f64` value. It is being updated
29 /// within the `assess_optim` function based on the calculations performed on the input values `xc`
30 /// and the internal state of the function.
31 fn assess_optim(&mut self, xc: &Arr, gamma: &mut f64) -> ((Arr, f64), bool) {
32 let sqrtx = xc[0];
33 let logy = xc[1];
34
35 let num_constraints = 2;
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 => sqrtx * sqrtx - logy,
43 1 => -sqrtx + *gamma * logy.exp(),
44 _ => unreachable!(),
45 };
46 if fj > 0.0 {
47 return (
48 (
49 match self.idx {
50 0 => array![2.0 * sqrtx, -1.0],
51 1 => array![-1.0, *gamma * logy.exp()],
52 _ => unreachable!(),
53 },
54 fj,
55 ),
56 false,
57 );
58 }
59 }
60 *gamma = sqrtx / logy.exp();
61 ((array![-1.0, sqrtx], 0.0), true)
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::MyOracle;
68 use crate::cutting_plane::{cutting_plane_optim, Options};
69 use crate::ell::Ell;
70 // use crate::ell_stable::EllStable;
71 use ndarray::array;
72
73 #[test]
74 pub fn test_feasible() {
75 let mut ell = Ell::new(array![10.0, 10.0], array![0.0, 0.0]);
76 let mut oracle = MyOracle::default();
77 let mut gamma = 0.0;
78 let options = Options {
79 max_iters: 2000,
80 tolerance: 1e-8,
81 };
82 let (x_opt, num_iters) = cutting_plane_optim(&mut oracle, &mut ell, &mut gamma, &options);
83 assert!(x_opt.is_some());
84 if let Some(x) = x_opt {
85 assert!(x[0] * x[0] >= 0.49 && x[0] * x[0] <= 0.51);
86 assert!(x[1].exp() >= 1.6 && x[1].exp() <= 1.7);
87 }
88 assert_eq!(num_iters, 35);
89 }
90
91 // #[test]
92 // pub fn test_feasible_stable() {
93 // let mut ell = EllStable::new(array![10.0, 10.0], array![0.0, 0.0]);
94 // let mut oracle = MyOracle::default();
95 // let mut gamma = 0.0;
96 // let options = Options {
97 // max_iters: 2000,
98 // tolerance: 1e-8,
99 // };
100 // let (x_opt, num_iters) = cutting_plane_optim(&mut oracle, &mut ell, &mut gamma, &options);
101 // assert!(x_opt.is_some());
102 // if let Some(x) = x_opt {
103 // assert!(x[0] * x[0] >= 0.49 && x[0] * x[0] <= 0.51);
104 // assert!(x[1].exp() >= 1.6 && x[1].exp() <= 1.7);
105 // }
106 // assert_eq!(num_iters, 35);
107 // }
108}