diff -r 495448cca603 -r 6aa955ad8122 src/bisection_tree/btfn.rs --- a/src/bisection_tree/btfn.rs Thu May 01 08:40:33 2025 -0500 +++ b/src/bisection_tree/btfn.rs Thu May 01 13:06:58 2025 -0500 @@ -22,7 +22,7 @@ /// Presentation for (mathematical) functions constructed as a sum of components functions with /// typically small support. /// -/// The domain of the function is [`Loc`]``, where `F` is the type of floating point numbers, +/// The domain of the function is [`Loc`]``, where `F` is the type of floating point numbers, /// and `N` the dimension. /// /// The `generator` lists the component functions that have to implement [`Support`]. @@ -30,7 +30,7 @@ /// in a [bisection tree][BTImpl], when one is provided as `bt`. However `bt` may also be `()` /// for a [`PreBTFN`] that is only useful for vector space operations with a full [`BTFN`]. #[derive(Clone, Debug)] -pub struct BTFN, BT /*: BTImpl*/, const N: usize> /*where G::SupportType : LocalAnalysis*/ +pub struct BTFN, BT /*: BTImpl< N, F>*/, const N: usize> /*where G::SupportType : LocalAnalysis*/ { bt: BT, generator: Arc, @@ -39,18 +39,18 @@ impl Space for BTFN where - G: SupportGenerator, + G: SupportGenerator, G::SupportType: LocalAnalysis, - BT: BTImpl, + BT: BTImpl, { type Decomp = BasicDecomposition; } impl BTFN where - G: SupportGenerator, + G: SupportGenerator, G::SupportType: LocalAnalysis, - BT: BTImpl, + BT: BTImpl, { /// Create a new BTFN from a support generator and a pre-initialised bisection tree. /// @@ -92,11 +92,11 @@ /// The top node of the created [`BT`] will have the given `domain`. /// /// See the documentation for [`BTFN`] on the role of the `generator`. - pub fn construct(domain: Cube, depth: BT::Depth, generator: G) -> Self { + pub fn construct(domain: Cube, depth: BT::Depth, generator: G) -> Self { Self::construct_arc(domain, depth, Arc::new(generator)) } - fn construct_arc(domain: Cube, depth: BT::Depth, generator: Arc) -> Self { + fn construct_arc(domain: Cube, depth: BT::Depth, generator: Arc) -> Self { let mut bt = BT::new(domain, depth); for (d, support) in generator.all_data() { bt.insert(d, &support); @@ -111,7 +111,7 @@ pub fn convert_aggregator(self) -> BTFN, N> where ANew: Aggregator, - G: SupportGenerator, + G: SupportGenerator, G::SupportType: LocalAnalysis, { BTFN::new_arc(self.bt.convert_aggregator(&*self.generator), self.generator) @@ -130,15 +130,15 @@ impl BTFN where - G: SupportGenerator, + G: SupportGenerator, { /// Change the [bisection tree][BTImpl] of the [`BTFN`] to a different one. /// /// This can be used to convert a [`PreBTFN`] to a full [`BTFN`], or the change /// the aggreagator; see also [`self.convert_aggregator`]. - pub fn instantiate>( + pub fn instantiate>( self, - domain: Cube, + domain: Cube, depth: BTNew::Depth, ) -> BTFN where @@ -157,7 +157,7 @@ impl PreBTFN where - G: SupportGenerator, + G: SupportGenerator, { /// Create a new [`PreBTFN`] with no bisection tree. pub fn new_pre(generator: G) -> Self { @@ -171,14 +171,14 @@ impl BTFN where - G: SupportGenerator, + G: SupportGenerator, G::SupportType: LocalAnalysis, - BT: BTImpl, + BT: BTImpl, { /// Helper function for implementing [`std::ops::Add`]. fn add_another(&self, g2: Arc) -> BTFN, BT, N> where - G2: SupportGenerator, + G2: SupportGenerator, G2::SupportType: LocalAnalysis, { let mut bt = self.bt.clone(); @@ -201,9 +201,9 @@ impl<'a, F : Float, G1, G2, BT1, BT2, const N : usize> std::ops::Add> for $lhs - where BT1 : BTImpl, - G1 : SupportGenerator + $($extra_trait)?, - G2 : SupportGenerator, + where BT1 : BTImpl< N, F, Data=usize>, + G1 : SupportGenerator< N, F, Id=usize> + $($extra_trait)?, + G2 : SupportGenerator< N, F, Id=usize>, G1::SupportType : LocalAnalysis, G2::SupportType : LocalAnalysis { type Output = BTFN, BT1, N>; @@ -216,9 +216,9 @@ impl<'a, 'b, F : Float, G1, G2, BT1, BT2, const N : usize> std::ops::Add<&'b BTFN> for $lhs - where BT1 : BTImpl, - G1 : SupportGenerator + $($extra_trait)?, - G2 : SupportGenerator, + where BT1 : BTImpl< N, F, Data=usize>, + G1 : SupportGenerator< N, F, Id=usize> + $($extra_trait)?, + G2 : SupportGenerator< N, F, Id=usize>, G1::SupportType : LocalAnalysis, G2::SupportType : LocalAnalysis { @@ -239,9 +239,9 @@ impl<'a, F : Float, G1, G2, BT1, BT2, const N : usize> std::ops::Sub> for $lhs - where BT1 : BTImpl, - G1 : SupportGenerator + $($extra_trait)?, - G2 : SupportGenerator, + where BT1 : BTImpl< N, F, Data=usize>, + G1 : SupportGenerator< N, F, Id=usize> + $($extra_trait)?, + G2 : SupportGenerator< N, F, Id=usize>, G1::SupportType : LocalAnalysis, G2::SupportType : LocalAnalysis { type Output = BTFN, BT1, N>; @@ -258,9 +258,9 @@ impl<'a, 'b, F : Float, G1, G2, BT1, BT2, const N : usize> std::ops::Sub<&'b BTFN> for $lhs - where BT1 : BTImpl, - G1 : SupportGenerator + $($extra_trait)?, - G2 : SupportGenerator + Clone, + where BT1 : BTImpl< N, F, Data=usize>, + G1 : SupportGenerator< N, F, Id=usize> + $($extra_trait)?, + G2 : SupportGenerator< N, F, Id=usize> + Clone, G1::SupportType : LocalAnalysis, G2::SupportType : LocalAnalysis, &'b G2 : std::ops::Neg { @@ -281,8 +281,8 @@ ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => { impl std::ops::$trait_assign for BTFN where - BT: BTImpl, - G: SupportGenerator, + BT: BTImpl, + G: SupportGenerator, G::SupportType: LocalAnalysis, { #[inline] @@ -294,8 +294,8 @@ impl std::ops::$trait for BTFN where - BT: BTImpl, - G: SupportGenerator, + BT: BTImpl, + G: SupportGenerator, G::SupportType: LocalAnalysis, { type Output = Self; @@ -309,8 +309,8 @@ impl<'a, F: Float, G, BT, const N: usize> std::ops::$trait for &'a BTFN where - BT: BTImpl, - G: SupportGenerator, + BT: BTImpl, + G: SupportGenerator, G::SupportType: LocalAnalysis, &'a G: std::ops::$trait, { @@ -331,8 +331,8 @@ impl std::ops::$trait> for $f - where BT : BTImpl<$f, N>, - G : SupportGenerator<$f, N, Id=BT::Data>, + where BT : BTImpl< N, $f>, + G : SupportGenerator< N, $f, Id=BT::Data>, G::SupportType : LocalAnalysis<$f, BT::Agg, N> { type Output = BTFN<$f, G, BT, N>; #[inline] @@ -346,8 +346,8 @@ impl<'a, G, BT, const N : usize> std::ops::$trait<&'a BTFN<$f, G, BT, N>> for $f - where BT : BTImpl<$f, N>, - G : SupportGenerator<$f, N, Id=BT::Data> + Clone, + where BT : BTImpl< N, $f>, + G : SupportGenerator< N, $f, Id=BT::Data> + Clone, G::SupportType : LocalAnalysis<$f, BT::Agg, N>, // FIXME: This causes compiler overflow /*&'a G : std::ops::$trait<$f,Output=G>*/ { @@ -371,8 +371,8 @@ ($trait:ident, $fn:ident) => { impl std::ops::$trait for BTFN where - BT: BTImpl, - G: SupportGenerator, + BT: BTImpl, + G: SupportGenerator, G::SupportType: LocalAnalysis, { type Output = Self; @@ -387,8 +387,8 @@ /*impl<'a, F : Float, G, BT, const N : usize> std::ops::$trait for &'a BTFN - where BT : BTImpl, - G : SupportGenerator, + where BT : BTImpl< N, F>, + G : SupportGenerator< N, F, Id=BT::Data>, G::SupportType : LocalAnalysis, &'a G : std::ops::$trait { type Output = BTFN; @@ -406,16 +406,16 @@ // Apply, Mapping, Differentiate // -impl Mapping> for BTFN +impl Mapping> for BTFN where - BT: BTImpl, - G: SupportGenerator, - G::SupportType: LocalAnalysis + Mapping, Codomain = V>, + BT: BTImpl, + G: SupportGenerator, + G::SupportType: LocalAnalysis + Mapping, Codomain = V>, V: Sum + Space, { type Codomain = V; - fn apply>>(&self, x: I) -> Self::Codomain { + fn apply>>(&self, x: I) -> Self::Codomain { let xc = x.cow(); self.bt .iter_at(&*xc) @@ -424,17 +424,17 @@ } } -impl DifferentiableImpl> for BTFN +impl DifferentiableImpl> for BTFN where - BT: BTImpl, - G: SupportGenerator, + BT: BTImpl, + G: SupportGenerator, G::SupportType: - LocalAnalysis + DifferentiableMapping, DerivativeDomain = V>, + LocalAnalysis + DifferentiableMapping, DerivativeDomain = V>, V: Sum + Space, { type Derivative = V; - fn differential_impl>>(&self, x: I) -> Self::Derivative { + fn differential_impl>>(&self, x: I) -> Self::Derivative { let xc = x.cow(); self.bt .iter_at(&*xc) @@ -449,8 +449,8 @@ impl GlobalAnalysis for BTFN where - BT: BTImpl, - G: SupportGenerator, + BT: BTImpl, + G: SupportGenerator, G::SupportType: LocalAnalysis, { #[inline] @@ -467,8 +467,8 @@ /* impl<'b, X, F : Float, G, BT, const N : usize> Apply<&'b X, F> for BTFN -where BT : BTImpl, - G : SupportGenerator, +where BT : BTImpl< N, F>, + G : SupportGenerator< N, F, Id=BT::Data>, G::SupportType : LocalAnalysis, X : for<'a> Apply<&'a BTFN, F> { @@ -480,8 +480,8 @@ impl Apply for BTFN -where BT : BTImpl, - G : SupportGenerator, +where BT : BTImpl< N, F>, + G : SupportGenerator< N, F, Id=BT::Data>, G::SupportType : LocalAnalysis, X : for<'a> Apply<&'a BTFN, F> { @@ -493,8 +493,8 @@ impl Linear for BTFN -where BT : BTImpl, - G : SupportGenerator, +where BT : BTImpl< N, F>, + G : SupportGenerator< N, F, Id=BT::Data>, G::SupportType : LocalAnalysis, X : for<'a> Apply<&'a BTFN, F> { type Codomain = F; @@ -512,16 +512,16 @@ fn p2_minimise F>(&self, g: G) -> (U, F); } -impl P2Minimise, F> for Cube { - fn p2_minimise) -> F>(&self, g: G) -> (Loc, F) { +impl P2Minimise, F> for Cube<1, F> { + fn p2_minimise) -> F>(&self, g: G) -> (Loc<1, F>, F) { let interval = Simplex(self.corners()); interval.p2_model(&g).minimise(&interval) } } #[replace_float_literals(F::cast_from(literal))] -impl P2Minimise, F> for Cube { - fn p2_minimise) -> F>(&self, g: G) -> (Loc, F) { +impl P2Minimise, F> for Cube<2, F> { + fn p2_minimise) -> F>(&self, g: G) -> (Loc<2, F>, F) { if false { // Split into two triangle (simplex) with separate P2 model in each. // The six nodes of each triangle are the corners and the edges. @@ -606,17 +606,17 @@ impl Refiner, G, N> for P2Refiner where - Cube: P2Minimise, F>, - G: SupportGenerator, - G::SupportType: Mapping, Codomain = F> + LocalAnalysis, N>, + Cube: P2Minimise, F>, + G: SupportGenerator, + G::SupportType: Mapping, Codomain = F> + LocalAnalysis, N>, { - type Result = Option<(Loc, F)>; + type Result = Option<(Loc, F)>; type Sorting = UpperBoundSorting; fn refine( &self, aggregator: &Bounds, - cube: &Cube, + cube: &Cube, data: &[G::Id], generator: &G, step: usize, @@ -630,7 +630,7 @@ } // g gives the negative of the value of the function presented by `data` and `generator`. - let g = move |x: &Loc| { + let g = move |x: &Loc| { let f = move |&d| generator.support_for(d).apply(x); -data.iter().map(f).sum::() }; @@ -669,17 +669,17 @@ impl Refiner, G, N> for P2Refiner where - Cube: P2Minimise, F>, - G: SupportGenerator, - G::SupportType: Mapping, Codomain = F> + LocalAnalysis, N>, + Cube: P2Minimise, F>, + G: SupportGenerator, + G::SupportType: Mapping, Codomain = F> + LocalAnalysis, N>, { - type Result = Option<(Loc, F)>; + type Result = Option<(Loc, F)>; type Sorting = LowerBoundSorting; fn refine( &self, aggregator: &Bounds, - cube: &Cube, + cube: &Cube, data: &[G::Id], generator: &G, step: usize, @@ -693,7 +693,7 @@ } // g gives the value of the function presented by `data` and `generator`. - let g = move |x: &Loc| { + let g = move |x: &Loc| { let f = move |&d| generator.support_for(d).apply(x); data.iter().map(f).sum::() }; @@ -755,7 +755,7 @@ impl Refiner, G, N> for BoundRefiner where - G: SupportGenerator, + G: SupportGenerator, { type Result = bool; type Sorting = UpperBoundSorting; @@ -763,7 +763,7 @@ fn refine( &self, aggregator: &Bounds, - _cube: &Cube, + _cube: &Cube, _data: &[G::Id], _generator: &G, step: usize, @@ -790,7 +790,7 @@ impl Refiner, G, N> for BoundRefiner where - G: SupportGenerator, + G: SupportGenerator, { type Result = bool; type Sorting = UpperBoundSorting; @@ -798,7 +798,7 @@ fn refine( &self, aggregator: &Bounds, - _cube: &Cube, + _cube: &Cube, _data: &[G::Id], _generator: &G, step: usize, @@ -838,14 +838,14 @@ // there should be a result, or new nodes above the `glb` inserted into the queue. Then the waiting // threads can also continue processing. If, however, numerical inaccuracy destroyes the `glb`, // the queue may run out, and we get “Refiner failure”. -impl MinMaxMapping for BTFN +impl MinMaxMapping for BTFN where - BT: BTSearch>, - G: SupportGenerator, - G::SupportType: Mapping, Codomain = F> + LocalAnalysis, N>, - Cube: P2Minimise, F>, + BT: BTSearch>, + G: SupportGenerator, + G::SupportType: Mapping, Codomain = F> + LocalAnalysis, N>, + Cube: P2Minimise, F>, { - fn maximise(&mut self, tolerance: F, max_steps: usize) -> (Loc, F) { + fn maximise(&mut self, tolerance: F, max_steps: usize) -> (Loc, F) { let refiner = P2Refiner { tolerance, max_steps, @@ -863,7 +863,7 @@ bound: F, tolerance: F, max_steps: usize, - ) -> Option<(Loc, F)> { + ) -> Option<(Loc, F)> { let refiner = P2Refiner { tolerance, max_steps, @@ -875,7 +875,7 @@ .expect("Refiner failure.") } - fn minimise(&mut self, tolerance: F, max_steps: usize) -> (Loc, F) { + fn minimise(&mut self, tolerance: F, max_steps: usize) -> (Loc, F) { let refiner = P2Refiner { tolerance, max_steps, @@ -893,7 +893,7 @@ bound: F, tolerance: F, max_steps: usize, - ) -> Option<(Loc, F)> { + ) -> Option<(Loc, F)> { let refiner = P2Refiner { tolerance, max_steps,