Mon, 06 Jan 2025 21:37:03 -0500
Attempt to do more Serialize / Deserialize but run into csv problems
| 0 | 1 | //! Implementation of the hat function |
| 2 | ||
| 3 | use numeric_literals::replace_float_literals; | |
|
38
0f59c0d02e13
Attempt to do more Serialize / Deserialize but run into csv problems
Tuomo Valkonen <tuomov@iki.fi>
parents:
35
diff
changeset
|
4 | use serde::{Serialize, Deserialize}; |
| 0 | 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 | }; | |
| 35 | 17 | use alg_tools::mapping::{Mapping, Instance}; |
| 18 | use alg_tools::maputil::array_init; | |
| 19 | use crate::types::Lipschitz; | |
| 0 | 20 | |
| 21 | /// Representation of the hat function $f(x)=1-\\|x\\|\_1/ε$ of `width` $ε$ on $ℝ^N$. | |
|
38
0f59c0d02e13
Attempt to do more Serialize / Deserialize but run into csv problems
Tuomo Valkonen <tuomov@iki.fi>
parents:
35
diff
changeset
|
22 | #[derive(Copy,Clone,Serialize,Deserialize,Debug,Eq,PartialEq)] |
| 0 | 23 | pub struct Hat<C : Constant, const N : usize> { |
| 24 | /// The parameter $ε>0$. | |
| 25 | pub width : C, | |
| 26 | } | |
| 27 | ||
| 28 | #[replace_float_literals(C::Type::cast_from(literal))] | |
| 35 | 29 | impl<'a, C : Constant, const N : usize> Mapping<Loc<C::Type, N>> for Hat<C, N> { |
| 30 | type Codomain = C::Type; | |
| 31 | ||
| 0 | 32 | #[inline] |
| 35 | 33 | fn apply<I : Instance<Loc<C::Type, N>>>(&self, x : I) -> Self::Codomain { |
| 0 | 34 | let ε = self.width.value(); |
| 35 | 35 | 0.0.max(1.0-x.cow().norm(L1)/ε) |
| 0 | 36 | } |
| 37 | } | |
| 38 | ||
| 39 | #[replace_float_literals(C::Type::cast_from(literal))] | |
| 40 | impl<'a, C : Constant, const N : usize> Support<C::Type, N> for Hat<C, N> { | |
| 41 | #[inline] | |
| 42 | fn support_hint(&self) -> Cube<C::Type,N> { | |
| 43 | let ε = self.width.value(); | |
| 44 | array_init(|| [-ε, ε]).into() | |
| 45 | } | |
| 46 | ||
| 47 | #[inline] | |
| 48 | fn in_support(&self, x : &Loc<C::Type,N>) -> bool { | |
| 49 | x.norm(L1) < self.width.value() | |
| 50 | } | |
| 51 | ||
| 52 | /*fn fully_in_support(&self, _cube : &Cube<C::Type,N>) -> bool { | |
| 53 | todo!("Not implemented, but not used at the moment") | |
| 54 | }*/ | |
| 55 | ||
| 56 | #[inline] | |
| 57 | fn bisection_hint(&self, cube : &Cube<C::Type,N>) -> [Option<C::Type>; N] { | |
| 58 | let ε = self.width.value(); | |
| 59 | cube.map(|a, b| { | |
| 60 | if a < 1.0 { | |
| 61 | if 1.0 < b { | |
| 62 | Some(1.0) | |
| 63 | } else { | |
| 64 | if a < -ε { | |
| 65 | if b > -ε { Some(-ε) } else { None } | |
| 66 | } else { | |
| 67 | None | |
| 68 | } | |
| 69 | } | |
| 70 | } else { | |
| 71 | if b > ε { Some(ε) } else { None } | |
| 72 | } | |
| 73 | }); | |
| 74 | todo!("also diagonals") | |
| 75 | } | |
| 76 | } | |
| 77 | ||
| 78 | ||
| 79 | #[replace_float_literals(C::Type::cast_from(literal))] | |
| 80 | impl<'a, C : Constant, const N : usize> | |
| 81 | GlobalAnalysis<C::Type, Bounds<C::Type>> | |
| 82 | for Hat<C, N> { | |
| 83 | #[inline] | |
| 84 | fn global_analysis(&self) -> Bounds<C::Type> { | |
| 85 | Bounds(0.0, 1.0) | |
| 86 | } | |
| 87 | } | |
| 88 | ||
| 35 | 89 | #[replace_float_literals(C::Type::cast_from(literal))] |
| 90 | impl<'a, C : Constant, const N : usize> Lipschitz<L1> for Hat<C, N> { | |
| 91 | type FloatType = C::Type; | |
| 92 | ||
| 93 | fn lipschitz_factor(&self, _l1 : L1) -> Option<C::Type> { | |
| 94 | Some(1.0/self.width.value()) | |
| 95 | } | |
| 96 | } | |
| 97 | ||
| 98 | #[replace_float_literals(C::Type::cast_from(literal))] | |
| 99 | impl<'a, C : Constant, const N : usize> Lipschitz<L2> for Hat<C, N> { | |
| 100 | type FloatType = C::Type; | |
| 101 | ||
| 102 | fn lipschitz_factor(&self, _l2 : L2) -> Option<C::Type> { | |
| 103 | self.lipschitz_factor(L1).map(|l1| | |
| 104 | <L2 as Dominated<C::Type, L1, Loc<C::Type,N>>>::from_norm(&L2, l1, L1) | |
| 105 | ) | |
| 106 | } | |
| 107 | } | |
| 108 | ||
| 0 | 109 | impl<'a, C : Constant, const N : usize> |
| 110 | LocalAnalysis<C::Type, Bounds<C::Type>, N> | |
| 111 | for Hat<C, N> { | |
| 112 | #[inline] | |
| 113 | fn local_analysis(&self, cube : &Cube<C::Type, N>) -> Bounds<C::Type> { | |
| 114 | // The function is maximised/minimised where the 1-norm is minimised/maximised. | |
| 115 | let lower = self.apply(cube.maxnorm_point()); | |
| 116 | let upper = self.apply(cube.minnorm_point()); | |
| 117 | Bounds(lower, upper) | |
| 118 | } | |
| 119 | } | |
| 120 | ||
| 121 | #[replace_float_literals(C::Type::cast_from(literal))] | |
| 122 | impl<'a, C : Constant, const N : usize> | |
| 123 | Norm<C::Type, Linfinity> | |
| 124 | for Hat<C, N> { | |
| 125 | #[inline] | |
| 126 | fn norm(&self, _ : Linfinity) -> C::Type { | |
| 127 | self.bounds().upper() | |
| 128 | } | |
| 129 | } | |
| 130 |