| 421 -> &'c DiscreteMeasure<Loc<F, N>, F> { |
425 -> &'c DiscreteMeasure<Loc<F, N>, F> { |
| 422 &self.μ_prev |
426 &self.μ_prev |
| 423 } |
427 } |
| 424 } |
428 } |
| 425 |
429 |
| 426 /// Iteratively solve the pointsource localisation problem using forward-backward splitting |
430 |
| 427 /// |
431 /// Abstraction of regularisation terms for [`generic_pointsource_fb_reg`]. |
| 428 /// The settings in `config` have their [respective documentation](FBConfig). `opA` is the |
432 pub trait RegTerm<F : Float + ToNalgebraRealField, const N : usize> |
| 429 /// forward operator $A$, $b$ the observable, and $\lambda$ the regularisation weight. |
433 : for<'a> Apply<&'a DiscreteMeasure<Loc<F, N>, F>, Output = F> { |
| 430 /// The operator `op𝒟` is used for forming the proximal term. Typically it is a convolution |
434 /// Approximately solve the problem |
| 431 /// operator. Finally, the `iterator` is an outer loop verbosity and iteration count control |
435 /// <div>$$ |
| 432 /// as documented in [`alg_tools::iterate`]. |
436 /// \min_{x ∈ ℝ^n} \frac{1}{2} x^⊤Ax - g^⊤ x + τ G(x) |
| 433 /// |
437 /// $$</div> |
| 434 /// For details on the mathematical formulation, see the [module level](self) documentation. |
438 /// for $G$ depending on the trait implementation. |
| 435 /// |
439 /// |
| 436 /// Returns the final iterate. |
440 /// The parameter `mA` is $A$. An estimate for its opeator norm should be provided in |
| |
441 /// `mA_normest`. The initial iterate and output is `x`. The current main tolerance is `ε`. |
| |
442 /// |
| |
443 /// Returns the number of iterations taken. |
| |
444 fn solve_findim( |
| |
445 &self, |
| |
446 mA : &DMatrix<F::MixedType>, |
| |
447 g : &DVector<F::MixedType>, |
| |
448 τ : F, |
| |
449 x : &mut DVector<F::MixedType>, |
| |
450 mA_normest : F, |
| |
451 ε : F, |
| |
452 config : &FBGenericConfig<F> |
| |
453 ) -> usize; |
| |
454 |
| |
455 /// Find a point where `d` may violate the tolerance `ε`. |
| |
456 /// |
| |
457 /// If `skip_by_rough_check` is set, do not find the point if a rough check indicates that we |
| |
458 /// are in bounds. `ε` is the current main tolerance and `τ` a scaling factor for the |
| |
459 /// regulariser. |
| |
460 /// |
| |
461 /// Returns `None` if `d` is in bounds either based on the rough check, or a more precise check |
| |
462 /// terminating early. Otherwise returns a possibly violating point, the value of `d` there, |
| |
463 /// and a boolean indicating whether the found point is in bounds. |
| |
464 fn find_tolerance_violation<G, BT>( |
| |
465 &self, |
| |
466 d : &mut BTFN<F, G, BT, N>, |
| |
467 τ : F, |
| |
468 ε : F, |
| |
469 skip_by_rough_check : bool, |
| |
470 config : &FBGenericConfig<F>, |
| |
471 ) -> Option<(Loc<F, N>, F, bool)> |
| |
472 where BT : BTSearch<F, N, Agg=Bounds<F>>, |
| |
473 G : SupportGenerator<F, N, Id=BT::Data>, |
| |
474 G::SupportType : Mapping<Loc<F, N>,Codomain=F> |
| |
475 + LocalAnalysis<F, Bounds<F>, N>; |
| |
476 |
| |
477 /// Verify that `d` is in bounds `ε` for a merge candidate `μ` |
| |
478 /// |
| |
479 /// `ε` is the current main tolerance and `τ` a scaling factor for the regulariser. |
| |
480 fn verify_merge_candidate<G, BT>( |
| |
481 &self, |
| |
482 d : &mut BTFN<F, G, BT, N>, |
| |
483 μ : &DiscreteMeasure<Loc<F, N>, F>, |
| |
484 τ : F, |
| |
485 ε : F, |
| |
486 config : &FBGenericConfig<F>, |
| |
487 ) -> bool |
| |
488 where BT : BTSearch<F, N, Agg=Bounds<F>>, |
| |
489 G : SupportGenerator<F, N, Id=BT::Data>, |
| |
490 G::SupportType : Mapping<Loc<F, N>,Codomain=F> |
| |
491 + LocalAnalysis<F, Bounds<F>, N>; |
| |
492 |
| |
493 fn target_bounds(&self, τ : F, ε : F) -> Option<Bounds<F>>; |
| |
494 |
| |
495 /// Returns a scaling factor for the tolerance sequence. |
| |
496 /// |
| |
497 /// Typically this is the regularisation parameter. |
| |
498 fn tolerance_scaling(&self) -> F; |
| |
499 } |
| |
500 |
| 437 #[replace_float_literals(F::cast_from(literal))] |
501 #[replace_float_literals(F::cast_from(literal))] |
| 438 pub fn pointsource_fb<'a, F, I, A, GA, 𝒟, BTA, G𝒟, S, K, const N : usize>( |
502 impl<F : Float + ToNalgebraRealField, const N : usize> RegTerm<F, N> for NonnegRadonRegTerm<F> |
| 439 opA : &'a A, |
503 where Cube<F, N> : P2Minimise<Loc<F, N>, F> { |
| 440 b : &A::Observable, |
504 fn solve_findim( |
| 441 α : F, |
505 &self, |
| 442 op𝒟 : &'a 𝒟, |
506 mA : &DMatrix<F::MixedType>, |
| 443 config : &FBConfig<F>, |
507 g : &DVector<F::MixedType>, |
| 444 iterator : I, |
508 τ : F, |
| 445 plotter : SeqPlotter<F, N> |
509 x : &mut DVector<F::MixedType>, |
| 446 ) -> DiscreteMeasure<Loc<F, N>, F> |
510 mA_normest : F, |
| 447 where F : Float + ToNalgebraRealField, |
511 ε : F, |
| 448 I : AlgIteratorFactory<IterInfo<F, N>>, |
512 config : &FBGenericConfig<F> |
| 449 for<'b> &'b A::Observable : std::ops::Neg<Output=A::Observable>, |
513 ) -> usize { |
| 450 //+ std::ops::Mul<F, Output=A::Observable>, <-- FIXME: compiler overflow |
514 let inner_tolerance = ε * config.inner.tolerance_mult; |
| 451 A::Observable : std::ops::MulAssign<F>, |
515 let inner_it = config.inner.iterator_options.stop_target(inner_tolerance); |
| 452 GA : SupportGenerator<F, N, SupportType = S, Id = usize> + Clone, |
516 let inner_τ = config.inner.τ0 / mA_normest; |
| 453 A : ForwardModel<Loc<F, N>, F, PreadjointCodomain = BTFN<F, GA, BTA, N>> |
517 quadratic_nonneg(config.inner.method, mA, g, τ * self.α(), x, |
| 454 + Lipschitz<𝒟, FloatType=F>, |
518 inner_τ, inner_it) |
| 455 BTA : BTSearch<F, N, Data=usize, Agg=Bounds<F>>, |
519 } |
| 456 G𝒟 : SupportGenerator<F, N, SupportType = K, Id = usize> + Clone, |
520 |
| 457 𝒟 : DiscreteMeasureOp<Loc<F, N>, F, PreCodomain = PreBTFN<F, G𝒟, N>>, |
521 #[inline] |
| 458 𝒟::Codomain : RealMapping<F, N>, |
522 fn find_tolerance_violation<G, BT>( |
| 459 S: RealMapping<F, N> + LocalAnalysis<F, Bounds<F>, N>, |
523 &self, |
| 460 K: RealMapping<F, N> + LocalAnalysis<F, Bounds<F>, N>, |
524 d : &mut BTFN<F, G, BT, N>, |
| 461 BTNodeLookup: BTNode<F, usize, Bounds<F>, N>, |
525 τ : F, |
| 462 Cube<F, N>: P2Minimise<Loc<F, N>, F>, |
526 ε : F, |
| 463 PlotLookup : Plotting<N>, |
527 skip_by_rough_check : bool, |
| 464 DiscreteMeasure<Loc<F, N>, F> : SpikeMerging<F> { |
528 config : &FBGenericConfig<F>, |
| 465 |
529 ) -> Option<(Loc<F, N>, F, bool)> |
| 466 let initial_residual = -b; |
530 where BT : BTSearch<F, N, Agg=Bounds<F>>, |
| 467 let τ = config.τ0/opA.lipschitz_factor(&op𝒟).unwrap(); |
531 G : SupportGenerator<F, N, Id=BT::Data>, |
| 468 |
532 G::SupportType : Mapping<Loc<F, N>,Codomain=F> |
| 469 match config.meta { |
533 + LocalAnalysis<F, Bounds<F>, N> { |
| 470 FBMetaAlgorithm::None => generic_pointsource_fb( |
534 let τα = τ * self.α(); |
| 471 opA, α, op𝒟, τ, &config.insertion, iterator, plotter, initial_residual, |
535 let keep_below = τα + ε; |
| 472 BasicFB{ b, opA } |
536 let maximise_above = τα + ε * config.insertion_cutoff_factor; |
| 473 ), |
537 let refinement_tolerance = ε * config.refinement.tolerance_mult; |
| 474 FBMetaAlgorithm::InertiaFISTA => generic_pointsource_fb( |
538 |
| 475 opA, α, op𝒟, τ, &config.insertion, iterator, plotter, initial_residual, |
539 // If preliminary check indicates that we are in bonds, and if it otherwise matches |
| 476 FISTA{ b, opA, λ : 1.0, μ_prev : DiscreteMeasure::new() } |
540 // the insertion strategy, skip insertion. |
| 477 ), |
541 if skip_by_rough_check && d.bounds().upper() <= keep_below { |
| 478 } |
542 None |
| 479 } |
543 } else { |
| 480 |
544 // If the rough check didn't indicate no insertion needed, find maximising point. |
| 481 /// Generic implementation of [`pointsource_fb`]. |
545 d.maximise_above(maximise_above, refinement_tolerance, config.refinement.max_steps) |
| |
546 .map(|(ξ, v_ξ)| (ξ, v_ξ, v_ξ <= keep_below)) |
| |
547 } |
| |
548 } |
| |
549 |
| |
550 fn verify_merge_candidate<G, BT>( |
| |
551 &self, |
| |
552 d : &mut BTFN<F, G, BT, N>, |
| |
553 μ : &DiscreteMeasure<Loc<F, N>, F>, |
| |
554 τ : F, |
| |
555 ε : F, |
| |
556 config : &FBGenericConfig<F>, |
| |
557 ) -> bool |
| |
558 where BT : BTSearch<F, N, Agg=Bounds<F>>, |
| |
559 G : SupportGenerator<F, N, Id=BT::Data>, |
| |
560 G::SupportType : Mapping<Loc<F, N>,Codomain=F> |
| |
561 + LocalAnalysis<F, Bounds<F>, N> { |
| |
562 let τα = τ * self.α(); |
| |
563 let refinement_tolerance = ε * config.refinement.tolerance_mult; |
| |
564 let merge_tolerance = config.merge_tolerance_mult * ε; |
| |
565 let keep_below = τα + merge_tolerance; |
| |
566 let keep_supp_above = τα - merge_tolerance; |
| |
567 let bnd = d.bounds(); |
| |
568 |
| |
569 return ( |
| |
570 bnd.lower() >= keep_supp_above |
| |
571 || |
| |
572 μ.iter_spikes().map(|&DeltaMeasure{ α : β, ref x }| { |
| |
573 (β == 0.0) || d.apply(x) >= keep_supp_above |
| |
574 }).all(std::convert::identity) |
| |
575 ) && ( |
| |
576 bnd.upper() <= keep_below |
| |
577 || |
| |
578 d.has_upper_bound(keep_below, refinement_tolerance, config.refinement.max_steps) |
| |
579 ) |
| |
580 } |
| |
581 |
| |
582 fn target_bounds(&self, τ : F, ε : F) -> Option<Bounds<F>> { |
| |
583 let τα = τ * self.α(); |
| |
584 Some(Bounds(τα - ε, τα + ε)) |
| |
585 } |
| |
586 |
| |
587 fn tolerance_scaling(&self) -> F { |
| |
588 self.α() |
| |
589 } |
| |
590 } |
| |
591 |
| |
592 #[replace_float_literals(F::cast_from(literal))] |
| |
593 impl<F : Float + ToNalgebraRealField, const N : usize> RegTerm<F, N> for RadonRegTerm<F> |
| |
594 where Cube<F, N> : P2Minimise<Loc<F, N>, F> { |
| |
595 fn solve_findim( |
| |
596 &self, |
| |
597 mA : &DMatrix<F::MixedType>, |
| |
598 g : &DVector<F::MixedType>, |
| |
599 τ : F, |
| |
600 x : &mut DVector<F::MixedType>, |
| |
601 mA_normest: F, |
| |
602 ε : F, |
| |
603 config : &FBGenericConfig<F> |
| |
604 ) -> usize { |
| |
605 let inner_tolerance = ε * config.inner.tolerance_mult; |
| |
606 let inner_it = config.inner.iterator_options.stop_target(inner_tolerance); |
| |
607 let inner_τ = config.inner.τ0 / mA_normest; |
| |
608 quadratic_unconstrained(config.inner.method, mA, g, τ * self.α(), x, |
| |
609 inner_τ, inner_it) |
| |
610 } |
| |
611 |
| |
612 fn find_tolerance_violation<G, BT>( |
| |
613 &self, |
| |
614 d : &mut BTFN<F, G, BT, N>, |
| |
615 τ : F, |
| |
616 ε : F, |
| |
617 skip_by_rough_check : bool, |
| |
618 config : &FBGenericConfig<F>, |
| |
619 ) -> Option<(Loc<F, N>, F, bool)> |
| |
620 where BT : BTSearch<F, N, Agg=Bounds<F>>, |
| |
621 G : SupportGenerator<F, N, Id=BT::Data>, |
| |
622 G::SupportType : Mapping<Loc<F, N>,Codomain=F> |
| |
623 + LocalAnalysis<F, Bounds<F>, N> { |
| |
624 let τα = τ * self.α(); |
| |
625 let keep_below = τα + ε; |
| |
626 let keep_above = -τα - ε; |
| |
627 let maximise_above = τα + ε * config.insertion_cutoff_factor; |
| |
628 let minimise_below = -τα - ε * config.insertion_cutoff_factor; |
| |
629 let refinement_tolerance = ε * config.refinement.tolerance_mult; |
| |
630 |
| |
631 // If preliminary check indicates that we are in bonds, and if it otherwise matches |
| |
632 // the insertion strategy, skip insertion. |
| |
633 if skip_by_rough_check && Bounds(keep_above, keep_below).superset(&d.bounds()) { |
| |
634 None |
| |
635 } else { |
| |
636 // If the rough check didn't indicate no insertion needed, find maximising point. |
| |
637 let mx = d.maximise_above(maximise_above, refinement_tolerance, |
| |
638 config.refinement.max_steps); |
| |
639 let mi = d.minimise_below(minimise_below, refinement_tolerance, |
| |
640 config.refinement.max_steps); |
| |
641 |
| |
642 match (mx, mi) { |
| |
643 (None, None) => None, |
| |
644 (Some((ξ, v_ξ)), None) => Some((ξ, v_ξ, keep_below >= v_ξ)), |
| |
645 (None, Some((ζ, v_ζ))) => Some((ζ, v_ζ, keep_above <= v_ζ)), |
| |
646 (Some((ξ, v_ξ)), Some((ζ, v_ζ))) => { |
| |
647 if v_ξ - τα > τα - v_ζ { |
| |
648 Some((ξ, v_ξ, keep_below >= v_ξ)) |
| |
649 } else { |
| |
650 Some((ζ, v_ζ, keep_above <= v_ζ)) |
| |
651 } |
| |
652 } |
| |
653 } |
| |
654 } |
| |
655 } |
| |
656 |
| |
657 fn verify_merge_candidate<G, BT>( |
| |
658 &self, |
| |
659 d : &mut BTFN<F, G, BT, N>, |
| |
660 μ : &DiscreteMeasure<Loc<F, N>, F>, |
| |
661 τ : F, |
| |
662 ε : F, |
| |
663 config : &FBGenericConfig<F>, |
| |
664 ) -> bool |
| |
665 where BT : BTSearch<F, N, Agg=Bounds<F>>, |
| |
666 G : SupportGenerator<F, N, Id=BT::Data>, |
| |
667 G::SupportType : Mapping<Loc<F, N>,Codomain=F> |
| |
668 + LocalAnalysis<F, Bounds<F>, N> { |
| |
669 let τα = τ * self.α(); |
| |
670 let refinement_tolerance = ε * config.refinement.tolerance_mult; |
| |
671 let merge_tolerance = config.merge_tolerance_mult * ε; |
| |
672 let keep_below = τα + merge_tolerance; |
| |
673 let keep_above = -τα - merge_tolerance; |
| |
674 let keep_supp_pos_above = τα - merge_tolerance; |
| |
675 let keep_supp_neg_below = -τα + merge_tolerance; |
| |
676 let bnd = d.bounds(); |
| |
677 |
| |
678 return ( |
| |
679 (bnd.lower() >= keep_supp_pos_above && bnd.upper() <= keep_supp_neg_below) |
| |
680 || |
| |
681 μ.iter_spikes().map(|&DeltaMeasure{ α : β, ref x }| { |
| |
682 use std::cmp::Ordering::*; |
| |
683 match β.partial_cmp(&0.0) { |
| |
684 Some(Greater) => d.apply(x) >= keep_supp_pos_above, |
| |
685 Some(Less) => d.apply(x) <= keep_supp_neg_below, |
| |
686 _ => true, |
| |
687 } |
| |
688 }).all(std::convert::identity) |
| |
689 ) && ( |
| |
690 bnd.upper() <= keep_below |
| |
691 || |
| |
692 d.has_upper_bound(keep_below, refinement_tolerance, |
| |
693 config.refinement.max_steps) |
| |
694 ) && ( |
| |
695 bnd.lower() >= keep_above |
| |
696 || |
| |
697 d.has_lower_bound(keep_above, refinement_tolerance, |
| |
698 config.refinement.max_steps) |
| |
699 ) |
| |
700 } |
| |
701 |
| |
702 fn target_bounds(&self, τ : F, ε : F) -> Option<Bounds<F>> { |
| |
703 let τα = τ * self.α(); |
| |
704 Some(Bounds(-τα - ε, τα + ε)) |
| |
705 } |
| |
706 |
| |
707 fn tolerance_scaling(&self) -> F { |
| |
708 self.α() |
| |
709 } |
| |
710 } |
| |
711 |
| |
712 |
| |
713 /// Generic implementation of [`pointsource_fb_reg`]. |
| 482 /// |
714 /// |
| 483 /// The method can be specialised to even primal-dual proximal splitting through the |
715 /// The method can be specialised to even primal-dual proximal splitting through the |
| 484 /// [`FBSpecialisation`] parameter `specialisation`. |
716 /// [`FBSpecialisation`] parameter `specialisation`. |
| 485 /// The settings in `config` have their [respective documentation](FBGenericConfig). `opA` is the |
717 /// The settings in `config` have their [respective documentation](FBGenericConfig). `opA` is the |
| 486 /// forward operator $A$, $b$ the observable, and $\lambda$ the regularisation weight. |
718 /// forward operator $A$, $b$ the observable, and $\lambda$ the regularisation weight. |
| 755 }); |
953 }); |
| 756 |
954 |
| 757 specialisation.postprocess(μ, config.final_merging) |
955 specialisation.postprocess(μ, config.final_merging) |
| 758 } |
956 } |
| 759 |
957 |
| 760 |
958 /// Iteratively solve the pointsource localisation problem using forward-backward splitting |
| 761 |
959 /// |
| 762 |
960 /// The settings in `config` have their [respective documentation](FBConfig). `opA` is the |
| |
961 /// forward operator $A$, $b$ the observable, and $\lambda$ the regularisation weight. |
| |
962 /// The operator `op𝒟` is used for forming the proximal term. Typically it is a convolution |
| |
963 /// operator. Finally, the `iterator` is an outer loop verbosity and iteration count control |
| |
964 /// as documented in [`alg_tools::iterate`]. |
| |
965 /// |
| |
966 /// For details on the mathematical formulation, see the [module level](self) documentation. |
| |
967 /// |
| |
968 /// Returns the final iterate. |
| |
969 #[replace_float_literals(F::cast_from(literal))] |
| |
970 pub fn pointsource_fb_reg<'a, F, I, A, GA, 𝒟, BTA, G𝒟, S, K, Reg, const N : usize>( |
| |
971 opA : &'a A, |
| |
972 b : &A::Observable, |
| |
973 reg : Reg, |
| |
974 op𝒟 : &'a 𝒟, |
| |
975 config : &FBConfig<F>, |
| |
976 iterator : I, |
| |
977 plotter : SeqPlotter<F, N>, |
| |
978 ) -> DiscreteMeasure<Loc<F, N>, F> |
| |
979 where F : Float + ToNalgebraRealField, |
| |
980 I : AlgIteratorFactory<IterInfo<F, N>>, |
| |
981 for<'b> &'b A::Observable : std::ops::Neg<Output=A::Observable>, |
| |
982 //+ std::ops::Mul<F, Output=A::Observable>, <-- FIXME: compiler overflow |
| |
983 A::Observable : std::ops::MulAssign<F>, |
| |
984 GA : SupportGenerator<F, N, SupportType = S, Id = usize> + Clone, |
| |
985 A : ForwardModel<Loc<F, N>, F, PreadjointCodomain = BTFN<F, GA, BTA, N>> |
| |
986 + Lipschitz<𝒟, FloatType=F>, |
| |
987 BTA : BTSearch<F, N, Data=usize, Agg=Bounds<F>>, |
| |
988 G𝒟 : SupportGenerator<F, N, SupportType = K, Id = usize> + Clone, |
| |
989 𝒟 : DiscreteMeasureOp<Loc<F, N>, F, PreCodomain = PreBTFN<F, G𝒟, N>>, |
| |
990 𝒟::Codomain : RealMapping<F, N>, |
| |
991 S: RealMapping<F, N> + LocalAnalysis<F, Bounds<F>, N>, |
| |
992 K: RealMapping<F, N> + LocalAnalysis<F, Bounds<F>, N>, |
| |
993 BTNodeLookup: BTNode<F, usize, Bounds<F>, N>, |
| |
994 Cube<F, N>: P2Minimise<Loc<F, N>, F>, |
| |
995 PlotLookup : Plotting<N>, |
| |
996 DiscreteMeasure<Loc<F, N>, F> : SpikeMerging<F>, |
| |
997 Reg : RegTerm<F, N> { |
| |
998 |
| |
999 let initial_residual = -b; |
| |
1000 let τ = config.τ0/opA.lipschitz_factor(&op𝒟).unwrap(); |
| |
1001 |
| |
1002 match config.meta { |
| |
1003 FBMetaAlgorithm::None => generic_pointsource_fb_reg( |
| |
1004 opA, reg, op𝒟, τ, &config.insertion, iterator, plotter, initial_residual, |
| |
1005 BasicFB{ b, opA }, |
| |
1006 ), |
| |
1007 FBMetaAlgorithm::InertiaFISTA => generic_pointsource_fb_reg( |
| |
1008 opA, reg, op𝒟, τ, &config.insertion, iterator, plotter, initial_residual, |
| |
1009 FISTA{ b, opA, λ : 1.0, μ_prev : DiscreteMeasure::new() }, |
| |
1010 ), |
| |
1011 } |
| |
1012 } |
| |
1013 |
| |
1014 // |
| |
1015 // Deprecated interfaces |
| |
1016 // |
| |
1017 |
| |
1018 #[deprecated(note = "Use `pointsource_fb_reg`")] |
| |
1019 pub fn pointsource_fb<'a, F, I, A, GA, 𝒟, BTA, G𝒟, S, K, const N : usize>( |
| |
1020 opA : &'a A, |
| |
1021 b : &A::Observable, |
| |
1022 α : F, |
| |
1023 op𝒟 : &'a 𝒟, |
| |
1024 config : &FBConfig<F>, |
| |
1025 iterator : I, |
| |
1026 plotter : SeqPlotter<F, N> |
| |
1027 ) -> DiscreteMeasure<Loc<F, N>, F> |
| |
1028 where F : Float + ToNalgebraRealField, |
| |
1029 I : AlgIteratorFactory<IterInfo<F, N>>, |
| |
1030 for<'b> &'b A::Observable : std::ops::Neg<Output=A::Observable>, |
| |
1031 A::Observable : std::ops::MulAssign<F>, |
| |
1032 GA : SupportGenerator<F, N, SupportType = S, Id = usize> + Clone, |
| |
1033 A : ForwardModel<Loc<F, N>, F, PreadjointCodomain = BTFN<F, GA, BTA, N>> |
| |
1034 + Lipschitz<𝒟, FloatType=F>, |
| |
1035 BTA : BTSearch<F, N, Data=usize, Agg=Bounds<F>>, |
| |
1036 G𝒟 : SupportGenerator<F, N, SupportType = K, Id = usize> + Clone, |
| |
1037 𝒟 : DiscreteMeasureOp<Loc<F, N>, F, PreCodomain = PreBTFN<F, G𝒟, N>>, |
| |
1038 𝒟::Codomain : RealMapping<F, N>, |
| |
1039 S: RealMapping<F, N> + LocalAnalysis<F, Bounds<F>, N>, |
| |
1040 K: RealMapping<F, N> + LocalAnalysis<F, Bounds<F>, N>, |
| |
1041 BTNodeLookup: BTNode<F, usize, Bounds<F>, N>, |
| |
1042 Cube<F, N>: P2Minimise<Loc<F, N>, F>, |
| |
1043 PlotLookup : Plotting<N>, |
| |
1044 DiscreteMeasure<Loc<F, N>, F> : SpikeMerging<F> { |
| |
1045 |
| |
1046 pointsource_fb_reg(opA, b, NonnegRadonRegTerm(α), op𝒟, config, iterator, plotter) |
| |
1047 } |
| |
1048 |
| |
1049 |
| |
1050 #[deprecated(note = "Use `generic_pointsource_fb_reg`")] |
| |
1051 pub fn generic_pointsource_fb<'a, F, I, A, GA, 𝒟, BTA, G𝒟, S, K, Spec, const N : usize>( |
| |
1052 opA : &'a A, |
| |
1053 α : F, |
| |
1054 op𝒟 : &'a 𝒟, |
| |
1055 τ : F, |
| |
1056 config : &FBGenericConfig<F>, |
| |
1057 iterator : I, |
| |
1058 plotter : SeqPlotter<F, N>, |
| |
1059 residual : A::Observable, |
| |
1060 specialisation : Spec, |
| |
1061 ) -> DiscreteMeasure<Loc<F, N>, F> |
| |
1062 where F : Float + ToNalgebraRealField, |
| |
1063 I : AlgIteratorFactory<IterInfo<F, N>>, |
| |
1064 Spec : FBSpecialisation<F, A::Observable, N>, |
| |
1065 A::Observable : std::ops::MulAssign<F>, |
| |
1066 GA : SupportGenerator<F, N, SupportType = S, Id = usize> + Clone, |
| |
1067 A : ForwardModel<Loc<F, N>, F, PreadjointCodomain = BTFN<F, GA, BTA, N>> |
| |
1068 + Lipschitz<𝒟, FloatType=F>, |
| |
1069 BTA : BTSearch<F, N, Data=usize, Agg=Bounds<F>>, |
| |
1070 G𝒟 : SupportGenerator<F, N, SupportType = K, Id = usize> + Clone, |
| |
1071 𝒟 : DiscreteMeasureOp<Loc<F, N>, F, PreCodomain = PreBTFN<F, G𝒟, N>>, |
| |
1072 𝒟::Codomain : RealMapping<F, N>, |
| |
1073 S: RealMapping<F, N> + LocalAnalysis<F, Bounds<F>, N>, |
| |
1074 K: RealMapping<F, N> + LocalAnalysis<F, Bounds<F>, N>, |
| |
1075 BTNodeLookup: BTNode<F, usize, Bounds<F>, N>, |
| |
1076 Cube<F, N>: P2Minimise<Loc<F, N>, F>, |
| |
1077 PlotLookup : Plotting<N>, |
| |
1078 DiscreteMeasure<Loc<F, N>, F> : SpikeMerging<F> { |
| |
1079 |
| |
1080 generic_pointsource_fb_reg(opA, NonnegRadonRegTerm(α), op𝒟, τ, config, iterator, plotter, |
| |
1081 residual, specialisation) |
| |
1082 } |