src/convex.rs

branch
dev
changeset 59
9226980e45a7
parent 58
1a38447a89fa
child 60
848ecc05becf
--- a/src/convex.rs	Sat Dec 14 09:31:27 2024 -0500
+++ b/src/convex.rs	Tue Dec 31 08:30:02 2024 -0500
@@ -2,20 +2,24 @@
 Some convex analysis basics
 */
 
-use crate::mapping::{Apply, Mapping};
+use crate::types::*;
+use crate::mapping::{Mapping, Space};
+use crate::instance::{Instance, InstanceMut, DecompositionMut};
+use crate::norms::*;
 
 /// Trait for convex mappings. Has no features, just serves as a constraint
 ///
 /// TODO: should constrain `Mapping::Codomain` to implement a partial order,
 /// but this makes everything complicated with little benefit.
-pub trait ConvexMapping<Domain> : Mapping<Domain> {}
+pub trait ConvexMapping<Domain : Space> : Mapping<Domain>
+{}
 
 /// Trait for mappings with a Fenchel conjugate
 ///
 /// The conjugate type has to implement [`ConvexMapping`], but a `Conjugable` mapping need
 /// not be convex.
-pub trait Conjugable<Domain> : Mapping<Domain> {
-    type DualDomain;
+pub trait Conjugable<Domain : Space> : Mapping<Domain> {
+    type DualDomain : Space;
     type Conjugate<'a> : ConvexMapping<Self::DualDomain> where Self : 'a;
 
     fn conjugate(&self) -> Self::Conjugate<'_>;
@@ -25,8 +29,8 @@
 ///
 /// In contrast to [`Conjugable`], the preconjugate need not implement [`ConvexMapping`],
 /// but a `Preconjugable` mapping has be convex.
-pub trait Preconjugable<Domain> : ConvexMapping<Domain> {
-    type PredualDomain;
+pub trait Preconjugable<Domain : Space> : ConvexMapping<Domain> {
+    type PredualDomain : Space;
     type Preconjugate<'a> : Mapping<Self::PredualDomain> where Self : 'a;
 
     fn preconjugate(&self) -> Self::Preconjugate<'_>;
@@ -36,15 +40,78 @@
 ///
 /// The conjugate type has to implement [`ConvexMapping`], but a `Conjugable` mapping need
 /// not be convex.
-pub trait HasProx<Domain> : Mapping<Domain> {
+pub trait Prox<Domain : Space> : Mapping<Domain> {
     type Prox<'a> : Mapping<Domain, Codomain=Domain> where Self : 'a;
 
     /// Returns a proximal mapping with weight τ
     fn prox_mapping(&self, τ : Self::Codomain) -> Self::Prox<'_>;
 
     /// Calculate the proximal mapping with weight τ
-    fn prox(&self, z : Domain, τ : Self::Codomain) -> Domain {
+    fn prox<I : Instance<Domain>>(&self, τ : Self::Codomain, z : I) -> Domain {
         self.prox_mapping(τ).apply(z)
     }
+
+    /// Calculate the proximal mapping with weight τ in-place
+    fn prox_mut<'b>(&self, τ : Self::Codomain, y : &'b mut Domain)
+    where
+        &'b mut Domain : InstanceMut<Domain>,
+        Domain:: Decomp : DecompositionMut<Domain>,
+        for<'a> &'a Domain : Instance<Domain>,
+    {
+        *y = self.prox(τ, &*y);
+    }
 }
 
+
+pub struct NormConjugate<F : Float, E : NormExponent>(NormMapping<F, E>);
+
+impl<Domain, E, F> ConvexMapping<Domain> for NormMapping<F, E>
+where
+    Domain : Space,
+    E : NormExponent,
+    F : Float,
+    Self : Mapping<Domain, Codomain=F> {}
+
+
+impl<Domain, E, F> ConvexMapping<Domain> for NormConjugate<F, E>
+where
+    Domain : Space,
+    E : NormExponent,
+    F : Float,
+    Self : Mapping<Domain, Codomain=F> {}
+
+
+impl<F, E, Domain> Mapping<Domain> for NormConjugate<F, E>
+where
+    Domain : Space + Norm<F, E>,
+    F : Float,
+    E : NormExponent,
+{
+    type Codomain = F;
+
+    fn apply<I : Instance<Domain>>(&self, d : I) -> F {
+        if d.eval(|x| x.norm(self.0.exponent)) <= F::ONE {
+            F::ZERO
+        } else {
+            F::INFINITY
+        }
+    }
+}
+
+
+
+impl<E, F, Domain> Conjugable<Domain> for NormMapping<F, E>
+where
+    E : NormExponent + Clone,
+    F : Float,
+    Domain : Norm<F, E> + Space,
+{
+
+    type DualDomain = Domain;
+    type Conjugate<'a> = NormConjugate<F, E> where Self : 'a;
+
+    fn conjugate(&self) -> Self::Conjugate<'_> {
+        NormConjugate(self.clone())
+    }
+}
+

mercurial