1 /*! |
1 /*! |
2 Simple parametric forward model. |
2 Simple parametric forward model. |
3 */ |
3 */ |
4 |
4 |
|
5 use super::{AdjointProductBoundedBy, AdjointProductPairBoundedBy, BoundedCurvature, ForwardModel}; |
|
6 use crate::measures::RNDM; |
|
7 use alg_tools::direct_product::Pair; |
|
8 use alg_tools::error::DynError; |
|
9 use alg_tools::linops::{IdOp, Linear, RowOp, ZeroOp, AXPY}; |
|
10 use alg_tools::mapping::Space; |
|
11 use alg_tools::norms::{Norm, NormExponent, PairNorm, L2}; |
|
12 use alg_tools::types::{ClosedAdd, Float}; |
5 use numeric_literals::replace_float_literals; |
13 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, IdOp, ZeroOp, AXPY}; |
|
10 use alg_tools::error::DynError; |
|
11 use alg_tools::norms::{L2, Norm, PairNorm, NormExponent}; |
|
12 use crate::measures::RNDM; |
|
13 use super::{ForwardModel, AdjointProductBoundedBy, AdjointProductPairBoundedBy, BoundedCurvature}; |
|
14 |
14 |
15 impl<Domain, F, A, E> ForwardModel<Pair<Domain, A::Observable>, F, PairNorm<E, L2, L2>> |
15 impl<Domain, F, A, E> ForwardModel<Pair<Domain, A::Observable>, F, PairNorm<E, L2, L2>> |
16 for RowOp<A, IdOp<A::Observable>> |
16 for RowOp<A, IdOp<A::Observable>> |
17 where |
17 where |
18 E : NormExponent, |
18 E: NormExponent, |
19 Domain : Space + Norm<F, E>, |
19 Domain: Space + Norm<F, E>, |
20 F : Float, |
20 F: Float, |
21 A::Observable : ClosedAdd + Norm<F, L2> + 'static, |
21 A::Observable: ClosedAdd + Norm<F, L2> + 'static, |
22 A : ForwardModel<Domain, F, E> + 'static |
22 A: ForwardModel<Domain, F, E> + 'static, |
23 { |
23 { |
24 type Observable = A::Observable; |
24 type Observable = A::Observable; |
25 |
25 |
26 fn write_observable(&self, b : &Self::Observable, prefix : String) -> DynError { |
26 fn write_observable(&self, b: &Self::Observable, prefix: String) -> DynError { |
27 self.0.write_observable(b, prefix) |
27 self.0.write_observable(b, prefix) |
28 } |
28 } |
29 |
29 |
30 /// Returns a zero observable |
30 /// Returns a zero observable |
31 fn zero_observable(&self) -> Self::Observable { |
31 fn zero_observable(&self) -> Self::Observable { |
33 } |
33 } |
34 } |
34 } |
35 |
35 |
36 #[replace_float_literals(F::cast_from(literal))] |
36 #[replace_float_literals(F::cast_from(literal))] |
37 impl<Domain, F, A, D, Z> AdjointProductPairBoundedBy<Pair<Domain, Z>, D, IdOp<Z>> |
37 impl<Domain, F, A, D, Z> AdjointProductPairBoundedBy<Pair<Domain, Z>, D, IdOp<Z>> |
38 for RowOp<A, IdOp<Z>> |
38 for RowOp<A, IdOp<Z>> |
39 where |
39 where |
40 Domain : Space, |
40 Domain: Space, |
41 F : Float, |
41 F: Float, |
42 Z : Clone + Space + ClosedAdd, |
42 Z: Clone + Space + ClosedAdd, |
43 A : AdjointProductBoundedBy<Domain, D, FloatType=F, Codomain = Z>, |
43 A: AdjointProductBoundedBy<Domain, D, FloatType = F, Codomain = Z>, |
44 A::Codomain : ClosedAdd, |
44 A::Codomain: ClosedAdd, |
45 { |
45 { |
46 type FloatType = F; |
46 type FloatType = F; |
47 |
47 |
48 fn adjoint_product_pair_bound(&self, d : &D, _ : &IdOp<Z>) -> Option<(F, F)> { |
48 fn adjoint_product_pair_bound(&self, d: &D, _: &IdOp<Z>) -> Option<(F, F)> { |
49 self.0.adjoint_product_bound(d).map(|l_0| { |
49 self.0.adjoint_product_bound(d).map(|l_0| { |
50 // [A_*; B_*][A, B] = [A_*A, A_* B; B_* A, B_* B] ≤ diag(2A_*A, 2B_*B) |
50 // [A_*; B_*][A, B] = [A_*A, A_* B; B_* A, B_* B] ≤ diag(2A_*A, 2B_*B) |
51 // ≤ diag(2l_A𝒟_A, 2l_B𝒟_B), where now 𝒟_B=Id and l_B=1. |
51 // ≤ diag(2l_A𝒟_A, 2l_B𝒟_B), where now 𝒟_B=Id and l_B=1. |
52 (2.0 * l_0, 2.0) |
52 (2.0 * l_0, 2.0) |
53 }) |
53 }) |
77 self.0.value_diff_unit_lipschitz_factor() |
77 self.0.value_diff_unit_lipschitz_factor() |
78 } |
78 } |
79 } |
79 } |
80 */ |
80 */ |
81 |
81 |
82 impl<F, A, Z> BoundedCurvature |
82 impl<F, A, Z> BoundedCurvature for RowOp<A, IdOp<Z>> |
83 for RowOp<A, IdOp<Z>> |
|
84 where |
83 where |
85 F : Float, |
84 F: Float, |
86 Z : Clone + Space + ClosedAdd, |
85 Z: Clone + Space + ClosedAdd, |
87 A : BoundedCurvature<FloatType = F>, |
86 A: BoundedCurvature<FloatType = F>, |
88 { |
87 { |
89 type FloatType = F; |
88 type FloatType = F; |
90 |
89 |
91 fn curvature_bound_components(&self) -> (Option<Self::FloatType>, Option<Self::FloatType>) { |
90 fn curvature_bound_components(&self) -> (Option<Self::FloatType>, Option<Self::FloatType>) { |
92 self.0.curvature_bound_components() |
91 self.0.curvature_bound_components() |
93 } |
92 } |
94 } |
93 } |
95 |
94 |
96 #[replace_float_literals(F::cast_from(literal))] |
95 #[replace_float_literals(F::cast_from(literal))] |
97 impl<'a, F, D, XD, Y, const N : usize> AdjointProductBoundedBy<RNDM<F, N>, D> |
96 impl<'a, F, D, XD, Y, const N: usize> AdjointProductBoundedBy<RNDM<F, N>, D> |
98 for ZeroOp<'a, RNDM<F, N>, XD, Y, F> |
97 for ZeroOp<'a, RNDM<F, N>, XD, Y, F> |
99 where |
98 where |
100 F : Float, |
99 F: Float, |
101 Y : AXPY<F> + Clone, |
100 Y: AXPY<F> + Clone, |
102 D : Linear<RNDM<F, N>>, |
101 D: Linear<RNDM<F, N>>, |
103 { |
102 { |
104 type FloatType = F; |
103 type FloatType = F; |
105 /// Return $L$ such that $A_*A ≤ L𝒟$ is bounded by some `other` operator $𝒟$. |
104 /// Return $L$ such that $A_*A ≤ L𝒟$ is bounded by some `other` operator $𝒟$. |
106 fn adjoint_product_bound(&self, _ : &D) -> Option<F> { |
105 fn adjoint_product_bound(&self, _: &D) -> Option<F> { |
107 Some(0.0) |
106 Some(0.0) |
108 } |
107 } |
109 } |
108 } |
110 |
|