Compositions dev

Tue, 31 Dec 2024 08:30:43 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Tue, 31 Dec 2024 08:30:43 -0500
branch
dev
changeset 61
05089fbc0310
parent 60
848ecc05becf
child 62
d8305c9b6fdf
child 78
cebedc4a8331

Compositions

src/linops.rs file | annotate | diff | comparison | revisions
src/mapping.rs file | annotate | diff | comparison | revisions
--- a/src/linops.rs	Tue Dec 31 09:02:55 2024 -0500
+++ b/src/linops.rs	Tue Dec 31 08:30:43 2024 -0500
@@ -6,10 +6,10 @@
 use std::marker::PhantomData;
 use serde::Serialize;
 use crate::types::*;
-pub use crate::mapping::{Mapping, Space};
+pub use crate::mapping::{Mapping, Space, Composition};
 use crate::direct_product::Pair;
 use crate::instance::Instance;
-use crate::norms::{NormExponent, PairNorm, L1, L2, Linfinity};
+use crate::norms::{NormExponent, PairNorm, L1, L2, Linfinity, Norm};
 
 /// Trait for linear operators on `X`.
 pub trait Linear<X : Space> : Mapping<X>
@@ -58,7 +58,7 @@
 pub trait BoundedLinear<X, XExp, CodExp, F = f64> : Linear<X>
 where
     F : Num,
-    X : Space,
+    X : Space + Norm<F, XExp>,
     XExp : NormExponent,
     CodExp : NormExponent
 {
@@ -152,7 +152,7 @@
 
 impl<F, X, E> BoundedLinear<X, E, E, F> for IdOp<X>
 where
-    X : Space + Clone,
+    X : Space + Clone + Norm<F, E>,
     F : Num,
     E : NormExponent
 {
@@ -173,6 +173,53 @@
     fn preadjoint(&self) -> Self::Preadjoint<'_> { IdOp::new() }
 }
 
+
+impl<S, T, E, X> Linear<X> for Composition<S, T, E>
+where
+    X : Space,
+    T : Linear<X>,
+    S : Linear<T::Codomain>
+{ }
+
+impl<F, S, T, E, X, Y> GEMV<F, X, Y> for Composition<S, T, E>
+where
+    F : Num,
+    X : Space,
+    T : Linear<X>,
+    S : GEMV<F, T::Codomain, Y>,
+{
+    fn gemv<I : Instance<X>>(&self, y : &mut Y, α : F, x : I, β : F) {
+        self.outer.gemv(y, α, self.inner.apply(x), β)
+    }
+
+    /// Computes `y = Ax`, where `A` is `Self`
+    fn apply_mut<I : Instance<X>>(&self, y : &mut Y, x : I){
+        self.outer.apply_mut(y, self.inner.apply(x))
+    }
+
+    /// Computes `y += Ax`, where `A` is `Self`
+    fn apply_add<I : Instance<X>>(&self, y : &mut Y, x : I){
+        self.outer.apply_add(y, self.inner.apply(x))
+    }
+}
+
+impl<F, S, T, X, Z, Xexp, Yexp, Zexp> BoundedLinear<X, Xexp, Yexp, F> for Composition<S, T, Zexp>
+where
+    F : Num,
+    X : Space + Norm<F, Xexp>,
+    Z : Space + Norm<F, Zexp>,
+    Xexp : NormExponent,
+    Yexp : NormExponent,
+    Zexp : NormExponent,
+    T : BoundedLinear<X, Xexp, Zexp, F, Codomain=Z>,
+    S : BoundedLinear<Z, Zexp, Yexp, F>,
+{
+    fn opnorm_bound(&self, xexp : Xexp, yexp : Yexp) -> F {
+        let zexp = self.intermediate_norm_exponent;
+        self.outer.opnorm_bound(zexp, yexp) * self.inner.opnorm_bound(xexp, zexp)
+    }
+}
+
 /// “Row operator” $(S, T)$; $(S, T)(x, y)=Sx + Ty$.
 pub struct RowOp<S, T>(pub S, pub T);
 
@@ -488,8 +535,8 @@
         for RowOp<S, T>
         where
             F : Float,
-            A : Space,
-            B : Space,
+            A : Space + Norm<F, ExpA>,
+            B : Space + Norm<F, ExpB>,
             S : BoundedLinear<A, ExpA, ExpR, F>,
             T : BoundedLinear<B, ExpB, ExpR, F>,
             S::Codomain : Add<T::Codomain>,
@@ -516,7 +563,7 @@
         for ColOp<S, T>
         where
             F : Float,
-            A : Space,
+            A : Space + Norm<F, ExpA>,
             S : BoundedLinear<A, ExpA, ExpS, F>,
             T : BoundedLinear<A, ExpA, ExpT, F>,
             ExpA : NormExponent,
--- a/src/mapping.rs	Tue Dec 31 09:02:55 2024 -0500
+++ b/src/mapping.rs	Tue Dec 31 08:30:43 2024 -0500
@@ -4,10 +4,11 @@
 
 use std::marker::PhantomData;
 use std::borrow::Cow;
-use crate::types::Float;
+use crate::types::{Num, Float};
 use serde::Serialize;
 use crate::loc::Loc;
 pub use crate::instance::{Instance, Decomposition, BasicDecomposition, Space};
+use crate::norms::{Norm, NormExponent};
 
 /// A mapping from `Domain` to `Codomain`.
 ///
@@ -17,6 +18,33 @@
 
     /// Compute the value of `self` at `x`.
     fn apply<I : Instance<Domain>>(&self, x : I) -> Self::Codomain;
+
+    #[inline]
+    /// Form the composition `self ∘ other`
+    fn compose<X : Space, T : Mapping<X, Codomain=Domain>>(self, other : T)
+        -> Composition<Self, T>
+    where
+        Self : Sized
+    {
+        Composition{ outer : self, inner : other, intermediate_norm_exponent : () }
+    }
+
+
+    #[inline]
+    /// Form the composition `self ∘ other`, assigning a norm to the inermediate space
+    fn compose_with_norm<F, X, T, E>(
+        self, other : T, norm : E
+    )  -> Composition<Self, T, E>
+    where
+        Self : Sized,
+        X : Space,
+        T : Mapping<X, Codomain=Domain>,
+        E : NormExponent,
+        Domain : Norm<F, E>,
+        F : Num
+    {
+        Composition{ outer : self, inner : other, intermediate_norm_exponent : norm }
+    }
 }
 
 /// Automatically implemented shorthand for referring to [`Mapping`]s from [`Loc<F, N>`] to `F`.
@@ -236,3 +264,25 @@
 impl<X : Space, F : Copy, G : Sized + Mapping<X, Codomain=Loc<F, N>> + Clone, const N : usize>
 SliceCodomain<X, F, N>
 for G {}
+
+
+/// The composition S ∘ T. `E` is for storing a `NormExponent` for the intermediate space.
+pub struct Composition<S, T, E = ()> {
+    pub outer : S,
+    pub inner : T,
+    pub intermediate_norm_exponent : E
+}
+
+impl<S, T, X, E> Mapping<X> for Composition<S, T, E>
+where
+    X : Space,
+    T : Mapping<X>,
+    S : Mapping<T::Codomain>
+{
+    type Codomain = S::Codomain;
+
+    #[inline]
+    fn apply<I : Instance<X>>(&self, x : I) -> Self::Codomain {
+        self.outer.apply(self.inner.apply(x))
+    }
+}

mercurial