src/convex.rs

branch
dev
changeset 80
f802ddbabcfc
parent 60
848ecc05becf
equal deleted inserted replaced
68:c5f70e767511 80:f802ddbabcfc
2 Some convex analysis basics 2 Some convex analysis basics
3 */ 3 */
4 4
5 use std::marker::PhantomData; 5 use std::marker::PhantomData;
6 use crate::types::*; 6 use crate::types::*;
7 use crate::mapping::{Mapping, Space}; 7 use crate::mapping::{Mapping, Space, ArithmeticTrue};
8 use crate::linops::IdOp; 8 use crate::linops::IdOp;
9 use crate::instance::{Instance, InstanceMut, DecompositionMut}; 9 use crate::instance::{Instance, InstanceMut, DecompositionMut,};
10 use crate::norms::*; 10 use crate::norms::*;
11 11
12 /// Trait for convex mappings. Has no features, just serves as a constraint 12 /// Trait for convex mappings. Has no features, just serves as a constraint
13 /// 13 ///
14 /// TODO: should constrain `Mapping::Codomain` to implement a partial order, 14 /// TODO: should constrain `Mapping::Codomain` to implement a partial order,
83 Domain : Space + Norm<F, E>, 83 Domain : Space + Norm<F, E>,
84 F : Float, 84 F : Float,
85 E : NormExponent, 85 E : NormExponent,
86 { 86 {
87 type Codomain = F; 87 type Codomain = F;
88 type ArithmeticOptIn = ArithmeticTrue;
88 89
89 fn apply<I : Instance<Domain>>(&self, d : I) -> F { 90 fn apply<I : Instance<Domain>>(&self, d : I) -> F {
90 if d.eval(|x| x.norm(self.0.exponent)) <= F::ONE { 91 if d.eval(|x| x.norm(self.0.exponent)) <= F::ONE {
91 F::ZERO 92 F::ZERO
92 } else { 93 } else {
116 fn conjugate(&self) -> Self::Conjugate<'_> { 117 fn conjugate(&self) -> Self::Conjugate<'_> {
117 NormConjugate(self.exponent.dual_exponent().as_mapping()) 118 NormConjugate(self.exponent.dual_exponent().as_mapping())
118 } 119 }
119 } 120 }
120 121
122 impl<Domain, E, F> Prox<Domain> for NormConjugate<F, E>
123 where
124 Domain : Space + Norm<F, E>,
125 E : NormExponent,
126 F : Float,
127 NormProjection<F, E> : Mapping<Domain, Codomain=Domain>,
128 {
129 type Prox<'a> = NormProjection<F, E> where Self : 'a;
130
131 #[inline]
132 fn prox_mapping(&self, τ : Self::Codomain) -> Self::Prox<'_> {
133 NormProjection{ α : τ, exponent : self.0.exponent }
134 }
135 }
136
137 pub struct NormProjection<F : Float, E : NormExponent> {
138 α : F,
139 exponent : E,
140 }
141
142 /*
143 impl<F, Domain> Mapping<Domain> for NormProjection<F, L2>
144 where
145 Domain : Space + Euclidean<F> + std::ops::MulAssign<F>,
146 F : Float,
147 {
148 type Codomain = Domain;
149
150 fn apply<I : Instance<Domain>>(&self, d : I) -> Domain {
151 d.own().proj_ball2(self.α)
152 }
153 }
154 */
155
156 impl<F, E, Domain> Mapping<Domain> for NormProjection<F, E>
157 where
158 Domain : Space + Projection<F, E> + std::ops::MulAssign<F>,
159 F : Float,
160 E : NormExponent,
161 {
162 type Codomain = Domain;
163 type ArithmeticOptIn = ArithmeticTrue;
164
165 fn apply<I : Instance<Domain>>(&self, d : I) -> Domain {
166 d.own().proj_ball(self.α, self.exponent)
167 }
168 }
121 169
122 /// The zero mapping 170 /// The zero mapping
123 pub struct Zero<Domain : Space, F : Num>(PhantomData<(Domain, F)>); 171 pub struct Zero<Domain : Space, F : Num>(PhantomData<(Domain, F)>);
124 172
125 impl<Domain : Space, F : Num> Zero<Domain, F> { 173 impl<Domain : Space, F : Num> Zero<Domain, F> {
128 } 176 }
129 } 177 }
130 178
131 impl<Domain : Space, F : Num> Mapping<Domain> for Zero<Domain, F> { 179 impl<Domain : Space, F : Num> Mapping<Domain> for Zero<Domain, F> {
132 type Codomain = F; 180 type Codomain = F;
181 type ArithmeticOptIn = ArithmeticTrue;
133 182
134 /// Compute the value of `self` at `x`. 183 /// Compute the value of `self` at `x`.
135 fn apply<I : Instance<Domain>>(&self, _x : I) -> Self::Codomain { 184 fn apply<I : Instance<Domain>>(&self, _x : I) -> Self::Codomain {
136 F::ZERO 185 F::ZERO
137 } 186 }
181 } 230 }
182 } 231 }
183 232
184 impl<Domain : Normed<F>, F : Float> Mapping<Domain> for ZeroIndicator<Domain, F> { 233 impl<Domain : Normed<F>, F : Float> Mapping<Domain> for ZeroIndicator<Domain, F> {
185 type Codomain = F; 234 type Codomain = F;
235 type ArithmeticOptIn = ArithmeticTrue;
186 236
187 /// Compute the value of `self` at `x`. 237 /// Compute the value of `self` at `x`.
188 fn apply<I : Instance<Domain>>(&self, x : I) -> Self::Codomain { 238 fn apply<I : Instance<Domain>>(&self, x : I) -> Self::Codomain {
189 x.eval(|x̃| if x̃.is_zero() { F::ZERO } else { F::INFINITY }) 239 x.eval(|x̃| if x̃.is_zero() { F::ZERO } else { F::INFINITY })
190 } 240 }

mercurial