--- 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`]`<F, N>`, where `F` is the type of floating point numbers, +/// The domain of the function is [`Loc`]`<N, F>`, 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<F: Float, G: SupportGenerator<F, N>, BT /*: BTImpl<F, N>*/, const N: usize> /*where G::SupportType : LocalAnalysis<F, A, N>*/ +pub struct BTFN<F: Float, G: SupportGenerator<N, F>, BT /*: BTImpl< N, F>*/, const N: usize> /*where G::SupportType : LocalAnalysis<F, A, N>*/ { bt: BT, generator: Arc<G>, @@ -39,18 +39,18 @@ impl<F: Float, G, BT, const N: usize> Space for BTFN<F, G, BT, N> where - G: SupportGenerator<F, N, Id = BT::Data>, + G: SupportGenerator<N, F, Id = BT::Data>, G::SupportType: LocalAnalysis<F, BT::Agg, N>, - BT: BTImpl<F, N>, + BT: BTImpl<N, F>, { type Decomp = BasicDecomposition; } impl<F: Float, G, BT, const N: usize> BTFN<F, G, BT, N> where - G: SupportGenerator<F, N, Id = BT::Data>, + G: SupportGenerator<N, F, Id = BT::Data>, G::SupportType: LocalAnalysis<F, BT::Agg, N>, - BT: BTImpl<F, N>, + BT: BTImpl<N, F>, { /// 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<F, N>, depth: BT::Depth, generator: G) -> Self { + pub fn construct(domain: Cube<N, F>, depth: BT::Depth, generator: G) -> Self { Self::construct_arc(domain, depth, Arc::new(generator)) } - fn construct_arc(domain: Cube<F, N>, depth: BT::Depth, generator: Arc<G>) -> Self { + fn construct_arc(domain: Cube<N, F>, depth: BT::Depth, generator: Arc<G>) -> 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<ANew>(self) -> BTFN<F, G, BT::Converted<ANew>, N> where ANew: Aggregator, - G: SupportGenerator<F, N, Id = BT::Data>, + G: SupportGenerator<N, F, Id = BT::Data>, G::SupportType: LocalAnalysis<F, ANew, N>, { BTFN::new_arc(self.bt.convert_aggregator(&*self.generator), self.generator) @@ -130,15 +130,15 @@ impl<F: Float, G, BT, const N: usize> BTFN<F, G, BT, N> where - G: SupportGenerator<F, N>, + G: SupportGenerator<N, F>, { /// 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<BTNew: BTImpl<F, N, Data = G::Id>>( + pub fn instantiate<BTNew: BTImpl<N, F, Data = G::Id>>( self, - domain: Cube<F, N>, + domain: Cube<N, F>, depth: BTNew::Depth, ) -> BTFN<F, G, BTNew, N> where @@ -157,7 +157,7 @@ impl<F: Float, G, const N: usize> PreBTFN<F, G, N> where - G: SupportGenerator<F, N>, + G: SupportGenerator<N, F>, { /// Create a new [`PreBTFN`] with no bisection tree. pub fn new_pre(generator: G) -> Self { @@ -171,14 +171,14 @@ impl<F: Float, G, BT, const N: usize> BTFN<F, G, BT, N> where - G: SupportGenerator<F, N, Id = usize>, + G: SupportGenerator<N, F, Id = usize>, G::SupportType: LocalAnalysis<F, BT::Agg, N>, - BT: BTImpl<F, N, Data = usize>, + BT: BTImpl<N, F, Data = usize>, { /// Helper function for implementing [`std::ops::Add`]. fn add_another<G2>(&self, g2: Arc<G2>) -> BTFN<F, BothGenerators<G, G2>, BT, N> where - G2: SupportGenerator<F, N, Id = usize>, + G2: SupportGenerator<N, F, Id = usize>, G2::SupportType: LocalAnalysis<F, BT::Agg, N>, { let mut bt = self.bt.clone(); @@ -201,9 +201,9 @@ impl<'a, F : Float, G1, G2, BT1, BT2, const N : usize> std::ops::Add<BTFN<F, G2, BT2, N>> for $lhs - where BT1 : BTImpl<F, N, Data=usize>, - G1 : SupportGenerator<F, N, Id=usize> + $($extra_trait)?, - G2 : SupportGenerator<F, N, Id=usize>, + where BT1 : BTImpl< N, F, Data=usize>, + G1 : SupportGenerator< N, F, Id=usize> + $($extra_trait)?, + G2 : SupportGenerator< N, F, Id=usize>, G1::SupportType : LocalAnalysis<F, BT1::Agg, N>, G2::SupportType : LocalAnalysis<F, BT1::Agg, N> { type Output = BTFN<F, BothGenerators<G1, G2>, BT1, N>; @@ -216,9 +216,9 @@ impl<'a, 'b, F : Float, G1, G2, BT1, BT2, const N : usize> std::ops::Add<&'b BTFN<F, G2, BT2, N>> for $lhs - where BT1 : BTImpl<F, N, Data=usize>, - G1 : SupportGenerator<F, N, Id=usize> + $($extra_trait)?, - G2 : SupportGenerator<F, N, Id=usize>, + where BT1 : BTImpl< N, F, Data=usize>, + G1 : SupportGenerator< N, F, Id=usize> + $($extra_trait)?, + G2 : SupportGenerator< N, F, Id=usize>, G1::SupportType : LocalAnalysis<F, BT1::Agg, N>, G2::SupportType : LocalAnalysis<F, BT1::Agg, N> { @@ -239,9 +239,9 @@ impl<'a, F : Float, G1, G2, BT1, BT2, const N : usize> std::ops::Sub<BTFN<F, G2, BT2, N>> for $lhs - where BT1 : BTImpl<F, N, Data=usize>, - G1 : SupportGenerator<F, N, Id=usize> + $($extra_trait)?, - G2 : SupportGenerator<F, N, Id=usize>, + where BT1 : BTImpl< N, F, Data=usize>, + G1 : SupportGenerator< N, F, Id=usize> + $($extra_trait)?, + G2 : SupportGenerator< N, F, Id=usize>, G1::SupportType : LocalAnalysis<F, BT1::Agg, N>, G2::SupportType : LocalAnalysis<F, BT1::Agg, N> { type Output = BTFN<F, BothGenerators<G1, G2>, BT1, N>; @@ -258,9 +258,9 @@ impl<'a, 'b, F : Float, G1, G2, BT1, BT2, const N : usize> std::ops::Sub<&'b BTFN<F, G2, BT2, N>> for $lhs - where BT1 : BTImpl<F, N, Data=usize>, - G1 : SupportGenerator<F, N, Id=usize> + $($extra_trait)?, - G2 : SupportGenerator<F, N, Id=usize> + 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<F, BT1::Agg, N>, G2::SupportType : LocalAnalysis<F, BT1::Agg, N>, &'b G2 : std::ops::Neg<Output=G2> { @@ -281,8 +281,8 @@ ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => { impl<F: Float, G, BT, const N: usize> std::ops::$trait_assign<F> for BTFN<F, G, BT, N> where - BT: BTImpl<F, N>, - G: SupportGenerator<F, N, Id = BT::Data>, + BT: BTImpl<N, F>, + G: SupportGenerator<N, F, Id = BT::Data>, G::SupportType: LocalAnalysis<F, BT::Agg, N>, { #[inline] @@ -294,8 +294,8 @@ impl<F: Float, G, BT, const N: usize> std::ops::$trait<F> for BTFN<F, G, BT, N> where - BT: BTImpl<F, N>, - G: SupportGenerator<F, N, Id = BT::Data>, + BT: BTImpl<N, F>, + G: SupportGenerator<N, F, Id = BT::Data>, G::SupportType: LocalAnalysis<F, BT::Agg, N>, { type Output = Self; @@ -309,8 +309,8 @@ impl<'a, F: Float, G, BT, const N: usize> std::ops::$trait<F> for &'a BTFN<F, G, BT, N> where - BT: BTImpl<F, N>, - G: SupportGenerator<F, N, Id = BT::Data>, + BT: BTImpl<N, F>, + G: SupportGenerator<N, F, Id = BT::Data>, G::SupportType: LocalAnalysis<F, BT::Agg, N>, &'a G: std::ops::$trait<F, Output = G>, { @@ -331,8 +331,8 @@ impl<G, BT, const N : usize> std::ops::$trait<BTFN<$f, G, BT, N>> 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<F: Float, G, BT, const N: usize> std::ops::$trait for BTFN<F, G, BT, N> where - BT: BTImpl<F, N>, - G: SupportGenerator<F, N, Id = BT::Data>, + BT: BTImpl<N, F>, + G: SupportGenerator<N, F, Id = BT::Data>, G::SupportType: LocalAnalysis<F, BT::Agg, N>, { type Output = Self; @@ -387,8 +387,8 @@ /*impl<'a, F : Float, G, BT, const N : usize> std::ops::$trait for &'a BTFN<F, G, BT, N> - 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>, &'a G : std::ops::$trait<Output=G> { type Output = BTFN<F, G, BT, N>; @@ -406,16 +406,16 @@ // Apply, Mapping, Differentiate // -impl<F: Float, G, BT, V, const N: usize> Mapping<Loc<F, N>> for BTFN<F, G, BT, N> +impl<F: Float, G, BT, V, const N: usize> Mapping<Loc<N, F>> for BTFN<F, G, BT, N> where - BT: BTImpl<F, N>, - G: SupportGenerator<F, N, Id = BT::Data>, - G::SupportType: LocalAnalysis<F, BT::Agg, N> + Mapping<Loc<F, N>, Codomain = V>, + BT: BTImpl<N, F>, + G: SupportGenerator<N, F, Id = BT::Data>, + G::SupportType: LocalAnalysis<F, BT::Agg, N> + Mapping<Loc<N, F>, Codomain = V>, V: Sum + Space, { type Codomain = V; - fn apply<I: Instance<Loc<F, N>>>(&self, x: I) -> Self::Codomain { + fn apply<I: Instance<Loc<N, F>>>(&self, x: I) -> Self::Codomain { let xc = x.cow(); self.bt .iter_at(&*xc) @@ -424,17 +424,17 @@ } } -impl<F: Float, G, BT, V, const N: usize> DifferentiableImpl<Loc<F, N>> for BTFN<F, G, BT, N> +impl<F: Float, G, BT, V, const N: usize> DifferentiableImpl<Loc<N, F>> for BTFN<F, G, BT, N> where - BT: BTImpl<F, N>, - G: SupportGenerator<F, N, Id = BT::Data>, + BT: BTImpl<N, F>, + G: SupportGenerator<N, F, Id = BT::Data>, G::SupportType: - LocalAnalysis<F, BT::Agg, N> + DifferentiableMapping<Loc<F, N>, DerivativeDomain = V>, + LocalAnalysis<F, BT::Agg, N> + DifferentiableMapping<Loc<N, F>, DerivativeDomain = V>, V: Sum + Space, { type Derivative = V; - fn differential_impl<I: Instance<Loc<F, N>>>(&self, x: I) -> Self::Derivative { + fn differential_impl<I: Instance<Loc<N, F>>>(&self, x: I) -> Self::Derivative { let xc = x.cow(); self.bt .iter_at(&*xc) @@ -449,8 +449,8 @@ impl<F: Float, G, BT, const N: usize> GlobalAnalysis<F, BT::Agg> for BTFN<F, G, BT, N> where - BT: BTImpl<F, N>, - G: SupportGenerator<F, N, Id = BT::Data>, + BT: BTImpl<N, F>, + G: SupportGenerator<N, F, Id = BT::Data>, G::SupportType: LocalAnalysis<F, BT::Agg, N>, { #[inline] @@ -467,8 +467,8 @@ /* impl<'b, X, F : Float, G, BT, const N : usize> Apply<&'b X, F> for BTFN<F, G, BT, N> -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>, X : for<'a> Apply<&'a BTFN<F, G, BT, N>, F> { @@ -480,8 +480,8 @@ impl<X, F : Float, G, BT, const N : usize> Apply<X, F> for BTFN<F, G, BT, N> -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>, X : for<'a> Apply<&'a BTFN<F, G, BT, N>, F> { @@ -493,8 +493,8 @@ impl<X, F : Float, G, BT, const N : usize> Linear<X> for BTFN<F, G, BT, N> -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>, X : for<'a> Apply<&'a BTFN<F, G, BT, N>, F> { type Codomain = F; @@ -512,16 +512,16 @@ fn p2_minimise<G: Fn(&U) -> F>(&self, g: G) -> (U, F); } -impl<F: Float> P2Minimise<Loc<F, 1>, F> for Cube<F, 1> { - fn p2_minimise<G: Fn(&Loc<F, 1>) -> F>(&self, g: G) -> (Loc<F, 1>, F) { +impl<F: Float> P2Minimise<Loc<1, F>, F> for Cube<1, F> { + fn p2_minimise<G: Fn(&Loc<1, F>) -> 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<F: Float> P2Minimise<Loc<F, 2>, F> for Cube<F, 2> { - fn p2_minimise<G: Fn(&Loc<F, 2>) -> F>(&self, g: G) -> (Loc<F, 2>, F) { +impl<F: Float> P2Minimise<Loc<2, F>, F> for Cube<2, F> { + fn p2_minimise<G: Fn(&Loc<2, F>) -> 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<F: Float, G, const N: usize> Refiner<F, Bounds<F>, G, N> for P2Refiner<F, RefineMax> where - Cube<F, N>: P2Minimise<Loc<F, N>, F>, - G: SupportGenerator<F, N>, - G::SupportType: Mapping<Loc<F, N>, Codomain = F> + LocalAnalysis<F, Bounds<F>, N>, + Cube<N, F>: P2Minimise<Loc<N, F>, F>, + G: SupportGenerator<N, F>, + G::SupportType: Mapping<Loc<N, F>, Codomain = F> + LocalAnalysis<F, Bounds<F>, N>, { - type Result = Option<(Loc<F, N>, F)>; + type Result = Option<(Loc<N, F>, F)>; type Sorting = UpperBoundSorting<F>; fn refine( &self, aggregator: &Bounds<F>, - cube: &Cube<F, N>, + cube: &Cube<N, F>, 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<F, N>| { + let g = move |x: &Loc<N, F>| { let f = move |&d| generator.support_for(d).apply(x); -data.iter().map(f).sum::<F>() }; @@ -669,17 +669,17 @@ impl<F: Float, G, const N: usize> Refiner<F, Bounds<F>, G, N> for P2Refiner<F, RefineMin> where - Cube<F, N>: P2Minimise<Loc<F, N>, F>, - G: SupportGenerator<F, N>, - G::SupportType: Mapping<Loc<F, N>, Codomain = F> + LocalAnalysis<F, Bounds<F>, N>, + Cube<N, F>: P2Minimise<Loc<N, F>, F>, + G: SupportGenerator<N, F>, + G::SupportType: Mapping<Loc<N, F>, Codomain = F> + LocalAnalysis<F, Bounds<F>, N>, { - type Result = Option<(Loc<F, N>, F)>; + type Result = Option<(Loc<N, F>, F)>; type Sorting = LowerBoundSorting<F>; fn refine( &self, aggregator: &Bounds<F>, - cube: &Cube<F, N>, + cube: &Cube<N, F>, 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<F, N>| { + let g = move |x: &Loc<N, F>| { let f = move |&d| generator.support_for(d).apply(x); data.iter().map(f).sum::<F>() }; @@ -755,7 +755,7 @@ impl<F: Float, G, const N: usize> Refiner<F, Bounds<F>, G, N> for BoundRefiner<F, RefineMax> where - G: SupportGenerator<F, N>, + G: SupportGenerator<N, F>, { type Result = bool; type Sorting = UpperBoundSorting<F>; @@ -763,7 +763,7 @@ fn refine( &self, aggregator: &Bounds<F>, - _cube: &Cube<F, N>, + _cube: &Cube<N, F>, _data: &[G::Id], _generator: &G, step: usize, @@ -790,7 +790,7 @@ impl<F: Float, G, const N: usize> Refiner<F, Bounds<F>, G, N> for BoundRefiner<F, RefineMin> where - G: SupportGenerator<F, N>, + G: SupportGenerator<N, F>, { type Result = bool; type Sorting = UpperBoundSorting<F>; @@ -798,7 +798,7 @@ fn refine( &self, aggregator: &Bounds<F>, - _cube: &Cube<F, N>, + _cube: &Cube<N, F>, _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<F: Float, G, BT, const N: usize> MinMaxMapping<F, N> for BTFN<F, G, BT, N> +impl<F: Float, G, BT, const N: usize> MinMaxMapping<N, F> for BTFN<F, G, BT, N> where - BT: BTSearch<F, N, Agg = Bounds<F>>, - G: SupportGenerator<F, N, Id = BT::Data>, - G::SupportType: Mapping<Loc<F, N>, Codomain = F> + LocalAnalysis<F, Bounds<F>, N>, - Cube<F, N>: P2Minimise<Loc<F, N>, F>, + BT: BTSearch<N, F, Agg = Bounds<F>>, + G: SupportGenerator<N, F, Id = BT::Data>, + G::SupportType: Mapping<Loc<N, F>, Codomain = F> + LocalAnalysis<F, Bounds<F>, N>, + Cube<N, F>: P2Minimise<Loc<N, F>, F>, { - fn maximise(&mut self, tolerance: F, max_steps: usize) -> (Loc<F, N>, F) { + fn maximise(&mut self, tolerance: F, max_steps: usize) -> (Loc<N, F>, F) { let refiner = P2Refiner { tolerance, max_steps, @@ -863,7 +863,7 @@ bound: F, tolerance: F, max_steps: usize, - ) -> Option<(Loc<F, N>, F)> { + ) -> Option<(Loc<N, F>, 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, N>, F) { + fn minimise(&mut self, tolerance: F, max_steps: usize) -> (Loc<N, F>, F) { let refiner = P2Refiner { tolerance, max_steps, @@ -893,7 +893,7 @@ bound: F, tolerance: F, max_steps: usize, - ) -> Option<(Loc<F, N>, F)> { + ) -> Option<(Loc<N, F>, F)> { let refiner = P2Refiner { tolerance, max_steps,