Tue, 31 Dec 2024 09:12:43 -0500
Try to have Field as member type in Mappings etc.
0 | 1 | /*! |
2 | Norms, projections, etc. | |
3 | */ | |
4 | ||
5 | 5 | use serde::Serialize; |
0 | 6 | use crate::types::*; |
5 | 7 | use crate::euclidean::*; |
81
d2acaaddd9af
Try to have Field as member type in Mappings etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
33
diff
changeset
|
8 | pub use crate::types::{HasScalarField, HasRealField}; |
0 | 9 | |
10 | // | |
11 | // Abstract norms | |
12 | // | |
13 | ||
6
d80b87b8acd0
Added NormExponent trait for exponents of norms
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
14 | /// An exponent for norms. |
d80b87b8acd0
Added NormExponent trait for exponents of norms
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
15 | /// |
33 | 16 | // Just a collection of desirable attributes for a marker type |
6
d80b87b8acd0
Added NormExponent trait for exponents of norms
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
17 | pub trait NormExponent : Copy + Send + Sync + 'static {} |
d80b87b8acd0
Added NormExponent trait for exponents of norms
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
18 | |
d80b87b8acd0
Added NormExponent trait for exponents of norms
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
19 | |
5 | 20 | /// Exponent type for the 1-[`Norm`]. |
0 | 21 | #[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] |
22 | pub struct L1; | |
6
d80b87b8acd0
Added NormExponent trait for exponents of norms
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
23 | impl NormExponent for L1 {} |
0 | 24 | |
5 | 25 | /// Exponent type for the 2-[`Norm`]. |
0 | 26 | #[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] |
27 | pub struct L2; | |
6
d80b87b8acd0
Added NormExponent trait for exponents of norms
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
28 | impl NormExponent for L2 {} |
0 | 29 | |
5 | 30 | /// Exponent type for the ∞-[`Norm`]. |
0 | 31 | #[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] |
32 | pub struct Linfinity; | |
6
d80b87b8acd0
Added NormExponent trait for exponents of norms
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
33 | impl NormExponent for Linfinity {} |
0 | 34 | |
5 | 35 | /// Exponent type for 2,1-[`Norm`]. |
36 | /// (1-norm over a domain Ω, 2-norm of a vector at each point of the domain.) | |
0 | 37 | #[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] |
38 | pub struct L21; | |
6
d80b87b8acd0
Added NormExponent trait for exponents of norms
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
39 | impl NormExponent for L21 {} |
0 | 40 | |
5 | 41 | /// A Huber/Moreau–Yosida smoothed [`L1`] norm. (Not a norm itself.) |
42 | /// | |
43 | /// The parameter γ of this type is the smoothing factor. Zero means no smoothing, and higher | |
44 | /// values more smoothing. Behaviour with γ < 0 is undefined. | |
0 | 45 | #[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] |
46 | pub struct HuberL1<F : Float>(pub F); | |
6
d80b87b8acd0
Added NormExponent trait for exponents of norms
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
47 | impl<F : Float> NormExponent for HuberL1<F> {} |
0 | 48 | |
5 | 49 | /// A Huber/Moreau–Yosida smoothed [`L21`] norm. (Not a norm itself.) |
50 | /// | |
51 | /// The parameter γ of this type is the smoothing factor. Zero means no smoothing, and higher | |
52 | /// values more smoothing. Behaviour with γ < 0 is undefined. | |
0 | 53 | #[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] |
54 | pub struct HuberL21<F : Float>(pub F); | |
6
d80b87b8acd0
Added NormExponent trait for exponents of norms
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
55 | impl<F : Float> NormExponent for HuberL21<F> {} |
d80b87b8acd0
Added NormExponent trait for exponents of norms
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
56 | |
5 | 57 | /// A normed space (type) with exponent or other type `Exponent` for the norm. |
58 | /// | |
59 | /// Use as | |
60 | /// ``` | |
61 | /// # use alg_tools::norms::{Norm, L1, L2, Linfinity}; | |
62 | /// # use alg_tools::loc::Loc; | |
63 | /// let x = Loc([1.0, 2.0, 3.0]); | |
64 | /// | |
65 | /// println!("{}, {} {}", x.norm(L1), x.norm(L2), x.norm(Linfinity)) | |
66 | /// ``` | |
81
d2acaaddd9af
Try to have Field as member type in Mappings etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
33
diff
changeset
|
67 | pub trait Norm<Exponent : NormExponent> : HasScalarField { |
5 | 68 | /// Calculate the norm. |
81
d2acaaddd9af
Try to have Field as member type in Mappings etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
33
diff
changeset
|
69 | fn norm(&self, _p : Exponent) -> Self::Field; |
0 | 70 | } |
71 | ||
5 | 72 | /// Indicates that the `Self`-[`Norm`] is dominated by the `Exponent`-`Norm` on the space |
73 | /// `Elem` with the corresponding field `F`. | |
81
d2acaaddd9af
Try to have Field as member type in Mappings etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
33
diff
changeset
|
74 | pub trait Dominated<Exponent : NormExponent, Elem> |
d2acaaddd9af
Try to have Field as member type in Mappings etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
33
diff
changeset
|
75 | where Elem : HasScalarField { |
0 | 76 | /// Indicates the factor $c$ for the inequality $‖x‖ ≤ C ‖x‖_p$. |
81
d2acaaddd9af
Try to have Field as member type in Mappings etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
33
diff
changeset
|
77 | fn norm_factor(&self, p : Exponent) -> Elem::Field; |
0 | 78 | /// Given a norm-value $‖x‖_p$, calculates $C‖x‖_p$ such that $‖x‖ ≤ C‖x‖_p$ |
79 | #[inline] | |
81
d2acaaddd9af
Try to have Field as member type in Mappings etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
33
diff
changeset
|
80 | fn from_norm(&self, p_norm : Elem::Field, p : Exponent) -> Elem::Field { |
0 | 81 | p_norm * self.norm_factor(p) |
82 | } | |
83 | } | |
84 | ||
5 | 85 | /// Trait for distances with respect to a norm. |
81
d2acaaddd9af
Try to have Field as member type in Mappings etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
33
diff
changeset
|
86 | pub trait Dist<Exponent : NormExponent> : Norm<Exponent> { |
0 | 87 | /// Calculate the distance |
81
d2acaaddd9af
Try to have Field as member type in Mappings etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
33
diff
changeset
|
88 | fn dist(&self, other : &Self, _p : Exponent) -> Self::Field; |
0 | 89 | } |
90 | ||
5 | 91 | /// Trait for Euclidean projections to the `Exponent`-[`Norm`]-ball. |
92 | /// | |
93 | /// Use as | |
94 | /// ``` | |
95 | /// # use alg_tools::norms::{Projection, L2, Linfinity}; | |
96 | /// # use alg_tools::loc::Loc; | |
97 | /// let x = Loc([1.0, 2.0, 3.0]); | |
98 | /// | |
99 | /// println!("{:?}, {:?}", x.proj_ball(1.0, L2), x.proj_ball(0.5, Linfinity)); | |
100 | /// ``` | |
81
d2acaaddd9af
Try to have Field as member type in Mappings etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
33
diff
changeset
|
101 | pub trait Projection<Exponent : NormExponent> : Norm<Exponent> + Euclidean { |
5 | 102 | /// Projection of `self` to the `q`-norm-ball of radius ρ. |
81
d2acaaddd9af
Try to have Field as member type in Mappings etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
33
diff
changeset
|
103 | fn proj_ball(mut self, ρ : Self::Field, q : Exponent) -> Self { |
0 | 104 | self.proj_ball_mut(ρ, q); |
105 | self | |
106 | } | |
107 | ||
5 | 108 | /// In-place projection of `self` to the `q`-norm-ball of radius ρ. |
81
d2acaaddd9af
Try to have Field as member type in Mappings etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
33
diff
changeset
|
109 | fn proj_ball_mut(&mut self, ρ : Self::Field, _q : Exponent); |
0 | 110 | } |
111 | ||
112 | /*impl<F : Float, E : Euclidean<F>> Norm<F, L2> for E { | |
113 | #[inline] | |
114 | fn norm(&self, _p : L2) -> F { self.norm2() } | |
115 | ||
116 | fn dist(&self, other : &Self, _p : L2) -> F { self.dist2(other) } | |
117 | }*/ | |
118 | ||
81
d2acaaddd9af
Try to have Field as member type in Mappings etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
33
diff
changeset
|
119 | impl<E : Norm<L2> + Euclidean> Projection<L2> for E { |
0 | 120 | #[inline] |
81
d2acaaddd9af
Try to have Field as member type in Mappings etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
33
diff
changeset
|
121 | fn proj_ball(self, ρ : Self::Field, _p : L2) -> Self { self.proj_ball2(ρ) } |
0 | 122 | |
123 | #[inline] | |
81
d2acaaddd9af
Try to have Field as member type in Mappings etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
33
diff
changeset
|
124 | fn proj_ball_mut(&mut self, ρ : Self::Field, _p : L2) { self.proj_ball2_mut(ρ) } |
0 | 125 | } |
126 | ||
127 | impl<F : Float> HuberL1<F> { | |
128 | fn apply(self, xnsq : F) -> F { | |
129 | let HuberL1(γ) = self; | |
130 | let xn = xnsq.sqrt(); | |
131 | if γ == F::ZERO { | |
132 | xn | |
133 | } else { | |
134 | if xn > γ { | |
5 | 135 | xn-γ / F::TWO |
0 | 136 | } else if xn<(-γ) { |
5 | 137 | -xn-γ / F::TWO |
0 | 138 | } else { |
5 | 139 | xnsq / (F::TWO * γ) |
0 | 140 | } |
141 | } | |
142 | } | |
143 | } | |
144 | ||
81
d2acaaddd9af
Try to have Field as member type in Mappings etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
33
diff
changeset
|
145 | impl<F : Float, E : Euclidean<RealField=F>> Norm<HuberL1<F>> for E { |
0 | 146 | fn norm(&self, huber : HuberL1<F>) -> F { |
147 | huber.apply(self.norm2_squared()) | |
148 | } | |
149 | } | |
150 | ||
81
d2acaaddd9af
Try to have Field as member type in Mappings etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
33
diff
changeset
|
151 | impl<F : Float, E : Euclidean<RealField=F>> Dist<HuberL1<F>> for E { |
0 | 152 | fn dist(&self, other : &Self, huber : HuberL1<F>) -> F { |
153 | huber.apply(self.dist2_squared(other)) | |
154 | } | |
155 | } | |
156 |