51 /// values more smoothing. Behaviour with γ < 0 is undefined. |
52 /// values more smoothing. Behaviour with γ < 0 is undefined. |
52 #[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] |
53 #[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] |
53 pub struct HuberL21<F : Float>(pub F); |
54 pub struct HuberL21<F : Float>(pub F); |
54 impl<F : Float> NormExponent for HuberL21<F> {} |
55 impl<F : Float> NormExponent for HuberL21<F> {} |
55 |
56 |
56 |
|
57 /// A normed space (type) with exponent or other type `Exponent` for the norm. |
57 /// A normed space (type) with exponent or other type `Exponent` for the norm. |
58 /// |
58 /// |
59 /// Use as |
59 /// Use as |
60 /// ``` |
60 /// ``` |
61 /// # use alg_tools::norms::{Norm, L1, L2, Linfinity}; |
61 /// # use alg_tools::norms::{Norm, L1, L2, Linfinity}; |
62 /// # use alg_tools::loc::Loc; |
62 /// # use alg_tools::loc::Loc; |
63 /// let x = Loc([1.0, 2.0, 3.0]); |
63 /// let x = Loc([1.0, 2.0, 3.0]); |
64 /// |
64 /// |
65 /// println!("{}, {} {}", x.norm(L1), x.norm(L2), x.norm(Linfinity)) |
65 /// println!("{}, {} {}", x.norm(L1), x.norm(L2), x.norm(Linfinity)) |
66 /// ``` |
66 /// ``` |
67 pub trait Norm<F : Num, Exponent : NormExponent> { |
67 pub trait Norm<Exponent : NormExponent> : HasScalarField { |
68 /// Calculate the norm. |
68 /// Calculate the norm. |
69 fn norm(&self, _p : Exponent) -> F; |
69 fn norm(&self, _p : Exponent) -> Self::Field; |
70 } |
70 } |
71 |
71 |
72 /// Indicates that the `Self`-[`Norm`] is dominated by the `Exponent`-`Norm` on the space |
72 /// Indicates that the `Self`-[`Norm`] is dominated by the `Exponent`-`Norm` on the space |
73 /// `Elem` with the corresponding field `F`. |
73 /// `Elem` with the corresponding field `F`. |
74 pub trait Dominated<F : Num, Exponent : NormExponent, Elem> { |
74 pub trait Dominated<Exponent : NormExponent, Elem> |
|
75 where Elem : HasScalarField { |
75 /// Indicates the factor $c$ for the inequality $‖x‖ ≤ C ‖x‖_p$. |
76 /// Indicates the factor $c$ for the inequality $‖x‖ ≤ C ‖x‖_p$. |
76 fn norm_factor(&self, p : Exponent) -> F; |
77 fn norm_factor(&self, p : Exponent) -> Elem::Field; |
77 /// Given a norm-value $‖x‖_p$, calculates $C‖x‖_p$ such that $‖x‖ ≤ C‖x‖_p$ |
78 /// Given a norm-value $‖x‖_p$, calculates $C‖x‖_p$ such that $‖x‖ ≤ C‖x‖_p$ |
78 #[inline] |
79 #[inline] |
79 fn from_norm(&self, p_norm : F, p : Exponent) -> F { |
80 fn from_norm(&self, p_norm : Elem::Field, p : Exponent) -> Elem::Field { |
80 p_norm * self.norm_factor(p) |
81 p_norm * self.norm_factor(p) |
81 } |
82 } |
82 } |
83 } |
83 |
84 |
84 /// Trait for distances with respect to a norm. |
85 /// Trait for distances with respect to a norm. |
85 pub trait Dist<F : Num, Exponent : NormExponent> : Norm<F, Exponent> { |
86 pub trait Dist<Exponent : NormExponent> : Norm<Exponent> { |
86 /// Calculate the distance |
87 /// Calculate the distance |
87 fn dist(&self, other : &Self, _p : Exponent) -> F; |
88 fn dist(&self, other : &Self, _p : Exponent) -> Self::Field; |
88 } |
89 } |
89 |
90 |
90 /// Trait for Euclidean projections to the `Exponent`-[`Norm`]-ball. |
91 /// Trait for Euclidean projections to the `Exponent`-[`Norm`]-ball. |
91 /// |
92 /// |
92 /// Use as |
93 /// Use as |
95 /// # use alg_tools::loc::Loc; |
96 /// # use alg_tools::loc::Loc; |
96 /// let x = Loc([1.0, 2.0, 3.0]); |
97 /// let x = Loc([1.0, 2.0, 3.0]); |
97 /// |
98 /// |
98 /// println!("{:?}, {:?}", x.proj_ball(1.0, L2), x.proj_ball(0.5, Linfinity)); |
99 /// println!("{:?}, {:?}", x.proj_ball(1.0, L2), x.proj_ball(0.5, Linfinity)); |
99 /// ``` |
100 /// ``` |
100 pub trait Projection<F : Num, Exponent : NormExponent> : Norm<F, Exponent> + Euclidean<F> |
101 pub trait Projection<Exponent : NormExponent> : Norm<Exponent> + Euclidean { |
101 where F : Float { |
|
102 /// Projection of `self` to the `q`-norm-ball of radius ρ. |
102 /// Projection of `self` to the `q`-norm-ball of radius ρ. |
103 fn proj_ball(mut self, ρ : F, q : Exponent) -> Self { |
103 fn proj_ball(mut self, ρ : Self::Field, q : Exponent) -> Self { |
104 self.proj_ball_mut(ρ, q); |
104 self.proj_ball_mut(ρ, q); |
105 self |
105 self |
106 } |
106 } |
107 |
107 |
108 /// In-place projection of `self` to the `q`-norm-ball of radius ρ. |
108 /// In-place projection of `self` to the `q`-norm-ball of radius ρ. |
109 fn proj_ball_mut(&mut self, ρ : F, _q : Exponent); |
109 fn proj_ball_mut(&mut self, ρ : Self::Field, _q : Exponent); |
110 } |
110 } |
111 |
111 |
112 /*impl<F : Float, E : Euclidean<F>> Norm<F, L2> for E { |
112 /*impl<F : Float, E : Euclidean<F>> Norm<F, L2> for E { |
113 #[inline] |
113 #[inline] |
114 fn norm(&self, _p : L2) -> F { self.norm2() } |
114 fn norm(&self, _p : L2) -> F { self.norm2() } |
115 |
115 |
116 fn dist(&self, other : &Self, _p : L2) -> F { self.dist2(other) } |
116 fn dist(&self, other : &Self, _p : L2) -> F { self.dist2(other) } |
117 }*/ |
117 }*/ |
118 |
118 |
119 impl<F : Float, E : Euclidean<F> + Norm<F, L2>> Projection<F, L2> for E { |
119 impl<E : Norm<L2> + Euclidean> Projection<L2> for E { |
120 #[inline] |
120 #[inline] |
121 fn proj_ball(self, ρ : F, _p : L2) -> Self { self.proj_ball2(ρ) } |
121 fn proj_ball(self, ρ : Self::Field, _p : L2) -> Self { self.proj_ball2(ρ) } |
122 |
122 |
123 #[inline] |
123 #[inline] |
124 fn proj_ball_mut(&mut self, ρ : F, _p : L2) { self.proj_ball2_mut(ρ) } |
124 fn proj_ball_mut(&mut self, ρ : Self::Field, _p : L2) { self.proj_ball2_mut(ρ) } |
125 } |
125 } |
126 |
126 |
127 impl<F : Float> HuberL1<F> { |
127 impl<F : Float> HuberL1<F> { |
128 fn apply(self, xnsq : F) -> F { |
128 fn apply(self, xnsq : F) -> F { |
129 let HuberL1(γ) = self; |
129 let HuberL1(γ) = self; |
140 } |
140 } |
141 } |
141 } |
142 } |
142 } |
143 } |
143 } |
144 |
144 |
145 impl<F : Float, E : Euclidean<F>> Norm<F, HuberL1<F>> for E { |
145 impl<F : Float, E : Euclidean<RealField=F>> Norm<HuberL1<F>> for E { |
146 fn norm(&self, huber : HuberL1<F>) -> F { |
146 fn norm(&self, huber : HuberL1<F>) -> F { |
147 huber.apply(self.norm2_squared()) |
147 huber.apply(self.norm2_squared()) |
148 } |
148 } |
149 } |
149 } |
150 |
150 |
151 impl<F : Float, E : Euclidean<F>> Dist<F, HuberL1<F>> for E { |
151 impl<F : Float, E : Euclidean<RealField=F>> Dist<HuberL1<F>> for E { |
152 fn dist(&self, other : &Self, huber : HuberL1<F>) -> F { |
152 fn dist(&self, other : &Self, huber : HuberL1<F>) -> F { |
153 huber.apply(self.dist2_squared(other)) |
153 huber.apply(self.dist2_squared(other)) |
154 } |
154 } |
155 } |
155 } |
156 |
156 |