| 1 /*! |
1 /*! |
| 2 Norms, projections, etc. |
2 Norms, projections, etc. |
| 3 */ |
3 */ |
| 4 |
4 |
| 5 use serde::Serialize; |
5 use serde::Serialize; |
| |
6 use std::marker::PhantomData; |
| 6 use crate::types::*; |
7 use crate::types::*; |
| 7 use crate::euclidean::*; |
8 use crate::euclidean::*; |
| |
9 use crate::mapping::{Mapping, Space, Instance}; |
| 8 |
10 |
| 9 // |
11 // |
| 10 // Abstract norms |
12 // Abstract norms |
| 11 // |
13 // |
| 12 |
14 |
| |
15 #[derive(Copy,Clone,Debug)] |
| |
16 /// Helper structure to convert a [`NormExponent`] into a [`Mapping`] |
| |
17 pub struct NormMapping<F : Float, E : NormExponent>{ |
| |
18 pub(crate) exponent : E, |
| |
19 _phantoms : PhantomData<F> |
| |
20 } |
| |
21 |
| 13 /// An exponent for norms. |
22 /// An exponent for norms. |
| 14 /// |
23 /// |
| 15 // Just a collection of desirable attributes for a marker type |
24 // Just a collection of desirable attributes for a marker type |
| 16 pub trait NormExponent : Copy + Send + Sync + 'static {} |
25 pub trait NormExponent : Copy + Send + Sync + 'static { |
| 17 |
26 /// Return the norm as a mappin |
| |
27 fn as_mapping<F : Float>(self) -> NormMapping<F, Self> { |
| |
28 NormMapping{ exponent : self, _phantoms : PhantomData } |
| |
29 } |
| |
30 } |
| 18 |
31 |
| 19 /// Exponent type for the 1-[`Norm`]. |
32 /// Exponent type for the 1-[`Norm`]. |
| 20 #[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] |
33 #[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] |
| 21 pub struct L1; |
34 pub struct L1; |
| 22 impl NormExponent for L1 {} |
35 impl NormExponent for L1 {} |
| 34 /// Exponent type for 2,1-[`Norm`]. |
47 /// Exponent type for 2,1-[`Norm`]. |
| 35 /// (1-norm over a domain Ω, 2-norm of a vector at each point of the domain.) |
48 /// (1-norm over a domain Ω, 2-norm of a vector at each point of the domain.) |
| 36 #[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] |
49 #[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] |
| 37 pub struct L21; |
50 pub struct L21; |
| 38 impl NormExponent for L21 {} |
51 impl NormExponent for L21 {} |
| |
52 |
| |
53 /// Norms for pairs (a, b). ‖(a,b)‖ = ‖(‖a‖_A, ‖b‖_B)‖_J |
| |
54 /// For use with [`crate::direct_product::Pair`] |
| |
55 #[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] |
| |
56 pub struct PairNorm<A, B, J>(pub A, pub B, pub J); |
| |
57 |
| |
58 impl<A, B, J> NormExponent for PairNorm<A, B, J> |
| |
59 where A : NormExponent, B : NormExponent, J : NormExponent {} |
| |
60 |
| 39 |
61 |
| 40 /// A Huber/Moreau–Yosida smoothed [`L1`] norm. (Not a norm itself.) |
62 /// A Huber/Moreau–Yosida smoothed [`L1`] norm. (Not a norm itself.) |
| 41 /// |
63 /// |
| 42 /// The parameter γ of this type is the smoothing factor. Zero means no smoothing, and higher |
64 /// The parameter γ of this type is the smoothing factor. Zero means no smoothing, and higher |
| 43 /// values more smoothing. Behaviour with γ < 0 is undefined. |
65 /// values more smoothing. Behaviour with γ < 0 is undefined. |
| 152 fn dist(&self, other : &Self, huber : HuberL1<F>) -> F { |
174 fn dist(&self, other : &Self, huber : HuberL1<F>) -> F { |
| 153 huber.apply(self.dist2_squared(other)) |
175 huber.apply(self.dist2_squared(other)) |
| 154 } |
176 } |
| 155 } |
177 } |
| 156 |
178 |
| |
179 impl<F : Float, E : Norm<F, L2>> Norm<F, L21> for Vec<E> { |
| |
180 fn norm(&self, _l21 : L21) -> F { |
| |
181 self.iter().map(|e| e.norm(L2)).sum() |
| |
182 } |
| |
183 } |
| |
184 |
| |
185 impl<F : Float, E : Dist<F, L2>> Dist<F, L21> for Vec<E> { |
| |
186 fn dist(&self, other : &Self, _l21 : L21) -> F { |
| |
187 self.iter().zip(other.iter()).map(|(e, g)| e.dist(g, L2)).sum() |
| |
188 } |
| |
189 } |
| |
190 |
| |
191 impl<E, F, Domain> Mapping<Domain> for NormMapping<F, E> |
| |
192 where |
| |
193 F : Float, |
| |
194 E : NormExponent, |
| |
195 Domain : Space + Norm<F, E>, |
| |
196 { |
| |
197 type Codomain = F; |
| |
198 |
| |
199 #[inline] |
| |
200 fn apply<I : Instance<Domain>>(&self, x : I) -> F { |
| |
201 x.eval(|r| r.norm(self.exponent)) |
| |
202 } |
| |
203 } |
| |
204 |