| 1 /*! |
1 /*! |
| 2 Norms, projections, etc. |
2 Norms, projections, etc. |
| 3 */ |
3 */ |
| 4 |
4 |
| |
5 use crate::euclidean::*; |
| |
6 use crate::mapping::{Instance, Mapping, Space}; |
| |
7 use crate::types::*; |
| 5 use serde::Serialize; |
8 use serde::Serialize; |
| 6 use std::marker::PhantomData; |
9 use std::marker::PhantomData; |
| 7 use crate::types::*; |
|
| 8 use crate::euclidean::*; |
|
| 9 use crate::mapping::{Mapping, Space, Instance}; |
|
| 10 |
10 |
| 11 // |
11 // |
| 12 // Abstract norms |
12 // Abstract norms |
| 13 // |
13 // |
| 14 |
14 |
| 15 #[derive(Copy,Clone,Debug)] |
15 #[derive(Copy, Clone, Debug)] |
| 16 /// Helper structure to convert a [`NormExponent`] into a [`Mapping`] |
16 /// Helper structure to convert a [`NormExponent`] into a [`Mapping`] |
| 17 pub struct NormMapping<F : Float, E : NormExponent>{ |
17 pub struct NormMapping<F: Float, E: NormExponent> { |
| 18 pub(crate) exponent : E, |
18 pub(crate) exponent: E, |
| 19 _phantoms : PhantomData<F> |
19 _phantoms: PhantomData<F>, |
| 20 } |
20 } |
| 21 |
21 |
| 22 /// An exponent for norms. |
22 /// An exponent for norms. |
| 23 /// |
23 /// |
| 24 // Just a collection of desirable attributes for a marker type |
24 // Just a collection of desirable attributes for a marker type |
| 25 pub trait NormExponent : Copy + Send + Sync + 'static { |
25 pub trait NormExponent: Copy { |
| 26 /// Return the norm as a mappin |
26 /// Return the norm as a mappin |
| 27 fn as_mapping<F : Float>(self) -> NormMapping<F, Self> { |
27 fn as_mapping<F: Float>(self) -> NormMapping<F, Self> { |
| 28 NormMapping{ exponent : self, _phantoms : PhantomData } |
28 NormMapping { |
| |
29 exponent: self, |
| |
30 _phantoms: PhantomData, |
| |
31 } |
| 29 } |
32 } |
| 30 } |
33 } |
| 31 |
34 |
| 32 /// Exponent type for the 1-[`Norm`]. |
35 /// Exponent type for the 1-[`Norm`]. |
| 33 #[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] |
36 #[derive(Copy, Debug, Clone, Serialize, Eq, PartialEq)] |
| 34 pub struct L1; |
37 pub struct L1; |
| 35 impl NormExponent for L1 {} |
38 impl NormExponent for L1 {} |
| 36 |
39 |
| 37 /// Exponent type for the 2-[`Norm`]. |
40 /// Exponent type for the 2-[`Norm`]. |
| 38 #[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] |
41 #[derive(Copy, Debug, Clone, Serialize, Eq, PartialEq)] |
| 39 pub struct L2; |
42 pub struct L2; |
| 40 impl NormExponent for L2 {} |
43 impl NormExponent for L2 {} |
| 41 |
44 |
| 42 /// Exponent type for the ∞-[`Norm`]. |
45 /// Exponent type for the ∞-[`Norm`]. |
| 43 #[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] |
46 #[derive(Copy, Debug, Clone, Serialize, Eq, PartialEq)] |
| 44 pub struct Linfinity; |
47 pub struct Linfinity; |
| 45 impl NormExponent for Linfinity {} |
48 impl NormExponent for Linfinity {} |
| 46 |
49 |
| 47 /// Exponent type for 2,1-[`Norm`]. |
50 /// Exponent type for 2,1-[`Norm`]. |
| 48 /// (1-norm over a domain Ω, 2-norm of a vector at each point of the domain.) |
51 /// (1-norm over a domain Ω, 2-norm of a vector at each point of the domain.) |
| 49 #[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] |
52 #[derive(Copy, Debug, Clone, Serialize, Eq, PartialEq)] |
| 50 pub struct L21; |
53 pub struct L21; |
| 51 impl NormExponent for L21 {} |
54 impl NormExponent for L21 {} |
| 52 |
55 |
| 53 /// Norms for pairs (a, b). ‖(a,b)‖ = ‖(‖a‖_A, ‖b‖_B)‖_J |
56 /// Norms for pairs (a, b). ‖(a,b)‖ = ‖(‖a‖_A, ‖b‖_B)‖_J |
| 54 /// For use with [`crate::direct_product::Pair`] |
57 /// For use with [`crate::direct_product::Pair`] |
| 55 #[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] |
58 #[derive(Copy, Debug, Clone, Serialize, Eq, PartialEq)] |
| 56 pub struct PairNorm<A, B, J>(pub A, pub B, pub J); |
59 pub struct PairNorm<A, B, J>(pub A, pub B, pub J); |
| 57 |
60 |
| 58 impl<A, B, J> NormExponent for PairNorm<A, B, J> |
61 impl<A, B, J> NormExponent for PairNorm<A, B, J> |
| 59 where A : NormExponent, B : NormExponent, J : NormExponent {} |
62 where |
| 60 |
63 A: NormExponent, |
| |
64 B: NormExponent, |
| |
65 J: NormExponent, |
| |
66 { |
| |
67 } |
| 61 |
68 |
| 62 /// A Huber/Moreau–Yosida smoothed [`L1`] norm. (Not a norm itself.) |
69 /// A Huber/Moreau–Yosida smoothed [`L1`] norm. (Not a norm itself.) |
| 63 /// |
70 /// |
| 64 /// The parameter γ of this type is the smoothing factor. Zero means no smoothing, and higher |
71 /// The parameter γ of this type is the smoothing factor. Zero means no smoothing, and higher |
| 65 /// values more smoothing. Behaviour with γ < 0 is undefined. |
72 /// values more smoothing. Behaviour with γ < 0 is undefined. |
| 66 #[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] |
73 #[derive(Copy, Debug, Clone, Serialize, Eq, PartialEq)] |
| 67 pub struct HuberL1<F : Float>(pub F); |
74 pub struct HuberL1<F: Float>(pub F); |
| 68 impl<F : Float> NormExponent for HuberL1<F> {} |
75 impl<F: Float> NormExponent for HuberL1<F> {} |
| 69 |
76 |
| 70 /// A Huber/Moreau–Yosida smoothed [`L21`] norm. (Not a norm itself.) |
77 /// A Huber/Moreau–Yosida smoothed [`L21`] norm. (Not a norm itself.) |
| 71 /// |
78 /// |
| 72 /// The parameter γ of this type is the smoothing factor. Zero means no smoothing, and higher |
79 /// The parameter γ of this type is the smoothing factor. Zero means no smoothing, and higher |
| 73 /// values more smoothing. Behaviour with γ < 0 is undefined. |
80 /// values more smoothing. Behaviour with γ < 0 is undefined. |
| 74 #[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] |
81 #[derive(Copy, Debug, Clone, Serialize, Eq, PartialEq)] |
| 75 pub struct HuberL21<F : Float>(pub F); |
82 pub struct HuberL21<F: Float>(pub F); |
| 76 impl<F : Float> NormExponent for HuberL21<F> {} |
83 impl<F: Float> NormExponent for HuberL21<F> {} |
| 77 |
|
| 78 |
84 |
| 79 /// A normed space (type) with exponent or other type `Exponent` for the norm. |
85 /// A normed space (type) with exponent or other type `Exponent` for the norm. |
| 80 /// |
86 /// |
| 81 /// Use as |
87 /// Use as |
| 82 /// ``` |
88 /// ``` |
| 84 /// # use alg_tools::loc::Loc; |
90 /// # use alg_tools::loc::Loc; |
| 85 /// let x = Loc([1.0, 2.0, 3.0]); |
91 /// let x = Loc([1.0, 2.0, 3.0]); |
| 86 /// |
92 /// |
| 87 /// println!("{}, {} {}", x.norm(L1), x.norm(L2), x.norm(Linfinity)) |
93 /// println!("{}, {} {}", x.norm(L1), x.norm(L2), x.norm(Linfinity)) |
| 88 /// ``` |
94 /// ``` |
| 89 pub trait Norm<F : Num, Exponent : NormExponent> { |
95 pub trait Norm<F: Num, Exponent: NormExponent> { |
| 90 /// Calculate the norm. |
96 /// Calculate the norm. |
| 91 fn norm(&self, _p : Exponent) -> F; |
97 fn norm(&self, _p: Exponent) -> F; |
| 92 } |
98 } |
| 93 |
99 |
| 94 /// Indicates that the `Self`-[`Norm`] is dominated by the `Exponent`-`Norm` on the space |
100 /// Indicates that the `Self`-[`Norm`] is dominated by the `Exponent`-`Norm` on the space |
| 95 /// `Elem` with the corresponding field `F`. |
101 /// `Elem` with the corresponding field `F`. |
| 96 pub trait Dominated<F : Num, Exponent : NormExponent, Elem> { |
102 pub trait Dominated<F: Num, Exponent: NormExponent, Elem> { |
| 97 /// Indicates the factor $c$ for the inequality $‖x‖ ≤ C ‖x‖_p$. |
103 /// Indicates the factor $c$ for the inequality $‖x‖ ≤ C ‖x‖_p$. |
| 98 fn norm_factor(&self, p : Exponent) -> F; |
104 fn norm_factor(&self, p: Exponent) -> F; |
| 99 /// Given a norm-value $‖x‖_p$, calculates $C‖x‖_p$ such that $‖x‖ ≤ C‖x‖_p$ |
105 /// Given a norm-value $‖x‖_p$, calculates $C‖x‖_p$ such that $‖x‖ ≤ C‖x‖_p$ |
| 100 #[inline] |
106 #[inline] |
| 101 fn from_norm(&self, p_norm : F, p : Exponent) -> F { |
107 fn from_norm(&self, p_norm: F, p: Exponent) -> F { |
| 102 p_norm * self.norm_factor(p) |
108 p_norm * self.norm_factor(p) |
| 103 } |
109 } |
| 104 } |
110 } |
| 105 |
111 |
| 106 /// Trait for distances with respect to a norm. |
112 /// Trait for distances with respect to a norm. |
| 107 pub trait Dist<F : Num, Exponent : NormExponent> : Norm<F, Exponent> + Space { |
113 pub trait Dist<F: Num, Exponent: NormExponent>: Norm<F, Exponent> + Space { |
| 108 /// Calculate the distance |
114 /// Calculate the distance |
| 109 fn dist<I : Instance<Self>>(&self, other : I, _p : Exponent) -> F; |
115 fn dist<I: Instance<Self>>(&self, other: I, _p: Exponent) -> F; |
| 110 } |
116 } |
| 111 |
117 |
| 112 /// Trait for Euclidean projections to the `Exponent`-[`Norm`]-ball. |
118 /// Trait for Euclidean projections to the `Exponent`-[`Norm`]-ball. |
| 113 /// |
119 /// |
| 114 /// Use as |
120 /// Use as |
| 117 /// # use alg_tools::loc::Loc; |
123 /// # use alg_tools::loc::Loc; |
| 118 /// let x = Loc([1.0, 2.0, 3.0]); |
124 /// let x = Loc([1.0, 2.0, 3.0]); |
| 119 /// |
125 /// |
| 120 /// println!("{:?}, {:?}", x.proj_ball(1.0, L2), x.proj_ball(0.5, Linfinity)); |
126 /// println!("{:?}, {:?}", x.proj_ball(1.0, L2), x.proj_ball(0.5, Linfinity)); |
| 121 /// ``` |
127 /// ``` |
| 122 pub trait Projection<F : Num, Exponent : NormExponent> : Norm<F, Exponent> + Sized |
128 pub trait Projection<F: Num, Exponent: NormExponent>: Norm<F, Exponent> + Sized |
| 123 where F : Float { |
129 where |
| |
130 F: Float, |
| |
131 { |
| 124 /// Projection of `self` to the `q`-norm-ball of radius ρ. |
132 /// Projection of `self` to the `q`-norm-ball of radius ρ. |
| 125 fn proj_ball(mut self, ρ : F, q : Exponent) -> Self { |
133 fn proj_ball(mut self, ρ: F, q: Exponent) -> Self { |
| 126 self.proj_ball_mut(ρ, q); |
134 self.proj_ball_mut(ρ, q); |
| 127 self |
135 self |
| 128 } |
136 } |
| 129 |
137 |
| 130 /// In-place projection of `self` to the `q`-norm-ball of radius ρ. |
138 /// In-place projection of `self` to the `q`-norm-ball of radius ρ. |
| 131 fn proj_ball_mut(&mut self, ρ : F, q : Exponent); |
139 fn proj_ball_mut(&mut self, ρ: F, q: Exponent); |
| 132 } |
140 } |
| 133 |
141 |
| 134 /*impl<F : Float, E : Euclidean<F>> Norm<F, L2> for E { |
142 /*impl<F : Float, E : Euclidean<F>> Norm<F, L2> for E { |
| 135 #[inline] |
143 #[inline] |
| 136 fn norm(&self, _p : L2) -> F { self.norm2() } |
144 fn norm(&self, _p : L2) -> F { self.norm2() } |
| 137 |
145 |
| 138 fn dist(&self, other : &Self, _p : L2) -> F { self.dist2(other) } |
146 fn dist(&self, other : &Self, _p : L2) -> F { self.dist2(other) } |
| 139 }*/ |
147 }*/ |
| 140 |
148 |
| 141 impl<F : Float, E : Euclidean<F> + Norm<F, L2>> Projection<F, L2> for E { |
149 impl<F: Float, E: Euclidean<F> + Norm<F, L2>> Projection<F, L2> for E { |
| 142 #[inline] |
150 #[inline] |
| 143 fn proj_ball(self, ρ : F, _p : L2) -> Self { self.proj_ball2(ρ) } |
151 fn proj_ball(self, ρ: F, _p: L2) -> Self { |
| 144 |
152 self.proj_ball2(ρ) |
| 145 #[inline] |
153 } |
| 146 fn proj_ball_mut(&mut self, ρ : F, _p : L2) { self.proj_ball2_mut(ρ) } |
154 |
| 147 } |
155 #[inline] |
| 148 |
156 fn proj_ball_mut(&mut self, ρ: F, _p: L2) { |
| 149 impl<F : Float> HuberL1<F> { |
157 self.proj_ball2_mut(ρ) |
| 150 fn apply(self, xnsq : F) -> F { |
158 } |
| |
159 } |
| |
160 |
| |
161 impl<F: Float> HuberL1<F> { |
| |
162 fn apply(self, xnsq: F) -> F { |
| 151 let HuberL1(γ) = self; |
163 let HuberL1(γ) = self; |
| 152 let xn = xnsq.sqrt(); |
164 let xn = xnsq.sqrt(); |
| 153 if γ == F::ZERO { |
165 if γ == F::ZERO { |
| 154 xn |
166 xn |
| 155 } else { |
167 } else { |
| 156 if xn > γ { |
168 if xn > γ { |
| 157 xn-γ / F::TWO |
169 xn - γ / F::TWO |
| 158 } else if xn<(-γ) { |
170 } else if xn < (-γ) { |
| 159 -xn-γ / F::TWO |
171 -xn - γ / F::TWO |
| 160 } else { |
172 } else { |
| 161 xnsq / (F::TWO * γ) |
173 xnsq / (F::TWO * γ) |
| 162 } |
174 } |
| 163 } |
175 } |
| 164 } |
176 } |
| 165 } |
177 } |
| 166 |
178 |
| 167 impl<F : Float, E : Euclidean<F>> Norm<F, HuberL1<F>> for E { |
179 impl<F: Float, E: Euclidean<F>> Norm<F, HuberL1<F>> for E { |
| 168 fn norm(&self, huber : HuberL1<F>) -> F { |
180 fn norm(&self, huber: HuberL1<F>) -> F { |
| 169 huber.apply(self.norm2_squared()) |
181 huber.apply(self.norm2_squared()) |
| 170 } |
182 } |
| 171 } |
183 } |
| 172 |
184 |
| 173 impl<F : Float, E : Euclidean<F>> Dist<F, HuberL1<F>> for E { |
185 impl<F: Float, E: Euclidean<F>> Dist<F, HuberL1<F>> for E { |
| 174 fn dist<I : Instance<Self>>(&self, other : I, huber : HuberL1<F>) -> F { |
186 fn dist<I: Instance<Self>>(&self, other: I, huber: HuberL1<F>) -> F { |
| 175 huber.apply(self.dist2_squared(other)) |
187 huber.apply(self.dist2_squared(other)) |
| 176 } |
188 } |
| 177 } |
189 } |
| 178 |
190 |
| 179 // impl<F : Float, E : Norm<F, L2>> Norm<F, L21> for Vec<E> { |
191 // impl<F : Float, E : Norm<F, L2>> Norm<F, L21> for Vec<E> { |
| 215 // fn similar_origin(&self) -> Self; |
227 // fn similar_origin(&self) -> Self; |
| 216 |
228 |
| 217 fn is_zero(&self) -> bool; |
229 fn is_zero(&self) -> bool; |
| 218 } |
230 } |
| 219 |
231 |
| 220 pub trait HasDual<F : Num = f64> : Normed<F> { |
232 pub trait HasDual<F: Num = f64>: Normed<F> { |
| 221 type DualSpace : Normed<F>; |
233 type DualSpace: Normed<F>; |
| 222 } |
234 } |
| 223 |
235 |
| 224 /// Automatically implemented trait for reflexive spaces |
236 /// Automatically implemented trait for reflexive spaces |
| 225 pub trait Reflexive<F : Num = f64> : HasDual<F> |
237 pub trait Reflexive<F: Num = f64>: HasDual<F> |
| 226 where |
238 where |
| 227 Self::DualSpace : HasDual<F, DualSpace = Self> |
239 Self::DualSpace: HasDual<F, DualSpace = Self>, |
| 228 { } |
240 { |
| 229 |
241 } |
| 230 impl<F : Num, X : HasDual<F>> Reflexive<F> for X |
242 |
| 231 where |
243 impl<F: Num, X: HasDual<F>> Reflexive<F> for X where X::DualSpace: HasDual<F, DualSpace = X> {} |
| 232 X::DualSpace : HasDual<F, DualSpace = X> |
244 |
| 233 { } |
245 pub trait HasDualExponent: NormExponent { |
| 234 |
246 type DualExp: NormExponent; |
| 235 pub trait HasDualExponent : NormExponent { |
|
| 236 type DualExp : NormExponent; |
|
| 237 |
247 |
| 238 fn dual_exponent(&self) -> Self::DualExp; |
248 fn dual_exponent(&self) -> Self::DualExp; |
| 239 } |
249 } |
| 240 |
250 |
| 241 impl HasDualExponent for L2 { |
251 impl HasDualExponent for L2 { |
| 242 type DualExp = L2; |
252 type DualExp = L2; |
| 243 |
253 |
| 244 #[inline] |
254 #[inline] |
| 245 fn dual_exponent(&self) -> Self::DualExp { |
255 fn dual_exponent(&self) -> Self::DualExp { |
| 246 L2 |
256 L2 |
| 247 } |
257 } |
| 248 } |
258 } |
| 249 |
259 |
| 250 impl HasDualExponent for L1 { |
260 impl HasDualExponent for L1 { |
| 251 type DualExp = Linfinity; |
261 type DualExp = Linfinity; |
| 252 |
262 |
| 253 #[inline] |
263 #[inline] |
| 254 fn dual_exponent(&self) -> Self::DualExp { |
264 fn dual_exponent(&self) -> Self::DualExp { |
| 255 Linfinity |
265 Linfinity |
| 256 } |
266 } |
| 257 } |
267 } |
| 258 |
268 |
| 259 |
|
| 260 impl HasDualExponent for Linfinity { |
269 impl HasDualExponent for Linfinity { |
| 261 type DualExp = L1; |
270 type DualExp = L1; |
| 262 |
271 |
| 263 #[inline] |
272 #[inline] |
| 264 fn dual_exponent(&self) -> Self::DualExp { |
273 fn dual_exponent(&self) -> Self::DualExp { |
| 265 L1 |
274 L1 |
| 266 } |
275 } |
| 267 } |
276 } |
| 269 #[macro_export] |
278 #[macro_export] |
| 270 macro_rules! impl_weighted_norm { |
279 macro_rules! impl_weighted_norm { |
| 271 ($exponent : ty) => { |
280 ($exponent : ty) => { |
| 272 impl<C, F, D> Norm<F, Weighted<$exponent, C>> for D |
281 impl<C, F, D> Norm<F, Weighted<$exponent, C>> for D |
| 273 where |
282 where |
| 274 F : Float, |
283 F: Float, |
| 275 D : Norm<F, $exponent>, |
284 D: Norm<F, $exponent>, |
| 276 C : Constant<Type = F>, |
285 C: Constant<Type = F>, |
| 277 { |
286 { |
| 278 fn norm(&self, e : Weighted<$exponent, C>) -> F { |
287 fn norm(&self, e: Weighted<$exponent, C>) -> F { |
| 279 let v = e.weight.value(); |
288 let v = e.weight.value(); |
| 280 assert!(v > F::ZERO); |
289 assert!(v > F::ZERO); |
| 281 v * self.norm(e.base_fn) |
290 v * self.norm(e.base_fn) |
| 282 } |
291 } |
| 283 } |
292 } |
| 284 |
293 |
| 285 impl<C : Constant> NormExponent for Weighted<$exponent, C> {} |
294 impl<C: Constant> NormExponent for Weighted<$exponent, C> {} |
| 286 |
295 |
| 287 impl<C : Constant> HasDualExponent for Weighted<$exponent, C> |
296 impl<C: Constant> HasDualExponent for Weighted<$exponent, C> |
| 288 where $exponent : HasDualExponent { |
297 where |
| |
298 $exponent: HasDualExponent, |
| |
299 { |
| 289 type DualExp = Weighted<<$exponent as HasDualExponent>::DualExp, C::Type>; |
300 type DualExp = Weighted<<$exponent as HasDualExponent>::DualExp, C::Type>; |
| 290 |
301 |
| 291 fn dual_exponent(&self) -> Self::DualExp { |
302 fn dual_exponent(&self) -> Self::DualExp { |
| 292 Weighted { |
303 Weighted { |
| 293 weight : C::Type::ONE / self.weight.value(), |
304 weight: C::Type::ONE / self.weight.value(), |
| 294 base_fn : self.base_fn.dual_exponent() |
305 base_fn: self.base_fn.dual_exponent(), |
| 295 } |
306 } |
| 296 } |
307 } |
| 297 } |
308 } |
| 298 |
309 |
| 299 impl<C, F, T> Projection<F, Weighted<$exponent , C>> for T |
310 impl<C, F, T> Projection<F, Weighted<$exponent, C>> for T |
| 300 where |
311 where |
| 301 T : Projection<F, $exponent >, |
312 T: Projection<F, $exponent>, |
| 302 F : Float, |
313 F: Float, |
| 303 C : Constant<Type = F>, |
314 C: Constant<Type = F>, |
| 304 { |
315 { |
| 305 fn proj_ball(self, ρ : F, q : Weighted<$exponent , C>) -> Self { |
316 fn proj_ball(self, ρ: F, q: Weighted<$exponent, C>) -> Self { |
| 306 self.proj_ball(ρ / q.weight.value(), q.base_fn) |
317 self.proj_ball(ρ / q.weight.value(), q.base_fn) |
| 307 } |
318 } |
| 308 |
319 |
| 309 fn proj_ball_mut(&mut self, ρ : F, q : Weighted<$exponent , C>) { |
320 fn proj_ball_mut(&mut self, ρ: F, q: Weighted<$exponent, C>) { |
| 310 self.proj_ball_mut(ρ / q.weight.value(), q.base_fn) |
321 self.proj_ball_mut(ρ / q.weight.value(), q.base_fn) |
| 311 } |
322 } |
| 312 } |
323 } |
| 313 } |
324 }; |
| 314 } |
325 } |
| 315 |
326 |
| 316 //impl_weighted_norm!(L1); |
327 //impl_weighted_norm!(L1); |
| 317 //impl_weighted_norm!(L2); |
328 //impl_weighted_norm!(L2); |
| 318 //impl_weighted_norm!(Linfinity); |
329 //impl_weighted_norm!(Linfinity); |
| 319 |
|