| 15 |
15 |
| 16 /// Trait for convex mappings. Has no features, just serves as a constraint |
16 /// Trait for convex mappings. Has no features, just serves as a constraint |
| 17 /// |
17 /// |
| 18 /// TODO: should constrain `Mapping::Codomain` to implement a partial order, |
18 /// TODO: should constrain `Mapping::Codomain` to implement a partial order, |
| 19 /// but this makes everything complicated with little benefit. |
19 /// but this makes everything complicated with little benefit. |
| 20 pub trait ConvexMapping<Domain: Normed<F>, F: Num = f64>: Mapping<Domain, Codomain = F> { |
20 pub trait ConvexMapping<Domain: Space, F: Num = f64>: Mapping<Domain, Codomain = F> { |
| 21 /// Returns (a lower estimate of) the factor of strong convexity in the norm of `Domain`. |
21 /// Returns (a lower estimate of) the factor of strong convexity in the norm of `Domain`. |
| 22 fn factor_of_strong_convexity(&self) -> F { |
22 fn factor_of_strong_convexity(&self) -> F { |
| 23 F::ZERO |
23 F::ZERO |
| 24 } |
24 } |
| 25 } |
25 } |
| 40 /// |
40 /// |
| 41 /// In contrast to [`Conjugable`], the preconjugate need not implement [`ConvexMapping`], |
41 /// In contrast to [`Conjugable`], the preconjugate need not implement [`ConvexMapping`], |
| 42 /// but a `Preconjugable` mapping has to be convex. |
42 /// but a `Preconjugable` mapping has to be convex. |
| 43 pub trait Preconjugable<Domain, Predual, F: Num = f64>: ConvexMapping<Domain, F> |
43 pub trait Preconjugable<Domain, Predual, F: Num = f64>: ConvexMapping<Domain, F> |
| 44 where |
44 where |
| 45 Domain: Normed<F>, |
45 Domain: Space, |
| 46 Predual: HasDual<F>, |
46 Predual: HasDual<F>, |
| 47 { |
47 { |
| 48 type Preconjugate<'a>: Mapping<Predual, Codomain = F> |
48 type Preconjugate<'a>: Mapping<Predual, Codomain = F> |
| 49 where |
49 where |
| 50 Self: 'a; |
50 Self: 'a; |
| 86 norm: NormMapping<F, E>, |
86 norm: NormMapping<F, E>, |
| 87 } |
87 } |
| 88 |
88 |
| 89 impl<Domain, E, F> ConvexMapping<Domain, F> for NormMapping<F, E> |
89 impl<Domain, E, F> ConvexMapping<Domain, F> for NormMapping<F, E> |
| 90 where |
90 where |
| 91 Domain: Normed<F>, |
91 Domain: Space, |
| 92 E: NormExponent, |
92 E: NormExponent, |
| 93 F: Float, |
93 F: Float, |
| 94 Self: Mapping<Domain, Codomain = F>, |
94 Self: Mapping<Domain, Codomain = F>, |
| 95 { |
95 { |
| 96 } |
96 } |
| 97 |
97 |
| 98 impl<F, E, Domain> Mapping<Domain> for NormConstraint<F, E> |
98 impl<F, E, Domain> Mapping<Domain> for NormConstraint<F, E> |
| 99 where |
99 where |
| 100 Domain: Space + Norm<E, F>, |
100 Domain: Space, |
| |
101 Domain::OwnedSpace: Norm<E, F>, |
| 101 F: Float, |
102 F: Float, |
| 102 E: NormExponent, |
103 E: NormExponent, |
| 103 { |
104 { |
| 104 type Codomain = F; |
105 type Codomain = F; |
| 105 |
106 |
| 112 } |
113 } |
| 113 } |
114 } |
| 114 |
115 |
| 115 impl<Domain, E, F> ConvexMapping<Domain, F> for NormConstraint<F, E> |
116 impl<Domain, E, F> ConvexMapping<Domain, F> for NormConstraint<F, E> |
| 116 where |
117 where |
| 117 Domain: Normed<F>, |
118 Domain: Space, |
| 118 E: NormExponent, |
119 E: NormExponent, |
| 119 F: Float, |
120 F: Float, |
| 120 Self: Mapping<Domain, Codomain = F>, |
121 Self: Mapping<Domain, Codomain = F>, |
| 121 { |
122 { |
| 122 } |
123 } |
| 123 |
124 |
| 124 impl<E, F, Domain> Conjugable<Domain, F> for NormMapping<F, E> |
125 impl<E, F, Domain> Conjugable<Domain, F> for NormMapping<F, E> |
| 125 where |
126 where |
| 126 E: HasDualExponent, |
127 E: HasDualExponent, |
| 127 F: Float, |
128 F: Float, |
| 128 Domain: HasDual<F> + Norm<E, F> + Normed<F>, |
129 Domain: HasDual<F>, |
| |
130 Domain::OwnedSpace: Norm<E, F>, |
| 129 <Domain as HasDual<F>>::DualSpace: Norm<E::DualExp, F>, |
131 <Domain as HasDual<F>>::DualSpace: Norm<E::DualExp, F>, |
| 130 { |
132 { |
| 131 type Conjugate<'a> |
133 type Conjugate<'a> |
| 132 = NormConstraint<F, E::DualExp> |
134 = NormConstraint<F, E::DualExp> |
| 133 where |
135 where |
| 141 impl<C, E, F, Domain> Conjugable<Domain, F> for Weighted<NormMapping<F, E>, C> |
143 impl<C, E, F, Domain> Conjugable<Domain, F> for Weighted<NormMapping<F, E>, C> |
| 142 where |
144 where |
| 143 C: Constant<Type = F>, |
145 C: Constant<Type = F>, |
| 144 E: HasDualExponent, |
146 E: HasDualExponent, |
| 145 F: Float, |
147 F: Float, |
| 146 Domain: HasDual<F> + Norm<E, F> + Space, |
148 Domain: HasDual<F>, |
| |
149 Domain::OwnedSpace: Norm<E, F>, |
| 147 <Domain as HasDual<F>>::DualSpace: Norm<E::DualExp, F>, |
150 <Domain as HasDual<F>>::DualSpace: Norm<E::DualExp, F>, |
| 148 { |
151 { |
| 149 type Conjugate<'a> |
152 type Conjugate<'a> |
| 150 = NormConstraint<F, E::DualExp> |
153 = NormConstraint<F, E::DualExp> |
| 151 where |
154 where |
| 159 } |
162 } |
| 160 } |
163 } |
| 161 |
164 |
| 162 impl<Domain, E, F> Prox<Domain> for NormConstraint<F, E> |
165 impl<Domain, E, F> Prox<Domain> for NormConstraint<F, E> |
| 163 where |
166 where |
| 164 Domain: Space + Norm<E, F>, |
167 Domain: Space, |
| |
168 Domain::OwnedSpace: Norm<E, F>, |
| 165 E: NormExponent, |
169 E: NormExponent, |
| 166 F: Float, |
170 F: Float, |
| 167 NormProjection<F, E>: Mapping<Domain, Codomain = Domain::OwnedSpace>, |
171 NormProjection<F, E>: Mapping<Domain, Codomain = Domain::OwnedSpace>, |
| 168 { |
172 { |
| 169 type Prox<'a> |
173 type Prox<'a> |
| 199 } |
203 } |
| 200 */ |
204 */ |
| 201 |
205 |
| 202 impl<F, E, Domain> Mapping<Domain> for NormProjection<F, E> |
206 impl<F, E, Domain> Mapping<Domain> for NormProjection<F, E> |
| 203 where |
207 where |
| 204 Domain: Normed<F> + Projection<F, E>, |
208 Domain: Space, |
| 205 Domain::OwnedSpace: ClosedSpace, |
209 Domain::OwnedSpace: ClosedSpace + Projection<F, E>, |
| 206 F: Float, |
210 F: Float, |
| 207 E: NormExponent, |
211 E: NormExponent, |
| 208 { |
212 { |
| 209 type Codomain = Domain::OwnedSpace; |
213 type Codomain = Domain::OwnedSpace; |
| 210 |
214 |
| 230 fn apply<I: Instance<Domain>>(&self, _x: I) -> Self::Codomain { |
234 fn apply<I: Instance<Domain>>(&self, _x: I) -> Self::Codomain { |
| 231 F::ZERO |
235 F::ZERO |
| 232 } |
236 } |
| 233 } |
237 } |
| 234 |
238 |
| 235 impl<Domain: Normed<F>, F: Float> ConvexMapping<Domain, F> for Zero<Domain, F> {} |
239 impl<Domain: Space, F: Float> ConvexMapping<Domain, F> for Zero<Domain, F> {} |
| 236 |
240 |
| 237 impl<Domain: HasDual<F>, F: Float> Conjugable<Domain, F> for Zero<Domain, F> { |
241 impl<Domain: HasDual<F>, F: Float> Conjugable<Domain, F> for Zero<Domain, F> { |
| 238 type Conjugate<'a> |
242 type Conjugate<'a> |
| 239 = ZeroIndicator<Domain::DualSpace, F> |
243 = ZeroIndicator<Domain::DualSpace, F> |
| 240 where |
244 where |
| 247 } |
251 } |
| 248 |
252 |
| 249 impl<Domain, Predual, F: Float> Preconjugable<Domain, Predual, F> for Zero<Domain, F> |
253 impl<Domain, Predual, F: Float> Preconjugable<Domain, Predual, F> for Zero<Domain, F> |
| 250 where |
254 where |
| 251 Domain: Normed<F>, |
255 Domain: Normed<F>, |
| 252 Predual: HasDual<F>, |
256 Predual: HasDual<F, Owned = Predual>, |
| 253 { |
257 { |
| 254 type Preconjugate<'a> |
258 type Preconjugate<'a> |
| 255 = ZeroIndicator<Predual, F> |
259 = ZeroIndicator<Predual, F> |
| 256 where |
260 where |
| 257 Self: 'a; |
261 Self: 'a; |
| 282 pub fn new() -> Self { |
286 pub fn new() -> Self { |
| 283 ZeroIndicator(PhantomData) |
287 ZeroIndicator(PhantomData) |
| 284 } |
288 } |
| 285 } |
289 } |
| 286 |
290 |
| 287 impl<Domain: Normed<F>, F: Float> Mapping<Domain> for ZeroIndicator<Domain, F> { |
291 impl<Domain, F> Mapping<Domain> for ZeroIndicator<Domain, F> |
| |
292 where |
| |
293 F: Float, |
| |
294 Domain: Space, |
| |
295 Domain::OwnedSpace: Normed<F>, |
| |
296 { |
| 288 type Codomain = F; |
297 type Codomain = F; |
| 289 |
298 |
| 290 /// Compute the value of `self` at `x`. |
299 /// Compute the value of `self` at `x`. |
| 291 fn apply<I: Instance<Domain>>(&self, x: I) -> Self::Codomain { |
300 fn apply<I: Instance<Domain>>(&self, x: I) -> Self::Codomain { |
| 292 x.eval(|x̃| if x̃.is_zero() { F::ZERO } else { F::INFINITY }) |
301 x.eval(|x̃| if x̃.is_zero() { F::ZERO } else { F::INFINITY }) |
| 293 } |
302 } |
| 294 } |
303 } |
| 295 |
304 |
| 296 impl<Domain: Normed<F>, F: Float> ConvexMapping<Domain, F> for ZeroIndicator<Domain, F> { |
305 impl<Domain, F: Float> ConvexMapping<Domain, F> for ZeroIndicator<Domain, F> |
| |
306 where |
| |
307 Domain: Space, |
| |
308 Domain::OwnedSpace: Normed<F>, |
| |
309 { |
| 297 fn factor_of_strong_convexity(&self) -> F { |
310 fn factor_of_strong_convexity(&self) -> F { |
| 298 F::INFINITY |
311 F::INFINITY |
| 299 } |
312 } |
| 300 } |
313 } |
| 301 |
314 |
| 302 impl<Domain: HasDual<F>, F: Float> Conjugable<Domain, F> for ZeroIndicator<Domain, F> { |
315 impl<Domain, F: Float> Conjugable<Domain, F> for ZeroIndicator<Domain, F> |
| |
316 where |
| |
317 Domain: HasDual<F>, |
| |
318 Domain::Owned: Normed<F>, |
| |
319 { |
| 303 type Conjugate<'a> |
320 type Conjugate<'a> |
| 304 = Zero<Domain::DualSpace, F> |
321 = Zero<Domain::DualSpace, F> |
| 305 where |
322 where |
| 306 Self: 'a; |
323 Self: 'a; |
| 307 |
324 |
| 311 } |
328 } |
| 312 } |
329 } |
| 313 |
330 |
| 314 impl<Domain, Predual, F: Float> Preconjugable<Domain, Predual, F> for ZeroIndicator<Domain, F> |
331 impl<Domain, Predual, F: Float> Preconjugable<Domain, Predual, F> for ZeroIndicator<Domain, F> |
| 315 where |
332 where |
| 316 Domain: Normed<F>, |
333 Domain: Space, |
| |
334 Domain::OwnedSpace: Normed<F>, |
| 317 Predual: HasDual<F>, |
335 Predual: HasDual<F>, |
| 318 { |
336 { |
| 319 type Preconjugate<'a> |
337 type Preconjugate<'a> |
| 320 = Zero<Predual, F> |
338 = Zero<Predual, F> |
| 321 where |
339 where |