diff -r 511bf440e24b -r 44a4f258a1ff src/convex.rs --- a/src/convex.rs Tue Dec 24 13:40:36 2024 -0500 +++ b/src/convex.rs Tue Dec 24 14:07:52 2024 -0500 @@ -7,6 +7,7 @@ use crate::mapping::{Mapping, Space}; use crate::linops::IdOp; use crate::instance::{Instance, InstanceMut, DecompositionMut}; +use crate::operator_arithmetic::{Constant, Weighted}; use crate::norms::*; /// Trait for convex mappings. Has no features, just serves as a constraint @@ -67,7 +68,11 @@ } -pub struct NormConjugate(NormMapping); +pub struct NormConstraint { + radius : F, + norm : NormMapping, +} + impl ConvexMapping for NormMapping where @@ -78,7 +83,7 @@ {} -impl Mapping for NormConjugate +impl Mapping for NormConstraint where Domain : Space + Norm, F : Float, @@ -87,7 +92,7 @@ type Codomain = F; fn apply>(&self, d : I) -> F { - if d.eval(|x| x.norm(self.0.exponent)) <= F::ONE { + if d.eval(|x| x.norm(self.norm.exponent)) <= self.radius { F::ZERO } else { F::INFINITY @@ -95,7 +100,7 @@ } } -impl ConvexMapping for NormConjugate +impl ConvexMapping for NormConstraint where Domain : Space, E : NormExponent, @@ -111,10 +116,79 @@ Domain : HasDual + Norm + Space, >::DualSpace : Norm { - type Conjugate<'a> = NormConjugate where Self : 'a; + type Conjugate<'a> = NormConstraint where Self : 'a; + + fn conjugate(&self) -> Self::Conjugate<'_> { + NormConstraint { + radius : F::ONE, + norm : self.exponent.dual_exponent().as_mapping() + } + } +} + +impl Conjugable for Weighted, C> +where + C : Constant, + E : HasDualExponent, + F : Float, + Domain : HasDual + Norm + Space, + >::DualSpace : Norm +{ + type Conjugate<'a> = NormConstraint where Self : 'a; fn conjugate(&self) -> Self::Conjugate<'_> { - NormConjugate(self.exponent.dual_exponent().as_mapping()) + NormConstraint { + radius : self.weight.value(), + norm : self.base_fn.exponent.dual_exponent().as_mapping() + } + } +} + +impl Prox for NormConstraint +where + Domain : Space + Norm, + E : NormExponent, + F : Float, + NormProjection : Mapping, +{ + type Prox<'a> = NormProjection where Self : 'a; + + #[inline] + fn prox_mapping(&self, _τ : Self::Codomain) -> Self::Prox<'_> { + assert!(self.radius >= F::ZERO); + NormProjection{ radius : self.radius, exponent : self.norm.exponent } + } +} + +pub struct NormProjection { + radius : F, + exponent : E, +} + +/* +impl Mapping for NormProjection +where + Domain : Space + Euclidean + std::ops::MulAssign, + F : Float, +{ + type Codomain = Domain; + + fn apply>(&self, d : I) -> Domain { + d.own().proj_ball2(self.radius) + } +} +*/ + +impl Mapping for NormProjection +where + Domain : Space + Projection + std::ops::MulAssign, + F : Float, + E : NormExponent, +{ + type Codomain = Domain; + + fn apply>(&self, d : I) -> Domain { + d.own().proj_ball(self.radius, self.exponent) } }