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 } |