src/forward_model/bias.rs

branch
dev
changeset 61
4f468d35fa29
parent 49
6b0db7251ebe
equal deleted inserted replaced
60:9738b51d90d7 61:4f468d35fa29
1 /*! 1 /*!
2 Simple parametric forward model. 2 Simple parametric forward model.
3 */ 3 */
4 4
5 use super::{AdjointProductBoundedBy, AdjointProductPairBoundedBy, BoundedCurvature, ForwardModel}; 5 use super::{BasicCurvatureBoundEstimates, BoundedCurvature, BoundedCurvatureGuess, ForwardModel};
6 use crate::measures::RNDM; 6 use crate::dataterm::QuadraticDataTerm;
7 use crate::measures::{Radon, RNDM};
8 use crate::prox_penalty::{RadonSquared, StepLengthBoundPair};
9 use crate::seminorms::DiscreteMeasureOp;
7 use alg_tools::direct_product::Pair; 10 use alg_tools::direct_product::Pair;
8 use alg_tools::error::DynError; 11 use alg_tools::error::{DynError, DynResult};
9 use alg_tools::linops::{IdOp, Linear, RowOp, ZeroOp, AXPY}; 12 use alg_tools::euclidean::ClosedEuclidean;
10 use alg_tools::mapping::Space; 13 use alg_tools::linops::{BoundedLinear, IdOp, RowOp, AXPY};
14 use alg_tools::loc::Loc;
15 use alg_tools::mapping::{Mapping, Space};
16 use alg_tools::nalgebra_support::ToNalgebraRealField;
11 use alg_tools::norms::{Norm, NormExponent, PairNorm, L2}; 17 use alg_tools::norms::{Norm, NormExponent, PairNorm, L2};
12 use alg_tools::types::{ClosedAdd, Float}; 18 use alg_tools::types::{ClosedAdd, Float};
13 use numeric_literals::replace_float_literals; 19 use numeric_literals::replace_float_literals;
14 20
15 impl<Domain, F, A, E> ForwardModel<Pair<Domain, A::Observable>, F, PairNorm<E, L2, L2>> 21 impl<Domain, F, A, E> ForwardModel<Pair<Domain, A::Observable>, F, PairNorm<E, L2, L2>>
16 for RowOp<A, IdOp<A::Observable>> 22 for RowOp<A, IdOp<A::Observable>>
17 where 23 where
18 E: NormExponent, 24 E: NormExponent,
19 Domain: Space + Norm<F, E>, 25 Domain: Space + Norm<E, F>,
20 F: Float, 26 F: Float,
21 A::Observable: ClosedAdd + Norm<F, L2> + 'static, 27 A::Observable: ClosedAdd + Norm<L2, F> + AXPY<Field = F> + 'static,
22 A: ForwardModel<Domain, F, E> + 'static, 28 A: ForwardModel<Domain, F, E> + 'static,
23 { 29 {
24 type Observable = A::Observable; 30 type Observable = A::Observable;
25 31
26 fn write_observable(&self, b: &Self::Observable, prefix: String) -> DynError { 32 fn write_observable(&self, b: &Self::Observable, prefix: String) -> DynError {
32 self.0.zero_observable() 38 self.0.zero_observable()
33 } 39 }
34 } 40 }
35 41
36 #[replace_float_literals(F::cast_from(literal))] 42 #[replace_float_literals(F::cast_from(literal))]
37 impl<Domain, F, A, D, Z> AdjointProductPairBoundedBy<Pair<Domain, Z>, D, IdOp<Z>> 43 impl<'a, F, A, 𝒟, Z, const N: usize>
38 for RowOp<A, IdOp<Z>> 44 StepLengthBoundPair<F, QuadraticDataTerm<F, Pair<RNDM<N, F>, Z>, RowOp<A, IdOp<Z>>>>
45 for Pair<&'a 𝒟, &'a IdOp<Z>>
39 where 46 where
40 Domain: Space, 47 RNDM<N, F>: Space + for<'b> Norm<&'b 𝒟, F>,
41 F: Float, 48 F: Float + ToNalgebraRealField,
42 Z: Clone + Space + ClosedAdd, 49 𝒟: DiscreteMeasureOp<Loc<N, F>, F>,
43 A: AdjointProductBoundedBy<Domain, D, FloatType = F, Codomain = Z>, 50 Z: Clone + ClosedEuclidean<F>,
44 A::Codomain: ClosedAdd, 51 A: for<'b> BoundedLinear<RNDM<N, F>, &'b 𝒟, L2, F, Codomain = Z>,
52 for<'b> &'b 𝒟: NormExponent,
45 { 53 {
46 type FloatType = F; 54 fn step_length_bound_pair(
55 &self,
56 f: &QuadraticDataTerm<F, Pair<RNDM<N, F>, Z>, RowOp<A, IdOp<Z>>>,
57 ) -> DynResult<(F, F)> {
58 let l_0 = f.operator().0.opnorm_bound(self.0, L2)?.powi(2);
59 // [A_*; B_*][A, B] = [A_*A, A_* B; B_* A, B_* B] ≤ diag(2A_*A, 2B_*B)
60 // ≤ diag(2l_A𝒟_A, 2l_B𝒟_B), where now 𝒟_B=Id and l_B=1.
61 Ok((2.0 * l_0, 2.0))
62 }
63 }
47 64
48 fn adjoint_product_pair_bound(&self, d: &D, _: &IdOp<Z>) -> Option<(F, F)> { 65 #[replace_float_literals(F::cast_from(literal))]
49 self.0.adjoint_product_bound(d).map(|l_0| { 66 impl<'a, F, A, Z, const N: usize>
50 // [A_*; B_*][A, B] = [A_*A, A_* B; B_* A, B_* B] ≤ diag(2A_*A, 2B_*B) 67 StepLengthBoundPair<F, QuadraticDataTerm<F, Pair<RNDM<N, F>, Z>, RowOp<A, IdOp<Z>>>>
51 // ≤ diag(2l_A𝒟_A, 2l_B𝒟_B), where now 𝒟_B=Id and l_B=1. 68 for Pair<&'a RadonSquared, &'a IdOp<Z>>
52 (2.0 * l_0, 2.0) 69 where
53 }) 70 RNDM<N, F>: Space + Norm<Radon, F>,
71 F: Float + ToNalgebraRealField,
72 Z: Clone + ClosedEuclidean<F>,
73 A: BoundedLinear<RNDM<N, F>, Radon, L2, F, Codomain = Z>,
74 {
75 fn step_length_bound_pair(
76 &self,
77 f: &QuadraticDataTerm<F, Pair<RNDM<N, F>, Z>, RowOp<A, IdOp<Z>>>,
78 ) -> DynResult<(F, F)> {
79 let l_0 = f.operator().0.opnorm_bound(Radon, L2)?.powi(2);
80 // [A_*; B_*][A, B] = [A_*A, A_* B; B_* A, B_* B] ≤ diag(2A_*A, 2B_*B)
81 // ≤ diag(2l_A𝒟_A, 2l_B𝒟_B), where now 𝒟_B=Id and l_B=1.
82 Ok((2.0 * l_0, 2.0))
54 } 83 }
55 } 84 }
56 85
57 /* 86 /*
58 /// This `impl` is bit of an abuse as the codomain of `Apre` is a [`Pair`] of a measure predual, 87 /// This `impl` is bit of an abuse as the codomain of `Apre` is a [`Pair`] of a measure predual,
77 self.0.value_diff_unit_lipschitz_factor() 106 self.0.value_diff_unit_lipschitz_factor()
78 } 107 }
79 } 108 }
80 */ 109 */
81 110
82 impl<F, A, Z> BoundedCurvature for RowOp<A, IdOp<Z>> 111 use BoundedCurvatureGuess::*;
112
113 /// Curvature error control: helper bounds for (4.2d), (5.2a), (5.2b), (5.15a), and (5.16a).
114 ///
115 /// Based on Lemma 5.11 and Example 5.12, the helper bound for (5.15a) and (5.16a) is (3.8).
116 /// Due to Example 6.1, defining $v^k$ as the projection $F'$ to the predual space of the
117 /// measures, returns, if possible, and subject to the guess being correct, factors $ℓ_F$ and
118 /// $Θ²$ such that $B_{P_ℳ^* F'(μ, z)} dγ ≤ ℓ_F c_2$ and
119 /// $⟨P_ℳ^*[F'(μ+Δ, z)-F'(μ, z)]|Δ⟩ ≤ Θ²|γ|(c_2)‖γ‖$, where $Δ=(π_♯^1-π_♯^0)γ$.
120 /// For our $F(μ, z)=\frac{1}{2}\|Aμ+z-b\|^2$, we have $F'(μ, z)=A\_*(Aμ+z-b)$, so
121 /// $F'(μ+Δ, z)-F'(μ, z)=A\_*AΔ$ is independent of $z$, and the bounding can be calculated
122 /// as in the case without $z$, based on Lemma 3.8.
123 ///
124 /// We use Remark 5.15 and Example 5.16 for (4.2d) and (5.2a) with the additional effect of $z$.
125 /// This is based on a Lipschitz estimate for $∇v^k$, where we still, similarly to the Example,
126 /// have $∇v^k(x)=∇A\_*(x)[Aμ^k+z^k-b]$. We estimate the final term similarly to the example,
127 /// assuming for the guess [`BetterThanZero`] that every iterate is better than $(μ, z)=0$.
128 /// This the final estimate is exactly as in the example, without $z$.
129 /// Thus we can directly use [`BasicCurvatureBoundEstimates`] on the operator $A$.
130 impl<F, A, Z, const N: usize> BoundedCurvature<F>
131 for QuadraticDataTerm<F, Pair<RNDM<N, F>, Z>, RowOp<A, IdOp<Z>>>
83 where 132 where
84 F: Float, 133 F: Float,
85 Z: Clone + Space + ClosedAdd, 134 Z: Clone + ClosedEuclidean<F>,
86 A: BoundedCurvature<FloatType = F>, 135 A: Mapping<RNDM<N, F>, Codomain = Z>,
136 A: BasicCurvatureBoundEstimates<F>,
87 { 137 {
88 type FloatType = F; 138 fn curvature_bound_components(
89 139 &self,
90 fn curvature_bound_components(&self) -> (Option<Self::FloatType>, Option<Self::FloatType>) { 140 guess: BoundedCurvatureGuess,
91 self.0.curvature_bound_components() 141 ) -> (DynResult<F>, DynResult<F>) {
142 match guess {
143 BetterThanZero => {
144 let opA = &self.operator().0;
145 let b = self.data();
146 let (ℓ_F0, θ2) = opA.basic_curvature_bound_components();
147 (ℓ_F0.map(|l| l * b.norm2()), θ2)
148 }
149 }
92 } 150 }
93 } 151 }
94
95 #[replace_float_literals(F::cast_from(literal))]
96 impl<'a, F, D, XD, Y, const N: usize> AdjointProductBoundedBy<RNDM<F, N>, D>
97 for ZeroOp<'a, RNDM<F, N>, XD, Y, F>
98 where
99 F: Float,
100 Y: AXPY<F> + Clone,
101 D: Linear<RNDM<F, N>>,
102 {
103 type FloatType = F;
104 /// Return $L$ such that $A_*A ≤ L𝒟$ is bounded by some `other` operator $𝒟$.
105 fn adjoint_product_bound(&self, _: &D) -> Option<F> {
106 Some(0.0)
107 }
108 }

mercurial