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}