| 186 }; |
186 }; |
| 187 let mut stats = IterInfo::new(); |
187 let mut stats = IterInfo::new(); |
| 188 |
188 |
| 189 // Run the algorithm |
189 // Run the algorithm |
| 190 for state in iterator.iter_init(|| full_stats(&μ, ε, stats.clone())) { |
190 for state in iterator.iter_init(|| full_stats(&μ, ε, stats.clone())) { |
| |
191 let maybe_μ_base = config.merge_now(&state).then(|| μ.clone()); |
| |
192 let μ_base_len = μ.len(); |
| |
193 |
| 191 // Calculate smooth part of surrogate model. |
194 // Calculate smooth part of surrogate model. |
| 192 // TODO: optimise τ to be applied to residual. |
|
| 193 let mut τv = f.differential(&μ) * τ; |
195 let mut τv = f.differential(&μ) * τ; |
| 194 |
196 |
| 195 // Save current base point for merge |
197 // Do spike insertiona nd finite-dimensional weight optimisation |
| 196 let μ_base_len = μ.len(); |
198 prox_penalty.insert_and_reweigh(&mut μ, &mut τv, τ, ε, config, ®, &state, &mut stats)?; |
| 197 let maybe_μ_base = config.merge_now(&state).then(|| μ.clone()); |
|
| 198 |
|
| 199 // Insert and reweigh |
|
| 200 let (maybe_d, _within_tolerances) = prox_penalty |
|
| 201 .insert_and_reweigh(&mut μ, &mut τv, τ, ε, config, ®, &state, &mut stats)?; |
|
| 202 |
199 |
| 203 stats.inserted += μ.len() - μ_base_len; |
200 stats.inserted += μ.len() - μ_base_len; |
| 204 |
201 |
| 205 // Prune and possibly merge spikes |
202 // Prune and possibly merge spikes |
| 206 if let Some(μ_base) = maybe_μ_base { |
203 if let Some(μ_base) = maybe_μ_base { |
| 216 ); |
213 ); |
| 217 } |
214 } |
| 218 |
215 |
| 219 stats.pruned += prune_with_stats(&mut μ); |
216 stats.pruned += prune_with_stats(&mut μ); |
| 220 |
217 |
| |
218 // Do extra weight optimisation step heuristic |
| |
219 for _ in 0..config.extra_weight_optimisation_steps { |
| |
220 τv = f.differential(&μ) * τ; |
| |
221 prox_penalty.reweigh(&mut μ, &mut τv, τ, ε, config, ®, &state, &mut stats)?; |
| |
222 } |
| |
223 |
| |
224 if config.extra_weight_optimisation_steps > 0 { |
| |
225 stats.pruned += prune_with_stats(&mut μ); |
| |
226 } |
| |
227 |
| 221 let iter = state.iteration(); |
228 let iter = state.iteration(); |
| 222 stats.this_iters += 1; |
229 stats.this_iters += 1; |
| 223 |
230 |
| 224 // Give statistics if needed |
231 // Give statistics if needed |
| 225 state.if_verbose(|| { |
232 state.if_verbose(|| { |
| 226 plotter.plot_spikes(iter, maybe_d.as_ref(), Some(&τv), &μ); |
233 plotter.plot_spikes(iter, None, Some(&τv), &μ); |
| 227 full_stats(&μ, ε, std::mem::replace(&mut stats, IterInfo::new())) |
234 full_stats(&μ, ε, std::mem::replace(&mut stats, IterInfo::new())) |
| 228 }); |
235 }); |
| 229 |
236 |
| 230 // Update main tolerance for next iteration |
237 // Update main tolerance for next iteration |
| 231 ε = tolerance.update(ε, iter); |
238 ε = tolerance.update(ε, iter); |
| 290 }; |
297 }; |
| 291 let mut stats = IterInfo::new(); |
298 let mut stats = IterInfo::new(); |
| 292 |
299 |
| 293 // Run the algorithm |
300 // Run the algorithm |
| 294 for state in iterator.iter_init(|| full_stats(&μ, ε, stats.clone())) { |
301 for state in iterator.iter_init(|| full_stats(&μ, ε, stats.clone())) { |
| |
302 let μ_base_len = μ.len(); |
| 295 // Calculate smooth part of surrogate model. |
303 // Calculate smooth part of surrogate model. |
| 296 let mut τv = f.differential(&μ) * τ; |
304 let mut τv = f.differential(&μ) * τ; |
| 297 |
305 |
| 298 let μ_base_len = μ.len(); |
306 // Do spike insertiona nd finite-dimensional weight optimisation |
| 299 |
307 prox_penalty.insert_and_reweigh(&mut μ, &mut τv, τ, ε, config, ®, &state, &mut stats)?; |
| 300 // Insert new spikes and reweigh |
|
| 301 let (maybe_d, _within_tolerances) = prox_penalty |
|
| 302 .insert_and_reweigh(&mut μ, &mut τv, τ, ε, config, ®, &state, &mut stats)?; |
|
| 303 |
308 |
| 304 stats.inserted += μ.len() - μ_base_len; |
309 stats.inserted += μ.len() - μ_base_len; |
| 305 |
310 |
| 306 // (Do not) merge spikes. |
311 // (Do not) merge spikes. |
| 307 if config.merge_now(&state) && !warned_merging { |
312 if config.merge_now(&state) && !warned_merging { |
| 308 let err = format!("Merging not supported for μFISTA"); |
313 let err = format!("Merging not supported for μFISTA"); |
| 309 println!("{}", err.red()); |
314 println!("{}", err.red()); |
| 310 warned_merging = true; |
315 warned_merging = true; |
| |
316 } |
| |
317 |
| |
318 // Do extra weight optimisation step heuristic |
| |
319 for _ in 0..config.extra_weight_optimisation_steps { |
| |
320 τv = f.differential(&μ) * τ; |
| |
321 prox_penalty.reweigh(&mut μ, &mut τv, τ, ε, config, ®, &state, &mut stats)?; |
| 311 } |
322 } |
| 312 |
323 |
| 313 // Update inertial prameters |
324 // Update inertial prameters |
| 314 let λ_prev = λ; |
325 let λ_prev = λ; |
| 315 λ = 2.0 * λ_prev / (λ_prev + (4.0 + λ_prev * λ_prev).sqrt()); |
326 λ = 2.0 * λ_prev / (λ_prev + (4.0 + λ_prev * λ_prev).sqrt()); |
| 332 let iter = state.iteration(); |
343 let iter = state.iteration(); |
| 333 stats.this_iters += 1; |
344 stats.this_iters += 1; |
| 334 |
345 |
| 335 // Give statistics if needed |
346 // Give statistics if needed |
| 336 state.if_verbose(|| { |
347 state.if_verbose(|| { |
| 337 plotter.plot_spikes(iter, maybe_d.as_ref(), Some(&τv), &μ_prev); |
348 plotter.plot_spikes(iter, None, Some(&τv), &μ_prev); |
| 338 full_stats(&μ_prev, ε, std::mem::replace(&mut stats, IterInfo::new())) |
349 full_stats(&μ_prev, ε, std::mem::replace(&mut stats, IterInfo::new())) |
| 339 }); |
350 }); |
| 340 |
351 |
| 341 // Update main tolerance for next iteration |
352 // Update main tolerance for next iteration |
| 342 ε = tolerance.update(ε, iter); |
353 ε = tolerance.update(ε, iter); |