src/kernels/hat.rs

changeset 0
eb3c7813b67a
equal deleted inserted replaced
-1:000000000000 0:eb3c7813b67a
1 //! Implementation of the hat 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 Constant,
12 Bounds,
13 LocalAnalysis,
14 GlobalAnalysis,
15 Bounded,
16 };
17 use alg_tools::mapping::Apply;
18 use alg_tools::maputil::{array_init};
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 Hat<C : Constant, const N : usize> {
23 /// The parameter $ε>0$.
24 pub width : C,
25 }
26
27 #[replace_float_literals(C::Type::cast_from(literal))]
28 impl<'a, C : Constant, const N : usize> Apply<&'a Loc<C::Type, N>> for Hat<C, N> {
29 type Output = C::Type;
30 #[inline]
31 fn apply(&self, x : &'a Loc<C::Type, N>) -> Self::Output {
32 let ε = self.width.value();
33 0.0.max(1.0-x.norm(L1)/ε)
34 }
35 }
36
37 #[replace_float_literals(C::Type::cast_from(literal))]
38 impl<C : Constant, const N : usize> Apply<Loc<C::Type, N>> for Hat<C, N> {
39 type Output = C::Type;
40 #[inline]
41 fn apply(&self, x : Loc<C::Type, N>) -> Self::Output {
42 self.apply(&x)
43 }
44 }
45
46
47 #[replace_float_literals(C::Type::cast_from(literal))]
48 impl<'a, C : Constant, const N : usize> Support<C::Type, N> for Hat<C, N> {
49 #[inline]
50 fn support_hint(&self) -> Cube<C::Type,N> {
51 let ε = self.width.value();
52 array_init(|| [-ε, ε]).into()
53 }
54
55 #[inline]
56 fn in_support(&self, x : &Loc<C::Type,N>) -> bool {
57 x.norm(L1) < self.width.value()
58 }
59
60 /*fn fully_in_support(&self, _cube : &Cube<C::Type,N>) -> bool {
61 todo!("Not implemented, but not used at the moment")
62 }*/
63
64 #[inline]
65 fn bisection_hint(&self, cube : &Cube<C::Type,N>) -> [Option<C::Type>; N] {
66 let ε = self.width.value();
67 cube.map(|a, b| {
68 if a < 1.0 {
69 if 1.0 < b {
70 Some(1.0)
71 } else {
72 if a < -ε {
73 if b > -ε { Some(-ε) } else { None }
74 } else {
75 None
76 }
77 }
78 } else {
79 if b > ε { Some(ε) } else { None }
80 }
81 });
82 todo!("also diagonals")
83 }
84 }
85
86
87 #[replace_float_literals(C::Type::cast_from(literal))]
88 impl<'a, C : Constant, const N : usize>
89 GlobalAnalysis<C::Type, Bounds<C::Type>>
90 for Hat<C, N> {
91 #[inline]
92 fn global_analysis(&self) -> Bounds<C::Type> {
93 Bounds(0.0, 1.0)
94 }
95 }
96
97 impl<'a, C : Constant, const N : usize>
98 LocalAnalysis<C::Type, Bounds<C::Type>, N>
99 for Hat<C, N> {
100 #[inline]
101 fn local_analysis(&self, cube : &Cube<C::Type, N>) -> Bounds<C::Type> {
102 // The function is maximised/minimised where the 1-norm is minimised/maximised.
103 let lower = self.apply(cube.maxnorm_point());
104 let upper = self.apply(cube.minnorm_point());
105 Bounds(lower, upper)
106 }
107 }
108
109 #[replace_float_literals(C::Type::cast_from(literal))]
110 impl<'a, C : Constant, const N : usize>
111 Norm<C::Type, Linfinity>
112 for Hat<C, N> {
113 #[inline]
114 fn norm(&self, _ : Linfinity) -> C::Type {
115 self.bounds().upper()
116 }
117 }
118

mercurial