src/convex.rs

branch
dev
changeset 60
848ecc05becf
parent 59
9226980e45a7
child 72
44a4f258a1ff
child 80
f802ddbabcfc
equal deleted inserted replaced
59:9226980e45a7 60:848ecc05becf
1 /*! 1 /*!
2 Some convex analysis basics 2 Some convex analysis basics
3 */ 3 */
4 4
5 use std::marker::PhantomData;
5 use crate::types::*; 6 use crate::types::*;
6 use crate::mapping::{Mapping, Space}; 7 use crate::mapping::{Mapping, Space};
8 use crate::linops::IdOp;
7 use crate::instance::{Instance, InstanceMut, DecompositionMut}; 9 use crate::instance::{Instance, InstanceMut, DecompositionMut};
8 use crate::norms::*; 10 use crate::norms::*;
9 11
10 /// 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
11 /// 13 ///
12 /// TODO: should constrain `Mapping::Codomain` to implement a partial order, 14 /// TODO: should constrain `Mapping::Codomain` to implement a partial order,
13 /// but this makes everything complicated with little benefit. 15 /// but this makes everything complicated with little benefit.
14 pub trait ConvexMapping<Domain : Space> : Mapping<Domain> 16 pub trait ConvexMapping<Domain : Space, F : Num = f64> : Mapping<Domain, Codomain = F>
15 {} 17 {}
16 18
17 /// Trait for mappings with a Fenchel conjugate 19 /// Trait for mappings with a Fenchel conjugate
18 /// 20 ///
19 /// The conjugate type has to implement [`ConvexMapping`], but a `Conjugable` mapping need 21 /// The conjugate type has to implement [`ConvexMapping`], but a `Conjugable` mapping need
20 /// not be convex. 22 /// not be convex.
21 pub trait Conjugable<Domain : Space> : Mapping<Domain> { 23 pub trait Conjugable<Domain : HasDual<F>, F : Num = f64> : Mapping<Domain> {
22 type DualDomain : Space; 24 type Conjugate<'a> : ConvexMapping<Domain::DualSpace, F> where Self : 'a;
23 type Conjugate<'a> : ConvexMapping<Self::DualDomain> where Self : 'a;
24 25
25 fn conjugate(&self) -> Self::Conjugate<'_>; 26 fn conjugate(&self) -> Self::Conjugate<'_>;
26 } 27 }
27 28
28 /// Trait for mappings with a Fenchel preconjugate 29 /// Trait for mappings with a Fenchel preconjugate
29 /// 30 ///
30 /// In contrast to [`Conjugable`], the preconjugate need not implement [`ConvexMapping`], 31 /// In contrast to [`Conjugable`], the preconjugate need not implement [`ConvexMapping`],
31 /// but a `Preconjugable` mapping has be convex. 32 /// but a `Preconjugable` mapping has to be convex.
32 pub trait Preconjugable<Domain : Space> : ConvexMapping<Domain> { 33 pub trait Preconjugable<Domain, Predual, F : Num = f64> : ConvexMapping<Domain, F>
33 type PredualDomain : Space; 34 where
34 type Preconjugate<'a> : Mapping<Self::PredualDomain> where Self : 'a; 35 Domain : Space,
36 Predual : HasDual<F>
37 {
38 type Preconjugate<'a> : Mapping<Predual> where Self : 'a;
35 39
36 fn preconjugate(&self) -> Self::Preconjugate<'_>; 40 fn preconjugate(&self) -> Self::Preconjugate<'_>;
37 } 41 }
38 42
39 /// Trait for mappings with a proximap map 43 /// Trait for mappings with a proximap map
63 } 67 }
64 68
65 69
66 pub struct NormConjugate<F : Float, E : NormExponent>(NormMapping<F, E>); 70 pub struct NormConjugate<F : Float, E : NormExponent>(NormMapping<F, E>);
67 71
68 impl<Domain, E, F> ConvexMapping<Domain> for NormMapping<F, E> 72 impl<Domain, E, F> ConvexMapping<Domain, F> for NormMapping<F, E>
69 where 73 where
70 Domain : Space, 74 Domain : Space,
71 E : NormExponent, 75 E : NormExponent,
72 F : Float, 76 F : Float,
73 Self : Mapping<Domain, Codomain=F> {} 77 Self : Mapping<Domain, Codomain=F>
74 78 {}
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 79
83 80
84 impl<F, E, Domain> Mapping<Domain> for NormConjugate<F, E> 81 impl<F, E, Domain> Mapping<Domain> for NormConjugate<F, E>
85 where 82 where
86 Domain : Space + Norm<F, E>, 83 Domain : Space + Norm<F, E>,
96 F::INFINITY 93 F::INFINITY
97 } 94 }
98 } 95 }
99 } 96 }
100 97
101 98 impl<Domain, E, F> ConvexMapping<Domain, F> for NormConjugate<F, E>
102 99 where
103 impl<E, F, Domain> Conjugable<Domain> for NormMapping<F, E> 100 Domain : Space,
104 where 101 E : NormExponent,
105 E : NormExponent + Clone, 102 F : Float,
106 F : Float, 103 Self : Mapping<Domain, Codomain=F>
107 Domain : Norm<F, E> + Space, 104 {}
108 { 105
109 106
110 type DualDomain = Domain; 107 impl<E, F, Domain> Conjugable<Domain, F> for NormMapping<F, E>
111 type Conjugate<'a> = NormConjugate<F, E> where Self : 'a; 108 where
109 E : HasDualExponent,
110 F : Float,
111 Domain : HasDual<F> + Norm<F, E> + Space,
112 <Domain as HasDual<F>>::DualSpace : Norm<F, E::DualExp>
113 {
114 type Conjugate<'a> = NormConjugate<F, E::DualExp> where Self : 'a;
112 115
113 fn conjugate(&self) -> Self::Conjugate<'_> { 116 fn conjugate(&self) -> Self::Conjugate<'_> {
114 NormConjugate(self.clone()) 117 NormConjugate(self.exponent.dual_exponent().as_mapping())
115 } 118 }
116 } 119 }
117 120
121
122 /// The zero mapping
123 pub struct Zero<Domain : Space, F : Num>(PhantomData<(Domain, F)>);
124
125 impl<Domain : Space, F : Num> Zero<Domain, F> {
126 pub fn new() -> Self {
127 Zero(PhantomData)
128 }
129 }
130
131 impl<Domain : Space, F : Num> Mapping<Domain> for Zero<Domain, F> {
132 type Codomain = F;
133
134 /// Compute the value of `self` at `x`.
135 fn apply<I : Instance<Domain>>(&self, _x : I) -> Self::Codomain {
136 F::ZERO
137 }
138 }
139
140 impl<Domain : Space, F : Num> ConvexMapping<Domain, F> for Zero<Domain, F> { }
141
142
143 impl<Domain : HasDual<F>, F : Float> Conjugable<Domain, F> for Zero<Domain, F> {
144 type Conjugate<'a> = ZeroIndicator<Domain::DualSpace, F> where Self : 'a;
145
146 #[inline]
147 fn conjugate(&self) -> Self::Conjugate<'_> {
148 ZeroIndicator::new()
149 }
150 }
151
152 impl<Domain, Predual, F : Float> Preconjugable<Domain, Predual, F> for Zero<Domain, F>
153 where
154 Domain : Space,
155 Predual : HasDual<F>
156 {
157 type Preconjugate<'a> = ZeroIndicator<Predual, F> where Self : 'a;
158
159 #[inline]
160 fn preconjugate(&self) -> Self::Preconjugate<'_> {
161 ZeroIndicator::new()
162 }
163 }
164
165 impl<Domain : Space + Clone, F : Num> Prox<Domain> for Zero<Domain, F> {
166 type Prox<'a> = IdOp<Domain> where Self : 'a;
167
168 #[inline]
169 fn prox_mapping(&self, _τ : Self::Codomain) -> Self::Prox<'_> {
170 IdOp::new()
171 }
172 }
173
174
175 /// The zero indicator
176 pub struct ZeroIndicator<Domain : Space, F : Num>(PhantomData<(Domain, F)>);
177
178 impl<Domain : Space, F : Num> ZeroIndicator<Domain, F> {
179 pub fn new() -> Self {
180 ZeroIndicator(PhantomData)
181 }
182 }
183
184 impl<Domain : Normed<F>, F : Float> Mapping<Domain> for ZeroIndicator<Domain, F> {
185 type Codomain = F;
186
187 /// Compute the value of `self` at `x`.
188 fn apply<I : Instance<Domain>>(&self, x : I) -> Self::Codomain {
189 x.eval(|x̃| if x̃.is_zero() { F::ZERO } else { F::INFINITY })
190 }
191 }
192
193 impl<Domain : Normed<F>, F : Float> ConvexMapping<Domain, F> for ZeroIndicator<Domain, F> { }
194
195 impl<Domain : HasDual<F>, F : Float> Conjugable<Domain, F> for ZeroIndicator<Domain, F> {
196 type Conjugate<'a> = Zero<Domain::DualSpace, F> where Self : 'a;
197
198 #[inline]
199 fn conjugate(&self) -> Self::Conjugate<'_> {
200 Zero::new()
201 }
202 }
203
204 impl<Domain, Predual, F : Float> Preconjugable<Domain, Predual, F> for ZeroIndicator<Domain, F>
205 where
206 Domain : Normed<F>,
207 Predual : HasDual<F>
208 {
209 type Preconjugate<'a> = Zero<Predual, F> where Self : 'a;
210
211 #[inline]
212 fn preconjugate(&self) -> Self::Preconjugate<'_> {
213 Zero::new()
214 }
215 }

mercurial