| |
1 /*! |
| |
2 Simple parametric forward model. |
| |
3 */ |
| |
4 |
| |
5 use numeric_literals::replace_float_literals; |
| |
6 use alg_tools::types::{Float, ClosedAdd}; |
| |
7 use alg_tools::mapping::Space; |
| |
8 use alg_tools::direct_product::Pair; |
| |
9 use alg_tools::linops::{Linear, RowOp, ColOp, IdOp, ZeroOp, AXPY}; |
| |
10 use alg_tools::error::DynError; |
| |
11 use alg_tools::norms::{L2, Norm, PairNorm, NormExponent}; |
| |
12 use crate::types::L2Squared; |
| |
13 use crate::measures::RNDM; |
| |
14 use super::{ForwardModel, AdjointProductBoundedBy, AdjointProductPairBoundedBy, LipschitzValues}; |
| |
15 use crate::transport::TransportLipschitz; |
| |
16 |
| |
17 impl<Domain, F, A, E> ForwardModel<Pair<Domain, A::Observable>, F, PairNorm<E, L2, L2>> |
| |
18 for RowOp<A, IdOp<A::Observable>> |
| |
19 where |
| |
20 E : NormExponent, |
| |
21 Domain : Space + Norm<F, E>, |
| |
22 F : Float, |
| |
23 A::Observable : ClosedAdd + Norm<F, L2> + 'static, |
| |
24 A : ForwardModel<Domain, F, E> + 'static |
| |
25 { |
| |
26 type Observable = A::Observable; |
| |
27 |
| |
28 fn write_observable(&self, b : &Self::Observable, prefix : String) -> DynError { |
| |
29 self.0.write_observable(b, prefix) |
| |
30 } |
| |
31 |
| |
32 /// Returns a zero observable |
| |
33 fn zero_observable(&self) -> Self::Observable { |
| |
34 self.0.zero_observable() |
| |
35 } |
| |
36 } |
| |
37 |
| |
38 #[replace_float_literals(F::cast_from(literal))] |
| |
39 impl<Domain, F, A, D, Z> AdjointProductPairBoundedBy<Pair<Domain, Z>, D, IdOp<Z>> |
| |
40 for RowOp<A, IdOp<Z>> |
| |
41 where |
| |
42 Domain : Space, |
| |
43 F : Float, |
| |
44 Z : Clone + Space + ClosedAdd, |
| |
45 A : AdjointProductBoundedBy<Domain, D, FloatType=F, Codomain = Z>, |
| |
46 D : Linear<Domain>, |
| |
47 A::Codomain : ClosedAdd, |
| |
48 { |
| |
49 type FloatType = F; |
| |
50 |
| |
51 fn adjoint_product_pair_bound(&self, d : &D, _ : &IdOp<Z>) -> Option<(F, F)> { |
| |
52 self.0.adjoint_product_bound(d).map(|l_0| { |
| |
53 // [A_*; B_*][A, B] = [A_*A, A_* B; B_* A, B_* B] ≤ diag(2A_*A, 2B_*B) |
| |
54 // ≤ diag(2l_A𝒟_A, 2l_B𝒟_B), where now 𝒟_B=Id and l_B=1. |
| |
55 (2.0 * l_0, 2.0) |
| |
56 }) |
| |
57 } |
| |
58 } |
| |
59 |
| |
60 /// This `impl` is bit of an abuse as the codomain of `Apre` is a [`Pair`] of a measure predual, |
| |
61 /// to which this `impl` applies, and another space. |
| |
62 impl<F, Apre, Z> LipschitzValues |
| |
63 for ColOp<Apre, IdOp<Z>> |
| |
64 where |
| |
65 F : Float, |
| |
66 Z : Clone + Space + ClosedAdd, |
| |
67 Apre : LipschitzValues<FloatType = F>, |
| |
68 { |
| |
69 type FloatType = F; |
| |
70 /// Return (if one exists) a factor $L$ such that $A_*z$ is $L$-Lipschitz for all |
| |
71 /// $z$ in the unit ball. |
| |
72 fn value_unit_lipschitz_factor(&self) -> Option<Self::FloatType> { |
| |
73 self.0.value_unit_lipschitz_factor() |
| |
74 } |
| |
75 |
| |
76 /// Return (if one exists) a factor $L$ such that $∇A_*z$ is $L$-Lipschitz for all |
| |
77 /// $z$ in the unit ball. |
| |
78 fn value_diff_unit_lipschitz_factor(&self) -> Option<Self::FloatType> { |
| |
79 self.0.value_diff_unit_lipschitz_factor() |
| |
80 } |
| |
81 } |
| |
82 |
| |
83 |
| |
84 |
| |
85 impl<'a, F : Float, Y : Space, XD, const N : usize> TransportLipschitz<L2Squared> for |
| |
86 ZeroOp<'a, RNDM<F, N>, XD, Y, F> { |
| |
87 type FloatType = F; |
| |
88 |
| |
89 fn transport_lipschitz_factor(&self, _ : L2Squared) -> Self::FloatType { |
| |
90 F::ZERO |
| |
91 } |
| |
92 } |
| |
93 |
| |
94 |
| |
95 /// TODO: should assume `D` to be positive semi-definite and self-adjoint. |
| |
96 #[replace_float_literals(F::cast_from(literal))] |
| |
97 impl<'a, F, D, XD, Y, const N : usize> AdjointProductBoundedBy<RNDM<F, N>, D> |
| |
98 for ZeroOp<'a, RNDM<F, N>, XD, Y, F> |
| |
99 where |
| |
100 F : Float, |
| |
101 Y : AXPY<F> + Clone, |
| |
102 D : Linear<RNDM<F, N>>, |
| |
103 { |
| |
104 type FloatType = F; |
| |
105 /// Return $L$ such that $A_*A ≤ L𝒟$ is bounded by some `other` operator $𝒟$. |
| |
106 fn adjoint_product_bound(&self, _ : &D) -> Option<F> { |
| |
107 Some(0.0) |
| |
108 } |
| |
109 } |
| |
110 |