src/fb.rs

changeset 8
ea3ca78873e8
parent 7
c32171f7cce5
child 13
bdc57366d4f5
equal deleted inserted replaced
7:c32171f7cce5 8:ea3ca78873e8
529 let quiet = iterator.is_quiet(); 529 let quiet = iterator.is_quiet();
530 let op𝒟norm = op𝒟.opnorm_bound(); 530 let op𝒟norm = op𝒟.opnorm_bound();
531 // We multiply tolerance by τ for FB since 531 // We multiply tolerance by τ for FB since
532 // our subproblems depending on tolerances are scaled by τ compared to the conditional 532 // our subproblems depending on tolerances are scaled by τ compared to the conditional
533 // gradient approach. 533 // gradient approach.
534 let mut tolerance = config.tolerance * τ * α; 534 let tolerance = config.tolerance * τ * α;
535 let mut ε = tolerance.initial(); 535 let mut ε = tolerance.initial();
536 536
537 // Initialise operators 537 // Initialise operators
538 let preadjA = opA.preadjoint(); 538 let preadjA = opA.preadjoint();
539 539
567 567
568 // Run the algorithm 568 // Run the algorithm
569 iterator.iterate(|state| { 569 iterator.iterate(|state| {
570 // Calculate subproblem tolerances, and update main tolerance for next iteration 570 // Calculate subproblem tolerances, and update main tolerance for next iteration
571 let τα = τ * α; 571 let τα = τ * α;
572 // if μ.len() == 0 /*state.iteration() == 1*/ {
573 // let t = minus_τv.bounds().upper() * 0.001;
574 // if t > 0.0 {
575 // let (ξ, v_ξ) = minus_τv.maximise(t, config.refinement.max_steps);
576 // if τα + ε > v_ξ && v_ξ > τα {
577 // // The zero measure is already within bounds, so improve them
578 // tolerance = config.tolerance * (v_ξ - τα);
579 // ε = tolerance.initial();
580 // }
581 // μ += DeltaMeasure { x : ξ, α : 0.0 };
582 // } else {
583 // // Zero is the solution.
584 // return Step::Terminated
585 // }
586 // }
587 let target_bounds = Bounds(τα - ε, τα + ε); 572 let target_bounds = Bounds(τα - ε, τα + ε);
588 let merge_tolerance = config.merge_tolerance_mult * ε; 573 let merge_tolerance = config.merge_tolerance_mult * ε;
589 let merge_target_bounds = Bounds(τα - merge_tolerance, τα + merge_tolerance); 574 let merge_target_bounds = Bounds(τα - merge_tolerance, τα + merge_tolerance);
590 let inner_tolerance = ε * config.inner.tolerance_mult; 575 let inner_tolerance = ε * config.inner.tolerance_mult;
591 let refinement_tolerance = ε * config.refinement.tolerance_mult; 576 let refinement_tolerance = ε * config.refinement.tolerance_mult;
592 let maximise_above = τα + ε * config.insertion_cutoff_factor; 577 let maximise_above = τα + ε * config.insertion_cutoff_factor;
593 let mut ε1 = ε;
594 let ε_prev = ε; 578 let ε_prev = ε;
595 ε = tolerance.update(ε, state.iteration()); 579 ε = tolerance.update(ε, state.iteration());
596 580
597 // Maximum insertion count and measure difference calculation depend on insertion style. 581 // Maximum insertion count and measure difference calculation depend on insertion style.
598 let (m, warn_insertions) = match (state.iteration(), config.bootstrap_insertions) { 582 let (m, warn_insertions) = match (state.iteration(), config.bootstrap_insertions) {
675 // the calculations in the beginning of the loop that v_ξ = (ω0-τv-𝒟μ)(ξ) = d(ξ), 659 // the calculations in the beginning of the loop that v_ξ = (ω0-τv-𝒟μ)(ξ) = d(ξ),
676 // where 𝒟μ is now distinct from μ0 after the insertions already performed. 660 // where 𝒟μ is now distinct from μ0 after the insertions already performed.
677 // We do not need to check lower bounds, as a solution of the finite-dimensional 661 // We do not need to check lower bounds, as a solution of the finite-dimensional
678 // subproblem should always satisfy them. 662 // subproblem should always satisfy them.
679 663
680 // // Find the mimimum over the support of μ. 664 // If μ has some spikes, only find a maximum of d if it is above a threshold
681 // let d_min_supp = d_max;μ.iter_spikes().filter_map(|&DeltaMeasure{ α, ref x }| { 665 // defined by the refinment tolerance.
682 // (α != F::ZERO).then(|| d.value(x)) 666 let (ξ, v_ξ) = match d.maximise_above(maximise_above, refinement_tolerance,
683 // }).reduce(F::min).unwrap_or(0.0); 667 config.refinement.max_steps) {
684 668 None => break 'insertion (true, d),
685 let (ξ, v_ξ) = if false /* μ.len() == 0*/ /*count == 0 &&*/ { 669 Some(res) => res,
686 // If μ has no spikes, just find the maximum of d. Then adjust the tolerance, if
687 // necessary, to adapt it to the problem.
688 let (ξ, v_ξ) = d.maximise(refinement_tolerance, config.refinement.max_steps);
689 //dbg!((τα, v_ξ, target_bounds.upper(), maximise_above));
690 if τα < v_ξ && v_ξ < target_bounds.upper() {
691 ε1 = v_ξ - τα;
692 ε *= ε1 / ε_prev;
693 tolerance *= ε1 / ε_prev;
694 }
695 (ξ, v_ξ)
696 } else {
697 // If μ has some spikes, only find a maximum of d if it is above a threshold
698 // defined by the refinment tolerance.
699 match d.maximise_above(maximise_above, refinement_tolerance,
700 config.refinement.max_steps) {
701 None => break 'insertion (true, d),
702 Some(res) => res,
703 }
704 }; 670 };
705
706 // // Do a one final check whether we can stop already without inserting more points
707 // // because `d` actually in bounds based on a more refined estimate.
708 // if may_break && target_bounds.upper() >= v_ξ {
709 // break (true, d)
710 // }
711 671
712 // Break if maximum insertion count reached 672 // Break if maximum insertion count reached
713 if count >= max_insertions { 673 if count >= max_insertions {
714 let in_bounds2 = target_bounds.upper() >= v_ξ; 674 let in_bounds2 = target_bounds.upper() >= v_ξ;
715 break 'insertion (in_bounds2, d) 675 break 'insertion (in_bounds2, d)
730 690
731 // Merge spikes 691 // Merge spikes
732 if state.iteration() % config.merge_every == 0 { 692 if state.iteration() % config.merge_every == 0 {
733 let n_before_merge = μ.len(); 693 let n_before_merge = μ.len();
734 μ.merge_spikes(config.merging, |μ_candidate| { 694 μ.merge_spikes(config.merging, |μ_candidate| {
735 //println!("Merge attempt!");
736 let mut d = &minus_τv + op𝒟.preapply(μ_diff(&μ_candidate, &μ_base)); 695 let mut d = &minus_τv + op𝒟.preapply(μ_diff(&μ_candidate, &μ_base));
737 696
738 if merge_target_bounds.superset(&d.bounds()) { 697 if merge_target_bounds.superset(&d.bounds()) {
739 //println!("…Early Ok");
740 return Some(()) 698 return Some(())
741 } 699 }
742 700
743 let d_min_supp = μ_candidate.iter_spikes().filter_map(|&DeltaMeasure{ α, ref x }| { 701 let d_min_supp = μ_candidate.iter_spikes().filter_map(|&DeltaMeasure{ α, ref x }| {
744 (α != 0.0).then(|| d.apply(x)) 702 (α != 0.0).then(|| d.apply(x))
745 }).reduce(F::min); 703 }).reduce(F::min);
746 704
747 if d_min_supp.map_or(true, |b| b >= merge_target_bounds.lower()) && 705 if d_min_supp.map_or(true, |b| b >= merge_target_bounds.lower()) &&
748 d.has_upper_bound(merge_target_bounds.upper(), refinement_tolerance, 706 d.has_upper_bound(merge_target_bounds.upper(), refinement_tolerance,
749 config.refinement.max_steps) { 707 config.refinement.max_steps) {
750 //println!("…Ok");
751 Some(()) 708 Some(())
752 } else { 709 } else {
753 //println!("…Fail");
754 None 710 None
755 } 711 }
756 }); 712 });
757 debug_assert!(μ.len() >= n_before_merge); 713 debug_assert!(μ.len() >= n_before_merge);
758 merged += μ.len() - n_before_merge; 714 merged += μ.len() - n_before_merge;
775 plotter.plot_spikes( 731 plotter.plot_spikes(
776 format!("iter {} end; {}", state.iteration(), within_tolerances), &d, 732 format!("iter {} end; {}", state.iteration(), within_tolerances), &d,
777 "start".to_string(), Some(&minus_τv), 733 "start".to_string(), Some(&minus_τv),
778 Some(target_bounds), value_μ, 734 Some(target_bounds), value_μ,
779 ); 735 );
780 // Calculate mean inner iterations and reset relevant counters 736 // Calculate mean inner iterations and reset relevant counters.
781 // Return the statistics 737 // Return the statistics
782 let res = IterInfo { 738 let res = IterInfo {
783 value : specialisation.calculate_fit(&μ, &residual) + α * value_μ.norm(Radon), 739 value : specialisation.calculate_fit(&μ, &residual) + α * value_μ.norm(Radon),
784 n_spikes : value_μ.len(), 740 n_spikes : value_μ.len(),
785 inner_iters, 741 inner_iters,
786 this_iters, 742 this_iters,
787 merged, 743 merged,
788 pruned, 744 pruned,
789 ε : ε_prev, 745 ε : ε_prev,
790 maybe_ε1 : Some(ε1),
791 postprocessing: config.postprocessing.then(|| value_μ.clone()), 746 postprocessing: config.postprocessing.then(|| value_μ.clone()),
792 }; 747 };
793 inner_iters = 0; 748 inner_iters = 0;
794 this_iters = 0; 749 this_iters = 0;
795 merged = 0; 750 merged = 0;

mercurial