src/convex.rs

branch
dev
changeset 150
c4e394a9c84c
parent 146
3f9a03f95457
child 151
402d717bb5c0
equal deleted inserted replaced
149:2f1798c65fd6 150:c4e394a9c84c
2 Some convex analysis basics 2 Some convex analysis basics
3 */ 3 */
4 4
5 use crate::error::DynResult; 5 use crate::error::DynResult;
6 use crate::euclidean::Euclidean; 6 use crate::euclidean::Euclidean;
7 use crate::instance::{DecompositionMut, Instance, InstanceMut}; 7 use crate::instance::{ClosedSpace, DecompositionMut, Instance};
8 use crate::linops::{IdOp, Scaled, SimpleZeroOp, AXPY}; 8 use crate::linops::{IdOp, Scaled, SimpleZeroOp, AXPY};
9 use crate::mapping::{DifferentiableImpl, LipschitzDifferentiableImpl, Mapping, Space}; 9 use crate::mapping::{DifferentiableImpl, LipschitzDifferentiableImpl, Mapping, Space};
10 use crate::norms::*; 10 use crate::norms::*;
11 use crate::operator_arithmetic::{Constant, Weighted}; 11 use crate::operator_arithmetic::{Constant, Weighted};
12 use crate::types::*; 12 use crate::types::*;
55 /// Trait for mappings with a proximap map 55 /// Trait for mappings with a proximap map
56 /// 56 ///
57 /// The conjugate type has to implement [`ConvexMapping`], but a `Conjugable` mapping need 57 /// The conjugate type has to implement [`ConvexMapping`], but a `Conjugable` mapping need
58 /// not be convex. 58 /// not be convex.
59 pub trait Prox<Domain: Space>: Mapping<Domain> { 59 pub trait Prox<Domain: Space>: Mapping<Domain> {
60 type Prox<'a>: Mapping<Domain, Codomain = Domain> 60 type Prox<'a>: Mapping<Domain, Codomain = Domain::OwnedSpace>
61 where 61 where
62 Self: 'a; 62 Self: 'a;
63 63
64 /// Returns a proximal mapping with weight τ 64 /// Returns a proximal mapping with weight τ
65 fn prox_mapping(&self, τ: Self::Codomain) -> Self::Prox<'_>; 65 fn prox_mapping(&self, τ: Self::Codomain) -> Self::Prox<'_>;
66 66
67 /// Calculate the proximal mapping with weight τ 67 /// Calculate the proximal mapping with weight τ
68 fn prox<I: Instance<Domain>>(&self, τ: Self::Codomain, z: I) -> Domain { 68 fn prox<I: Instance<Domain>>(&self, τ: Self::Codomain, z: I) -> Domain::OwnedSpace {
69 self.prox_mapping(τ).apply(z) 69 self.prox_mapping(τ).apply(z)
70 } 70 }
71 71
72 /// Calculate the proximal mapping with weight τ in-place 72 /// Calculate the proximal mapping with weight τ in-place
73 fn prox_mut<'b>(&self, τ: Self::Codomain, y: &'b mut Domain) 73 fn prox_mut<'b>(&self, τ: Self::Codomain, y: &'b mut Domain::OwnedSpace)
74 where 74 where
75 &'b mut Domain: InstanceMut<Domain>,
76 Domain::Decomp: DecompositionMut<Domain>, 75 Domain::Decomp: DecompositionMut<Domain>,
77 for<'a> &'a Domain: Instance<Domain>, 76 for<'a> &'a Domain::OwnedSpace: Instance<Domain>,
78 { 77 {
79 *y = self.prox(τ, &*y); 78 *y = self.prox(τ, &*y);
80 } 79 }
81 } 80 }
82 81
163 impl<Domain, E, F> Prox<Domain> for NormConstraint<F, E> 162 impl<Domain, E, F> Prox<Domain> for NormConstraint<F, E>
164 where 163 where
165 Domain: Space + Norm<E, F>, 164 Domain: Space + Norm<E, F>,
166 E: NormExponent, 165 E: NormExponent,
167 F: Float, 166 F: Float,
168 NormProjection<F, E>: Mapping<Domain, Codomain = Domain>, 167 NormProjection<F, E>: Mapping<Domain, Codomain = Domain::OwnedSpace>,
169 { 168 {
170 type Prox<'a> 169 type Prox<'a>
171 = NormProjection<F, E> 170 = NormProjection<F, E>
172 where 171 where
173 Self: 'a; 172 Self: 'a;
201 */ 200 */
202 201
203 impl<F, E, Domain> Mapping<Domain> for NormProjection<F, E> 202 impl<F, E, Domain> Mapping<Domain> for NormProjection<F, E>
204 where 203 where
205 Domain: Normed<F> + Projection<F, E>, 204 Domain: Normed<F> + Projection<F, E>,
205 Domain::OwnedSpace: ClosedSpace,
206 F: Float, 206 F: Float,
207 E: NormExponent, 207 E: NormExponent,
208 { 208 {
209 type Codomain = Domain; 209 type Codomain = Domain::OwnedSpace;
210 210
211 fn apply<I: Instance<Domain>>(&self, d: I) -> Domain { 211 fn apply<I: Instance<Domain>>(&self, d: I) -> Self::Codomain {
212 d.own().proj_ball(self.radius, self.exponent) 212 d.own().proj_ball(self.radius, self.exponent)
213 } 213 }
214 } 214 }
215 215
216 /// The zero mapping 216 /// The zero mapping
260 fn preconjugate(&self) -> Self::Preconjugate<'_> { 260 fn preconjugate(&self) -> Self::Preconjugate<'_> {
261 ZeroIndicator::new() 261 ZeroIndicator::new()
262 } 262 }
263 } 263 }
264 264
265 impl<Domain: Space + Clone, F: Num> Prox<Domain> for Zero<Domain, F> { 265 impl<Domain: Space, F: Num> Prox<Domain> for Zero<Domain, F> {
266 type Prox<'a> 266 type Prox<'a>
267 = IdOp<Domain> 267 = IdOp<Domain>
268 where 268 where
269 Self: 'a; 269 Self: 'a;
270 270
393 } 393 }
394 394
395 impl<X, F> Prox<X> for Norm222<F> 395 impl<X, F> Prox<X> for Norm222<F>
396 where 396 where
397 F: Float, 397 F: Float,
398 X: Euclidean<F, Owned = X>, 398 X: Euclidean<F, Owned = X> + ClosedMul<F>,
399 { 399 {
400 type Prox<'a> 400 type Prox<'a>
401 = Scaled<F> 401 = Scaled<F>
402 where 402 where
403 Self: 'a; 403 Self: 'a;
408 } 408 }
409 409
410 impl<X, F> DifferentiableImpl<X> for Norm222<F> 410 impl<X, F> DifferentiableImpl<X> for Norm222<F>
411 where 411 where
412 F: Float, 412 F: Float,
413 X: Euclidean<F, Owned = X>, 413 X: Euclidean<F>,
414 { 414 {
415 type Derivative = X; 415 type Derivative = X::Owned;
416 416
417 fn differential_impl<I: Instance<X>>(&self, x: I) -> X { 417 fn differential_impl<I: Instance<X>>(&self, x: I) -> Self::Derivative {
418 x.own() 418 x.own()
419 } 419 }
420 } 420 }
421 421
422 impl<X, F> LipschitzDifferentiableImpl<X, L2> for Norm222<F> 422 impl<X, F> LipschitzDifferentiableImpl<X, L2> for Norm222<F>
423 where 423 where
424 F: Float, 424 F: Float,
425 X: Euclidean<F, Owned = X>, 425 X: Euclidean<F>,
426 { 426 {
427 type FloatType = F; 427 type FloatType = F;
428 428
429 fn diff_lipschitz_factor(&self, _: L2) -> DynResult<Self::FloatType> { 429 fn diff_lipschitz_factor(&self, _: L2) -> DynResult<Self::FloatType> {
430 Ok(F::ONE) 430 Ok(F::ONE)

mercurial