src/linops.rs

branch
dev
changeset 164
fd9dba51afd3
parent 163
b4a47e8e80d1
child 168
93daa824c04a
equal deleted inserted replaced
163:b4a47e8e80d1 164:fd9dba51afd3
26 // } 26 // }
27 27
28 /// Vector spaces 28 /// Vector spaces
29 #[replace_float_literals(Self::Field::cast_from(literal))] 29 #[replace_float_literals(Self::Field::cast_from(literal))]
30 pub trait VectorSpace: 30 pub trait VectorSpace:
31 Space<OwnedSpace = Self::Owned> 31 Space<Principal = Self::PrincipalV>
32 + Mul<Self::Field, Output = Self::Owned> 32 + Mul<Self::Field, Output = Self::PrincipalV>
33 + Div<Self::Field, Output = Self::Owned> 33 + Div<Self::Field, Output = Self::PrincipalV>
34 + Add<Self, Output = Self::Owned> 34 + Add<Self, Output = Self::PrincipalV>
35 + Add<Self::Owned, Output = Self::Owned> 35 + Add<Self::PrincipalV, Output = Self::PrincipalV>
36 + Sub<Self, Output = Self::Owned> 36 + Sub<Self, Output = Self::PrincipalV>
37 + Sub<Self::Owned, Output = Self::Owned> 37 + Sub<Self::PrincipalV, Output = Self::PrincipalV>
38 + Neg 38 + Neg
39 + for<'b> Add<&'b Self, Output = <Self as VectorSpace>::Owned> 39 + for<'b> Add<&'b Self, Output = <Self as VectorSpace>::PrincipalV>
40 + for<'b> Sub<&'b Self, Output = <Self as VectorSpace>::Owned> 40 + for<'b> Sub<&'b Self, Output = <Self as VectorSpace>::PrincipalV>
41 { 41 {
42 /// Underlying scalar field
42 type Field: Num; 43 type Field: Num;
43 type Owned: ClosedSpace 44
45 /// Principal form of the space; always equal to [`Space::Principal`], but with
46 /// more traits guaranteed.
47 type PrincipalV: ClosedSpace
44 + AXPY< 48 + AXPY<
45 Self, 49 Self,
46 Field = Self::Field, 50 Field = Self::Field,
47 Owned = Self::Owned, 51 PrincipalV = Self::PrincipalV,
48 OwnedVariant = Self::Owned, 52 OwnedVariant = Self::PrincipalV,
49 OwnedSpace = Self::Owned, 53 Principal = Self::PrincipalV,
50 >; 54 >;
51 55
52 /// Return a similar zero as `self`. 56 /// Return a similar zero as `self`.
53 fn similar_origin(&self) -> Self::Owned; 57 fn similar_origin(&self) -> Self::PrincipalV;
54 // { 58 // {
55 // self.make_origin_generator().make_origin() 59 // self.make_origin_generator().make_origin()
56 // } 60 // }
57 61
58 /// Return a similar zero as `x`. 62 /// Return a similar zero as `x`.
59 fn similar_origin_inst<I: Instance<Self>>(x: I) -> Self::Owned { 63 fn similar_origin_inst<I: Instance<Self>>(x: I) -> Self::PrincipalV {
60 x.eval(|xr| xr.similar_origin()) 64 x.eval(|xr| xr.similar_origin())
61 } 65 }
62 } 66 }
63 67
64 /// Efficient in-place summation. 68 /// Efficient in-place summation.
66 pub trait AXPY<X = Self>: 70 pub trait AXPY<X = Self>:
67 VectorSpace 71 VectorSpace
68 + MulAssign<Self::Field> 72 + MulAssign<Self::Field>
69 + DivAssign<Self::Field> 73 + DivAssign<Self::Field>
70 + AddAssign<Self> 74 + AddAssign<Self>
71 + AddAssign<Self::Owned> 75 + AddAssign<Self::PrincipalV>
72 + SubAssign<Self> 76 + SubAssign<Self>
73 + SubAssign<Self::Owned> 77 + SubAssign<Self::PrincipalV>
74 + for<'b> AddAssign<&'b Self> 78 + for<'b> AddAssign<&'b Self>
75 + for<'b> SubAssign<&'b Self> 79 + for<'b> SubAssign<&'b Self>
76 where 80 where
77 X: Space, 81 X: Space,
78 { 82 {
91 95
92 /// Set self to zero. 96 /// Set self to zero.
93 fn set_zero(&mut self); 97 fn set_zero(&mut self);
94 } 98 }
95 99
96 pub trait ClosedVectorSpace: Instance<Self> + VectorSpace<Owned = Self> {} 100 pub trait ClosedVectorSpace: Instance<Self> + VectorSpace<PrincipalV = Self> {}
97 impl<X: Instance<X> + VectorSpace<Owned = Self>> ClosedVectorSpace for X {} 101 impl<X: Instance<X> + VectorSpace<PrincipalV = Self>> ClosedVectorSpace for X {}
98 102
99 /// Efficient in-place application for [`Linear`] operators. 103 /// Efficient in-place application for [`Linear`] operators.
100 #[replace_float_literals(F::cast_from(literal))] 104 #[replace_float_literals(F::cast_from(literal))]
101 pub trait GEMV<F: Num, X: Space, Y = <Self as Mapping<X>>::Codomain>: Linear<X> { 105 pub trait GEMV<F: Num, X: Space, Y = <Self as Mapping<X>>::Codomain>: Linear<X> {
102 /// Computes `y = αAx + βy`, where `A` is `Self`. 106 /// Computes `y = αAx + βy`, where `A` is `Self`.
195 IdOp(PhantomData) 199 IdOp(PhantomData)
196 } 200 }
197 } 201 }
198 202
199 impl<X: Space> Mapping<X> for IdOp<X> { 203 impl<X: Space> Mapping<X> for IdOp<X> {
200 type Codomain = X::OwnedSpace; 204 type Codomain = X::Principal;
201 205
202 fn apply<I: Instance<X>>(&self, x: I) -> Self::Codomain { 206 fn apply<I: Instance<X>>(&self, x: I) -> Self::Codomain {
203 x.into_owned() 207 x.into_owned()
204 } 208 }
205 } 209 }
231 fn opnorm_bound(&self, _xexp: E, _codexp: E) -> DynResult<F> { 235 fn opnorm_bound(&self, _xexp: E, _codexp: E) -> DynResult<F> {
232 Ok(F::ONE) 236 Ok(F::ONE)
233 } 237 }
234 } 238 }
235 239
236 impl<X: Clone + Space> Adjointable<X, X::OwnedSpace> for IdOp<X> { 240 impl<X: Clone + Space> Adjointable<X, X::Principal> for IdOp<X> {
237 type AdjointCodomain = X::OwnedSpace; 241 type AdjointCodomain = X::Principal;
238 type Adjoint<'a> 242 type Adjoint<'a>
239 = IdOp<X::OwnedSpace> 243 = IdOp<X::Principal>
240 where 244 where
241 X: 'a; 245 X: 'a;
242 246
243 fn adjoint(&self) -> Self::Adjoint<'_> { 247 fn adjoint(&self) -> Self::Adjoint<'_> {
244 IdOp::new() 248 IdOp::new()
245 } 249 }
246 } 250 }
247 251
248 impl<X: Clone + Space> Preadjointable<X, X::OwnedSpace> for IdOp<X> { 252 impl<X: Clone + Space> Preadjointable<X, X::Principal> for IdOp<X> {
249 type PreadjointCodomain = X::OwnedSpace; 253 type PreadjointCodomain = X::Principal;
250 type Preadjoint<'a> 254 type Preadjoint<'a>
251 = IdOp<X::OwnedSpace> 255 = IdOp<X::Principal>
252 where 256 where
253 X: 'a; 257 X: 'a;
254 258
255 fn preadjoint(&self) -> Self::Preadjoint<'_> { 259 fn preadjoint(&self) -> Self::Preadjoint<'_> {
256 IdOp::new() 260 IdOp::new()
260 /// The zero operator from a space to itself 264 /// The zero operator from a space to itself
261 #[derive(Clone, Copy, Debug, Serialize, Eq, PartialEq)] 265 #[derive(Clone, Copy, Debug, Serialize, Eq, PartialEq)]
262 pub struct SimpleZeroOp; 266 pub struct SimpleZeroOp;
263 267
264 impl<X: VectorSpace> Mapping<X> for SimpleZeroOp { 268 impl<X: VectorSpace> Mapping<X> for SimpleZeroOp {
265 type Codomain = X::Owned; 269 type Codomain = X::PrincipalV;
266 270
267 fn apply<I: Instance<X>>(&self, x: I) -> X::Owned { 271 fn apply<I: Instance<X>>(&self, x: I) -> X::PrincipalV {
268 X::similar_origin_inst(x) 272 X::similar_origin_inst(x)
269 } 273 }
270 } 274 }
271 275
272 impl<X: VectorSpace> Linear<X> for SimpleZeroOp {} 276 impl<X: VectorSpace> Linear<X> for SimpleZeroOp {}
321 pub trait OriginGenerator<Y: VectorSpace> { 325 pub trait OriginGenerator<Y: VectorSpace> {
322 type Ref<'b>: OriginGenerator<Y> 326 type Ref<'b>: OriginGenerator<Y>
323 where 327 where
324 Self: 'b; 328 Self: 'b;
325 329
326 fn origin(&self) -> Y::Owned; 330 fn origin(&self) -> Y::PrincipalV;
327 fn as_ref(&self) -> Self::Ref<'_>; 331 fn as_ref(&self) -> Self::Ref<'_>;
328 } 332 }
329 333
330 impl<Y: VectorSpace> OriginGenerator<Y> for Y { 334 impl<Y: VectorSpace> OriginGenerator<Y> for Y {
331 type Ref<'b> 335 type Ref<'b>
332 = &'b Y 336 = &'b Y
333 where 337 where
334 Self: 'b; 338 Self: 'b;
335 339
336 #[inline] 340 #[inline]
337 fn origin(&self) -> Y::Owned { 341 fn origin(&self) -> Y::PrincipalV {
338 return self.similar_origin(); 342 return self.similar_origin();
339 } 343 }
340 344
341 #[inline] 345 #[inline]
342 fn as_ref(&self) -> Self::Ref<'_> { 346 fn as_ref(&self) -> Self::Ref<'_> {
349 = Self 353 = Self
350 where 354 where
351 Self: 'c; 355 Self: 'c;
352 356
353 #[inline] 357 #[inline]
354 fn origin(&self) -> Y::Owned { 358 fn origin(&self) -> Y::PrincipalV {
355 return self.similar_origin(); 359 return self.similar_origin();
356 } 360 }
357 361
358 #[inline] 362 #[inline]
359 fn as_ref(&self) -> Self::Ref<'_> { 363 fn as_ref(&self) -> Self::Ref<'_> {
390 OY: OriginGenerator<Y>, 394 OY: OriginGenerator<Y>,
391 OXprime: OriginGenerator<Xprime>, 395 OXprime: OriginGenerator<Xprime>,
392 X: HasDual<F, DualSpace = Xprime>, 396 X: HasDual<F, DualSpace = Xprime>,
393 Y: HasDual<F, DualSpace = Yprime>, 397 Y: HasDual<F, DualSpace = Yprime>,
394 F: Float, 398 F: Float,
395 Xprime: VectorSpace<Field = F, Owned = Xprime>, 399 Xprime: VectorSpace<Field = F, PrincipalV = Xprime>,
396 Xprime::Owned: AXPY<Field = F>, 400 Xprime::PrincipalV: AXPY<Field = F>,
397 Yprime: Space + Instance<Yprime>, 401 Yprime: Space + Instance<Yprime>,
398 { 402 {
399 pub fn new_dualisable(y_og: OY, xprime_og: OXprime) -> Self { 403 pub fn new_dualisable(y_og: OY, xprime_og: OXprime) -> Self {
400 ZeroOp { 404 ZeroOp {
401 codomain_origin_generator: y_og, 405 codomain_origin_generator: y_og,
410 X: Space, 414 X: Space,
411 Y: VectorSpace<Field = F>, 415 Y: VectorSpace<Field = F>,
412 F: Float, 416 F: Float,
413 OY: OriginGenerator<Y>, 417 OY: OriginGenerator<Y>,
414 { 418 {
415 type Codomain = Y::Owned; 419 type Codomain = Y::PrincipalV;
416 420
417 fn apply<I: Instance<X>>(&self, _x: I) -> Y::Owned { 421 fn apply<I: Instance<X>>(&self, _x: I) -> Y::PrincipalV {
418 self.codomain_origin_generator.origin() 422 self.codomain_origin_generator.origin()
419 } 423 }
420 } 424 }
421 425
422 impl<X, Y, OY, O, F> Linear<X> for ZeroOp<X, Y, OY, O, F> 426 impl<X, Y, OY, O, F> Linear<X> for ZeroOp<X, Y, OY, O, F>
430 434
431 #[replace_float_literals(F::cast_from(literal))] 435 #[replace_float_literals(F::cast_from(literal))]
432 impl<X, Y, OY, O, F> GEMV<F, X, Y> for ZeroOp<X, Y, OY, O, F> 436 impl<X, Y, OY, O, F> GEMV<F, X, Y> for ZeroOp<X, Y, OY, O, F>
433 where 437 where
434 X: Space, 438 X: Space,
435 Y: AXPY<Field = F, Owned = Y>, 439 Y: AXPY<Field = F, PrincipalV = Y>,
436 F: Float, 440 F: Float,
437 OY: OriginGenerator<Y>, 441 OY: OriginGenerator<Y>,
438 { 442 {
439 // Computes `y = αAx + βy`, where `A` is `Self`. 443 // Computes `y = αAx + βy`, where `A` is `Self`.
440 fn gemv<I: Instance<X>>(&self, y: &mut Y, _α: F, _x: I, β: F) { 444 fn gemv<I: Instance<X>>(&self, y: &mut Y, _α: F, _x: I, β: F) {
448 452
449 impl<X, Y, OY, O, F, E1, E2> BoundedLinear<X, E1, E2, F> for ZeroOp<X, Y, OY, O, F> 453 impl<X, Y, OY, O, F, E1, E2> BoundedLinear<X, E1, E2, F> for ZeroOp<X, Y, OY, O, F>
450 where 454 where
451 X: Space + Instance<X> + Norm<E1, F>, 455 X: Space + Instance<X> + Norm<E1, F>,
452 Y: VectorSpace<Field = F>, 456 Y: VectorSpace<Field = F>,
453 Y::Owned: Clone, 457 Y::PrincipalV: Clone,
454 F: Float, 458 F: Float,
455 E1: NormExponent, 459 E1: NormExponent,
456 E2: NormExponent, 460 E2: NormExponent,
457 OY: OriginGenerator<Y>, 461 OY: OriginGenerator<Y>,
458 { 462 {
918 922
919 impl<Domain, F> Mapping<Domain> for Scaled<F> 923 impl<Domain, F> Mapping<Domain> for Scaled<F>
920 where 924 where
921 F: Float, 925 F: Float,
922 Domain: Space, 926 Domain: Space,
923 Domain::OwnedSpace: Mul<F>, 927 Domain::Principal: Mul<F>,
924 <Domain::OwnedSpace as Mul<F>>::Output: ClosedSpace, 928 <Domain::Principal as Mul<F>>::Output: ClosedSpace,
925 { 929 {
926 type Codomain = <Domain::OwnedSpace as Mul<F>>::Output; 930 type Codomain = <Domain::Principal as Mul<F>>::Output;
927 931
928 /// Compute the value of `self` at `x`. 932 /// Compute the value of `self` at `x`.
929 fn apply<I: Instance<Domain>>(&self, x: I) -> Self::Codomain { 933 fn apply<I: Instance<Domain>>(&self, x: I) -> Self::Codomain {
930 x.own() * self.0 934 x.own() * self.0
931 } 935 }
933 937
934 impl<Domain, F> Linear<Domain> for Scaled<F> 938 impl<Domain, F> Linear<Domain> for Scaled<F>
935 where 939 where
936 F: Float, 940 F: Float,
937 Domain: Space, 941 Domain: Space,
938 Domain::OwnedSpace: Mul<F>, 942 Domain::Principal: Mul<F>,
939 <Domain::OwnedSpace as Mul<F>>::Output: ClosedSpace, 943 <Domain::Principal as Mul<F>>::Output: ClosedSpace,
940 { 944 {
941 } 945 }

mercurial