src/linops.rs

branch
dev
changeset 184
b7b60b3b3eff
parent 177
b071a1b484f8
child 185
e6829fbe2737
equal deleted inserted replaced
183:d077dff509f1 184:b7b60b3b3eff
154 pub trait Adjointable<X, Yʹ>: Linear<X> 154 pub trait Adjointable<X, Yʹ>: Linear<X>
155 where 155 where
156 X: Space, 156 X: Space,
157 Yʹ: Space, 157 Yʹ: Space,
158 { 158 {
159 /// Codomain of the adjoint operator.
159 type AdjointCodomain: ClosedSpace; 160 type AdjointCodomain: ClosedSpace;
161 /// Type of the adjoint operator.
160 type Adjoint<'a>: Linear<Yʹ, Codomain = Self::AdjointCodomain> 162 type Adjoint<'a>: Linear<Yʹ, Codomain = Self::AdjointCodomain>
161 where 163 where
162 Self: 'a; 164 Self: 'a;
163 165
164 /// Form the adjoint operator of `self`. 166 /// Form the adjoint operator of `self`.
165 fn adjoint(&self) -> Self::Adjoint<'_>; 167 fn adjoint(&self) -> Self::Adjoint<'_>;
168 }
169
170 /// Variant of [`Adjointable`] where the adjoint does not depend on a lifetime parameter.
171 /// This exists due to restrictions of Rust's type system: if `A :: Adjointable`, and we make
172 /// further restrictions on the adjoint operator, through, e.g.
173 /// ```
174 /// for<'a> A::Adjoint<'a> : GEMV<F, X, Y>,
175 /// ```
176 /// Then `'static` lifetime is forced on `X`. Having `A::SimpleAdjoint` not depend on `'a`
177 /// avoids this, but makes it impossible for the adjoint to be just a light wrapper around the
178 /// original operator.
179 pub trait SimplyAdjointable<X, Yʹ>: Linear<X>
180 where
181 X: Space,
182 Yʹ: Space,
183 {
184 /// Codomain of the adjoint operator.
185 type AdjointCodomain: ClosedSpace;
186 /// Type of the adjoint operator.
187 type SimpleAdjoint: Linear<Yʹ, Codomain = Self::AdjointCodomain>;
188
189 /// Form the adjoint operator of `self`.
190 fn adjoint(&self) -> Self::SimpleAdjoint;
166 } 191 }
167 192
168 /// Trait for forming a preadjoint of an operator. 193 /// Trait for forming a preadjoint of an operator.
169 /// 194 ///
170 /// For an operator $A$ this is an operator $A\_\*$ 195 /// For an operator $A$ this is an operator $A\_\*$
185 210
186 /// Form the adjoint operator of `self`. 211 /// Form the adjoint operator of `self`.
187 fn preadjoint(&self) -> Self::Preadjoint<'_>; 212 fn preadjoint(&self) -> Self::Preadjoint<'_>;
188 } 213 }
189 214
190 /// Adjointable operators $A: X → Y$ between reflexive spaces $X$ and $Y$.
191 pub trait SimplyAdjointable<X: Space>: Adjointable<X, <Self as Mapping<X>>::Codomain> {}
192 impl<'a, X: Space, T> SimplyAdjointable<X> for T where
193 T: Adjointable<X, <Self as Mapping<X>>::Codomain>
194 {
195 }
196
197 /// The identity operator 215 /// The identity operator
198 #[derive(Clone, Copy, Debug, Serialize, Eq, PartialEq)] 216 #[derive(Clone, Copy, Debug, Serialize, Eq, PartialEq)]
199 pub struct IdOp<X>(PhantomData<X>); 217 pub struct IdOp<X>(PhantomData<X>);
200 218
201 impl<X> IdOp<X> { 219 impl<X> IdOp<X> {
247 = IdOp<X::Principal> 265 = IdOp<X::Principal>
248 where 266 where
249 X: 'a; 267 X: 'a;
250 268
251 fn adjoint(&self) -> Self::Adjoint<'_> { 269 fn adjoint(&self) -> Self::Adjoint<'_> {
270 IdOp::new()
271 }
272 }
273
274 impl<X: Clone + Space> SimplyAdjointable<X, X::Principal> for IdOp<X> {
275 type AdjointCodomain = X::Principal;
276 type SimpleAdjoint = IdOp<X::Principal>;
277
278 fn adjoint(&self) -> Self::SimpleAdjoint {
252 IdOp::new() 279 IdOp::new()
253 } 280 }
254 } 281 }
255 282
256 impl<X: Clone + Space> Preadjointable<X, X::Principal> for IdOp<X> { 283 impl<X: Clone + Space> Preadjointable<X, X::Principal> for IdOp<X> {
489 // () means not (pre)adjointable. 516 // () means not (pre)adjointable.
490 517
491 fn adjoint(&self) -> Self::Adjoint<'_> { 518 fn adjoint(&self) -> Self::Adjoint<'_> {
492 ZeroOp { 519 ZeroOp {
493 codomain_origin_generator: self.other_origin_generator.as_ref(), 520 codomain_origin_generator: self.other_origin_generator.as_ref(),
521 other_origin_generator: (),
522 _phantoms: PhantomData,
523 }
524 }
525 }
526
527 impl<'b, X, Y, OY, OXprime, Xprime, Yprime, F> SimplyAdjointable<X, Yprime>
528 for ZeroOp<X, Y, OY, OXprime, F>
529 where
530 X: HasDual<F, DualSpace = Xprime>,
531 Y: HasDual<F, DualSpace = Yprime>,
532 F: Float,
533 Xprime: ClosedVectorSpace<Field = F>,
534 //Xprime::Owned: AXPY<Field = F>,
535 Yprime: ClosedSpace,
536 OY: OriginGenerator<Y>,
537 OXprime: OriginGenerator<X::DualSpace> + Clone,
538 {
539 type AdjointCodomain = Xprime;
540 type SimpleAdjoint = ZeroOp<Yprime, Xprime, OXprime, (), F>;
541 // () means not (pre)adjointable.
542
543 fn adjoint(&self) -> Self::SimpleAdjoint {
544 ZeroOp {
545 codomain_origin_generator: self.other_origin_generator.clone(),
494 other_origin_generator: (), 546 other_origin_generator: (),
495 _phantoms: PhantomData, 547 _phantoms: PhantomData,
496 } 548 }
497 } 549 }
498 } 550 }
675 = ColOp<S::Adjoint<'a>, T::Adjoint<'a>> 727 = ColOp<S::Adjoint<'a>, T::Adjoint<'a>>
676 where 728 where
677 Self: 'a; 729 Self: 'a;
678 730
679 fn adjoint(&self) -> Self::Adjoint<'_> { 731 fn adjoint(&self) -> Self::Adjoint<'_> {
732 ColOp(self.0.adjoint(), self.1.adjoint())
733 }
734 }
735
736 impl<A, B, Yʹ, S, T> SimplyAdjointable<Pair<A, B>, Yʹ> for RowOp<S, T>
737 where
738 A: Space,
739 B: Space,
740 Yʹ: Space,
741 S: SimplyAdjointable<A, Yʹ>,
742 T: SimplyAdjointable<B, Yʹ>,
743 Self: Linear<Pair<A, B>>,
744 // for<'a> ColOp<S::Adjoint<'a>, T::Adjoint<'a>> : Linear<
745 // Yʹ,
746 // Codomain=Pair<S::AdjointCodomain, T::AdjointCodomain>
747 // >,
748 {
749 type AdjointCodomain = Pair<S::AdjointCodomain, T::AdjointCodomain>;
750 type SimpleAdjoint = ColOp<S::SimpleAdjoint, T::SimpleAdjoint>;
751
752 fn adjoint(&self) -> Self::SimpleAdjoint {
680 ColOp(self.0.adjoint(), self.1.adjoint()) 753 ColOp(self.0.adjoint(), self.1.adjoint())
681 } 754 }
682 } 755 }
683 756
684 impl<A, B, Yʹ, S, T> Preadjointable<Pair<A, B>, Yʹ> for RowOp<S, T> 757 impl<A, B, Yʹ, S, T> Preadjointable<Pair<A, B>, Yʹ> for RowOp<S, T>
726 fn adjoint(&self) -> Self::Adjoint<'_> { 799 fn adjoint(&self) -> Self::Adjoint<'_> {
727 RowOp(self.0.adjoint(), self.1.adjoint()) 800 RowOp(self.0.adjoint(), self.1.adjoint())
728 } 801 }
729 } 802 }
730 803
804 impl<A, Xʹ, Yʹ, R, S, T> SimplyAdjointable<A, Pair<Xʹ, Yʹ>> for ColOp<S, T>
805 where
806 A: Space,
807 Xʹ: Space,
808 Yʹ: Space,
809 R: ClosedSpace + ClosedAdd,
810 S: SimplyAdjointable<A, Xʹ, AdjointCodomain = R>,
811 T: SimplyAdjointable<A, Yʹ, AdjointCodomain = R>,
812 Self: Linear<A>,
813 // for<'a> RowOp<S::Adjoint<'a>, T::Adjoint<'a>> : Linear<
814 // Pair<Xʹ,Yʹ>,
815 // Codomain=R,
816 // >,
817 {
818 type AdjointCodomain = R;
819 type SimpleAdjoint = RowOp<S::SimpleAdjoint, T::SimpleAdjoint>;
820
821 fn adjoint(&self) -> Self::SimpleAdjoint {
822 RowOp(self.0.adjoint(), self.1.adjoint())
823 }
824 }
825
731 impl<A, Xʹ, Yʹ, R, S, T> Preadjointable<A, Pair<Xʹ, Yʹ>> for ColOp<S, T> 826 impl<A, Xʹ, Yʹ, R, S, T> Preadjointable<A, Pair<Xʹ, Yʹ>> for ColOp<S, T>
732 where 827 where
733 A: Space, 828 A: Space,
734 Xʹ: Space, 829 Xʹ: Space,
735 Yʹ: Space, 830 Yʹ: Space,
828 = DiagOp<S::Adjoint<'a>, T::Adjoint<'a>> 923 = DiagOp<S::Adjoint<'a>, T::Adjoint<'a>>
829 where 924 where
830 Self: 'a; 925 Self: 'a;
831 926
832 fn adjoint(&self) -> Self::Adjoint<'_> { 927 fn adjoint(&self) -> Self::Adjoint<'_> {
928 DiagOp(self.0.adjoint(), self.1.adjoint())
929 }
930 }
931
932 impl<A, B, Xʹ, Yʹ, R, S, T> SimplyAdjointable<Pair<A, B>, Pair<Xʹ, Yʹ>> for DiagOp<S, T>
933 where
934 A: Space,
935 B: Space,
936 Xʹ: Space,
937 Yʹ: Space,
938 R: ClosedSpace,
939 S: SimplyAdjointable<A, Xʹ>,
940 T: SimplyAdjointable<B, Yʹ>,
941 Self: Linear<Pair<A, B>>,
942 for<'a> DiagOp<S::SimpleAdjoint, T::SimpleAdjoint>: Linear<Pair<Xʹ, Yʹ>, Codomain = R>,
943 {
944 type AdjointCodomain = R;
945 type SimpleAdjoint = DiagOp<S::SimpleAdjoint, T::SimpleAdjoint>;
946
947 fn adjoint(&self) -> Self::SimpleAdjoint {
833 DiagOp(self.0.adjoint(), self.1.adjoint()) 948 DiagOp(self.0.adjoint(), self.1.adjoint())
834 } 949 }
835 } 950 }
836 951
837 impl<A, B, Xʹ, Yʹ, R, S, T> Preadjointable<Pair<A, B>, Pair<Xʹ, Yʹ>> for DiagOp<S, T> 952 impl<A, B, Xʹ, Yʹ, R, S, T> Preadjointable<Pair<A, B>, Pair<Xʹ, Yʹ>> for DiagOp<S, T>

mercurial