| 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> |