147 α : F, |
147 α : F, |
148 findim_data : &FindimData<F>, |
148 findim_data : &FindimData<F>, |
149 inner : &InnerSettings<F>, |
149 inner : &InnerSettings<F>, |
150 iterator : I |
150 iterator : I |
151 ) -> usize |
151 ) -> usize |
152 where F : Float + ToNalgebraRealField, |
152 where F : Float + ToNalgebraRealField<MixedType=F>, |
153 I : AlgIteratorFactory<F>, |
153 I : AlgIteratorFactory<F>, |
154 A : ForwardModel<Loc<F, N>, F> |
154 A : ForwardModel<Loc<F, N>, F> |
155 { |
155 { |
156 // Form and solve finite-dimensional subproblem. |
156 // Form and solve finite-dimensional subproblem. |
157 let (Ã, g̃) = opA.findim_quadratic_model(&μ, b); |
157 let (Ã, g̃) = opA.findim_quadratic_model(&μ, b); |
158 let mut x = μ.masses_dvector(); |
158 let mut x = μ.masses_mut(); |
159 |
159 |
160 // `inner_τ1` is based on an estimate of the operator norm of $A$ from ℳ(Ω) to |
160 // `inner_τ1` is based on an estimate of the operator norm of $A$ from ℳ(Ω) to |
161 // ℝ^n. This estimate is a good one for the matrix norm from ℝ^m to ℝ^n when the |
161 // ℝ^n. This estimate is a good one for the matrix norm from ℝ^m to ℝ^n when the |
162 // former is equipped with the 1-norm. We need the 2-norm. To pass from 1-norm to |
162 // former is equipped with the 1-norm. We need the 2-norm. To pass from 1-norm to |
163 // 2-norm, we estimate |
163 // 2-norm, we estimate |
166 // where C = √m satisfies ‖x‖_1 ≤ C ‖x‖_2. Since we are intested in ‖A_*A‖, no |
166 // where C = √m satisfies ‖x‖_1 ≤ C ‖x‖_2. Since we are intested in ‖A_*A‖, no |
167 // square root is needed when we scale: |
167 // square root is needed when we scale: |
168 let inner_τ = inner.τ0 / (findim_data.opAnorm_squared * F::cast_from(μ.len())); |
168 let inner_τ = inner.τ0 / (findim_data.opAnorm_squared * F::cast_from(μ.len())); |
169 let iters = quadratic_nonneg(inner.method, &Ã, &g̃, α, &mut x, inner_τ, iterator); |
169 let iters = quadratic_nonneg(inner.method, &Ã, &g̃, α, &mut x, inner_τ, iterator); |
170 // Update masses of μ based on solution of finite-dimensional subproblem. |
170 // Update masses of μ based on solution of finite-dimensional subproblem. |
171 μ.set_masses_dvector(&x); |
171 //μ.set_masses_dvector(&x); |
172 |
172 |
173 iters |
173 iters |
174 } |
174 } |
175 |
175 |
176 /// Solve point source localisation problem using a conditional gradient method |
176 /// Solve point source localisation problem using a conditional gradient method |
191 //domain : Cube<F, N>, |
191 //domain : Cube<F, N>, |
192 config : &FWConfig<F>, |
192 config : &FWConfig<F>, |
193 iterator : I, |
193 iterator : I, |
194 mut plotter : SeqPlotter<F, N>, |
194 mut plotter : SeqPlotter<F, N>, |
195 ) -> DiscreteMeasure<Loc<F, N>, F> |
195 ) -> DiscreteMeasure<Loc<F, N>, F> |
196 where F : Float + ToNalgebraRealField, |
196 where F : Float + ToNalgebraRealField<MixedType=F>, |
197 I : AlgIteratorFactory<IterInfo<F, N>>, |
197 I : AlgIteratorFactory<IterInfo<F, N>>, |
198 for<'b> &'b A::Observable : std::ops::Neg<Output=A::Observable>, |
198 for<'b> &'b A::Observable : std::ops::Neg<Output=A::Observable>, |
199 //+ std::ops::Mul<F, Output=A::Observable>, <-- FIXME: compiler overflow |
199 //+ std::ops::Mul<F, Output=A::Observable>, <-- FIXME: compiler overflow |
200 A::Observable : std::ops::MulAssign<F>, |
200 A::Observable : std::ops::MulAssign<F>, |
201 GA : SupportGenerator<F, N, SupportType = S, Id = usize> + Clone, |
201 GA : SupportGenerator<F, N, SupportType = S, Id = usize> + Clone, |