|
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 |