170 |
169 |
171 // Run the algorithm |
170 // Run the algorithm |
172 for state in iterator.iter_init(|| full_stats(&residual, &μ, &z, ε, stats.clone())) { |
171 for state in iterator.iter_init(|| full_stats(&residual, &μ, &z, ε, stats.clone())) { |
173 // Calculate initial transport |
172 // Calculate initial transport |
174 let Pair(mut τv, τz) = opA.preadjoint().apply(residual * τ); |
173 let Pair(mut τv, τz) = opA.preadjoint().apply(residual * τ); |
175 let z_base = z.clone(); |
|
176 let μ_base = μ.clone(); |
174 let μ_base = μ.clone(); |
177 |
175 |
178 // Construct μ^{k+1} by solving finite-dimensional subproblems and insert new spikes. |
176 // Construct μ^{k+1} by solving finite-dimensional subproblems and insert new spikes. |
179 let (maybe_d, _within_tolerances) = prox_penalty.insert_and_reweigh( |
177 let (maybe_d, _within_tolerances) = prox_penalty.insert_and_reweigh( |
180 &mut μ, &mut τv, &μ_base, None, |
178 &mut μ, &mut τv, &μ_base, None, |
181 τ, ε, &config.insertion, |
179 τ, ε, &config.insertion, |
182 ®, &state, &mut stats, |
180 ®, &state, &mut stats, |
183 ); |
181 ); |
184 |
182 |
185 // // Merge spikes. |
183 // Merge spikes. |
186 // // This expects the prune below to prune γ. |
184 // This crucially expects the merge routine to be stable with respect to spike locations, |
187 // // TODO: This may not work correctly in all cases. |
185 // and not to performing any pruning. That is be to done below simultaneously for γ. |
188 // let ins = &config.insertion; |
186 // Merge spikes. |
189 // if ins.merge_now(&state) { |
187 // This crucially expects the merge routine to be stable with respect to spike locations, |
190 // if let SpikeMergingMethod::None = ins.merging { |
188 // and not to performing any pruning. That is be to done below simultaneously for γ. |
191 // } else { |
189 let ins = &config.insertion; |
192 // stats.merged += μ.merge_spikes(ins.merging, |μ_candidate| { |
190 if ins.merge_now(&state) { |
193 // let ν = μ_candidate.sub_matching(&γ1)-&μ_base_minus_γ0; |
191 stats.merged += prox_penalty.merge_spikes_no_fitness( |
194 // let mut d = &τv̆ + op𝒟.preapply(ν); |
192 &mut μ, &mut τv, &μ_base, None, τ, ε, ins, ®, |
195 // reg.verify_merge_candidate(&mut d, μ_candidate, τ, ε, ins) |
193 //Some(|μ̃ : &RNDM<F, N>| calculate_residual(Pair(μ̃, &z), opA, b).norm2_squared_div2()), |
196 // }); |
194 ); |
197 // } |
195 } |
198 // } |
|
199 |
196 |
200 // Prune spikes with zero weight. |
197 // Prune spikes with zero weight. |
201 stats.pruned += prune_with_stats(&mut μ); |
198 stats.pruned += prune_with_stats(&mut μ); |
202 |
199 |
203 // Do z variable primal update |
200 // Do z variable primal update |
204 z.axpy(-σ_p/τ, τz, 1.0); // TODO: simplify nasty factors |
201 let mut z_new = τz; |
205 opKz.adjoint().gemv(&mut z, -σ_p, &y, 1.0); |
202 opKz.adjoint().gemv(&mut z_new, -σ_p, &y, -σ_p/τ); |
206 z = fnR.prox(σ_p, z); |
203 z_new = fnR.prox(σ_p, z_new + &z); |
207 // Do dual update |
204 // Do dual update |
208 // opKμ.gemv(&mut y, σ_d*(1.0 + ω), &μ, 1.0); // y = y + σ_d K[(1+ω)(μ,z)^{k+1}] |
205 // opKμ.gemv(&mut y, σ_d*(1.0 + ω), &μ, 1.0); // y = y + σ_d K[(1+ω)(μ,z)^{k+1}] |
209 opKz.gemv(&mut y, σ_d*(1.0 + ω), &z, 1.0); |
206 opKz.gemv(&mut y, σ_d*(1.0 + ω), &z_new, 1.0); |
210 // opKμ.gemv(&mut y, -σ_d*ω, μ_base, 1.0);// y = y + σ_d K[(1+ω)(μ,z)^{k+1} - ω (μ,z)^k]-b |
207 // opKμ.gemv(&mut y, -σ_d*ω, μ_base, 1.0);// y = y + σ_d K[(1+ω)(μ,z)^{k+1} - ω (μ,z)^k]-b |
211 opKz.gemv(&mut y, -σ_d*ω, z_base, 1.0);// y = y + σ_d K[(1+ω)(μ,z)^{k+1} - ω (μ,z)^k]-b |
208 opKz.gemv(&mut y, -σ_d*ω, z, 1.0);// y = y + σ_d K[(1+ω)(μ,z)^{k+1} - ω (μ,z)^k]-b |
212 y = starH.prox(σ_d, y); |
209 y = starH.prox(σ_d, y); |
|
210 z = z_new; |
213 |
211 |
214 // Update residual |
212 // Update residual |
215 residual = calculate_residual(Pair(&μ, &z), opA, b); |
213 residual = calculate_residual(Pair(&μ, &z), opA, b); |
216 |
214 |
217 // Update step length parameters |
215 // Update step length parameters |