Thanks to visit codestin.com
Credit goes to docs.rs

optimization_engine/constraints/
halfspace.rs

1use super::Constraint;
2use crate::matrix_operations;
3
4#[derive(Clone)]
5/// A halfspace is a set given by $H = \\{x \in \mathbb{R}^n {}:{} \langle c, x\rangle \leq b\\}$.
6pub struct Halfspace<'a> {
7    /// normal vector
8    normal_vector: &'a [f64],
9    /// offset
10    offset: f64,
11    /// squared Euclidean norm of the normal vector (computed once upon construction)
12    normal_vector_squared_norm: f64,
13}
14
15impl<'a> Halfspace<'a> {
16    /// A halfspace is a set given by $H = \\{x \in \mathbb{R}^n {}:{} \langle c, x\rangle \leq b\\}$,
17    /// where $c$ is the normal vector of the halfspace and $b$ is an offset.
18    ///
19    /// This method constructs a new instance of `Halfspace` with a given normal
20    /// vector and bias
21    ///
22    /// # Arguments
23    ///
24    /// - `normal_vector`: the normal vector, $c$, as a slice
25    /// - `offset`: the offset parameter, $b$
26    ///
27    /// # Returns
28    ///
29    /// New instance of `Halfspace`
30    ///
31    /// # Panics
32    ///
33    /// Does not panic. Note: it does not panic if you provide an empty slice as `normal_vector`,
34    /// but you should avoid doing that.
35    ///
36    /// # Example
37    ///
38    /// ```
39    /// use optimization_engine::constraints::{Constraint, Halfspace};
40    ///
41    /// let normal_vector = [1., 2.];
42    /// let offset = 1.0;
43    /// let halfspace = Halfspace::new(&normal_vector, offset);
44    /// let mut x = [-1., 3.];
45    /// halfspace.project(&mut x);
46    /// ```
47    ///
48    pub fn new(normal_vector: &'a [f64], offset: f64) -> Self {
49        let normal_vector_squared_norm = matrix_operations::norm2_squared(normal_vector);
50        Halfspace {
51            normal_vector,
52            offset,
53            normal_vector_squared_norm,
54        }
55    }
56}
57
58impl<'a> Constraint for Halfspace<'a> {
59    /// Projects on halfspace using the following formula:
60    ///
61    /// $$\begin{aligned}
62    /// \mathrm{proj}_{H}(x) = \begin{cases}
63    /// x,& \text{ if } \langle c, x\rangle \leq b
64    /// \\\\
65    /// x - \frac{\langle c, x\rangle - b}
66    ///          {\\|c\\|}c,& \text{else}
67    /// \end{cases}
68    /// \end{aligned}$$
69    ///
70    /// where $H = \\{x \in \mathbb{R}^n {}:{} \langle c, x\rangle \leq b\\}$
71    ///
72    /// # Arguments
73    ///
74    /// - `x`: (in) vector to be projected on the current instance of a halfspace,
75    ///    (out) projection on the second-order cone
76    ///
77    /// # Panics
78    ///
79    /// This method panics if the length of `x` is not equal to the dimension
80    /// of the halfspace.
81    ///
82    fn project(&self, x: &mut [f64]) {
83        let inner_product = matrix_operations::inner_product(x, self.normal_vector);
84        if inner_product > self.offset {
85            let factor = (inner_product - self.offset) / self.normal_vector_squared_norm;
86            x.iter_mut()
87                .zip(self.normal_vector.iter())
88                .for_each(|(x, normal_vector_i)| *x -= factor * normal_vector_i);
89        }
90    }
91
92    /// Halfspaces are convex sets
93    ///
94    /// # Returns
95    ///
96    /// Returns `true`
97    fn is_convex(&self) -> bool {
98        true
99    }
100}