|
1 /*! |
|
2 Basid definitions for data terms |
|
3 */ |
|
4 |
|
5 use numeric_literals::replace_float_literals; |
|
6 |
|
7 use alg_tools::loc::Loc; |
|
8 use alg_tools::euclidean::Euclidean; |
|
9 use alg_tools::linops::GEMV; |
|
10 pub use alg_tools::norms::L1; |
|
11 use alg_tools::norms::Norm; |
|
12 |
|
13 use crate::types::*; |
|
14 pub use crate::types::L2Squared; |
|
15 use crate::measures::DiscreteMeasure; |
|
16 |
|
17 /// Calculates the residual $Aμ-b$. |
|
18 #[replace_float_literals(F::cast_from(literal))] |
|
19 pub(crate) fn calculate_residual< |
|
20 F : Float, |
|
21 V : Euclidean<F> + Clone, |
|
22 A : GEMV<F, DiscreteMeasure<Loc<F, N>, F>, Codomain = V>, |
|
23 const N : usize |
|
24 >( |
|
25 μ : &DiscreteMeasure<Loc<F, N>, F>, |
|
26 opA : &A, |
|
27 b : &V |
|
28 ) -> V { |
|
29 let mut r = b.clone(); |
|
30 opA.gemv(&mut r, 1.0, μ, -1.0); |
|
31 r |
|
32 } |
|
33 |
|
34 /// Calculates the residual $A(μ+μ_delta)-b$. |
|
35 #[replace_float_literals(F::cast_from(literal))] |
|
36 pub(crate) fn calculate_residual2< |
|
37 F : Float, |
|
38 V : Euclidean<F> + Clone, |
|
39 A : GEMV<F, DiscreteMeasure<Loc<F, N>, F>, Codomain = V>, |
|
40 const N : usize |
|
41 >( |
|
42 μ : &DiscreteMeasure<Loc<F, N>, F>, |
|
43 μ_delta : &DiscreteMeasure<Loc<F, N>, F>, |
|
44 opA : &A, |
|
45 b : &V |
|
46 ) -> V { |
|
47 let mut r = b.clone(); |
|
48 opA.gemv(&mut r, 1.0, μ, -1.0); |
|
49 opA.gemv(&mut r, 1.0, μ_delta, -1.0); |
|
50 r |
|
51 } |
|
52 |
|
53 |
|
54 /// Trait for data terms |
|
55 #[replace_float_literals(F::cast_from(literal))] |
|
56 pub trait DataTerm<F : Float, V, const N : usize> { |
|
57 /// Calculates $F(y)$, where $F$ is the data fidelity. |
|
58 fn calculate_fit(&self, _residual : &V) -> F; |
|
59 |
|
60 /// Calculates $F(Aμ-b)$, where $F$ is the data fidelity. |
|
61 fn calculate_fit_op<A : GEMV<F, DiscreteMeasure<Loc<F, N>, F>, Codomain = V>>( |
|
62 &self, |
|
63 μ : &DiscreteMeasure<Loc<F, N>, F>, |
|
64 opA : &A, |
|
65 b : &V |
|
66 ) -> F |
|
67 where V : Euclidean<F> + Clone { |
|
68 let r = calculate_residual(&μ, opA, b); |
|
69 self.calculate_fit(&r) |
|
70 } |
|
71 } |
|
72 |
|
73 impl<F : Float, V : Euclidean<F>, const N : usize> |
|
74 DataTerm<F, V, N> |
|
75 for L2Squared { |
|
76 fn calculate_fit(&self, residual : &V) -> F { |
|
77 residual.norm2_squared_div2() |
|
78 } |
|
79 } |
|
80 |
|
81 |
|
82 impl<F : Float, V : Euclidean<F> + Norm<F, L1>, const N : usize> |
|
83 DataTerm<F, V, N> |
|
84 for L1 { |
|
85 fn calculate_fit(&self, residual : &V) -> F { |
|
86 residual.norm(L1) |
|
87 } |
|
88 } |