@@ -13,11 +13,11 @@ See [`GeometricSplitter`](@ref) for an example of an implementation.
1313abstract type AbstractSplitter end
1414
1515"""
16- should_split(clt::ClusterTree,splitter::AbstractSplitter)
16+ should_split(clt::ClusterTree, depth, splitter::AbstractSplitter)
1717
1818Determine whether or not a `ClusterTree` should be further divided.
1919"""
20- function should_split (clt, splitter:: AbstractSplitter )
20+ function should_split (clt, depth, splitter:: AbstractSplitter )
2121 abstractmethod (splitter)
2222end
2323
@@ -41,14 +41,15 @@ Used to split an `N` dimensional `ClusterTree` into `2^N` children until at most
4141## See also: [`AbstractSplitter`](@ref)
4242"""
4343Base. @kwdef struct DyadicSplitter <: AbstractSplitter
44- nmax:: Int = typemax (Int)
44+ nmax:: Int = 50
45+ keep_empty:: Bool = false
4546end
4647
47- function should_split (node:: ClusterTree , splitter:: DyadicSplitter )
48+ function should_split (node:: ClusterTree , depth, splitter:: DyadicSplitter )
4849 return length (node) > splitter. nmax
4950end
5051
51- function split! (parentcluster:: ClusterTree , :: DyadicSplitter )
52+ function split! (parentcluster:: ClusterTree , spl :: DyadicSplitter )
5253 d = ambient_dimension (parentcluster)
5354 clusters = [parentcluster]
5455 rec = container (parentcluster)
@@ -61,10 +62,73 @@ function split!(parentcluster::ClusterTree, ::DyadicSplitter)
6162 append! (clusters, _binary_split! (clt, i, pos; parentcluster))
6263 end
6364 end
65+ if ! spl. keep_empty
66+ iempty = Int[]
67+ for (i,cluster) in enumerate (clusters)
68+ irange = index_range (cluster)
69+ isempty (irange) && (push! (iempty,i))
70+ end
71+ clusters = deleteat! (clusters,iempty)
72+ end
6473 parentcluster. children = clusters
6574 return parentcluster
6675end
6776
77+ """
78+ struct DyadicMinimalSplitter <: AbstractSplitter
79+
80+ Similar to [`DiadicSplitter`](@ref), but the boundin boxes are shrank to the
81+ minimal axis-aligned boxes at the end.
82+
83+ ## See also: [`AbstractSplitter`](@ref)
84+ """
85+ Base. @kwdef struct DyadicMinimalSplitter <: AbstractSplitter
86+ nmax:: Int = 50
87+ keep_empty:: Bool = false
88+ end
89+
90+ should_split (node:: ClusterTree , depth, splitter:: DyadicMinimalSplitter ) = length (node) > splitter. nmax
91+
92+ function split! (parentcluster:: ClusterTree , spl:: DyadicMinimalSplitter )
93+ # split as a dyadic splitter, then shrink bounding boxes
94+ split! (parentcluster,DyadicSplitter (spl. nmax,spl. keep_empty))
95+ # shrink bounding boxes to minimal one
96+ l2g = loc2glob (parentcluster)
97+ root_els = root_elements (parentcluster)
98+ clusters = children (parentcluster)
99+ for (i,cluster) in enumerate (clusters)
100+ irange = index_range (cluster)
101+ isempty (irange) && continue
102+ els = (root_els[l2g[j]] for j in irange)
103+ cluster. container = HyperRectangle (els,true )
104+ end
105+ return parentcluster
106+ end
107+
108+ """
109+ struct DyadicMaxDepthSplitter <: AbstractSplitter
110+
111+ Similar to [`DyadicSplitter`](@ref), but splits nodes until a maximum `depth` is reached.
112+
113+ ## See also: [`AbstractSplitter`](@ref)
114+ """
115+ Base. @kwdef struct DyadicMaxDepthSplitter <: AbstractSplitter
116+ depth:: Int
117+ keep_empty:: Bool = false
118+ end
119+
120+ function should_split (node:: ClusterTree , depth, spl:: DyadicMaxDepthSplitter )
121+ if ! spl. keep_empty
122+ length (node) == 0 && (return false )
123+ end
124+ depth < spl. depth
125+ end
126+
127+ function split! (parentcluster:: ClusterTree , spl:: DyadicMaxDepthSplitter )
128+ # exactly like the dyadic splitter
129+ split! (parentcluster, DyadicSplitter (- 1 ,spl. keep_empty))
130+ end
131+
68132"""
69133 struct GeometricSplitter <: AbstractSplitter
70134
@@ -74,7 +138,7 @@ Base.@kwdef struct GeometricSplitter <: AbstractSplitter
74138 nmax:: Int = 50
75139end
76140
77- should_split (node:: ClusterTree , splitter:: GeometricSplitter ) = length (node) > splitter. nmax
141+ should_split (node:: ClusterTree , depth, splitter:: GeometricSplitter ) = length (node) > splitter. nmax
78142
79143function split! (cluster:: ClusterTree , :: GeometricSplitter )
80144 rec = cluster. container
@@ -93,7 +157,7 @@ Base.@kwdef struct GeometricMinimalSplitter <: AbstractSplitter
93157 nmax:: Int = 50
94158end
95159
96- should_split (node:: ClusterTree , splitter:: GeometricMinimalSplitter ) = length (node) > splitter. nmax
160+ should_split (node:: ClusterTree , depth, splitter:: GeometricMinimalSplitter ) = length (node) > splitter. nmax
97161
98162function split! (cluster:: ClusterTree , :: GeometricMinimalSplitter )
99163 rec = cluster. container
@@ -112,7 +176,7 @@ Base.@kwdef struct PrincipalComponentSplitter <: AbstractSplitter
112176 nmax:: Int = 50
113177end
114178
115- should_split (node:: ClusterTree , splitter:: PrincipalComponentSplitter ) = length (node) > splitter. nmax
179+ should_split (node:: ClusterTree , depth, splitter:: PrincipalComponentSplitter ) = length (node) > splitter. nmax
116180
117181function split! (cluster:: ClusterTree , :: PrincipalComponentSplitter )
118182 pts = cluster. _elements
@@ -157,7 +221,7 @@ Base.@kwdef struct CardinalitySplitter <: AbstractSplitter
157221 nmax:: Int = 50
158222end
159223
160- should_split (node:: ClusterTree , splitter:: CardinalitySplitter ) = length (node) > splitter. nmax
224+ should_split (node:: ClusterTree , depth, splitter:: CardinalitySplitter ) = length (node) > splitter. nmax
161225
162226function split! (cluster:: ClusterTree , :: CardinalitySplitter )
163227 points = cluster. _elements
0 commit comments