1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
use super::Constraint; /// /// A finite set, `X = {x1, x2, ..., xn}`, where `xi` are given vectors /// of equal dimensions. /// pub struct FiniteSet { /// The data is stored in a Vec-of-Vec datatype, that is, a vector /// of vectors data: Vec<Vec<f64>>, } impl FiniteSet { /// Construct a finite set, `X = {x1, x2, ..., xn}`, given vectors /// `xi` of equal dimensions /// /// /// ### Parameters /// /// - data: vector of vectors (see example below) /// /// /// ### Example /// /// ``` /// use optimization_engine::constraints::*; /// /// let data: Vec<Vec<f64>> = vec![ /// vec![0.0, 0.0], /// vec![1.0, 1.0], /// vec![0.0, 1.0], /// vec![1.0, 0.0], /// ]; /// let finite_set = FiniteSet::new(data); /// ``` /// /// /// ### Panics /// /// This method will panic if (i) the given vector of data is empty /// and (ii) if the given vectors have unequal dimensions. /// pub fn new(data: Vec<Vec<f64>>) -> Self { // Do a sanity check... assert!(data.len() > 0, "empty data not allowed"); let n = data[0].len(); for v in data.iter() { assert!(n == v.len(), "inconsistent dimensions"); } FiniteSet { data: data } } } impl<'a> Constraint for FiniteSet { /// /// Projection on the current finite set /// /// Traverses the elements of the vector, computes norm-2 distances /// to each element, and updates the given vector `x` with the closest /// element from the finite set. /// /// /// ### Parameters /// /// - x: (input) given vector, (output) projection on finite set /// /// /// ### Example /// /// ``` /// use optimization_engine::constraints::*; /// /// let data: Vec<Vec<f64>> = vec![ /// vec![0.0, 0.0], /// vec![1.0, 1.0], /// ]; /// let finite_set = FiniteSet::new(data); /// let mut x = [0.7, 0.6]; /// finite_set.project(&mut x); // compute projection /// ``` /// /// ### Panics /// /// Does not panic /// fn project(&self, x: &mut [f64]) { let mut idx: usize = 0; let mut best_distance: f64 = num::Float::infinity(); for (i, v) in self.data.iter().enumerate() { let dist = crate::matrix_operations::norm2_squared_diff(v, x); if dist < best_distance { idx = i; best_distance = dist; } } x.copy_from_slice(&self.data[idx]); } }