| |
1 //! Implementation of the linear function |
| |
2 |
| |
3 use numeric_literals::replace_float_literals; |
| |
4 use serde::Serialize; |
| |
5 use alg_tools::types::*; |
| |
6 use alg_tools::norms::*; |
| |
7 use alg_tools::loc::Loc; |
| |
8 use alg_tools::sets::Cube; |
| |
9 use alg_tools::bisection_tree::{ |
| |
10 Support, |
| |
11 Bounds, |
| |
12 LocalAnalysis, |
| |
13 GlobalAnalysis, |
| |
14 Bounded, |
| |
15 }; |
| |
16 use alg_tools::mapping::{Mapping, Instance}; |
| |
17 use alg_tools::maputil::array_init; |
| |
18 use alg_tools::euclidean::Euclidean; |
| |
19 |
| |
20 /// Representation of the hat function $f(x)=1-\\|x\\|\_1/ε$ of `width` $ε$ on $ℝ^N$. |
| |
21 #[derive(Copy,Clone,Serialize,Debug,Eq,PartialEq)] |
| |
22 pub struct Linear<F : Float, const N : usize> { |
| |
23 /// The parameter $ε>0$. |
| |
24 pub v : Loc<F, N>, |
| |
25 } |
| |
26 |
| |
27 #[replace_float_literals(F::cast_from(literal))] |
| |
28 impl<F : Float, const N : usize> Mapping<Loc<F, N>> for Linear<F, N> { |
| |
29 type Codomain = F; |
| |
30 |
| |
31 #[inline] |
| |
32 fn apply<I : Instance<Loc<F, N>>>(&self, x : I) -> Self::Codomain { |
| |
33 x.eval(|x| self.v.dot(x)) |
| |
34 } |
| |
35 } |
| |
36 |
| |
37 |
| |
38 #[replace_float_literals(F::cast_from(literal))] |
| |
39 impl<'a, F : Float, const N : usize> Support<F, N> for Linear<F, N> { |
| |
40 #[inline] |
| |
41 fn support_hint(&self) -> Cube<F,N> { |
| |
42 array_init(|| [F::NEG_INFINITY, F::INFINITY]).into() |
| |
43 } |
| |
44 |
| |
45 #[inline] |
| |
46 fn in_support(&self, _x : &Loc<F,N>) -> bool { |
| |
47 true |
| |
48 } |
| |
49 |
| |
50 /*fn fully_in_support(&self, _cube : &Cube<F,N>) -> bool { |
| |
51 todo!("Not implemented, but not used at the moment") |
| |
52 }*/ |
| |
53 |
| |
54 #[inline] |
| |
55 fn bisection_hint(&self, _cube : &Cube<F,N>) -> [Option<F>; N] { |
| |
56 [None; N] |
| |
57 } |
| |
58 } |
| |
59 |
| |
60 |
| |
61 #[replace_float_literals(F::cast_from(literal))] |
| |
62 impl<'a, F : Float, const N : usize> |
| |
63 GlobalAnalysis<F, Bounds<F>> |
| |
64 for Linear<F, N> { |
| |
65 #[inline] |
| |
66 fn global_analysis(&self) -> Bounds<F> { |
| |
67 Bounds(F::NEG_INFINITY, F::INFINITY) |
| |
68 } |
| |
69 } |
| |
70 |
| |
71 impl<'a, F : Float, const N : usize> |
| |
72 LocalAnalysis<F, Bounds<F>, N> |
| |
73 for Linear<F, N> { |
| |
74 #[inline] |
| |
75 fn local_analysis(&self, cube : &Cube<F, N>) -> Bounds<F> { |
| |
76 let (lower, upper) = cube.iter_corners() |
| |
77 .map(|x| self.apply(x)) |
| |
78 .fold((F::INFINITY, F::NEG_INFINITY), |(lower, upper), v| { |
| |
79 (lower.min(v), upper.max(v)) |
| |
80 }); |
| |
81 Bounds(lower, upper) |
| |
82 } |
| |
83 } |
| |
84 |
| |
85 #[replace_float_literals(F::cast_from(literal))] |
| |
86 impl<'a, F : Float, const N : usize> |
| |
87 Norm<F, Linfinity> |
| |
88 for Linear<F, N> { |
| |
89 #[inline] |
| |
90 fn norm(&self, _ : Linfinity) -> F { |
| |
91 self.bounds().upper() |
| |
92 } |
| |
93 } |
| |
94 |