src/bisection_tree/bt.rs

branch
dev
changeset 81
d2acaaddd9af
parent 9
f40dfaf2166d
equal deleted inserted replaced
49:edb95d2b83cc 81:d2acaaddd9af
241 A : Aggregator, 241 A : Aggregator,
242 D : 'static + Copy + Send + Sync { 242 D : 'static + Copy + Send + Sync {
243 243
244 /// Creates a new node branching structure, subdividing `domain` based on the 244 /// Creates a new node branching structure, subdividing `domain` based on the
245 /// [hint][Support::support_hint] of `support`. 245 /// [hint][Support::support_hint] of `support`.
246 pub(super) fn new_with<S : LocalAnalysis <F, A, N>>( 246 pub(super) fn new_with<S>(
247 domain : &Cube<F,N>, 247 domain : &Cube<F,N>,
248 support : &S 248 support : &S
249 ) -> Self { 249 ) -> Self
250 where S : Support<N, RealField=F> + LocalAnalysis<A, Cube<F, N>> {
250 let hint = support.bisection_hint(domain); 251 let hint = support.bisection_hint(domain);
251 let branch_at = map2(&hint, domain, |h, r| { 252 let branch_at = map2(&hint, domain, |h, r| {
252 h.unwrap_or_else(|| (r[0]+r[1])/F::TWO).max(r[0]).min(r[1]) 253 h.unwrap_or_else(|| (r[0]+r[1])/F::TWO).max(r[0]).min(r[1])
253 }).into(); 254 }).into();
254 Branches{ 255 Branches{
319 /// * `d` is the data to be inserted 320 /// * `d` is the data to be inserted
320 /// * `new_leaf_depth` is the depth relative to `self` at which the data is to be inserted. 321 /// * `new_leaf_depth` is the depth relative to `self` at which the data is to be inserted.
321 /// * `support` is the [`Support`] that is used determine with which subcubes of `domain` 322 /// * `support` is the [`Support`] that is used determine with which subcubes of `domain`
322 /// (at subdivision depth `new_leaf_depth`) the data `d` is to be associated with. 323 /// (at subdivision depth `new_leaf_depth`) the data `d` is to be associated with.
323 /// 324 ///
324 pub(super) fn insert<'refs, 'scope, M : Depth, S : LocalAnalysis<F, A, N>>( 325 pub(super) fn insert<'refs, 'scope, M : Depth, S>(
325 &mut self, 326 &mut self,
326 domain : &Cube<F,N>, 327 domain : &Cube<F,N>,
327 d : D, 328 d : D,
328 new_leaf_depth : M, 329 new_leaf_depth : M,
329 support : &S, 330 support : &S,
330 task_budget : TaskBudget<'scope, 'refs>, 331 task_budget : TaskBudget<'scope, 'refs>,
331 ) { 332 )
333 where S : Support<N, RealField=F> + LocalAnalysis<A, Cube<F, N>> {
332 let support_hint = support.support_hint(); 334 let support_hint = support.support_hint();
333 self.recurse(domain, task_budget, 335 self.recurse(domain, task_budget,
334 |_, subcube| support_hint.intersects(&subcube), 336 |_, subcube| support_hint.intersects(&subcube),
335 move |node, subcube, new_budget| node.insert(subcube, d, new_leaf_depth, support, 337 move |node, subcube, new_budget| node.insert(subcube, d, new_leaf_depth, support,
336 new_budget)); 338 new_budget));
346 self, 348 self,
347 generator : &G, 349 generator : &G,
348 domain : &Cube<F, N> 350 domain : &Cube<F, N>
349 ) -> Branches<F,D,ANew,N,P> 351 ) -> Branches<F,D,ANew,N,P>
350 where ANew : Aggregator, 352 where ANew : Aggregator,
351 G : SupportGenerator<F, N, Id=D>, 353 G : SupportGenerator<N, Id=D, RealField = F>,
352 G::SupportType : LocalAnalysis<F, ANew, N> { 354 G::SupportType : LocalAnalysis<ANew, Cube<F, N>> {
353 let branch_at = self.branch_at; 355 let branch_at = self.branch_at;
354 let subcube_iter = self.iter_subcubes(domain); 356 let subcube_iter = self.iter_subcubes(domain);
355 let new_nodes = self.nodes.into_iter().zip(subcube_iter).map(|(node, subcube)| { 357 let new_nodes = self.nodes.into_iter().zip(subcube_iter).map(|(node, subcube)| {
356 Node::convert_aggregator(node, generator, &subcube) 358 Node::convert_aggregator(node, generator, &subcube)
357 }); 359 });
368 pub(super) fn refresh_aggregator<'refs, 'scope, G>( 370 pub(super) fn refresh_aggregator<'refs, 'scope, G>(
369 &mut self, 371 &mut self,
370 generator : &G, 372 generator : &G,
371 domain : &Cube<F, N>, 373 domain : &Cube<F, N>,
372 task_budget : TaskBudget<'scope, 'refs>, 374 task_budget : TaskBudget<'scope, 'refs>,
373 ) where G : SupportGenerator<F, N, Id=D>, 375 ) where G : SupportGenerator<N, Id=D, RealField = F>,
374 G::SupportType : LocalAnalysis<F, A, N> { 376 G::SupportType : LocalAnalysis<A, Cube<F, N>> {
375 self.recurse(domain, task_budget, 377 self.recurse(domain, task_budget,
376 |_, _| true, 378 |_, _| true,
377 move |node, subcube, new_budget| node.refresh_aggregator(generator, subcube, 379 move |node, subcube, new_budget| node.refresh_aggregator(generator, subcube,
378 new_budget)); 380 new_budget));
379 } 381 }
432 /// 434 ///
433 /// If `self` is already [`NodeOption::Leaf`], the data is inserted directly in this node. 435 /// If `self` is already [`NodeOption::Leaf`], the data is inserted directly in this node.
434 /// If `self` is a [`NodeOption::Branches`], the data is passed to branches whose subcubes 436 /// If `self` is a [`NodeOption::Branches`], the data is passed to branches whose subcubes
435 /// `support` intersects. If an [`NodeOption::Uninitialised`] node is encountered, a new leaf is 437 /// `support` intersects. If an [`NodeOption::Uninitialised`] node is encountered, a new leaf is
436 /// created at a minimum depth of `new_leaf_depth`. 438 /// created at a minimum depth of `new_leaf_depth`.
437 pub(super) fn insert<'refs, 'scope, M : Depth, S : LocalAnalysis <F, A, N>>( 439 pub(super) fn insert<'refs, 'scope, M : Depth, S>(
438 &mut self, 440 &mut self,
439 domain : &Cube<F,N>, 441 domain : &Cube<F,N>,
440 d : D, 442 d : D,
441 new_leaf_depth : M, 443 new_leaf_depth : M,
442 support : &S, 444 support : &S,
443 task_budget : TaskBudget<'scope, 'refs>, 445 task_budget : TaskBudget<'scope, 'refs>,
444 ) { 446 )
447 where S : Support<N, RealField = F> + LocalAnalysis<A, Cube<F, N>> {
445 match &mut self.data { 448 match &mut self.data {
446 NodeOption::Uninitialised => { 449 NodeOption::Uninitialised => {
447 // Replace uninitialised node with a leaf or a branch 450 // Replace uninitialised node with a leaf or a branch
448 self.data = match new_leaf_depth.lower() { 451 self.data = match new_leaf_depth.lower() {
449 None => { 452 None => {
491 mut self, 494 mut self,
492 generator : &G, 495 generator : &G,
493 domain : &Cube<F, N> 496 domain : &Cube<F, N>
494 ) -> Node<F,D,ANew,N,P> 497 ) -> Node<F,D,ANew,N,P>
495 where ANew : Aggregator, 498 where ANew : Aggregator,
496 G : SupportGenerator<F, N, Id=D>, 499 G : SupportGenerator<N, Id=D, RealField = F>,
497 G::SupportType : LocalAnalysis<F, ANew, N> { 500 G::SupportType : LocalAnalysis<ANew, Cube<F, N>> {
498 501
499 // The mem::replace is needed due to the [`Drop`] implementation to extract self.data. 502 // The mem::replace is needed due to the [`Drop`] implementation to extract self.data.
500 match std::mem::replace(&mut self.data, NodeOption::Uninitialised) { 503 match std::mem::replace(&mut self.data, NodeOption::Uninitialised) {
501 NodeOption::Uninitialised => Node { 504 NodeOption::Uninitialised => Node {
502 data : NodeOption::Uninitialised, 505 data : NodeOption::Uninitialised,
535 pub(super) fn refresh_aggregator<'refs, 'scope, G>( 538 pub(super) fn refresh_aggregator<'refs, 'scope, G>(
536 &mut self, 539 &mut self,
537 generator : &G, 540 generator : &G,
538 domain : &Cube<F, N>, 541 domain : &Cube<F, N>,
539 task_budget : TaskBudget<'scope, 'refs>, 542 task_budget : TaskBudget<'scope, 'refs>,
540 ) where G : SupportGenerator<F, N, Id=D>, 543 ) where G : SupportGenerator<N, Id=D, RealField = F>,
541 G::SupportType : LocalAnalysis<F, A, N> { 544 G::SupportType : LocalAnalysis<A, Cube<F, N>> {
542 match &mut self.data { 545 match &mut self.data {
543 NodeOption::Uninitialised => { }, 546 NodeOption::Uninitialised => { },
544 NodeOption::Leaf(v) => { 547 NodeOption::Leaf(v) => {
545 self.aggregator = A::new(); 548 self.aggregator = A::new();
546 self.aggregator.aggregate(v.iter().map(|d| { 549 self.aggregator.aggregate(v.iter().map(|d| {
578 pub struct BTNodeLookup; 581 pub struct BTNodeLookup;
579 582
580 /// Basic interface to a [`BT`] bisection tree. 583 /// Basic interface to a [`BT`] bisection tree.
581 /// 584 ///
582 /// Further routines are provided by the [`BTSearch`][super::refine::BTSearch] trait. 585 /// Further routines are provided by the [`BTSearch`][super::refine::BTSearch] trait.
583 pub trait BTImpl<F : Float, const N : usize> : std::fmt::Debug + Clone + GlobalAnalysis<F, Self::Agg> { 586 pub trait BTImpl<F : Float, const N : usize> : std::fmt::Debug + Clone + GlobalAnalysis<Self::Agg> {
584 /// The data type stored in the tree 587 /// The data type stored in the tree
585 type Data : 'static + Copy + Send + Sync; 588 type Data : 'static + Copy + Send + Sync;
586 /// The depth type of the tree 589 /// The depth type of the tree
587 type Depth : Depth; 590 type Depth : Depth;
588 /// The type for the [aggregate information][Aggregator] about the `Data` stored in each node 591 /// The type for the [aggregate information][Aggregator] about the `Data` stored in each node
593 596
594 /// Insert the data `d` into the tree for `support`. 597 /// Insert the data `d` into the tree for `support`.
595 /// 598 ///
596 /// Every leaf node of the tree that intersects the `support` will contain a copy of 599 /// Every leaf node of the tree that intersects the `support` will contain a copy of
597 /// `d`. 600 /// `d`.
598 fn insert<S : LocalAnalysis<F, Self::Agg, N>>( 601 fn insert<S>(
599 &mut self, 602 &mut self,
600 d : Self::Data, 603 d : Self::Data,
601 support : &S 604 support : &S
602 ); 605 )
606 where S: Support<N, RealField=F> + LocalAnalysis<Self::Agg, Cube<F, N>>;
603 607
604 /// Construct a new instance of the tree for a different aggregator 608 /// Construct a new instance of the tree for a different aggregator
605 /// 609 ///
606 /// The `generator` is used to convert the data of type [`Self::Data`] contained in the tree 610 /// The `generator` is used to convert the data of type [`Self::Data`] contained in the tree
607 /// into corresponding [`Support`]s. 611 /// into corresponding [`Support`]s.
608 fn convert_aggregator<ANew, G>(self, generator : &G) 612 fn convert_aggregator<ANew, G>(self, generator : &G)
609 -> Self::Converted<ANew> 613 -> Self::Converted<ANew>
610 where ANew : Aggregator, 614 where ANew : Aggregator,
611 G : SupportGenerator<F, N, Id=Self::Data>, 615 G : SupportGenerator< N, Id=Self::Data, RealField = F>,
612 G::SupportType : LocalAnalysis<F, ANew, N>; 616 G::SupportType : LocalAnalysis<ANew, Cube<F, N>>;
613 617
614 618
615 /// Refreshes the aggregator of the three after possible changes to the support generator. 619 /// Refreshes the aggregator of the three after possible changes to the support generator.
616 /// 620 ///
617 /// The `generator` is used to convert the data of type [`Self::Data`] contained in the tree 621 /// The `generator` is used to convert the data of type [`Self::Data`] contained in the tree
618 /// into corresponding [`Support`]s. 622 /// into corresponding [`Support`]s.
619 fn refresh_aggregator<G>(&mut self, generator : &G) 623 fn refresh_aggregator<G>(&mut self, generator : &G)
620 where G : SupportGenerator<F, N, Id=Self::Data>, 624 where G : SupportGenerator<N, Id=Self::Data, RealField = F>,
621 G::SupportType : LocalAnalysis<F, Self::Agg, N>; 625 G::SupportType : LocalAnalysis<Self::Agg, Cube<F, N>>;
622 626
623 /// Returns an iterator over all [`Self::Data`] items at the point `x` of the domain. 627 /// Returns an iterator over all [`Self::Data`] items at the point `x` of the domain.
624 fn iter_at(&self, x : &Loc<F,N>) -> std::slice::Iter<'_, Self::Data>; 628 fn iter_at(&self, x : &Loc<F,N>) -> std::slice::Iter<'_, Self::Data>;
625 629
626 /* 630 /*
670 type Data = D; 674 type Data = D;
671 type Depth = M; 675 type Depth = M;
672 type Agg = A; 676 type Agg = A;
673 type Converted<ANew> = BT<M,F,D,ANew,$n> where ANew : Aggregator; 677 type Converted<ANew> = BT<M,F,D,ANew,$n> where ANew : Aggregator;
674 678
675 fn insert<S: LocalAnalysis<F, A, $n>>( 679 fn insert<S>(
676 &mut self, 680 &mut self,
677 d : D, 681 d : D,
678 support : &S 682 support : &S
679 ) { 683 )
684 where S : Support<$n, RealField = F> + LocalAnalysis<A, Cube<F, $n>> {
680 with_task_budget(|task_budget| 685 with_task_budget(|task_budget|
681 self.topnode.insert( 686 self.topnode.insert(
682 &self.domain, 687 &self.domain,
683 d, 688 d,
684 self.depth, 689 self.depth,
688 ) 693 )
689 } 694 }
690 695
691 fn convert_aggregator<ANew, G>(self, generator : &G) -> Self::Converted<ANew> 696 fn convert_aggregator<ANew, G>(self, generator : &G) -> Self::Converted<ANew>
692 where ANew : Aggregator, 697 where ANew : Aggregator,
693 G : SupportGenerator<F, $n, Id=D>, 698 G : SupportGenerator<$n, Id=D, RealField = F>,
694 G::SupportType : LocalAnalysis<F, ANew, $n> { 699 G::SupportType : LocalAnalysis<ANew, Cube<F, $n>> {
695 let topnode = self.topnode.convert_aggregator(generator, &self.domain); 700 let topnode = self.topnode.convert_aggregator(generator, &self.domain);
696 701
697 BT { 702 BT {
698 depth : self.depth, 703 depth : self.depth,
699 domain : self.domain, 704 domain : self.domain,
700 topnode 705 topnode
701 } 706 }
702 } 707 }
703 708
704 fn refresh_aggregator<G>(&mut self, generator : &G) 709 fn refresh_aggregator<G>(&mut self, generator : &G)
705 where G : SupportGenerator<F, $n, Id=Self::Data>, 710 where G : SupportGenerator<$n, Id=Self::Data, RealField = F>,
706 G::SupportType : LocalAnalysis<F, Self::Agg, $n> { 711 G::SupportType : LocalAnalysis<Self::Agg, Cube<F, $n>> {
707 with_task_budget(|task_budget| 712 with_task_budget(|task_budget|
708 self.topnode.refresh_aggregator(generator, &self.domain, task_budget) 713 self.topnode.refresh_aggregator(generator, &self.domain, task_budget)
709 ) 714 )
710 } 715 }
711 716
724 topnode : Node::new(), 729 topnode : Node::new(),
725 } 730 }
726 } 731 }
727 } 732 }
728 733
729 impl<M,F,D,A> GlobalAnalysis<F,A> for BT<M,F,D,A,$n> 734 impl<M,F,D,A> GlobalAnalysis<A> for BT<M,F,D,A,$n>
730 where M : Depth, 735 where M : Depth,
731 F : Float, 736 F : Float,
732 D : 'static + Copy + Send + Sync + std::fmt::Debug, 737 D : 'static + Copy + Send + Sync + std::fmt::Debug,
733 A : Aggregator { 738 A : Aggregator {
734 fn global_analysis(&self) -> A { 739 fn global_analysis(&self) -> A {

mercurial