Tue, 24 Dec 2024 14:07:52 -0500
NormConstraint with radius
src/convex.rs | file | annotate | diff | comparison | revisions | |
src/norms.rs | file | annotate | diff | comparison | revisions |
--- 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<F : Float, E : NormExponent>(NormMapping<F, E>); +pub struct NormConstraint<F : Float, E : NormExponent> { + radius : F, + norm : NormMapping<F, E>, +} + impl<Domain, E, F> ConvexMapping<Domain, F> for NormMapping<F, E> where @@ -78,7 +83,7 @@ {} -impl<F, E, Domain> Mapping<Domain> for NormConjugate<F, E> +impl<F, E, Domain> Mapping<Domain> for NormConstraint<F, E> where Domain : Space + Norm<F, E>, F : Float, @@ -87,7 +92,7 @@ type Codomain = F; fn apply<I : Instance<Domain>>(&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<Domain, E, F> ConvexMapping<Domain, F> for NormConjugate<F, E> +impl<Domain, E, F> ConvexMapping<Domain, F> for NormConstraint<F, E> where Domain : Space, E : NormExponent, @@ -111,10 +116,79 @@ Domain : HasDual<F> + Norm<F, E> + Space, <Domain as HasDual<F>>::DualSpace : Norm<F, E::DualExp> { - type Conjugate<'a> = NormConjugate<F, E::DualExp> where Self : 'a; + type Conjugate<'a> = NormConstraint<F, E::DualExp> where Self : 'a; + + fn conjugate(&self) -> Self::Conjugate<'_> { + NormConstraint { + radius : F::ONE, + norm : self.exponent.dual_exponent().as_mapping() + } + } +} + +impl<C, E, F, Domain> Conjugable<Domain, F> for Weighted<NormMapping<F, E>, C> +where + C : Constant<Type = F>, + E : HasDualExponent, + F : Float, + Domain : HasDual<F> + Norm<F, E> + Space, + <Domain as HasDual<F>>::DualSpace : Norm<F, E::DualExp> +{ + type Conjugate<'a> = NormConstraint<F, E::DualExp> 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<Domain, E, F> Prox<Domain> for NormConstraint<F, E> +where + Domain : Space + Norm<F, E>, + E : NormExponent, + F : Float, + NormProjection<F, E> : Mapping<Domain, Codomain=Domain>, +{ + type Prox<'a> = NormProjection<F, E> 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<F : Float, E : NormExponent> { + radius : F, + exponent : E, +} + +/* +impl<F, Domain> Mapping<Domain> for NormProjection<F, L2> +where + Domain : Space + Euclidean<F> + std::ops::MulAssign<F>, + F : Float, +{ + type Codomain = Domain; + + fn apply<I : Instance<Domain>>(&self, d : I) -> Domain { + d.own().proj_ball2(self.radius) + } +} +*/ + +impl<F, E, Domain> Mapping<Domain> for NormProjection<F, E> +where + Domain : Space + Projection<F, E> + std::ops::MulAssign<F>, + F : Float, + E : NormExponent, +{ + type Codomain = Domain; + + fn apply<I : Instance<Domain>>(&self, d : I) -> Domain { + d.own().proj_ball(self.radius, self.exponent) } }