src/convex.rs

branch
dev
changeset 72
44a4f258a1ff
parent 60
848ecc05becf
child 73
ca53a962106c
equal deleted inserted replaced
71:511bf440e24b 72:44a4f258a1ff
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};
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::operator_arithmetic::{Constant, Weighted};
10 use crate::norms::*; 11 use crate::norms::*;
11 12
12 /// Trait for convex mappings. Has no features, just serves as a constraint 13 /// Trait for convex mappings. Has no features, just serves as a constraint
13 /// 14 ///
14 /// TODO: should constrain `Mapping::Codomain` to implement a partial order, 15 /// TODO: should constrain `Mapping::Codomain` to implement a partial order,
65 *y = self.prox(τ, &*y); 66 *y = self.prox(τ, &*y);
66 } 67 }
67 } 68 }
68 69
69 70
70 pub struct NormConjugate<F : Float, E : NormExponent>(NormMapping<F, E>); 71 pub struct NormConstraint<F : Float, E : NormExponent> {
72 radius : F,
73 norm : NormMapping<F, E>,
74 }
75
71 76
72 impl<Domain, E, F> ConvexMapping<Domain, F> for NormMapping<F, E> 77 impl<Domain, E, F> ConvexMapping<Domain, F> for NormMapping<F, E>
73 where 78 where
74 Domain : Space, 79 Domain : Space,
75 E : NormExponent, 80 E : NormExponent,
76 F : Float, 81 F : Float,
77 Self : Mapping<Domain, Codomain=F> 82 Self : Mapping<Domain, Codomain=F>
78 {} 83 {}
79 84
80 85
81 impl<F, E, Domain> Mapping<Domain> for NormConjugate<F, E> 86 impl<F, E, Domain> Mapping<Domain> for NormConstraint<F, E>
82 where 87 where
83 Domain : Space + Norm<F, E>, 88 Domain : Space + Norm<F, E>,
84 F : Float, 89 F : Float,
85 E : NormExponent, 90 E : NormExponent,
86 { 91 {
87 type Codomain = F; 92 type Codomain = F;
88 93
89 fn apply<I : Instance<Domain>>(&self, d : I) -> F { 94 fn apply<I : Instance<Domain>>(&self, d : I) -> F {
90 if d.eval(|x| x.norm(self.0.exponent)) <= F::ONE { 95 if d.eval(|x| x.norm(self.norm.exponent)) <= self.radius {
91 F::ZERO 96 F::ZERO
92 } else { 97 } else {
93 F::INFINITY 98 F::INFINITY
94 } 99 }
95 } 100 }
96 } 101 }
97 102
98 impl<Domain, E, F> ConvexMapping<Domain, F> for NormConjugate<F, E> 103 impl<Domain, E, F> ConvexMapping<Domain, F> for NormConstraint<F, E>
99 where 104 where
100 Domain : Space, 105 Domain : Space,
101 E : NormExponent, 106 E : NormExponent,
102 F : Float, 107 F : Float,
103 Self : Mapping<Domain, Codomain=F> 108 Self : Mapping<Domain, Codomain=F>
109 E : HasDualExponent, 114 E : HasDualExponent,
110 F : Float, 115 F : Float,
111 Domain : HasDual<F> + Norm<F, E> + Space, 116 Domain : HasDual<F> + Norm<F, E> + Space,
112 <Domain as HasDual<F>>::DualSpace : Norm<F, E::DualExp> 117 <Domain as HasDual<F>>::DualSpace : Norm<F, E::DualExp>
113 { 118 {
114 type Conjugate<'a> = NormConjugate<F, E::DualExp> where Self : 'a; 119 type Conjugate<'a> = NormConstraint<F, E::DualExp> where Self : 'a;
115 120
116 fn conjugate(&self) -> Self::Conjugate<'_> { 121 fn conjugate(&self) -> Self::Conjugate<'_> {
117 NormConjugate(self.exponent.dual_exponent().as_mapping()) 122 NormConstraint {
123 radius : F::ONE,
124 norm : self.exponent.dual_exponent().as_mapping()
125 }
126 }
127 }
128
129 impl<C, E, F, Domain> Conjugable<Domain, F> for Weighted<NormMapping<F, E>, C>
130 where
131 C : Constant<Type = F>,
132 E : HasDualExponent,
133 F : Float,
134 Domain : HasDual<F> + Norm<F, E> + Space,
135 <Domain as HasDual<F>>::DualSpace : Norm<F, E::DualExp>
136 {
137 type Conjugate<'a> = NormConstraint<F, E::DualExp> where Self : 'a;
138
139 fn conjugate(&self) -> Self::Conjugate<'_> {
140 NormConstraint {
141 radius : self.weight.value(),
142 norm : self.base_fn.exponent.dual_exponent().as_mapping()
143 }
144 }
145 }
146
147 impl<Domain, E, F> Prox<Domain> for NormConstraint<F, E>
148 where
149 Domain : Space + Norm<F, E>,
150 E : NormExponent,
151 F : Float,
152 NormProjection<F, E> : Mapping<Domain, Codomain=Domain>,
153 {
154 type Prox<'a> = NormProjection<F, E> where Self : 'a;
155
156 #[inline]
157 fn prox_mapping(&self, _τ : Self::Codomain) -> Self::Prox<'_> {
158 assert!(self.radius >= F::ZERO);
159 NormProjection{ radius : self.radius, exponent : self.norm.exponent }
160 }
161 }
162
163 pub struct NormProjection<F : Float, E : NormExponent> {
164 radius : F,
165 exponent : E,
166 }
167
168 /*
169 impl<F, Domain> Mapping<Domain> for NormProjection<F, L2>
170 where
171 Domain : Space + Euclidean<F> + std::ops::MulAssign<F>,
172 F : Float,
173 {
174 type Codomain = Domain;
175
176 fn apply<I : Instance<Domain>>(&self, d : I) -> Domain {
177 d.own().proj_ball2(self.radius)
178 }
179 }
180 */
181
182 impl<F, E, Domain> Mapping<Domain> for NormProjection<F, E>
183 where
184 Domain : Space + Projection<F, E> + std::ops::MulAssign<F>,
185 F : Float,
186 E : NormExponent,
187 {
188 type Codomain = Domain;
189
190 fn apply<I : Instance<Domain>>(&self, d : I) -> Domain {
191 d.own().proj_ball(self.radius, self.exponent)
118 } 192 }
119 } 193 }
120 194
121 195
122 /// The zero mapping 196 /// The zero mapping

mercurial