src/convex.rs

branch
dev
changeset 59
9226980e45a7
parent 58
1a38447a89fa
child 60
848ecc05becf
equal deleted inserted replaced
58:1a38447a89fa 59:9226980e45a7
1 /*! 1 /*!
2 Some convex analysis basics 2 Some convex analysis basics
3 */ 3 */
4 4
5 use crate::mapping::{Apply, Mapping}; 5 use crate::types::*;
6 use crate::mapping::{Mapping, Space};
7 use crate::instance::{Instance, InstanceMut, DecompositionMut};
8 use crate::norms::*;
6 9
7 /// Trait for convex mappings. Has no features, just serves as a constraint 10 /// Trait for convex mappings. Has no features, just serves as a constraint
8 /// 11 ///
9 /// TODO: should constrain `Mapping::Codomain` to implement a partial order, 12 /// TODO: should constrain `Mapping::Codomain` to implement a partial order,
10 /// but this makes everything complicated with little benefit. 13 /// but this makes everything complicated with little benefit.
11 pub trait ConvexMapping<Domain> : Mapping<Domain> {} 14 pub trait ConvexMapping<Domain : Space> : Mapping<Domain>
15 {}
12 16
13 /// Trait for mappings with a Fenchel conjugate 17 /// Trait for mappings with a Fenchel conjugate
14 /// 18 ///
15 /// The conjugate type has to implement [`ConvexMapping`], but a `Conjugable` mapping need 19 /// The conjugate type has to implement [`ConvexMapping`], but a `Conjugable` mapping need
16 /// not be convex. 20 /// not be convex.
17 pub trait Conjugable<Domain> : Mapping<Domain> { 21 pub trait Conjugable<Domain : Space> : Mapping<Domain> {
18 type DualDomain; 22 type DualDomain : Space;
19 type Conjugate<'a> : ConvexMapping<Self::DualDomain> where Self : 'a; 23 type Conjugate<'a> : ConvexMapping<Self::DualDomain> where Self : 'a;
20 24
21 fn conjugate(&self) -> Self::Conjugate<'_>; 25 fn conjugate(&self) -> Self::Conjugate<'_>;
22 } 26 }
23 27
24 /// Trait for mappings with a Fenchel preconjugate 28 /// Trait for mappings with a Fenchel preconjugate
25 /// 29 ///
26 /// In contrast to [`Conjugable`], the preconjugate need not implement [`ConvexMapping`], 30 /// In contrast to [`Conjugable`], the preconjugate need not implement [`ConvexMapping`],
27 /// but a `Preconjugable` mapping has be convex. 31 /// but a `Preconjugable` mapping has be convex.
28 pub trait Preconjugable<Domain> : ConvexMapping<Domain> { 32 pub trait Preconjugable<Domain : Space> : ConvexMapping<Domain> {
29 type PredualDomain; 33 type PredualDomain : Space;
30 type Preconjugate<'a> : Mapping<Self::PredualDomain> where Self : 'a; 34 type Preconjugate<'a> : Mapping<Self::PredualDomain> where Self : 'a;
31 35
32 fn preconjugate(&self) -> Self::Preconjugate<'_>; 36 fn preconjugate(&self) -> Self::Preconjugate<'_>;
33 } 37 }
34 38
35 /// Trait for mappings with a proximap map 39 /// Trait for mappings with a proximap map
36 /// 40 ///
37 /// The conjugate type has to implement [`ConvexMapping`], but a `Conjugable` mapping need 41 /// The conjugate type has to implement [`ConvexMapping`], but a `Conjugable` mapping need
38 /// not be convex. 42 /// not be convex.
39 pub trait HasProx<Domain> : Mapping<Domain> { 43 pub trait Prox<Domain : Space> : Mapping<Domain> {
40 type Prox<'a> : Mapping<Domain, Codomain=Domain> where Self : 'a; 44 type Prox<'a> : Mapping<Domain, Codomain=Domain> where Self : 'a;
41 45
42 /// Returns a proximal mapping with weight τ 46 /// Returns a proximal mapping with weight τ
43 fn prox_mapping(&self, τ : Self::Codomain) -> Self::Prox<'_>; 47 fn prox_mapping(&self, τ : Self::Codomain) -> Self::Prox<'_>;
44 48
45 /// Calculate the proximal mapping with weight τ 49 /// Calculate the proximal mapping with weight τ
46 fn prox(&self, z : Domain, τ : Self::Codomain) -> Domain { 50 fn prox<I : Instance<Domain>>(&self, τ : Self::Codomain, z : I) -> Domain {
47 self.prox_mapping(τ).apply(z) 51 self.prox_mapping(τ).apply(z)
52 }
53
54 /// Calculate the proximal mapping with weight τ in-place
55 fn prox_mut<'b>(&self, τ : Self::Codomain, y : &'b mut Domain)
56 where
57 &'b mut Domain : InstanceMut<Domain>,
58 Domain:: Decomp : DecompositionMut<Domain>,
59 for<'a> &'a Domain : Instance<Domain>,
60 {
61 *y = self.prox(τ, &*y);
48 } 62 }
49 } 63 }
50 64
65
66 pub struct NormConjugate<F : Float, E : NormExponent>(NormMapping<F, E>);
67
68 impl<Domain, E, F> ConvexMapping<Domain> for NormMapping<F, E>
69 where
70 Domain : Space,
71 E : NormExponent,
72 F : Float,
73 Self : Mapping<Domain, Codomain=F> {}
74
75
76 impl<Domain, E, F> ConvexMapping<Domain> for NormConjugate<F, E>
77 where
78 Domain : Space,
79 E : NormExponent,
80 F : Float,
81 Self : Mapping<Domain, Codomain=F> {}
82
83
84 impl<F, E, Domain> Mapping<Domain> for NormConjugate<F, E>
85 where
86 Domain : Space + Norm<F, E>,
87 F : Float,
88 E : NormExponent,
89 {
90 type Codomain = F;
91
92 fn apply<I : Instance<Domain>>(&self, d : I) -> F {
93 if d.eval(|x| x.norm(self.0.exponent)) <= F::ONE {
94 F::ZERO
95 } else {
96 F::INFINITY
97 }
98 }
99 }
100
101
102
103 impl<E, F, Domain> Conjugable<Domain> for NormMapping<F, E>
104 where
105 E : NormExponent + Clone,
106 F : Float,
107 Domain : Norm<F, E> + Space,
108 {
109
110 type DualDomain = Domain;
111 type Conjugate<'a> = NormConjugate<F, E> where Self : 'a;
112
113 fn conjugate(&self) -> Self::Conjugate<'_> {
114 NormConjugate(self.clone())
115 }
116 }
117

mercurial