| 90 /// # use alg_tools::loc::Loc; |
90 /// # use alg_tools::loc::Loc; |
| 91 /// let x = Loc([1.0, 2.0, 3.0]); |
91 /// let x = Loc([1.0, 2.0, 3.0]); |
| 92 /// |
92 /// |
| 93 /// println!("{}, {} {}", x.norm(L1), x.norm(L2), x.norm(Linfinity)) |
93 /// println!("{}, {} {}", x.norm(L1), x.norm(L2), x.norm(Linfinity)) |
| 94 /// ``` |
94 /// ``` |
| 95 pub trait Norm<F: Num, Exponent: NormExponent> { |
95 pub trait Norm<Exponent: NormExponent, F: Num = f64> { |
| 96 /// Calculate the norm. |
96 /// Calculate the norm. |
| 97 fn norm(&self, _p: Exponent) -> F; |
97 fn norm(&self, _p: Exponent) -> F; |
| 98 } |
98 } |
| 99 |
99 |
| 100 /// 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 |
| 108 p_norm * self.norm_factor(p) |
108 p_norm * self.norm_factor(p) |
| 109 } |
109 } |
| 110 } |
110 } |
| 111 |
111 |
| 112 /// Trait for distances with respect to a norm. |
112 /// Trait for distances with respect to a norm. |
| 113 pub trait Dist<F: Num, Exponent: NormExponent>: Norm<F, Exponent> + Space { |
113 pub trait Dist<F: Num, Exponent: NormExponent>: Norm<Exponent, F> + Space { |
| 114 /// Calculate the distance |
114 /// Calculate the distance |
| 115 fn dist<I: Instance<Self>>(&self, other: I, _p: Exponent) -> F; |
115 fn dist<I: Instance<Self>>(&self, other: I, _p: Exponent) -> F; |
| 116 } |
116 } |
| 117 |
117 |
| 118 /// Trait for Euclidean projections to the `Exponent`-[`Norm`]-ball. |
118 /// Trait for Euclidean projections to the `Exponent`-[`Norm`]-ball. |
| 123 /// # use alg_tools::loc::Loc; |
123 /// # use alg_tools::loc::Loc; |
| 124 /// let x = Loc([1.0, 2.0, 3.0]); |
124 /// let x = Loc([1.0, 2.0, 3.0]); |
| 125 /// |
125 /// |
| 126 /// 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)); |
| 127 /// ``` |
127 /// ``` |
| 128 pub trait Projection<F: Num, Exponent: NormExponent>: Norm<F, Exponent> + Sized |
128 pub trait Projection<F: Num, Exponent: NormExponent>: Norm<Exponent, F> + Sized |
| 129 where |
129 where |
| 130 F: Float, |
130 F: Float, |
| 131 { |
131 { |
| 132 /// Projection of `self` to the `q`-norm-ball of radius ρ. |
132 /// Projection of `self` to the `q`-norm-ball of radius ρ. |
| 133 fn proj_ball(mut self, ρ: F, q: Exponent) -> Self { |
133 fn proj_ball(mut self, ρ: F, q: Exponent) -> Self { |
| 137 |
137 |
| 138 /// 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 ρ. |
| 139 fn proj_ball_mut(&mut self, ρ: F, q: Exponent); |
139 fn proj_ball_mut(&mut self, ρ: F, q: Exponent); |
| 140 } |
140 } |
| 141 |
141 |
| 142 /*impl<F : Float, E : Euclidean<F>> Norm<F, L2> for E { |
142 /*impl<F : Float, E : Euclidean<F>> Norm<L2, F> for E { |
| 143 #[inline] |
143 #[inline] |
| 144 fn norm(&self, _p : L2) -> F { self.norm2() } |
144 fn norm(&self, _p : L2) -> F { self.norm2() } |
| 145 |
145 |
| 146 fn dist(&self, other : &Self, _p : L2) -> F { self.dist2(other) } |
146 fn dist(&self, other : &Self, _p : L2) -> F { self.dist2(other) } |
| 147 }*/ |
147 }*/ |
| 148 |
148 |
| 149 impl<F: Float, E: Euclidean<F> + Norm<F, L2>> Projection<F, L2> for E { |
149 impl<F: Float, E: Euclidean<F> + Norm<L2, F>> Projection<F, L2> for E { |
| 150 #[inline] |
150 #[inline] |
| 151 fn proj_ball(self, ρ: F, _p: L2) -> Self { |
151 fn proj_ball(self, ρ: F, _p: L2) -> Self { |
| 152 self.proj_ball2(ρ) |
152 self.proj_ball2(ρ) |
| 153 } |
153 } |
| 154 |
154 |
| 186 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 { |
| 187 huber.apply(self.dist2_squared(other)) |
187 huber.apply(self.dist2_squared(other)) |
| 188 } |
188 } |
| 189 } |
189 } |
| 190 |
190 |
| 191 // impl<F : Float, E : Norm<F, L2>> Norm<F, L21> for Vec<E> { |
191 // impl<F : Float, E : Norm<L2, F>> Norm<L21, F> for Vec<E> { |
| 192 // fn norm(&self, _l21 : L21) -> F { |
192 // fn norm(&self, _l21 : L21) -> F { |
| 193 // self.iter().map(|e| e.norm(L2)).sum() |
193 // self.iter().map(|e| e.norm(L2)).sum() |
| 194 // } |
194 // } |
| 195 // } |
195 // } |
| 196 |
196 |
| 202 |
202 |
| 203 impl<E, F, Domain> Mapping<Domain> for NormMapping<F, E> |
203 impl<E, F, Domain> Mapping<Domain> for NormMapping<F, E> |
| 204 where |
204 where |
| 205 F: Float, |
205 F: Float, |
| 206 E: NormExponent, |
206 E: NormExponent, |
| 207 Domain: Space + Norm<F, E>, |
207 Domain: Space + Norm<E, F>, |
| 208 { |
208 { |
| 209 type Codomain = F; |
209 type Codomain = F; |
| 210 |
210 |
| 211 #[inline] |
211 #[inline] |
| 212 fn apply<I: Instance<Domain>>(&self, x: I) -> F { |
212 fn apply<I: Instance<Domain>>(&self, x: I) -> F { |
| 213 x.eval(|r| r.norm(self.exponent)) |
213 x.eval(|r| r.norm(self.exponent)) |
| 214 } |
214 } |
| 215 } |
215 } |
| 216 |
216 |
| 217 pub trait Normed<F: Num = f64>: Space + Norm<F, Self::NormExp> { |
217 pub trait Normed<F: Num = f64>: Space + Norm<Self::NormExp, F> { |
| 218 type NormExp: NormExponent; |
218 type NormExp: NormExponent; |
| 219 |
219 |
| 220 fn norm_exponent(&self) -> Self::NormExp; |
220 fn norm_exponent(&self) -> Self::NormExp; |
| 221 |
221 |
| 222 #[inline] |
222 #[inline] |
| 281 macro_rules! impl_weighted_norm { |
281 macro_rules! impl_weighted_norm { |
| 282 ($exponent : ty) => { |
282 ($exponent : ty) => { |
| 283 impl<C, F, D> Norm<F, Weighted<$exponent, C>> for D |
283 impl<C, F, D> Norm<F, Weighted<$exponent, C>> for D |
| 284 where |
284 where |
| 285 F: Float, |
285 F: Float, |
| 286 D: Norm<F, $exponent>, |
286 D: Norm<$exponent, F>, |
| 287 C: Constant<Type = F>, |
287 C: Constant<Type = F>, |
| 288 { |
288 { |
| 289 fn norm(&self, e: Weighted<$exponent, C>) -> F { |
289 fn norm(&self, e: Weighted<$exponent, C>) -> F { |
| 290 let v = e.weight.value(); |
290 let v = e.weight.value(); |
| 291 assert!(v > F::ZERO); |
291 assert!(v > F::ZERO); |