Tue, 29 Apr 2025 07:55:18 -0500
sketch
| 105 | 1 | /*! |
| 2 | General deata terms of the form $g(Ax-b)$ for an operator $A$ | |
| 3 | to a [`Euclidean`] space, and a function g on that space. | |
| 4 | */ | |
| 5 | ||
| 6 | #![allow(non_snake_case)] | |
| 7 | ||
| 8 | use super::{DifferentiableImpl, DifferentiableMapping, /*LipschitzDifferentiableImpl,*/ Mapping,}; | |
| 9 | use crate::convex::ConvexMapping; | |
| 10 | use crate::instance::{Instance, Space}; | |
| 11 | use crate::linops::{/*BoundedLinear,*/ Linear, Preadjointable}; | |
| 12 | //use crate::norms::{Norm, NormExponent, L2}; | |
| 13 | use crate::types::Float; | |
| 14 | use std::ops::Sub; | |
| 15 | //use serde::{Deserialize, Serialize}; | |
| 16 | ||
| 17 | /// Functions of the form $\frac{1}{2}\|Ax-b\|_2^2$ for an operator $A$ | |
| 18 | /// to a [`Euclidean`] space. | |
| 19 | pub struct DataTerm< | |
| 20 | F: Float, | |
| 21 | Domain: Space, | |
| 22 | A: Mapping<Domain>, | |
| 23 | G: Mapping<A::Codomain, Codomain = F>, | |
| 24 | > { | |
| 25 | opA: A, | |
| 26 | b: <A as Mapping<Domain>>::Codomain, | |
| 27 | g: G, | |
| 28 | } | |
| 29 | ||
| 30 | #[allow(non_snake_case)] | |
| 31 | impl<F: Float, Domain: Space, A: Mapping<Domain>, G: Mapping<A::Codomain, Codomain = F>> | |
| 32 | DataTerm<F, Domain, A, G> | |
| 33 | { | |
| 34 | pub fn new(opA: A, b: A::Codomain, g: G) -> Self { | |
| 35 | DataTerm { opA, b, g } | |
| 36 | } | |
| 37 | ||
| 38 | pub fn operator(&self) -> &'_ A { | |
| 39 | &self.opA | |
| 40 | } | |
| 41 | ||
| 42 | pub fn data(&self) -> &'_ <A as Mapping<Domain>>::Codomain { | |
| 43 | &self.b | |
| 44 | } | |
| 45 | ||
| 46 | pub fn fidelity(&self) -> &'_ G { | |
| 47 | &self.g | |
| 48 | } | |
| 49 | } | |
| 50 | ||
| 51 | //+ AdjointProductBoundedBy<RNDM<F, N>, P, FloatType = F>, | |
| 52 | ||
| 53 | impl<F, X, A, G> Mapping<X> for DataTerm<F, X, A, G> | |
| 54 | where | |
| 55 | F: Float, | |
| 56 | X: Space, | |
| 57 | A: Mapping<X>, | |
| 58 | G: Mapping<A::Codomain, Codomain = F>, | |
| 59 | A::Codomain: for<'a> Sub<&'a A::Codomain, Output = A::Codomain>, | |
| 60 | { | |
| 61 | type Codomain = F; | |
| 62 | ||
| 63 | fn apply<I: Instance<X>>(&self, x: I) -> F { | |
| 64 | // TODO: possibly (if at all more effcient) use GEMV once generalised | |
| 65 | // to not require preallocation. However, Rust should be pretty efficient | |
| 66 | // at not doing preallocations or anything here, as the result of self.opA.apply() | |
| 67 | // can be consumed, so maybe GEMV is no use. | |
| 68 | self.g.apply(self.opA.apply(x) - &self.b) | |
| 69 | } | |
| 70 | } | |
| 71 | ||
| 72 | impl<F, X, A, G> ConvexMapping<X, F> for DataTerm<F, X, A, G> | |
| 73 | where | |
| 74 | F: Float, | |
| 75 | X: Space, | |
| 76 | A: Linear<X>, | |
| 77 | G: ConvexMapping<A::Codomain, F>, | |
| 78 | A::Codomain: for<'a> Sub<&'a A::Codomain, Output = A::Codomain>, | |
| 79 | { | |
| 80 | } | |
| 81 | ||
| 82 | impl<F, X, Y, A, G> DifferentiableImpl<X> for DataTerm<F, X, A, G> | |
| 83 | where | |
| 84 | F: Float, | |
| 85 | X: Space, | |
| 86 | Y: Space + for<'a> Sub<&'a Y, Output = Y>, | |
| 87 | //<A as Mapping<X>>::Codomain: Euclidean<F>, | |
| 88 | A: Linear<X, Codomain = Y> + Preadjointable<X, G::DerivativeDomain>, | |
| 89 | //<<A as Mapping<X>>::Codomain as Euclidean<F>>::Output: Instance<<A as Mapping<X>>::Codomain>, | |
| 90 | G: DifferentiableMapping<Y, Codomain = F>, | |
| 91 | { | |
| 92 | type Derivative = A::PreadjointCodomain; | |
| 93 | ||
| 94 | fn differential_impl<I: Instance<X>>(&self, x: I) -> Self::Derivative { | |
| 95 | // TODO: possibly (if at all more effcient) use GEMV once generalised | |
| 96 | // to not require preallocation. However, Rust should be pretty efficient | |
| 97 | // at not doing preallocations or anything here, as the result of self.opA.apply() | |
| 98 | // can be consumed, so maybe GEMV is no use. | |
| 99 | //self.opA.preadjoint().apply(self.opA.apply(x) - self.b) | |
| 100 | self.opA | |
| 101 | .preadjoint() | |
| 102 | .apply(self.g.diff_ref().apply(self.opA.apply(x) - &self.b)) | |
| 103 | } | |
| 104 | } | |
| 105 | ||
| 106 | /* | |
| 107 | impl<'a, F, X, ExpX, Y, ExpY, A, G> LipschitzDifferentiableImpl<X, ExpX> for DataTerm<F, X, A, G> | |
| 108 | where | |
| 109 | F: Float, | |
| 110 | X: Space + Clone + Norm<F, ExpX>, | |
| 111 | Y: Space + Norm<F, ExpY>, | |
| 112 | ExpX: NormExponent, | |
| 113 | ExpY: NormExponent, | |
| 114 | A: Clone + BoundedLinear<X, ExpX, L2, F, Codomain = Y>, | |
| 115 | G: Mapping<Y, Codomain = F> + LipschitzDifferentiableImpl<Y, ExpY>, | |
| 116 | Self: DifferentiableImpl<X>, | |
| 117 | { | |
| 118 | type FloatType = F; | |
| 119 | ||
| 120 | fn diff_lipschitz_factor(&self, seminorm: ExpX) -> Option<F> { | |
| 121 | Some(self.opA.opnorm_bound(seminorm, L2).powi(2)) | |
| 122 | } | |
| 123 | } | |
| 124 | */ |