src/norms.rs

branch
dev
changeset 81
d2acaaddd9af
parent 33
75d65fa74eba
equal deleted inserted replaced
49:edb95d2b83cc 81:d2acaaddd9af
3 */ 3 */
4 4
5 use serde::Serialize; 5 use serde::Serialize;
6 use crate::types::*; 6 use crate::types::*;
7 use crate::euclidean::*; 7 use crate::euclidean::*;
8 pub use crate::types::{HasScalarField, HasRealField};
8 9
9 // 10 //
10 // Abstract norms 11 // Abstract norms
11 // 12 //
12 13
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

mercurial